]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - net/netfilter/nf_tables_api.c
netfilter: nfnetlink: allow commit to fail
[mirror_ubuntu-jammy-kernel.git] / net / netfilter / nf_tables_api.c
CommitLineData
96518518 1/*
20a69341 2 * Copyright (c) 2007-2009 Patrick McHardy <kaber@trash.net>
96518518
PM
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Development of this code funded by Astaro AG (http://www.astaro.com/)
9 */
10
11#include <linux/module.h>
12#include <linux/init.h>
13#include <linux/list.h>
14#include <linux/skbuff.h>
15#include <linux/netlink.h>
1ff75a3e 16#include <linux/vmalloc.h>
96518518
PM
17#include <linux/netfilter.h>
18#include <linux/netfilter/nfnetlink.h>
19#include <linux/netfilter/nf_tables.h>
3b49e2e9 20#include <net/netfilter/nf_flow_table.h>
96518518
PM
21#include <net/netfilter/nf_tables_core.h>
22#include <net/netfilter/nf_tables.h>
99633ab2 23#include <net/net_namespace.h>
96518518
PM
24#include <net/sock.h>
25
96518518 26static LIST_HEAD(nf_tables_expressions);
e5009240 27static LIST_HEAD(nf_tables_objects);
3b49e2e9 28static LIST_HEAD(nf_tables_flowtables);
3ecbfd65 29static u64 table_handle;
96518518 30
7c95f6d8 31static void nft_ctx_init(struct nft_ctx *ctx,
633c9a84 32 struct net *net,
7c95f6d8
PNA
33 const struct sk_buff *skb,
34 const struct nlmsghdr *nlh,
36596dad 35 u8 family,
7c95f6d8
PNA
36 struct nft_table *table,
37 struct nft_chain *chain,
38 const struct nlattr * const *nla)
39{
633c9a84 40 ctx->net = net;
36596dad 41 ctx->family = family;
128ad332
PNA
42 ctx->table = table;
43 ctx->chain = chain;
44 ctx->nla = nla;
45 ctx->portid = NETLINK_CB(skb).portid;
46 ctx->report = nlmsg_report(nlh);
47 ctx->seq = nlh->nlmsg_seq;
7c95f6d8
PNA
48}
49
8411b644
PNA
50static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
51 int msg_type, u32 size, gfp_t gfp)
1081d11b
PNA
52{
53 struct nft_trans *trans;
54
8411b644 55 trans = kzalloc(sizeof(struct nft_trans) + size, gfp);
1081d11b
PNA
56 if (trans == NULL)
57 return NULL;
58
b380e5c7 59 trans->msg_type = msg_type;
1081d11b
PNA
60 trans->ctx = *ctx;
61
62 return trans;
63}
64
8411b644
PNA
65static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx,
66 int msg_type, u32 size)
67{
68 return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL);
69}
70
1081d11b
PNA
71static void nft_trans_destroy(struct nft_trans *trans)
72{
73 list_del(&trans->list);
74 kfree(trans);
75}
76
c974a3a3
PNA
77static int nf_tables_register_hook(struct net *net,
78 const struct nft_table *table,
79 struct nft_chain *chain)
d8ee8f7c 80{
4e25ceb8 81 const struct nft_base_chain *basechain;
a37061a6 82 const struct nf_hook_ops *ops;
ae6153b5 83
d8ee8f7c 84 if (table->flags & NFT_TABLE_F_DORMANT ||
f323d954 85 !nft_is_base_chain(chain))
d8ee8f7c
PNA
86 return 0;
87
4e25ceb8
FW
88 basechain = nft_base_chain(chain);
89 ops = &basechain->ops;
ae6153b5 90
4e25ceb8
FW
91 if (basechain->type->ops_register)
92 return basechain->type->ops_register(net, ops);
93
a37061a6 94 return nf_register_net_hook(net, ops);
d8ee8f7c
PNA
95}
96
c974a3a3
PNA
97static void nf_tables_unregister_hook(struct net *net,
98 const struct nft_table *table,
99 struct nft_chain *chain)
c5598794 100{
4e25ceb8
FW
101 const struct nft_base_chain *basechain;
102 const struct nf_hook_ops *ops;
103
d8ee8f7c 104 if (table->flags & NFT_TABLE_F_DORMANT ||
f323d954 105 !nft_is_base_chain(chain))
d8ee8f7c 106 return;
4e25ceb8
FW
107 basechain = nft_base_chain(chain);
108 ops = &basechain->ops;
d8ee8f7c 109
4e25ceb8
FW
110 if (basechain->type->ops_unregister)
111 return basechain->type->ops_unregister(net, ops);
112
113 nf_unregister_net_hook(net, ops);
c5598794
AB
114}
115
ee01d542
AB
116static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type)
117{
118 struct nft_trans *trans;
119
120 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_table));
121 if (trans == NULL)
122 return -ENOMEM;
123
124 if (msg_type == NFT_MSG_NEWTABLE)
f2a6d766 125 nft_activate_next(ctx->net, ctx->table);
ee01d542
AB
126
127 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
128 return 0;
129}
130
131static int nft_deltable(struct nft_ctx *ctx)
132{
133 int err;
134
135 err = nft_trans_table_add(ctx, NFT_MSG_DELTABLE);
136 if (err < 0)
137 return err;
138
f2a6d766 139 nft_deactivate_next(ctx->net, ctx->table);
ee01d542
AB
140 return err;
141}
142
143static int nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
144{
145 struct nft_trans *trans;
146
147 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_chain));
148 if (trans == NULL)
149 return -ENOMEM;
150
151 if (msg_type == NFT_MSG_NEWCHAIN)
664b0f8c 152 nft_activate_next(ctx->net, ctx->chain);
ee01d542
AB
153
154 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
155 return 0;
156}
157
158static int nft_delchain(struct nft_ctx *ctx)
159{
160 int err;
161
162 err = nft_trans_chain_add(ctx, NFT_MSG_DELCHAIN);
163 if (err < 0)
164 return err;
165
166 ctx->table->use--;
664b0f8c 167 nft_deactivate_next(ctx->net, ctx->chain);
ee01d542
AB
168
169 return err;
170}
171
bb7b40ae
PNA
172static void nft_rule_expr_activate(const struct nft_ctx *ctx,
173 struct nft_rule *rule)
174{
175 struct nft_expr *expr;
176
177 expr = nft_expr_first(rule);
178 while (expr != nft_expr_last(rule) && expr->ops) {
179 if (expr->ops->activate)
180 expr->ops->activate(ctx, expr);
181
182 expr = nft_expr_next(expr);
183 }
184}
185
186static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
187 struct nft_rule *rule)
188{
189 struct nft_expr *expr;
190
191 expr = nft_expr_first(rule);
192 while (expr != nft_expr_last(rule) && expr->ops) {
193 if (expr->ops->deactivate)
194 expr->ops->deactivate(ctx, expr);
195
196 expr = nft_expr_next(expr);
197 }
198}
199
ee01d542
AB
200static int
201nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule)
202{
203 /* You cannot delete the same rule twice */
889f7ee7
PNA
204 if (nft_is_active_next(ctx->net, rule)) {
205 nft_deactivate_next(ctx->net, rule);
ee01d542
AB
206 ctx->chain->use--;
207 return 0;
208 }
209 return -ENOENT;
210}
211
212static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx, int msg_type,
213 struct nft_rule *rule)
214{
215 struct nft_trans *trans;
216
217 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_rule));
218 if (trans == NULL)
219 return NULL;
220
1a94e38d
PNA
221 if (msg_type == NFT_MSG_NEWRULE && ctx->nla[NFTA_RULE_ID] != NULL) {
222 nft_trans_rule_id(trans) =
223 ntohl(nla_get_be32(ctx->nla[NFTA_RULE_ID]));
224 }
ee01d542
AB
225 nft_trans_rule(trans) = rule;
226 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
227
228 return trans;
229}
230
231static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule)
232{
233 struct nft_trans *trans;
234 int err;
235
236 trans = nft_trans_rule_add(ctx, NFT_MSG_DELRULE, rule);
237 if (trans == NULL)
238 return -ENOMEM;
239
240 err = nf_tables_delrule_deactivate(ctx, rule);
241 if (err < 0) {
242 nft_trans_destroy(trans);
243 return err;
244 }
bb7b40ae 245 nft_rule_expr_deactivate(ctx, rule);
ee01d542
AB
246
247 return 0;
248}
249
250static int nft_delrule_by_chain(struct nft_ctx *ctx)
251{
252 struct nft_rule *rule;
253 int err;
254
255 list_for_each_entry(rule, &ctx->chain->rules, list) {
256 err = nft_delrule(ctx, rule);
257 if (err < 0)
258 return err;
259 }
260 return 0;
261}
262
ee01d542
AB
263static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type,
264 struct nft_set *set)
265{
266 struct nft_trans *trans;
267
268 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_set));
269 if (trans == NULL)
270 return -ENOMEM;
271
272 if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) {
273 nft_trans_set_id(trans) =
274 ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID]));
37a9cc52 275 nft_activate_next(ctx->net, set);
ee01d542
AB
276 }
277 nft_trans_set(trans) = set;
278 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
279
280 return 0;
281}
282
283static int nft_delset(struct nft_ctx *ctx, struct nft_set *set)
284{
285 int err;
286
287 err = nft_trans_set_add(ctx, NFT_MSG_DELSET, set);
288 if (err < 0)
289 return err;
290
37a9cc52 291 nft_deactivate_next(ctx->net, set);
ee01d542
AB
292 ctx->table->use--;
293
294 return err;
295}
296
e5009240
PNA
297static int nft_trans_obj_add(struct nft_ctx *ctx, int msg_type,
298 struct nft_object *obj)
299{
300 struct nft_trans *trans;
301
302 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_obj));
303 if (trans == NULL)
304 return -ENOMEM;
305
306 if (msg_type == NFT_MSG_NEWOBJ)
307 nft_activate_next(ctx->net, obj);
308
309 nft_trans_obj(trans) = obj;
310 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
311
312 return 0;
313}
314
315static int nft_delobj(struct nft_ctx *ctx, struct nft_object *obj)
316{
317 int err;
318
319 err = nft_trans_obj_add(ctx, NFT_MSG_DELOBJ, obj);
320 if (err < 0)
321 return err;
322
323 nft_deactivate_next(ctx->net, obj);
324 ctx->table->use--;
325
326 return err;
327}
328
3b49e2e9
PNA
329static int nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type,
330 struct nft_flowtable *flowtable)
331{
332 struct nft_trans *trans;
333
334 trans = nft_trans_alloc(ctx, msg_type,
335 sizeof(struct nft_trans_flowtable));
336 if (trans == NULL)
337 return -ENOMEM;
338
339 if (msg_type == NFT_MSG_NEWFLOWTABLE)
340 nft_activate_next(ctx->net, flowtable);
341
342 nft_trans_flowtable(trans) = flowtable;
343 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
344
345 return 0;
346}
347
348static int nft_delflowtable(struct nft_ctx *ctx,
349 struct nft_flowtable *flowtable)
350{
351 int err;
352
353 err = nft_trans_flowtable_add(ctx, NFT_MSG_DELFLOWTABLE, flowtable);
354 if (err < 0)
355 return err;
356
357 nft_deactivate_next(ctx->net, flowtable);
358 ctx->table->use--;
359
360 return err;
361}
362
96518518
PM
363/*
364 * Tables
365 */
366
36596dad 367static struct nft_table *nft_table_lookup(const struct net *net,
f2a6d766 368 const struct nlattr *nla,
36596dad 369 u8 family, u8 genmask)
96518518
PM
370{
371 struct nft_table *table;
372
cac20fcd
PNA
373 if (nla == NULL)
374 return ERR_PTR(-EINVAL);
375
36596dad 376 list_for_each_entry(table, &net->nft.tables, list) {
f2a6d766 377 if (!nla_strcmp(nla, table->name) &&
98319cb9 378 table->family == family &&
f2a6d766 379 nft_active_genmask(table, genmask))
96518518
PM
380 return table;
381 }
cac20fcd
PNA
382
383 return ERR_PTR(-ENOENT);
96518518
PM
384}
385
3ecbfd65
HS
386static struct nft_table *nft_table_lookup_byhandle(const struct net *net,
387 const struct nlattr *nla,
388 u8 genmask)
389{
390 struct nft_table *table;
391
392 list_for_each_entry(table, &net->nft.tables, list) {
393 if (be64_to_cpu(nla_get_be64(nla)) == table->handle &&
394 nft_active_genmask(table, genmask))
395 return table;
396 }
3ecbfd65
HS
397
398 return ERR_PTR(-ENOENT);
399}
400
96518518
PM
401static inline u64 nf_tables_alloc_handle(struct nft_table *table)
402{
403 return ++table->hgenerator;
404}
405
32537e91 406static const struct nft_chain_type *chain_type[NFPROTO_NUMPROTO][NFT_CHAIN_T_MAX];
9370761c 407
32537e91 408static const struct nft_chain_type *
1ea26cca 409__nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family)
9370761c
PNA
410{
411 int i;
412
baae3e62 413 for (i = 0; i < NFT_CHAIN_T_MAX; i++) {
9370761c
PNA
414 if (chain_type[family][i] != NULL &&
415 !nla_strcmp(nla, chain_type[family][i]->name))
baae3e62 416 return chain_type[family][i];
9370761c 417 }
baae3e62 418 return NULL;
9370761c
PNA
419}
420
32537e91 421static const struct nft_chain_type *
1ea26cca 422nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family, bool autoload)
9370761c 423{
32537e91 424 const struct nft_chain_type *type;
9370761c 425
1ea26cca 426 type = __nf_tables_chain_type_lookup(nla, family);
93b0806f
PM
427 if (type != NULL)
428 return type;
9370761c 429#ifdef CONFIG_MODULES
93b0806f 430 if (autoload) {
9370761c 431 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1ea26cca 432 request_module("nft-chain-%u-%.*s", family,
2fec6bb6 433 nla_len(nla), (const char *)nla_data(nla));
9370761c 434 nfnl_lock(NFNL_SUBSYS_NFTABLES);
1ea26cca 435 type = __nf_tables_chain_type_lookup(nla, family);
93b0806f
PM
436 if (type != NULL)
437 return ERR_PTR(-EAGAIN);
9370761c
PNA
438 }
439#endif
93b0806f 440 return ERR_PTR(-ENOENT);
9370761c
PNA
441}
442
96518518 443static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = {
1cae565e
PNA
444 [NFTA_TABLE_NAME] = { .type = NLA_STRING,
445 .len = NFT_TABLE_MAXNAMELEN - 1 },
9ddf6323 446 [NFTA_TABLE_FLAGS] = { .type = NLA_U32 },
3ecbfd65 447 [NFTA_TABLE_HANDLE] = { .type = NLA_U64 },
96518518
PM
448};
449
84d7fce6
PNA
450static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net,
451 u32 portid, u32 seq, int event, u32 flags,
452 int family, const struct nft_table *table)
96518518
PM
453{
454 struct nlmsghdr *nlh;
455 struct nfgenmsg *nfmsg;
456
dedb67c4 457 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
96518518
PM
458 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags);
459 if (nlh == NULL)
460 goto nla_put_failure;
461
462 nfmsg = nlmsg_data(nlh);
463 nfmsg->nfgen_family = family;
464 nfmsg->version = NFNETLINK_V0;
84d7fce6 465 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
96518518 466
9ddf6323 467 if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) ||
d8bcc768 468 nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) ||
3ecbfd65
HS
469 nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)) ||
470 nla_put_be64(skb, NFTA_TABLE_HANDLE, cpu_to_be64(table->handle),
471 NFTA_TABLE_PAD))
96518518
PM
472 goto nla_put_failure;
473
053c095a
JB
474 nlmsg_end(skb, nlh);
475 return 0;
96518518
PM
476
477nla_put_failure:
478 nlmsg_trim(skb, nlh);
479 return -1;
480}
481
25e94a99 482static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
96518518
PM
483{
484 struct sk_buff *skb;
96518518
PM
485 int err;
486
128ad332
PNA
487 if (!ctx->report &&
488 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
25e94a99 489 return;
96518518 490
96518518
PM
491 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
492 if (skb == NULL)
493 goto err;
494
84d7fce6 495 err = nf_tables_fill_table_info(skb, ctx->net, ctx->portid, ctx->seq,
36596dad 496 event, 0, ctx->family, ctx->table);
96518518
PM
497 if (err < 0) {
498 kfree_skb(skb);
499 goto err;
500 }
501
25e94a99
PNA
502 nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
503 ctx->report, GFP_KERNEL);
504 return;
96518518 505err:
25e94a99 506 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
96518518
PM
507}
508
509static int nf_tables_dump_tables(struct sk_buff *skb,
510 struct netlink_callback *cb)
511{
512 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
96518518
PM
513 const struct nft_table *table;
514 unsigned int idx = 0, s_idx = cb->args[0];
99633ab2 515 struct net *net = sock_net(skb->sk);
96518518
PM
516 int family = nfmsg->nfgen_family;
517
e688a7f8 518 rcu_read_lock();
38e029f1
PNA
519 cb->seq = net->nft.base_seq;
520
36596dad 521 list_for_each_entry_rcu(table, &net->nft.tables, list) {
98319cb9 522 if (family != NFPROTO_UNSPEC && family != table->family)
96518518
PM
523 continue;
524
36596dad
PNA
525 if (idx < s_idx)
526 goto cont;
527 if (idx > s_idx)
528 memset(&cb->args[1], 0,
529 sizeof(cb->args) - sizeof(cb->args[0]));
530 if (!nft_is_active(net, table))
531 continue;
532 if (nf_tables_fill_table_info(skb, net,
533 NETLINK_CB(cb->skb).portid,
534 cb->nlh->nlmsg_seq,
535 NFT_MSG_NEWTABLE, NLM_F_MULTI,
98319cb9 536 table->family, table) < 0)
36596dad
PNA
537 goto done;
538
539 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
96518518 540cont:
36596dad 541 idx++;
96518518
PM
542 }
543done:
e688a7f8 544 rcu_read_unlock();
96518518
PM
545 cb->args[0] = idx;
546 return skb->len;
547}
548
7b8002a1
PNA
549static int nf_tables_gettable(struct net *net, struct sock *nlsk,
550 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
551 const struct nlattr * const nla[],
552 struct netlink_ext_ack *extack)
96518518
PM
553{
554 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 555 u8 genmask = nft_genmask_cur(net);
96518518
PM
556 const struct nft_table *table;
557 struct sk_buff *skb2;
558 int family = nfmsg->nfgen_family;
559 int err;
560
561 if (nlh->nlmsg_flags & NLM_F_DUMP) {
562 struct netlink_dump_control c = {
563 .dump = nf_tables_dump_tables,
564 };
565 return netlink_dump_start(nlsk, skb, nlh, &c);
566 }
567
cac20fcd 568 table = nft_table_lookup(net, nla[NFTA_TABLE_NAME], family, genmask);
36dd1bcc
PNA
569 if (IS_ERR(table)) {
570 NL_SET_BAD_ATTR(extack, nla[NFTA_TABLE_NAME]);
96518518 571 return PTR_ERR(table);
36dd1bcc 572 }
96518518
PM
573
574 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
575 if (!skb2)
576 return -ENOMEM;
577
84d7fce6 578 err = nf_tables_fill_table_info(skb2, net, NETLINK_CB(skb).portid,
96518518
PM
579 nlh->nlmsg_seq, NFT_MSG_NEWTABLE, 0,
580 family, table);
581 if (err < 0)
582 goto err;
583
584 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
585
586err:
587 kfree_skb(skb2);
588 return err;
589}
590
c9c17211 591static void nft_table_disable(struct net *net, struct nft_table *table, u32 cnt)
10435c11
F
592{
593 struct nft_chain *chain;
594 u32 i = 0;
595
596 list_for_each_entry(chain, &table->chains, list) {
597 if (!nft_is_active_next(net, chain))
598 continue;
f323d954 599 if (!nft_is_base_chain(chain))
10435c11
F
600 continue;
601
602 if (cnt && i++ == cnt)
603 break;
604
c974a3a3 605 nf_unregister_net_hook(net, &nft_base_chain(chain)->ops);
10435c11
F
606 }
607}
608
c9c17211 609static int nf_tables_table_enable(struct net *net, struct nft_table *table)
9ddf6323
PNA
610{
611 struct nft_chain *chain;
612 int err, i = 0;
613
614 list_for_each_entry(chain, &table->chains, list) {
664b0f8c
PNA
615 if (!nft_is_active_next(net, chain))
616 continue;
f323d954 617 if (!nft_is_base_chain(chain))
d2012975
PNA
618 continue;
619
c974a3a3 620 err = nf_register_net_hook(net, &nft_base_chain(chain)->ops);
9ddf6323
PNA
621 if (err < 0)
622 goto err;
623
624 i++;
625 }
626 return 0;
627err:
10435c11 628 if (i)
c9c17211 629 nft_table_disable(net, table, i);
9ddf6323
PNA
630 return err;
631}
632
c9c17211 633static void nf_tables_table_disable(struct net *net, struct nft_table *table)
9ddf6323 634{
c9c17211 635 nft_table_disable(net, table, 0);
9ddf6323
PNA
636}
637
e1aaca93 638static int nf_tables_updtable(struct nft_ctx *ctx)
9ddf6323 639{
55dd6f93 640 struct nft_trans *trans;
e1aaca93 641 u32 flags;
55dd6f93 642 int ret = 0;
9ddf6323 643
e1aaca93
PNA
644 if (!ctx->nla[NFTA_TABLE_FLAGS])
645 return 0;
9ddf6323 646
e1aaca93
PNA
647 flags = ntohl(nla_get_be32(ctx->nla[NFTA_TABLE_FLAGS]));
648 if (flags & ~NFT_TABLE_F_DORMANT)
649 return -EINVAL;
650
63283dd2
PNA
651 if (flags == ctx->table->flags)
652 return 0;
653
55dd6f93
PNA
654 trans = nft_trans_alloc(ctx, NFT_MSG_NEWTABLE,
655 sizeof(struct nft_trans_table));
656 if (trans == NULL)
657 return -ENOMEM;
9ddf6323 658
e1aaca93
PNA
659 if ((flags & NFT_TABLE_F_DORMANT) &&
660 !(ctx->table->flags & NFT_TABLE_F_DORMANT)) {
55dd6f93 661 nft_trans_table_enable(trans) = false;
e1aaca93
PNA
662 } else if (!(flags & NFT_TABLE_F_DORMANT) &&
663 ctx->table->flags & NFT_TABLE_F_DORMANT) {
c9c17211 664 ret = nf_tables_table_enable(ctx->net, ctx->table);
55dd6f93 665 if (ret >= 0) {
e1aaca93 666 ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
55dd6f93 667 nft_trans_table_enable(trans) = true;
9ddf6323 668 }
9ddf6323 669 }
e1aaca93
PNA
670 if (ret < 0)
671 goto err;
9ddf6323 672
55dd6f93
PNA
673 nft_trans_table_update(trans) = true;
674 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
675 return 0;
9ddf6323 676err:
55dd6f93 677 nft_trans_destroy(trans);
9ddf6323
PNA
678 return ret;
679}
680
633c9a84
PNA
681static int nf_tables_newtable(struct net *net, struct sock *nlsk,
682 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
683 const struct nlattr * const nla[],
684 struct netlink_ext_ack *extack)
96518518
PM
685{
686 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 687 u8 genmask = nft_genmask_next(net);
96518518 688 int family = nfmsg->nfgen_family;
36dd1bcc
PNA
689 const struct nlattr *attr;
690 struct nft_table *table;
c5c1f975 691 u32 flags = 0;
e1aaca93 692 struct nft_ctx ctx;
55dd6f93 693 int err;
96518518 694
36dd1bcc
PNA
695 attr = nla[NFTA_TABLE_NAME];
696 table = nft_table_lookup(net, attr, family, genmask);
96518518
PM
697 if (IS_ERR(table)) {
698 if (PTR_ERR(table) != -ENOENT)
699 return PTR_ERR(table);
1a28ad74 700 } else {
36dd1bcc
PNA
701 if (nlh->nlmsg_flags & NLM_F_EXCL) {
702 NL_SET_BAD_ATTR(extack, attr);
96518518 703 return -EEXIST;
36dd1bcc 704 }
96518518
PM
705 if (nlh->nlmsg_flags & NLM_F_REPLACE)
706 return -EOPNOTSUPP;
e1aaca93 707
98319cb9 708 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
e1aaca93 709 return nf_tables_updtable(&ctx);
96518518
PM
710 }
711
c5c1f975
PM
712 if (nla[NFTA_TABLE_FLAGS]) {
713 flags = ntohl(nla_get_be32(nla[NFTA_TABLE_FLAGS]));
714 if (flags & ~NFT_TABLE_F_DORMANT)
715 return -EINVAL;
716 }
717
ffdb210e 718 err = -ENOMEM;
1cae565e 719 table = kzalloc(sizeof(*table), GFP_KERNEL);
ffdb210e 720 if (table == NULL)
98319cb9 721 goto err_kzalloc;
96518518 722
36dd1bcc 723 table->name = nla_strdup(attr, GFP_KERNEL);
e46abbcc 724 if (table->name == NULL)
98319cb9 725 goto err_strdup;
e46abbcc 726
96518518 727 INIT_LIST_HEAD(&table->chains);
20a69341 728 INIT_LIST_HEAD(&table->sets);
e5009240 729 INIT_LIST_HEAD(&table->objects);
3b49e2e9 730 INIT_LIST_HEAD(&table->flowtables);
98319cb9 731 table->family = family;
c5c1f975 732 table->flags = flags;
3ecbfd65 733 table->handle = ++table_handle;
9ddf6323 734
98319cb9 735 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
55dd6f93 736 err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE);
ffdb210e 737 if (err < 0)
98319cb9 738 goto err_trans;
ffdb210e 739
36596dad 740 list_add_tail_rcu(&table->list, &net->nft.tables);
96518518 741 return 0;
98319cb9 742err_trans:
e46abbcc 743 kfree(table->name);
98319cb9 744err_strdup:
ffdb210e 745 kfree(table);
98319cb9 746err_kzalloc:
ffdb210e 747 return err;
96518518
PM
748}
749
b9ac12ef
AB
750static int nft_flush_table(struct nft_ctx *ctx)
751{
3b49e2e9 752 struct nft_flowtable *flowtable, *nft;
b9ac12ef 753 struct nft_chain *chain, *nc;
e5009240 754 struct nft_object *obj, *ne;
b9ac12ef 755 struct nft_set *set, *ns;
3b49e2e9 756 int err;
b9ac12ef 757
a2f18db0 758 list_for_each_entry(chain, &ctx->table->chains, list) {
664b0f8c
PNA
759 if (!nft_is_active_next(ctx->net, chain))
760 continue;
761
b9ac12ef
AB
762 ctx->chain = chain;
763
764 err = nft_delrule_by_chain(ctx);
765 if (err < 0)
766 goto out;
b9ac12ef
AB
767 }
768
769 list_for_each_entry_safe(set, ns, &ctx->table->sets, list) {
37a9cc52
PNA
770 if (!nft_is_active_next(ctx->net, set))
771 continue;
772
408070d6 773 if (nft_set_is_anonymous(set) &&
b9ac12ef
AB
774 !list_empty(&set->bindings))
775 continue;
776
777 err = nft_delset(ctx, set);
778 if (err < 0)
779 goto out;
780 }
781
3b49e2e9
PNA
782 list_for_each_entry_safe(flowtable, nft, &ctx->table->flowtables, list) {
783 err = nft_delflowtable(ctx, flowtable);
784 if (err < 0)
785 goto out;
786 }
787
e5009240
PNA
788 list_for_each_entry_safe(obj, ne, &ctx->table->objects, list) {
789 err = nft_delobj(ctx, obj);
790 if (err < 0)
791 goto out;
792 }
793
a2f18db0 794 list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) {
664b0f8c
PNA
795 if (!nft_is_active_next(ctx->net, chain))
796 continue;
797
a2f18db0
PNA
798 ctx->chain = chain;
799
800 err = nft_delchain(ctx);
801 if (err < 0)
802 goto out;
803 }
804
b9ac12ef
AB
805 err = nft_deltable(ctx);
806out:
807 return err;
808}
809
810static int nft_flush(struct nft_ctx *ctx, int family)
811{
b9ac12ef
AB
812 struct nft_table *table, *nt;
813 const struct nlattr * const *nla = ctx->nla;
814 int err = 0;
815
36596dad 816 list_for_each_entry_safe(table, nt, &ctx->net->nft.tables, list) {
98319cb9 817 if (family != AF_UNSPEC && table->family != family)
b9ac12ef
AB
818 continue;
819
98319cb9 820 ctx->family = table->family;
f2a6d766 821
36596dad
PNA
822 if (!nft_is_active_next(ctx->net, table))
823 continue;
b9ac12ef 824
36596dad
PNA
825 if (nla[NFTA_TABLE_NAME] &&
826 nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0)
827 continue;
b9ac12ef 828
36596dad
PNA
829 ctx->table = table;
830
831 err = nft_flush_table(ctx);
832 if (err < 0)
833 goto out;
b9ac12ef
AB
834 }
835out:
836 return err;
837}
838
633c9a84
PNA
839static int nf_tables_deltable(struct net *net, struct sock *nlsk,
840 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
841 const struct nlattr * const nla[],
842 struct netlink_ext_ack *extack)
96518518
PM
843{
844 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 845 u8 genmask = nft_genmask_next(net);
ee01d542 846 int family = nfmsg->nfgen_family;
36dd1bcc
PNA
847 const struct nlattr *attr;
848 struct nft_table *table;
55dd6f93 849 struct nft_ctx ctx;
96518518 850
36596dad 851 nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla);
3ecbfd65
HS
852 if (family == AF_UNSPEC ||
853 (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE]))
b9ac12ef
AB
854 return nft_flush(&ctx, family);
855
36dd1bcc
PNA
856 if (nla[NFTA_TABLE_HANDLE]) {
857 attr = nla[NFTA_TABLE_HANDLE];
858 table = nft_table_lookup_byhandle(net, attr, genmask);
859 } else {
860 attr = nla[NFTA_TABLE_NAME];
861 table = nft_table_lookup(net, attr, family, genmask);
862 }
3ecbfd65 863
36dd1bcc
PNA
864 if (IS_ERR(table)) {
865 NL_SET_BAD_ATTR(extack, attr);
96518518 866 return PTR_ERR(table);
36dd1bcc 867 }
96518518 868
a8278400
PNA
869 if (nlh->nlmsg_flags & NLM_F_NONREC &&
870 table->use > 0)
871 return -EBUSY;
872
98319cb9 873 ctx.family = family;
b9ac12ef 874 ctx.table = table;
55dd6f93 875
b9ac12ef 876 return nft_flush_table(&ctx);
96518518
PM
877}
878
55dd6f93
PNA
879static void nf_tables_table_destroy(struct nft_ctx *ctx)
880{
4fefee57
PNA
881 BUG_ON(ctx->table->use > 0);
882
e46abbcc 883 kfree(ctx->table->name);
55dd6f93 884 kfree(ctx->table);
55dd6f93
PNA
885}
886
cc07eeb0 887void nft_register_chain_type(const struct nft_chain_type *ctype)
96518518 888{
d8297d4f 889 if (WARN_ON(ctype->family >= NFPROTO_NUMPROTO))
cc07eeb0 890 return;
d8297d4f 891
96518518 892 nfnl_lock(NFNL_SUBSYS_NFTABLES);
cc07eeb0
PNA
893 if (WARN_ON(chain_type[ctype->family][ctype->type] != NULL)) {
894 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
895 return;
96518518 896 }
9370761c 897 chain_type[ctype->family][ctype->type] = ctype;
96518518 898 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
96518518 899}
9370761c 900EXPORT_SYMBOL_GPL(nft_register_chain_type);
96518518 901
32537e91 902void nft_unregister_chain_type(const struct nft_chain_type *ctype)
96518518 903{
96518518 904 nfnl_lock(NFNL_SUBSYS_NFTABLES);
9370761c 905 chain_type[ctype->family][ctype->type] = NULL;
96518518
PM
906 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
907}
9370761c 908EXPORT_SYMBOL_GPL(nft_unregister_chain_type);
96518518
PM
909
910/*
911 * Chains
912 */
913
914static struct nft_chain *
cac20fcd 915nft_chain_lookup_byhandle(const struct nft_table *table, u64 handle, u8 genmask)
96518518
PM
916{
917 struct nft_chain *chain;
918
919 list_for_each_entry(chain, &table->chains, list) {
664b0f8c
PNA
920 if (chain->handle == handle &&
921 nft_active_genmask(chain, genmask))
96518518
PM
922 return chain;
923 }
924
925 return ERR_PTR(-ENOENT);
926}
927
cac20fcd
PNA
928static struct nft_chain *nft_chain_lookup(const struct nft_table *table,
929 const struct nlattr *nla, u8 genmask)
96518518
PM
930{
931 struct nft_chain *chain;
932
933 if (nla == NULL)
934 return ERR_PTR(-EINVAL);
935
936 list_for_each_entry(chain, &table->chains, list) {
664b0f8c
PNA
937 if (!nla_strcmp(nla, chain->name) &&
938 nft_active_genmask(chain, genmask))
96518518
PM
939 return chain;
940 }
941
942 return ERR_PTR(-ENOENT);
943}
944
945static const struct nla_policy nft_chain_policy[NFTA_CHAIN_MAX + 1] = {
b2fbd044
LZ
946 [NFTA_CHAIN_TABLE] = { .type = NLA_STRING,
947 .len = NFT_TABLE_MAXNAMELEN - 1 },
96518518
PM
948 [NFTA_CHAIN_HANDLE] = { .type = NLA_U64 },
949 [NFTA_CHAIN_NAME] = { .type = NLA_STRING,
950 .len = NFT_CHAIN_MAXNAMELEN - 1 },
951 [NFTA_CHAIN_HOOK] = { .type = NLA_NESTED },
0ca743a5 952 [NFTA_CHAIN_POLICY] = { .type = NLA_U32 },
4c1f7818 953 [NFTA_CHAIN_TYPE] = { .type = NLA_STRING },
0ca743a5 954 [NFTA_CHAIN_COUNTERS] = { .type = NLA_NESTED },
96518518
PM
955};
956
957static const struct nla_policy nft_hook_policy[NFTA_HOOK_MAX + 1] = {
958 [NFTA_HOOK_HOOKNUM] = { .type = NLA_U32 },
959 [NFTA_HOOK_PRIORITY] = { .type = NLA_U32 },
2cbce139
PNA
960 [NFTA_HOOK_DEV] = { .type = NLA_STRING,
961 .len = IFNAMSIZ - 1 },
96518518
PM
962};
963
0ca743a5
PNA
964static int nft_dump_stats(struct sk_buff *skb, struct nft_stats __percpu *stats)
965{
966 struct nft_stats *cpu_stats, total;
967 struct nlattr *nest;
ce355e20
ED
968 unsigned int seq;
969 u64 pkts, bytes;
0ca743a5
PNA
970 int cpu;
971
972 memset(&total, 0, sizeof(total));
973 for_each_possible_cpu(cpu) {
974 cpu_stats = per_cpu_ptr(stats, cpu);
ce355e20
ED
975 do {
976 seq = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
977 pkts = cpu_stats->pkts;
978 bytes = cpu_stats->bytes;
979 } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, seq));
980 total.pkts += pkts;
981 total.bytes += bytes;
0ca743a5
PNA
982 }
983 nest = nla_nest_start(skb, NFTA_CHAIN_COUNTERS);
984 if (nest == NULL)
985 goto nla_put_failure;
986
b46f6ded
ND
987 if (nla_put_be64(skb, NFTA_COUNTER_PACKETS, cpu_to_be64(total.pkts),
988 NFTA_COUNTER_PAD) ||
989 nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes),
990 NFTA_COUNTER_PAD))
0ca743a5
PNA
991 goto nla_put_failure;
992
993 nla_nest_end(skb, nest);
994 return 0;
995
996nla_put_failure:
997 return -ENOSPC;
998}
999
84d7fce6
PNA
1000static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
1001 u32 portid, u32 seq, int event, u32 flags,
1002 int family, const struct nft_table *table,
96518518
PM
1003 const struct nft_chain *chain)
1004{
1005 struct nlmsghdr *nlh;
1006 struct nfgenmsg *nfmsg;
1007
dedb67c4 1008 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
96518518
PM
1009 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags);
1010 if (nlh == NULL)
1011 goto nla_put_failure;
1012
1013 nfmsg = nlmsg_data(nlh);
1014 nfmsg->nfgen_family = family;
1015 nfmsg->version = NFNETLINK_V0;
84d7fce6 1016 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
96518518
PM
1017
1018 if (nla_put_string(skb, NFTA_CHAIN_TABLE, table->name))
1019 goto nla_put_failure;
b46f6ded
ND
1020 if (nla_put_be64(skb, NFTA_CHAIN_HANDLE, cpu_to_be64(chain->handle),
1021 NFTA_CHAIN_PAD))
96518518
PM
1022 goto nla_put_failure;
1023 if (nla_put_string(skb, NFTA_CHAIN_NAME, chain->name))
1024 goto nla_put_failure;
1025
f323d954 1026 if (nft_is_base_chain(chain)) {
0ca743a5 1027 const struct nft_base_chain *basechain = nft_base_chain(chain);
c974a3a3 1028 const struct nf_hook_ops *ops = &basechain->ops;
0ca743a5
PNA
1029 struct nlattr *nest;
1030
1031 nest = nla_nest_start(skb, NFTA_CHAIN_HOOK);
96518518
PM
1032 if (nest == NULL)
1033 goto nla_put_failure;
1034 if (nla_put_be32(skb, NFTA_HOOK_HOOKNUM, htonl(ops->hooknum)))
1035 goto nla_put_failure;
1036 if (nla_put_be32(skb, NFTA_HOOK_PRIORITY, htonl(ops->priority)))
1037 goto nla_put_failure;
2cbce139
PNA
1038 if (basechain->dev_name[0] &&
1039 nla_put_string(skb, NFTA_HOOK_DEV, basechain->dev_name))
1040 goto nla_put_failure;
96518518 1041 nla_nest_end(skb, nest);
9370761c 1042
0ca743a5
PNA
1043 if (nla_put_be32(skb, NFTA_CHAIN_POLICY,
1044 htonl(basechain->policy)))
1045 goto nla_put_failure;
1046
baae3e62
PM
1047 if (nla_put_string(skb, NFTA_CHAIN_TYPE, basechain->type->name))
1048 goto nla_put_failure;
0ca743a5 1049
5f9bfe0e 1050 if (basechain->stats && nft_dump_stats(skb, basechain->stats))
0ca743a5 1051 goto nla_put_failure;
96518518
PM
1052 }
1053
0ca743a5
PNA
1054 if (nla_put_be32(skb, NFTA_CHAIN_USE, htonl(chain->use)))
1055 goto nla_put_failure;
1056
053c095a
JB
1057 nlmsg_end(skb, nlh);
1058 return 0;
96518518
PM
1059
1060nla_put_failure:
1061 nlmsg_trim(skb, nlh);
1062 return -1;
1063}
1064
25e94a99 1065static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
96518518
PM
1066{
1067 struct sk_buff *skb;
96518518
PM
1068 int err;
1069
128ad332
PNA
1070 if (!ctx->report &&
1071 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
25e94a99 1072 return;
96518518 1073
96518518
PM
1074 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1075 if (skb == NULL)
1076 goto err;
1077
84d7fce6 1078 err = nf_tables_fill_chain_info(skb, ctx->net, ctx->portid, ctx->seq,
36596dad 1079 event, 0, ctx->family, ctx->table,
35151d84 1080 ctx->chain);
96518518
PM
1081 if (err < 0) {
1082 kfree_skb(skb);
1083 goto err;
1084 }
1085
25e94a99
PNA
1086 nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1087 ctx->report, GFP_KERNEL);
1088 return;
96518518 1089err:
25e94a99 1090 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
96518518
PM
1091}
1092
1093static int nf_tables_dump_chains(struct sk_buff *skb,
1094 struct netlink_callback *cb)
1095{
1096 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
96518518
PM
1097 const struct nft_table *table;
1098 const struct nft_chain *chain;
1099 unsigned int idx = 0, s_idx = cb->args[0];
99633ab2 1100 struct net *net = sock_net(skb->sk);
96518518
PM
1101 int family = nfmsg->nfgen_family;
1102
e688a7f8 1103 rcu_read_lock();
38e029f1
PNA
1104 cb->seq = net->nft.base_seq;
1105
36596dad 1106 list_for_each_entry_rcu(table, &net->nft.tables, list) {
98319cb9 1107 if (family != NFPROTO_UNSPEC && family != table->family)
96518518
PM
1108 continue;
1109
36596dad
PNA
1110 list_for_each_entry_rcu(chain, &table->chains, list) {
1111 if (idx < s_idx)
1112 goto cont;
1113 if (idx > s_idx)
1114 memset(&cb->args[1], 0,
1115 sizeof(cb->args) - sizeof(cb->args[0]));
1116 if (!nft_is_active(net, chain))
1117 continue;
1118 if (nf_tables_fill_chain_info(skb, net,
1119 NETLINK_CB(cb->skb).portid,
1120 cb->nlh->nlmsg_seq,
1121 NFT_MSG_NEWCHAIN,
1122 NLM_F_MULTI,
98319cb9 1123 table->family, table,
36596dad
PNA
1124 chain) < 0)
1125 goto done;
38e029f1 1126
36596dad 1127 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
96518518 1128cont:
36596dad 1129 idx++;
96518518
PM
1130 }
1131 }
1132done:
e688a7f8 1133 rcu_read_unlock();
96518518
PM
1134 cb->args[0] = idx;
1135 return skb->len;
1136}
1137
7b8002a1
PNA
1138static int nf_tables_getchain(struct net *net, struct sock *nlsk,
1139 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
1140 const struct nlattr * const nla[],
1141 struct netlink_ext_ack *extack)
96518518
PM
1142{
1143 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 1144 u8 genmask = nft_genmask_cur(net);
96518518
PM
1145 const struct nft_table *table;
1146 const struct nft_chain *chain;
1147 struct sk_buff *skb2;
1148 int family = nfmsg->nfgen_family;
1149 int err;
1150
1151 if (nlh->nlmsg_flags & NLM_F_DUMP) {
1152 struct netlink_dump_control c = {
1153 .dump = nf_tables_dump_chains,
1154 };
1155 return netlink_dump_start(nlsk, skb, nlh, &c);
1156 }
1157
cac20fcd 1158 table = nft_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, genmask);
36dd1bcc
PNA
1159 if (IS_ERR(table)) {
1160 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_TABLE]);
96518518 1161 return PTR_ERR(table);
36dd1bcc 1162 }
96518518 1163
cac20fcd 1164 chain = nft_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask);
36dd1bcc
PNA
1165 if (IS_ERR(chain)) {
1166 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_NAME]);
96518518 1167 return PTR_ERR(chain);
36dd1bcc 1168 }
96518518
PM
1169
1170 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1171 if (!skb2)
1172 return -ENOMEM;
1173
84d7fce6 1174 err = nf_tables_fill_chain_info(skb2, net, NETLINK_CB(skb).portid,
96518518
PM
1175 nlh->nlmsg_seq, NFT_MSG_NEWCHAIN, 0,
1176 family, table, chain);
1177 if (err < 0)
1178 goto err;
1179
1180 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
1181
1182err:
1183 kfree_skb(skb2);
1184 return err;
1185}
1186
0ca743a5
PNA
1187static const struct nla_policy nft_counter_policy[NFTA_COUNTER_MAX + 1] = {
1188 [NFTA_COUNTER_PACKETS] = { .type = NLA_U64 },
1189 [NFTA_COUNTER_BYTES] = { .type = NLA_U64 },
1190};
1191
ff3cd7b3 1192static struct nft_stats __percpu *nft_stats_alloc(const struct nlattr *attr)
0ca743a5
PNA
1193{
1194 struct nlattr *tb[NFTA_COUNTER_MAX+1];
1195 struct nft_stats __percpu *newstats;
1196 struct nft_stats *stats;
1197 int err;
1198
fceb6435
JB
1199 err = nla_parse_nested(tb, NFTA_COUNTER_MAX, attr, nft_counter_policy,
1200 NULL);
0ca743a5 1201 if (err < 0)
ff3cd7b3 1202 return ERR_PTR(err);
0ca743a5
PNA
1203
1204 if (!tb[NFTA_COUNTER_BYTES] || !tb[NFTA_COUNTER_PACKETS])
ff3cd7b3 1205 return ERR_PTR(-EINVAL);
0ca743a5 1206
ce355e20 1207 newstats = netdev_alloc_pcpu_stats(struct nft_stats);
0ca743a5 1208 if (newstats == NULL)
ff3cd7b3 1209 return ERR_PTR(-ENOMEM);
0ca743a5
PNA
1210
1211 /* Restore old counters on this cpu, no problem. Per-cpu statistics
1212 * are not exposed to userspace.
1213 */
e8781f70 1214 preempt_disable();
0ca743a5
PNA
1215 stats = this_cpu_ptr(newstats);
1216 stats->bytes = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES]));
1217 stats->pkts = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS]));
e8781f70 1218 preempt_enable();
0ca743a5 1219
ff3cd7b3
PNA
1220 return newstats;
1221}
1222
1223static void nft_chain_stats_replace(struct nft_base_chain *chain,
1224 struct nft_stats __percpu *newstats)
1225{
0befd061
PNA
1226 struct nft_stats __percpu *oldstats;
1227
b88825de
PNA
1228 if (newstats == NULL)
1229 return;
1230
0ca743a5 1231 if (chain->stats) {
0befd061 1232 oldstats = nfnl_dereference(chain->stats, NFNL_SUBSYS_NFTABLES);
0ca743a5
PNA
1233 rcu_assign_pointer(chain->stats, newstats);
1234 synchronize_rcu();
1235 free_percpu(oldstats);
1236 } else
1237 rcu_assign_pointer(chain->stats, newstats);
0ca743a5
PNA
1238}
1239
43a605f2 1240static void nf_tables_chain_destroy(struct nft_ctx *ctx)
91c7b38d 1241{
43a605f2
PNA
1242 struct nft_chain *chain = ctx->chain;
1243
91c7b38d
PNA
1244 BUG_ON(chain->use > 0);
1245
f323d954 1246 if (nft_is_base_chain(chain)) {
2cbce139
PNA
1247 struct nft_base_chain *basechain = nft_base_chain(chain);
1248
1249 module_put(basechain->type->owner);
1250 free_percpu(basechain->stats);
9f08ea84
PNA
1251 if (basechain->stats)
1252 static_branch_dec(&nft_counters_enabled);
b7263e07 1253 kfree(chain->name);
2cbce139 1254 kfree(basechain);
91c7b38d 1255 } else {
b7263e07 1256 kfree(chain->name);
91c7b38d
PNA
1257 kfree(chain);
1258 }
1259}
1260
508f8ccd
PNA
1261struct nft_chain_hook {
1262 u32 num;
84ba7dd7 1263 s32 priority;
32537e91 1264 const struct nft_chain_type *type;
508f8ccd
PNA
1265 struct net_device *dev;
1266};
1267
1268static int nft_chain_parse_hook(struct net *net,
1269 const struct nlattr * const nla[],
36596dad
PNA
1270 struct nft_chain_hook *hook, u8 family,
1271 bool create)
508f8ccd
PNA
1272{
1273 struct nlattr *ha[NFTA_HOOK_MAX + 1];
32537e91 1274 const struct nft_chain_type *type;
508f8ccd
PNA
1275 struct net_device *dev;
1276 int err;
1277
1278 err = nla_parse_nested(ha, NFTA_HOOK_MAX, nla[NFTA_CHAIN_HOOK],
fceb6435 1279 nft_hook_policy, NULL);
508f8ccd
PNA
1280 if (err < 0)
1281 return err;
1282
1283 if (ha[NFTA_HOOK_HOOKNUM] == NULL ||
1284 ha[NFTA_HOOK_PRIORITY] == NULL)
1285 return -EINVAL;
1286
1287 hook->num = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
508f8ccd
PNA
1288 hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
1289
36596dad 1290 type = chain_type[family][NFT_CHAIN_T_DEFAULT];
508f8ccd 1291 if (nla[NFTA_CHAIN_TYPE]) {
1ea26cca 1292 type = nf_tables_chain_type_lookup(nla[NFTA_CHAIN_TYPE],
36596dad 1293 family, create);
508f8ccd
PNA
1294 if (IS_ERR(type))
1295 return PTR_ERR(type);
1296 }
1297 if (!(type->hook_mask & (1 << hook->num)))
1298 return -EOPNOTSUPP;
84ba7dd7
FW
1299
1300 if (type->type == NFT_CHAIN_T_NAT &&
1301 hook->priority <= NF_IP_PRI_CONNTRACK)
1302 return -EOPNOTSUPP;
1303
508f8ccd
PNA
1304 if (!try_module_get(type->owner))
1305 return -ENOENT;
1306
1307 hook->type = type;
1308
1309 hook->dev = NULL;
36596dad 1310 if (family == NFPROTO_NETDEV) {
508f8ccd
PNA
1311 char ifname[IFNAMSIZ];
1312
1313 if (!ha[NFTA_HOOK_DEV]) {
1314 module_put(type->owner);
1315 return -EOPNOTSUPP;
1316 }
1317
1318 nla_strlcpy(ifname, ha[NFTA_HOOK_DEV], IFNAMSIZ);
90d2723c 1319 dev = __dev_get_by_name(net, ifname);
508f8ccd
PNA
1320 if (!dev) {
1321 module_put(type->owner);
1322 return -ENOENT;
1323 }
1324 hook->dev = dev;
1325 } else if (ha[NFTA_HOOK_DEV]) {
1326 module_put(type->owner);
1327 return -EOPNOTSUPP;
1328 }
1329
1330 return 0;
1331}
1332
1333static void nft_chain_release_hook(struct nft_chain_hook *hook)
1334{
1335 module_put(hook->type->owner);
508f8ccd
PNA
1336}
1337
4035285f
PNA
1338static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
1339 u8 policy, bool create)
1340{
1341 const struct nlattr * const *nla = ctx->nla;
1342 struct nft_table *table = ctx->table;
4035285f
PNA
1343 struct nft_base_chain *basechain;
1344 struct nft_stats __percpu *stats;
1345 struct net *net = ctx->net;
1346 struct nft_chain *chain;
4035285f
PNA
1347 int err;
1348
1349 if (table->use == UINT_MAX)
1350 return -EOVERFLOW;
1351
1352 if (nla[NFTA_CHAIN_HOOK]) {
1353 struct nft_chain_hook hook;
1354 struct nf_hook_ops *ops;
4035285f 1355
36596dad 1356 err = nft_chain_parse_hook(net, nla, &hook, family, create);
4035285f
PNA
1357 if (err < 0)
1358 return err;
1359
1360 basechain = kzalloc(sizeof(*basechain), GFP_KERNEL);
1361 if (basechain == NULL) {
1362 nft_chain_release_hook(&hook);
1363 return -ENOMEM;
1364 }
1365
1366 if (hook.dev != NULL)
1367 strncpy(basechain->dev_name, hook.dev->name, IFNAMSIZ);
1368
1369 if (nla[NFTA_CHAIN_COUNTERS]) {
1370 stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
1371 if (IS_ERR(stats)) {
1372 nft_chain_release_hook(&hook);
1373 kfree(basechain);
1374 return PTR_ERR(stats);
1375 }
1376 basechain->stats = stats;
1377 static_branch_inc(&nft_counters_enabled);
1378 }
1379
4035285f
PNA
1380 basechain->type = hook.type;
1381 chain = &basechain->chain;
1382
c974a3a3
PNA
1383 ops = &basechain->ops;
1384 ops->pf = family;
1385 ops->hooknum = hook.num;
1386 ops->priority = hook.priority;
1387 ops->priv = chain;
c2f9eafe 1388 ops->hook = hook.type->hooks[ops->hooknum];
c974a3a3 1389 ops->dev = hook.dev;
c974a3a3 1390
4035285f
PNA
1391 chain->flags |= NFT_BASE_CHAIN;
1392 basechain->policy = policy;
1393 } else {
1394 chain = kzalloc(sizeof(*chain), GFP_KERNEL);
1395 if (chain == NULL)
1396 return -ENOMEM;
1397 }
43a605f2
PNA
1398 ctx->chain = chain;
1399
4035285f
PNA
1400 INIT_LIST_HEAD(&chain->rules);
1401 chain->handle = nf_tables_alloc_handle(table);
1402 chain->table = table;
1403 chain->name = nla_strdup(nla[NFTA_CHAIN_NAME], GFP_KERNEL);
1404 if (!chain->name) {
1405 err = -ENOMEM;
1406 goto err1;
1407 }
1408
c974a3a3 1409 err = nf_tables_register_hook(net, table, chain);
4035285f
PNA
1410 if (err < 0)
1411 goto err1;
1412
4035285f
PNA
1413 err = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN);
1414 if (err < 0)
1415 goto err2;
1416
1417 table->use++;
1418 list_add_tail_rcu(&chain->list, &table->chains);
1419
1420 return 0;
1421err2:
c974a3a3 1422 nf_tables_unregister_hook(net, table, chain);
4035285f 1423err1:
43a605f2 1424 nf_tables_chain_destroy(ctx);
4035285f
PNA
1425
1426 return err;
1427}
1428
2c4a488a
PNA
1429static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
1430 bool create)
1431{
1432 const struct nlattr * const *nla = ctx->nla;
1433 struct nft_table *table = ctx->table;
1434 struct nft_chain *chain = ctx->chain;
2c4a488a
PNA
1435 struct nft_base_chain *basechain;
1436 struct nft_stats *stats = NULL;
1437 struct nft_chain_hook hook;
1438 const struct nlattr *name;
1439 struct nf_hook_ops *ops;
1440 struct nft_trans *trans;
c974a3a3 1441 int err;
2c4a488a
PNA
1442
1443 if (nla[NFTA_CHAIN_HOOK]) {
1444 if (!nft_is_base_chain(chain))
1445 return -EBUSY;
1446
36596dad 1447 err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family,
2c4a488a
PNA
1448 create);
1449 if (err < 0)
1450 return err;
1451
1452 basechain = nft_base_chain(chain);
1453 if (basechain->type != hook.type) {
1454 nft_chain_release_hook(&hook);
1455 return -EBUSY;
1456 }
1457
c974a3a3
PNA
1458 ops = &basechain->ops;
1459 if (ops->hooknum != hook.num ||
1460 ops->priority != hook.priority ||
1461 ops->dev != hook.dev) {
1462 nft_chain_release_hook(&hook);
1463 return -EBUSY;
2c4a488a
PNA
1464 }
1465 nft_chain_release_hook(&hook);
1466 }
1467
1468 if (nla[NFTA_CHAIN_HANDLE] &&
1469 nla[NFTA_CHAIN_NAME]) {
1470 struct nft_chain *chain2;
1471
cac20fcd 1472 chain2 = nft_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask);
0d18779b
JC
1473 if (!IS_ERR(chain2))
1474 return -EEXIST;
2c4a488a
PNA
1475 }
1476
1477 if (nla[NFTA_CHAIN_COUNTERS]) {
1478 if (!nft_is_base_chain(chain))
1479 return -EOPNOTSUPP;
1480
1481 stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
1482 if (IS_ERR(stats))
1483 return PTR_ERR(stats);
1484 }
1485
1486 trans = nft_trans_alloc(ctx, NFT_MSG_NEWCHAIN,
1487 sizeof(struct nft_trans_chain));
1488 if (trans == NULL) {
1489 free_percpu(stats);
1490 return -ENOMEM;
1491 }
1492
1493 nft_trans_chain_stats(trans) = stats;
1494 nft_trans_chain_update(trans) = true;
1495
1496 if (nla[NFTA_CHAIN_POLICY])
1497 nft_trans_chain_policy(trans) = policy;
1498 else
1499 nft_trans_chain_policy(trans) = -1;
1500
1501 name = nla[NFTA_CHAIN_NAME];
1502 if (nla[NFTA_CHAIN_HANDLE] && name) {
1503 nft_trans_chain_name(trans) =
1504 nla_strdup(name, GFP_KERNEL);
1505 if (!nft_trans_chain_name(trans)) {
1506 kfree(trans);
1507 free_percpu(stats);
1508 return -ENOMEM;
1509 }
1510 }
1511 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
1512
1513 return 0;
1514}
1515
633c9a84
PNA
1516static int nf_tables_newchain(struct net *net, struct sock *nlsk,
1517 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
1518 const struct nlattr * const nla[],
1519 struct netlink_ext_ack *extack)
96518518
PM
1520{
1521 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
4035285f
PNA
1522 u8 genmask = nft_genmask_next(net);
1523 int family = nfmsg->nfgen_family;
36dd1bcc 1524 const struct nlattr *attr;
96518518
PM
1525 struct nft_table *table;
1526 struct nft_chain *chain;
57de2a0c 1527 u8 policy = NF_ACCEPT;
4035285f 1528 struct nft_ctx ctx;
96518518 1529 u64 handle = 0;
96518518
PM
1530 bool create;
1531
1532 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
1533
cac20fcd 1534 table = nft_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, genmask);
36dd1bcc
PNA
1535 if (IS_ERR(table)) {
1536 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_TABLE]);
96518518 1537 return PTR_ERR(table);
36dd1bcc 1538 }
96518518 1539
96518518 1540 chain = NULL;
36dd1bcc 1541 attr = nla[NFTA_CHAIN_NAME];
96518518
PM
1542
1543 if (nla[NFTA_CHAIN_HANDLE]) {
1544 handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE]));
cac20fcd 1545 chain = nft_chain_lookup_byhandle(table, handle, genmask);
36dd1bcc
PNA
1546 if (IS_ERR(chain)) {
1547 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_HANDLE]);
96518518 1548 return PTR_ERR(chain);
36dd1bcc
PNA
1549 }
1550 attr = nla[NFTA_CHAIN_HANDLE];
96518518 1551 } else {
36dd1bcc 1552 chain = nft_chain_lookup(table, attr, genmask);
96518518 1553 if (IS_ERR(chain)) {
36dd1bcc
PNA
1554 if (PTR_ERR(chain) != -ENOENT) {
1555 NL_SET_BAD_ATTR(extack, attr);
96518518 1556 return PTR_ERR(chain);
36dd1bcc 1557 }
96518518
PM
1558 chain = NULL;
1559 }
1560 }
1561
57de2a0c 1562 if (nla[NFTA_CHAIN_POLICY]) {
f323d954 1563 if (chain != NULL &&
36dd1bcc
PNA
1564 !nft_is_base_chain(chain)) {
1565 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_POLICY]);
d6b6cb1d 1566 return -EOPNOTSUPP;
36dd1bcc 1567 }
d6b6cb1d
PNA
1568
1569 if (chain == NULL &&
36dd1bcc
PNA
1570 nla[NFTA_CHAIN_HOOK] == NULL) {
1571 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_POLICY]);
57de2a0c 1572 return -EOPNOTSUPP;
36dd1bcc 1573 }
57de2a0c 1574
8f46df18 1575 policy = ntohl(nla_get_be32(nla[NFTA_CHAIN_POLICY]));
57de2a0c
PM
1576 switch (policy) {
1577 case NF_DROP:
1578 case NF_ACCEPT:
1579 break;
1580 default:
1581 return -EINVAL;
1582 }
1583 }
1584
98319cb9 1585 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
4035285f 1586
96518518 1587 if (chain != NULL) {
36dd1bcc
PNA
1588 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1589 NL_SET_BAD_ATTR(extack, attr);
96518518 1590 return -EEXIST;
36dd1bcc 1591 }
96518518
PM
1592 if (nlh->nlmsg_flags & NLM_F_REPLACE)
1593 return -EOPNOTSUPP;
1594
2c4a488a 1595 return nf_tables_updchain(&ctx, genmask, policy, create);
96518518
PM
1596 }
1597
4035285f 1598 return nf_tables_addchain(&ctx, family, genmask, policy, create);
96518518
PM
1599}
1600
633c9a84
PNA
1601static int nf_tables_delchain(struct net *net, struct sock *nlsk,
1602 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
1603 const struct nlattr * const nla[],
1604 struct netlink_ext_ack *extack)
96518518
PM
1605{
1606 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 1607 u8 genmask = nft_genmask_next(net);
36dd1bcc
PNA
1608 int family = nfmsg->nfgen_family;
1609 const struct nlattr *attr;
96518518
PM
1610 struct nft_table *table;
1611 struct nft_chain *chain;
9dee1474 1612 struct nft_rule *rule;
91c7b38d 1613 struct nft_ctx ctx;
3ecbfd65 1614 u64 handle;
9dee1474
PNA
1615 u32 use;
1616 int err;
96518518 1617
cac20fcd 1618 table = nft_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, genmask);
36dd1bcc
PNA
1619 if (IS_ERR(table)) {
1620 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_TABLE]);
96518518 1621 return PTR_ERR(table);
36dd1bcc 1622 }
96518518 1623
3ecbfd65 1624 if (nla[NFTA_CHAIN_HANDLE]) {
36dd1bcc
PNA
1625 attr = nla[NFTA_CHAIN_HANDLE];
1626 handle = be64_to_cpu(nla_get_be64(attr));
cac20fcd 1627 chain = nft_chain_lookup_byhandle(table, handle, genmask);
3ecbfd65 1628 } else {
36dd1bcc
PNA
1629 attr = nla[NFTA_CHAIN_NAME];
1630 chain = nft_chain_lookup(table, attr, genmask);
3ecbfd65 1631 }
36dd1bcc
PNA
1632 if (IS_ERR(chain)) {
1633 NL_SET_BAD_ATTR(extack, attr);
96518518 1634 return PTR_ERR(chain);
36dd1bcc 1635 }
9dee1474
PNA
1636
1637 if (nlh->nlmsg_flags & NLM_F_NONREC &&
1638 chain->use > 0)
96518518
PM
1639 return -EBUSY;
1640
98319cb9 1641 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
0165d932 1642
9dee1474
PNA
1643 use = chain->use;
1644 list_for_each_entry(rule, &chain->rules, list) {
1645 if (!nft_is_active_next(net, rule))
1646 continue;
1647 use--;
1648
1649 err = nft_delrule(&ctx, rule);
1650 if (err < 0)
1651 return err;
1652 }
1653
1654 /* There are rules and elements that are still holding references to us,
1655 * we cannot do a recursive removal in this case.
1656 */
36dd1bcc
PNA
1657 if (use > 0) {
1658 NL_SET_BAD_ATTR(extack, attr);
9dee1474 1659 return -EBUSY;
36dd1bcc 1660 }
9dee1474 1661
ee01d542 1662 return nft_delchain(&ctx);
96518518
PM
1663}
1664
96518518
PM
1665/*
1666 * Expressions
1667 */
1668
1669/**
ef1f7df9
PM
1670 * nft_register_expr - register nf_tables expr type
1671 * @ops: expr type
96518518 1672 *
ef1f7df9 1673 * Registers the expr type for use with nf_tables. Returns zero on
96518518
PM
1674 * success or a negative errno code otherwise.
1675 */
ef1f7df9 1676int nft_register_expr(struct nft_expr_type *type)
96518518
PM
1677{
1678 nfnl_lock(NFNL_SUBSYS_NFTABLES);
758dbcec 1679 if (type->family == NFPROTO_UNSPEC)
e688a7f8 1680 list_add_tail_rcu(&type->list, &nf_tables_expressions);
758dbcec 1681 else
e688a7f8 1682 list_add_rcu(&type->list, &nf_tables_expressions);
96518518
PM
1683 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1684 return 0;
1685}
1686EXPORT_SYMBOL_GPL(nft_register_expr);
1687
1688/**
ef1f7df9
PM
1689 * nft_unregister_expr - unregister nf_tables expr type
1690 * @ops: expr type
96518518 1691 *
ef1f7df9 1692 * Unregisters the expr typefor use with nf_tables.
96518518 1693 */
ef1f7df9 1694void nft_unregister_expr(struct nft_expr_type *type)
96518518
PM
1695{
1696 nfnl_lock(NFNL_SUBSYS_NFTABLES);
e688a7f8 1697 list_del_rcu(&type->list);
96518518
PM
1698 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1699}
1700EXPORT_SYMBOL_GPL(nft_unregister_expr);
1701
64d46806
PM
1702static const struct nft_expr_type *__nft_expr_type_get(u8 family,
1703 struct nlattr *nla)
96518518 1704{
ef1f7df9 1705 const struct nft_expr_type *type;
96518518 1706
ef1f7df9 1707 list_for_each_entry(type, &nf_tables_expressions, list) {
64d46806
PM
1708 if (!nla_strcmp(nla, type->name) &&
1709 (!type->family || type->family == family))
ef1f7df9 1710 return type;
96518518
PM
1711 }
1712 return NULL;
1713}
1714
64d46806
PM
1715static const struct nft_expr_type *nft_expr_type_get(u8 family,
1716 struct nlattr *nla)
96518518 1717{
ef1f7df9 1718 const struct nft_expr_type *type;
96518518
PM
1719
1720 if (nla == NULL)
1721 return ERR_PTR(-EINVAL);
1722
64d46806 1723 type = __nft_expr_type_get(family, nla);
ef1f7df9
PM
1724 if (type != NULL && try_module_get(type->owner))
1725 return type;
96518518
PM
1726
1727#ifdef CONFIG_MODULES
ef1f7df9 1728 if (type == NULL) {
64d46806
PM
1729 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1730 request_module("nft-expr-%u-%.*s", family,
1731 nla_len(nla), (char *)nla_data(nla));
1732 nfnl_lock(NFNL_SUBSYS_NFTABLES);
1733 if (__nft_expr_type_get(family, nla))
1734 return ERR_PTR(-EAGAIN);
1735
96518518
PM
1736 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1737 request_module("nft-expr-%.*s",
1738 nla_len(nla), (char *)nla_data(nla));
1739 nfnl_lock(NFNL_SUBSYS_NFTABLES);
64d46806 1740 if (__nft_expr_type_get(family, nla))
96518518
PM
1741 return ERR_PTR(-EAGAIN);
1742 }
1743#endif
1744 return ERR_PTR(-ENOENT);
1745}
1746
1747static const struct nla_policy nft_expr_policy[NFTA_EXPR_MAX + 1] = {
1748 [NFTA_EXPR_NAME] = { .type = NLA_STRING },
1749 [NFTA_EXPR_DATA] = { .type = NLA_NESTED },
1750};
1751
1752static int nf_tables_fill_expr_info(struct sk_buff *skb,
1753 const struct nft_expr *expr)
1754{
ef1f7df9 1755 if (nla_put_string(skb, NFTA_EXPR_NAME, expr->ops->type->name))
96518518
PM
1756 goto nla_put_failure;
1757
1758 if (expr->ops->dump) {
1759 struct nlattr *data = nla_nest_start(skb, NFTA_EXPR_DATA);
1760 if (data == NULL)
1761 goto nla_put_failure;
1762 if (expr->ops->dump(skb, expr) < 0)
1763 goto nla_put_failure;
1764 nla_nest_end(skb, data);
1765 }
1766
1767 return skb->len;
1768
1769nla_put_failure:
1770 return -1;
1771};
1772
0b2d8a7b
PM
1773int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
1774 const struct nft_expr *expr)
1775{
1776 struct nlattr *nest;
1777
1778 nest = nla_nest_start(skb, attr);
1779 if (!nest)
1780 goto nla_put_failure;
1781 if (nf_tables_fill_expr_info(skb, expr) < 0)
1782 goto nla_put_failure;
1783 nla_nest_end(skb, nest);
1784 return 0;
1785
1786nla_put_failure:
1787 return -1;
1788}
1789
96518518
PM
1790struct nft_expr_info {
1791 const struct nft_expr_ops *ops;
ef1f7df9 1792 struct nlattr *tb[NFT_EXPR_MAXATTR + 1];
96518518
PM
1793};
1794
0ca743a5
PNA
1795static int nf_tables_expr_parse(const struct nft_ctx *ctx,
1796 const struct nlattr *nla,
96518518
PM
1797 struct nft_expr_info *info)
1798{
ef1f7df9 1799 const struct nft_expr_type *type;
96518518 1800 const struct nft_expr_ops *ops;
ef1f7df9 1801 struct nlattr *tb[NFTA_EXPR_MAX + 1];
96518518
PM
1802 int err;
1803
fceb6435 1804 err = nla_parse_nested(tb, NFTA_EXPR_MAX, nla, nft_expr_policy, NULL);
96518518
PM
1805 if (err < 0)
1806 return err;
1807
36596dad 1808 type = nft_expr_type_get(ctx->family, tb[NFTA_EXPR_NAME]);
ef1f7df9
PM
1809 if (IS_ERR(type))
1810 return PTR_ERR(type);
1811
1812 if (tb[NFTA_EXPR_DATA]) {
1813 err = nla_parse_nested(info->tb, type->maxattr,
fceb6435 1814 tb[NFTA_EXPR_DATA], type->policy, NULL);
ef1f7df9
PM
1815 if (err < 0)
1816 goto err1;
1817 } else
1818 memset(info->tb, 0, sizeof(info->tb[0]) * (type->maxattr + 1));
1819
1820 if (type->select_ops != NULL) {
0ca743a5
PNA
1821 ops = type->select_ops(ctx,
1822 (const struct nlattr * const *)info->tb);
ef1f7df9
PM
1823 if (IS_ERR(ops)) {
1824 err = PTR_ERR(ops);
1825 goto err1;
1826 }
1827 } else
1828 ops = type->ops;
1829
96518518
PM
1830 info->ops = ops;
1831 return 0;
ef1f7df9
PM
1832
1833err1:
1834 module_put(type->owner);
1835 return err;
96518518
PM
1836}
1837
1838static int nf_tables_newexpr(const struct nft_ctx *ctx,
ef1f7df9 1839 const struct nft_expr_info *info,
96518518
PM
1840 struct nft_expr *expr)
1841{
1842 const struct nft_expr_ops *ops = info->ops;
1843 int err;
1844
1845 expr->ops = ops;
1846 if (ops->init) {
ef1f7df9 1847 err = ops->init(ctx, expr, (const struct nlattr **)info->tb);
96518518
PM
1848 if (err < 0)
1849 goto err1;
1850 }
1851
c56e3956
LZ
1852 if (ops->validate) {
1853 const struct nft_data *data = NULL;
1854
1855 err = ops->validate(ctx, expr, &data);
1856 if (err < 0)
1857 goto err2;
1858 }
1859
96518518
PM
1860 return 0;
1861
c56e3956
LZ
1862err2:
1863 if (ops->destroy)
1864 ops->destroy(ctx, expr);
96518518
PM
1865err1:
1866 expr->ops = NULL;
1867 return err;
1868}
1869
62472bce
PM
1870static void nf_tables_expr_destroy(const struct nft_ctx *ctx,
1871 struct nft_expr *expr)
96518518
PM
1872{
1873 if (expr->ops->destroy)
62472bce 1874 expr->ops->destroy(ctx, expr);
ef1f7df9 1875 module_put(expr->ops->type->owner);
96518518
PM
1876}
1877
0b2d8a7b
PM
1878struct nft_expr *nft_expr_init(const struct nft_ctx *ctx,
1879 const struct nlattr *nla)
1880{
1881 struct nft_expr_info info;
1882 struct nft_expr *expr;
1883 int err;
1884
1885 err = nf_tables_expr_parse(ctx, nla, &info);
1886 if (err < 0)
1887 goto err1;
1888
1889 err = -ENOMEM;
1890 expr = kzalloc(info.ops->size, GFP_KERNEL);
1891 if (expr == NULL)
1892 goto err2;
1893
1894 err = nf_tables_newexpr(ctx, &info, expr);
1895 if (err < 0)
6cafaf47 1896 goto err3;
0b2d8a7b
PM
1897
1898 return expr;
6cafaf47
LZ
1899err3:
1900 kfree(expr);
0b2d8a7b
PM
1901err2:
1902 module_put(info.ops->type->owner);
1903err1:
1904 return ERR_PTR(err);
1905}
1906
1907void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr)
1908{
1909 nf_tables_expr_destroy(ctx, expr);
1910 kfree(expr);
1911}
1912
96518518
PM
1913/*
1914 * Rules
1915 */
1916
cac20fcd
PNA
1917static struct nft_rule *__nft_rule_lookup(const struct nft_chain *chain,
1918 u64 handle)
96518518
PM
1919{
1920 struct nft_rule *rule;
1921
1922 // FIXME: this sucks
1923 list_for_each_entry(rule, &chain->rules, list) {
1924 if (handle == rule->handle)
1925 return rule;
1926 }
1927
1928 return ERR_PTR(-ENOENT);
1929}
1930
cac20fcd
PNA
1931static struct nft_rule *nft_rule_lookup(const struct nft_chain *chain,
1932 const struct nlattr *nla)
96518518
PM
1933{
1934 if (nla == NULL)
1935 return ERR_PTR(-EINVAL);
1936
cac20fcd 1937 return __nft_rule_lookup(chain, be64_to_cpu(nla_get_be64(nla)));
96518518
PM
1938}
1939
1940static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
b2fbd044
LZ
1941 [NFTA_RULE_TABLE] = { .type = NLA_STRING,
1942 .len = NFT_TABLE_MAXNAMELEN - 1 },
96518518
PM
1943 [NFTA_RULE_CHAIN] = { .type = NLA_STRING,
1944 .len = NFT_CHAIN_MAXNAMELEN - 1 },
1945 [NFTA_RULE_HANDLE] = { .type = NLA_U64 },
1946 [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED },
0ca743a5 1947 [NFTA_RULE_COMPAT] = { .type = NLA_NESTED },
5e948466 1948 [NFTA_RULE_POSITION] = { .type = NLA_U64 },
0768b3b3
PNA
1949 [NFTA_RULE_USERDATA] = { .type = NLA_BINARY,
1950 .len = NFT_USERDATA_MAXLEN },
467697d2 1951 [NFTA_RULE_ID] = { .type = NLA_U32 },
96518518
PM
1952};
1953
84d7fce6
PNA
1954static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
1955 u32 portid, u32 seq, int event,
1956 u32 flags, int family,
96518518
PM
1957 const struct nft_table *table,
1958 const struct nft_chain *chain,
1959 const struct nft_rule *rule)
1960{
1961 struct nlmsghdr *nlh;
1962 struct nfgenmsg *nfmsg;
1963 const struct nft_expr *expr, *next;
1964 struct nlattr *list;
5e948466 1965 const struct nft_rule *prule;
dedb67c4 1966 u16 type = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
96518518 1967
dedb67c4 1968 nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg), flags);
96518518
PM
1969 if (nlh == NULL)
1970 goto nla_put_failure;
1971
1972 nfmsg = nlmsg_data(nlh);
1973 nfmsg->nfgen_family = family;
1974 nfmsg->version = NFNETLINK_V0;
84d7fce6 1975 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
96518518
PM
1976
1977 if (nla_put_string(skb, NFTA_RULE_TABLE, table->name))
1978 goto nla_put_failure;
1979 if (nla_put_string(skb, NFTA_RULE_CHAIN, chain->name))
1980 goto nla_put_failure;
b46f6ded
ND
1981 if (nla_put_be64(skb, NFTA_RULE_HANDLE, cpu_to_be64(rule->handle),
1982 NFTA_RULE_PAD))
96518518
PM
1983 goto nla_put_failure;
1984
5e948466 1985 if ((event != NFT_MSG_DELRULE) && (rule->list.prev != &chain->rules)) {
cbbb40e2 1986 prule = list_prev_entry(rule, list);
5e948466 1987 if (nla_put_be64(skb, NFTA_RULE_POSITION,
b46f6ded
ND
1988 cpu_to_be64(prule->handle),
1989 NFTA_RULE_PAD))
5e948466
EL
1990 goto nla_put_failure;
1991 }
1992
96518518
PM
1993 list = nla_nest_start(skb, NFTA_RULE_EXPRESSIONS);
1994 if (list == NULL)
1995 goto nla_put_failure;
1996 nft_rule_for_each_expr(expr, next, rule) {
0b2d8a7b 1997 if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr) < 0)
96518518 1998 goto nla_put_failure;
96518518
PM
1999 }
2000 nla_nest_end(skb, list);
2001
86f1ec32
PM
2002 if (rule->udata) {
2003 struct nft_userdata *udata = nft_userdata(rule);
2004 if (nla_put(skb, NFTA_RULE_USERDATA, udata->len + 1,
2005 udata->data) < 0)
2006 goto nla_put_failure;
2007 }
0768b3b3 2008
053c095a
JB
2009 nlmsg_end(skb, nlh);
2010 return 0;
96518518
PM
2011
2012nla_put_failure:
2013 nlmsg_trim(skb, nlh);
2014 return -1;
2015}
2016
25e94a99
PNA
2017static void nf_tables_rule_notify(const struct nft_ctx *ctx,
2018 const struct nft_rule *rule, int event)
96518518
PM
2019{
2020 struct sk_buff *skb;
96518518
PM
2021 int err;
2022
128ad332
PNA
2023 if (!ctx->report &&
2024 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
25e94a99 2025 return;
96518518 2026
96518518
PM
2027 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
2028 if (skb == NULL)
2029 goto err;
2030
84d7fce6 2031 err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq,
36596dad 2032 event, 0, ctx->family, ctx->table,
35151d84 2033 ctx->chain, rule);
96518518
PM
2034 if (err < 0) {
2035 kfree_skb(skb);
2036 goto err;
2037 }
2038
25e94a99
PNA
2039 nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
2040 ctx->report, GFP_KERNEL);
2041 return;
96518518 2042err:
25e94a99 2043 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
96518518
PM
2044}
2045
6e1f760e 2046struct nft_rule_dump_ctx {
e46abbcc 2047 char *table;
b7263e07 2048 char *chain;
6e1f760e
PNA
2049};
2050
96518518
PM
2051static int nf_tables_dump_rules(struct sk_buff *skb,
2052 struct netlink_callback *cb)
2053{
2054 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
6e1f760e 2055 const struct nft_rule_dump_ctx *ctx = cb->data;
96518518
PM
2056 const struct nft_table *table;
2057 const struct nft_chain *chain;
2058 const struct nft_rule *rule;
2059 unsigned int idx = 0, s_idx = cb->args[0];
99633ab2 2060 struct net *net = sock_net(skb->sk);
96518518
PM
2061 int family = nfmsg->nfgen_family;
2062
e688a7f8 2063 rcu_read_lock();
38e029f1
PNA
2064 cb->seq = net->nft.base_seq;
2065
36596dad 2066 list_for_each_entry_rcu(table, &net->nft.tables, list) {
98319cb9 2067 if (family != NFPROTO_UNSPEC && family != table->family)
36596dad
PNA
2068 continue;
2069
2070 if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0)
96518518
PM
2071 continue;
2072
36596dad
PNA
2073 list_for_each_entry_rcu(chain, &table->chains, list) {
2074 if (ctx && ctx->chain &&
2075 strcmp(ctx->chain, chain->name) != 0)
6e1f760e
PNA
2076 continue;
2077
36596dad
PNA
2078 list_for_each_entry_rcu(rule, &chain->rules, list) {
2079 if (!nft_is_active(net, rule))
2080 goto cont;
2081 if (idx < s_idx)
2082 goto cont;
2083 if (idx > s_idx)
2084 memset(&cb->args[1], 0,
2085 sizeof(cb->args) - sizeof(cb->args[0]));
2086 if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid,
2087 cb->nlh->nlmsg_seq,
2088 NFT_MSG_NEWRULE,
2089 NLM_F_MULTI | NLM_F_APPEND,
98319cb9 2090 table->family,
36596dad
PNA
2091 table, chain, rule) < 0)
2092 goto done;
2093
2094 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
96518518 2095cont:
36596dad 2096 idx++;
96518518
PM
2097 }
2098 }
2099 }
2100done:
e688a7f8
PNA
2101 rcu_read_unlock();
2102
96518518
PM
2103 cb->args[0] = idx;
2104 return skb->len;
2105}
2106
6e1f760e
PNA
2107static int nf_tables_dump_rules_done(struct netlink_callback *cb)
2108{
e46abbcc
PS
2109 struct nft_rule_dump_ctx *ctx = cb->data;
2110
2111 if (ctx) {
2112 kfree(ctx->table);
b7263e07 2113 kfree(ctx->chain);
e46abbcc
PS
2114 kfree(ctx);
2115 }
6e1f760e
PNA
2116 return 0;
2117}
2118
7b8002a1
PNA
2119static int nf_tables_getrule(struct net *net, struct sock *nlsk,
2120 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
2121 const struct nlattr * const nla[],
2122 struct netlink_ext_ack *extack)
96518518
PM
2123{
2124 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 2125 u8 genmask = nft_genmask_cur(net);
96518518
PM
2126 const struct nft_table *table;
2127 const struct nft_chain *chain;
2128 const struct nft_rule *rule;
2129 struct sk_buff *skb2;
2130 int family = nfmsg->nfgen_family;
2131 int err;
2132
2133 if (nlh->nlmsg_flags & NLM_F_DUMP) {
2134 struct netlink_dump_control c = {
2135 .dump = nf_tables_dump_rules,
6e1f760e 2136 .done = nf_tables_dump_rules_done,
96518518 2137 };
6e1f760e
PNA
2138
2139 if (nla[NFTA_RULE_TABLE] || nla[NFTA_RULE_CHAIN]) {
2140 struct nft_rule_dump_ctx *ctx;
2141
2142 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
2143 if (!ctx)
2144 return -ENOMEM;
2145
e46abbcc
PS
2146 if (nla[NFTA_RULE_TABLE]) {
2147 ctx->table = nla_strdup(nla[NFTA_RULE_TABLE],
2148 GFP_KERNEL);
2149 if (!ctx->table) {
2150 kfree(ctx);
2151 return -ENOMEM;
2152 }
2153 }
b7263e07
PS
2154 if (nla[NFTA_RULE_CHAIN]) {
2155 ctx->chain = nla_strdup(nla[NFTA_RULE_CHAIN],
2156 GFP_KERNEL);
2157 if (!ctx->chain) {
2158 kfree(ctx->table);
2159 kfree(ctx);
2160 return -ENOMEM;
2161 }
2162 }
6e1f760e
PNA
2163 c.data = ctx;
2164 }
2165
96518518
PM
2166 return netlink_dump_start(nlsk, skb, nlh, &c);
2167 }
2168
cac20fcd 2169 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask);
36dd1bcc
PNA
2170 if (IS_ERR(table)) {
2171 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_TABLE]);
96518518 2172 return PTR_ERR(table);
36dd1bcc 2173 }
96518518 2174
cac20fcd 2175 chain = nft_chain_lookup(table, nla[NFTA_RULE_CHAIN], genmask);
36dd1bcc
PNA
2176 if (IS_ERR(chain)) {
2177 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
96518518 2178 return PTR_ERR(chain);
36dd1bcc 2179 }
96518518 2180
cac20fcd 2181 rule = nft_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
36dd1bcc
PNA
2182 if (IS_ERR(rule)) {
2183 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]);
96518518 2184 return PTR_ERR(rule);
36dd1bcc 2185 }
96518518
PM
2186
2187 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
2188 if (!skb2)
2189 return -ENOMEM;
2190
84d7fce6 2191 err = nf_tables_fill_rule_info(skb2, net, NETLINK_CB(skb).portid,
96518518
PM
2192 nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
2193 family, table, chain, rule);
2194 if (err < 0)
2195 goto err;
2196
2197 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
2198
2199err:
2200 kfree_skb(skb2);
2201 return err;
2202}
2203
62472bce
PM
2204static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
2205 struct nft_rule *rule)
96518518 2206{
96518518
PM
2207 struct nft_expr *expr;
2208
2209 /*
2210 * Careful: some expressions might not be initialized in case this
2211 * is called on error from nf_tables_newrule().
2212 */
2213 expr = nft_expr_first(rule);
3e38df13 2214 while (expr != nft_expr_last(rule) && expr->ops) {
62472bce 2215 nf_tables_expr_destroy(ctx, expr);
96518518
PM
2216 expr = nft_expr_next(expr);
2217 }
2218 kfree(rule);
2219}
2220
bb7b40ae
PNA
2221static void nf_tables_rule_release(const struct nft_ctx *ctx,
2222 struct nft_rule *rule)
2223{
2224 nft_rule_expr_deactivate(ctx, rule);
2225 nf_tables_rule_destroy(ctx, rule);
2226}
2227
1081d11b
PNA
2228#define NFT_RULE_MAXEXPRS 128
2229
2230static struct nft_expr_info *info;
2231
633c9a84
PNA
2232static int nf_tables_newrule(struct net *net, struct sock *nlsk,
2233 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
2234 const struct nlattr * const nla[],
2235 struct netlink_ext_ack *extack)
96518518
PM
2236{
2237 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 2238 u8 genmask = nft_genmask_next(net);
98319cb9 2239 int family = nfmsg->nfgen_family;
96518518
PM
2240 struct nft_table *table;
2241 struct nft_chain *chain;
2242 struct nft_rule *rule, *old_rule = NULL;
86f1ec32 2243 struct nft_userdata *udata;
1081d11b 2244 struct nft_trans *trans = NULL;
96518518
PM
2245 struct nft_expr *expr;
2246 struct nft_ctx ctx;
2247 struct nlattr *tmp;
86f1ec32 2248 unsigned int size, i, n, ulen = 0, usize = 0;
96518518
PM
2249 int err, rem;
2250 bool create;
5e948466 2251 u64 handle, pos_handle;
96518518
PM
2252
2253 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
2254
cac20fcd 2255 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask);
36dd1bcc
PNA
2256 if (IS_ERR(table)) {
2257 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_TABLE]);
96518518 2258 return PTR_ERR(table);
36dd1bcc 2259 }
96518518 2260
cac20fcd 2261 chain = nft_chain_lookup(table, nla[NFTA_RULE_CHAIN], genmask);
36dd1bcc
PNA
2262 if (IS_ERR(chain)) {
2263 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
96518518 2264 return PTR_ERR(chain);
36dd1bcc 2265 }
96518518
PM
2266
2267 if (nla[NFTA_RULE_HANDLE]) {
2268 handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_HANDLE]));
cac20fcd 2269 rule = __nft_rule_lookup(chain, handle);
36dd1bcc
PNA
2270 if (IS_ERR(rule)) {
2271 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]);
96518518 2272 return PTR_ERR(rule);
36dd1bcc 2273 }
96518518 2274
36dd1bcc
PNA
2275 if (nlh->nlmsg_flags & NLM_F_EXCL) {
2276 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]);
96518518 2277 return -EEXIST;
36dd1bcc 2278 }
96518518
PM
2279 if (nlh->nlmsg_flags & NLM_F_REPLACE)
2280 old_rule = rule;
2281 else
2282 return -EOPNOTSUPP;
2283 } else {
2284 if (!create || nlh->nlmsg_flags & NLM_F_REPLACE)
2285 return -EINVAL;
2286 handle = nf_tables_alloc_handle(table);
a0a7379e
PNA
2287
2288 if (chain->use == UINT_MAX)
2289 return -EOVERFLOW;
96518518
PM
2290 }
2291
5e948466
EL
2292 if (nla[NFTA_RULE_POSITION]) {
2293 if (!(nlh->nlmsg_flags & NLM_F_CREATE))
2294 return -EOPNOTSUPP;
2295
2296 pos_handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_POSITION]));
cac20fcd 2297 old_rule = __nft_rule_lookup(chain, pos_handle);
36dd1bcc
PNA
2298 if (IS_ERR(old_rule)) {
2299 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_POSITION]);
5e948466 2300 return PTR_ERR(old_rule);
36dd1bcc 2301 }
5e948466
EL
2302 }
2303
98319cb9 2304 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
0ca743a5 2305
96518518
PM
2306 n = 0;
2307 size = 0;
2308 if (nla[NFTA_RULE_EXPRESSIONS]) {
2309 nla_for_each_nested(tmp, nla[NFTA_RULE_EXPRESSIONS], rem) {
2310 err = -EINVAL;
2311 if (nla_type(tmp) != NFTA_LIST_ELEM)
2312 goto err1;
2313 if (n == NFT_RULE_MAXEXPRS)
2314 goto err1;
0ca743a5 2315 err = nf_tables_expr_parse(&ctx, tmp, &info[n]);
96518518
PM
2316 if (err < 0)
2317 goto err1;
2318 size += info[n].ops->size;
2319 n++;
2320 }
2321 }
9889840f
PM
2322 /* Check for overflow of dlen field */
2323 err = -EFBIG;
2324 if (size >= 1 << 12)
2325 goto err1;
96518518 2326
86f1ec32 2327 if (nla[NFTA_RULE_USERDATA]) {
0768b3b3 2328 ulen = nla_len(nla[NFTA_RULE_USERDATA]);
86f1ec32
PM
2329 if (ulen > 0)
2330 usize = sizeof(struct nft_userdata) + ulen;
2331 }
0768b3b3 2332
96518518 2333 err = -ENOMEM;
86f1ec32 2334 rule = kzalloc(sizeof(*rule) + size + usize, GFP_KERNEL);
96518518
PM
2335 if (rule == NULL)
2336 goto err1;
2337
889f7ee7 2338 nft_activate_next(net, rule);
0628b123 2339
96518518
PM
2340 rule->handle = handle;
2341 rule->dlen = size;
86f1ec32 2342 rule->udata = ulen ? 1 : 0;
0768b3b3 2343
86f1ec32
PM
2344 if (ulen) {
2345 udata = nft_userdata(rule);
2346 udata->len = ulen - 1;
2347 nla_memcpy(udata->data, nla[NFTA_RULE_USERDATA], ulen);
2348 }
96518518 2349
96518518
PM
2350 expr = nft_expr_first(rule);
2351 for (i = 0; i < n; i++) {
2352 err = nf_tables_newexpr(&ctx, &info[i], expr);
2353 if (err < 0)
2354 goto err2;
ef1f7df9 2355 info[i].ops = NULL;
96518518
PM
2356 expr = nft_expr_next(expr);
2357 }
2358
96518518 2359 if (nlh->nlmsg_flags & NLM_F_REPLACE) {
569ccae6 2360 if (!nft_is_active_next(net, old_rule)) {
0628b123
PNA
2361 err = -ENOENT;
2362 goto err2;
2363 }
569ccae6
FW
2364 trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE,
2365 old_rule);
2366 if (trans == NULL) {
2367 err = -ENOMEM;
2368 goto err2;
2369 }
2370 nft_deactivate_next(net, old_rule);
2371 chain->use--;
96518518 2372
569ccae6
FW
2373 if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
2374 err = -ENOMEM;
2375 goto err2;
2376 }
2377
2378 list_add_tail_rcu(&rule->list, &old_rule->list);
2379 } else {
2380 if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
2381 err = -ENOMEM;
2382 goto err2;
2383 }
2384
2385 if (nlh->nlmsg_flags & NLM_F_APPEND) {
2386 if (old_rule)
2387 list_add_rcu(&rule->list, &old_rule->list);
2388 else
2389 list_add_tail_rcu(&rule->list, &chain->rules);
2390 } else {
2391 if (old_rule)
2392 list_add_tail_rcu(&rule->list, &old_rule->list);
2393 else
2394 list_add_rcu(&rule->list, &chain->rules);
2395 }
0628b123 2396 }
4fefee57 2397 chain->use++;
96518518
PM
2398 return 0;
2399
2400err2:
bb7b40ae 2401 nf_tables_rule_release(&ctx, rule);
96518518
PM
2402err1:
2403 for (i = 0; i < n; i++) {
2404 if (info[i].ops != NULL)
ef1f7df9 2405 module_put(info[i].ops->type->owner);
96518518
PM
2406 }
2407 return err;
2408}
2409
1a94e38d
PNA
2410static struct nft_rule *nft_rule_lookup_byid(const struct net *net,
2411 const struct nlattr *nla)
2412{
2413 u32 id = ntohl(nla_get_be32(nla));
2414 struct nft_trans *trans;
2415
2416 list_for_each_entry(trans, &net->nft.commit_list, list) {
2417 struct nft_rule *rule = nft_trans_rule(trans);
2418
2419 if (trans->msg_type == NFT_MSG_NEWRULE &&
2420 id == nft_trans_rule_id(trans))
2421 return rule;
2422 }
2423 return ERR_PTR(-ENOENT);
2424}
2425
633c9a84
PNA
2426static int nf_tables_delrule(struct net *net, struct sock *nlsk,
2427 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
2428 const struct nlattr * const nla[],
2429 struct netlink_ext_ack *extack)
96518518
PM
2430{
2431 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 2432 u8 genmask = nft_genmask_next(net);
7c95f6d8 2433 struct nft_table *table;
cf9dc09d
PNA
2434 struct nft_chain *chain = NULL;
2435 struct nft_rule *rule;
0628b123
PNA
2436 int family = nfmsg->nfgen_family, err = 0;
2437 struct nft_ctx ctx;
96518518 2438
cac20fcd 2439 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask);
36dd1bcc
PNA
2440 if (IS_ERR(table)) {
2441 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_TABLE]);
96518518 2442 return PTR_ERR(table);
36dd1bcc 2443 }
96518518 2444
cf9dc09d 2445 if (nla[NFTA_RULE_CHAIN]) {
cac20fcd 2446 chain = nft_chain_lookup(table, nla[NFTA_RULE_CHAIN], genmask);
36dd1bcc
PNA
2447 if (IS_ERR(chain)) {
2448 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
cf9dc09d 2449 return PTR_ERR(chain);
36dd1bcc 2450 }
cf9dc09d 2451 }
96518518 2452
98319cb9 2453 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
0628b123 2454
cf9dc09d
PNA
2455 if (chain) {
2456 if (nla[NFTA_RULE_HANDLE]) {
cac20fcd 2457 rule = nft_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
36dd1bcc
PNA
2458 if (IS_ERR(rule)) {
2459 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]);
cf9dc09d 2460 return PTR_ERR(rule);
36dd1bcc 2461 }
96518518 2462
1a94e38d
PNA
2463 err = nft_delrule(&ctx, rule);
2464 } else if (nla[NFTA_RULE_ID]) {
2465 rule = nft_rule_lookup_byid(net, nla[NFTA_RULE_ID]);
36dd1bcc
PNA
2466 if (IS_ERR(rule)) {
2467 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_ID]);
1a94e38d 2468 return PTR_ERR(rule);
36dd1bcc 2469 }
1a94e38d 2470
5e266fe7 2471 err = nft_delrule(&ctx, rule);
cf9dc09d 2472 } else {
ce24b721 2473 err = nft_delrule_by_chain(&ctx);
cf9dc09d
PNA
2474 }
2475 } else {
2476 list_for_each_entry(chain, &table->chains, list) {
664b0f8c
PNA
2477 if (!nft_is_active_next(net, chain))
2478 continue;
2479
cf9dc09d 2480 ctx.chain = chain;
ce24b721 2481 err = nft_delrule_by_chain(&ctx);
0628b123
PNA
2482 if (err < 0)
2483 break;
2484 }
2485 }
2486
2487 return err;
2488}
2489
20a69341
PM
2490/*
2491 * Sets
2492 */
2493
2b664957 2494static LIST_HEAD(nf_tables_set_types);
20a69341 2495
2b664957 2496int nft_register_set(struct nft_set_type *type)
20a69341
PM
2497{
2498 nfnl_lock(NFNL_SUBSYS_NFTABLES);
2b664957 2499 list_add_tail_rcu(&type->list, &nf_tables_set_types);
20a69341
PM
2500 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
2501 return 0;
2502}
2503EXPORT_SYMBOL_GPL(nft_register_set);
2504
2b664957 2505void nft_unregister_set(struct nft_set_type *type)
20a69341
PM
2506{
2507 nfnl_lock(NFNL_SUBSYS_NFTABLES);
2b664957 2508 list_del_rcu(&type->list);
20a69341
PM
2509 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
2510}
2511EXPORT_SYMBOL_GPL(nft_unregister_set);
2512
2b664957 2513#define NFT_SET_FEATURES (NFT_SET_INTERVAL | NFT_SET_MAP | \
71cc0873
PS
2514 NFT_SET_TIMEOUT | NFT_SET_OBJECT | \
2515 NFT_SET_EVAL)
2b664957 2516
71cc0873 2517static bool nft_set_ops_candidate(const struct nft_set_type *type, u32 flags)
2b664957 2518{
71cc0873 2519 return (flags & type->features) == (flags & NFT_SET_FEATURES);
2b664957
PNA
2520}
2521
c50b960c
PM
2522/*
2523 * Select a set implementation based on the data characteristics and the
2524 * given policy. The total memory use might not be known if no size is
2525 * given, in that case the amount of memory per element is used.
2526 */
2527static const struct nft_set_ops *
2b664957
PNA
2528nft_select_set_ops(const struct nft_ctx *ctx,
2529 const struct nlattr * const nla[],
c50b960c
PM
2530 const struct nft_set_desc *desc,
2531 enum nft_set_policies policy)
20a69341 2532{
c50b960c
PM
2533 const struct nft_set_ops *ops, *bops;
2534 struct nft_set_estimate est, best;
2b664957
PNA
2535 const struct nft_set_type *type;
2536 u32 flags = 0;
20a69341
PM
2537
2538#ifdef CONFIG_MODULES
2b664957 2539 if (list_empty(&nf_tables_set_types)) {
20a69341
PM
2540 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
2541 request_module("nft-set");
2542 nfnl_lock(NFNL_SUBSYS_NFTABLES);
2b664957 2543 if (!list_empty(&nf_tables_set_types))
20a69341
PM
2544 return ERR_PTR(-EAGAIN);
2545 }
2546#endif
2b664957
PNA
2547 if (nla[NFTA_SET_FLAGS] != NULL)
2548 flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
20a69341 2549
55af753c
PNA
2550 bops = NULL;
2551 best.size = ~0;
2552 best.lookup = ~0;
0b5a7874 2553 best.space = ~0;
c50b960c 2554
2b664957 2555 list_for_each_entry(type, &nf_tables_set_types, list) {
71cc0873 2556 ops = &type->ops;
2b664957 2557
71cc0873 2558 if (!nft_set_ops_candidate(type, flags))
20a69341 2559 continue;
2b664957 2560 if (!ops->estimate(desc, flags, &est))
c50b960c
PM
2561 continue;
2562
2563 switch (policy) {
2564 case NFT_SET_POL_PERFORMANCE:
55af753c 2565 if (est.lookup < best.lookup)
c50b960c 2566 break;
644e334e
PNA
2567 if (est.lookup == best.lookup &&
2568 est.space < best.space)
2569 break;
c50b960c
PM
2570 continue;
2571 case NFT_SET_POL_MEMORY:
0b5a7874
PNA
2572 if (!desc->size) {
2573 if (est.space < best.space)
2574 break;
2575 if (est.space == best.space &&
2576 est.lookup < best.lookup)
2577 break;
4f2921ca 2578 } else if (est.size < best.size || !bops) {
c50b960c 2579 break;
0b5a7874 2580 }
c50b960c
PM
2581 continue;
2582 default:
2583 break;
2584 }
2585
2b664957 2586 if (!try_module_get(type->owner))
20a69341 2587 continue;
c50b960c 2588 if (bops != NULL)
71cc0873 2589 module_put(to_set_type(bops)->owner);
c50b960c
PM
2590
2591 bops = ops;
2592 best = est;
20a69341
PM
2593 }
2594
c50b960c
PM
2595 if (bops != NULL)
2596 return bops;
2597
20a69341
PM
2598 return ERR_PTR(-EOPNOTSUPP);
2599}
2600
2601static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
b2fbd044
LZ
2602 [NFTA_SET_TABLE] = { .type = NLA_STRING,
2603 .len = NFT_TABLE_MAXNAMELEN - 1 },
a9bdd836 2604 [NFTA_SET_NAME] = { .type = NLA_STRING,
cb39ad8b 2605 .len = NFT_SET_MAXNAMELEN - 1 },
20a69341
PM
2606 [NFTA_SET_FLAGS] = { .type = NLA_U32 },
2607 [NFTA_SET_KEY_TYPE] = { .type = NLA_U32 },
2608 [NFTA_SET_KEY_LEN] = { .type = NLA_U32 },
2609 [NFTA_SET_DATA_TYPE] = { .type = NLA_U32 },
2610 [NFTA_SET_DATA_LEN] = { .type = NLA_U32 },
c50b960c
PM
2611 [NFTA_SET_POLICY] = { .type = NLA_U32 },
2612 [NFTA_SET_DESC] = { .type = NLA_NESTED },
958bee14 2613 [NFTA_SET_ID] = { .type = NLA_U32 },
761da293
PM
2614 [NFTA_SET_TIMEOUT] = { .type = NLA_U64 },
2615 [NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 },
e6d8ecac
CFG
2616 [NFTA_SET_USERDATA] = { .type = NLA_BINARY,
2617 .len = NFT_USERDATA_MAXLEN },
8aeff920 2618 [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 },
3ecbfd65 2619 [NFTA_SET_HANDLE] = { .type = NLA_U64 },
c50b960c
PM
2620};
2621
2622static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
2623 [NFTA_SET_DESC_SIZE] = { .type = NLA_U32 },
20a69341
PM
2624};
2625
633c9a84 2626static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,
20a69341
PM
2627 const struct sk_buff *skb,
2628 const struct nlmsghdr *nlh,
f2a6d766 2629 const struct nlattr * const nla[],
36dd1bcc 2630 struct netlink_ext_ack *extack,
f2a6d766 2631 u8 genmask)
20a69341
PM
2632{
2633 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
98319cb9 2634 int family = nfmsg->nfgen_family;
7c95f6d8 2635 struct nft_table *table = NULL;
20a69341 2636
20a69341 2637 if (nla[NFTA_SET_TABLE] != NULL) {
cac20fcd
PNA
2638 table = nft_table_lookup(net, nla[NFTA_SET_TABLE], family,
2639 genmask);
36dd1bcc
PNA
2640 if (IS_ERR(table)) {
2641 NL_SET_BAD_ATTR(extack, nla[NFTA_SET_TABLE]);
20a69341 2642 return PTR_ERR(table);
36dd1bcc 2643 }
20a69341
PM
2644 }
2645
98319cb9 2646 nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla);
20a69341
PM
2647 return 0;
2648}
2649
cac20fcd
PNA
2650static struct nft_set *nft_set_lookup(const struct nft_table *table,
2651 const struct nlattr *nla, u8 genmask)
20a69341
PM
2652{
2653 struct nft_set *set;
2654
2655 if (nla == NULL)
2656 return ERR_PTR(-EINVAL);
2657
2658 list_for_each_entry(set, &table->sets, list) {
37a9cc52
PNA
2659 if (!nla_strcmp(nla, set->name) &&
2660 nft_active_genmask(set, genmask))
20a69341
PM
2661 return set;
2662 }
2663 return ERR_PTR(-ENOENT);
2664}
2665
cac20fcd
PNA
2666static struct nft_set *nft_set_lookup_byhandle(const struct nft_table *table,
2667 const struct nlattr *nla,
2668 u8 genmask)
3ecbfd65
HS
2669{
2670 struct nft_set *set;
2671
3ecbfd65
HS
2672 list_for_each_entry(set, &table->sets, list) {
2673 if (be64_to_cpu(nla_get_be64(nla)) == set->handle &&
2674 nft_active_genmask(set, genmask))
2675 return set;
2676 }
2677 return ERR_PTR(-ENOENT);
2678}
2679
cac20fcd
PNA
2680static struct nft_set *nft_set_lookup_byid(const struct net *net,
2681 const struct nlattr *nla, u8 genmask)
958bee14
PNA
2682{
2683 struct nft_trans *trans;
2684 u32 id = ntohl(nla_get_be32(nla));
2685
2686 list_for_each_entry(trans, &net->nft.commit_list, list) {
37a9cc52
PNA
2687 struct nft_set *set = nft_trans_set(trans);
2688
958bee14 2689 if (trans->msg_type == NFT_MSG_NEWSET &&
37a9cc52
PNA
2690 id == nft_trans_set_id(trans) &&
2691 nft_active_genmask(set, genmask))
2692 return set;
958bee14
PNA
2693 }
2694 return ERR_PTR(-ENOENT);
2695}
c7a72e3f 2696
10659cba
PNA
2697struct nft_set *nft_set_lookup_global(const struct net *net,
2698 const struct nft_table *table,
2699 const struct nlattr *nla_set_name,
2700 const struct nlattr *nla_set_id,
2701 u8 genmask)
c7a72e3f
PNA
2702{
2703 struct nft_set *set;
2704
cac20fcd 2705 set = nft_set_lookup(table, nla_set_name, genmask);
c7a72e3f
PNA
2706 if (IS_ERR(set)) {
2707 if (!nla_set_id)
2708 return set;
2709
cac20fcd 2710 set = nft_set_lookup_byid(net, nla_set_id, genmask);
c7a72e3f
PNA
2711 }
2712 return set;
2713}
10659cba 2714EXPORT_SYMBOL_GPL(nft_set_lookup_global);
958bee14 2715
20a69341
PM
2716static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
2717 const char *name)
2718{
2719 const struct nft_set *i;
2720 const char *p;
2721 unsigned long *inuse;
60eb1894 2722 unsigned int n = 0, min = 0;
20a69341 2723
38745490 2724 p = strchr(name, '%');
20a69341
PM
2725 if (p != NULL) {
2726 if (p[1] != 'd' || strchr(p + 2, '%'))
2727 return -EINVAL;
2728
2729 inuse = (unsigned long *)get_zeroed_page(GFP_KERNEL);
2730 if (inuse == NULL)
2731 return -ENOMEM;
60eb1894 2732cont:
20a69341 2733 list_for_each_entry(i, &ctx->table->sets, list) {
14662917
DB
2734 int tmp;
2735
37a9cc52
PNA
2736 if (!nft_is_active_next(ctx->net, set))
2737 continue;
14662917 2738 if (!sscanf(i->name, name, &tmp))
20a69341 2739 continue;
60eb1894 2740 if (tmp < min || tmp >= min + BITS_PER_BYTE * PAGE_SIZE)
20a69341 2741 continue;
14662917 2742
60eb1894 2743 set_bit(tmp - min, inuse);
20a69341
PM
2744 }
2745
53b70287 2746 n = find_first_zero_bit(inuse, BITS_PER_BYTE * PAGE_SIZE);
60eb1894
PM
2747 if (n >= BITS_PER_BYTE * PAGE_SIZE) {
2748 min += BITS_PER_BYTE * PAGE_SIZE;
2749 memset(inuse, 0, PAGE_SIZE);
2750 goto cont;
2751 }
20a69341
PM
2752 free_page((unsigned long)inuse);
2753 }
2754
38745490
PS
2755 set->name = kasprintf(GFP_KERNEL, name, min + n);
2756 if (!set->name)
2757 return -ENOMEM;
2758
20a69341 2759 list_for_each_entry(i, &ctx->table->sets, list) {
37a9cc52
PNA
2760 if (!nft_is_active_next(ctx->net, i))
2761 continue;
e63aaaa6
AY
2762 if (!strcmp(set->name, i->name)) {
2763 kfree(set->name);
20a69341 2764 return -ENFILE;
e63aaaa6 2765 }
20a69341
PM
2766 }
2767 return 0;
2768}
2769
8e1102d5
FW
2770static int nf_msecs_to_jiffies64(const struct nlattr *nla, u64 *result)
2771{
2772 u64 ms = be64_to_cpu(nla_get_be64(nla));
2773 u64 max = (u64)(~((u64)0));
2774
2775 max = div_u64(max, NSEC_PER_MSEC);
2776 if (ms >= max)
2777 return -ERANGE;
2778
2779 ms *= NSEC_PER_MSEC;
2780 *result = nsecs_to_jiffies64(ms);
2781 return 0;
2782}
2783
2784static u64 nf_jiffies64_to_msecs(u64 input)
2785{
2786 u64 ms = jiffies64_to_nsecs(input);
2787
2788 return cpu_to_be64(div_u64(ms, NSEC_PER_MSEC));
2789}
2790
20a69341
PM
2791static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
2792 const struct nft_set *set, u16 event, u16 flags)
2793{
2794 struct nfgenmsg *nfmsg;
2795 struct nlmsghdr *nlh;
c50b960c 2796 struct nlattr *desc;
128ad332
PNA
2797 u32 portid = ctx->portid;
2798 u32 seq = ctx->seq;
20a69341 2799
dedb67c4 2800 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
20a69341
PM
2801 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),
2802 flags);
2803 if (nlh == NULL)
2804 goto nla_put_failure;
2805
2806 nfmsg = nlmsg_data(nlh);
36596dad 2807 nfmsg->nfgen_family = ctx->family;
20a69341 2808 nfmsg->version = NFNETLINK_V0;
84d7fce6 2809 nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff);
20a69341
PM
2810
2811 if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name))
2812 goto nla_put_failure;
2813 if (nla_put_string(skb, NFTA_SET_NAME, set->name))
2814 goto nla_put_failure;
3ecbfd65
HS
2815 if (nla_put_be64(skb, NFTA_SET_HANDLE, cpu_to_be64(set->handle),
2816 NFTA_SET_PAD))
2817 goto nla_put_failure;
20a69341
PM
2818 if (set->flags != 0)
2819 if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags)))
2820 goto nla_put_failure;
2821
2822 if (nla_put_be32(skb, NFTA_SET_KEY_TYPE, htonl(set->ktype)))
2823 goto nla_put_failure;
2824 if (nla_put_be32(skb, NFTA_SET_KEY_LEN, htonl(set->klen)))
2825 goto nla_put_failure;
2826 if (set->flags & NFT_SET_MAP) {
2827 if (nla_put_be32(skb, NFTA_SET_DATA_TYPE, htonl(set->dtype)))
2828 goto nla_put_failure;
2829 if (nla_put_be32(skb, NFTA_SET_DATA_LEN, htonl(set->dlen)))
2830 goto nla_put_failure;
2831 }
8aeff920
PNA
2832 if (set->flags & NFT_SET_OBJECT &&
2833 nla_put_be32(skb, NFTA_SET_OBJ_TYPE, htonl(set->objtype)))
2834 goto nla_put_failure;
20a69341 2835
761da293 2836 if (set->timeout &&
d3e2a111 2837 nla_put_be64(skb, NFTA_SET_TIMEOUT,
8e1102d5 2838 nf_jiffies64_to_msecs(set->timeout),
b46f6ded 2839 NFTA_SET_PAD))
761da293
PM
2840 goto nla_put_failure;
2841 if (set->gc_int &&
2842 nla_put_be32(skb, NFTA_SET_GC_INTERVAL, htonl(set->gc_int)))
2843 goto nla_put_failure;
2844
9363dc4b
AB
2845 if (set->policy != NFT_SET_POL_PERFORMANCE) {
2846 if (nla_put_be32(skb, NFTA_SET_POLICY, htonl(set->policy)))
2847 goto nla_put_failure;
2848 }
2849
e6d8ecac
CFG
2850 if (nla_put(skb, NFTA_SET_USERDATA, set->udlen, set->udata))
2851 goto nla_put_failure;
2852
c50b960c
PM
2853 desc = nla_nest_start(skb, NFTA_SET_DESC);
2854 if (desc == NULL)
2855 goto nla_put_failure;
2856 if (set->size &&
2857 nla_put_be32(skb, NFTA_SET_DESC_SIZE, htonl(set->size)))
2858 goto nla_put_failure;
2859 nla_nest_end(skb, desc);
2860
053c095a
JB
2861 nlmsg_end(skb, nlh);
2862 return 0;
20a69341
PM
2863
2864nla_put_failure:
2865 nlmsg_trim(skb, nlh);
2866 return -1;
2867}
2868
25e94a99
PNA
2869static void nf_tables_set_notify(const struct nft_ctx *ctx,
2870 const struct nft_set *set, int event,
2871 gfp_t gfp_flags)
20a69341
PM
2872{
2873 struct sk_buff *skb;
128ad332 2874 u32 portid = ctx->portid;
20a69341
PM
2875 int err;
2876
128ad332
PNA
2877 if (!ctx->report &&
2878 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
25e94a99 2879 return;
20a69341 2880
31f8441c 2881 skb = nlmsg_new(NLMSG_GOODSIZE, gfp_flags);
20a69341
PM
2882 if (skb == NULL)
2883 goto err;
2884
2885 err = nf_tables_fill_set(skb, ctx, set, event, 0);
2886 if (err < 0) {
2887 kfree_skb(skb);
2888 goto err;
2889 }
2890
25e94a99
PNA
2891 nfnetlink_send(skb, ctx->net, portid, NFNLGRP_NFTABLES, ctx->report,
2892 gfp_flags);
2893 return;
20a69341 2894err:
25e94a99 2895 nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
20a69341
PM
2896}
2897
5b96af77 2898static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
c9c8e485
PNA
2899{
2900 const struct nft_set *set;
2901 unsigned int idx, s_idx = cb->args[0];
c9c8e485
PNA
2902 struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
2903 struct net *net = sock_net(skb->sk);
5b96af77 2904 struct nft_ctx *ctx = cb->data, ctx_set;
c9c8e485
PNA
2905
2906 if (cb->args[1])
2907 return skb->len;
2908
e688a7f8 2909 rcu_read_lock();
38e029f1
PNA
2910 cb->seq = net->nft.base_seq;
2911
36596dad
PNA
2912 list_for_each_entry_rcu(table, &net->nft.tables, list) {
2913 if (ctx->family != NFPROTO_UNSPEC &&
98319cb9 2914 ctx->family != table->family)
36596dad
PNA
2915 continue;
2916
2917 if (ctx->table && ctx->table != table)
5b96af77
PNA
2918 continue;
2919
36596dad
PNA
2920 if (cur_table) {
2921 if (cur_table != table)
c9c8e485
PNA
2922 continue;
2923
36596dad 2924 cur_table = NULL;
c9c8e485 2925 }
36596dad
PNA
2926 idx = 0;
2927 list_for_each_entry_rcu(set, &table->sets, list) {
2928 if (idx < s_idx)
2929 goto cont;
2930 if (!nft_is_active(net, set))
2931 goto cont;
5b96af77 2932
36596dad
PNA
2933 ctx_set = *ctx;
2934 ctx_set.table = table;
98319cb9 2935 ctx_set.family = table->family;
c9c8e485 2936
36596dad
PNA
2937 if (nf_tables_fill_set(skb, &ctx_set, set,
2938 NFT_MSG_NEWSET,
2939 NLM_F_MULTI) < 0) {
2940 cb->args[0] = idx;
2941 cb->args[2] = (unsigned long) table;
2942 goto done;
c9c8e485 2943 }
36596dad 2944 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
c9c8e485 2945cont:
36596dad 2946 idx++;
c9c8e485 2947 }
36596dad
PNA
2948 if (s_idx)
2949 s_idx = 0;
c9c8e485
PNA
2950 }
2951 cb->args[1] = 1;
2952done:
e688a7f8 2953 rcu_read_unlock();
c9c8e485
PNA
2954 return skb->len;
2955}
2956
5b96af77 2957static int nf_tables_dump_sets_done(struct netlink_callback *cb)
20a69341 2958{
5b96af77
PNA
2959 kfree(cb->data);
2960 return 0;
20a69341
PM
2961}
2962
7b8002a1
PNA
2963static int nf_tables_getset(struct net *net, struct sock *nlsk,
2964 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
2965 const struct nlattr * const nla[],
2966 struct netlink_ext_ack *extack)
20a69341 2967{
f2a6d766 2968 u8 genmask = nft_genmask_cur(net);
20a69341
PM
2969 const struct nft_set *set;
2970 struct nft_ctx ctx;
2971 struct sk_buff *skb2;
c9c8e485 2972 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
20a69341
PM
2973 int err;
2974
01cfa0a4 2975 /* Verify existence before starting dump */
36dd1bcc
PNA
2976 err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, extack,
2977 genmask);
20a69341
PM
2978 if (err < 0)
2979 return err;
2980
2981 if (nlh->nlmsg_flags & NLM_F_DUMP) {
2982 struct netlink_dump_control c = {
2983 .dump = nf_tables_dump_sets,
5b96af77 2984 .done = nf_tables_dump_sets_done,
20a69341 2985 };
5b96af77
PNA
2986 struct nft_ctx *ctx_dump;
2987
2988 ctx_dump = kmalloc(sizeof(*ctx_dump), GFP_KERNEL);
2989 if (ctx_dump == NULL)
2990 return -ENOMEM;
2991
2992 *ctx_dump = ctx;
2993 c.data = ctx_dump;
2994
20a69341
PM
2995 return netlink_dump_start(nlsk, skb, nlh, &c);
2996 }
2997
c9c8e485
PNA
2998 /* Only accept unspec with dump */
2999 if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
3000 return -EAFNOSUPPORT;
eaa2bcd6
PT
3001 if (!nla[NFTA_SET_TABLE])
3002 return -EINVAL;
c9c8e485 3003
cac20fcd 3004 set = nft_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask);
20a69341
PM
3005 if (IS_ERR(set))
3006 return PTR_ERR(set);
3007
3008 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
3009 if (skb2 == NULL)
3010 return -ENOMEM;
3011
3012 err = nf_tables_fill_set(skb2, &ctx, set, NFT_MSG_NEWSET, 0);
3013 if (err < 0)
3014 goto err;
3015
3016 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
3017
3018err:
3019 kfree_skb(skb2);
3020 return err;
3021}
3022
c50b960c
PM
3023static int nf_tables_set_desc_parse(const struct nft_ctx *ctx,
3024 struct nft_set_desc *desc,
3025 const struct nlattr *nla)
3026{
3027 struct nlattr *da[NFTA_SET_DESC_MAX + 1];
3028 int err;
3029
fceb6435
JB
3030 err = nla_parse_nested(da, NFTA_SET_DESC_MAX, nla,
3031 nft_set_desc_policy, NULL);
c50b960c
PM
3032 if (err < 0)
3033 return err;
3034
3035 if (da[NFTA_SET_DESC_SIZE] != NULL)
3036 desc->size = ntohl(nla_get_be32(da[NFTA_SET_DESC_SIZE]));
3037
3038 return 0;
3039}
3040
633c9a84
PNA
3041static int nf_tables_newset(struct net *net, struct sock *nlsk,
3042 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
3043 const struct nlattr * const nla[],
3044 struct netlink_ext_ack *extack)
20a69341
PM
3045{
3046 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 3047 u8 genmask = nft_genmask_next(net);
98319cb9 3048 int family = nfmsg->nfgen_family;
20a69341 3049 const struct nft_set_ops *ops;
20a69341
PM
3050 struct nft_table *table;
3051 struct nft_set *set;
3052 struct nft_ctx ctx;
38745490 3053 char *name;
20a69341
PM
3054 unsigned int size;
3055 bool create;
761da293 3056 u64 timeout;
8aeff920 3057 u32 ktype, dtype, flags, policy, gc_int, objtype;
c50b960c 3058 struct nft_set_desc desc;
e6d8ecac
CFG
3059 unsigned char *udata;
3060 u16 udlen;
20a69341
PM
3061 int err;
3062
3063 if (nla[NFTA_SET_TABLE] == NULL ||
3064 nla[NFTA_SET_NAME] == NULL ||
958bee14
PNA
3065 nla[NFTA_SET_KEY_LEN] == NULL ||
3066 nla[NFTA_SET_ID] == NULL)
20a69341
PM
3067 return -EINVAL;
3068
c50b960c
PM
3069 memset(&desc, 0, sizeof(desc));
3070
20a69341
PM
3071 ktype = NFT_DATA_VALUE;
3072 if (nla[NFTA_SET_KEY_TYPE] != NULL) {
3073 ktype = ntohl(nla_get_be32(nla[NFTA_SET_KEY_TYPE]));
3074 if ((ktype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK)
3075 return -EINVAL;
3076 }
3077
c50b960c 3078 desc.klen = ntohl(nla_get_be32(nla[NFTA_SET_KEY_LEN]));
7d740264 3079 if (desc.klen == 0 || desc.klen > NFT_DATA_VALUE_MAXLEN)
20a69341
PM
3080 return -EINVAL;
3081
3082 flags = 0;
3083 if (nla[NFTA_SET_FLAGS] != NULL) {
3084 flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
3085 if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
7c6c6e95 3086 NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
8aeff920
PNA
3087 NFT_SET_MAP | NFT_SET_EVAL |
3088 NFT_SET_OBJECT))
20a69341 3089 return -EINVAL;
8aeff920
PNA
3090 /* Only one of these operations is supported */
3091 if ((flags & (NFT_SET_MAP | NFT_SET_EVAL | NFT_SET_OBJECT)) ==
3092 (NFT_SET_MAP | NFT_SET_EVAL | NFT_SET_OBJECT))
7c6c6e95 3093 return -EOPNOTSUPP;
20a69341
PM
3094 }
3095
3096 dtype = 0;
20a69341
PM
3097 if (nla[NFTA_SET_DATA_TYPE] != NULL) {
3098 if (!(flags & NFT_SET_MAP))
3099 return -EINVAL;
3100
3101 dtype = ntohl(nla_get_be32(nla[NFTA_SET_DATA_TYPE]));
3102 if ((dtype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK &&
3103 dtype != NFT_DATA_VERDICT)
3104 return -EINVAL;
3105
3106 if (dtype != NFT_DATA_VERDICT) {
3107 if (nla[NFTA_SET_DATA_LEN] == NULL)
3108 return -EINVAL;
c50b960c 3109 desc.dlen = ntohl(nla_get_be32(nla[NFTA_SET_DATA_LEN]));
7d740264 3110 if (desc.dlen == 0 || desc.dlen > NFT_DATA_VALUE_MAXLEN)
20a69341
PM
3111 return -EINVAL;
3112 } else
7d740264 3113 desc.dlen = sizeof(struct nft_verdict);
20a69341
PM
3114 } else if (flags & NFT_SET_MAP)
3115 return -EINVAL;
3116
8aeff920
PNA
3117 if (nla[NFTA_SET_OBJ_TYPE] != NULL) {
3118 if (!(flags & NFT_SET_OBJECT))
3119 return -EINVAL;
3120
3121 objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE]));
3122 if (objtype == NFT_OBJECT_UNSPEC ||
3123 objtype > NFT_OBJECT_MAX)
3124 return -EINVAL;
3125 } else if (flags & NFT_SET_OBJECT)
3126 return -EINVAL;
3127 else
3128 objtype = NFT_OBJECT_UNSPEC;
3129
761da293
PM
3130 timeout = 0;
3131 if (nla[NFTA_SET_TIMEOUT] != NULL) {
3132 if (!(flags & NFT_SET_TIMEOUT))
3133 return -EINVAL;
8e1102d5
FW
3134
3135 err = nf_msecs_to_jiffies64(nla[NFTA_SET_TIMEOUT], &timeout);
3136 if (err)
3137 return err;
761da293
PM
3138 }
3139 gc_int = 0;
3140 if (nla[NFTA_SET_GC_INTERVAL] != NULL) {
3141 if (!(flags & NFT_SET_TIMEOUT))
3142 return -EINVAL;
3143 gc_int = ntohl(nla_get_be32(nla[NFTA_SET_GC_INTERVAL]));
3144 }
3145
c50b960c
PM
3146 policy = NFT_SET_POL_PERFORMANCE;
3147 if (nla[NFTA_SET_POLICY] != NULL)
3148 policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY]));
3149
3150 if (nla[NFTA_SET_DESC] != NULL) {
3151 err = nf_tables_set_desc_parse(&ctx, &desc, nla[NFTA_SET_DESC]);
3152 if (err < 0)
3153 return err;
3154 }
3155
20a69341
PM
3156 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
3157
cac20fcd 3158 table = nft_table_lookup(net, nla[NFTA_SET_TABLE], family, genmask);
36dd1bcc
PNA
3159 if (IS_ERR(table)) {
3160 NL_SET_BAD_ATTR(extack, nla[NFTA_SET_TABLE]);
20a69341 3161 return PTR_ERR(table);
36dd1bcc 3162 }
20a69341 3163
98319cb9 3164 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
20a69341 3165
cac20fcd 3166 set = nft_set_lookup(table, nla[NFTA_SET_NAME], genmask);
20a69341 3167 if (IS_ERR(set)) {
36dd1bcc
PNA
3168 if (PTR_ERR(set) != -ENOENT) {
3169 NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]);
20a69341 3170 return PTR_ERR(set);
36dd1bcc 3171 }
1a28ad74 3172 } else {
36dd1bcc
PNA
3173 if (nlh->nlmsg_flags & NLM_F_EXCL) {
3174 NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]);
20a69341 3175 return -EEXIST;
36dd1bcc 3176 }
20a69341
PM
3177 if (nlh->nlmsg_flags & NLM_F_REPLACE)
3178 return -EOPNOTSUPP;
36dd1bcc 3179
20a69341
PM
3180 return 0;
3181 }
3182
3183 if (!(nlh->nlmsg_flags & NLM_F_CREATE))
3184 return -ENOENT;
3185
2b664957 3186 ops = nft_select_set_ops(&ctx, nla, &desc, policy);
20a69341
PM
3187 if (IS_ERR(ops))
3188 return PTR_ERR(ops);
3189
e6d8ecac
CFG
3190 udlen = 0;
3191 if (nla[NFTA_SET_USERDATA])
3192 udlen = nla_len(nla[NFTA_SET_USERDATA]);
3193
20a69341
PM
3194 size = 0;
3195 if (ops->privsize != NULL)
347b408d 3196 size = ops->privsize(nla, &desc);
20a69341 3197
1ff75a3e
PNA
3198 set = kvzalloc(sizeof(*set) + size + udlen, GFP_KERNEL);
3199 if (!set) {
3200 err = -ENOMEM;
20a69341 3201 goto err1;
1ff75a3e 3202 }
20a69341 3203
38745490
PS
3204 name = nla_strdup(nla[NFTA_SET_NAME], GFP_KERNEL);
3205 if (!name) {
3206 err = -ENOMEM;
3207 goto err2;
3208 }
3209
20a69341 3210 err = nf_tables_set_alloc_name(&ctx, set, name);
38745490 3211 kfree(name);
20a69341
PM
3212 if (err < 0)
3213 goto err2;
3214
e6d8ecac
CFG
3215 udata = NULL;
3216 if (udlen) {
3217 udata = set->data + size;
3218 nla_memcpy(udata, nla[NFTA_SET_USERDATA], udlen);
3219 }
3220
20a69341
PM
3221 INIT_LIST_HEAD(&set->bindings);
3222 set->ops = ops;
3223 set->ktype = ktype;
c50b960c 3224 set->klen = desc.klen;
20a69341 3225 set->dtype = dtype;
8aeff920 3226 set->objtype = objtype;
c50b960c 3227 set->dlen = desc.dlen;
20a69341 3228 set->flags = flags;
c50b960c 3229 set->size = desc.size;
9363dc4b 3230 set->policy = policy;
e6d8ecac
CFG
3231 set->udlen = udlen;
3232 set->udata = udata;
761da293
PM
3233 set->timeout = timeout;
3234 set->gc_int = gc_int;
3ecbfd65 3235 set->handle = nf_tables_alloc_handle(table);
20a69341 3236
c50b960c 3237 err = ops->init(set, &desc, nla);
20a69341 3238 if (err < 0)
2f6adf48 3239 goto err3;
20a69341 3240
958bee14 3241 err = nft_trans_set_add(&ctx, NFT_MSG_NEWSET, set);
20a69341 3242 if (err < 0)
2f6adf48 3243 goto err4;
20a69341 3244
e688a7f8 3245 list_add_tail_rcu(&set->list, &table->sets);
4fefee57 3246 table->use++;
20a69341
PM
3247 return 0;
3248
2f6adf48 3249err4:
c17c3cdf 3250 ops->destroy(set);
2f6adf48
FW
3251err3:
3252 kfree(set->name);
20a69341 3253err2:
1ff75a3e 3254 kvfree(set);
20a69341 3255err1:
71cc0873 3256 module_put(to_set_type(ops)->owner);
20a69341
PM
3257 return err;
3258}
3259
958bee14 3260static void nft_set_destroy(struct nft_set *set)
20a69341 3261{
20a69341 3262 set->ops->destroy(set);
71cc0873 3263 module_put(to_set_type(set->ops)->owner);
38745490 3264 kfree(set->name);
1ff75a3e 3265 kvfree(set);
20a69341
PM
3266}
3267
958bee14
PNA
3268static void nf_tables_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
3269{
e688a7f8 3270 list_del_rcu(&set->list);
31f8441c 3271 nf_tables_set_notify(ctx, set, NFT_MSG_DELSET, GFP_ATOMIC);
958bee14
PNA
3272 nft_set_destroy(set);
3273}
3274
633c9a84
PNA
3275static int nf_tables_delset(struct net *net, struct sock *nlsk,
3276 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
3277 const struct nlattr * const nla[],
3278 struct netlink_ext_ack *extack)
20a69341 3279{
c9c8e485 3280 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 3281 u8 genmask = nft_genmask_next(net);
36dd1bcc 3282 const struct nlattr *attr;
20a69341
PM
3283 struct nft_set *set;
3284 struct nft_ctx ctx;
3285 int err;
3286
ec2c9935
PM
3287 if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
3288 return -EAFNOSUPPORT;
20a69341
PM
3289 if (nla[NFTA_SET_TABLE] == NULL)
3290 return -EINVAL;
3291
36dd1bcc
PNA
3292 err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, extack,
3293 genmask);
20a69341
PM
3294 if (err < 0)
3295 return err;
3296
36dd1bcc
PNA
3297 if (nla[NFTA_SET_HANDLE]) {
3298 attr = nla[NFTA_SET_HANDLE];
3299 set = nft_set_lookup_byhandle(ctx.table, attr, genmask);
3300 } else {
3301 attr = nla[NFTA_SET_NAME];
3302 set = nft_set_lookup(ctx.table, attr, genmask);
3303 }
a8278400 3304
36dd1bcc
PNA
3305 if (IS_ERR(set)) {
3306 NL_SET_BAD_ATTR(extack, attr);
3307 return PTR_ERR(set);
3308 }
a8278400 3309 if (!list_empty(&set->bindings) ||
36dd1bcc
PNA
3310 (nlh->nlmsg_flags & NLM_F_NONREC && atomic_read(&set->nelems) > 0)) {
3311 NL_SET_BAD_ATTR(extack, attr);
20a69341 3312 return -EBUSY;
36dd1bcc 3313 }
20a69341 3314
ee01d542 3315 return nft_delset(&ctx, set);
20a69341
PM
3316}
3317
3318static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
de70185d 3319 struct nft_set *set,
20a69341 3320 const struct nft_set_iter *iter,
de70185d 3321 struct nft_set_elem *elem)
20a69341 3322{
fe2811eb 3323 const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
20a69341
PM
3324 enum nft_registers dreg;
3325
3326 dreg = nft_type_to_reg(set->dtype);
1ec10212
PM
3327 return nft_validate_register_store(ctx, dreg, nft_set_ext_data(ext),
3328 set->dtype == NFT_DATA_VERDICT ?
3329 NFT_DATA_VERDICT : NFT_DATA_VALUE,
3330 set->dlen);
20a69341
PM
3331}
3332
3333int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
3334 struct nft_set_binding *binding)
3335{
3336 struct nft_set_binding *i;
3337 struct nft_set_iter iter;
3338
408070d6 3339 if (!list_empty(&set->bindings) && nft_set_is_anonymous(set))
20a69341
PM
3340 return -EBUSY;
3341
11113e19 3342 if (binding->flags & NFT_SET_MAP) {
20a69341
PM
3343 /* If the set is already bound to the same chain all
3344 * jumps are already validated for that chain.
3345 */
3346 list_for_each_entry(i, &set->bindings, list) {
a4684402 3347 if (i->flags & NFT_SET_MAP &&
11113e19 3348 i->chain == binding->chain)
20a69341
PM
3349 goto bind;
3350 }
3351
8588ac09 3352 iter.genmask = nft_genmask_next(ctx->net);
20a69341
PM
3353 iter.skip = 0;
3354 iter.count = 0;
3355 iter.err = 0;
3356 iter.fn = nf_tables_bind_check_setelem;
3357
3358 set->ops->walk(ctx, set, &iter);
a02f4248 3359 if (iter.err < 0)
20a69341 3360 return iter.err;
20a69341
PM
3361 }
3362bind:
3363 binding->chain = ctx->chain;
e688a7f8 3364 list_add_tail_rcu(&binding->list, &set->bindings);
20a69341
PM
3365 return 0;
3366}
63aea290 3367EXPORT_SYMBOL_GPL(nf_tables_bind_set);
20a69341
PM
3368
3369void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
3370 struct nft_set_binding *binding)
3371{
e688a7f8 3372 list_del_rcu(&binding->list);
20a69341 3373
408070d6 3374 if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
37a9cc52 3375 nft_is_active(ctx->net, set))
20a69341
PM
3376 nf_tables_set_destroy(ctx, set);
3377}
63aea290 3378EXPORT_SYMBOL_GPL(nf_tables_unbind_set);
20a69341 3379
3ac4c07a
PM
3380const struct nft_set_ext_type nft_set_ext_types[] = {
3381 [NFT_SET_EXT_KEY] = {
7d740264 3382 .align = __alignof__(u32),
3ac4c07a
PM
3383 },
3384 [NFT_SET_EXT_DATA] = {
7d740264 3385 .align = __alignof__(u32),
3ac4c07a 3386 },
f25ad2e9
PM
3387 [NFT_SET_EXT_EXPR] = {
3388 .align = __alignof__(struct nft_expr),
3389 },
8aeff920
PNA
3390 [NFT_SET_EXT_OBJREF] = {
3391 .len = sizeof(struct nft_object *),
3392 .align = __alignof__(struct nft_object *),
3393 },
3ac4c07a
PM
3394 [NFT_SET_EXT_FLAGS] = {
3395 .len = sizeof(u8),
3396 .align = __alignof__(u8),
3397 },
c3e1b005
PM
3398 [NFT_SET_EXT_TIMEOUT] = {
3399 .len = sizeof(u64),
3400 .align = __alignof__(u64),
3401 },
3402 [NFT_SET_EXT_EXPIRATION] = {
8e1102d5
FW
3403 .len = sizeof(u64),
3404 .align = __alignof__(u64),
c3e1b005 3405 },
68e942e8
PM
3406 [NFT_SET_EXT_USERDATA] = {
3407 .len = sizeof(struct nft_userdata),
3408 .align = __alignof__(struct nft_userdata),
3409 },
3ac4c07a
PM
3410};
3411EXPORT_SYMBOL_GPL(nft_set_ext_types);
3412
20a69341
PM
3413/*
3414 * Set elements
3415 */
3416
3417static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
3418 [NFTA_SET_ELEM_KEY] = { .type = NLA_NESTED },
3419 [NFTA_SET_ELEM_DATA] = { .type = NLA_NESTED },
3420 [NFTA_SET_ELEM_FLAGS] = { .type = NLA_U32 },
c3e1b005 3421 [NFTA_SET_ELEM_TIMEOUT] = { .type = NLA_U64 },
68e942e8
PM
3422 [NFTA_SET_ELEM_USERDATA] = { .type = NLA_BINARY,
3423 .len = NFT_USERDATA_MAXLEN },
467697d2
FW
3424 [NFTA_SET_ELEM_EXPR] = { .type = NLA_NESTED },
3425 [NFTA_SET_ELEM_OBJREF] = { .type = NLA_STRING },
20a69341
PM
3426};
3427
3428static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = {
b2fbd044
LZ
3429 [NFTA_SET_ELEM_LIST_TABLE] = { .type = NLA_STRING,
3430 .len = NFT_TABLE_MAXNAMELEN - 1 },
3431 [NFTA_SET_ELEM_LIST_SET] = { .type = NLA_STRING,
3432 .len = NFT_SET_MAXNAMELEN - 1 },
20a69341 3433 [NFTA_SET_ELEM_LIST_ELEMENTS] = { .type = NLA_NESTED },
958bee14 3434 [NFTA_SET_ELEM_LIST_SET_ID] = { .type = NLA_U32 },
20a69341
PM
3435};
3436
633c9a84 3437static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
20a69341
PM
3438 const struct sk_buff *skb,
3439 const struct nlmsghdr *nlh,
f2a6d766 3440 const struct nlattr * const nla[],
36dd1bcc 3441 struct netlink_ext_ack *extack,
f2a6d766 3442 u8 genmask)
20a69341
PM
3443{
3444 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
98319cb9 3445 int family = nfmsg->nfgen_family;
7c95f6d8 3446 struct nft_table *table;
20a69341 3447
cac20fcd
PNA
3448 table = nft_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], family,
3449 genmask);
36dd1bcc
PNA
3450 if (IS_ERR(table)) {
3451 NL_SET_BAD_ATTR(extack, nla[NFTA_SET_ELEM_LIST_TABLE]);
20a69341 3452 return PTR_ERR(table);
36dd1bcc 3453 }
20a69341 3454
98319cb9 3455 nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla);
20a69341
PM
3456 return 0;
3457}
3458
3459static int nf_tables_fill_setelem(struct sk_buff *skb,
3460 const struct nft_set *set,
3461 const struct nft_set_elem *elem)
3462{
fe2811eb 3463 const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
20a69341
PM
3464 unsigned char *b = skb_tail_pointer(skb);
3465 struct nlattr *nest;
3466
3467 nest = nla_nest_start(skb, NFTA_LIST_ELEM);
3468 if (nest == NULL)
3469 goto nla_put_failure;
3470
fe2811eb
PM
3471 if (nft_data_dump(skb, NFTA_SET_ELEM_KEY, nft_set_ext_key(ext),
3472 NFT_DATA_VALUE, set->klen) < 0)
20a69341
PM
3473 goto nla_put_failure;
3474
fe2811eb
PM
3475 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
3476 nft_data_dump(skb, NFTA_SET_ELEM_DATA, nft_set_ext_data(ext),
20a69341
PM
3477 set->dtype == NFT_DATA_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE,
3478 set->dlen) < 0)
3479 goto nla_put_failure;
3480
f25ad2e9
PM
3481 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR) &&
3482 nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, nft_set_ext_expr(ext)) < 0)
3483 goto nla_put_failure;
3484
8aeff920
PNA
3485 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) &&
3486 nla_put_string(skb, NFTA_SET_ELEM_OBJREF,
3487 (*nft_set_ext_obj(ext))->name) < 0)
3488 goto nla_put_failure;
3489
fe2811eb
PM
3490 if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
3491 nla_put_be32(skb, NFTA_SET_ELEM_FLAGS,
3492 htonl(*nft_set_ext_flags(ext))))
3493 goto nla_put_failure;
20a69341 3494
c3e1b005
PM
3495 if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) &&
3496 nla_put_be64(skb, NFTA_SET_ELEM_TIMEOUT,
8e1102d5 3497 nf_jiffies64_to_msecs(*nft_set_ext_timeout(ext)),
b46f6ded 3498 NFTA_SET_ELEM_PAD))
c3e1b005
PM
3499 goto nla_put_failure;
3500
3501 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) {
8e1102d5 3502 u64 expires, now = get_jiffies_64();
c3e1b005
PM
3503
3504 expires = *nft_set_ext_expiration(ext);
8e1102d5 3505 if (time_before64(now, expires))
c3e1b005
PM
3506 expires -= now;
3507 else
3508 expires = 0;
3509
3510 if (nla_put_be64(skb, NFTA_SET_ELEM_EXPIRATION,
8e1102d5 3511 nf_jiffies64_to_msecs(expires),
b46f6ded 3512 NFTA_SET_ELEM_PAD))
c3e1b005
PM
3513 goto nla_put_failure;
3514 }
3515
68e942e8
PM
3516 if (nft_set_ext_exists(ext, NFT_SET_EXT_USERDATA)) {
3517 struct nft_userdata *udata;
3518
3519 udata = nft_set_ext_userdata(ext);
3520 if (nla_put(skb, NFTA_SET_ELEM_USERDATA,
3521 udata->len + 1, udata->data))
3522 goto nla_put_failure;
3523 }
3524
20a69341
PM
3525 nla_nest_end(skb, nest);
3526 return 0;
3527
3528nla_put_failure:
3529 nlmsg_trim(skb, b);
3530 return -EMSGSIZE;
3531}
3532
3533struct nft_set_dump_args {
3534 const struct netlink_callback *cb;
3535 struct nft_set_iter iter;
3536 struct sk_buff *skb;
3537};
3538
3539static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
de70185d 3540 struct nft_set *set,
20a69341 3541 const struct nft_set_iter *iter,
de70185d 3542 struct nft_set_elem *elem)
20a69341
PM
3543{
3544 struct nft_set_dump_args *args;
3545
3546 args = container_of(iter, struct nft_set_dump_args, iter);
3547 return nf_tables_fill_setelem(args->skb, set, elem);
3548}
3549
fa803605
LZ
3550struct nft_set_dump_ctx {
3551 const struct nft_set *set;
3552 struct nft_ctx ctx;
3553};
3554
20a69341
PM
3555static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
3556{
fa803605 3557 struct nft_set_dump_ctx *dump_ctx = cb->data;
633c9a84 3558 struct net *net = sock_net(skb->sk);
fa803605 3559 struct nft_table *table;
de70185d 3560 struct nft_set *set;
20a69341 3561 struct nft_set_dump_args args;
fa803605 3562 bool set_found = false;
20a69341
PM
3563 struct nfgenmsg *nfmsg;
3564 struct nlmsghdr *nlh;
3565 struct nlattr *nest;
3566 u32 portid, seq;
fa803605 3567 int event;
20a69341 3568
fa803605 3569 rcu_read_lock();
36596dad
PNA
3570 list_for_each_entry_rcu(table, &net->nft.tables, list) {
3571 if (dump_ctx->ctx.family != NFPROTO_UNSPEC &&
98319cb9 3572 dump_ctx->ctx.family != table->family)
fa803605 3573 continue;
20a69341 3574
36596dad
PNA
3575 if (table != dump_ctx->ctx.table)
3576 continue;
20a69341 3577
36596dad
PNA
3578 list_for_each_entry_rcu(set, &table->sets, list) {
3579 if (set == dump_ctx->set) {
3580 set_found = true;
3581 break;
fa803605 3582 }
fa803605
LZ
3583 }
3584 break;
3585 }
3586
3587 if (!set_found) {
3588 rcu_read_unlock();
3589 return -ENOENT;
3590 }
20a69341 3591
dedb67c4 3592 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, NFT_MSG_NEWSETELEM);
20a69341
PM
3593 portid = NETLINK_CB(cb->skb).portid;
3594 seq = cb->nlh->nlmsg_seq;
3595
3596 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),
3597 NLM_F_MULTI);
3598 if (nlh == NULL)
3599 goto nla_put_failure;
3600
3601 nfmsg = nlmsg_data(nlh);
98319cb9 3602 nfmsg->nfgen_family = table->family;
20a69341 3603 nfmsg->version = NFNETLINK_V0;
fa803605 3604 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
20a69341 3605
fa803605 3606 if (nla_put_string(skb, NFTA_SET_ELEM_LIST_TABLE, table->name))
20a69341
PM
3607 goto nla_put_failure;
3608 if (nla_put_string(skb, NFTA_SET_ELEM_LIST_SET, set->name))
3609 goto nla_put_failure;
3610
3611 nest = nla_nest_start(skb, NFTA_SET_ELEM_LIST_ELEMENTS);
3612 if (nest == NULL)
3613 goto nla_put_failure;
3614
8588ac09
PNA
3615 args.cb = cb;
3616 args.skb = skb;
fa803605 3617 args.iter.genmask = nft_genmask_cur(net);
8588ac09
PNA
3618 args.iter.skip = cb->args[0];
3619 args.iter.count = 0;
3620 args.iter.err = 0;
3621 args.iter.fn = nf_tables_dump_setelem;
fa803605
LZ
3622 set->ops->walk(&dump_ctx->ctx, set, &args.iter);
3623 rcu_read_unlock();
20a69341
PM
3624
3625 nla_nest_end(skb, nest);
3626 nlmsg_end(skb, nlh);
3627
3628 if (args.iter.err && args.iter.err != -EMSGSIZE)
3629 return args.iter.err;
3630 if (args.iter.count == cb->args[0])
3631 return 0;
3632
3633 cb->args[0] = args.iter.count;
3634 return skb->len;
3635
3636nla_put_failure:
fa803605 3637 rcu_read_unlock();
20a69341
PM
3638 return -ENOSPC;
3639}
3640
fa803605
LZ
3641static int nf_tables_dump_set_done(struct netlink_callback *cb)
3642{
3643 kfree(cb->data);
3644 return 0;
3645}
3646
d60ce62f
AB
3647static int nf_tables_fill_setelem_info(struct sk_buff *skb,
3648 const struct nft_ctx *ctx, u32 seq,
3649 u32 portid, int event, u16 flags,
3650 const struct nft_set *set,
3651 const struct nft_set_elem *elem)
3652{
3653 struct nfgenmsg *nfmsg;
3654 struct nlmsghdr *nlh;
3655 struct nlattr *nest;
3656 int err;
3657
dedb67c4 3658 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
d60ce62f
AB
3659 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),
3660 flags);
3661 if (nlh == NULL)
3662 goto nla_put_failure;
3663
3664 nfmsg = nlmsg_data(nlh);
36596dad 3665 nfmsg->nfgen_family = ctx->family;
d60ce62f 3666 nfmsg->version = NFNETLINK_V0;
84d7fce6 3667 nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff);
d60ce62f
AB
3668
3669 if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name))
3670 goto nla_put_failure;
3671 if (nla_put_string(skb, NFTA_SET_NAME, set->name))
3672 goto nla_put_failure;
3673
3674 nest = nla_nest_start(skb, NFTA_SET_ELEM_LIST_ELEMENTS);
3675 if (nest == NULL)
3676 goto nla_put_failure;
3677
3678 err = nf_tables_fill_setelem(skb, set, elem);
3679 if (err < 0)
3680 goto nla_put_failure;
3681
3682 nla_nest_end(skb, nest);
3683
053c095a
JB
3684 nlmsg_end(skb, nlh);
3685 return 0;
d60ce62f
AB
3686
3687nla_put_failure:
3688 nlmsg_trim(skb, nlh);
3689 return -1;
3690}
3691
ba0e4d99
PNA
3692static int nft_setelem_parse_flags(const struct nft_set *set,
3693 const struct nlattr *attr, u32 *flags)
3694{
3695 if (attr == NULL)
3696 return 0;
3697
3698 *flags = ntohl(nla_get_be32(attr));
3699 if (*flags & ~NFT_SET_ELEM_INTERVAL_END)
3700 return -EINVAL;
3701 if (!(set->flags & NFT_SET_INTERVAL) &&
3702 *flags & NFT_SET_ELEM_INTERVAL_END)
3703 return -EINVAL;
3704
3705 return 0;
3706}
3707
3708static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3709 const struct nlattr *attr)
3710{
3711 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
3712 const struct nft_set_ext *ext;
3713 struct nft_data_desc desc;
3714 struct nft_set_elem elem;
3715 struct sk_buff *skb;
3716 uint32_t flags = 0;
3717 void *priv;
3718 int err;
3719
3720 err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr,
3721 nft_set_elem_policy, NULL);
3722 if (err < 0)
3723 return err;
3724
3725 if (!nla[NFTA_SET_ELEM_KEY])
3726 return -EINVAL;
3727
3728 err = nft_setelem_parse_flags(set, nla[NFTA_SET_ELEM_FLAGS], &flags);
3729 if (err < 0)
3730 return err;
3731
3732 err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &desc,
3733 nla[NFTA_SET_ELEM_KEY]);
3734 if (err < 0)
3735 return err;
3736
3737 err = -EINVAL;
3738 if (desc.type != NFT_DATA_VALUE || desc.len != set->klen)
3739 return err;
3740
3741 priv = set->ops->get(ctx->net, set, &elem, flags);
3742 if (IS_ERR(priv))
3743 return PTR_ERR(priv);
3744
3745 elem.priv = priv;
3746 ext = nft_set_elem_ext(set, &elem);
3747
3748 err = -ENOMEM;
3749 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
3750 if (skb == NULL)
3751 goto err1;
3752
3753 err = nf_tables_fill_setelem_info(skb, ctx, ctx->seq, ctx->portid,
3754 NFT_MSG_NEWSETELEM, 0, set, &elem);
3755 if (err < 0)
3756 goto err2;
3757
3758 err = nfnetlink_unicast(skb, ctx->net, ctx->portid, MSG_DONTWAIT);
3759 /* This avoids a loop in nfnetlink. */
3760 if (err < 0)
3761 goto err1;
3762
3763 return 0;
3764err2:
3765 kfree_skb(skb);
3766err1:
3767 /* this avoids a loop in nfnetlink. */
3768 return err == -EAGAIN ? -ENOBUFS : err;
3769}
3770
3771static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
3772 struct sk_buff *skb, const struct nlmsghdr *nlh,
3773 const struct nlattr * const nla[],
3774 struct netlink_ext_ack *extack)
3775{
3776 u8 genmask = nft_genmask_cur(net);
3777 struct nft_set *set;
3778 struct nlattr *attr;
3779 struct nft_ctx ctx;
3780 int rem, err = 0;
3781
36dd1bcc
PNA
3782 err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, extack,
3783 genmask);
ba0e4d99
PNA
3784 if (err < 0)
3785 return err;
3786
cac20fcd 3787 set = nft_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
ba0e4d99
PNA
3788 if (IS_ERR(set))
3789 return PTR_ERR(set);
3790
3791 if (nlh->nlmsg_flags & NLM_F_DUMP) {
3792 struct netlink_dump_control c = {
3793 .dump = nf_tables_dump_set,
3794 .done = nf_tables_dump_set_done,
3795 };
3796 struct nft_set_dump_ctx *dump_ctx;
3797
3798 dump_ctx = kmalloc(sizeof(*dump_ctx), GFP_KERNEL);
3799 if (!dump_ctx)
3800 return -ENOMEM;
3801
3802 dump_ctx->set = set;
3803 dump_ctx->ctx = ctx;
3804
3805 c.data = dump_ctx;
3806 return netlink_dump_start(nlsk, skb, nlh, &c);
3807 }
3808
3809 if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
3810 return -EINVAL;
3811
3812 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
3813 err = nft_get_set_elem(&ctx, set, attr);
3814 if (err < 0)
3815 break;
3816 }
3817
3818 return err;
3819}
3820
25e94a99
PNA
3821static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
3822 const struct nft_set *set,
3823 const struct nft_set_elem *elem,
3824 int event, u16 flags)
d60ce62f 3825{
128ad332
PNA
3826 struct net *net = ctx->net;
3827 u32 portid = ctx->portid;
d60ce62f
AB
3828 struct sk_buff *skb;
3829 int err;
3830
128ad332 3831 if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
25e94a99 3832 return;
d60ce62f 3833
d60ce62f
AB
3834 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
3835 if (skb == NULL)
3836 goto err;
3837
3838 err = nf_tables_fill_setelem_info(skb, ctx, 0, portid, event, flags,
3839 set, elem);
3840 if (err < 0) {
3841 kfree_skb(skb);
3842 goto err;
3843 }
3844
25e94a99
PNA
3845 nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, ctx->report,
3846 GFP_KERNEL);
3847 return;
d60ce62f 3848err:
25e94a99 3849 nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
d60ce62f
AB
3850}
3851
60319eb1
PNA
3852static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx,
3853 int msg_type,
3854 struct nft_set *set)
3855{
3856 struct nft_trans *trans;
3857
3858 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_elem));
3859 if (trans == NULL)
3860 return NULL;
3861
3862 nft_trans_elem_set(trans) = set;
3863 return trans;
3864}
3865
22fe54d5
PM
3866void *nft_set_elem_init(const struct nft_set *set,
3867 const struct nft_set_ext_tmpl *tmpl,
49499c3e 3868 const u32 *key, const u32 *data,
22fe54d5 3869 u64 timeout, gfp_t gfp)
fe2811eb
PM
3870{
3871 struct nft_set_ext *ext;
3872 void *elem;
3873
3874 elem = kzalloc(set->ops->elemsize + tmpl->len, gfp);
3875 if (elem == NULL)
3876 return NULL;
3877
3878 ext = nft_set_elem_ext(set, elem);
3879 nft_set_ext_init(ext, tmpl);
3880
3881 memcpy(nft_set_ext_key(ext), key, set->klen);
3882 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
3883 memcpy(nft_set_ext_data(ext), data, set->dlen);
c3e1b005
PM
3884 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION))
3885 *nft_set_ext_expiration(ext) =
8e1102d5 3886 get_jiffies_64() + timeout;
c3e1b005
PM
3887 if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT))
3888 *nft_set_ext_timeout(ext) = timeout;
fe2811eb
PM
3889
3890 return elem;
3891}
3892
61f9e292
LZ
3893void nft_set_elem_destroy(const struct nft_set *set, void *elem,
3894 bool destroy_expr)
61edafbb
PM
3895{
3896 struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
3897
59105446 3898 nft_data_release(nft_set_ext_key(ext), NFT_DATA_VALUE);
61edafbb 3899 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
59105446 3900 nft_data_release(nft_set_ext_data(ext), set->dtype);
61f9e292 3901 if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
f25ad2e9 3902 nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext));
8aeff920
PNA
3903 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
3904 (*nft_set_ext_obj(ext))->use--;
61edafbb
PM
3905 kfree(elem);
3906}
3907EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
3908
59105446
PNA
3909/* Only called from commit path, nft_set_elem_deactivate() already deals with
3910 * the refcounting from the preparation phase.
3911 */
3912static void nf_tables_set_elem_destroy(const struct nft_set *set, void *elem)
3913{
3914 struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
3915
3916 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
3917 nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext));
3918 kfree(elem);
3919}
3920
60319eb1 3921static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
c016c7e4 3922 const struct nlattr *attr, u32 nlmsg_flags)
20a69341
PM
3923{
3924 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
8aeff920 3925 u8 genmask = nft_genmask_next(ctx->net);
20a69341 3926 struct nft_data_desc d1, d2;
fe2811eb 3927 struct nft_set_ext_tmpl tmpl;
c016c7e4 3928 struct nft_set_ext *ext, *ext2;
20a69341
PM
3929 struct nft_set_elem elem;
3930 struct nft_set_binding *binding;
8aeff920 3931 struct nft_object *obj = NULL;
68e942e8 3932 struct nft_userdata *udata;
fe2811eb 3933 struct nft_data data;
20a69341 3934 enum nft_registers dreg;
60319eb1 3935 struct nft_trans *trans;
0e9091d6 3936 u32 flags = 0;
c3e1b005 3937 u64 timeout;
68e942e8 3938 u8 ulen;
20a69341
PM
3939 int err;
3940
3941 err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr,
fceb6435 3942 nft_set_elem_policy, NULL);
20a69341
PM
3943 if (err < 0)
3944 return err;
3945
3946 if (nla[NFTA_SET_ELEM_KEY] == NULL)
3947 return -EINVAL;
3948
fe2811eb
PM
3949 nft_set_ext_prepare(&tmpl);
3950
0e9091d6
PNA
3951 err = nft_setelem_parse_flags(set, nla[NFTA_SET_ELEM_FLAGS], &flags);
3952 if (err < 0)
3953 return err;
3954 if (flags != 0)
3955 nft_set_ext_add(&tmpl, NFT_SET_EXT_FLAGS);
20a69341
PM
3956
3957 if (set->flags & NFT_SET_MAP) {
3958 if (nla[NFTA_SET_ELEM_DATA] == NULL &&
fe2811eb 3959 !(flags & NFT_SET_ELEM_INTERVAL_END))
20a69341 3960 return -EINVAL;
bd7fc645 3961 if (nla[NFTA_SET_ELEM_DATA] != NULL &&
fe2811eb 3962 flags & NFT_SET_ELEM_INTERVAL_END)
bd7fc645 3963 return -EINVAL;
20a69341
PM
3964 } else {
3965 if (nla[NFTA_SET_ELEM_DATA] != NULL)
3966 return -EINVAL;
3967 }
3968
c3e1b005
PM
3969 timeout = 0;
3970 if (nla[NFTA_SET_ELEM_TIMEOUT] != NULL) {
3971 if (!(set->flags & NFT_SET_TIMEOUT))
3972 return -EINVAL;
8e1102d5
FW
3973 err = nf_msecs_to_jiffies64(nla[NFTA_SET_ELEM_TIMEOUT],
3974 &timeout);
3975 if (err)
3976 return err;
c3e1b005
PM
3977 } else if (set->flags & NFT_SET_TIMEOUT) {
3978 timeout = set->timeout;
3979 }
3980
7d740264 3981 err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &d1,
d0a11fc3 3982 nla[NFTA_SET_ELEM_KEY]);
20a69341
PM
3983 if (err < 0)
3984 goto err1;
3985 err = -EINVAL;
3986 if (d1.type != NFT_DATA_VALUE || d1.len != set->klen)
3987 goto err2;
3988
7d740264 3989 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, d1.len);
c3e1b005
PM
3990 if (timeout > 0) {
3991 nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION);
3992 if (timeout != set->timeout)
3993 nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT);
3994 }
fe2811eb 3995
8aeff920
PNA
3996 if (nla[NFTA_SET_ELEM_OBJREF] != NULL) {
3997 if (!(set->flags & NFT_SET_OBJECT)) {
3998 err = -EINVAL;
3999 goto err2;
4000 }
cac20fcd
PNA
4001 obj = nft_obj_lookup(ctx->table, nla[NFTA_SET_ELEM_OBJREF],
4002 set->objtype, genmask);
8aeff920
PNA
4003 if (IS_ERR(obj)) {
4004 err = PTR_ERR(obj);
4005 goto err2;
4006 }
4007 nft_set_ext_add(&tmpl, NFT_SET_EXT_OBJREF);
4008 }
4009
20a69341 4010 if (nla[NFTA_SET_ELEM_DATA] != NULL) {
d0a11fc3
PM
4011 err = nft_data_init(ctx, &data, sizeof(data), &d2,
4012 nla[NFTA_SET_ELEM_DATA]);
20a69341
PM
4013 if (err < 0)
4014 goto err2;
4015
4016 err = -EINVAL;
4017 if (set->dtype != NFT_DATA_VERDICT && d2.len != set->dlen)
4018 goto err3;
4019
4020 dreg = nft_type_to_reg(set->dtype);
4021 list_for_each_entry(binding, &set->bindings, list) {
4022 struct nft_ctx bind_ctx = {
58c78e10 4023 .net = ctx->net,
36596dad 4024 .family = ctx->family,
20a69341 4025 .table = ctx->table,
7c95f6d8 4026 .chain = (struct nft_chain *)binding->chain,
20a69341
PM
4027 };
4028
11113e19
PM
4029 if (!(binding->flags & NFT_SET_MAP))
4030 continue;
4031
1ec10212
PM
4032 err = nft_validate_register_store(&bind_ctx, dreg,
4033 &data,
4034 d2.type, d2.len);
20a69341
PM
4035 if (err < 0)
4036 goto err3;
4037 }
fe2811eb 4038
7d740264 4039 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_DATA, d2.len);
20a69341
PM
4040 }
4041
68e942e8
PM
4042 /* The full maximum length of userdata can exceed the maximum
4043 * offset value (U8_MAX) for following extensions, therefor it
4044 * must be the last extension added.
4045 */
4046 ulen = 0;
4047 if (nla[NFTA_SET_ELEM_USERDATA] != NULL) {
4048 ulen = nla_len(nla[NFTA_SET_ELEM_USERDATA]);
4049 if (ulen > 0)
4050 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_USERDATA,
4051 ulen);
4052 }
4053
fe2811eb 4054 err = -ENOMEM;
7d740264 4055 elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, data.data,
c3e1b005 4056 timeout, GFP_KERNEL);
fe2811eb
PM
4057 if (elem.priv == NULL)
4058 goto err3;
4059
4060 ext = nft_set_elem_ext(set, elem.priv);
4061 if (flags)
4062 *nft_set_ext_flags(ext) = flags;
68e942e8
PM
4063 if (ulen > 0) {
4064 udata = nft_set_ext_userdata(ext);
4065 udata->len = ulen - 1;
4066 nla_memcpy(&udata->data, nla[NFTA_SET_ELEM_USERDATA], ulen);
4067 }
8aeff920
PNA
4068 if (obj) {
4069 *nft_set_ext_obj(ext) = obj;
4070 obj->use++;
4071 }
fe2811eb 4072
60319eb1
PNA
4073 trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set);
4074 if (trans == NULL)
fe2811eb 4075 goto err4;
60319eb1 4076
69086658 4077 ext->genmask = nft_genmask_cur(ctx->net) | NFT_SET_ELEM_BUSY_MASK;
c016c7e4
PNA
4078 err = set->ops->insert(ctx->net, set, &elem, &ext2);
4079 if (err) {
4080 if (err == -EEXIST) {
9744a6fc
PNA
4081 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) ^
4082 nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) ||
4083 nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) ^
f0dfd7a2
CIK
4084 nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF)) {
4085 err = -EBUSY;
4086 goto err5;
4087 }
8aeff920
PNA
4088 if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
4089 nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) &&
4090 memcmp(nft_set_ext_data(ext),
4091 nft_set_ext_data(ext2), set->dlen) != 0) ||
4092 (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) &&
4093 nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF) &&
4094 *nft_set_ext_obj(ext) != *nft_set_ext_obj(ext2)))
c016c7e4
PNA
4095 err = -EBUSY;
4096 else if (!(nlmsg_flags & NLM_F_EXCL))
4097 err = 0;
4098 }
fe2811eb 4099 goto err5;
c016c7e4 4100 }
20a69341 4101
35d0ac90
PNA
4102 if (set->size &&
4103 !atomic_add_unless(&set->nelems, 1, set->size + set->ndeact)) {
4104 err = -ENFILE;
4105 goto err6;
4106 }
4107
60319eb1 4108 nft_trans_elem(trans) = elem;
46bbafce 4109 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
20a69341
PM
4110 return 0;
4111
35d0ac90 4112err6:
5cb82a38 4113 set->ops->remove(ctx->net, set, &elem);
fe2811eb 4114err5:
60319eb1 4115 kfree(trans);
fe2811eb
PM
4116err4:
4117 kfree(elem.priv);
20a69341
PM
4118err3:
4119 if (nla[NFTA_SET_ELEM_DATA] != NULL)
59105446 4120 nft_data_release(&data, d2.type);
20a69341 4121err2:
59105446 4122 nft_data_release(&elem.key.val, d1.type);
20a69341
PM
4123err1:
4124 return err;
4125}
4126
633c9a84
PNA
4127static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
4128 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
4129 const struct nlattr * const nla[],
4130 struct netlink_ext_ack *extack)
20a69341 4131{
f2a6d766 4132 u8 genmask = nft_genmask_next(net);
20a69341
PM
4133 const struct nlattr *attr;
4134 struct nft_set *set;
4135 struct nft_ctx ctx;
60319eb1 4136 int rem, err = 0;
20a69341 4137
7d5570ca
PNA
4138 if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
4139 return -EINVAL;
4140
36dd1bcc
PNA
4141 err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, extack,
4142 genmask);
20a69341
PM
4143 if (err < 0)
4144 return err;
4145
a3073c17
PNA
4146 set = nft_set_lookup_global(net, ctx.table, nla[NFTA_SET_ELEM_LIST_SET],
4147 nla[NFTA_SET_ELEM_LIST_SET_ID], genmask);
4148 if (IS_ERR(set))
4149 return PTR_ERR(set);
958bee14 4150
20a69341
PM
4151 if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
4152 return -EBUSY;
4153
4154 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
c016c7e4 4155 err = nft_add_set_elem(&ctx, set, attr, nlh->nlmsg_flags);
35d0ac90 4156 if (err < 0)
60319eb1 4157 break;
20a69341 4158 }
60319eb1 4159 return err;
20a69341
PM
4160}
4161
59105446
PNA
4162/**
4163 * nft_data_hold - hold a nft_data item
4164 *
4165 * @data: struct nft_data to release
4166 * @type: type of data
4167 *
4168 * Hold a nft_data item. NFT_DATA_VALUE types can be silently discarded,
4169 * NFT_DATA_VERDICT bumps the reference to chains in case of NFT_JUMP and
4170 * NFT_GOTO verdicts. This function must be called on active data objects
4171 * from the second phase of the commit protocol.
4172 */
bb7b40ae 4173void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
59105446
PNA
4174{
4175 if (type == NFT_DATA_VERDICT) {
4176 switch (data->verdict.code) {
4177 case NFT_JUMP:
4178 case NFT_GOTO:
4179 data->verdict.chain->use++;
4180 break;
4181 }
4182 }
4183}
4184
4185static void nft_set_elem_activate(const struct net *net,
4186 const struct nft_set *set,
4187 struct nft_set_elem *elem)
4188{
4189 const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
4190
4191 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
4192 nft_data_hold(nft_set_ext_data(ext), set->dtype);
4193 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
4194 (*nft_set_ext_obj(ext))->use++;
4195}
4196
4197static void nft_set_elem_deactivate(const struct net *net,
4198 const struct nft_set *set,
4199 struct nft_set_elem *elem)
4200{
4201 const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
4202
4203 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
4204 nft_data_release(nft_set_ext_data(ext), set->dtype);
4205 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
4206 (*nft_set_ext_obj(ext))->use--;
4207}
4208
60319eb1 4209static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
20a69341
PM
4210 const struct nlattr *attr)
4211{
4212 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
3971ca14 4213 struct nft_set_ext_tmpl tmpl;
20a69341
PM
4214 struct nft_data_desc desc;
4215 struct nft_set_elem elem;
3971ca14 4216 struct nft_set_ext *ext;
60319eb1 4217 struct nft_trans *trans;
3971ca14
PNA
4218 u32 flags = 0;
4219 void *priv;
20a69341
PM
4220 int err;
4221
4222 err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr,
fceb6435 4223 nft_set_elem_policy, NULL);
20a69341
PM
4224 if (err < 0)
4225 goto err1;
4226
4227 err = -EINVAL;
4228 if (nla[NFTA_SET_ELEM_KEY] == NULL)
4229 goto err1;
4230
3971ca14
PNA
4231 nft_set_ext_prepare(&tmpl);
4232
4233 err = nft_setelem_parse_flags(set, nla[NFTA_SET_ELEM_FLAGS], &flags);
4234 if (err < 0)
4235 return err;
4236 if (flags != 0)
4237 nft_set_ext_add(&tmpl, NFT_SET_EXT_FLAGS);
4238
7d740264 4239 err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &desc,
d0a11fc3 4240 nla[NFTA_SET_ELEM_KEY]);
20a69341
PM
4241 if (err < 0)
4242 goto err1;
4243
4244 err = -EINVAL;
4245 if (desc.type != NFT_DATA_VALUE || desc.len != set->klen)
4246 goto err2;
4247
3971ca14
PNA
4248 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, desc.len);
4249
4250 err = -ENOMEM;
4251 elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, NULL, 0,
4252 GFP_KERNEL);
4253 if (elem.priv == NULL)
4254 goto err2;
4255
4256 ext = nft_set_elem_ext(set, elem.priv);
4257 if (flags)
4258 *nft_set_ext_flags(ext) = flags;
4259
60319eb1 4260 trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set);
609ccf08
JL
4261 if (trans == NULL) {
4262 err = -ENOMEM;
3971ca14 4263 goto err3;
609ccf08 4264 }
20a69341 4265
42a55769 4266 priv = set->ops->deactivate(ctx->net, set, &elem);
3971ca14 4267 if (priv == NULL) {
cc02e457 4268 err = -ENOENT;
3971ca14 4269 goto err4;
cc02e457 4270 }
3971ca14
PNA
4271 kfree(elem.priv);
4272 elem.priv = priv;
cc02e457 4273
59105446
PNA
4274 nft_set_elem_deactivate(ctx->net, set, &elem);
4275
60319eb1 4276 nft_trans_elem(trans) = elem;
46bbafce 4277 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
0dc13625 4278 return 0;
cc02e457 4279
3971ca14 4280err4:
cc02e457 4281 kfree(trans);
3971ca14
PNA
4282err3:
4283 kfree(elem.priv);
20a69341 4284err2:
59105446 4285 nft_data_release(&elem.key.val, desc.type);
20a69341
PM
4286err1:
4287 return err;
4288}
4289
8411b644 4290static int nft_flush_set(const struct nft_ctx *ctx,
de70185d 4291 struct nft_set *set,
8411b644 4292 const struct nft_set_iter *iter,
de70185d 4293 struct nft_set_elem *elem)
8411b644
PNA
4294{
4295 struct nft_trans *trans;
4296 int err;
4297
4298 trans = nft_trans_alloc_gfp(ctx, NFT_MSG_DELSETELEM,
4299 sizeof(struct nft_trans_elem), GFP_ATOMIC);
4300 if (!trans)
4301 return -ENOMEM;
4302
1ba1c414 4303 if (!set->ops->flush(ctx->net, set, elem->priv)) {
8411b644
PNA
4304 err = -ENOENT;
4305 goto err1;
4306 }
b2c11e4b 4307 set->ndeact++;
8411b644 4308
de70185d
PNA
4309 nft_trans_elem_set(trans) = set;
4310 nft_trans_elem(trans) = *elem;
8411b644
PNA
4311 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
4312
4313 return 0;
4314err1:
4315 kfree(trans);
4316 return err;
4317}
4318
633c9a84
PNA
4319static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
4320 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
4321 const struct nlattr * const nla[],
4322 struct netlink_ext_ack *extack)
20a69341 4323{
f2a6d766 4324 u8 genmask = nft_genmask_next(net);
20a69341
PM
4325 const struct nlattr *attr;
4326 struct nft_set *set;
4327 struct nft_ctx ctx;
60319eb1 4328 int rem, err = 0;
20a69341 4329
36dd1bcc
PNA
4330 err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, extack,
4331 genmask);
20a69341
PM
4332 if (err < 0)
4333 return err;
4334
cac20fcd 4335 set = nft_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
20a69341
PM
4336 if (IS_ERR(set))
4337 return PTR_ERR(set);
4338 if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
4339 return -EBUSY;
4340
8411b644 4341 if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) {
baa2d42c
PNA
4342 struct nft_set_iter iter = {
4343 .genmask = genmask,
4344 .fn = nft_flush_set,
8411b644 4345 };
baa2d42c 4346 set->ops->walk(&ctx, set, &iter);
8411b644 4347
baa2d42c 4348 return iter.err;
8411b644
PNA
4349 }
4350
20a69341
PM
4351 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
4352 err = nft_del_setelem(&ctx, set, attr);
4353 if (err < 0)
60319eb1 4354 break;
4fefee57 4355
3dd0673a 4356 set->ndeact++;
20a69341 4357 }
60319eb1 4358 return err;
20a69341
PM
4359}
4360
cfed7e1b
PM
4361void nft_set_gc_batch_release(struct rcu_head *rcu)
4362{
4363 struct nft_set_gc_batch *gcb;
4364 unsigned int i;
4365
4366 gcb = container_of(rcu, struct nft_set_gc_batch, head.rcu);
4367 for (i = 0; i < gcb->head.cnt; i++)
61f9e292 4368 nft_set_elem_destroy(gcb->head.set, gcb->elems[i], true);
cfed7e1b
PM
4369 kfree(gcb);
4370}
4371EXPORT_SYMBOL_GPL(nft_set_gc_batch_release);
4372
4373struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
4374 gfp_t gfp)
4375{
4376 struct nft_set_gc_batch *gcb;
4377
4378 gcb = kzalloc(sizeof(*gcb), gfp);
4379 if (gcb == NULL)
4380 return gcb;
4381 gcb->head.set = set;
4382 return gcb;
4383}
4384EXPORT_SYMBOL_GPL(nft_set_gc_batch_alloc);
4385
e5009240
PNA
4386/*
4387 * Stateful objects
4388 */
4389
4390/**
4391 * nft_register_obj- register nf_tables stateful object type
4392 * @obj: object type
4393 *
4394 * Registers the object type for use with nf_tables. Returns zero on
4395 * success or a negative errno code otherwise.
4396 */
4397int nft_register_obj(struct nft_object_type *obj_type)
4398{
4399 if (obj_type->type == NFT_OBJECT_UNSPEC)
4400 return -EINVAL;
4401
4402 nfnl_lock(NFNL_SUBSYS_NFTABLES);
4403 list_add_rcu(&obj_type->list, &nf_tables_objects);
4404 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
4405 return 0;
4406}
4407EXPORT_SYMBOL_GPL(nft_register_obj);
4408
4409/**
4410 * nft_unregister_obj - unregister nf_tables object type
4411 * @obj: object type
4412 *
4413 * Unregisters the object type for use with nf_tables.
4414 */
4415void nft_unregister_obj(struct nft_object_type *obj_type)
4416{
4417 nfnl_lock(NFNL_SUBSYS_NFTABLES);
4418 list_del_rcu(&obj_type->list);
4419 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
4420}
4421EXPORT_SYMBOL_GPL(nft_unregister_obj);
4422
cac20fcd
PNA
4423struct nft_object *nft_obj_lookup(const struct nft_table *table,
4424 const struct nlattr *nla, u32 objtype,
4425 u8 genmask)
e5009240
PNA
4426{
4427 struct nft_object *obj;
4428
4429 list_for_each_entry(obj, &table->objects, list) {
4430 if (!nla_strcmp(nla, obj->name) &&
dfc46034 4431 objtype == obj->ops->type->type &&
e5009240
PNA
4432 nft_active_genmask(obj, genmask))
4433 return obj;
4434 }
4435 return ERR_PTR(-ENOENT);
4436}
cac20fcd 4437EXPORT_SYMBOL_GPL(nft_obj_lookup);
e5009240 4438
cac20fcd
PNA
4439static struct nft_object *nft_obj_lookup_byhandle(const struct nft_table *table,
4440 const struct nlattr *nla,
4441 u32 objtype, u8 genmask)
3ecbfd65
HS
4442{
4443 struct nft_object *obj;
4444
4445 list_for_each_entry(obj, &table->objects, list) {
4446 if (be64_to_cpu(nla_get_be64(nla)) == obj->handle &&
4447 objtype == obj->ops->type->type &&
4448 nft_active_genmask(obj, genmask))
4449 return obj;
4450 }
4451 return ERR_PTR(-ENOENT);
4452}
4453
e5009240 4454static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
b2fbd044
LZ
4455 [NFTA_OBJ_TABLE] = { .type = NLA_STRING,
4456 .len = NFT_TABLE_MAXNAMELEN - 1 },
4457 [NFTA_OBJ_NAME] = { .type = NLA_STRING,
4458 .len = NFT_OBJ_MAXNAMELEN - 1 },
e5009240
PNA
4459 [NFTA_OBJ_TYPE] = { .type = NLA_U32 },
4460 [NFTA_OBJ_DATA] = { .type = NLA_NESTED },
3ecbfd65 4461 [NFTA_OBJ_HANDLE] = { .type = NLA_U64},
e5009240
PNA
4462};
4463
84fba055
FW
4464static struct nft_object *nft_obj_init(const struct nft_ctx *ctx,
4465 const struct nft_object_type *type,
e5009240
PNA
4466 const struct nlattr *attr)
4467{
5b4c6e38 4468 struct nlattr **tb;
dfc46034 4469 const struct nft_object_ops *ops;
e5009240 4470 struct nft_object *obj;
5b4c6e38
GS
4471 int err = -ENOMEM;
4472
4473 tb = kmalloc_array(type->maxattr + 1, sizeof(*tb), GFP_KERNEL);
4474 if (!tb)
4475 goto err1;
e5009240
PNA
4476
4477 if (attr) {
fceb6435
JB
4478 err = nla_parse_nested(tb, type->maxattr, attr, type->policy,
4479 NULL);
e5009240 4480 if (err < 0)
5b4c6e38 4481 goto err2;
e5009240
PNA
4482 } else {
4483 memset(tb, 0, sizeof(tb[0]) * (type->maxattr + 1));
4484 }
4485
dfc46034
PBG
4486 if (type->select_ops) {
4487 ops = type->select_ops(ctx, (const struct nlattr * const *)tb);
4488 if (IS_ERR(ops)) {
4489 err = PTR_ERR(ops);
5b4c6e38 4490 goto err2;
dfc46034
PBG
4491 }
4492 } else {
4493 ops = type->ops;
4494 }
4495
e5009240 4496 err = -ENOMEM;
dfc46034 4497 obj = kzalloc(sizeof(*obj) + ops->size, GFP_KERNEL);
5b4c6e38
GS
4498 if (!obj)
4499 goto err2;
e5009240 4500
dfc46034 4501 err = ops->init(ctx, (const struct nlattr * const *)tb, obj);
e5009240 4502 if (err < 0)
5b4c6e38 4503 goto err3;
e5009240 4504
dfc46034
PBG
4505 obj->ops = ops;
4506
5b4c6e38 4507 kfree(tb);
e5009240 4508 return obj;
5b4c6e38 4509err3:
e5009240 4510 kfree(obj);
5b4c6e38
GS
4511err2:
4512 kfree(tb);
e5009240
PNA
4513err1:
4514 return ERR_PTR(err);
4515}
4516
4517static int nft_object_dump(struct sk_buff *skb, unsigned int attr,
43da04a5 4518 struct nft_object *obj, bool reset)
e5009240
PNA
4519{
4520 struct nlattr *nest;
4521
4522 nest = nla_nest_start(skb, attr);
4523 if (!nest)
4524 goto nla_put_failure;
dfc46034 4525 if (obj->ops->dump(skb, obj, reset) < 0)
e5009240
PNA
4526 goto nla_put_failure;
4527 nla_nest_end(skb, nest);
4528 return 0;
4529
4530nla_put_failure:
4531 return -1;
4532}
4533
4534static const struct nft_object_type *__nft_obj_type_get(u32 objtype)
4535{
4536 const struct nft_object_type *type;
4537
4538 list_for_each_entry(type, &nf_tables_objects, list) {
4539 if (objtype == type->type)
4540 return type;
4541 }
4542 return NULL;
4543}
4544
4545static const struct nft_object_type *nft_obj_type_get(u32 objtype)
4546{
4547 const struct nft_object_type *type;
4548
4549 type = __nft_obj_type_get(objtype);
4550 if (type != NULL && try_module_get(type->owner))
4551 return type;
4552
4553#ifdef CONFIG_MODULES
4554 if (type == NULL) {
4555 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
4556 request_module("nft-obj-%u", objtype);
4557 nfnl_lock(NFNL_SUBSYS_NFTABLES);
4558 if (__nft_obj_type_get(objtype))
4559 return ERR_PTR(-EAGAIN);
4560 }
4561#endif
4562 return ERR_PTR(-ENOENT);
4563}
4564
4565static int nf_tables_newobj(struct net *net, struct sock *nlsk,
4566 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
4567 const struct nlattr * const nla[],
4568 struct netlink_ext_ack *extack)
e5009240
PNA
4569{
4570 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
4571 const struct nft_object_type *type;
4572 u8 genmask = nft_genmask_next(net);
4573 int family = nfmsg->nfgen_family;
e5009240
PNA
4574 struct nft_table *table;
4575 struct nft_object *obj;
4576 struct nft_ctx ctx;
4577 u32 objtype;
4578 int err;
4579
4580 if (!nla[NFTA_OBJ_TYPE] ||
4581 !nla[NFTA_OBJ_NAME] ||
4582 !nla[NFTA_OBJ_DATA])
4583 return -EINVAL;
4584
cac20fcd 4585 table = nft_table_lookup(net, nla[NFTA_OBJ_TABLE], family, genmask);
36dd1bcc
PNA
4586 if (IS_ERR(table)) {
4587 NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_TABLE]);
e5009240 4588 return PTR_ERR(table);
36dd1bcc 4589 }
e5009240
PNA
4590
4591 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
cac20fcd 4592 obj = nft_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask);
e5009240
PNA
4593 if (IS_ERR(obj)) {
4594 err = PTR_ERR(obj);
36dd1bcc
PNA
4595 if (err != -ENOENT) {
4596 NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_NAME]);
e5009240 4597 return err;
36dd1bcc 4598 }
1a28ad74 4599 } else {
36dd1bcc
PNA
4600 if (nlh->nlmsg_flags & NLM_F_EXCL) {
4601 NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_NAME]);
e5009240 4602 return -EEXIST;
36dd1bcc 4603 }
e5009240
PNA
4604 return 0;
4605 }
4606
98319cb9 4607 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
e5009240
PNA
4608
4609 type = nft_obj_type_get(objtype);
4610 if (IS_ERR(type))
4611 return PTR_ERR(type);
4612
84fba055 4613 obj = nft_obj_init(&ctx, type, nla[NFTA_OBJ_DATA]);
e5009240
PNA
4614 if (IS_ERR(obj)) {
4615 err = PTR_ERR(obj);
4616 goto err1;
4617 }
18965317 4618 obj->table = table;
3ecbfd65
HS
4619 obj->handle = nf_tables_alloc_handle(table);
4620
61509575
PS
4621 obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL);
4622 if (!obj->name) {
4623 err = -ENOMEM;
4624 goto err2;
4625 }
e5009240
PNA
4626
4627 err = nft_trans_obj_add(&ctx, NFT_MSG_NEWOBJ, obj);
4628 if (err < 0)
61509575 4629 goto err3;
e5009240
PNA
4630
4631 list_add_tail_rcu(&obj->list, &table->objects);
4632 table->use++;
4633 return 0;
61509575
PS
4634err3:
4635 kfree(obj->name);
e5009240 4636err2:
dfc46034
PBG
4637 if (obj->ops->destroy)
4638 obj->ops->destroy(obj);
e5009240
PNA
4639 kfree(obj);
4640err1:
4641 module_put(type->owner);
4642 return err;
4643}
4644
4645static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net,
4646 u32 portid, u32 seq, int event, u32 flags,
4647 int family, const struct nft_table *table,
43da04a5 4648 struct nft_object *obj, bool reset)
e5009240
PNA
4649{
4650 struct nfgenmsg *nfmsg;
4651 struct nlmsghdr *nlh;
4652
dedb67c4 4653 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
e5009240
PNA
4654 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags);
4655 if (nlh == NULL)
4656 goto nla_put_failure;
4657
4658 nfmsg = nlmsg_data(nlh);
4659 nfmsg->nfgen_family = family;
4660 nfmsg->version = NFNETLINK_V0;
4661 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
4662
4663 if (nla_put_string(skb, NFTA_OBJ_TABLE, table->name) ||
4664 nla_put_string(skb, NFTA_OBJ_NAME, obj->name) ||
dfc46034 4665 nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) ||
e5009240 4666 nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) ||
3ecbfd65
HS
4667 nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset) ||
4668 nla_put_be64(skb, NFTA_OBJ_HANDLE, cpu_to_be64(obj->handle),
4669 NFTA_OBJ_PAD))
e5009240
PNA
4670 goto nla_put_failure;
4671
4672 nlmsg_end(skb, nlh);
4673 return 0;
4674
4675nla_put_failure:
4676 nlmsg_trim(skb, nlh);
4677 return -1;
4678}
4679
a9fea2a3 4680struct nft_obj_filter {
e46abbcc 4681 char *table;
a9fea2a3
PNA
4682 u32 type;
4683};
4684
e5009240
PNA
4685static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
4686{
4687 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
e5009240 4688 const struct nft_table *table;
e5009240 4689 unsigned int idx = 0, s_idx = cb->args[0];
a9fea2a3 4690 struct nft_obj_filter *filter = cb->data;
e5009240
PNA
4691 struct net *net = sock_net(skb->sk);
4692 int family = nfmsg->nfgen_family;
43da04a5
PNA
4693 struct nft_object *obj;
4694 bool reset = false;
4695
4696 if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
4697 reset = true;
e5009240
PNA
4698
4699 rcu_read_lock();
4700 cb->seq = net->nft.base_seq;
4701
36596dad 4702 list_for_each_entry_rcu(table, &net->nft.tables, list) {
98319cb9 4703 if (family != NFPROTO_UNSPEC && family != table->family)
e5009240
PNA
4704 continue;
4705
36596dad
PNA
4706 list_for_each_entry_rcu(obj, &table->objects, list) {
4707 if (!nft_is_active(net, obj))
4708 goto cont;
4709 if (idx < s_idx)
4710 goto cont;
4711 if (idx > s_idx)
4712 memset(&cb->args[1], 0,
4713 sizeof(cb->args) - sizeof(cb->args[0]));
4714 if (filter && filter->table[0] &&
4715 strcmp(filter->table, table->name))
4716 goto cont;
4717 if (filter &&
4718 filter->type != NFT_OBJECT_UNSPEC &&
4719 obj->ops->type->type != filter->type)
4720 goto cont;
a9fea2a3 4721
36596dad
PNA
4722 if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid,
4723 cb->nlh->nlmsg_seq,
4724 NFT_MSG_NEWOBJ,
4725 NLM_F_MULTI | NLM_F_APPEND,
98319cb9 4726 table->family, table,
36596dad
PNA
4727 obj, reset) < 0)
4728 goto done;
e5009240 4729
36596dad 4730 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
e5009240 4731cont:
36596dad 4732 idx++;
e5009240
PNA
4733 }
4734 }
4735done:
4736 rcu_read_unlock();
4737
4738 cb->args[0] = idx;
4739 return skb->len;
4740}
4741
a9fea2a3
PNA
4742static int nf_tables_dump_obj_done(struct netlink_callback *cb)
4743{
e46abbcc
PS
4744 struct nft_obj_filter *filter = cb->data;
4745
8bea728d
HL
4746 if (filter) {
4747 kfree(filter->table);
4748 kfree(filter);
4749 }
a9fea2a3
PNA
4750
4751 return 0;
4752}
4753
4754static struct nft_obj_filter *
4755nft_obj_filter_alloc(const struct nlattr * const nla[])
4756{
4757 struct nft_obj_filter *filter;
4758
4759 filter = kzalloc(sizeof(*filter), GFP_KERNEL);
4760 if (!filter)
4761 return ERR_PTR(-ENOMEM);
4762
e46abbcc
PS
4763 if (nla[NFTA_OBJ_TABLE]) {
4764 filter->table = nla_strdup(nla[NFTA_OBJ_TABLE], GFP_KERNEL);
4765 if (!filter->table) {
4766 kfree(filter);
4767 return ERR_PTR(-ENOMEM);
4768 }
4769 }
a9fea2a3
PNA
4770 if (nla[NFTA_OBJ_TYPE])
4771 filter->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
4772
4773 return filter;
4774}
4775
e5009240
PNA
4776static int nf_tables_getobj(struct net *net, struct sock *nlsk,
4777 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
4778 const struct nlattr * const nla[],
4779 struct netlink_ext_ack *extack)
e5009240
PNA
4780{
4781 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
4782 u8 genmask = nft_genmask_cur(net);
4783 int family = nfmsg->nfgen_family;
e5009240
PNA
4784 const struct nft_table *table;
4785 struct nft_object *obj;
4786 struct sk_buff *skb2;
43da04a5 4787 bool reset = false;
e5009240
PNA
4788 u32 objtype;
4789 int err;
4790
4791 if (nlh->nlmsg_flags & NLM_F_DUMP) {
4792 struct netlink_dump_control c = {
4793 .dump = nf_tables_dump_obj,
a9fea2a3 4794 .done = nf_tables_dump_obj_done,
e5009240 4795 };
a9fea2a3
PNA
4796
4797 if (nla[NFTA_OBJ_TABLE] ||
4798 nla[NFTA_OBJ_TYPE]) {
4799 struct nft_obj_filter *filter;
4800
4801 filter = nft_obj_filter_alloc(nla);
4802 if (IS_ERR(filter))
4803 return -ENOMEM;
4804
4805 c.data = filter;
4806 }
e5009240
PNA
4807 return netlink_dump_start(nlsk, skb, nlh, &c);
4808 }
4809
4810 if (!nla[NFTA_OBJ_NAME] ||
4811 !nla[NFTA_OBJ_TYPE])
4812 return -EINVAL;
4813
cac20fcd 4814 table = nft_table_lookup(net, nla[NFTA_OBJ_TABLE], family, genmask);
36dd1bcc
PNA
4815 if (IS_ERR(table)) {
4816 NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_TABLE]);
e5009240 4817 return PTR_ERR(table);
36dd1bcc 4818 }
e5009240
PNA
4819
4820 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
cac20fcd 4821 obj = nft_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask);
36dd1bcc
PNA
4822 if (IS_ERR(obj)) {
4823 NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_NAME]);
e5009240 4824 return PTR_ERR(obj);
36dd1bcc 4825 }
e5009240
PNA
4826
4827 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
4828 if (!skb2)
4829 return -ENOMEM;
4830
43da04a5
PNA
4831 if (NFNL_MSG_TYPE(nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
4832 reset = true;
4833
e5009240
PNA
4834 err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid,
4835 nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
43da04a5 4836 family, table, obj, reset);
e5009240
PNA
4837 if (err < 0)
4838 goto err;
4839
4840 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
4841err:
4842 kfree_skb(skb2);
4843 return err;
e5009240
PNA
4844}
4845
4846static void nft_obj_destroy(struct nft_object *obj)
4847{
dfc46034
PBG
4848 if (obj->ops->destroy)
4849 obj->ops->destroy(obj);
e5009240 4850
dfc46034 4851 module_put(obj->ops->type->owner);
61509575 4852 kfree(obj->name);
e5009240
PNA
4853 kfree(obj);
4854}
4855
4856static int nf_tables_delobj(struct net *net, struct sock *nlsk,
04ba724b
PNA
4857 struct sk_buff *skb, const struct nlmsghdr *nlh,
4858 const struct nlattr * const nla[],
4859 struct netlink_ext_ack *extack)
e5009240
PNA
4860{
4861 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
4862 u8 genmask = nft_genmask_next(net);
4863 int family = nfmsg->nfgen_family;
36dd1bcc 4864 const struct nlattr *attr;
e5009240
PNA
4865 struct nft_table *table;
4866 struct nft_object *obj;
4867 struct nft_ctx ctx;
4868 u32 objtype;
4869
4870 if (!nla[NFTA_OBJ_TYPE] ||
3ecbfd65 4871 (!nla[NFTA_OBJ_NAME] && !nla[NFTA_OBJ_HANDLE]))
e5009240
PNA
4872 return -EINVAL;
4873
cac20fcd 4874 table = nft_table_lookup(net, nla[NFTA_OBJ_TABLE], family, genmask);
36dd1bcc
PNA
4875 if (IS_ERR(table)) {
4876 NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_TABLE]);
e5009240 4877 return PTR_ERR(table);
36dd1bcc 4878 }
e5009240
PNA
4879
4880 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
36dd1bcc
PNA
4881 if (nla[NFTA_OBJ_HANDLE]) {
4882 attr = nla[NFTA_OBJ_HANDLE];
4883 obj = nft_obj_lookup_byhandle(table, attr, objtype, genmask);
4884 } else {
4885 attr = nla[NFTA_OBJ_NAME];
4886 obj = nft_obj_lookup(table, attr, objtype, genmask);
4887 }
4888
4889 if (IS_ERR(obj)) {
4890 NL_SET_BAD_ATTR(extack, attr);
e5009240 4891 return PTR_ERR(obj);
36dd1bcc
PNA
4892 }
4893 if (obj->use > 0) {
4894 NL_SET_BAD_ATTR(extack, attr);
e5009240 4895 return -EBUSY;
36dd1bcc 4896 }
e5009240 4897
98319cb9 4898 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
e5009240
PNA
4899
4900 return nft_delobj(&ctx, obj);
4901}
4902
25e94a99
PNA
4903void nft_obj_notify(struct net *net, struct nft_table *table,
4904 struct nft_object *obj, u32 portid, u32 seq, int event,
4905 int family, int report, gfp_t gfp)
e5009240
PNA
4906{
4907 struct sk_buff *skb;
4908 int err;
4909
2599e989
PNA
4910 if (!report &&
4911 !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
25e94a99 4912 return;
e5009240 4913
2599e989 4914 skb = nlmsg_new(NLMSG_GOODSIZE, gfp);
e5009240
PNA
4915 if (skb == NULL)
4916 goto err;
4917
2599e989
PNA
4918 err = nf_tables_fill_obj_info(skb, net, portid, seq, event, 0, family,
4919 table, obj, false);
e5009240
PNA
4920 if (err < 0) {
4921 kfree_skb(skb);
4922 goto err;
4923 }
4924
25e94a99
PNA
4925 nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, report, gfp);
4926 return;
e5009240 4927err:
25e94a99 4928 nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
e5009240 4929}
2599e989
PNA
4930EXPORT_SYMBOL_GPL(nft_obj_notify);
4931
25e94a99
PNA
4932static void nf_tables_obj_notify(const struct nft_ctx *ctx,
4933 struct nft_object *obj, int event)
2599e989 4934{
25e94a99 4935 nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event,
36596dad 4936 ctx->family, ctx->report, GFP_KERNEL);
2599e989 4937}
e5009240 4938
3b49e2e9
PNA
4939/*
4940 * Flow tables
4941 */
4942void nft_register_flowtable_type(struct nf_flowtable_type *type)
4943{
4944 nfnl_lock(NFNL_SUBSYS_NFTABLES);
4945 list_add_tail_rcu(&type->list, &nf_tables_flowtables);
4946 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
4947}
4948EXPORT_SYMBOL_GPL(nft_register_flowtable_type);
4949
4950void nft_unregister_flowtable_type(struct nf_flowtable_type *type)
4951{
4952 nfnl_lock(NFNL_SUBSYS_NFTABLES);
4953 list_del_rcu(&type->list);
4954 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
4955}
4956EXPORT_SYMBOL_GPL(nft_unregister_flowtable_type);
4957
4958static const struct nla_policy nft_flowtable_policy[NFTA_FLOWTABLE_MAX + 1] = {
4959 [NFTA_FLOWTABLE_TABLE] = { .type = NLA_STRING,
4960 .len = NFT_NAME_MAXLEN - 1 },
4961 [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING,
4962 .len = NFT_NAME_MAXLEN - 1 },
4963 [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED },
3ecbfd65 4964 [NFTA_FLOWTABLE_HANDLE] = { .type = NLA_U64 },
3b49e2e9
PNA
4965};
4966
cac20fcd
PNA
4967struct nft_flowtable *nft_flowtable_lookup(const struct nft_table *table,
4968 const struct nlattr *nla, u8 genmask)
3b49e2e9
PNA
4969{
4970 struct nft_flowtable *flowtable;
4971
4972 list_for_each_entry(flowtable, &table->flowtables, list) {
4973 if (!nla_strcmp(nla, flowtable->name) &&
4974 nft_active_genmask(flowtable, genmask))
4975 return flowtable;
4976 }
4977 return ERR_PTR(-ENOENT);
4978}
cac20fcd 4979EXPORT_SYMBOL_GPL(nft_flowtable_lookup);
3b49e2e9 4980
ae0662f8 4981static struct nft_flowtable *
cac20fcd
PNA
4982nft_flowtable_lookup_byhandle(const struct nft_table *table,
4983 const struct nlattr *nla, u8 genmask)
3ecbfd65
HS
4984{
4985 struct nft_flowtable *flowtable;
4986
4987 list_for_each_entry(flowtable, &table->flowtables, list) {
4988 if (be64_to_cpu(nla_get_be64(nla)) == flowtable->handle &&
4989 nft_active_genmask(flowtable, genmask))
4990 return flowtable;
4991 }
4992 return ERR_PTR(-ENOENT);
4993}
4994
3b49e2e9
PNA
4995static int nf_tables_parse_devices(const struct nft_ctx *ctx,
4996 const struct nlattr *attr,
4997 struct net_device *dev_array[], int *len)
4998{
4999 const struct nlattr *tmp;
5000 struct net_device *dev;
5001 char ifname[IFNAMSIZ];
5002 int rem, n = 0, err;
5003
5004 nla_for_each_nested(tmp, attr, rem) {
5005 if (nla_type(tmp) != NFTA_DEVICE_NAME) {
5006 err = -EINVAL;
5007 goto err1;
5008 }
5009
5010 nla_strlcpy(ifname, tmp, IFNAMSIZ);
90d2723c 5011 dev = __dev_get_by_name(ctx->net, ifname);
3b49e2e9
PNA
5012 if (!dev) {
5013 err = -ENOENT;
5014 goto err1;
5015 }
5016
5017 dev_array[n++] = dev;
5018 if (n == NFT_FLOWTABLE_DEVICE_MAX) {
5019 err = -EFBIG;
5020 goto err1;
5021 }
5022 }
5023 if (!len)
5024 return -EINVAL;
5025
5026 err = 0;
5027err1:
5028 *len = n;
5029 return err;
5030}
5031
5032static const struct nla_policy nft_flowtable_hook_policy[NFTA_FLOWTABLE_HOOK_MAX + 1] = {
5033 [NFTA_FLOWTABLE_HOOK_NUM] = { .type = NLA_U32 },
5034 [NFTA_FLOWTABLE_HOOK_PRIORITY] = { .type = NLA_U32 },
5035 [NFTA_FLOWTABLE_HOOK_DEVS] = { .type = NLA_NESTED },
5036};
5037
5038static int nf_tables_flowtable_parse_hook(const struct nft_ctx *ctx,
5039 const struct nlattr *attr,
5040 struct nft_flowtable *flowtable)
5041{
5042 struct net_device *dev_array[NFT_FLOWTABLE_DEVICE_MAX];
5043 struct nlattr *tb[NFTA_FLOWTABLE_HOOK_MAX + 1];
5044 struct nf_hook_ops *ops;
5045 int hooknum, priority;
5046 int err, n = 0, i;
5047
5048 err = nla_parse_nested(tb, NFTA_FLOWTABLE_HOOK_MAX, attr,
5049 nft_flowtable_hook_policy, NULL);
5050 if (err < 0)
5051 return err;
5052
5053 if (!tb[NFTA_FLOWTABLE_HOOK_NUM] ||
5054 !tb[NFTA_FLOWTABLE_HOOK_PRIORITY] ||
5055 !tb[NFTA_FLOWTABLE_HOOK_DEVS])
5056 return -EINVAL;
5057
5058 hooknum = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_NUM]));
fe19c04c 5059 if (hooknum != NF_NETDEV_INGRESS)
3b49e2e9
PNA
5060 return -EINVAL;
5061
5062 priority = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_PRIORITY]));
5063
5064 err = nf_tables_parse_devices(ctx, tb[NFTA_FLOWTABLE_HOOK_DEVS],
5065 dev_array, &n);
5066 if (err < 0)
d92191aa 5067 return err;
3b49e2e9
PNA
5068
5069 ops = kzalloc(sizeof(struct nf_hook_ops) * n, GFP_KERNEL);
90d2723c
PNA
5070 if (!ops)
5071 return -ENOMEM;
3b49e2e9 5072
0e839dfa
PNA
5073 flowtable->hooknum = hooknum;
5074 flowtable->priority = priority;
3b49e2e9
PNA
5075 flowtable->ops = ops;
5076 flowtable->ops_len = n;
5077
5078 for (i = 0; i < n; i++) {
5079 flowtable->ops[i].pf = NFPROTO_NETDEV;
5080 flowtable->ops[i].hooknum = hooknum;
5081 flowtable->ops[i].priority = priority;
17857d92 5082 flowtable->ops[i].priv = &flowtable->data;
3b49e2e9
PNA
5083 flowtable->ops[i].hook = flowtable->data.type->hook;
5084 flowtable->ops[i].dev = dev_array[i];
d92191aa
PNA
5085 flowtable->dev_name[i] = kstrdup(dev_array[i]->name,
5086 GFP_KERNEL);
3b49e2e9
PNA
5087 }
5088
3b49e2e9
PNA
5089 return err;
5090}
5091
98319cb9 5092static const struct nf_flowtable_type *__nft_flowtable_type_get(u8 family)
3b49e2e9
PNA
5093{
5094 const struct nf_flowtable_type *type;
5095
5096 list_for_each_entry(type, &nf_tables_flowtables, list) {
98319cb9 5097 if (family == type->family)
3b49e2e9
PNA
5098 return type;
5099 }
5100 return NULL;
5101}
5102
98319cb9 5103static const struct nf_flowtable_type *nft_flowtable_type_get(u8 family)
3b49e2e9
PNA
5104{
5105 const struct nf_flowtable_type *type;
5106
98319cb9 5107 type = __nft_flowtable_type_get(family);
3b49e2e9
PNA
5108 if (type != NULL && try_module_get(type->owner))
5109 return type;
5110
5111#ifdef CONFIG_MODULES
5112 if (type == NULL) {
5113 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
98319cb9 5114 request_module("nf-flowtable-%u", family);
3b49e2e9 5115 nfnl_lock(NFNL_SUBSYS_NFTABLES);
98319cb9 5116 if (__nft_flowtable_type_get(family))
3b49e2e9
PNA
5117 return ERR_PTR(-EAGAIN);
5118 }
5119#endif
5120 return ERR_PTR(-ENOENT);
5121}
5122
3b49e2e9
PNA
5123static void nft_unregister_flowtable_net_hooks(struct net *net,
5124 struct nft_flowtable *flowtable)
5125{
5126 int i;
5127
5128 for (i = 0; i < flowtable->ops_len; i++) {
5129 if (!flowtable->ops[i].dev)
5130 continue;
5131
5132 nf_unregister_net_hook(net, &flowtable->ops[i]);
5133 }
5134}
5135
5136static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
5137 struct sk_buff *skb,
5138 const struct nlmsghdr *nlh,
5139 const struct nlattr * const nla[],
5140 struct netlink_ext_ack *extack)
5141{
5142 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
5143 const struct nf_flowtable_type *type;
32fc7187 5144 struct nft_flowtable *flowtable, *ft;
3b49e2e9
PNA
5145 u8 genmask = nft_genmask_next(net);
5146 int family = nfmsg->nfgen_family;
3b49e2e9
PNA
5147 struct nft_table *table;
5148 struct nft_ctx ctx;
5149 int err, i, k;
5150
5151 if (!nla[NFTA_FLOWTABLE_TABLE] ||
5152 !nla[NFTA_FLOWTABLE_NAME] ||
5153 !nla[NFTA_FLOWTABLE_HOOK])
5154 return -EINVAL;
5155
cac20fcd
PNA
5156 table = nft_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], family,
5157 genmask);
36dd1bcc
PNA
5158 if (IS_ERR(table)) {
5159 NL_SET_BAD_ATTR(extack, nla[NFTA_FLOWTABLE_TABLE]);
3b49e2e9 5160 return PTR_ERR(table);
36dd1bcc 5161 }
3b49e2e9 5162
cac20fcd
PNA
5163 flowtable = nft_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME],
5164 genmask);
3b49e2e9
PNA
5165 if (IS_ERR(flowtable)) {
5166 err = PTR_ERR(flowtable);
36dd1bcc
PNA
5167 if (err != -ENOENT) {
5168 NL_SET_BAD_ATTR(extack, nla[NFTA_FLOWTABLE_NAME]);
3b49e2e9 5169 return err;
36dd1bcc 5170 }
3b49e2e9 5171 } else {
36dd1bcc
PNA
5172 if (nlh->nlmsg_flags & NLM_F_EXCL) {
5173 NL_SET_BAD_ATTR(extack, nla[NFTA_FLOWTABLE_NAME]);
3b49e2e9 5174 return -EEXIST;
36dd1bcc 5175 }
3b49e2e9
PNA
5176
5177 return 0;
5178 }
5179
98319cb9 5180 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
3b49e2e9
PNA
5181
5182 flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL);
5183 if (!flowtable)
5184 return -ENOMEM;
5185
5186 flowtable->table = table;
3ecbfd65
HS
5187 flowtable->handle = nf_tables_alloc_handle(table);
5188
3b49e2e9
PNA
5189 flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL);
5190 if (!flowtable->name) {
5191 err = -ENOMEM;
5192 goto err1;
5193 }
5194
98319cb9 5195 type = nft_flowtable_type_get(family);
3b49e2e9
PNA
5196 if (IS_ERR(type)) {
5197 err = PTR_ERR(type);
5198 goto err2;
5199 }
5200
5201 flowtable->data.type = type;
a268de77 5202 err = type->init(&flowtable->data);
3b49e2e9
PNA
5203 if (err < 0)
5204 goto err3;
5205
5206 err = nf_tables_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK],
5207 flowtable);
5208 if (err < 0)
a268de77 5209 goto err4;
3b49e2e9
PNA
5210
5211 for (i = 0; i < flowtable->ops_len; i++) {
32fc7187
PNA
5212 if (!flowtable->ops[i].dev)
5213 continue;
5214
5215 list_for_each_entry(ft, &table->flowtables, list) {
5216 for (k = 0; k < ft->ops_len; k++) {
5217 if (!ft->ops[k].dev)
5218 continue;
5219
5220 if (flowtable->ops[i].dev == ft->ops[k].dev &&
5221 flowtable->ops[i].pf == ft->ops[k].pf) {
5222 err = -EBUSY;
a268de77 5223 goto err5;
32fc7187
PNA
5224 }
5225 }
5226 }
5227
3b49e2e9
PNA
5228 err = nf_register_net_hook(net, &flowtable->ops[i]);
5229 if (err < 0)
a268de77 5230 goto err5;
3b49e2e9
PNA
5231 }
5232
5233 err = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable);
5234 if (err < 0)
a268de77 5235 goto err6;
3b49e2e9
PNA
5236
5237 list_add_tail_rcu(&flowtable->list, &table->flowtables);
5238 table->use++;
5239
5240 return 0;
a268de77 5241err6:
3b49e2e9 5242 i = flowtable->ops_len;
a268de77 5243err5:
d92191aa
PNA
5244 for (k = i - 1; k >= 0; k--) {
5245 kfree(flowtable->dev_name[k]);
0e0d5002 5246 nf_unregister_net_hook(net, &flowtable->ops[k]);
d92191aa 5247 }
3b49e2e9
PNA
5248
5249 kfree(flowtable->ops);
a268de77
FF
5250err4:
5251 flowtable->data.type->free(&flowtable->data);
3b49e2e9
PNA
5252err3:
5253 module_put(type->owner);
5254err2:
5255 kfree(flowtable->name);
5256err1:
5257 kfree(flowtable);
5258 return err;
5259}
5260
5261static int nf_tables_delflowtable(struct net *net, struct sock *nlsk,
5262 struct sk_buff *skb,
5263 const struct nlmsghdr *nlh,
5264 const struct nlattr * const nla[],
5265 struct netlink_ext_ack *extack)
5266{
5267 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
5268 u8 genmask = nft_genmask_next(net);
5269 int family = nfmsg->nfgen_family;
5270 struct nft_flowtable *flowtable;
36dd1bcc 5271 const struct nlattr *attr;
3b49e2e9
PNA
5272 struct nft_table *table;
5273 struct nft_ctx ctx;
5274
e603ea4b
PNA
5275 if (!nla[NFTA_FLOWTABLE_TABLE] ||
5276 (!nla[NFTA_FLOWTABLE_NAME] &&
5277 !nla[NFTA_FLOWTABLE_HANDLE]))
5278 return -EINVAL;
5279
cac20fcd
PNA
5280 table = nft_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], family,
5281 genmask);
36dd1bcc
PNA
5282 if (IS_ERR(table)) {
5283 NL_SET_BAD_ATTR(extack, nla[NFTA_FLOWTABLE_TABLE]);
3b49e2e9 5284 return PTR_ERR(table);
36dd1bcc 5285 }
3b49e2e9 5286
36dd1bcc
PNA
5287 if (nla[NFTA_FLOWTABLE_HANDLE]) {
5288 attr = nla[NFTA_FLOWTABLE_HANDLE];
5289 flowtable = nft_flowtable_lookup_byhandle(table, attr, genmask);
5290 } else {
5291 attr = nla[NFTA_FLOWTABLE_NAME];
5292 flowtable = nft_flowtable_lookup(table, attr, genmask);
5293 }
5294
5295 if (IS_ERR(flowtable)) {
5296 NL_SET_BAD_ATTR(extack, attr);
5297 return PTR_ERR(flowtable);
5298 }
5299 if (flowtable->use > 0) {
5300 NL_SET_BAD_ATTR(extack, attr);
3b49e2e9 5301 return -EBUSY;
36dd1bcc 5302 }
3b49e2e9 5303
98319cb9 5304 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
3b49e2e9
PNA
5305
5306 return nft_delflowtable(&ctx, flowtable);
5307}
5308
5309static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net,
5310 u32 portid, u32 seq, int event,
5311 u32 flags, int family,
5312 struct nft_flowtable *flowtable)
5313{
5314 struct nlattr *nest, *nest_devs;
5315 struct nfgenmsg *nfmsg;
5316 struct nlmsghdr *nlh;
5317 int i;
5318
5319 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
5320 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags);
5321 if (nlh == NULL)
5322 goto nla_put_failure;
5323
5324 nfmsg = nlmsg_data(nlh);
5325 nfmsg->nfgen_family = family;
5326 nfmsg->version = NFNETLINK_V0;
5327 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
5328
5329 if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) ||
5330 nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) ||
3ecbfd65
HS
5331 nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) ||
5332 nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle),
5333 NFTA_FLOWTABLE_PAD))
3b49e2e9
PNA
5334 goto nla_put_failure;
5335
5336 nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK);
5337 if (nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_NUM, htonl(flowtable->hooknum)) ||
5338 nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_PRIORITY, htonl(flowtable->priority)))
5339 goto nla_put_failure;
5340
5341 nest_devs = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK_DEVS);
5342 if (!nest_devs)
5343 goto nla_put_failure;
5344
5345 for (i = 0; i < flowtable->ops_len; i++) {
d92191aa 5346 if (flowtable->dev_name[i][0] &&
3b49e2e9 5347 nla_put_string(skb, NFTA_DEVICE_NAME,
d92191aa 5348 flowtable->dev_name[i]))
3b49e2e9
PNA
5349 goto nla_put_failure;
5350 }
5351 nla_nest_end(skb, nest_devs);
5352 nla_nest_end(skb, nest);
5353
5354 nlmsg_end(skb, nlh);
5355 return 0;
5356
5357nla_put_failure:
5358 nlmsg_trim(skb, nlh);
5359 return -1;
5360}
5361
5362struct nft_flowtable_filter {
5363 char *table;
5364};
5365
5366static int nf_tables_dump_flowtable(struct sk_buff *skb,
5367 struct netlink_callback *cb)
5368{
5369 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
5370 struct nft_flowtable_filter *filter = cb->data;
5371 unsigned int idx = 0, s_idx = cb->args[0];
5372 struct net *net = sock_net(skb->sk);
5373 int family = nfmsg->nfgen_family;
5374 struct nft_flowtable *flowtable;
3b49e2e9
PNA
5375 const struct nft_table *table;
5376
5377 rcu_read_lock();
5378 cb->seq = net->nft.base_seq;
5379
36596dad 5380 list_for_each_entry_rcu(table, &net->nft.tables, list) {
98319cb9 5381 if (family != NFPROTO_UNSPEC && family != table->family)
3b49e2e9
PNA
5382 continue;
5383
36596dad
PNA
5384 list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
5385 if (!nft_is_active(net, flowtable))
5386 goto cont;
5387 if (idx < s_idx)
5388 goto cont;
5389 if (idx > s_idx)
5390 memset(&cb->args[1], 0,
5391 sizeof(cb->args) - sizeof(cb->args[0]));
5392 if (filter && filter->table[0] &&
5393 strcmp(filter->table, table->name))
5394 goto cont;
3b49e2e9 5395
36596dad
PNA
5396 if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid,
5397 cb->nlh->nlmsg_seq,
5398 NFT_MSG_NEWFLOWTABLE,
5399 NLM_F_MULTI | NLM_F_APPEND,
98319cb9 5400 table->family, flowtable) < 0)
36596dad 5401 goto done;
3b49e2e9 5402
36596dad 5403 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
3b49e2e9 5404cont:
36596dad 5405 idx++;
3b49e2e9
PNA
5406 }
5407 }
5408done:
5409 rcu_read_unlock();
5410
5411 cb->args[0] = idx;
5412 return skb->len;
5413}
5414
5415static int nf_tables_dump_flowtable_done(struct netlink_callback *cb)
5416{
5417 struct nft_flowtable_filter *filter = cb->data;
5418
5419 if (!filter)
5420 return 0;
5421
5422 kfree(filter->table);
5423 kfree(filter);
5424
5425 return 0;
5426}
5427
5428static struct nft_flowtable_filter *
5429nft_flowtable_filter_alloc(const struct nlattr * const nla[])
5430{
5431 struct nft_flowtable_filter *filter;
5432
5433 filter = kzalloc(sizeof(*filter), GFP_KERNEL);
5434 if (!filter)
5435 return ERR_PTR(-ENOMEM);
5436
5437 if (nla[NFTA_FLOWTABLE_TABLE]) {
5438 filter->table = nla_strdup(nla[NFTA_FLOWTABLE_TABLE],
5439 GFP_KERNEL);
5440 if (!filter->table) {
5441 kfree(filter);
5442 return ERR_PTR(-ENOMEM);
5443 }
5444 }
5445 return filter;
5446}
5447
5448static int nf_tables_getflowtable(struct net *net, struct sock *nlsk,
5449 struct sk_buff *skb,
5450 const struct nlmsghdr *nlh,
5451 const struct nlattr * const nla[],
5452 struct netlink_ext_ack *extack)
5453{
5454 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
5455 u8 genmask = nft_genmask_cur(net);
5456 int family = nfmsg->nfgen_family;
5457 struct nft_flowtable *flowtable;
3b49e2e9
PNA
5458 const struct nft_table *table;
5459 struct sk_buff *skb2;
5460 int err;
5461
5462 if (nlh->nlmsg_flags & NLM_F_DUMP) {
5463 struct netlink_dump_control c = {
5464 .dump = nf_tables_dump_flowtable,
5465 .done = nf_tables_dump_flowtable_done,
5466 };
5467
5468 if (nla[NFTA_FLOWTABLE_TABLE]) {
5469 struct nft_flowtable_filter *filter;
5470
5471 filter = nft_flowtable_filter_alloc(nla);
5472 if (IS_ERR(filter))
5473 return -ENOMEM;
5474
5475 c.data = filter;
5476 }
5477 return netlink_dump_start(nlsk, skb, nlh, &c);
5478 }
5479
5480 if (!nla[NFTA_FLOWTABLE_NAME])
5481 return -EINVAL;
5482
cac20fcd
PNA
5483 table = nft_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], family,
5484 genmask);
3b49e2e9
PNA
5485 if (IS_ERR(table))
5486 return PTR_ERR(table);
5487
cac20fcd
PNA
5488 flowtable = nft_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME],
5489 genmask);
03a0120f 5490 if (IS_ERR(flowtable))
3b49e2e9
PNA
5491 return PTR_ERR(flowtable);
5492
5493 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
5494 if (!skb2)
5495 return -ENOMEM;
5496
5497 err = nf_tables_fill_flowtable_info(skb2, net, NETLINK_CB(skb).portid,
5498 nlh->nlmsg_seq,
5499 NFT_MSG_NEWFLOWTABLE, 0, family,
5500 flowtable);
5501 if (err < 0)
5502 goto err;
5503
5504 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
5505err:
5506 kfree_skb(skb2);
5507 return err;
5508}
5509
5510static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
5511 struct nft_flowtable *flowtable,
5512 int event)
5513{
5514 struct sk_buff *skb;
5515 int err;
5516
5517 if (ctx->report &&
5518 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
5519 return;
5520
5521 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
5522 if (skb == NULL)
5523 goto err;
5524
5525 err = nf_tables_fill_flowtable_info(skb, ctx->net, ctx->portid,
5526 ctx->seq, event, 0,
36596dad 5527 ctx->family, flowtable);
3b49e2e9
PNA
5528 if (err < 0) {
5529 kfree_skb(skb);
5530 goto err;
5531 }
5532
5533 nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
5534 ctx->report, GFP_KERNEL);
5535 return;
5536err:
5537 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
5538}
5539
3b49e2e9
PNA
5540static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
5541{
c04a3f73 5542 kfree(flowtable->ops);
3b49e2e9 5543 kfree(flowtable->name);
b408c5b0 5544 flowtable->data.type->free(&flowtable->data);
3b49e2e9
PNA
5545 module_put(flowtable->data.type->owner);
5546}
5547
84d7fce6
PNA
5548static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
5549 u32 portid, u32 seq)
5550{
5551 struct nlmsghdr *nlh;
5552 struct nfgenmsg *nfmsg;
784b4e61 5553 char buf[TASK_COMM_LEN];
dedb67c4 5554 int event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, NFT_MSG_NEWGEN);
84d7fce6
PNA
5555
5556 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), 0);
5557 if (nlh == NULL)
5558 goto nla_put_failure;
5559
5560 nfmsg = nlmsg_data(nlh);
5561 nfmsg->nfgen_family = AF_UNSPEC;
5562 nfmsg->version = NFNETLINK_V0;
5563 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
5564
784b4e61
PS
5565 if (nla_put_be32(skb, NFTA_GEN_ID, htonl(net->nft.base_seq)) ||
5566 nla_put_be32(skb, NFTA_GEN_PROC_PID, htonl(task_pid_nr(current))) ||
5567 nla_put_string(skb, NFTA_GEN_PROC_NAME, get_task_comm(buf, current)))
84d7fce6
PNA
5568 goto nla_put_failure;
5569
053c095a
JB
5570 nlmsg_end(skb, nlh);
5571 return 0;
84d7fce6
PNA
5572
5573nla_put_failure:
5574 nlmsg_trim(skb, nlh);
5575 return -EMSGSIZE;
5576}
5577
3b49e2e9
PNA
5578static void nft_flowtable_event(unsigned long event, struct net_device *dev,
5579 struct nft_flowtable *flowtable)
5580{
5581 int i;
5582
5583 for (i = 0; i < flowtable->ops_len; i++) {
5584 if (flowtable->ops[i].dev != dev)
5585 continue;
5586
5587 nf_unregister_net_hook(dev_net(dev), &flowtable->ops[i]);
d92191aa 5588 flowtable->dev_name[i][0] = '\0';
3b49e2e9
PNA
5589 flowtable->ops[i].dev = NULL;
5590 break;
5591 }
5592}
5593
5594static int nf_tables_flowtable_event(struct notifier_block *this,
5595 unsigned long event, void *ptr)
5596{
5597 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
5598 struct nft_flowtable *flowtable;
5599 struct nft_table *table;
3b49e2e9
PNA
5600
5601 if (event != NETDEV_UNREGISTER)
5602 return 0;
5603
5604 nfnl_lock(NFNL_SUBSYS_NFTABLES);
36596dad
PNA
5605 list_for_each_entry(table, &dev_net(dev)->nft.tables, list) {
5606 list_for_each_entry(flowtable, &table->flowtables, list) {
5607 nft_flowtable_event(event, dev, flowtable);
3b49e2e9
PNA
5608 }
5609 }
5610 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
5611
5612 return NOTIFY_DONE;
5613}
5614
5615static struct notifier_block nf_tables_flowtable_notifier = {
5616 .notifier_call = nf_tables_flowtable_event,
5617};
5618
25e94a99
PNA
5619static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb,
5620 int event)
84d7fce6
PNA
5621{
5622 struct nlmsghdr *nlh = nlmsg_hdr(skb);
5623 struct sk_buff *skb2;
5624 int err;
5625
5626 if (nlmsg_report(nlh) &&
5627 !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
25e94a99 5628 return;
84d7fce6 5629
84d7fce6
PNA
5630 skb2 = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
5631 if (skb2 == NULL)
5632 goto err;
5633
5634 err = nf_tables_fill_gen_info(skb2, net, NETLINK_CB(skb).portid,
5635 nlh->nlmsg_seq);
5636 if (err < 0) {
5637 kfree_skb(skb2);
5638 goto err;
5639 }
5640
25e94a99
PNA
5641 nfnetlink_send(skb2, net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES,
5642 nlmsg_report(nlh), GFP_KERNEL);
5643 return;
84d7fce6 5644err:
25e94a99
PNA
5645 nfnetlink_set_err(net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES,
5646 -ENOBUFS);
84d7fce6
PNA
5647}
5648
7b8002a1
PNA
5649static int nf_tables_getgen(struct net *net, struct sock *nlsk,
5650 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
5651 const struct nlattr * const nla[],
5652 struct netlink_ext_ack *extack)
84d7fce6 5653{
84d7fce6
PNA
5654 struct sk_buff *skb2;
5655 int err;
5656
5657 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
5658 if (skb2 == NULL)
5659 return -ENOMEM;
5660
5661 err = nf_tables_fill_gen_info(skb2, net, NETLINK_CB(skb).portid,
5662 nlh->nlmsg_seq);
5663 if (err < 0)
5664 goto err;
5665
5666 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
5667err:
5668 kfree_skb(skb2);
5669 return err;
5670}
5671
96518518
PM
5672static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
5673 [NFT_MSG_NEWTABLE] = {
55dd6f93 5674 .call_batch = nf_tables_newtable,
96518518
PM
5675 .attr_count = NFTA_TABLE_MAX,
5676 .policy = nft_table_policy,
5677 },
5678 [NFT_MSG_GETTABLE] = {
5679 .call = nf_tables_gettable,
5680 .attr_count = NFTA_TABLE_MAX,
5681 .policy = nft_table_policy,
5682 },
5683 [NFT_MSG_DELTABLE] = {
55dd6f93 5684 .call_batch = nf_tables_deltable,
96518518
PM
5685 .attr_count = NFTA_TABLE_MAX,
5686 .policy = nft_table_policy,
5687 },
5688 [NFT_MSG_NEWCHAIN] = {
91c7b38d 5689 .call_batch = nf_tables_newchain,
96518518
PM
5690 .attr_count = NFTA_CHAIN_MAX,
5691 .policy = nft_chain_policy,
5692 },
5693 [NFT_MSG_GETCHAIN] = {
5694 .call = nf_tables_getchain,
5695 .attr_count = NFTA_CHAIN_MAX,
5696 .policy = nft_chain_policy,
5697 },
5698 [NFT_MSG_DELCHAIN] = {
91c7b38d 5699 .call_batch = nf_tables_delchain,
96518518
PM
5700 .attr_count = NFTA_CHAIN_MAX,
5701 .policy = nft_chain_policy,
5702 },
5703 [NFT_MSG_NEWRULE] = {
0628b123 5704 .call_batch = nf_tables_newrule,
96518518
PM
5705 .attr_count = NFTA_RULE_MAX,
5706 .policy = nft_rule_policy,
5707 },
5708 [NFT_MSG_GETRULE] = {
5709 .call = nf_tables_getrule,
5710 .attr_count = NFTA_RULE_MAX,
5711 .policy = nft_rule_policy,
5712 },
5713 [NFT_MSG_DELRULE] = {
0628b123 5714 .call_batch = nf_tables_delrule,
96518518
PM
5715 .attr_count = NFTA_RULE_MAX,
5716 .policy = nft_rule_policy,
5717 },
20a69341 5718 [NFT_MSG_NEWSET] = {
958bee14 5719 .call_batch = nf_tables_newset,
20a69341
PM
5720 .attr_count = NFTA_SET_MAX,
5721 .policy = nft_set_policy,
5722 },
5723 [NFT_MSG_GETSET] = {
5724 .call = nf_tables_getset,
5725 .attr_count = NFTA_SET_MAX,
5726 .policy = nft_set_policy,
5727 },
5728 [NFT_MSG_DELSET] = {
958bee14 5729 .call_batch = nf_tables_delset,
20a69341
PM
5730 .attr_count = NFTA_SET_MAX,
5731 .policy = nft_set_policy,
5732 },
5733 [NFT_MSG_NEWSETELEM] = {
958bee14 5734 .call_batch = nf_tables_newsetelem,
20a69341
PM
5735 .attr_count = NFTA_SET_ELEM_LIST_MAX,
5736 .policy = nft_set_elem_list_policy,
5737 },
5738 [NFT_MSG_GETSETELEM] = {
5739 .call = nf_tables_getsetelem,
5740 .attr_count = NFTA_SET_ELEM_LIST_MAX,
5741 .policy = nft_set_elem_list_policy,
5742 },
5743 [NFT_MSG_DELSETELEM] = {
958bee14 5744 .call_batch = nf_tables_delsetelem,
20a69341
PM
5745 .attr_count = NFTA_SET_ELEM_LIST_MAX,
5746 .policy = nft_set_elem_list_policy,
5747 },
84d7fce6
PNA
5748 [NFT_MSG_GETGEN] = {
5749 .call = nf_tables_getgen,
5750 },
e5009240
PNA
5751 [NFT_MSG_NEWOBJ] = {
5752 .call_batch = nf_tables_newobj,
5753 .attr_count = NFTA_OBJ_MAX,
5754 .policy = nft_obj_policy,
5755 },
5756 [NFT_MSG_GETOBJ] = {
5757 .call = nf_tables_getobj,
5758 .attr_count = NFTA_OBJ_MAX,
5759 .policy = nft_obj_policy,
5760 },
5761 [NFT_MSG_DELOBJ] = {
5762 .call_batch = nf_tables_delobj,
5763 .attr_count = NFTA_OBJ_MAX,
5764 .policy = nft_obj_policy,
5765 },
43da04a5
PNA
5766 [NFT_MSG_GETOBJ_RESET] = {
5767 .call = nf_tables_getobj,
5768 .attr_count = NFTA_OBJ_MAX,
5769 .policy = nft_obj_policy,
5770 },
3b49e2e9
PNA
5771 [NFT_MSG_NEWFLOWTABLE] = {
5772 .call_batch = nf_tables_newflowtable,
5773 .attr_count = NFTA_FLOWTABLE_MAX,
5774 .policy = nft_flowtable_policy,
5775 },
5776 [NFT_MSG_GETFLOWTABLE] = {
5777 .call = nf_tables_getflowtable,
5778 .attr_count = NFTA_FLOWTABLE_MAX,
5779 .policy = nft_flowtable_policy,
5780 },
5781 [NFT_MSG_DELFLOWTABLE] = {
5782 .call_batch = nf_tables_delflowtable,
5783 .attr_count = NFTA_FLOWTABLE_MAX,
5784 .policy = nft_flowtable_policy,
5785 },
96518518
PM
5786};
5787
91c7b38d
PNA
5788static void nft_chain_commit_update(struct nft_trans *trans)
5789{
5790 struct nft_base_chain *basechain;
5791
b7263e07 5792 if (nft_trans_chain_name(trans))
d71efb59 5793 swap(trans->ctx.chain->name, nft_trans_chain_name(trans));
91c7b38d 5794
f323d954 5795 if (!nft_is_base_chain(trans->ctx.chain))
91c7b38d
PNA
5796 return;
5797
5798 basechain = nft_base_chain(trans->ctx.chain);
5799 nft_chain_stats_replace(basechain, nft_trans_chain_stats(trans));
5800
5801 switch (nft_trans_chain_policy(trans)) {
5802 case NF_DROP:
5803 case NF_ACCEPT:
5804 basechain->policy = nft_trans_chain_policy(trans);
5805 break;
5806 }
5807}
5808
2f99aa31 5809static void nft_commit_release(struct nft_trans *trans)
c7c32e72 5810{
c7c32e72
PNA
5811 switch (trans->msg_type) {
5812 case NFT_MSG_DELTABLE:
5813 nf_tables_table_destroy(&trans->ctx);
5814 break;
5815 case NFT_MSG_DELCHAIN:
43a605f2 5816 nf_tables_chain_destroy(&trans->ctx);
c7c32e72
PNA
5817 break;
5818 case NFT_MSG_DELRULE:
5819 nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
5820 break;
5821 case NFT_MSG_DELSET:
5822 nft_set_destroy(nft_trans_set(trans));
5823 break;
61edafbb 5824 case NFT_MSG_DELSETELEM:
59105446
PNA
5825 nf_tables_set_elem_destroy(nft_trans_elem_set(trans),
5826 nft_trans_elem(trans).priv);
61edafbb 5827 break;
e5009240
PNA
5828 case NFT_MSG_DELOBJ:
5829 nft_obj_destroy(nft_trans_obj(trans));
5830 break;
3b49e2e9
PNA
5831 case NFT_MSG_DELFLOWTABLE:
5832 nf_tables_flowtable_destroy(nft_trans_flowtable(trans));
5833 break;
c7c32e72
PNA
5834 }
5835 kfree(trans);
5836}
5837
2f99aa31
FW
5838static void nf_tables_commit_release(struct net *net)
5839{
5840 struct nft_trans *trans, *next;
5841
5842 if (list_empty(&net->nft.commit_list))
5843 return;
5844
5845 synchronize_rcu();
5846
5847 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
5848 list_del(&trans->list);
5849 nft_commit_release(trans);
5850 }
5851}
5852
5913beaf 5853static int nf_tables_commit(struct net *net, struct sk_buff *skb)
37082f93 5854{
37082f93 5855 struct nft_trans *trans, *next;
a3716e70 5856 struct nft_trans_elem *te;
37082f93
PNA
5857
5858 /* Bump generation counter, invalidate any dump in progress */
38e029f1 5859 while (++net->nft.base_seq == 0);
37082f93
PNA
5860
5861 /* A new generation has just started */
ea4bd995 5862 net->nft.gencursor = nft_gencursor_next(net);
37082f93
PNA
5863
5864 /* Make sure all packets have left the previous generation before
5865 * purging old rules.
5866 */
5867 synchronize_rcu();
5868
5869 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
b380e5c7 5870 switch (trans->msg_type) {
55dd6f93
PNA
5871 case NFT_MSG_NEWTABLE:
5872 if (nft_trans_table_update(trans)) {
5873 if (!nft_trans_table_enable(trans)) {
664b0f8c 5874 nf_tables_table_disable(net,
55dd6f93
PNA
5875 trans->ctx.table);
5876 trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
5877 }
5878 } else {
f2a6d766 5879 nft_clear(net, trans->ctx.table);
55dd6f93 5880 }
35151d84 5881 nf_tables_table_notify(&trans->ctx, NFT_MSG_NEWTABLE);
55dd6f93
PNA
5882 nft_trans_destroy(trans);
5883 break;
5884 case NFT_MSG_DELTABLE:
f2a6d766 5885 list_del_rcu(&trans->ctx.table->list);
35151d84 5886 nf_tables_table_notify(&trans->ctx, NFT_MSG_DELTABLE);
55dd6f93 5887 break;
91c7b38d
PNA
5888 case NFT_MSG_NEWCHAIN:
5889 if (nft_trans_chain_update(trans))
5890 nft_chain_commit_update(trans);
4fefee57 5891 else
664b0f8c 5892 nft_clear(net, trans->ctx.chain);
4fefee57 5893
35151d84 5894 nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
91c7b38d
PNA
5895 nft_trans_destroy(trans);
5896 break;
5897 case NFT_MSG_DELCHAIN:
664b0f8c 5898 list_del_rcu(&trans->ctx.chain->list);
35151d84 5899 nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN);
c974a3a3
PNA
5900 nf_tables_unregister_hook(trans->ctx.net,
5901 trans->ctx.table,
5902 trans->ctx.chain);
91c7b38d 5903 break;
b380e5c7 5904 case NFT_MSG_NEWRULE:
889f7ee7 5905 nft_clear(trans->ctx.net, nft_trans_rule(trans));
35151d84 5906 nf_tables_rule_notify(&trans->ctx,
37082f93 5907 nft_trans_rule(trans),
35151d84 5908 NFT_MSG_NEWRULE);
37082f93 5909 nft_trans_destroy(trans);
b380e5c7
PNA
5910 break;
5911 case NFT_MSG_DELRULE:
5912 list_del_rcu(&nft_trans_rule(trans)->list);
35151d84
PNA
5913 nf_tables_rule_notify(&trans->ctx,
5914 nft_trans_rule(trans),
5915 NFT_MSG_DELRULE);
b380e5c7 5916 break;
958bee14 5917 case NFT_MSG_NEWSET:
37a9cc52 5918 nft_clear(net, nft_trans_set(trans));
4fefee57
PNA
5919 /* This avoids hitting -EBUSY when deleting the table
5920 * from the transaction.
5921 */
408070d6 5922 if (nft_set_is_anonymous(nft_trans_set(trans)) &&
4fefee57
PNA
5923 !list_empty(&nft_trans_set(trans)->bindings))
5924 trans->ctx.table->use--;
5925
958bee14 5926 nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
31f8441c 5927 NFT_MSG_NEWSET, GFP_KERNEL);
958bee14
PNA
5928 nft_trans_destroy(trans);
5929 break;
5930 case NFT_MSG_DELSET:
37a9cc52 5931 list_del_rcu(&nft_trans_set(trans)->list);
958bee14 5932 nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
31f8441c 5933 NFT_MSG_DELSET, GFP_KERNEL);
958bee14 5934 break;
60319eb1 5935 case NFT_MSG_NEWSETELEM:
cc02e457
PM
5936 te = (struct nft_trans_elem *)trans->data;
5937
42a55769 5938 te->set->ops->activate(net, te->set, &te->elem);
cc02e457
PM
5939 nf_tables_setelem_notify(&trans->ctx, te->set,
5940 &te->elem,
60319eb1
PNA
5941 NFT_MSG_NEWSETELEM, 0);
5942 nft_trans_destroy(trans);
5943 break;
5944 case NFT_MSG_DELSETELEM:
a3716e70 5945 te = (struct nft_trans_elem *)trans->data;
fe2811eb 5946
a3716e70
PNA
5947 nf_tables_setelem_notify(&trans->ctx, te->set,
5948 &te->elem,
60319eb1 5949 NFT_MSG_DELSETELEM, 0);
5cb82a38 5950 te->set->ops->remove(net, te->set, &te->elem);
3dd0673a
PM
5951 atomic_dec(&te->set->nelems);
5952 te->set->ndeact--;
60319eb1 5953 break;
e5009240
PNA
5954 case NFT_MSG_NEWOBJ:
5955 nft_clear(net, nft_trans_obj(trans));
5956 nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans),
5957 NFT_MSG_NEWOBJ);
5958 nft_trans_destroy(trans);
5959 break;
5960 case NFT_MSG_DELOBJ:
5961 list_del_rcu(&nft_trans_obj(trans)->list);
5962 nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans),
5963 NFT_MSG_DELOBJ);
5964 break;
3b49e2e9
PNA
5965 case NFT_MSG_NEWFLOWTABLE:
5966 nft_clear(net, nft_trans_flowtable(trans));
5967 nf_tables_flowtable_notify(&trans->ctx,
5968 nft_trans_flowtable(trans),
5969 NFT_MSG_NEWFLOWTABLE);
5970 nft_trans_destroy(trans);
5971 break;
5972 case NFT_MSG_DELFLOWTABLE:
5973 list_del_rcu(&nft_trans_flowtable(trans)->list);
5974 nf_tables_flowtable_notify(&trans->ctx,
5975 nft_trans_flowtable(trans),
5976 NFT_MSG_DELFLOWTABLE);
5977 nft_unregister_flowtable_net_hooks(net,
5978 nft_trans_flowtable(trans));
5979 break;
37082f93 5980 }
37082f93
PNA
5981 }
5982
2f99aa31 5983 nf_tables_commit_release(net);
84d7fce6 5984 nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
37082f93
PNA
5985
5986 return 0;
5987}
5988
b326dd37 5989static void nf_tables_abort_release(struct nft_trans *trans)
c7c32e72 5990{
c7c32e72
PNA
5991 switch (trans->msg_type) {
5992 case NFT_MSG_NEWTABLE:
5993 nf_tables_table_destroy(&trans->ctx);
5994 break;
5995 case NFT_MSG_NEWCHAIN:
43a605f2 5996 nf_tables_chain_destroy(&trans->ctx);
c7c32e72
PNA
5997 break;
5998 case NFT_MSG_NEWRULE:
5999 nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
6000 break;
6001 case NFT_MSG_NEWSET:
6002 nft_set_destroy(nft_trans_set(trans));
6003 break;
61edafbb
PM
6004 case NFT_MSG_NEWSETELEM:
6005 nft_set_elem_destroy(nft_trans_elem_set(trans),
61f9e292 6006 nft_trans_elem(trans).priv, true);
61edafbb 6007 break;
e5009240
PNA
6008 case NFT_MSG_NEWOBJ:
6009 nft_obj_destroy(nft_trans_obj(trans));
6010 break;
3b49e2e9
PNA
6011 case NFT_MSG_NEWFLOWTABLE:
6012 nf_tables_flowtable_destroy(nft_trans_flowtable(trans));
6013 break;
c7c32e72
PNA
6014 }
6015 kfree(trans);
6016}
6017
5913beaf 6018static int nf_tables_abort(struct net *net, struct sk_buff *skb)
37082f93 6019{
37082f93 6020 struct nft_trans *trans, *next;
02263db0 6021 struct nft_trans_elem *te;
37082f93 6022
a907e36d
XL
6023 list_for_each_entry_safe_reverse(trans, next, &net->nft.commit_list,
6024 list) {
b380e5c7 6025 switch (trans->msg_type) {
55dd6f93
PNA
6026 case NFT_MSG_NEWTABLE:
6027 if (nft_trans_table_update(trans)) {
6028 if (nft_trans_table_enable(trans)) {
664b0f8c 6029 nf_tables_table_disable(net,
55dd6f93
PNA
6030 trans->ctx.table);
6031 trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
6032 }
6033 nft_trans_destroy(trans);
6034 } else {
e688a7f8 6035 list_del_rcu(&trans->ctx.table->list);
55dd6f93
PNA
6036 }
6037 break;
6038 case NFT_MSG_DELTABLE:
f2a6d766 6039 nft_clear(trans->ctx.net, trans->ctx.table);
55dd6f93
PNA
6040 nft_trans_destroy(trans);
6041 break;
91c7b38d
PNA
6042 case NFT_MSG_NEWCHAIN:
6043 if (nft_trans_chain_update(trans)) {
982f4051 6044 free_percpu(nft_trans_chain_stats(trans));
91c7b38d
PNA
6045
6046 nft_trans_destroy(trans);
6047 } else {
4fefee57 6048 trans->ctx.table->use--;
e688a7f8 6049 list_del_rcu(&trans->ctx.chain->list);
c974a3a3
PNA
6050 nf_tables_unregister_hook(trans->ctx.net,
6051 trans->ctx.table,
6052 trans->ctx.chain);
91c7b38d
PNA
6053 }
6054 break;
6055 case NFT_MSG_DELCHAIN:
4fefee57 6056 trans->ctx.table->use++;
664b0f8c 6057 nft_clear(trans->ctx.net, trans->ctx.chain);
91c7b38d
PNA
6058 nft_trans_destroy(trans);
6059 break;
b380e5c7 6060 case NFT_MSG_NEWRULE:
4fefee57 6061 trans->ctx.chain->use--;
b380e5c7 6062 list_del_rcu(&nft_trans_rule(trans)->list);
bb7b40ae 6063 nft_rule_expr_deactivate(&trans->ctx, nft_trans_rule(trans));
b380e5c7
PNA
6064 break;
6065 case NFT_MSG_DELRULE:
4fefee57 6066 trans->ctx.chain->use++;
889f7ee7 6067 nft_clear(trans->ctx.net, nft_trans_rule(trans));
bb7b40ae 6068 nft_rule_expr_activate(&trans->ctx, nft_trans_rule(trans));
37082f93 6069 nft_trans_destroy(trans);
b380e5c7 6070 break;
958bee14 6071 case NFT_MSG_NEWSET:
4fefee57 6072 trans->ctx.table->use--;
e688a7f8 6073 list_del_rcu(&nft_trans_set(trans)->list);
958bee14
PNA
6074 break;
6075 case NFT_MSG_DELSET:
4fefee57 6076 trans->ctx.table->use++;
37a9cc52 6077 nft_clear(trans->ctx.net, nft_trans_set(trans));
958bee14
PNA
6078 nft_trans_destroy(trans);
6079 break;
60319eb1 6080 case NFT_MSG_NEWSETELEM:
02263db0 6081 te = (struct nft_trans_elem *)trans->data;
fe2811eb 6082
5cb82a38 6083 te->set->ops->remove(net, te->set, &te->elem);
3dd0673a 6084 atomic_dec(&te->set->nelems);
60319eb1
PNA
6085 break;
6086 case NFT_MSG_DELSETELEM:
cc02e457
PM
6087 te = (struct nft_trans_elem *)trans->data;
6088
59105446 6089 nft_set_elem_activate(net, te->set, &te->elem);
42a55769 6090 te->set->ops->activate(net, te->set, &te->elem);
3dd0673a 6091 te->set->ndeact--;
cc02e457 6092
e5009240
PNA
6093 nft_trans_destroy(trans);
6094 break;
6095 case NFT_MSG_NEWOBJ:
6096 trans->ctx.table->use--;
6097 list_del_rcu(&nft_trans_obj(trans)->list);
6098 break;
6099 case NFT_MSG_DELOBJ:
6100 trans->ctx.table->use++;
6101 nft_clear(trans->ctx.net, nft_trans_obj(trans));
60319eb1
PNA
6102 nft_trans_destroy(trans);
6103 break;
3b49e2e9
PNA
6104 case NFT_MSG_NEWFLOWTABLE:
6105 trans->ctx.table->use--;
6106 list_del_rcu(&nft_trans_flowtable(trans)->list);
6107 nft_unregister_flowtable_net_hooks(net,
6108 nft_trans_flowtable(trans));
6109 break;
6110 case NFT_MSG_DELFLOWTABLE:
6111 trans->ctx.table->use++;
6112 nft_clear(trans->ctx.net, nft_trans_flowtable(trans));
6113 nft_trans_destroy(trans);
6114 break;
37082f93 6115 }
37082f93
PNA
6116 }
6117
b326dd37
PNA
6118 synchronize_rcu();
6119
a1cee076
PNA
6120 list_for_each_entry_safe_reverse(trans, next,
6121 &net->nft.commit_list, list) {
c7c32e72 6122 list_del(&trans->list);
b326dd37 6123 nf_tables_abort_release(trans);
37082f93
PNA
6124 }
6125
6126 return 0;
6127}
6128
74e8bcd2
PNA
6129static bool nf_tables_valid_genid(struct net *net, u32 genid)
6130{
6131 return net->nft.base_seq == genid;
6132}
6133
96518518
PM
6134static const struct nfnetlink_subsystem nf_tables_subsys = {
6135 .name = "nf_tables",
6136 .subsys_id = NFNL_SUBSYS_NFTABLES,
6137 .cb_count = NFT_MSG_MAX,
6138 .cb = nf_tables_cb,
0628b123
PNA
6139 .commit = nf_tables_commit,
6140 .abort = nf_tables_abort,
74e8bcd2 6141 .valid_genid = nf_tables_valid_genid,
96518518
PM
6142};
6143
7210e4e3 6144int nft_chain_validate_dependency(const struct nft_chain *chain,
32537e91 6145 enum nft_chain_types type)
7210e4e3
PNA
6146{
6147 const struct nft_base_chain *basechain;
6148
f323d954 6149 if (nft_is_base_chain(chain)) {
7210e4e3
PNA
6150 basechain = nft_base_chain(chain);
6151 if (basechain->type->type != type)
6152 return -EOPNOTSUPP;
6153 }
6154 return 0;
6155}
6156EXPORT_SYMBOL_GPL(nft_chain_validate_dependency);
6157
75e8d06d
PNA
6158int nft_chain_validate_hooks(const struct nft_chain *chain,
6159 unsigned int hook_flags)
6160{
6161 struct nft_base_chain *basechain;
6162
f323d954 6163 if (nft_is_base_chain(chain)) {
75e8d06d
PNA
6164 basechain = nft_base_chain(chain);
6165
c974a3a3 6166 if ((1 << basechain->ops.hooknum) & hook_flags)
75e8d06d
PNA
6167 return 0;
6168
6169 return -EOPNOTSUPP;
6170 }
6171
6172 return 0;
6173}
6174EXPORT_SYMBOL_GPL(nft_chain_validate_hooks);
6175
20a69341
PM
6176/*
6177 * Loop detection - walk through the ruleset beginning at the destination chain
6178 * of a new jump until either the source chain is reached (loop) or all
6179 * reachable chains have been traversed.
6180 *
6181 * The loop check is performed whenever a new jump verdict is added to an
6182 * expression or verdict map or a verdict map is bound to a new chain.
6183 */
6184
6185static int nf_tables_check_loops(const struct nft_ctx *ctx,
6186 const struct nft_chain *chain);
6187
6188static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx,
de70185d 6189 struct nft_set *set,
20a69341 6190 const struct nft_set_iter *iter,
de70185d 6191 struct nft_set_elem *elem)
20a69341 6192{
fe2811eb
PM
6193 const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
6194 const struct nft_data *data;
6195
6196 if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
6197 *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
62f9c8b4
PNA
6198 return 0;
6199
fe2811eb 6200 data = nft_set_ext_data(ext);
1ca2e170 6201 switch (data->verdict.code) {
20a69341
PM
6202 case NFT_JUMP:
6203 case NFT_GOTO:
1ca2e170 6204 return nf_tables_check_loops(ctx, data->verdict.chain);
20a69341
PM
6205 default:
6206 return 0;
6207 }
6208}
6209
6210static int nf_tables_check_loops(const struct nft_ctx *ctx,
6211 const struct nft_chain *chain)
6212{
6213 const struct nft_rule *rule;
6214 const struct nft_expr *expr, *last;
de70185d 6215 struct nft_set *set;
20a69341
PM
6216 struct nft_set_binding *binding;
6217 struct nft_set_iter iter;
20a69341
PM
6218
6219 if (ctx->chain == chain)
6220 return -ELOOP;
6221
6222 list_for_each_entry(rule, &chain->rules, list) {
6223 nft_rule_for_each_expr(expr, last, rule) {
0ca743a5
PNA
6224 const struct nft_data *data = NULL;
6225 int err;
6226
6227 if (!expr->ops->validate)
20a69341
PM
6228 continue;
6229
0ca743a5
PNA
6230 err = expr->ops->validate(ctx, expr, &data);
6231 if (err < 0)
6232 return err;
6233
20a69341 6234 if (data == NULL)
0ca743a5 6235 continue;
20a69341 6236
1ca2e170 6237 switch (data->verdict.code) {
20a69341
PM
6238 case NFT_JUMP:
6239 case NFT_GOTO:
1ca2e170
PM
6240 err = nf_tables_check_loops(ctx,
6241 data->verdict.chain);
20a69341
PM
6242 if (err < 0)
6243 return err;
6244 default:
6245 break;
6246 }
6247 }
6248 }
6249
6250 list_for_each_entry(set, &ctx->table->sets, list) {
37a9cc52
PNA
6251 if (!nft_is_active_next(ctx->net, set))
6252 continue;
20a69341
PM
6253 if (!(set->flags & NFT_SET_MAP) ||
6254 set->dtype != NFT_DATA_VERDICT)
6255 continue;
6256
6257 list_for_each_entry(binding, &set->bindings, list) {
11113e19
PM
6258 if (!(binding->flags & NFT_SET_MAP) ||
6259 binding->chain != chain)
20a69341
PM
6260 continue;
6261
8588ac09 6262 iter.genmask = nft_genmask_next(ctx->net);
20a69341
PM
6263 iter.skip = 0;
6264 iter.count = 0;
6265 iter.err = 0;
6266 iter.fn = nf_tables_loop_check_setelem;
6267
6268 set->ops->walk(ctx, set, &iter);
6269 if (iter.err < 0)
6270 return iter.err;
6271 }
6272 }
6273
6274 return 0;
6275}
6276
36b701fa
LGL
6277/**
6278 * nft_parse_u32_check - fetch u32 attribute and check for maximum value
6279 *
6280 * @attr: netlink attribute to fetch value from
6281 * @max: maximum value to be stored in dest
6282 * @dest: pointer to the variable
6283 *
6284 * Parse, check and store a given u32 netlink attribute into variable.
6285 * This function returns -ERANGE if the value goes over maximum value.
6286 * Otherwise a 0 is returned and the attribute value is stored in the
6287 * destination variable.
6288 */
f1d505bb 6289int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest)
36b701fa 6290{
09525a09 6291 u32 val;
36b701fa
LGL
6292
6293 val = ntohl(nla_get_be32(attr));
6294 if (val > max)
6295 return -ERANGE;
6296
6297 *dest = val;
6298 return 0;
6299}
6300EXPORT_SYMBOL_GPL(nft_parse_u32_check);
6301
49499c3e
PM
6302/**
6303 * nft_parse_register - parse a register value from a netlink attribute
6304 *
6305 * @attr: netlink attribute
6306 *
6307 * Parse and translate a register value from a netlink attribute.
6308 * Registers used to be 128 bit wide, these register numbers will be
6309 * mapped to the corresponding 32 bit register numbers.
6310 */
b1c96ed3
PM
6311unsigned int nft_parse_register(const struct nlattr *attr)
6312{
49499c3e
PM
6313 unsigned int reg;
6314
6315 reg = ntohl(nla_get_be32(attr));
6316 switch (reg) {
6317 case NFT_REG_VERDICT...NFT_REG_4:
6318 return reg * NFT_REG_SIZE / NFT_REG32_SIZE;
6319 default:
6320 return reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00;
6321 }
b1c96ed3
PM
6322}
6323EXPORT_SYMBOL_GPL(nft_parse_register);
6324
49499c3e
PM
6325/**
6326 * nft_dump_register - dump a register value to a netlink attribute
6327 *
6328 * @skb: socket buffer
6329 * @attr: attribute number
6330 * @reg: register number
6331 *
6332 * Construct a netlink attribute containing the register number. For
6333 * compatibility reasons, register numbers being a multiple of 4 are
6334 * translated to the corresponding 128 bit register numbers.
6335 */
b1c96ed3
PM
6336int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg)
6337{
49499c3e
PM
6338 if (reg % (NFT_REG_SIZE / NFT_REG32_SIZE) == 0)
6339 reg = reg / (NFT_REG_SIZE / NFT_REG32_SIZE);
6340 else
6341 reg = reg - NFT_REG_SIZE / NFT_REG32_SIZE + NFT_REG32_00;
6342
b1c96ed3
PM
6343 return nla_put_be32(skb, attr, htonl(reg));
6344}
6345EXPORT_SYMBOL_GPL(nft_dump_register);
6346
96518518 6347/**
d07db988 6348 * nft_validate_register_load - validate a load from a register
96518518
PM
6349 *
6350 * @reg: the register number
d07db988 6351 * @len: the length of the data
96518518
PM
6352 *
6353 * Validate that the input register is one of the general purpose
d07db988 6354 * registers and that the length of the load is within the bounds.
96518518 6355 */
d07db988 6356int nft_validate_register_load(enum nft_registers reg, unsigned int len)
96518518 6357{
49499c3e 6358 if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE)
96518518 6359 return -EINVAL;
d07db988
PM
6360 if (len == 0)
6361 return -EINVAL;
49499c3e 6362 if (reg * NFT_REG32_SIZE + len > FIELD_SIZEOF(struct nft_regs, data))
d07db988 6363 return -ERANGE;
49499c3e 6364
96518518
PM
6365 return 0;
6366}
d07db988 6367EXPORT_SYMBOL_GPL(nft_validate_register_load);
96518518 6368
96518518 6369/**
1ec10212 6370 * nft_validate_register_store - validate an expressions' register store
96518518
PM
6371 *
6372 * @ctx: context of the expression performing the load
6373 * @reg: the destination register number
6374 * @data: the data to load
6375 * @type: the data type
45d9bcda 6376 * @len: the length of the data
96518518
PM
6377 *
6378 * Validate that a data load uses the appropriate data type for
45d9bcda
PM
6379 * the destination register and the length is within the bounds.
6380 * A value of NULL for the data means that its runtime gathered
58f40ab6 6381 * data.
96518518 6382 */
1ec10212
PM
6383int nft_validate_register_store(const struct nft_ctx *ctx,
6384 enum nft_registers reg,
6385 const struct nft_data *data,
6386 enum nft_data_types type, unsigned int len)
96518518 6387{
20a69341
PM
6388 int err;
6389
96518518
PM
6390 switch (reg) {
6391 case NFT_REG_VERDICT:
58f40ab6 6392 if (type != NFT_DATA_VERDICT)
96518518 6393 return -EINVAL;
20a69341 6394
58f40ab6 6395 if (data != NULL &&
1ca2e170
PM
6396 (data->verdict.code == NFT_GOTO ||
6397 data->verdict.code == NFT_JUMP)) {
6398 err = nf_tables_check_loops(ctx, data->verdict.chain);
20a69341
PM
6399 if (err < 0)
6400 return err;
6401
1ca2e170
PM
6402 if (ctx->chain->level + 1 >
6403 data->verdict.chain->level) {
20a69341
PM
6404 if (ctx->chain->level + 1 == NFT_JUMP_STACK_SIZE)
6405 return -EMLINK;
1ca2e170 6406 data->verdict.chain->level = ctx->chain->level + 1;
20a69341
PM
6407 }
6408 }
6409
96518518
PM
6410 return 0;
6411 default:
49499c3e 6412 if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE)
27e6d201 6413 return -EINVAL;
45d9bcda
PM
6414 if (len == 0)
6415 return -EINVAL;
49499c3e
PM
6416 if (reg * NFT_REG32_SIZE + len >
6417 FIELD_SIZEOF(struct nft_regs, data))
45d9bcda 6418 return -ERANGE;
27e6d201 6419
96518518
PM
6420 if (data != NULL && type != NFT_DATA_VALUE)
6421 return -EINVAL;
6422 return 0;
6423 }
6424}
1ec10212 6425EXPORT_SYMBOL_GPL(nft_validate_register_store);
96518518
PM
6426
6427static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = {
6428 [NFTA_VERDICT_CODE] = { .type = NLA_U32 },
6429 [NFTA_VERDICT_CHAIN] = { .type = NLA_STRING,
6430 .len = NFT_CHAIN_MAXNAMELEN - 1 },
6431};
6432
6433static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
6434 struct nft_data_desc *desc, const struct nlattr *nla)
6435{
664b0f8c 6436 u8 genmask = nft_genmask_next(ctx->net);
96518518
PM
6437 struct nlattr *tb[NFTA_VERDICT_MAX + 1];
6438 struct nft_chain *chain;
6439 int err;
6440
fceb6435
JB
6441 err = nla_parse_nested(tb, NFTA_VERDICT_MAX, nla, nft_verdict_policy,
6442 NULL);
96518518
PM
6443 if (err < 0)
6444 return err;
6445
6446 if (!tb[NFTA_VERDICT_CODE])
6447 return -EINVAL;
1ca2e170 6448 data->verdict.code = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE]));
96518518 6449
1ca2e170 6450 switch (data->verdict.code) {
e0abdadc 6451 default:
1ca2e170 6452 switch (data->verdict.code & NF_VERDICT_MASK) {
e0abdadc
PM
6453 case NF_ACCEPT:
6454 case NF_DROP:
6455 case NF_QUEUE:
6456 break;
6457 default:
6458 return -EINVAL;
6459 }
6460 /* fall through */
96518518
PM
6461 case NFT_CONTINUE:
6462 case NFT_BREAK:
6463 case NFT_RETURN:
96518518
PM
6464 break;
6465 case NFT_JUMP:
6466 case NFT_GOTO:
6467 if (!tb[NFTA_VERDICT_CHAIN])
6468 return -EINVAL;
cac20fcd
PNA
6469 chain = nft_chain_lookup(ctx->table, tb[NFTA_VERDICT_CHAIN],
6470 genmask);
96518518
PM
6471 if (IS_ERR(chain))
6472 return PTR_ERR(chain);
f323d954 6473 if (nft_is_base_chain(chain))
96518518
PM
6474 return -EOPNOTSUPP;
6475
96518518 6476 chain->use++;
1ca2e170 6477 data->verdict.chain = chain;
96518518 6478 break;
96518518
PM
6479 }
6480
4c4ed074 6481 desc->len = sizeof(data->verdict);
96518518
PM
6482 desc->type = NFT_DATA_VERDICT;
6483 return 0;
6484}
6485
6486static void nft_verdict_uninit(const struct nft_data *data)
6487{
1ca2e170 6488 switch (data->verdict.code) {
96518518
PM
6489 case NFT_JUMP:
6490 case NFT_GOTO:
1ca2e170 6491 data->verdict.chain->use--;
96518518
PM
6492 break;
6493 }
6494}
6495
33d5a7b1 6496int nft_verdict_dump(struct sk_buff *skb, int type, const struct nft_verdict *v)
96518518
PM
6497{
6498 struct nlattr *nest;
6499
33d5a7b1 6500 nest = nla_nest_start(skb, type);
96518518
PM
6501 if (!nest)
6502 goto nla_put_failure;
6503
33d5a7b1 6504 if (nla_put_be32(skb, NFTA_VERDICT_CODE, htonl(v->code)))
96518518
PM
6505 goto nla_put_failure;
6506
33d5a7b1 6507 switch (v->code) {
96518518
PM
6508 case NFT_JUMP:
6509 case NFT_GOTO:
1ca2e170 6510 if (nla_put_string(skb, NFTA_VERDICT_CHAIN,
33d5a7b1 6511 v->chain->name))
96518518
PM
6512 goto nla_put_failure;
6513 }
6514 nla_nest_end(skb, nest);
6515 return 0;
6516
6517nla_put_failure:
6518 return -1;
6519}
6520
d0a11fc3
PM
6521static int nft_value_init(const struct nft_ctx *ctx,
6522 struct nft_data *data, unsigned int size,
96518518
PM
6523 struct nft_data_desc *desc, const struct nlattr *nla)
6524{
6525 unsigned int len;
6526
6527 len = nla_len(nla);
6528 if (len == 0)
6529 return -EINVAL;
d0a11fc3 6530 if (len > size)
96518518
PM
6531 return -EOVERFLOW;
6532
d0a11fc3 6533 nla_memcpy(data->data, nla, len);
96518518
PM
6534 desc->type = NFT_DATA_VALUE;
6535 desc->len = len;
6536 return 0;
6537}
6538
6539static int nft_value_dump(struct sk_buff *skb, const struct nft_data *data,
6540 unsigned int len)
6541{
6542 return nla_put(skb, NFTA_DATA_VALUE, len, data->data);
6543}
6544
6545static const struct nla_policy nft_data_policy[NFTA_DATA_MAX + 1] = {
d0a11fc3 6546 [NFTA_DATA_VALUE] = { .type = NLA_BINARY },
96518518
PM
6547 [NFTA_DATA_VERDICT] = { .type = NLA_NESTED },
6548};
6549
6550/**
6551 * nft_data_init - parse nf_tables data netlink attributes
6552 *
6553 * @ctx: context of the expression using the data
6554 * @data: destination struct nft_data
d0a11fc3 6555 * @size: maximum data length
96518518
PM
6556 * @desc: data description
6557 * @nla: netlink attribute containing data
6558 *
6559 * Parse the netlink data attributes and initialize a struct nft_data.
6560 * The type and length of data are returned in the data description.
6561 *
6562 * The caller can indicate that it only wants to accept data of type
6563 * NFT_DATA_VALUE by passing NULL for the ctx argument.
6564 */
d0a11fc3
PM
6565int nft_data_init(const struct nft_ctx *ctx,
6566 struct nft_data *data, unsigned int size,
96518518
PM
6567 struct nft_data_desc *desc, const struct nlattr *nla)
6568{
6569 struct nlattr *tb[NFTA_DATA_MAX + 1];
6570 int err;
6571
fceb6435 6572 err = nla_parse_nested(tb, NFTA_DATA_MAX, nla, nft_data_policy, NULL);
96518518
PM
6573 if (err < 0)
6574 return err;
6575
6576 if (tb[NFTA_DATA_VALUE])
d0a11fc3
PM
6577 return nft_value_init(ctx, data, size, desc,
6578 tb[NFTA_DATA_VALUE]);
96518518
PM
6579 if (tb[NFTA_DATA_VERDICT] && ctx != NULL)
6580 return nft_verdict_init(ctx, data, desc, tb[NFTA_DATA_VERDICT]);
6581 return -EINVAL;
6582}
6583EXPORT_SYMBOL_GPL(nft_data_init);
6584
6585/**
59105446 6586 * nft_data_release - release a nft_data item
96518518
PM
6587 *
6588 * @data: struct nft_data to release
6589 * @type: type of data
6590 *
6591 * Release a nft_data item. NFT_DATA_VALUE types can be silently discarded,
6592 * all others need to be released by calling this function.
6593 */
59105446 6594void nft_data_release(const struct nft_data *data, enum nft_data_types type)
96518518 6595{
960bd2c2 6596 if (type < NFT_DATA_VERDICT)
96518518 6597 return;
960bd2c2 6598 switch (type) {
96518518
PM
6599 case NFT_DATA_VERDICT:
6600 return nft_verdict_uninit(data);
6601 default:
6602 WARN_ON(1);
6603 }
6604}
59105446 6605EXPORT_SYMBOL_GPL(nft_data_release);
96518518
PM
6606
6607int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
6608 enum nft_data_types type, unsigned int len)
6609{
6610 struct nlattr *nest;
6611 int err;
6612
6613 nest = nla_nest_start(skb, attr);
6614 if (nest == NULL)
6615 return -1;
6616
6617 switch (type) {
6618 case NFT_DATA_VALUE:
6619 err = nft_value_dump(skb, data, len);
6620 break;
6621 case NFT_DATA_VERDICT:
33d5a7b1 6622 err = nft_verdict_dump(skb, NFTA_DATA_VERDICT, &data->verdict);
96518518
PM
6623 break;
6624 default:
6625 err = -EINVAL;
6626 WARN_ON(1);
6627 }
6628
6629 nla_nest_end(skb, nest);
6630 return err;
6631}
6632EXPORT_SYMBOL_GPL(nft_data_dump);
6633
5ebe0b0e
PNA
6634int __nft_release_basechain(struct nft_ctx *ctx)
6635{
6636 struct nft_rule *rule, *nr;
6637
f323d954 6638 BUG_ON(!nft_is_base_chain(ctx->chain));
5ebe0b0e 6639
c974a3a3 6640 nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain);
5ebe0b0e
PNA
6641 list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
6642 list_del(&rule->list);
6643 ctx->chain->use--;
bb7b40ae 6644 nf_tables_rule_release(ctx, rule);
5ebe0b0e
PNA
6645 }
6646 list_del(&ctx->chain->list);
6647 ctx->table->use--;
43a605f2 6648 nf_tables_chain_destroy(ctx);
5ebe0b0e
PNA
6649
6650 return 0;
6651}
6652EXPORT_SYMBOL_GPL(__nft_release_basechain);
6653
98319cb9 6654static void __nft_release_tables(struct net *net)
df05ef87 6655{
3b49e2e9 6656 struct nft_flowtable *flowtable, *nf;
df05ef87
PNA
6657 struct nft_table *table, *nt;
6658 struct nft_chain *chain, *nc;
e5009240 6659 struct nft_object *obj, *ne;
df05ef87
PNA
6660 struct nft_rule *rule, *nr;
6661 struct nft_set *set, *ns;
6662 struct nft_ctx ctx = {
6663 .net = net,
43a605f2 6664 .family = NFPROTO_NETDEV,
df05ef87
PNA
6665 };
6666
36596dad 6667 list_for_each_entry_safe(table, nt, &net->nft.tables, list) {
98319cb9 6668 ctx.family = table->family;
dd4cbef7 6669
df05ef87 6670 list_for_each_entry(chain, &table->chains, list)
c974a3a3 6671 nf_tables_unregister_hook(net, table, chain);
3b49e2e9
PNA
6672 list_for_each_entry(flowtable, &table->flowtables, list)
6673 nf_unregister_net_hooks(net, flowtable->ops,
6674 flowtable->ops_len);
df05ef87
PNA
6675 /* No packets are walking on these chains anymore. */
6676 ctx.table = table;
6677 list_for_each_entry(chain, &table->chains, list) {
6678 ctx.chain = chain;
6679 list_for_each_entry_safe(rule, nr, &chain->rules, list) {
6680 list_del(&rule->list);
6681 chain->use--;
bb7b40ae 6682 nf_tables_rule_release(&ctx, rule);
df05ef87
PNA
6683 }
6684 }
3b49e2e9
PNA
6685 list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) {
6686 list_del(&flowtable->list);
6687 table->use--;
6688 nf_tables_flowtable_destroy(flowtable);
6689 }
df05ef87
PNA
6690 list_for_each_entry_safe(set, ns, &table->sets, list) {
6691 list_del(&set->list);
6692 table->use--;
6693 nft_set_destroy(set);
6694 }
e5009240
PNA
6695 list_for_each_entry_safe(obj, ne, &table->objects, list) {
6696 list_del(&obj->list);
6697 table->use--;
6698 nft_obj_destroy(obj);
6699 }
df05ef87 6700 list_for_each_entry_safe(chain, nc, &table->chains, list) {
43a605f2 6701 ctx.chain = chain;
df05ef87
PNA
6702 list_del(&chain->list);
6703 table->use--;
43a605f2 6704 nf_tables_chain_destroy(&ctx);
df05ef87
PNA
6705 }
6706 list_del(&table->list);
6707 nf_tables_table_destroy(&ctx);
6708 }
6709}
6710
dd4cbef7
PNA
6711static int __net_init nf_tables_init_net(struct net *net)
6712{
6713 INIT_LIST_HEAD(&net->nft.tables);
6714 INIT_LIST_HEAD(&net->nft.commit_list);
6715 net->nft.base_seq = 1;
6716 return 0;
6717}
6718
6719static void __net_exit nf_tables_exit_net(struct net *net)
6720{
98319cb9 6721 __nft_release_tables(net);
dd4cbef7
PNA
6722 WARN_ON_ONCE(!list_empty(&net->nft.tables));
6723 WARN_ON_ONCE(!list_empty(&net->nft.commit_list));
6724}
6725
99633ab2
PNA
6726static struct pernet_operations nf_tables_net_ops = {
6727 .init = nf_tables_init_net,
613d0776 6728 .exit = nf_tables_exit_net,
99633ab2
PNA
6729};
6730
96518518
PM
6731static int __init nf_tables_module_init(void)
6732{
6733 int err;
6734
02c7b25e
PNA
6735 nft_chain_filter_init();
6736
96518518
PM
6737 info = kmalloc(sizeof(struct nft_expr_info) * NFT_RULE_MAXEXPRS,
6738 GFP_KERNEL);
6739 if (info == NULL) {
6740 err = -ENOMEM;
6741 goto err1;
6742 }
6743
6744 err = nf_tables_core_module_init();
6745 if (err < 0)
6746 goto err2;
6747
6748 err = nfnetlink_subsys_register(&nf_tables_subsys);
6749 if (err < 0)
6750 goto err3;
6751
3b49e2e9
PNA
6752 register_netdevice_notifier(&nf_tables_flowtable_notifier);
6753
99633ab2 6754 return register_pernet_subsys(&nf_tables_net_ops);
96518518
PM
6755err3:
6756 nf_tables_core_module_exit();
6757err2:
6758 kfree(info);
6759err1:
6760 return err;
6761}
6762
6763static void __exit nf_tables_module_exit(void)
6764{
99633ab2 6765 unregister_pernet_subsys(&nf_tables_net_ops);
96518518 6766 nfnetlink_subsys_unregister(&nf_tables_subsys);
3b49e2e9 6767 unregister_netdevice_notifier(&nf_tables_flowtable_notifier);
1b1bc49c 6768 rcu_barrier();
96518518
PM
6769 nf_tables_core_module_exit();
6770 kfree(info);
02c7b25e 6771 nft_chain_filter_fini();
96518518
PM
6772}
6773
6774module_init(nf_tables_module_init);
6775module_exit(nf_tables_module_exit);
6776
6777MODULE_LICENSE("GPL");
6778MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
6779MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFTABLES);