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