]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - net/netfilter/nf_tables_api.c
netfilter: nf_tables: set NLM_F_DUMP_INTR if netlink dumping is stale
[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>
16#include <linux/netfilter.h>
17#include <linux/netfilter/nfnetlink.h>
18#include <linux/netfilter/nf_tables.h>
19#include <net/netfilter/nf_tables_core.h>
20#include <net/netfilter/nf_tables.h>
99633ab2 21#include <net/net_namespace.h>
96518518
PM
22#include <net/sock.h>
23
96518518
PM
24static LIST_HEAD(nf_tables_expressions);
25
26/**
27 * nft_register_afinfo - register nf_tables address family info
28 *
29 * @afi: address family info to register
30 *
31 * Register the address family for use with nf_tables. Returns zero on
32 * success or a negative errno code otherwise.
33 */
99633ab2 34int nft_register_afinfo(struct net *net, struct nft_af_info *afi)
96518518
PM
35{
36 INIT_LIST_HEAD(&afi->tables);
37 nfnl_lock(NFNL_SUBSYS_NFTABLES);
e688a7f8 38 list_add_tail_rcu(&afi->list, &net->nft.af_info);
96518518
PM
39 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
40 return 0;
41}
42EXPORT_SYMBOL_GPL(nft_register_afinfo);
43
44/**
45 * nft_unregister_afinfo - unregister nf_tables address family info
46 *
47 * @afi: address family info to unregister
48 *
49 * Unregister the address family for use with nf_tables.
50 */
51void nft_unregister_afinfo(struct nft_af_info *afi)
52{
53 nfnl_lock(NFNL_SUBSYS_NFTABLES);
e688a7f8 54 list_del_rcu(&afi->list);
96518518
PM
55 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
56}
57EXPORT_SYMBOL_GPL(nft_unregister_afinfo);
58
99633ab2 59static struct nft_af_info *nft_afinfo_lookup(struct net *net, int family)
96518518
PM
60{
61 struct nft_af_info *afi;
62
99633ab2 63 list_for_each_entry(afi, &net->nft.af_info, list) {
96518518
PM
64 if (afi->family == family)
65 return afi;
66 }
67 return NULL;
68}
69
99633ab2
PNA
70static struct nft_af_info *
71nf_tables_afinfo_lookup(struct net *net, int family, bool autoload)
96518518
PM
72{
73 struct nft_af_info *afi;
74
99633ab2 75 afi = nft_afinfo_lookup(net, family);
96518518
PM
76 if (afi != NULL)
77 return afi;
78#ifdef CONFIG_MODULES
79 if (autoload) {
80 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
81 request_module("nft-afinfo-%u", family);
82 nfnl_lock(NFNL_SUBSYS_NFTABLES);
99633ab2 83 afi = nft_afinfo_lookup(net, family);
96518518
PM
84 if (afi != NULL)
85 return ERR_PTR(-EAGAIN);
86 }
87#endif
88 return ERR_PTR(-EAFNOSUPPORT);
89}
90
7c95f6d8
PNA
91static void nft_ctx_init(struct nft_ctx *ctx,
92 const struct sk_buff *skb,
93 const struct nlmsghdr *nlh,
94 struct nft_af_info *afi,
95 struct nft_table *table,
96 struct nft_chain *chain,
97 const struct nlattr * const *nla)
98{
128ad332
PNA
99 ctx->net = sock_net(skb->sk);
100 ctx->afi = afi;
101 ctx->table = table;
102 ctx->chain = chain;
103 ctx->nla = nla;
104 ctx->portid = NETLINK_CB(skb).portid;
105 ctx->report = nlmsg_report(nlh);
106 ctx->seq = nlh->nlmsg_seq;
7c95f6d8
PNA
107}
108
b380e5c7
PNA
109static struct nft_trans *nft_trans_alloc(struct nft_ctx *ctx, int msg_type,
110 u32 size)
1081d11b
PNA
111{
112 struct nft_trans *trans;
113
114 trans = kzalloc(sizeof(struct nft_trans) + size, GFP_KERNEL);
115 if (trans == NULL)
116 return NULL;
117
b380e5c7 118 trans->msg_type = msg_type;
1081d11b
PNA
119 trans->ctx = *ctx;
120
121 return trans;
122}
123
124static void nft_trans_destroy(struct nft_trans *trans)
125{
126 list_del(&trans->list);
127 kfree(trans);
128}
129
96518518
PM
130/*
131 * Tables
132 */
133
134static struct nft_table *nft_table_lookup(const struct nft_af_info *afi,
135 const struct nlattr *nla)
136{
137 struct nft_table *table;
138
139 list_for_each_entry(table, &afi->tables, list) {
140 if (!nla_strcmp(nla, table->name))
141 return table;
142 }
143 return NULL;
144}
145
146static struct nft_table *nf_tables_table_lookup(const struct nft_af_info *afi,
9370761c 147 const struct nlattr *nla)
96518518
PM
148{
149 struct nft_table *table;
150
151 if (nla == NULL)
152 return ERR_PTR(-EINVAL);
153
154 table = nft_table_lookup(afi, nla);
155 if (table != NULL)
156 return table;
157
96518518
PM
158 return ERR_PTR(-ENOENT);
159}
160
161static inline u64 nf_tables_alloc_handle(struct nft_table *table)
162{
163 return ++table->hgenerator;
164}
165
2a37d755 166static const struct nf_chain_type *chain_type[AF_MAX][NFT_CHAIN_T_MAX];
9370761c 167
2a37d755 168static const struct nf_chain_type *
baae3e62 169__nf_tables_chain_type_lookup(int family, const struct nlattr *nla)
9370761c
PNA
170{
171 int i;
172
baae3e62 173 for (i = 0; i < NFT_CHAIN_T_MAX; i++) {
9370761c
PNA
174 if (chain_type[family][i] != NULL &&
175 !nla_strcmp(nla, chain_type[family][i]->name))
baae3e62 176 return chain_type[family][i];
9370761c 177 }
baae3e62 178 return NULL;
9370761c
PNA
179}
180
2a37d755 181static const struct nf_chain_type *
baae3e62
PM
182nf_tables_chain_type_lookup(const struct nft_af_info *afi,
183 const struct nlattr *nla,
184 bool autoload)
9370761c 185{
2a37d755 186 const struct nf_chain_type *type;
9370761c
PNA
187
188 type = __nf_tables_chain_type_lookup(afi->family, nla);
93b0806f
PM
189 if (type != NULL)
190 return type;
9370761c 191#ifdef CONFIG_MODULES
93b0806f 192 if (autoload) {
9370761c 193 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
2fec6bb6
PNA
194 request_module("nft-chain-%u-%.*s", afi->family,
195 nla_len(nla), (const char *)nla_data(nla));
9370761c
PNA
196 nfnl_lock(NFNL_SUBSYS_NFTABLES);
197 type = __nf_tables_chain_type_lookup(afi->family, nla);
93b0806f
PM
198 if (type != NULL)
199 return ERR_PTR(-EAGAIN);
9370761c
PNA
200 }
201#endif
93b0806f 202 return ERR_PTR(-ENOENT);
9370761c
PNA
203}
204
96518518
PM
205static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = {
206 [NFTA_TABLE_NAME] = { .type = NLA_STRING },
9ddf6323 207 [NFTA_TABLE_FLAGS] = { .type = NLA_U32 },
96518518
PM
208};
209
210static int nf_tables_fill_table_info(struct sk_buff *skb, u32 portid, u32 seq,
211 int event, u32 flags, int family,
212 const struct nft_table *table)
213{
214 struct nlmsghdr *nlh;
215 struct nfgenmsg *nfmsg;
216
217 event |= NFNL_SUBSYS_NFTABLES << 8;
218 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags);
219 if (nlh == NULL)
220 goto nla_put_failure;
221
222 nfmsg = nlmsg_data(nlh);
223 nfmsg->nfgen_family = family;
224 nfmsg->version = NFNETLINK_V0;
225 nfmsg->res_id = 0;
226
9ddf6323 227 if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) ||
d8bcc768
TB
228 nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) ||
229 nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)))
96518518
PM
230 goto nla_put_failure;
231
232 return nlmsg_end(skb, nlh);
233
234nla_put_failure:
235 nlmsg_trim(skb, nlh);
236 return -1;
237}
238
35151d84 239static int nf_tables_table_notify(const struct nft_ctx *ctx, int event)
96518518
PM
240{
241 struct sk_buff *skb;
96518518
PM
242 int err;
243
128ad332
PNA
244 if (!ctx->report &&
245 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
96518518
PM
246 return 0;
247
248 err = -ENOBUFS;
249 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
250 if (skb == NULL)
251 goto err;
252
128ad332 253 err = nf_tables_fill_table_info(skb, ctx->portid, ctx->seq, event, 0,
35151d84 254 ctx->afi->family, ctx->table);
96518518
PM
255 if (err < 0) {
256 kfree_skb(skb);
257 goto err;
258 }
259
128ad332
PNA
260 err = nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
261 ctx->report, GFP_KERNEL);
96518518 262err:
128ad332
PNA
263 if (err < 0) {
264 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES,
265 err);
266 }
96518518
PM
267 return err;
268}
269
270static int nf_tables_dump_tables(struct sk_buff *skb,
271 struct netlink_callback *cb)
272{
273 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
274 const struct nft_af_info *afi;
275 const struct nft_table *table;
276 unsigned int idx = 0, s_idx = cb->args[0];
99633ab2 277 struct net *net = sock_net(skb->sk);
96518518
PM
278 int family = nfmsg->nfgen_family;
279
e688a7f8 280 rcu_read_lock();
38e029f1
PNA
281 cb->seq = net->nft.base_seq;
282
e688a7f8 283 list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
96518518
PM
284 if (family != NFPROTO_UNSPEC && family != afi->family)
285 continue;
286
e688a7f8 287 list_for_each_entry_rcu(table, &afi->tables, list) {
96518518
PM
288 if (idx < s_idx)
289 goto cont;
290 if (idx > s_idx)
291 memset(&cb->args[1], 0,
292 sizeof(cb->args) - sizeof(cb->args[0]));
293 if (nf_tables_fill_table_info(skb,
294 NETLINK_CB(cb->skb).portid,
295 cb->nlh->nlmsg_seq,
296 NFT_MSG_NEWTABLE,
297 NLM_F_MULTI,
298 afi->family, table) < 0)
299 goto done;
38e029f1
PNA
300
301 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
96518518
PM
302cont:
303 idx++;
304 }
305 }
306done:
e688a7f8 307 rcu_read_unlock();
96518518
PM
308 cb->args[0] = idx;
309 return skb->len;
310}
311
55dd6f93
PNA
312/* Internal table flags */
313#define NFT_TABLE_INACTIVE (1 << 15)
314
96518518
PM
315static int nf_tables_gettable(struct sock *nlsk, struct sk_buff *skb,
316 const struct nlmsghdr *nlh,
317 const struct nlattr * const nla[])
318{
319 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
320 const struct nft_af_info *afi;
321 const struct nft_table *table;
322 struct sk_buff *skb2;
99633ab2 323 struct net *net = sock_net(skb->sk);
96518518
PM
324 int family = nfmsg->nfgen_family;
325 int err;
326
327 if (nlh->nlmsg_flags & NLM_F_DUMP) {
328 struct netlink_dump_control c = {
329 .dump = nf_tables_dump_tables,
330 };
331 return netlink_dump_start(nlsk, skb, nlh, &c);
332 }
333
99633ab2 334 afi = nf_tables_afinfo_lookup(net, family, false);
96518518
PM
335 if (IS_ERR(afi))
336 return PTR_ERR(afi);
337
9370761c 338 table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME]);
96518518
PM
339 if (IS_ERR(table))
340 return PTR_ERR(table);
55dd6f93
PNA
341 if (table->flags & NFT_TABLE_INACTIVE)
342 return -ENOENT;
96518518
PM
343
344 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
345 if (!skb2)
346 return -ENOMEM;
347
348 err = nf_tables_fill_table_info(skb2, NETLINK_CB(skb).portid,
349 nlh->nlmsg_seq, NFT_MSG_NEWTABLE, 0,
350 family, table);
351 if (err < 0)
352 goto err;
353
354 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
355
356err:
357 kfree_skb(skb2);
358 return err;
359}
360
115a60b1
PM
361static int nf_tables_table_enable(const struct nft_af_info *afi,
362 struct nft_table *table)
9ddf6323
PNA
363{
364 struct nft_chain *chain;
365 int err, i = 0;
366
367 list_for_each_entry(chain, &table->chains, list) {
d2012975
PNA
368 if (!(chain->flags & NFT_BASE_CHAIN))
369 continue;
370
115a60b1 371 err = nf_register_hooks(nft_base_chain(chain)->ops, afi->nops);
9ddf6323
PNA
372 if (err < 0)
373 goto err;
374
375 i++;
376 }
377 return 0;
378err:
379 list_for_each_entry(chain, &table->chains, list) {
d2012975
PNA
380 if (!(chain->flags & NFT_BASE_CHAIN))
381 continue;
382
9ddf6323
PNA
383 if (i-- <= 0)
384 break;
385
115a60b1 386 nf_unregister_hooks(nft_base_chain(chain)->ops, afi->nops);
9ddf6323
PNA
387 }
388 return err;
389}
390
f75edf5e 391static void nf_tables_table_disable(const struct nft_af_info *afi,
115a60b1 392 struct nft_table *table)
9ddf6323
PNA
393{
394 struct nft_chain *chain;
395
d2012975
PNA
396 list_for_each_entry(chain, &table->chains, list) {
397 if (chain->flags & NFT_BASE_CHAIN)
115a60b1
PM
398 nf_unregister_hooks(nft_base_chain(chain)->ops,
399 afi->nops);
d2012975 400 }
9ddf6323
PNA
401}
402
e1aaca93 403static int nf_tables_updtable(struct nft_ctx *ctx)
9ddf6323 404{
55dd6f93 405 struct nft_trans *trans;
e1aaca93 406 u32 flags;
55dd6f93 407 int ret = 0;
9ddf6323 408
e1aaca93
PNA
409 if (!ctx->nla[NFTA_TABLE_FLAGS])
410 return 0;
9ddf6323 411
e1aaca93
PNA
412 flags = ntohl(nla_get_be32(ctx->nla[NFTA_TABLE_FLAGS]));
413 if (flags & ~NFT_TABLE_F_DORMANT)
414 return -EINVAL;
415
63283dd2
PNA
416 if (flags == ctx->table->flags)
417 return 0;
418
55dd6f93
PNA
419 trans = nft_trans_alloc(ctx, NFT_MSG_NEWTABLE,
420 sizeof(struct nft_trans_table));
421 if (trans == NULL)
422 return -ENOMEM;
9ddf6323 423
e1aaca93
PNA
424 if ((flags & NFT_TABLE_F_DORMANT) &&
425 !(ctx->table->flags & NFT_TABLE_F_DORMANT)) {
55dd6f93 426 nft_trans_table_enable(trans) = false;
e1aaca93
PNA
427 } else if (!(flags & NFT_TABLE_F_DORMANT) &&
428 ctx->table->flags & NFT_TABLE_F_DORMANT) {
429 ret = nf_tables_table_enable(ctx->afi, ctx->table);
55dd6f93 430 if (ret >= 0) {
e1aaca93 431 ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
55dd6f93 432 nft_trans_table_enable(trans) = true;
9ddf6323 433 }
9ddf6323 434 }
e1aaca93
PNA
435 if (ret < 0)
436 goto err;
9ddf6323 437
55dd6f93
PNA
438 nft_trans_table_update(trans) = true;
439 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
440 return 0;
9ddf6323 441err:
55dd6f93 442 nft_trans_destroy(trans);
9ddf6323
PNA
443 return ret;
444}
445
55dd6f93
PNA
446static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type)
447{
448 struct nft_trans *trans;
449
450 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_table));
451 if (trans == NULL)
452 return -ENOMEM;
453
454 if (msg_type == NFT_MSG_NEWTABLE)
455 ctx->table->flags |= NFT_TABLE_INACTIVE;
456
457 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
458 return 0;
459}
460
96518518
PM
461static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
462 const struct nlmsghdr *nlh,
463 const struct nlattr * const nla[])
464{
465 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
466 const struct nlattr *name;
467 struct nft_af_info *afi;
468 struct nft_table *table;
99633ab2 469 struct net *net = sock_net(skb->sk);
96518518 470 int family = nfmsg->nfgen_family;
c5c1f975 471 u32 flags = 0;
e1aaca93 472 struct nft_ctx ctx;
55dd6f93 473 int err;
96518518 474
99633ab2 475 afi = nf_tables_afinfo_lookup(net, family, true);
96518518
PM
476 if (IS_ERR(afi))
477 return PTR_ERR(afi);
478
479 name = nla[NFTA_TABLE_NAME];
9370761c 480 table = nf_tables_table_lookup(afi, name);
96518518
PM
481 if (IS_ERR(table)) {
482 if (PTR_ERR(table) != -ENOENT)
483 return PTR_ERR(table);
484 table = NULL;
485 }
486
487 if (table != NULL) {
55dd6f93
PNA
488 if (table->flags & NFT_TABLE_INACTIVE)
489 return -ENOENT;
96518518
PM
490 if (nlh->nlmsg_flags & NLM_F_EXCL)
491 return -EEXIST;
492 if (nlh->nlmsg_flags & NLM_F_REPLACE)
493 return -EOPNOTSUPP;
e1aaca93
PNA
494
495 nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
496 return nf_tables_updtable(&ctx);
96518518
PM
497 }
498
c5c1f975
PM
499 if (nla[NFTA_TABLE_FLAGS]) {
500 flags = ntohl(nla_get_be32(nla[NFTA_TABLE_FLAGS]));
501 if (flags & ~NFT_TABLE_F_DORMANT)
502 return -EINVAL;
503 }
504
7047f9d0
PM
505 if (!try_module_get(afi->owner))
506 return -EAFNOSUPPORT;
507
96518518 508 table = kzalloc(sizeof(*table) + nla_len(name), GFP_KERNEL);
7047f9d0
PM
509 if (table == NULL) {
510 module_put(afi->owner);
96518518 511 return -ENOMEM;
7047f9d0 512 }
96518518
PM
513
514 nla_strlcpy(table->name, name, nla_len(name));
515 INIT_LIST_HEAD(&table->chains);
20a69341 516 INIT_LIST_HEAD(&table->sets);
c5c1f975 517 table->flags = flags;
9ddf6323 518
55dd6f93
PNA
519 nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
520 err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE);
521 if (err < 0) {
522 kfree(table);
523 module_put(afi->owner);
524 return err;
525 }
e688a7f8 526 list_add_tail_rcu(&table->list, &afi->tables);
96518518
PM
527 return 0;
528}
529
530static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
531 const struct nlmsghdr *nlh,
532 const struct nlattr * const nla[])
533{
534 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
535 struct nft_af_info *afi;
536 struct nft_table *table;
99633ab2 537 struct net *net = sock_net(skb->sk);
55dd6f93
PNA
538 int family = nfmsg->nfgen_family, err;
539 struct nft_ctx ctx;
96518518 540
99633ab2 541 afi = nf_tables_afinfo_lookup(net, family, false);
96518518
PM
542 if (IS_ERR(afi))
543 return PTR_ERR(afi);
544
9370761c 545 table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME]);
96518518
PM
546 if (IS_ERR(table))
547 return PTR_ERR(table);
55dd6f93
PNA
548 if (table->flags & NFT_TABLE_INACTIVE)
549 return -ENOENT;
4fefee57 550 if (table->use > 0)
96518518
PM
551 return -EBUSY;
552
55dd6f93
PNA
553 nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
554 err = nft_trans_table_add(&ctx, NFT_MSG_DELTABLE);
555 if (err < 0)
556 return err;
557
e688a7f8 558 list_del_rcu(&table->list);
96518518
PM
559 return 0;
560}
561
55dd6f93
PNA
562static void nf_tables_table_destroy(struct nft_ctx *ctx)
563{
4fefee57
PNA
564 BUG_ON(ctx->table->use > 0);
565
55dd6f93
PNA
566 kfree(ctx->table);
567 module_put(ctx->afi->owner);
568}
569
2a37d755 570int nft_register_chain_type(const struct nf_chain_type *ctype)
96518518 571{
9370761c 572 int err = 0;
96518518
PM
573
574 nfnl_lock(NFNL_SUBSYS_NFTABLES);
9370761c
PNA
575 if (chain_type[ctype->family][ctype->type] != NULL) {
576 err = -EBUSY;
577 goto out;
96518518 578 }
9370761c
PNA
579 chain_type[ctype->family][ctype->type] = ctype;
580out:
96518518
PM
581 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
582 return err;
583}
9370761c 584EXPORT_SYMBOL_GPL(nft_register_chain_type);
96518518 585
2a37d755 586void nft_unregister_chain_type(const struct nf_chain_type *ctype)
96518518 587{
96518518 588 nfnl_lock(NFNL_SUBSYS_NFTABLES);
9370761c 589 chain_type[ctype->family][ctype->type] = NULL;
96518518
PM
590 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
591}
9370761c 592EXPORT_SYMBOL_GPL(nft_unregister_chain_type);
96518518
PM
593
594/*
595 * Chains
596 */
597
598static struct nft_chain *
599nf_tables_chain_lookup_byhandle(const struct nft_table *table, u64 handle)
600{
601 struct nft_chain *chain;
602
603 list_for_each_entry(chain, &table->chains, list) {
604 if (chain->handle == handle)
605 return chain;
606 }
607
608 return ERR_PTR(-ENOENT);
609}
610
611static struct nft_chain *nf_tables_chain_lookup(const struct nft_table *table,
612 const struct nlattr *nla)
613{
614 struct nft_chain *chain;
615
616 if (nla == NULL)
617 return ERR_PTR(-EINVAL);
618
619 list_for_each_entry(chain, &table->chains, list) {
620 if (!nla_strcmp(nla, chain->name))
621 return chain;
622 }
623
624 return ERR_PTR(-ENOENT);
625}
626
627static const struct nla_policy nft_chain_policy[NFTA_CHAIN_MAX + 1] = {
628 [NFTA_CHAIN_TABLE] = { .type = NLA_STRING },
629 [NFTA_CHAIN_HANDLE] = { .type = NLA_U64 },
630 [NFTA_CHAIN_NAME] = { .type = NLA_STRING,
631 .len = NFT_CHAIN_MAXNAMELEN - 1 },
632 [NFTA_CHAIN_HOOK] = { .type = NLA_NESTED },
0ca743a5 633 [NFTA_CHAIN_POLICY] = { .type = NLA_U32 },
4c1f7818 634 [NFTA_CHAIN_TYPE] = { .type = NLA_STRING },
0ca743a5 635 [NFTA_CHAIN_COUNTERS] = { .type = NLA_NESTED },
96518518
PM
636};
637
638static const struct nla_policy nft_hook_policy[NFTA_HOOK_MAX + 1] = {
639 [NFTA_HOOK_HOOKNUM] = { .type = NLA_U32 },
640 [NFTA_HOOK_PRIORITY] = { .type = NLA_U32 },
641};
642
0ca743a5
PNA
643static int nft_dump_stats(struct sk_buff *skb, struct nft_stats __percpu *stats)
644{
645 struct nft_stats *cpu_stats, total;
646 struct nlattr *nest;
647 int cpu;
648
649 memset(&total, 0, sizeof(total));
650 for_each_possible_cpu(cpu) {
651 cpu_stats = per_cpu_ptr(stats, cpu);
652 total.pkts += cpu_stats->pkts;
653 total.bytes += cpu_stats->bytes;
654 }
655 nest = nla_nest_start(skb, NFTA_CHAIN_COUNTERS);
656 if (nest == NULL)
657 goto nla_put_failure;
658
659 if (nla_put_be64(skb, NFTA_COUNTER_PACKETS, cpu_to_be64(total.pkts)) ||
660 nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes)))
661 goto nla_put_failure;
662
663 nla_nest_end(skb, nest);
664 return 0;
665
666nla_put_failure:
667 return -ENOSPC;
668}
669
96518518
PM
670static int nf_tables_fill_chain_info(struct sk_buff *skb, u32 portid, u32 seq,
671 int event, u32 flags, int family,
672 const struct nft_table *table,
673 const struct nft_chain *chain)
674{
675 struct nlmsghdr *nlh;
676 struct nfgenmsg *nfmsg;
677
678 event |= NFNL_SUBSYS_NFTABLES << 8;
679 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags);
680 if (nlh == NULL)
681 goto nla_put_failure;
682
683 nfmsg = nlmsg_data(nlh);
684 nfmsg->nfgen_family = family;
685 nfmsg->version = NFNETLINK_V0;
686 nfmsg->res_id = 0;
687
688 if (nla_put_string(skb, NFTA_CHAIN_TABLE, table->name))
689 goto nla_put_failure;
690 if (nla_put_be64(skb, NFTA_CHAIN_HANDLE, cpu_to_be64(chain->handle)))
691 goto nla_put_failure;
692 if (nla_put_string(skb, NFTA_CHAIN_NAME, chain->name))
693 goto nla_put_failure;
694
695 if (chain->flags & NFT_BASE_CHAIN) {
0ca743a5 696 const struct nft_base_chain *basechain = nft_base_chain(chain);
115a60b1 697 const struct nf_hook_ops *ops = &basechain->ops[0];
0ca743a5
PNA
698 struct nlattr *nest;
699
700 nest = nla_nest_start(skb, NFTA_CHAIN_HOOK);
96518518
PM
701 if (nest == NULL)
702 goto nla_put_failure;
703 if (nla_put_be32(skb, NFTA_HOOK_HOOKNUM, htonl(ops->hooknum)))
704 goto nla_put_failure;
705 if (nla_put_be32(skb, NFTA_HOOK_PRIORITY, htonl(ops->priority)))
706 goto nla_put_failure;
707 nla_nest_end(skb, nest);
9370761c 708
0ca743a5
PNA
709 if (nla_put_be32(skb, NFTA_CHAIN_POLICY,
710 htonl(basechain->policy)))
711 goto nla_put_failure;
712
baae3e62
PM
713 if (nla_put_string(skb, NFTA_CHAIN_TYPE, basechain->type->name))
714 goto nla_put_failure;
0ca743a5
PNA
715
716 if (nft_dump_stats(skb, nft_base_chain(chain)->stats))
717 goto nla_put_failure;
96518518
PM
718 }
719
0ca743a5
PNA
720 if (nla_put_be32(skb, NFTA_CHAIN_USE, htonl(chain->use)))
721 goto nla_put_failure;
722
96518518
PM
723 return nlmsg_end(skb, nlh);
724
725nla_put_failure:
726 nlmsg_trim(skb, nlh);
727 return -1;
728}
729
35151d84 730static int nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
96518518
PM
731{
732 struct sk_buff *skb;
96518518
PM
733 int err;
734
128ad332
PNA
735 if (!ctx->report &&
736 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
96518518
PM
737 return 0;
738
739 err = -ENOBUFS;
740 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
741 if (skb == NULL)
742 goto err;
743
128ad332 744 err = nf_tables_fill_chain_info(skb, ctx->portid, ctx->seq, event, 0,
35151d84
PNA
745 ctx->afi->family, ctx->table,
746 ctx->chain);
96518518
PM
747 if (err < 0) {
748 kfree_skb(skb);
749 goto err;
750 }
751
128ad332
PNA
752 err = nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
753 ctx->report, GFP_KERNEL);
96518518 754err:
128ad332
PNA
755 if (err < 0) {
756 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES,
757 err);
758 }
96518518
PM
759 return err;
760}
761
762static int nf_tables_dump_chains(struct sk_buff *skb,
763 struct netlink_callback *cb)
764{
765 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
766 const struct nft_af_info *afi;
767 const struct nft_table *table;
768 const struct nft_chain *chain;
769 unsigned int idx = 0, s_idx = cb->args[0];
99633ab2 770 struct net *net = sock_net(skb->sk);
96518518
PM
771 int family = nfmsg->nfgen_family;
772
e688a7f8 773 rcu_read_lock();
38e029f1
PNA
774 cb->seq = net->nft.base_seq;
775
e688a7f8 776 list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
96518518
PM
777 if (family != NFPROTO_UNSPEC && family != afi->family)
778 continue;
779
e688a7f8
PNA
780 list_for_each_entry_rcu(table, &afi->tables, list) {
781 list_for_each_entry_rcu(chain, &table->chains, list) {
96518518
PM
782 if (idx < s_idx)
783 goto cont;
784 if (idx > s_idx)
785 memset(&cb->args[1], 0,
786 sizeof(cb->args) - sizeof(cb->args[0]));
787 if (nf_tables_fill_chain_info(skb, NETLINK_CB(cb->skb).portid,
788 cb->nlh->nlmsg_seq,
789 NFT_MSG_NEWCHAIN,
790 NLM_F_MULTI,
791 afi->family, table, chain) < 0)
792 goto done;
38e029f1
PNA
793
794 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
96518518
PM
795cont:
796 idx++;
797 }
798 }
799 }
800done:
e688a7f8 801 rcu_read_unlock();
96518518
PM
802 cb->args[0] = idx;
803 return skb->len;
804}
805
96518518
PM
806static int nf_tables_getchain(struct sock *nlsk, struct sk_buff *skb,
807 const struct nlmsghdr *nlh,
808 const struct nlattr * const nla[])
809{
810 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
811 const struct nft_af_info *afi;
812 const struct nft_table *table;
813 const struct nft_chain *chain;
814 struct sk_buff *skb2;
99633ab2 815 struct net *net = sock_net(skb->sk);
96518518
PM
816 int family = nfmsg->nfgen_family;
817 int err;
818
819 if (nlh->nlmsg_flags & NLM_F_DUMP) {
820 struct netlink_dump_control c = {
821 .dump = nf_tables_dump_chains,
822 };
823 return netlink_dump_start(nlsk, skb, nlh, &c);
824 }
825
99633ab2 826 afi = nf_tables_afinfo_lookup(net, family, false);
96518518
PM
827 if (IS_ERR(afi))
828 return PTR_ERR(afi);
829
9370761c 830 table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]);
96518518
PM
831 if (IS_ERR(table))
832 return PTR_ERR(table);
55dd6f93
PNA
833 if (table->flags & NFT_TABLE_INACTIVE)
834 return -ENOENT;
96518518
PM
835
836 chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]);
837 if (IS_ERR(chain))
838 return PTR_ERR(chain);
91c7b38d
PNA
839 if (chain->flags & NFT_CHAIN_INACTIVE)
840 return -ENOENT;
96518518
PM
841
842 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
843 if (!skb2)
844 return -ENOMEM;
845
846 err = nf_tables_fill_chain_info(skb2, NETLINK_CB(skb).portid,
847 nlh->nlmsg_seq, NFT_MSG_NEWCHAIN, 0,
848 family, table, chain);
849 if (err < 0)
850 goto err;
851
852 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
853
854err:
855 kfree_skb(skb2);
856 return err;
857}
858
0ca743a5
PNA
859static const struct nla_policy nft_counter_policy[NFTA_COUNTER_MAX + 1] = {
860 [NFTA_COUNTER_PACKETS] = { .type = NLA_U64 },
861 [NFTA_COUNTER_BYTES] = { .type = NLA_U64 },
862};
863
ff3cd7b3 864static struct nft_stats __percpu *nft_stats_alloc(const struct nlattr *attr)
0ca743a5
PNA
865{
866 struct nlattr *tb[NFTA_COUNTER_MAX+1];
867 struct nft_stats __percpu *newstats;
868 struct nft_stats *stats;
869 int err;
870
871 err = nla_parse_nested(tb, NFTA_COUNTER_MAX, attr, nft_counter_policy);
872 if (err < 0)
ff3cd7b3 873 return ERR_PTR(err);
0ca743a5
PNA
874
875 if (!tb[NFTA_COUNTER_BYTES] || !tb[NFTA_COUNTER_PACKETS])
ff3cd7b3 876 return ERR_PTR(-EINVAL);
0ca743a5
PNA
877
878 newstats = alloc_percpu(struct nft_stats);
879 if (newstats == NULL)
ff3cd7b3 880 return ERR_PTR(-ENOMEM);
0ca743a5
PNA
881
882 /* Restore old counters on this cpu, no problem. Per-cpu statistics
883 * are not exposed to userspace.
884 */
885 stats = this_cpu_ptr(newstats);
886 stats->bytes = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES]));
887 stats->pkts = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS]));
888
ff3cd7b3
PNA
889 return newstats;
890}
891
892static void nft_chain_stats_replace(struct nft_base_chain *chain,
893 struct nft_stats __percpu *newstats)
894{
0ca743a5 895 if (chain->stats) {
0ca743a5 896 struct nft_stats __percpu *oldstats =
67a8fc27 897 nft_dereference(chain->stats);
0ca743a5
PNA
898
899 rcu_assign_pointer(chain->stats, newstats);
900 synchronize_rcu();
901 free_percpu(oldstats);
902 } else
903 rcu_assign_pointer(chain->stats, newstats);
0ca743a5
PNA
904}
905
91c7b38d
PNA
906static int nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
907{
908 struct nft_trans *trans;
909
910 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_chain));
911 if (trans == NULL)
912 return -ENOMEM;
913
914 if (msg_type == NFT_MSG_NEWCHAIN)
915 ctx->chain->flags |= NFT_CHAIN_INACTIVE;
0ca743a5 916
91c7b38d 917 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
0ca743a5
PNA
918 return 0;
919}
920
91c7b38d
PNA
921static void nf_tables_chain_destroy(struct nft_chain *chain)
922{
923 BUG_ON(chain->use > 0);
924
925 if (chain->flags & NFT_BASE_CHAIN) {
926 module_put(nft_base_chain(chain)->type->owner);
927 free_percpu(nft_base_chain(chain)->stats);
928 kfree(nft_base_chain(chain));
929 } else {
930 kfree(chain);
931 }
932}
933
96518518
PM
934static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
935 const struct nlmsghdr *nlh,
936 const struct nlattr * const nla[])
937{
938 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
939 const struct nlattr * uninitialized_var(name);
7c95f6d8 940 struct nft_af_info *afi;
96518518
PM
941 struct nft_table *table;
942 struct nft_chain *chain;
0ca743a5 943 struct nft_base_chain *basechain = NULL;
96518518 944 struct nlattr *ha[NFTA_HOOK_MAX + 1];
99633ab2 945 struct net *net = sock_net(skb->sk);
96518518 946 int family = nfmsg->nfgen_family;
57de2a0c 947 u8 policy = NF_ACCEPT;
96518518 948 u64 handle = 0;
115a60b1 949 unsigned int i;
ff3cd7b3 950 struct nft_stats __percpu *stats;
96518518
PM
951 int err;
952 bool create;
91c7b38d 953 struct nft_ctx ctx;
96518518
PM
954
955 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
956
99633ab2 957 afi = nf_tables_afinfo_lookup(net, family, true);
96518518
PM
958 if (IS_ERR(afi))
959 return PTR_ERR(afi);
960
9370761c 961 table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]);
96518518
PM
962 if (IS_ERR(table))
963 return PTR_ERR(table);
964
96518518
PM
965 chain = NULL;
966 name = nla[NFTA_CHAIN_NAME];
967
968 if (nla[NFTA_CHAIN_HANDLE]) {
969 handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE]));
970 chain = nf_tables_chain_lookup_byhandle(table, handle);
971 if (IS_ERR(chain))
972 return PTR_ERR(chain);
973 } else {
974 chain = nf_tables_chain_lookup(table, name);
975 if (IS_ERR(chain)) {
976 if (PTR_ERR(chain) != -ENOENT)
977 return PTR_ERR(chain);
978 chain = NULL;
979 }
980 }
981
57de2a0c
PM
982 if (nla[NFTA_CHAIN_POLICY]) {
983 if ((chain != NULL &&
984 !(chain->flags & NFT_BASE_CHAIN)) ||
985 nla[NFTA_CHAIN_HOOK] == NULL)
986 return -EOPNOTSUPP;
987
8f46df18 988 policy = ntohl(nla_get_be32(nla[NFTA_CHAIN_POLICY]));
57de2a0c
PM
989 switch (policy) {
990 case NF_DROP:
991 case NF_ACCEPT:
992 break;
993 default:
994 return -EINVAL;
995 }
996 }
997
96518518 998 if (chain != NULL) {
91c7b38d
PNA
999 struct nft_stats *stats = NULL;
1000 struct nft_trans *trans;
1001
1002 if (chain->flags & NFT_CHAIN_INACTIVE)
1003 return -ENOENT;
96518518
PM
1004 if (nlh->nlmsg_flags & NLM_F_EXCL)
1005 return -EEXIST;
1006 if (nlh->nlmsg_flags & NLM_F_REPLACE)
1007 return -EOPNOTSUPP;
1008
1009 if (nla[NFTA_CHAIN_HANDLE] && name &&
1010 !IS_ERR(nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME])))
1011 return -EEXIST;
1012
0ca743a5
PNA
1013 if (nla[NFTA_CHAIN_COUNTERS]) {
1014 if (!(chain->flags & NFT_BASE_CHAIN))
1015 return -EOPNOTSUPP;
1016
ff3cd7b3
PNA
1017 stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
1018 if (IS_ERR(stats))
1019 return PTR_ERR(stats);
0ca743a5
PNA
1020 }
1021
91c7b38d
PNA
1022 nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
1023 trans = nft_trans_alloc(&ctx, NFT_MSG_NEWCHAIN,
1024 sizeof(struct nft_trans_chain));
1025 if (trans == NULL)
1026 return -ENOMEM;
4401a862 1027
91c7b38d
PNA
1028 nft_trans_chain_stats(trans) = stats;
1029 nft_trans_chain_update(trans) = true;
4401a862 1030
91c7b38d
PNA
1031 if (nla[NFTA_CHAIN_POLICY])
1032 nft_trans_chain_policy(trans) = policy;
1033 else
1034 nft_trans_chain_policy(trans) = -1;
96518518 1035
91c7b38d
PNA
1036 if (nla[NFTA_CHAIN_HANDLE] && name) {
1037 nla_strlcpy(nft_trans_chain_name(trans), name,
1038 NFT_CHAIN_MAXNAMELEN);
1039 }
1040 list_add_tail(&trans->list, &net->nft.commit_list);
1041 return 0;
96518518
PM
1042 }
1043
75820676
PM
1044 if (table->use == UINT_MAX)
1045 return -EOVERFLOW;
1046
96518518 1047 if (nla[NFTA_CHAIN_HOOK]) {
2a37d755 1048 const struct nf_chain_type *type;
96518518 1049 struct nf_hook_ops *ops;
9370761c 1050 nf_hookfn *hookfn;
115a60b1 1051 u32 hooknum, priority;
9370761c 1052
baae3e62 1053 type = chain_type[family][NFT_CHAIN_T_DEFAULT];
9370761c
PNA
1054 if (nla[NFTA_CHAIN_TYPE]) {
1055 type = nf_tables_chain_type_lookup(afi,
1056 nla[NFTA_CHAIN_TYPE],
1057 create);
93b0806f
PM
1058 if (IS_ERR(type))
1059 return PTR_ERR(type);
9370761c 1060 }
96518518
PM
1061
1062 err = nla_parse_nested(ha, NFTA_HOOK_MAX, nla[NFTA_CHAIN_HOOK],
1063 nft_hook_policy);
1064 if (err < 0)
1065 return err;
1066 if (ha[NFTA_HOOK_HOOKNUM] == NULL ||
1067 ha[NFTA_HOOK_PRIORITY] == NULL)
1068 return -EINVAL;
9370761c
PNA
1069
1070 hooknum = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
1071 if (hooknum >= afi->nhooks)
96518518 1072 return -EINVAL;
115a60b1 1073 priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
96518518 1074
baae3e62 1075 if (!(type->hook_mask & (1 << hooknum)))
9370761c 1076 return -EOPNOTSUPP;
fa2c1de0 1077 if (!try_module_get(type->owner))
baae3e62 1078 return -ENOENT;
fa2c1de0 1079 hookfn = type->hooks[hooknum];
9370761c 1080
96518518
PM
1081 basechain = kzalloc(sizeof(*basechain), GFP_KERNEL);
1082 if (basechain == NULL)
1083 return -ENOMEM;
9370761c 1084
4401a862 1085 if (nla[NFTA_CHAIN_COUNTERS]) {
ff3cd7b3
PNA
1086 stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
1087 if (IS_ERR(stats)) {
fa2c1de0 1088 module_put(type->owner);
4401a862 1089 kfree(basechain);
ff3cd7b3 1090 return PTR_ERR(stats);
4401a862 1091 }
ff3cd7b3 1092 basechain->stats = stats;
4401a862 1093 } else {
ff3cd7b3
PNA
1094 stats = alloc_percpu(struct nft_stats);
1095 if (IS_ERR(stats)) {
fa2c1de0 1096 module_put(type->owner);
4401a862 1097 kfree(basechain);
ff3cd7b3 1098 return PTR_ERR(stats);
4401a862 1099 }
ff3cd7b3 1100 rcu_assign_pointer(basechain->stats, stats);
4401a862
PM
1101 }
1102
9370761c 1103 basechain->type = type;
96518518
PM
1104 chain = &basechain->chain;
1105
115a60b1
PM
1106 for (i = 0; i < afi->nops; i++) {
1107 ops = &basechain->ops[i];
1108 ops->pf = family;
1109 ops->owner = afi->owner;
1110 ops->hooknum = hooknum;
1111 ops->priority = priority;
1112 ops->priv = chain;
1113 ops->hook = afi->hooks[ops->hooknum];
1114 if (hookfn)
1115 ops->hook = hookfn;
1116 if (afi->hook_ops_init)
1117 afi->hook_ops_init(ops, i);
1118 }
96518518
PM
1119
1120 chain->flags |= NFT_BASE_CHAIN;
57de2a0c 1121 basechain->policy = policy;
96518518
PM
1122 } else {
1123 chain = kzalloc(sizeof(*chain), GFP_KERNEL);
1124 if (chain == NULL)
1125 return -ENOMEM;
1126 }
1127
1128 INIT_LIST_HEAD(&chain->rules);
1129 chain->handle = nf_tables_alloc_handle(table);
0628b123 1130 chain->net = net;
b5bc89bf 1131 chain->table = table;
96518518
PM
1132 nla_strlcpy(chain->name, name, NFT_CHAIN_MAXNAMELEN);
1133
9ddf6323
PNA
1134 if (!(table->flags & NFT_TABLE_F_DORMANT) &&
1135 chain->flags & NFT_BASE_CHAIN) {
115a60b1 1136 err = nf_register_hooks(nft_base_chain(chain)->ops, afi->nops);
91c7b38d
PNA
1137 if (err < 0)
1138 goto err1;
0ca743a5 1139 }
96518518 1140
91c7b38d
PNA
1141 nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
1142 err = nft_trans_chain_add(&ctx, NFT_MSG_NEWCHAIN);
1143 if (err < 0)
1144 goto err2;
96518518 1145
4fefee57 1146 table->use++;
e688a7f8 1147 list_add_tail_rcu(&chain->list, &table->chains);
91c7b38d
PNA
1148 return 0;
1149err2:
1150 if (!(table->flags & NFT_TABLE_F_DORMANT) &&
1151 chain->flags & NFT_BASE_CHAIN) {
1152 nf_unregister_hooks(nft_base_chain(chain)->ops,
1153 afi->nops);
1154 }
1155err1:
1156 nf_tables_chain_destroy(chain);
1157 return err;
96518518
PM
1158}
1159
1160static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
1161 const struct nlmsghdr *nlh,
1162 const struct nlattr * const nla[])
1163{
1164 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7c95f6d8 1165 struct nft_af_info *afi;
96518518
PM
1166 struct nft_table *table;
1167 struct nft_chain *chain;
99633ab2 1168 struct net *net = sock_net(skb->sk);
96518518 1169 int family = nfmsg->nfgen_family;
91c7b38d
PNA
1170 struct nft_ctx ctx;
1171 int err;
96518518 1172
99633ab2 1173 afi = nf_tables_afinfo_lookup(net, family, false);
96518518
PM
1174 if (IS_ERR(afi))
1175 return PTR_ERR(afi);
1176
9370761c 1177 table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]);
96518518
PM
1178 if (IS_ERR(table))
1179 return PTR_ERR(table);
55dd6f93
PNA
1180 if (table->flags & NFT_TABLE_INACTIVE)
1181 return -ENOENT;
96518518
PM
1182
1183 chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]);
1184 if (IS_ERR(chain))
1185 return PTR_ERR(chain);
91c7b38d
PNA
1186 if (chain->flags & NFT_CHAIN_INACTIVE)
1187 return -ENOENT;
4fefee57 1188 if (chain->use > 0)
96518518
PM
1189 return -EBUSY;
1190
91c7b38d
PNA
1191 nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
1192 err = nft_trans_chain_add(&ctx, NFT_MSG_DELCHAIN);
1193 if (err < 0)
1194 return err;
0165d932 1195
4fefee57 1196 table->use--;
e688a7f8 1197 list_del_rcu(&chain->list);
96518518
PM
1198 return 0;
1199}
1200
96518518
PM
1201/*
1202 * Expressions
1203 */
1204
1205/**
ef1f7df9
PM
1206 * nft_register_expr - register nf_tables expr type
1207 * @ops: expr type
96518518 1208 *
ef1f7df9 1209 * Registers the expr type for use with nf_tables. Returns zero on
96518518
PM
1210 * success or a negative errno code otherwise.
1211 */
ef1f7df9 1212int nft_register_expr(struct nft_expr_type *type)
96518518
PM
1213{
1214 nfnl_lock(NFNL_SUBSYS_NFTABLES);
758dbcec 1215 if (type->family == NFPROTO_UNSPEC)
e688a7f8 1216 list_add_tail_rcu(&type->list, &nf_tables_expressions);
758dbcec 1217 else
e688a7f8 1218 list_add_rcu(&type->list, &nf_tables_expressions);
96518518
PM
1219 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1220 return 0;
1221}
1222EXPORT_SYMBOL_GPL(nft_register_expr);
1223
1224/**
ef1f7df9
PM
1225 * nft_unregister_expr - unregister nf_tables expr type
1226 * @ops: expr type
96518518 1227 *
ef1f7df9 1228 * Unregisters the expr typefor use with nf_tables.
96518518 1229 */
ef1f7df9 1230void nft_unregister_expr(struct nft_expr_type *type)
96518518
PM
1231{
1232 nfnl_lock(NFNL_SUBSYS_NFTABLES);
e688a7f8 1233 list_del_rcu(&type->list);
96518518
PM
1234 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1235}
1236EXPORT_SYMBOL_GPL(nft_unregister_expr);
1237
64d46806
PM
1238static const struct nft_expr_type *__nft_expr_type_get(u8 family,
1239 struct nlattr *nla)
96518518 1240{
ef1f7df9 1241 const struct nft_expr_type *type;
96518518 1242
ef1f7df9 1243 list_for_each_entry(type, &nf_tables_expressions, list) {
64d46806
PM
1244 if (!nla_strcmp(nla, type->name) &&
1245 (!type->family || type->family == family))
ef1f7df9 1246 return type;
96518518
PM
1247 }
1248 return NULL;
1249}
1250
64d46806
PM
1251static const struct nft_expr_type *nft_expr_type_get(u8 family,
1252 struct nlattr *nla)
96518518 1253{
ef1f7df9 1254 const struct nft_expr_type *type;
96518518
PM
1255
1256 if (nla == NULL)
1257 return ERR_PTR(-EINVAL);
1258
64d46806 1259 type = __nft_expr_type_get(family, nla);
ef1f7df9
PM
1260 if (type != NULL && try_module_get(type->owner))
1261 return type;
96518518
PM
1262
1263#ifdef CONFIG_MODULES
ef1f7df9 1264 if (type == NULL) {
64d46806
PM
1265 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1266 request_module("nft-expr-%u-%.*s", family,
1267 nla_len(nla), (char *)nla_data(nla));
1268 nfnl_lock(NFNL_SUBSYS_NFTABLES);
1269 if (__nft_expr_type_get(family, nla))
1270 return ERR_PTR(-EAGAIN);
1271
96518518
PM
1272 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1273 request_module("nft-expr-%.*s",
1274 nla_len(nla), (char *)nla_data(nla));
1275 nfnl_lock(NFNL_SUBSYS_NFTABLES);
64d46806 1276 if (__nft_expr_type_get(family, nla))
96518518
PM
1277 return ERR_PTR(-EAGAIN);
1278 }
1279#endif
1280 return ERR_PTR(-ENOENT);
1281}
1282
1283static const struct nla_policy nft_expr_policy[NFTA_EXPR_MAX + 1] = {
1284 [NFTA_EXPR_NAME] = { .type = NLA_STRING },
1285 [NFTA_EXPR_DATA] = { .type = NLA_NESTED },
1286};
1287
1288static int nf_tables_fill_expr_info(struct sk_buff *skb,
1289 const struct nft_expr *expr)
1290{
ef1f7df9 1291 if (nla_put_string(skb, NFTA_EXPR_NAME, expr->ops->type->name))
96518518
PM
1292 goto nla_put_failure;
1293
1294 if (expr->ops->dump) {
1295 struct nlattr *data = nla_nest_start(skb, NFTA_EXPR_DATA);
1296 if (data == NULL)
1297 goto nla_put_failure;
1298 if (expr->ops->dump(skb, expr) < 0)
1299 goto nla_put_failure;
1300 nla_nest_end(skb, data);
1301 }
1302
1303 return skb->len;
1304
1305nla_put_failure:
1306 return -1;
1307};
1308
1309struct nft_expr_info {
1310 const struct nft_expr_ops *ops;
ef1f7df9 1311 struct nlattr *tb[NFT_EXPR_MAXATTR + 1];
96518518
PM
1312};
1313
0ca743a5
PNA
1314static int nf_tables_expr_parse(const struct nft_ctx *ctx,
1315 const struct nlattr *nla,
96518518
PM
1316 struct nft_expr_info *info)
1317{
ef1f7df9 1318 const struct nft_expr_type *type;
96518518 1319 const struct nft_expr_ops *ops;
ef1f7df9 1320 struct nlattr *tb[NFTA_EXPR_MAX + 1];
96518518
PM
1321 int err;
1322
ef1f7df9 1323 err = nla_parse_nested(tb, NFTA_EXPR_MAX, nla, nft_expr_policy);
96518518
PM
1324 if (err < 0)
1325 return err;
1326
64d46806 1327 type = nft_expr_type_get(ctx->afi->family, tb[NFTA_EXPR_NAME]);
ef1f7df9
PM
1328 if (IS_ERR(type))
1329 return PTR_ERR(type);
1330
1331 if (tb[NFTA_EXPR_DATA]) {
1332 err = nla_parse_nested(info->tb, type->maxattr,
1333 tb[NFTA_EXPR_DATA], type->policy);
1334 if (err < 0)
1335 goto err1;
1336 } else
1337 memset(info->tb, 0, sizeof(info->tb[0]) * (type->maxattr + 1));
1338
1339 if (type->select_ops != NULL) {
0ca743a5
PNA
1340 ops = type->select_ops(ctx,
1341 (const struct nlattr * const *)info->tb);
ef1f7df9
PM
1342 if (IS_ERR(ops)) {
1343 err = PTR_ERR(ops);
1344 goto err1;
1345 }
1346 } else
1347 ops = type->ops;
1348
96518518
PM
1349 info->ops = ops;
1350 return 0;
ef1f7df9
PM
1351
1352err1:
1353 module_put(type->owner);
1354 return err;
96518518
PM
1355}
1356
1357static int nf_tables_newexpr(const struct nft_ctx *ctx,
ef1f7df9 1358 const struct nft_expr_info *info,
96518518
PM
1359 struct nft_expr *expr)
1360{
1361 const struct nft_expr_ops *ops = info->ops;
1362 int err;
1363
1364 expr->ops = ops;
1365 if (ops->init) {
ef1f7df9 1366 err = ops->init(ctx, expr, (const struct nlattr **)info->tb);
96518518
PM
1367 if (err < 0)
1368 goto err1;
1369 }
1370
96518518
PM
1371 return 0;
1372
1373err1:
1374 expr->ops = NULL;
1375 return err;
1376}
1377
62472bce
PM
1378static void nf_tables_expr_destroy(const struct nft_ctx *ctx,
1379 struct nft_expr *expr)
96518518
PM
1380{
1381 if (expr->ops->destroy)
62472bce 1382 expr->ops->destroy(ctx, expr);
ef1f7df9 1383 module_put(expr->ops->type->owner);
96518518
PM
1384}
1385
1386/*
1387 * Rules
1388 */
1389
1390static struct nft_rule *__nf_tables_rule_lookup(const struct nft_chain *chain,
1391 u64 handle)
1392{
1393 struct nft_rule *rule;
1394
1395 // FIXME: this sucks
1396 list_for_each_entry(rule, &chain->rules, list) {
1397 if (handle == rule->handle)
1398 return rule;
1399 }
1400
1401 return ERR_PTR(-ENOENT);
1402}
1403
1404static struct nft_rule *nf_tables_rule_lookup(const struct nft_chain *chain,
1405 const struct nlattr *nla)
1406{
1407 if (nla == NULL)
1408 return ERR_PTR(-EINVAL);
1409
1410 return __nf_tables_rule_lookup(chain, be64_to_cpu(nla_get_be64(nla)));
1411}
1412
1413static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
1414 [NFTA_RULE_TABLE] = { .type = NLA_STRING },
1415 [NFTA_RULE_CHAIN] = { .type = NLA_STRING,
1416 .len = NFT_CHAIN_MAXNAMELEN - 1 },
1417 [NFTA_RULE_HANDLE] = { .type = NLA_U64 },
1418 [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED },
0ca743a5 1419 [NFTA_RULE_COMPAT] = { .type = NLA_NESTED },
5e948466 1420 [NFTA_RULE_POSITION] = { .type = NLA_U64 },
0768b3b3
PNA
1421 [NFTA_RULE_USERDATA] = { .type = NLA_BINARY,
1422 .len = NFT_USERDATA_MAXLEN },
96518518
PM
1423};
1424
1425static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
1426 int event, u32 flags, int family,
1427 const struct nft_table *table,
1428 const struct nft_chain *chain,
1429 const struct nft_rule *rule)
1430{
1431 struct nlmsghdr *nlh;
1432 struct nfgenmsg *nfmsg;
1433 const struct nft_expr *expr, *next;
1434 struct nlattr *list;
5e948466
EL
1435 const struct nft_rule *prule;
1436 int type = event | NFNL_SUBSYS_NFTABLES << 8;
96518518 1437
5e948466 1438 nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg),
96518518
PM
1439 flags);
1440 if (nlh == NULL)
1441 goto nla_put_failure;
1442
1443 nfmsg = nlmsg_data(nlh);
1444 nfmsg->nfgen_family = family;
1445 nfmsg->version = NFNETLINK_V0;
1446 nfmsg->res_id = 0;
1447
1448 if (nla_put_string(skb, NFTA_RULE_TABLE, table->name))
1449 goto nla_put_failure;
1450 if (nla_put_string(skb, NFTA_RULE_CHAIN, chain->name))
1451 goto nla_put_failure;
1452 if (nla_put_be64(skb, NFTA_RULE_HANDLE, cpu_to_be64(rule->handle)))
1453 goto nla_put_failure;
1454
5e948466
EL
1455 if ((event != NFT_MSG_DELRULE) && (rule->list.prev != &chain->rules)) {
1456 prule = list_entry(rule->list.prev, struct nft_rule, list);
1457 if (nla_put_be64(skb, NFTA_RULE_POSITION,
1458 cpu_to_be64(prule->handle)))
1459 goto nla_put_failure;
1460 }
1461
96518518
PM
1462 list = nla_nest_start(skb, NFTA_RULE_EXPRESSIONS);
1463 if (list == NULL)
1464 goto nla_put_failure;
1465 nft_rule_for_each_expr(expr, next, rule) {
1466 struct nlattr *elem = nla_nest_start(skb, NFTA_LIST_ELEM);
1467 if (elem == NULL)
1468 goto nla_put_failure;
1469 if (nf_tables_fill_expr_info(skb, expr) < 0)
1470 goto nla_put_failure;
1471 nla_nest_end(skb, elem);
1472 }
1473 nla_nest_end(skb, list);
1474
0768b3b3
PNA
1475 if (rule->ulen &&
1476 nla_put(skb, NFTA_RULE_USERDATA, rule->ulen, nft_userdata(rule)))
1477 goto nla_put_failure;
1478
96518518
PM
1479 return nlmsg_end(skb, nlh);
1480
1481nla_put_failure:
1482 nlmsg_trim(skb, nlh);
1483 return -1;
1484}
1485
35151d84 1486static int nf_tables_rule_notify(const struct nft_ctx *ctx,
96518518 1487 const struct nft_rule *rule,
35151d84 1488 int event)
96518518
PM
1489{
1490 struct sk_buff *skb;
96518518
PM
1491 int err;
1492
128ad332
PNA
1493 if (!ctx->report &&
1494 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
96518518
PM
1495 return 0;
1496
1497 err = -ENOBUFS;
1498 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1499 if (skb == NULL)
1500 goto err;
1501
128ad332 1502 err = nf_tables_fill_rule_info(skb, ctx->portid, ctx->seq, event, 0,
35151d84
PNA
1503 ctx->afi->family, ctx->table,
1504 ctx->chain, rule);
96518518
PM
1505 if (err < 0) {
1506 kfree_skb(skb);
1507 goto err;
1508 }
1509
128ad332
PNA
1510 err = nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1511 ctx->report, GFP_KERNEL);
96518518 1512err:
128ad332
PNA
1513 if (err < 0) {
1514 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1515 err);
1516 }
96518518
PM
1517 return err;
1518}
1519
0628b123
PNA
1520static inline bool
1521nft_rule_is_active(struct net *net, const struct nft_rule *rule)
1522{
1523 return (rule->genmask & (1 << net->nft.gencursor)) == 0;
1524}
1525
1526static inline int gencursor_next(struct net *net)
1527{
1528 return net->nft.gencursor+1 == 1 ? 1 : 0;
1529}
1530
1531static inline int
1532nft_rule_is_active_next(struct net *net, const struct nft_rule *rule)
1533{
1534 return (rule->genmask & (1 << gencursor_next(net))) == 0;
1535}
1536
1537static inline void
1538nft_rule_activate_next(struct net *net, struct nft_rule *rule)
1539{
1540 /* Now inactive, will be active in the future */
1541 rule->genmask = (1 << net->nft.gencursor);
1542}
1543
1544static inline void
1545nft_rule_disactivate_next(struct net *net, struct nft_rule *rule)
1546{
1547 rule->genmask = (1 << gencursor_next(net));
1548}
1549
1550static inline void nft_rule_clear(struct net *net, struct nft_rule *rule)
1551{
1552 rule->genmask = 0;
1553}
1554
96518518
PM
1555static int nf_tables_dump_rules(struct sk_buff *skb,
1556 struct netlink_callback *cb)
1557{
1558 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
1559 const struct nft_af_info *afi;
1560 const struct nft_table *table;
1561 const struct nft_chain *chain;
1562 const struct nft_rule *rule;
1563 unsigned int idx = 0, s_idx = cb->args[0];
99633ab2 1564 struct net *net = sock_net(skb->sk);
96518518
PM
1565 int family = nfmsg->nfgen_family;
1566
e688a7f8 1567 rcu_read_lock();
38e029f1
PNA
1568 cb->seq = net->nft.base_seq;
1569
e688a7f8 1570 list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
96518518
PM
1571 if (family != NFPROTO_UNSPEC && family != afi->family)
1572 continue;
1573
e688a7f8
PNA
1574 list_for_each_entry_rcu(table, &afi->tables, list) {
1575 list_for_each_entry_rcu(chain, &table->chains, list) {
1576 list_for_each_entry_rcu(rule, &chain->rules, list) {
0628b123
PNA
1577 if (!nft_rule_is_active(net, rule))
1578 goto cont;
96518518
PM
1579 if (idx < s_idx)
1580 goto cont;
1581 if (idx > s_idx)
1582 memset(&cb->args[1], 0,
1583 sizeof(cb->args) - sizeof(cb->args[0]));
1584 if (nf_tables_fill_rule_info(skb, NETLINK_CB(cb->skb).portid,
1585 cb->nlh->nlmsg_seq,
1586 NFT_MSG_NEWRULE,
1587 NLM_F_MULTI | NLM_F_APPEND,
1588 afi->family, table, chain, rule) < 0)
1589 goto done;
38e029f1
PNA
1590
1591 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
96518518
PM
1592cont:
1593 idx++;
1594 }
1595 }
1596 }
1597 }
1598done:
e688a7f8
PNA
1599 rcu_read_unlock();
1600
96518518
PM
1601 cb->args[0] = idx;
1602 return skb->len;
1603}
1604
1605static int nf_tables_getrule(struct sock *nlsk, struct sk_buff *skb,
1606 const struct nlmsghdr *nlh,
1607 const struct nlattr * const nla[])
1608{
1609 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1610 const struct nft_af_info *afi;
1611 const struct nft_table *table;
1612 const struct nft_chain *chain;
1613 const struct nft_rule *rule;
1614 struct sk_buff *skb2;
99633ab2 1615 struct net *net = sock_net(skb->sk);
96518518
PM
1616 int family = nfmsg->nfgen_family;
1617 int err;
1618
1619 if (nlh->nlmsg_flags & NLM_F_DUMP) {
1620 struct netlink_dump_control c = {
1621 .dump = nf_tables_dump_rules,
1622 };
1623 return netlink_dump_start(nlsk, skb, nlh, &c);
1624 }
1625
99633ab2 1626 afi = nf_tables_afinfo_lookup(net, family, false);
96518518
PM
1627 if (IS_ERR(afi))
1628 return PTR_ERR(afi);
1629
9370761c 1630 table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]);
96518518
PM
1631 if (IS_ERR(table))
1632 return PTR_ERR(table);
55dd6f93
PNA
1633 if (table->flags & NFT_TABLE_INACTIVE)
1634 return -ENOENT;
96518518
PM
1635
1636 chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
1637 if (IS_ERR(chain))
1638 return PTR_ERR(chain);
91c7b38d
PNA
1639 if (chain->flags & NFT_CHAIN_INACTIVE)
1640 return -ENOENT;
96518518
PM
1641
1642 rule = nf_tables_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
1643 if (IS_ERR(rule))
1644 return PTR_ERR(rule);
1645
1646 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1647 if (!skb2)
1648 return -ENOMEM;
1649
1650 err = nf_tables_fill_rule_info(skb2, NETLINK_CB(skb).portid,
1651 nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
1652 family, table, chain, rule);
1653 if (err < 0)
1654 goto err;
1655
1656 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
1657
1658err:
1659 kfree_skb(skb2);
1660 return err;
1661}
1662
62472bce
PM
1663static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
1664 struct nft_rule *rule)
96518518 1665{
96518518
PM
1666 struct nft_expr *expr;
1667
1668 /*
1669 * Careful: some expressions might not be initialized in case this
1670 * is called on error from nf_tables_newrule().
1671 */
1672 expr = nft_expr_first(rule);
1673 while (expr->ops && expr != nft_expr_last(rule)) {
62472bce 1674 nf_tables_expr_destroy(ctx, expr);
96518518
PM
1675 expr = nft_expr_next(expr);
1676 }
1677 kfree(rule);
1678}
1679
b380e5c7 1680static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx, int msg_type,
1081d11b 1681 struct nft_rule *rule)
0628b123 1682{
1081d11b 1683 struct nft_trans *trans;
0628b123 1684
b380e5c7 1685 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_rule));
1081d11b
PNA
1686 if (trans == NULL)
1687 return NULL;
0628b123 1688
1081d11b
PNA
1689 nft_trans_rule(trans) = rule;
1690 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
0628b123 1691
1081d11b 1692 return trans;
0628b123
PNA
1693}
1694
1081d11b
PNA
1695#define NFT_RULE_MAXEXPRS 128
1696
1697static struct nft_expr_info *info;
1698
96518518
PM
1699static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
1700 const struct nlmsghdr *nlh,
1701 const struct nlattr * const nla[])
1702{
1703 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7c95f6d8 1704 struct nft_af_info *afi;
99633ab2 1705 struct net *net = sock_net(skb->sk);
96518518
PM
1706 struct nft_table *table;
1707 struct nft_chain *chain;
1708 struct nft_rule *rule, *old_rule = NULL;
1081d11b 1709 struct nft_trans *trans = NULL;
96518518
PM
1710 struct nft_expr *expr;
1711 struct nft_ctx ctx;
1712 struct nlattr *tmp;
0768b3b3 1713 unsigned int size, i, n, ulen = 0;
96518518
PM
1714 int err, rem;
1715 bool create;
5e948466 1716 u64 handle, pos_handle;
96518518
PM
1717
1718 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
1719
99633ab2 1720 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create);
96518518
PM
1721 if (IS_ERR(afi))
1722 return PTR_ERR(afi);
1723
9370761c 1724 table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]);
96518518
PM
1725 if (IS_ERR(table))
1726 return PTR_ERR(table);
1727
1728 chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
1729 if (IS_ERR(chain))
1730 return PTR_ERR(chain);
1731
1732 if (nla[NFTA_RULE_HANDLE]) {
1733 handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_HANDLE]));
1734 rule = __nf_tables_rule_lookup(chain, handle);
1735 if (IS_ERR(rule))
1736 return PTR_ERR(rule);
1737
1738 if (nlh->nlmsg_flags & NLM_F_EXCL)
1739 return -EEXIST;
1740 if (nlh->nlmsg_flags & NLM_F_REPLACE)
1741 old_rule = rule;
1742 else
1743 return -EOPNOTSUPP;
1744 } else {
1745 if (!create || nlh->nlmsg_flags & NLM_F_REPLACE)
1746 return -EINVAL;
1747 handle = nf_tables_alloc_handle(table);
a0a7379e
PNA
1748
1749 if (chain->use == UINT_MAX)
1750 return -EOVERFLOW;
96518518
PM
1751 }
1752
5e948466
EL
1753 if (nla[NFTA_RULE_POSITION]) {
1754 if (!(nlh->nlmsg_flags & NLM_F_CREATE))
1755 return -EOPNOTSUPP;
1756
1757 pos_handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_POSITION]));
1758 old_rule = __nf_tables_rule_lookup(chain, pos_handle);
1759 if (IS_ERR(old_rule))
1760 return PTR_ERR(old_rule);
1761 }
1762
0ca743a5
PNA
1763 nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
1764
96518518
PM
1765 n = 0;
1766 size = 0;
1767 if (nla[NFTA_RULE_EXPRESSIONS]) {
1768 nla_for_each_nested(tmp, nla[NFTA_RULE_EXPRESSIONS], rem) {
1769 err = -EINVAL;
1770 if (nla_type(tmp) != NFTA_LIST_ELEM)
1771 goto err1;
1772 if (n == NFT_RULE_MAXEXPRS)
1773 goto err1;
0ca743a5 1774 err = nf_tables_expr_parse(&ctx, tmp, &info[n]);
96518518
PM
1775 if (err < 0)
1776 goto err1;
1777 size += info[n].ops->size;
1778 n++;
1779 }
1780 }
1781
0768b3b3
PNA
1782 if (nla[NFTA_RULE_USERDATA])
1783 ulen = nla_len(nla[NFTA_RULE_USERDATA]);
1784
96518518 1785 err = -ENOMEM;
0768b3b3 1786 rule = kzalloc(sizeof(*rule) + size + ulen, GFP_KERNEL);
96518518
PM
1787 if (rule == NULL)
1788 goto err1;
1789
0628b123
PNA
1790 nft_rule_activate_next(net, rule);
1791
96518518
PM
1792 rule->handle = handle;
1793 rule->dlen = size;
0768b3b3
PNA
1794 rule->ulen = ulen;
1795
1796 if (ulen)
1797 nla_memcpy(nft_userdata(rule), nla[NFTA_RULE_USERDATA], ulen);
96518518 1798
96518518
PM
1799 expr = nft_expr_first(rule);
1800 for (i = 0; i < n; i++) {
1801 err = nf_tables_newexpr(&ctx, &info[i], expr);
1802 if (err < 0)
1803 goto err2;
ef1f7df9 1804 info[i].ops = NULL;
96518518
PM
1805 expr = nft_expr_next(expr);
1806 }
1807
96518518 1808 if (nlh->nlmsg_flags & NLM_F_REPLACE) {
0628b123 1809 if (nft_rule_is_active_next(net, old_rule)) {
ac904ac8 1810 trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE,
b380e5c7 1811 old_rule);
1081d11b 1812 if (trans == NULL) {
0628b123
PNA
1813 err = -ENOMEM;
1814 goto err2;
1815 }
1816 nft_rule_disactivate_next(net, old_rule);
ac34b861 1817 chain->use--;
5bc5c307 1818 list_add_tail_rcu(&rule->list, &old_rule->list);
0628b123
PNA
1819 } else {
1820 err = -ENOENT;
1821 goto err2;
1822 }
96518518 1823 } else if (nlh->nlmsg_flags & NLM_F_APPEND)
5e948466
EL
1824 if (old_rule)
1825 list_add_rcu(&rule->list, &old_rule->list);
1826 else
1827 list_add_tail_rcu(&rule->list, &chain->rules);
1828 else {
1829 if (old_rule)
1830 list_add_tail_rcu(&rule->list, &old_rule->list);
1831 else
1832 list_add_rcu(&rule->list, &chain->rules);
1833 }
96518518 1834
b380e5c7 1835 if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
0628b123
PNA
1836 err = -ENOMEM;
1837 goto err3;
1838 }
4fefee57 1839 chain->use++;
96518518
PM
1840 return 0;
1841
0628b123
PNA
1842err3:
1843 list_del_rcu(&rule->list);
1081d11b
PNA
1844 if (trans) {
1845 list_del_rcu(&nft_trans_rule(trans)->list);
1846 nft_rule_clear(net, nft_trans_rule(trans));
1847 nft_trans_destroy(trans);
ac34b861 1848 chain->use++;
0628b123 1849 }
96518518 1850err2:
62472bce 1851 nf_tables_rule_destroy(&ctx, rule);
96518518
PM
1852err1:
1853 for (i = 0; i < n; i++) {
1854 if (info[i].ops != NULL)
ef1f7df9 1855 module_put(info[i].ops->type->owner);
96518518
PM
1856 }
1857 return err;
1858}
1859
0628b123
PNA
1860static int
1861nf_tables_delrule_one(struct nft_ctx *ctx, struct nft_rule *rule)
1862{
1863 /* You cannot delete the same rule twice */
1864 if (nft_rule_is_active_next(ctx->net, rule)) {
b380e5c7 1865 if (nft_trans_rule_add(ctx, NFT_MSG_DELRULE, rule) == NULL)
0628b123
PNA
1866 return -ENOMEM;
1867 nft_rule_disactivate_next(ctx->net, rule);
4fefee57 1868 ctx->chain->use--;
0628b123
PNA
1869 return 0;
1870 }
1871 return -ENOENT;
1872}
1873
cf9dc09d
PNA
1874static int nf_table_delrule_by_chain(struct nft_ctx *ctx)
1875{
1876 struct nft_rule *rule;
1877 int err;
1878
1879 list_for_each_entry(rule, &ctx->chain->rules, list) {
1880 err = nf_tables_delrule_one(ctx, rule);
1881 if (err < 0)
1882 return err;
1883 }
1884 return 0;
1885}
1886
96518518
PM
1887static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
1888 const struct nlmsghdr *nlh,
1889 const struct nlattr * const nla[])
1890{
1891 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7c95f6d8 1892 struct nft_af_info *afi;
99633ab2 1893 struct net *net = sock_net(skb->sk);
7c95f6d8 1894 struct nft_table *table;
cf9dc09d
PNA
1895 struct nft_chain *chain = NULL;
1896 struct nft_rule *rule;
0628b123
PNA
1897 int family = nfmsg->nfgen_family, err = 0;
1898 struct nft_ctx ctx;
96518518 1899
99633ab2 1900 afi = nf_tables_afinfo_lookup(net, family, false);
96518518
PM
1901 if (IS_ERR(afi))
1902 return PTR_ERR(afi);
1903
9370761c 1904 table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]);
96518518
PM
1905 if (IS_ERR(table))
1906 return PTR_ERR(table);
55dd6f93
PNA
1907 if (table->flags & NFT_TABLE_INACTIVE)
1908 return -ENOENT;
96518518 1909
cf9dc09d
PNA
1910 if (nla[NFTA_RULE_CHAIN]) {
1911 chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
1912 if (IS_ERR(chain))
1913 return PTR_ERR(chain);
1914 }
96518518 1915
0628b123
PNA
1916 nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
1917
cf9dc09d
PNA
1918 if (chain) {
1919 if (nla[NFTA_RULE_HANDLE]) {
1920 rule = nf_tables_rule_lookup(chain,
1921 nla[NFTA_RULE_HANDLE]);
1922 if (IS_ERR(rule))
1923 return PTR_ERR(rule);
96518518 1924
0628b123 1925 err = nf_tables_delrule_one(&ctx, rule);
cf9dc09d
PNA
1926 } else {
1927 err = nf_table_delrule_by_chain(&ctx);
1928 }
1929 } else {
1930 list_for_each_entry(chain, &table->chains, list) {
1931 ctx.chain = chain;
1932 err = nf_table_delrule_by_chain(&ctx);
0628b123
PNA
1933 if (err < 0)
1934 break;
1935 }
1936 }
1937
1938 return err;
1939}
1940
20a69341
PM
1941/*
1942 * Sets
1943 */
1944
1945static LIST_HEAD(nf_tables_set_ops);
1946
1947int nft_register_set(struct nft_set_ops *ops)
1948{
1949 nfnl_lock(NFNL_SUBSYS_NFTABLES);
e688a7f8 1950 list_add_tail_rcu(&ops->list, &nf_tables_set_ops);
20a69341
PM
1951 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1952 return 0;
1953}
1954EXPORT_SYMBOL_GPL(nft_register_set);
1955
1956void nft_unregister_set(struct nft_set_ops *ops)
1957{
1958 nfnl_lock(NFNL_SUBSYS_NFTABLES);
e688a7f8 1959 list_del_rcu(&ops->list);
20a69341
PM
1960 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1961}
1962EXPORT_SYMBOL_GPL(nft_unregister_set);
1963
c50b960c
PM
1964/*
1965 * Select a set implementation based on the data characteristics and the
1966 * given policy. The total memory use might not be known if no size is
1967 * given, in that case the amount of memory per element is used.
1968 */
1969static const struct nft_set_ops *
1970nft_select_set_ops(const struct nlattr * const nla[],
1971 const struct nft_set_desc *desc,
1972 enum nft_set_policies policy)
20a69341 1973{
c50b960c
PM
1974 const struct nft_set_ops *ops, *bops;
1975 struct nft_set_estimate est, best;
20a69341
PM
1976 u32 features;
1977
1978#ifdef CONFIG_MODULES
1979 if (list_empty(&nf_tables_set_ops)) {
1980 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1981 request_module("nft-set");
1982 nfnl_lock(NFNL_SUBSYS_NFTABLES);
1983 if (!list_empty(&nf_tables_set_ops))
1984 return ERR_PTR(-EAGAIN);
1985 }
1986#endif
1987 features = 0;
1988 if (nla[NFTA_SET_FLAGS] != NULL) {
1989 features = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
1990 features &= NFT_SET_INTERVAL | NFT_SET_MAP;
1991 }
1992
c50b960c
PM
1993 bops = NULL;
1994 best.size = ~0;
1995 best.class = ~0;
1996
20a69341
PM
1997 list_for_each_entry(ops, &nf_tables_set_ops, list) {
1998 if ((ops->features & features) != features)
1999 continue;
c50b960c
PM
2000 if (!ops->estimate(desc, features, &est))
2001 continue;
2002
2003 switch (policy) {
2004 case NFT_SET_POL_PERFORMANCE:
2005 if (est.class < best.class)
2006 break;
2007 if (est.class == best.class && est.size < best.size)
2008 break;
2009 continue;
2010 case NFT_SET_POL_MEMORY:
2011 if (est.size < best.size)
2012 break;
2013 if (est.size == best.size && est.class < best.class)
2014 break;
2015 continue;
2016 default:
2017 break;
2018 }
2019
20a69341
PM
2020 if (!try_module_get(ops->owner))
2021 continue;
c50b960c
PM
2022 if (bops != NULL)
2023 module_put(bops->owner);
2024
2025 bops = ops;
2026 best = est;
20a69341
PM
2027 }
2028
c50b960c
PM
2029 if (bops != NULL)
2030 return bops;
2031
20a69341
PM
2032 return ERR_PTR(-EOPNOTSUPP);
2033}
2034
2035static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
2036 [NFTA_SET_TABLE] = { .type = NLA_STRING },
a9bdd836
PNA
2037 [NFTA_SET_NAME] = { .type = NLA_STRING,
2038 .len = IFNAMSIZ - 1 },
20a69341
PM
2039 [NFTA_SET_FLAGS] = { .type = NLA_U32 },
2040 [NFTA_SET_KEY_TYPE] = { .type = NLA_U32 },
2041 [NFTA_SET_KEY_LEN] = { .type = NLA_U32 },
2042 [NFTA_SET_DATA_TYPE] = { .type = NLA_U32 },
2043 [NFTA_SET_DATA_LEN] = { .type = NLA_U32 },
c50b960c
PM
2044 [NFTA_SET_POLICY] = { .type = NLA_U32 },
2045 [NFTA_SET_DESC] = { .type = NLA_NESTED },
958bee14 2046 [NFTA_SET_ID] = { .type = NLA_U32 },
c50b960c
PM
2047};
2048
2049static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
2050 [NFTA_SET_DESC_SIZE] = { .type = NLA_U32 },
20a69341
PM
2051};
2052
2053static int nft_ctx_init_from_setattr(struct nft_ctx *ctx,
2054 const struct sk_buff *skb,
2055 const struct nlmsghdr *nlh,
2056 const struct nlattr * const nla[])
2057{
99633ab2 2058 struct net *net = sock_net(skb->sk);
20a69341 2059 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7c95f6d8
PNA
2060 struct nft_af_info *afi = NULL;
2061 struct nft_table *table = NULL;
20a69341 2062
c9c8e485
PNA
2063 if (nfmsg->nfgen_family != NFPROTO_UNSPEC) {
2064 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
2065 if (IS_ERR(afi))
2066 return PTR_ERR(afi);
2067 }
20a69341
PM
2068
2069 if (nla[NFTA_SET_TABLE] != NULL) {
ec2c9935
PM
2070 if (afi == NULL)
2071 return -EAFNOSUPPORT;
2072
9370761c 2073 table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]);
20a69341
PM
2074 if (IS_ERR(table))
2075 return PTR_ERR(table);
55dd6f93
PNA
2076 if (table->flags & NFT_TABLE_INACTIVE)
2077 return -ENOENT;
20a69341
PM
2078 }
2079
0ca743a5 2080 nft_ctx_init(ctx, skb, nlh, afi, table, NULL, nla);
20a69341
PM
2081 return 0;
2082}
2083
2084struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
2085 const struct nlattr *nla)
2086{
2087 struct nft_set *set;
2088
2089 if (nla == NULL)
2090 return ERR_PTR(-EINVAL);
2091
2092 list_for_each_entry(set, &table->sets, list) {
2093 if (!nla_strcmp(nla, set->name))
2094 return set;
2095 }
2096 return ERR_PTR(-ENOENT);
2097}
2098
958bee14
PNA
2099struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
2100 const struct nlattr *nla)
2101{
2102 struct nft_trans *trans;
2103 u32 id = ntohl(nla_get_be32(nla));
2104
2105 list_for_each_entry(trans, &net->nft.commit_list, list) {
2106 if (trans->msg_type == NFT_MSG_NEWSET &&
2107 id == nft_trans_set_id(trans))
2108 return nft_trans_set(trans);
2109 }
2110 return ERR_PTR(-ENOENT);
2111}
2112
20a69341
PM
2113static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
2114 const char *name)
2115{
2116 const struct nft_set *i;
2117 const char *p;
2118 unsigned long *inuse;
60eb1894 2119 unsigned int n = 0, min = 0;
20a69341
PM
2120
2121 p = strnchr(name, IFNAMSIZ, '%');
2122 if (p != NULL) {
2123 if (p[1] != 'd' || strchr(p + 2, '%'))
2124 return -EINVAL;
2125
2126 inuse = (unsigned long *)get_zeroed_page(GFP_KERNEL);
2127 if (inuse == NULL)
2128 return -ENOMEM;
60eb1894 2129cont:
20a69341 2130 list_for_each_entry(i, &ctx->table->sets, list) {
14662917
DB
2131 int tmp;
2132
2133 if (!sscanf(i->name, name, &tmp))
20a69341 2134 continue;
60eb1894 2135 if (tmp < min || tmp >= min + BITS_PER_BYTE * PAGE_SIZE)
20a69341 2136 continue;
14662917 2137
60eb1894 2138 set_bit(tmp - min, inuse);
20a69341
PM
2139 }
2140
53b70287 2141 n = find_first_zero_bit(inuse, BITS_PER_BYTE * PAGE_SIZE);
60eb1894
PM
2142 if (n >= BITS_PER_BYTE * PAGE_SIZE) {
2143 min += BITS_PER_BYTE * PAGE_SIZE;
2144 memset(inuse, 0, PAGE_SIZE);
2145 goto cont;
2146 }
20a69341
PM
2147 free_page((unsigned long)inuse);
2148 }
2149
60eb1894 2150 snprintf(set->name, sizeof(set->name), name, min + n);
20a69341
PM
2151 list_for_each_entry(i, &ctx->table->sets, list) {
2152 if (!strcmp(set->name, i->name))
2153 return -ENFILE;
2154 }
2155 return 0;
2156}
2157
2158static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
2159 const struct nft_set *set, u16 event, u16 flags)
2160{
2161 struct nfgenmsg *nfmsg;
2162 struct nlmsghdr *nlh;
c50b960c 2163 struct nlattr *desc;
128ad332
PNA
2164 u32 portid = ctx->portid;
2165 u32 seq = ctx->seq;
20a69341
PM
2166
2167 event |= NFNL_SUBSYS_NFTABLES << 8;
2168 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),
2169 flags);
2170 if (nlh == NULL)
2171 goto nla_put_failure;
2172
2173 nfmsg = nlmsg_data(nlh);
2174 nfmsg->nfgen_family = ctx->afi->family;
2175 nfmsg->version = NFNETLINK_V0;
2176 nfmsg->res_id = 0;
2177
2178 if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name))
2179 goto nla_put_failure;
2180 if (nla_put_string(skb, NFTA_SET_NAME, set->name))
2181 goto nla_put_failure;
2182 if (set->flags != 0)
2183 if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags)))
2184 goto nla_put_failure;
2185
2186 if (nla_put_be32(skb, NFTA_SET_KEY_TYPE, htonl(set->ktype)))
2187 goto nla_put_failure;
2188 if (nla_put_be32(skb, NFTA_SET_KEY_LEN, htonl(set->klen)))
2189 goto nla_put_failure;
2190 if (set->flags & NFT_SET_MAP) {
2191 if (nla_put_be32(skb, NFTA_SET_DATA_TYPE, htonl(set->dtype)))
2192 goto nla_put_failure;
2193 if (nla_put_be32(skb, NFTA_SET_DATA_LEN, htonl(set->dlen)))
2194 goto nla_put_failure;
2195 }
2196
c50b960c
PM
2197 desc = nla_nest_start(skb, NFTA_SET_DESC);
2198 if (desc == NULL)
2199 goto nla_put_failure;
2200 if (set->size &&
2201 nla_put_be32(skb, NFTA_SET_DESC_SIZE, htonl(set->size)))
2202 goto nla_put_failure;
2203 nla_nest_end(skb, desc);
2204
20a69341
PM
2205 return nlmsg_end(skb, nlh);
2206
2207nla_put_failure:
2208 nlmsg_trim(skb, nlh);
2209 return -1;
2210}
2211
2212static int nf_tables_set_notify(const struct nft_ctx *ctx,
2213 const struct nft_set *set,
31f8441c 2214 int event, gfp_t gfp_flags)
20a69341
PM
2215{
2216 struct sk_buff *skb;
128ad332 2217 u32 portid = ctx->portid;
20a69341
PM
2218 int err;
2219
128ad332
PNA
2220 if (!ctx->report &&
2221 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
20a69341
PM
2222 return 0;
2223
2224 err = -ENOBUFS;
31f8441c 2225 skb = nlmsg_new(NLMSG_GOODSIZE, gfp_flags);
20a69341
PM
2226 if (skb == NULL)
2227 goto err;
2228
2229 err = nf_tables_fill_set(skb, ctx, set, event, 0);
2230 if (err < 0) {
2231 kfree_skb(skb);
2232 goto err;
2233 }
2234
128ad332 2235 err = nfnetlink_send(skb, ctx->net, portid, NFNLGRP_NFTABLES,
31f8441c 2236 ctx->report, gfp_flags);
20a69341
PM
2237err:
2238 if (err < 0)
99633ab2 2239 nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, err);
20a69341
PM
2240 return err;
2241}
2242
2243static int nf_tables_dump_sets_table(struct nft_ctx *ctx, struct sk_buff *skb,
2244 struct netlink_callback *cb)
2245{
2246 const struct nft_set *set;
2247 unsigned int idx = 0, s_idx = cb->args[0];
2248
2249 if (cb->args[1])
2250 return skb->len;
2251
e688a7f8 2252 rcu_read_lock();
38e029f1
PNA
2253 cb->seq = ctx->net->nft.base_seq;
2254
e688a7f8 2255 list_for_each_entry_rcu(set, &ctx->table->sets, list) {
20a69341
PM
2256 if (idx < s_idx)
2257 goto cont;
2258 if (nf_tables_fill_set(skb, ctx, set, NFT_MSG_NEWSET,
2259 NLM_F_MULTI) < 0) {
2260 cb->args[0] = idx;
2261 goto done;
2262 }
38e029f1 2263 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
20a69341
PM
2264cont:
2265 idx++;
2266 }
2267 cb->args[1] = 1;
2268done:
e688a7f8 2269 rcu_read_unlock();
20a69341
PM
2270 return skb->len;
2271}
2272
c9c8e485
PNA
2273static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb,
2274 struct netlink_callback *cb)
20a69341
PM
2275{
2276 const struct nft_set *set;
e38195bf 2277 unsigned int idx, s_idx = cb->args[0];
20a69341
PM
2278 struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
2279
2280 if (cb->args[1])
2281 return skb->len;
2282
e688a7f8 2283 rcu_read_lock();
38e029f1
PNA
2284 cb->seq = ctx->net->nft.base_seq;
2285
e688a7f8 2286 list_for_each_entry_rcu(table, &ctx->afi->tables, list) {
e38195bf
PNA
2287 if (cur_table) {
2288 if (cur_table != table)
2289 continue;
20a69341 2290
e38195bf
PNA
2291 cur_table = NULL;
2292 }
20a69341 2293 ctx->table = table;
e38195bf 2294 idx = 0;
e688a7f8 2295 list_for_each_entry_rcu(set, &ctx->table->sets, list) {
20a69341
PM
2296 if (idx < s_idx)
2297 goto cont;
2298 if (nf_tables_fill_set(skb, ctx, set, NFT_MSG_NEWSET,
2299 NLM_F_MULTI) < 0) {
2300 cb->args[0] = idx;
2301 cb->args[2] = (unsigned long) table;
2302 goto done;
2303 }
38e029f1 2304 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
20a69341
PM
2305cont:
2306 idx++;
2307 }
2308 }
2309 cb->args[1] = 1;
2310done:
e688a7f8 2311 rcu_read_unlock();
20a69341
PM
2312 return skb->len;
2313}
2314
c9c8e485
PNA
2315static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
2316 struct netlink_callback *cb)
2317{
2318 const struct nft_set *set;
2319 unsigned int idx, s_idx = cb->args[0];
7c95f6d8 2320 struct nft_af_info *afi;
c9c8e485
PNA
2321 struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
2322 struct net *net = sock_net(skb->sk);
2323 int cur_family = cb->args[3];
2324
2325 if (cb->args[1])
2326 return skb->len;
2327
e688a7f8 2328 rcu_read_lock();
38e029f1
PNA
2329 cb->seq = net->nft.base_seq;
2330
e688a7f8 2331 list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
c9c8e485
PNA
2332 if (cur_family) {
2333 if (afi->family != cur_family)
2334 continue;
2335
2336 cur_family = 0;
2337 }
2338
e688a7f8 2339 list_for_each_entry_rcu(table, &afi->tables, list) {
c9c8e485
PNA
2340 if (cur_table) {
2341 if (cur_table != table)
2342 continue;
2343
2344 cur_table = NULL;
2345 }
2346
2347 ctx->table = table;
2348 ctx->afi = afi;
2349 idx = 0;
e688a7f8 2350 list_for_each_entry_rcu(set, &ctx->table->sets, list) {
c9c8e485
PNA
2351 if (idx < s_idx)
2352 goto cont;
2353 if (nf_tables_fill_set(skb, ctx, set,
2354 NFT_MSG_NEWSET,
2355 NLM_F_MULTI) < 0) {
2356 cb->args[0] = idx;
2357 cb->args[2] = (unsigned long) table;
2358 cb->args[3] = afi->family;
2359 goto done;
2360 }
38e029f1 2361 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
c9c8e485
PNA
2362cont:
2363 idx++;
2364 }
2365 if (s_idx)
2366 s_idx = 0;
2367 }
2368 }
2369 cb->args[1] = 1;
2370done:
e688a7f8 2371 rcu_read_unlock();
c9c8e485
PNA
2372 return skb->len;
2373}
2374
20a69341
PM
2375static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
2376{
2377 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
2378 struct nlattr *nla[NFTA_SET_MAX + 1];
2379 struct nft_ctx ctx;
2380 int err, ret;
2381
2382 err = nlmsg_parse(cb->nlh, sizeof(*nfmsg), nla, NFTA_SET_MAX,
2383 nft_set_policy);
2384 if (err < 0)
2385 return err;
2386
2387 err = nft_ctx_init_from_setattr(&ctx, cb->skb, cb->nlh, (void *)nla);
2388 if (err < 0)
2389 return err;
2390
c9c8e485
PNA
2391 if (ctx.table == NULL) {
2392 if (ctx.afi == NULL)
2393 ret = nf_tables_dump_sets_all(&ctx, skb, cb);
2394 else
2395 ret = nf_tables_dump_sets_family(&ctx, skb, cb);
2396 } else
20a69341
PM
2397 ret = nf_tables_dump_sets_table(&ctx, skb, cb);
2398
2399 return ret;
2400}
2401
958bee14
PNA
2402#define NFT_SET_INACTIVE (1 << 15) /* Internal set flag */
2403
20a69341
PM
2404static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
2405 const struct nlmsghdr *nlh,
2406 const struct nlattr * const nla[])
2407{
2408 const struct nft_set *set;
2409 struct nft_ctx ctx;
2410 struct sk_buff *skb2;
c9c8e485 2411 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
20a69341
PM
2412 int err;
2413
2414 /* Verify existance before starting dump */
2415 err = nft_ctx_init_from_setattr(&ctx, skb, nlh, nla);
2416 if (err < 0)
2417 return err;
2418
2419 if (nlh->nlmsg_flags & NLM_F_DUMP) {
2420 struct netlink_dump_control c = {
2421 .dump = nf_tables_dump_sets,
2422 };
2423 return netlink_dump_start(nlsk, skb, nlh, &c);
2424 }
2425
c9c8e485
PNA
2426 /* Only accept unspec with dump */
2427 if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
2428 return -EAFNOSUPPORT;
2429
20a69341
PM
2430 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
2431 if (IS_ERR(set))
2432 return PTR_ERR(set);
958bee14
PNA
2433 if (set->flags & NFT_SET_INACTIVE)
2434 return -ENOENT;
20a69341
PM
2435
2436 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
2437 if (skb2 == NULL)
2438 return -ENOMEM;
2439
2440 err = nf_tables_fill_set(skb2, &ctx, set, NFT_MSG_NEWSET, 0);
2441 if (err < 0)
2442 goto err;
2443
2444 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
2445
2446err:
2447 kfree_skb(skb2);
2448 return err;
2449}
2450
c50b960c
PM
2451static int nf_tables_set_desc_parse(const struct nft_ctx *ctx,
2452 struct nft_set_desc *desc,
2453 const struct nlattr *nla)
2454{
2455 struct nlattr *da[NFTA_SET_DESC_MAX + 1];
2456 int err;
2457
2458 err = nla_parse_nested(da, NFTA_SET_DESC_MAX, nla, nft_set_desc_policy);
2459 if (err < 0)
2460 return err;
2461
2462 if (da[NFTA_SET_DESC_SIZE] != NULL)
2463 desc->size = ntohl(nla_get_be32(da[NFTA_SET_DESC_SIZE]));
2464
2465 return 0;
2466}
2467
958bee14
PNA
2468static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type,
2469 struct nft_set *set)
2470{
2471 struct nft_trans *trans;
2472
2473 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_set));
2474 if (trans == NULL)
2475 return -ENOMEM;
2476
2477 if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) {
2478 nft_trans_set_id(trans) =
2479 ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID]));
2480 set->flags |= NFT_SET_INACTIVE;
2481 }
2482 nft_trans_set(trans) = set;
2483 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
2484
2485 return 0;
2486}
2487
20a69341
PM
2488static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2489 const struct nlmsghdr *nlh,
2490 const struct nlattr * const nla[])
2491{
2492 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
2493 const struct nft_set_ops *ops;
7c95f6d8 2494 struct nft_af_info *afi;
99633ab2 2495 struct net *net = sock_net(skb->sk);
20a69341
PM
2496 struct nft_table *table;
2497 struct nft_set *set;
2498 struct nft_ctx ctx;
2499 char name[IFNAMSIZ];
2500 unsigned int size;
2501 bool create;
c50b960c
PM
2502 u32 ktype, dtype, flags, policy;
2503 struct nft_set_desc desc;
20a69341
PM
2504 int err;
2505
2506 if (nla[NFTA_SET_TABLE] == NULL ||
2507 nla[NFTA_SET_NAME] == NULL ||
958bee14
PNA
2508 nla[NFTA_SET_KEY_LEN] == NULL ||
2509 nla[NFTA_SET_ID] == NULL)
20a69341
PM
2510 return -EINVAL;
2511
c50b960c
PM
2512 memset(&desc, 0, sizeof(desc));
2513
20a69341
PM
2514 ktype = NFT_DATA_VALUE;
2515 if (nla[NFTA_SET_KEY_TYPE] != NULL) {
2516 ktype = ntohl(nla_get_be32(nla[NFTA_SET_KEY_TYPE]));
2517 if ((ktype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK)
2518 return -EINVAL;
2519 }
2520
c50b960c
PM
2521 desc.klen = ntohl(nla_get_be32(nla[NFTA_SET_KEY_LEN]));
2522 if (desc.klen == 0 || desc.klen > FIELD_SIZEOF(struct nft_data, data))
20a69341
PM
2523 return -EINVAL;
2524
2525 flags = 0;
2526 if (nla[NFTA_SET_FLAGS] != NULL) {
2527 flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
2528 if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
2529 NFT_SET_INTERVAL | NFT_SET_MAP))
2530 return -EINVAL;
2531 }
2532
2533 dtype = 0;
20a69341
PM
2534 if (nla[NFTA_SET_DATA_TYPE] != NULL) {
2535 if (!(flags & NFT_SET_MAP))
2536 return -EINVAL;
2537
2538 dtype = ntohl(nla_get_be32(nla[NFTA_SET_DATA_TYPE]));
2539 if ((dtype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK &&
2540 dtype != NFT_DATA_VERDICT)
2541 return -EINVAL;
2542
2543 if (dtype != NFT_DATA_VERDICT) {
2544 if (nla[NFTA_SET_DATA_LEN] == NULL)
2545 return -EINVAL;
c50b960c
PM
2546 desc.dlen = ntohl(nla_get_be32(nla[NFTA_SET_DATA_LEN]));
2547 if (desc.dlen == 0 ||
2548 desc.dlen > FIELD_SIZEOF(struct nft_data, data))
20a69341
PM
2549 return -EINVAL;
2550 } else
c50b960c 2551 desc.dlen = sizeof(struct nft_data);
20a69341
PM
2552 } else if (flags & NFT_SET_MAP)
2553 return -EINVAL;
2554
c50b960c
PM
2555 policy = NFT_SET_POL_PERFORMANCE;
2556 if (nla[NFTA_SET_POLICY] != NULL)
2557 policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY]));
2558
2559 if (nla[NFTA_SET_DESC] != NULL) {
2560 err = nf_tables_set_desc_parse(&ctx, &desc, nla[NFTA_SET_DESC]);
2561 if (err < 0)
2562 return err;
2563 }
2564
20a69341
PM
2565 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
2566
99633ab2 2567 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create);
20a69341
PM
2568 if (IS_ERR(afi))
2569 return PTR_ERR(afi);
2570
9370761c 2571 table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]);
20a69341
PM
2572 if (IS_ERR(table))
2573 return PTR_ERR(table);
2574
0ca743a5 2575 nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
20a69341
PM
2576
2577 set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME]);
2578 if (IS_ERR(set)) {
2579 if (PTR_ERR(set) != -ENOENT)
2580 return PTR_ERR(set);
2581 set = NULL;
2582 }
2583
2584 if (set != NULL) {
2585 if (nlh->nlmsg_flags & NLM_F_EXCL)
2586 return -EEXIST;
2587 if (nlh->nlmsg_flags & NLM_F_REPLACE)
2588 return -EOPNOTSUPP;
2589 return 0;
2590 }
2591
2592 if (!(nlh->nlmsg_flags & NLM_F_CREATE))
2593 return -ENOENT;
2594
c50b960c 2595 ops = nft_select_set_ops(nla, &desc, policy);
20a69341
PM
2596 if (IS_ERR(ops))
2597 return PTR_ERR(ops);
2598
2599 size = 0;
2600 if (ops->privsize != NULL)
2601 size = ops->privsize(nla);
2602
2603 err = -ENOMEM;
2604 set = kzalloc(sizeof(*set) + size, GFP_KERNEL);
2605 if (set == NULL)
2606 goto err1;
2607
2608 nla_strlcpy(name, nla[NFTA_SET_NAME], sizeof(set->name));
2609 err = nf_tables_set_alloc_name(&ctx, set, name);
2610 if (err < 0)
2611 goto err2;
2612
2613 INIT_LIST_HEAD(&set->bindings);
2614 set->ops = ops;
2615 set->ktype = ktype;
c50b960c 2616 set->klen = desc.klen;
20a69341 2617 set->dtype = dtype;
c50b960c 2618 set->dlen = desc.dlen;
20a69341 2619 set->flags = flags;
c50b960c 2620 set->size = desc.size;
20a69341 2621
c50b960c 2622 err = ops->init(set, &desc, nla);
20a69341
PM
2623 if (err < 0)
2624 goto err2;
2625
958bee14 2626 err = nft_trans_set_add(&ctx, NFT_MSG_NEWSET, set);
20a69341
PM
2627 if (err < 0)
2628 goto err2;
2629
e688a7f8 2630 list_add_tail_rcu(&set->list, &table->sets);
4fefee57 2631 table->use++;
20a69341
PM
2632 return 0;
2633
2634err2:
2635 kfree(set);
2636err1:
2637 module_put(ops->owner);
2638 return err;
2639}
2640
958bee14 2641static void nft_set_destroy(struct nft_set *set)
20a69341 2642{
20a69341
PM
2643 set->ops->destroy(set);
2644 module_put(set->ops->owner);
2645 kfree(set);
2646}
2647
958bee14
PNA
2648static void nf_tables_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
2649{
e688a7f8 2650 list_del_rcu(&set->list);
31f8441c 2651 nf_tables_set_notify(ctx, set, NFT_MSG_DELSET, GFP_ATOMIC);
958bee14
PNA
2652 nft_set_destroy(set);
2653}
2654
20a69341
PM
2655static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
2656 const struct nlmsghdr *nlh,
2657 const struct nlattr * const nla[])
2658{
c9c8e485 2659 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
20a69341
PM
2660 struct nft_set *set;
2661 struct nft_ctx ctx;
2662 int err;
2663
ec2c9935
PM
2664 if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
2665 return -EAFNOSUPPORT;
20a69341
PM
2666 if (nla[NFTA_SET_TABLE] == NULL)
2667 return -EINVAL;
2668
2669 err = nft_ctx_init_from_setattr(&ctx, skb, nlh, nla);
2670 if (err < 0)
2671 return err;
2672
2673 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
2674 if (IS_ERR(set))
2675 return PTR_ERR(set);
958bee14
PNA
2676 if (set->flags & NFT_SET_INACTIVE)
2677 return -ENOENT;
20a69341
PM
2678 if (!list_empty(&set->bindings))
2679 return -EBUSY;
2680
958bee14
PNA
2681 err = nft_trans_set_add(&ctx, NFT_MSG_DELSET, set);
2682 if (err < 0)
2683 return err;
2684
e688a7f8 2685 list_del_rcu(&set->list);
4fefee57 2686 ctx.table->use--;
20a69341
PM
2687 return 0;
2688}
2689
2690static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
2691 const struct nft_set *set,
2692 const struct nft_set_iter *iter,
2693 const struct nft_set_elem *elem)
2694{
2695 enum nft_registers dreg;
2696
2697 dreg = nft_type_to_reg(set->dtype);
2ee0d3c8
PNA
2698 return nft_validate_data_load(ctx, dreg, &elem->data,
2699 set->dtype == NFT_DATA_VERDICT ?
2700 NFT_DATA_VERDICT : NFT_DATA_VALUE);
20a69341
PM
2701}
2702
2703int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
2704 struct nft_set_binding *binding)
2705{
2706 struct nft_set_binding *i;
2707 struct nft_set_iter iter;
2708
2709 if (!list_empty(&set->bindings) && set->flags & NFT_SET_ANONYMOUS)
2710 return -EBUSY;
2711
2712 if (set->flags & NFT_SET_MAP) {
2713 /* If the set is already bound to the same chain all
2714 * jumps are already validated for that chain.
2715 */
2716 list_for_each_entry(i, &set->bindings, list) {
2717 if (i->chain == binding->chain)
2718 goto bind;
2719 }
2720
2721 iter.skip = 0;
2722 iter.count = 0;
2723 iter.err = 0;
2724 iter.fn = nf_tables_bind_check_setelem;
2725
2726 set->ops->walk(ctx, set, &iter);
2727 if (iter.err < 0) {
2728 /* Destroy anonymous sets if binding fails */
2729 if (set->flags & NFT_SET_ANONYMOUS)
2730 nf_tables_set_destroy(ctx, set);
2731
2732 return iter.err;
2733 }
2734 }
2735bind:
2736 binding->chain = ctx->chain;
e688a7f8 2737 list_add_tail_rcu(&binding->list, &set->bindings);
20a69341
PM
2738 return 0;
2739}
2740
2741void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
2742 struct nft_set_binding *binding)
2743{
e688a7f8 2744 list_del_rcu(&binding->list);
20a69341 2745
958bee14
PNA
2746 if (list_empty(&set->bindings) && set->flags & NFT_SET_ANONYMOUS &&
2747 !(set->flags & NFT_SET_INACTIVE))
20a69341
PM
2748 nf_tables_set_destroy(ctx, set);
2749}
2750
2751/*
2752 * Set elements
2753 */
2754
2755static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
2756 [NFTA_SET_ELEM_KEY] = { .type = NLA_NESTED },
2757 [NFTA_SET_ELEM_DATA] = { .type = NLA_NESTED },
2758 [NFTA_SET_ELEM_FLAGS] = { .type = NLA_U32 },
2759};
2760
2761static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = {
2762 [NFTA_SET_ELEM_LIST_TABLE] = { .type = NLA_STRING },
2763 [NFTA_SET_ELEM_LIST_SET] = { .type = NLA_STRING },
2764 [NFTA_SET_ELEM_LIST_ELEMENTS] = { .type = NLA_NESTED },
958bee14 2765 [NFTA_SET_ELEM_LIST_SET_ID] = { .type = NLA_U32 },
20a69341
PM
2766};
2767
2768static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx,
2769 const struct sk_buff *skb,
2770 const struct nlmsghdr *nlh,
55dd6f93
PNA
2771 const struct nlattr * const nla[],
2772 bool trans)
20a69341
PM
2773{
2774 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7c95f6d8
PNA
2775 struct nft_af_info *afi;
2776 struct nft_table *table;
99633ab2 2777 struct net *net = sock_net(skb->sk);
20a69341 2778
99633ab2 2779 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
20a69341
PM
2780 if (IS_ERR(afi))
2781 return PTR_ERR(afi);
2782
9370761c 2783 table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE]);
20a69341
PM
2784 if (IS_ERR(table))
2785 return PTR_ERR(table);
55dd6f93
PNA
2786 if (!trans && (table->flags & NFT_TABLE_INACTIVE))
2787 return -ENOENT;
20a69341 2788
0ca743a5 2789 nft_ctx_init(ctx, skb, nlh, afi, table, NULL, nla);
20a69341
PM
2790 return 0;
2791}
2792
2793static int nf_tables_fill_setelem(struct sk_buff *skb,
2794 const struct nft_set *set,
2795 const struct nft_set_elem *elem)
2796{
2797 unsigned char *b = skb_tail_pointer(skb);
2798 struct nlattr *nest;
2799
2800 nest = nla_nest_start(skb, NFTA_LIST_ELEM);
2801 if (nest == NULL)
2802 goto nla_put_failure;
2803
2804 if (nft_data_dump(skb, NFTA_SET_ELEM_KEY, &elem->key, NFT_DATA_VALUE,
2805 set->klen) < 0)
2806 goto nla_put_failure;
2807
2808 if (set->flags & NFT_SET_MAP &&
2809 !(elem->flags & NFT_SET_ELEM_INTERVAL_END) &&
2810 nft_data_dump(skb, NFTA_SET_ELEM_DATA, &elem->data,
2811 set->dtype == NFT_DATA_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE,
2812 set->dlen) < 0)
2813 goto nla_put_failure;
2814
2815 if (elem->flags != 0)
2816 if (nla_put_be32(skb, NFTA_SET_ELEM_FLAGS, htonl(elem->flags)))
2817 goto nla_put_failure;
2818
2819 nla_nest_end(skb, nest);
2820 return 0;
2821
2822nla_put_failure:
2823 nlmsg_trim(skb, b);
2824 return -EMSGSIZE;
2825}
2826
2827struct nft_set_dump_args {
2828 const struct netlink_callback *cb;
2829 struct nft_set_iter iter;
2830 struct sk_buff *skb;
2831};
2832
2833static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
2834 const struct nft_set *set,
2835 const struct nft_set_iter *iter,
2836 const struct nft_set_elem *elem)
2837{
2838 struct nft_set_dump_args *args;
2839
2840 args = container_of(iter, struct nft_set_dump_args, iter);
2841 return nf_tables_fill_setelem(args->skb, set, elem);
2842}
2843
2844static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
2845{
2846 const struct nft_set *set;
2847 struct nft_set_dump_args args;
2848 struct nft_ctx ctx;
2849 struct nlattr *nla[NFTA_SET_ELEM_LIST_MAX + 1];
2850 struct nfgenmsg *nfmsg;
2851 struct nlmsghdr *nlh;
2852 struct nlattr *nest;
2853 u32 portid, seq;
2854 int event, err;
2855
720e0dfa
MN
2856 err = nlmsg_parse(cb->nlh, sizeof(struct nfgenmsg), nla,
2857 NFTA_SET_ELEM_LIST_MAX, nft_set_elem_list_policy);
20a69341
PM
2858 if (err < 0)
2859 return err;
2860
55dd6f93
PNA
2861 err = nft_ctx_init_from_elemattr(&ctx, cb->skb, cb->nlh, (void *)nla,
2862 false);
20a69341
PM
2863 if (err < 0)
2864 return err;
2865
2866 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]);
2867 if (IS_ERR(set))
2868 return PTR_ERR(set);
958bee14
PNA
2869 if (set->flags & NFT_SET_INACTIVE)
2870 return -ENOENT;
20a69341
PM
2871
2872 event = NFT_MSG_NEWSETELEM;
2873 event |= NFNL_SUBSYS_NFTABLES << 8;
2874 portid = NETLINK_CB(cb->skb).portid;
2875 seq = cb->nlh->nlmsg_seq;
2876
2877 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),
2878 NLM_F_MULTI);
2879 if (nlh == NULL)
2880 goto nla_put_failure;
2881
2882 nfmsg = nlmsg_data(nlh);
6403d962 2883 nfmsg->nfgen_family = ctx.afi->family;
20a69341
PM
2884 nfmsg->version = NFNETLINK_V0;
2885 nfmsg->res_id = 0;
2886
2887 if (nla_put_string(skb, NFTA_SET_ELEM_LIST_TABLE, ctx.table->name))
2888 goto nla_put_failure;
2889 if (nla_put_string(skb, NFTA_SET_ELEM_LIST_SET, set->name))
2890 goto nla_put_failure;
2891
2892 nest = nla_nest_start(skb, NFTA_SET_ELEM_LIST_ELEMENTS);
2893 if (nest == NULL)
2894 goto nla_put_failure;
2895
2896 args.cb = cb;
2897 args.skb = skb;
2898 args.iter.skip = cb->args[0];
2899 args.iter.count = 0;
2900 args.iter.err = 0;
2901 args.iter.fn = nf_tables_dump_setelem;
2902 set->ops->walk(&ctx, set, &args.iter);
2903
2904 nla_nest_end(skb, nest);
2905 nlmsg_end(skb, nlh);
2906
2907 if (args.iter.err && args.iter.err != -EMSGSIZE)
2908 return args.iter.err;
2909 if (args.iter.count == cb->args[0])
2910 return 0;
2911
2912 cb->args[0] = args.iter.count;
2913 return skb->len;
2914
2915nla_put_failure:
2916 return -ENOSPC;
2917}
2918
2919static int nf_tables_getsetelem(struct sock *nlsk, struct sk_buff *skb,
2920 const struct nlmsghdr *nlh,
2921 const struct nlattr * const nla[])
2922{
2923 const struct nft_set *set;
2924 struct nft_ctx ctx;
2925 int err;
2926
55dd6f93 2927 err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, false);
20a69341
PM
2928 if (err < 0)
2929 return err;
2930
2931 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]);
2932 if (IS_ERR(set))
2933 return PTR_ERR(set);
958bee14
PNA
2934 if (set->flags & NFT_SET_INACTIVE)
2935 return -ENOENT;
20a69341
PM
2936
2937 if (nlh->nlmsg_flags & NLM_F_DUMP) {
2938 struct netlink_dump_control c = {
2939 .dump = nf_tables_dump_set,
2940 };
2941 return netlink_dump_start(nlsk, skb, nlh, &c);
2942 }
2943 return -EOPNOTSUPP;
2944}
2945
d60ce62f
AB
2946static int nf_tables_fill_setelem_info(struct sk_buff *skb,
2947 const struct nft_ctx *ctx, u32 seq,
2948 u32 portid, int event, u16 flags,
2949 const struct nft_set *set,
2950 const struct nft_set_elem *elem)
2951{
2952 struct nfgenmsg *nfmsg;
2953 struct nlmsghdr *nlh;
2954 struct nlattr *nest;
2955 int err;
2956
2957 event |= NFNL_SUBSYS_NFTABLES << 8;
2958 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),
2959 flags);
2960 if (nlh == NULL)
2961 goto nla_put_failure;
2962
2963 nfmsg = nlmsg_data(nlh);
2964 nfmsg->nfgen_family = ctx->afi->family;
2965 nfmsg->version = NFNETLINK_V0;
2966 nfmsg->res_id = 0;
2967
2968 if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name))
2969 goto nla_put_failure;
2970 if (nla_put_string(skb, NFTA_SET_NAME, set->name))
2971 goto nla_put_failure;
2972
2973 nest = nla_nest_start(skb, NFTA_SET_ELEM_LIST_ELEMENTS);
2974 if (nest == NULL)
2975 goto nla_put_failure;
2976
2977 err = nf_tables_fill_setelem(skb, set, elem);
2978 if (err < 0)
2979 goto nla_put_failure;
2980
2981 nla_nest_end(skb, nest);
2982
2983 return nlmsg_end(skb, nlh);
2984
2985nla_put_failure:
2986 nlmsg_trim(skb, nlh);
2987 return -1;
2988}
2989
2990static int nf_tables_setelem_notify(const struct nft_ctx *ctx,
2991 const struct nft_set *set,
2992 const struct nft_set_elem *elem,
2993 int event, u16 flags)
2994{
128ad332
PNA
2995 struct net *net = ctx->net;
2996 u32 portid = ctx->portid;
d60ce62f
AB
2997 struct sk_buff *skb;
2998 int err;
2999
128ad332 3000 if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
d60ce62f
AB
3001 return 0;
3002
3003 err = -ENOBUFS;
3004 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
3005 if (skb == NULL)
3006 goto err;
3007
3008 err = nf_tables_fill_setelem_info(skb, ctx, 0, portid, event, flags,
3009 set, elem);
3010 if (err < 0) {
3011 kfree_skb(skb);
3012 goto err;
3013 }
3014
128ad332 3015 err = nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, ctx->report,
d60ce62f
AB
3016 GFP_KERNEL);
3017err:
3018 if (err < 0)
3019 nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, err);
3020 return err;
3021}
3022
60319eb1
PNA
3023static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx,
3024 int msg_type,
3025 struct nft_set *set)
3026{
3027 struct nft_trans *trans;
3028
3029 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_elem));
3030 if (trans == NULL)
3031 return NULL;
3032
3033 nft_trans_elem_set(trans) = set;
3034 return trans;
3035}
3036
3037static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
20a69341
PM
3038 const struct nlattr *attr)
3039{
3040 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
3041 struct nft_data_desc d1, d2;
3042 struct nft_set_elem elem;
3043 struct nft_set_binding *binding;
3044 enum nft_registers dreg;
60319eb1 3045 struct nft_trans *trans;
20a69341
PM
3046 int err;
3047
c50b960c
PM
3048 if (set->size && set->nelems == set->size)
3049 return -ENFILE;
3050
20a69341
PM
3051 err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr,
3052 nft_set_elem_policy);
3053 if (err < 0)
3054 return err;
3055
3056 if (nla[NFTA_SET_ELEM_KEY] == NULL)
3057 return -EINVAL;
3058
3059 elem.flags = 0;
3060 if (nla[NFTA_SET_ELEM_FLAGS] != NULL) {
3061 elem.flags = ntohl(nla_get_be32(nla[NFTA_SET_ELEM_FLAGS]));
3062 if (elem.flags & ~NFT_SET_ELEM_INTERVAL_END)
3063 return -EINVAL;
3064 }
3065
3066 if (set->flags & NFT_SET_MAP) {
3067 if (nla[NFTA_SET_ELEM_DATA] == NULL &&
3068 !(elem.flags & NFT_SET_ELEM_INTERVAL_END))
3069 return -EINVAL;
bd7fc645
PNA
3070 if (nla[NFTA_SET_ELEM_DATA] != NULL &&
3071 elem.flags & NFT_SET_ELEM_INTERVAL_END)
3072 return -EINVAL;
20a69341
PM
3073 } else {
3074 if (nla[NFTA_SET_ELEM_DATA] != NULL)
3075 return -EINVAL;
3076 }
3077
3078 err = nft_data_init(ctx, &elem.key, &d1, nla[NFTA_SET_ELEM_KEY]);
3079 if (err < 0)
3080 goto err1;
3081 err = -EINVAL;
3082 if (d1.type != NFT_DATA_VALUE || d1.len != set->klen)
3083 goto err2;
3084
3085 err = -EEXIST;
3086 if (set->ops->get(set, &elem) == 0)
3087 goto err2;
3088
3089 if (nla[NFTA_SET_ELEM_DATA] != NULL) {
3090 err = nft_data_init(ctx, &elem.data, &d2, nla[NFTA_SET_ELEM_DATA]);
3091 if (err < 0)
3092 goto err2;
3093
3094 err = -EINVAL;
3095 if (set->dtype != NFT_DATA_VERDICT && d2.len != set->dlen)
3096 goto err3;
3097
3098 dreg = nft_type_to_reg(set->dtype);
3099 list_for_each_entry(binding, &set->bindings, list) {
3100 struct nft_ctx bind_ctx = {
3101 .afi = ctx->afi,
3102 .table = ctx->table,
7c95f6d8 3103 .chain = (struct nft_chain *)binding->chain,
20a69341
PM
3104 };
3105
3106 err = nft_validate_data_load(&bind_ctx, dreg,
3107 &elem.data, d2.type);
3108 if (err < 0)
3109 goto err3;
3110 }
3111 }
3112
60319eb1
PNA
3113 trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set);
3114 if (trans == NULL)
3115 goto err3;
3116
20a69341
PM
3117 err = set->ops->insert(set, &elem);
3118 if (err < 0)
60319eb1 3119 goto err4;
20a69341 3120
60319eb1 3121 nft_trans_elem(trans) = elem;
46bbafce 3122 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
20a69341
PM
3123 return 0;
3124
60319eb1
PNA
3125err4:
3126 kfree(trans);
20a69341
PM
3127err3:
3128 if (nla[NFTA_SET_ELEM_DATA] != NULL)
3129 nft_data_uninit(&elem.data, d2.type);
3130err2:
3131 nft_data_uninit(&elem.key, d1.type);
3132err1:
3133 return err;
3134}
3135
3136static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb,
3137 const struct nlmsghdr *nlh,
3138 const struct nlattr * const nla[])
3139{
958bee14 3140 struct net *net = sock_net(skb->sk);
20a69341
PM
3141 const struct nlattr *attr;
3142 struct nft_set *set;
3143 struct nft_ctx ctx;
60319eb1 3144 int rem, err = 0;
20a69341 3145
55dd6f93 3146 err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, true);
20a69341
PM
3147 if (err < 0)
3148 return err;
3149
3150 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]);
958bee14
PNA
3151 if (IS_ERR(set)) {
3152 if (nla[NFTA_SET_ELEM_LIST_SET_ID]) {
3153 set = nf_tables_set_lookup_byid(net,
3154 nla[NFTA_SET_ELEM_LIST_SET_ID]);
3155 }
3156 if (IS_ERR(set))
3157 return PTR_ERR(set);
3158 }
3159
20a69341
PM
3160 if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
3161 return -EBUSY;
3162
3163 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
3164 err = nft_add_set_elem(&ctx, set, attr);
3165 if (err < 0)
60319eb1 3166 break;
4fefee57
PNA
3167
3168 set->nelems++;
20a69341 3169 }
60319eb1 3170 return err;
20a69341
PM
3171}
3172
60319eb1 3173static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
20a69341
PM
3174 const struct nlattr *attr)
3175{
3176 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
3177 struct nft_data_desc desc;
3178 struct nft_set_elem elem;
60319eb1 3179 struct nft_trans *trans;
20a69341
PM
3180 int err;
3181
3182 err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr,
3183 nft_set_elem_policy);
3184 if (err < 0)
3185 goto err1;
3186
3187 err = -EINVAL;
3188 if (nla[NFTA_SET_ELEM_KEY] == NULL)
3189 goto err1;
3190
3191 err = nft_data_init(ctx, &elem.key, &desc, nla[NFTA_SET_ELEM_KEY]);
3192 if (err < 0)
3193 goto err1;
3194
3195 err = -EINVAL;
3196 if (desc.type != NFT_DATA_VALUE || desc.len != set->klen)
3197 goto err2;
3198
3199 err = set->ops->get(set, &elem);
3200 if (err < 0)
3201 goto err2;
3202
60319eb1
PNA
3203 trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set);
3204 if (trans == NULL)
3205 goto err2;
20a69341 3206
60319eb1 3207 nft_trans_elem(trans) = elem;
46bbafce 3208 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
20a69341
PM
3209
3210 nft_data_uninit(&elem.key, NFT_DATA_VALUE);
3211 if (set->flags & NFT_SET_MAP)
3212 nft_data_uninit(&elem.data, set->dtype);
3213
3214err2:
3215 nft_data_uninit(&elem.key, desc.type);
3216err1:
3217 return err;
3218}
3219
3220static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb,
3221 const struct nlmsghdr *nlh,
3222 const struct nlattr * const nla[])
3223{
3224 const struct nlattr *attr;
3225 struct nft_set *set;
3226 struct nft_ctx ctx;
60319eb1 3227 int rem, err = 0;
20a69341 3228
55dd6f93 3229 err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, false);
20a69341
PM
3230 if (err < 0)
3231 return err;
3232
3233 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]);
3234 if (IS_ERR(set))
3235 return PTR_ERR(set);
3236 if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
3237 return -EBUSY;
3238
3239 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
3240 err = nft_del_setelem(&ctx, set, attr);
3241 if (err < 0)
60319eb1 3242 break;
4fefee57
PNA
3243
3244 set->nelems--;
20a69341 3245 }
60319eb1 3246 return err;
20a69341
PM
3247}
3248
96518518
PM
3249static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
3250 [NFT_MSG_NEWTABLE] = {
55dd6f93 3251 .call_batch = nf_tables_newtable,
96518518
PM
3252 .attr_count = NFTA_TABLE_MAX,
3253 .policy = nft_table_policy,
3254 },
3255 [NFT_MSG_GETTABLE] = {
3256 .call = nf_tables_gettable,
3257 .attr_count = NFTA_TABLE_MAX,
3258 .policy = nft_table_policy,
3259 },
3260 [NFT_MSG_DELTABLE] = {
55dd6f93 3261 .call_batch = nf_tables_deltable,
96518518
PM
3262 .attr_count = NFTA_TABLE_MAX,
3263 .policy = nft_table_policy,
3264 },
3265 [NFT_MSG_NEWCHAIN] = {
91c7b38d 3266 .call_batch = nf_tables_newchain,
96518518
PM
3267 .attr_count = NFTA_CHAIN_MAX,
3268 .policy = nft_chain_policy,
3269 },
3270 [NFT_MSG_GETCHAIN] = {
3271 .call = nf_tables_getchain,
3272 .attr_count = NFTA_CHAIN_MAX,
3273 .policy = nft_chain_policy,
3274 },
3275 [NFT_MSG_DELCHAIN] = {
91c7b38d 3276 .call_batch = nf_tables_delchain,
96518518
PM
3277 .attr_count = NFTA_CHAIN_MAX,
3278 .policy = nft_chain_policy,
3279 },
3280 [NFT_MSG_NEWRULE] = {
0628b123 3281 .call_batch = nf_tables_newrule,
96518518
PM
3282 .attr_count = NFTA_RULE_MAX,
3283 .policy = nft_rule_policy,
3284 },
3285 [NFT_MSG_GETRULE] = {
3286 .call = nf_tables_getrule,
3287 .attr_count = NFTA_RULE_MAX,
3288 .policy = nft_rule_policy,
3289 },
3290 [NFT_MSG_DELRULE] = {
0628b123 3291 .call_batch = nf_tables_delrule,
96518518
PM
3292 .attr_count = NFTA_RULE_MAX,
3293 .policy = nft_rule_policy,
3294 },
20a69341 3295 [NFT_MSG_NEWSET] = {
958bee14 3296 .call_batch = nf_tables_newset,
20a69341
PM
3297 .attr_count = NFTA_SET_MAX,
3298 .policy = nft_set_policy,
3299 },
3300 [NFT_MSG_GETSET] = {
3301 .call = nf_tables_getset,
3302 .attr_count = NFTA_SET_MAX,
3303 .policy = nft_set_policy,
3304 },
3305 [NFT_MSG_DELSET] = {
958bee14 3306 .call_batch = nf_tables_delset,
20a69341
PM
3307 .attr_count = NFTA_SET_MAX,
3308 .policy = nft_set_policy,
3309 },
3310 [NFT_MSG_NEWSETELEM] = {
958bee14 3311 .call_batch = nf_tables_newsetelem,
20a69341
PM
3312 .attr_count = NFTA_SET_ELEM_LIST_MAX,
3313 .policy = nft_set_elem_list_policy,
3314 },
3315 [NFT_MSG_GETSETELEM] = {
3316 .call = nf_tables_getsetelem,
3317 .attr_count = NFTA_SET_ELEM_LIST_MAX,
3318 .policy = nft_set_elem_list_policy,
3319 },
3320 [NFT_MSG_DELSETELEM] = {
958bee14 3321 .call_batch = nf_tables_delsetelem,
20a69341
PM
3322 .attr_count = NFTA_SET_ELEM_LIST_MAX,
3323 .policy = nft_set_elem_list_policy,
3324 },
96518518
PM
3325};
3326
91c7b38d
PNA
3327static void nft_chain_commit_update(struct nft_trans *trans)
3328{
3329 struct nft_base_chain *basechain;
3330
3331 if (nft_trans_chain_name(trans)[0])
3332 strcpy(trans->ctx.chain->name, nft_trans_chain_name(trans));
3333
3334 if (!(trans->ctx.chain->flags & NFT_BASE_CHAIN))
3335 return;
3336
3337 basechain = nft_base_chain(trans->ctx.chain);
3338 nft_chain_stats_replace(basechain, nft_trans_chain_stats(trans));
3339
3340 switch (nft_trans_chain_policy(trans)) {
3341 case NF_DROP:
3342 case NF_ACCEPT:
3343 basechain->policy = nft_trans_chain_policy(trans);
3344 break;
3345 }
3346}
3347
c7c32e72
PNA
3348/* Schedule objects for release via rcu to make sure no packets are accesing
3349 * removed rules.
3350 */
3351static void nf_tables_commit_release_rcu(struct rcu_head *rt)
3352{
3353 struct nft_trans *trans = container_of(rt, struct nft_trans, rcu_head);
3354
3355 switch (trans->msg_type) {
3356 case NFT_MSG_DELTABLE:
3357 nf_tables_table_destroy(&trans->ctx);
3358 break;
3359 case NFT_MSG_DELCHAIN:
3360 nf_tables_chain_destroy(trans->ctx.chain);
3361 break;
3362 case NFT_MSG_DELRULE:
3363 nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
3364 break;
3365 case NFT_MSG_DELSET:
3366 nft_set_destroy(nft_trans_set(trans));
3367 break;
3368 }
3369 kfree(trans);
3370}
3371
37082f93
PNA
3372static int nf_tables_commit(struct sk_buff *skb)
3373{
3374 struct net *net = sock_net(skb->sk);
3375 struct nft_trans *trans, *next;
60319eb1 3376 struct nft_set *set;
37082f93
PNA
3377
3378 /* Bump generation counter, invalidate any dump in progress */
38e029f1 3379 while (++net->nft.base_seq == 0);
37082f93
PNA
3380
3381 /* A new generation has just started */
3382 net->nft.gencursor = gencursor_next(net);
3383
3384 /* Make sure all packets have left the previous generation before
3385 * purging old rules.
3386 */
3387 synchronize_rcu();
3388
3389 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
b380e5c7 3390 switch (trans->msg_type) {
55dd6f93
PNA
3391 case NFT_MSG_NEWTABLE:
3392 if (nft_trans_table_update(trans)) {
3393 if (!nft_trans_table_enable(trans)) {
3394 nf_tables_table_disable(trans->ctx.afi,
3395 trans->ctx.table);
3396 trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
3397 }
3398 } else {
3399 trans->ctx.table->flags &= ~NFT_TABLE_INACTIVE;
3400 }
35151d84 3401 nf_tables_table_notify(&trans->ctx, NFT_MSG_NEWTABLE);
55dd6f93
PNA
3402 nft_trans_destroy(trans);
3403 break;
3404 case NFT_MSG_DELTABLE:
35151d84 3405 nf_tables_table_notify(&trans->ctx, NFT_MSG_DELTABLE);
55dd6f93 3406 break;
91c7b38d
PNA
3407 case NFT_MSG_NEWCHAIN:
3408 if (nft_trans_chain_update(trans))
3409 nft_chain_commit_update(trans);
4fefee57 3410 else
91c7b38d 3411 trans->ctx.chain->flags &= ~NFT_CHAIN_INACTIVE;
4fefee57 3412
35151d84 3413 nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
91c7b38d
PNA
3414 nft_trans_destroy(trans);
3415 break;
3416 case NFT_MSG_DELCHAIN:
35151d84 3417 nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN);
91c7b38d
PNA
3418 if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT) &&
3419 trans->ctx.chain->flags & NFT_BASE_CHAIN) {
3420 nf_unregister_hooks(nft_base_chain(trans->ctx.chain)->ops,
3421 trans->ctx.afi->nops);
3422 }
3423 break;
b380e5c7
PNA
3424 case NFT_MSG_NEWRULE:
3425 nft_rule_clear(trans->ctx.net, nft_trans_rule(trans));
35151d84 3426 nf_tables_rule_notify(&trans->ctx,
37082f93 3427 nft_trans_rule(trans),
35151d84 3428 NFT_MSG_NEWRULE);
37082f93 3429 nft_trans_destroy(trans);
b380e5c7
PNA
3430 break;
3431 case NFT_MSG_DELRULE:
3432 list_del_rcu(&nft_trans_rule(trans)->list);
35151d84
PNA
3433 nf_tables_rule_notify(&trans->ctx,
3434 nft_trans_rule(trans),
3435 NFT_MSG_DELRULE);
b380e5c7 3436 break;
958bee14
PNA
3437 case NFT_MSG_NEWSET:
3438 nft_trans_set(trans)->flags &= ~NFT_SET_INACTIVE;
4fefee57
PNA
3439 /* This avoids hitting -EBUSY when deleting the table
3440 * from the transaction.
3441 */
3442 if (nft_trans_set(trans)->flags & NFT_SET_ANONYMOUS &&
3443 !list_empty(&nft_trans_set(trans)->bindings))
3444 trans->ctx.table->use--;
3445
958bee14 3446 nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
31f8441c 3447 NFT_MSG_NEWSET, GFP_KERNEL);
958bee14
PNA
3448 nft_trans_destroy(trans);
3449 break;
3450 case NFT_MSG_DELSET:
3451 nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
31f8441c 3452 NFT_MSG_DELSET, GFP_KERNEL);
958bee14 3453 break;
60319eb1 3454 case NFT_MSG_NEWSETELEM:
60319eb1
PNA
3455 nf_tables_setelem_notify(&trans->ctx,
3456 nft_trans_elem_set(trans),
3457 &nft_trans_elem(trans),
3458 NFT_MSG_NEWSETELEM, 0);
3459 nft_trans_destroy(trans);
3460 break;
3461 case NFT_MSG_DELSETELEM:
60319eb1
PNA
3462 nf_tables_setelem_notify(&trans->ctx,
3463 nft_trans_elem_set(trans),
3464 &nft_trans_elem(trans),
3465 NFT_MSG_DELSETELEM, 0);
3466 set = nft_trans_elem_set(trans);
3467 set->ops->get(set, &nft_trans_elem(trans));
3468 set->ops->remove(set, &nft_trans_elem(trans));
3469 nft_trans_destroy(trans);
3470 break;
37082f93 3471 }
37082f93
PNA
3472 }
3473
37082f93 3474 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
c7c32e72
PNA
3475 list_del(&trans->list);
3476 trans->ctx.nla = NULL;
3477 call_rcu(&trans->rcu_head, nf_tables_commit_release_rcu);
37082f93
PNA
3478 }
3479
3480 return 0;
3481}
3482
c7c32e72
PNA
3483/* Schedule objects for release via rcu to make sure no packets are accesing
3484 * aborted rules.
3485 */
3486static void nf_tables_abort_release_rcu(struct rcu_head *rt)
3487{
3488 struct nft_trans *trans = container_of(rt, struct nft_trans, rcu_head);
3489
3490 switch (trans->msg_type) {
3491 case NFT_MSG_NEWTABLE:
3492 nf_tables_table_destroy(&trans->ctx);
3493 break;
3494 case NFT_MSG_NEWCHAIN:
3495 nf_tables_chain_destroy(trans->ctx.chain);
3496 break;
3497 case NFT_MSG_NEWRULE:
3498 nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
3499 break;
3500 case NFT_MSG_NEWSET:
3501 nft_set_destroy(nft_trans_set(trans));
3502 break;
3503 }
3504 kfree(trans);
3505}
3506
37082f93
PNA
3507static int nf_tables_abort(struct sk_buff *skb)
3508{
3509 struct net *net = sock_net(skb->sk);
3510 struct nft_trans *trans, *next;
60319eb1 3511 struct nft_set *set;
37082f93
PNA
3512
3513 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
b380e5c7 3514 switch (trans->msg_type) {
55dd6f93
PNA
3515 case NFT_MSG_NEWTABLE:
3516 if (nft_trans_table_update(trans)) {
3517 if (nft_trans_table_enable(trans)) {
3518 nf_tables_table_disable(trans->ctx.afi,
3519 trans->ctx.table);
3520 trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
3521 }
3522 nft_trans_destroy(trans);
3523 } else {
e688a7f8 3524 list_del_rcu(&trans->ctx.table->list);
55dd6f93
PNA
3525 }
3526 break;
3527 case NFT_MSG_DELTABLE:
e688a7f8
PNA
3528 list_add_tail_rcu(&trans->ctx.table->list,
3529 &trans->ctx.afi->tables);
55dd6f93
PNA
3530 nft_trans_destroy(trans);
3531 break;
91c7b38d
PNA
3532 case NFT_MSG_NEWCHAIN:
3533 if (nft_trans_chain_update(trans)) {
3534 if (nft_trans_chain_stats(trans))
3535 free_percpu(nft_trans_chain_stats(trans));
3536
3537 nft_trans_destroy(trans);
3538 } else {
4fefee57 3539 trans->ctx.table->use--;
e688a7f8 3540 list_del_rcu(&trans->ctx.chain->list);
91c7b38d
PNA
3541 if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT) &&
3542 trans->ctx.chain->flags & NFT_BASE_CHAIN) {
3543 nf_unregister_hooks(nft_base_chain(trans->ctx.chain)->ops,
3544 trans->ctx.afi->nops);
3545 }
3546 }
3547 break;
3548 case NFT_MSG_DELCHAIN:
4fefee57 3549 trans->ctx.table->use++;
e688a7f8
PNA
3550 list_add_tail_rcu(&trans->ctx.chain->list,
3551 &trans->ctx.table->chains);
91c7b38d
PNA
3552 nft_trans_destroy(trans);
3553 break;
b380e5c7 3554 case NFT_MSG_NEWRULE:
4fefee57 3555 trans->ctx.chain->use--;
b380e5c7
PNA
3556 list_del_rcu(&nft_trans_rule(trans)->list);
3557 break;
3558 case NFT_MSG_DELRULE:
4fefee57 3559 trans->ctx.chain->use++;
b380e5c7 3560 nft_rule_clear(trans->ctx.net, nft_trans_rule(trans));
37082f93 3561 nft_trans_destroy(trans);
b380e5c7 3562 break;
958bee14 3563 case NFT_MSG_NEWSET:
4fefee57 3564 trans->ctx.table->use--;
e688a7f8 3565 list_del_rcu(&nft_trans_set(trans)->list);
958bee14
PNA
3566 break;
3567 case NFT_MSG_DELSET:
4fefee57 3568 trans->ctx.table->use++;
e688a7f8
PNA
3569 list_add_tail_rcu(&nft_trans_set(trans)->list,
3570 &trans->ctx.table->sets);
958bee14
PNA
3571 nft_trans_destroy(trans);
3572 break;
60319eb1 3573 case NFT_MSG_NEWSETELEM:
4fefee57 3574 nft_trans_elem_set(trans)->nelems--;
60319eb1
PNA
3575 set = nft_trans_elem_set(trans);
3576 set->ops->get(set, &nft_trans_elem(trans));
3577 set->ops->remove(set, &nft_trans_elem(trans));
3578 nft_trans_destroy(trans);
3579 break;
3580 case NFT_MSG_DELSETELEM:
4fefee57 3581 nft_trans_elem_set(trans)->nelems++;
60319eb1
PNA
3582 nft_trans_destroy(trans);
3583 break;
37082f93 3584 }
37082f93
PNA
3585 }
3586
a1cee076
PNA
3587 list_for_each_entry_safe_reverse(trans, next,
3588 &net->nft.commit_list, list) {
c7c32e72
PNA
3589 list_del(&trans->list);
3590 trans->ctx.nla = NULL;
3591 call_rcu(&trans->rcu_head, nf_tables_abort_release_rcu);
37082f93
PNA
3592 }
3593
3594 return 0;
3595}
3596
96518518
PM
3597static const struct nfnetlink_subsystem nf_tables_subsys = {
3598 .name = "nf_tables",
3599 .subsys_id = NFNL_SUBSYS_NFTABLES,
3600 .cb_count = NFT_MSG_MAX,
3601 .cb = nf_tables_cb,
0628b123
PNA
3602 .commit = nf_tables_commit,
3603 .abort = nf_tables_abort,
96518518
PM
3604};
3605
20a69341
PM
3606/*
3607 * Loop detection - walk through the ruleset beginning at the destination chain
3608 * of a new jump until either the source chain is reached (loop) or all
3609 * reachable chains have been traversed.
3610 *
3611 * The loop check is performed whenever a new jump verdict is added to an
3612 * expression or verdict map or a verdict map is bound to a new chain.
3613 */
3614
3615static int nf_tables_check_loops(const struct nft_ctx *ctx,
3616 const struct nft_chain *chain);
3617
3618static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx,
3619 const struct nft_set *set,
3620 const struct nft_set_iter *iter,
3621 const struct nft_set_elem *elem)
3622{
62f9c8b4
PNA
3623 if (elem->flags & NFT_SET_ELEM_INTERVAL_END)
3624 return 0;
3625
20a69341
PM
3626 switch (elem->data.verdict) {
3627 case NFT_JUMP:
3628 case NFT_GOTO:
3629 return nf_tables_check_loops(ctx, elem->data.chain);
3630 default:
3631 return 0;
3632 }
3633}
3634
3635static int nf_tables_check_loops(const struct nft_ctx *ctx,
3636 const struct nft_chain *chain)
3637{
3638 const struct nft_rule *rule;
3639 const struct nft_expr *expr, *last;
20a69341
PM
3640 const struct nft_set *set;
3641 struct nft_set_binding *binding;
3642 struct nft_set_iter iter;
20a69341
PM
3643
3644 if (ctx->chain == chain)
3645 return -ELOOP;
3646
3647 list_for_each_entry(rule, &chain->rules, list) {
3648 nft_rule_for_each_expr(expr, last, rule) {
0ca743a5
PNA
3649 const struct nft_data *data = NULL;
3650 int err;
3651
3652 if (!expr->ops->validate)
20a69341
PM
3653 continue;
3654
0ca743a5
PNA
3655 err = expr->ops->validate(ctx, expr, &data);
3656 if (err < 0)
3657 return err;
3658
20a69341 3659 if (data == NULL)
0ca743a5 3660 continue;
20a69341
PM
3661
3662 switch (data->verdict) {
3663 case NFT_JUMP:
3664 case NFT_GOTO:
3665 err = nf_tables_check_loops(ctx, data->chain);
3666 if (err < 0)
3667 return err;
3668 default:
3669 break;
3670 }
3671 }
3672 }
3673
3674 list_for_each_entry(set, &ctx->table->sets, list) {
3675 if (!(set->flags & NFT_SET_MAP) ||
3676 set->dtype != NFT_DATA_VERDICT)
3677 continue;
3678
3679 list_for_each_entry(binding, &set->bindings, list) {
3680 if (binding->chain != chain)
3681 continue;
3682
3683 iter.skip = 0;
3684 iter.count = 0;
3685 iter.err = 0;
3686 iter.fn = nf_tables_loop_check_setelem;
3687
3688 set->ops->walk(ctx, set, &iter);
3689 if (iter.err < 0)
3690 return iter.err;
3691 }
3692 }
3693
3694 return 0;
3695}
3696
96518518
PM
3697/**
3698 * nft_validate_input_register - validate an expressions' input register
3699 *
3700 * @reg: the register number
3701 *
3702 * Validate that the input register is one of the general purpose
3703 * registers.
3704 */
3705int nft_validate_input_register(enum nft_registers reg)
3706{
3707 if (reg <= NFT_REG_VERDICT)
3708 return -EINVAL;
3709 if (reg > NFT_REG_MAX)
3710 return -ERANGE;
3711 return 0;
3712}
3713EXPORT_SYMBOL_GPL(nft_validate_input_register);
3714
3715/**
3716 * nft_validate_output_register - validate an expressions' output register
3717 *
3718 * @reg: the register number
3719 *
3720 * Validate that the output register is one of the general purpose
3721 * registers or the verdict register.
3722 */
3723int nft_validate_output_register(enum nft_registers reg)
3724{
3725 if (reg < NFT_REG_VERDICT)
3726 return -EINVAL;
3727 if (reg > NFT_REG_MAX)
3728 return -ERANGE;
3729 return 0;
3730}
3731EXPORT_SYMBOL_GPL(nft_validate_output_register);
3732
3733/**
3734 * nft_validate_data_load - validate an expressions' data load
3735 *
3736 * @ctx: context of the expression performing the load
3737 * @reg: the destination register number
3738 * @data: the data to load
3739 * @type: the data type
3740 *
3741 * Validate that a data load uses the appropriate data type for
3742 * the destination register. A value of NULL for the data means
3743 * that its runtime gathered data, which is always of type
3744 * NFT_DATA_VALUE.
3745 */
3746int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg,
3747 const struct nft_data *data,
3748 enum nft_data_types type)
3749{
20a69341
PM
3750 int err;
3751
96518518
PM
3752 switch (reg) {
3753 case NFT_REG_VERDICT:
3754 if (data == NULL || type != NFT_DATA_VERDICT)
3755 return -EINVAL;
20a69341
PM
3756
3757 if (data->verdict == NFT_GOTO || data->verdict == NFT_JUMP) {
3758 err = nf_tables_check_loops(ctx, data->chain);
3759 if (err < 0)
3760 return err;
3761
3762 if (ctx->chain->level + 1 > data->chain->level) {
3763 if (ctx->chain->level + 1 == NFT_JUMP_STACK_SIZE)
3764 return -EMLINK;
3765 data->chain->level = ctx->chain->level + 1;
3766 }
3767 }
3768
96518518
PM
3769 return 0;
3770 default:
3771 if (data != NULL && type != NFT_DATA_VALUE)
3772 return -EINVAL;
3773 return 0;
3774 }
3775}
3776EXPORT_SYMBOL_GPL(nft_validate_data_load);
3777
3778static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = {
3779 [NFTA_VERDICT_CODE] = { .type = NLA_U32 },
3780 [NFTA_VERDICT_CHAIN] = { .type = NLA_STRING,
3781 .len = NFT_CHAIN_MAXNAMELEN - 1 },
3782};
3783
3784static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
3785 struct nft_data_desc *desc, const struct nlattr *nla)
3786{
3787 struct nlattr *tb[NFTA_VERDICT_MAX + 1];
3788 struct nft_chain *chain;
3789 int err;
3790
3791 err = nla_parse_nested(tb, NFTA_VERDICT_MAX, nla, nft_verdict_policy);
3792 if (err < 0)
3793 return err;
3794
3795 if (!tb[NFTA_VERDICT_CODE])
3796 return -EINVAL;
3797 data->verdict = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE]));
3798
3799 switch (data->verdict) {
e0abdadc
PM
3800 default:
3801 switch (data->verdict & NF_VERDICT_MASK) {
3802 case NF_ACCEPT:
3803 case NF_DROP:
3804 case NF_QUEUE:
3805 break;
3806 default:
3807 return -EINVAL;
3808 }
3809 /* fall through */
96518518
PM
3810 case NFT_CONTINUE:
3811 case NFT_BREAK:
3812 case NFT_RETURN:
3813 desc->len = sizeof(data->verdict);
3814 break;
3815 case NFT_JUMP:
3816 case NFT_GOTO:
3817 if (!tb[NFTA_VERDICT_CHAIN])
3818 return -EINVAL;
3819 chain = nf_tables_chain_lookup(ctx->table,
3820 tb[NFTA_VERDICT_CHAIN]);
3821 if (IS_ERR(chain))
3822 return PTR_ERR(chain);
3823 if (chain->flags & NFT_BASE_CHAIN)
3824 return -EOPNOTSUPP;
3825
96518518
PM
3826 chain->use++;
3827 data->chain = chain;
3828 desc->len = sizeof(data);
3829 break;
96518518
PM
3830 }
3831
3832 desc->type = NFT_DATA_VERDICT;
3833 return 0;
3834}
3835
3836static void nft_verdict_uninit(const struct nft_data *data)
3837{
3838 switch (data->verdict) {
3839 case NFT_JUMP:
3840 case NFT_GOTO:
3841 data->chain->use--;
3842 break;
3843 }
3844}
3845
3846static int nft_verdict_dump(struct sk_buff *skb, const struct nft_data *data)
3847{
3848 struct nlattr *nest;
3849
3850 nest = nla_nest_start(skb, NFTA_DATA_VERDICT);
3851 if (!nest)
3852 goto nla_put_failure;
3853
3854 if (nla_put_be32(skb, NFTA_VERDICT_CODE, htonl(data->verdict)))
3855 goto nla_put_failure;
3856
3857 switch (data->verdict) {
3858 case NFT_JUMP:
3859 case NFT_GOTO:
3860 if (nla_put_string(skb, NFTA_VERDICT_CHAIN, data->chain->name))
3861 goto nla_put_failure;
3862 }
3863 nla_nest_end(skb, nest);
3864 return 0;
3865
3866nla_put_failure:
3867 return -1;
3868}
3869
3870static int nft_value_init(const struct nft_ctx *ctx, struct nft_data *data,
3871 struct nft_data_desc *desc, const struct nlattr *nla)
3872{
3873 unsigned int len;
3874
3875 len = nla_len(nla);
3876 if (len == 0)
3877 return -EINVAL;
3878 if (len > sizeof(data->data))
3879 return -EOVERFLOW;
3880
3881 nla_memcpy(data->data, nla, sizeof(data->data));
3882 desc->type = NFT_DATA_VALUE;
3883 desc->len = len;
3884 return 0;
3885}
3886
3887static int nft_value_dump(struct sk_buff *skb, const struct nft_data *data,
3888 unsigned int len)
3889{
3890 return nla_put(skb, NFTA_DATA_VALUE, len, data->data);
3891}
3892
3893static const struct nla_policy nft_data_policy[NFTA_DATA_MAX + 1] = {
3894 [NFTA_DATA_VALUE] = { .type = NLA_BINARY,
3895 .len = FIELD_SIZEOF(struct nft_data, data) },
3896 [NFTA_DATA_VERDICT] = { .type = NLA_NESTED },
3897};
3898
3899/**
3900 * nft_data_init - parse nf_tables data netlink attributes
3901 *
3902 * @ctx: context of the expression using the data
3903 * @data: destination struct nft_data
3904 * @desc: data description
3905 * @nla: netlink attribute containing data
3906 *
3907 * Parse the netlink data attributes and initialize a struct nft_data.
3908 * The type and length of data are returned in the data description.
3909 *
3910 * The caller can indicate that it only wants to accept data of type
3911 * NFT_DATA_VALUE by passing NULL for the ctx argument.
3912 */
3913int nft_data_init(const struct nft_ctx *ctx, struct nft_data *data,
3914 struct nft_data_desc *desc, const struct nlattr *nla)
3915{
3916 struct nlattr *tb[NFTA_DATA_MAX + 1];
3917 int err;
3918
3919 err = nla_parse_nested(tb, NFTA_DATA_MAX, nla, nft_data_policy);
3920 if (err < 0)
3921 return err;
3922
3923 if (tb[NFTA_DATA_VALUE])
3924 return nft_value_init(ctx, data, desc, tb[NFTA_DATA_VALUE]);
3925 if (tb[NFTA_DATA_VERDICT] && ctx != NULL)
3926 return nft_verdict_init(ctx, data, desc, tb[NFTA_DATA_VERDICT]);
3927 return -EINVAL;
3928}
3929EXPORT_SYMBOL_GPL(nft_data_init);
3930
3931/**
3932 * nft_data_uninit - release a nft_data item
3933 *
3934 * @data: struct nft_data to release
3935 * @type: type of data
3936 *
3937 * Release a nft_data item. NFT_DATA_VALUE types can be silently discarded,
3938 * all others need to be released by calling this function.
3939 */
3940void nft_data_uninit(const struct nft_data *data, enum nft_data_types type)
3941{
3942 switch (type) {
3943 case NFT_DATA_VALUE:
3944 return;
3945 case NFT_DATA_VERDICT:
3946 return nft_verdict_uninit(data);
3947 default:
3948 WARN_ON(1);
3949 }
3950}
3951EXPORT_SYMBOL_GPL(nft_data_uninit);
3952
3953int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
3954 enum nft_data_types type, unsigned int len)
3955{
3956 struct nlattr *nest;
3957 int err;
3958
3959 nest = nla_nest_start(skb, attr);
3960 if (nest == NULL)
3961 return -1;
3962
3963 switch (type) {
3964 case NFT_DATA_VALUE:
3965 err = nft_value_dump(skb, data, len);
3966 break;
3967 case NFT_DATA_VERDICT:
3968 err = nft_verdict_dump(skb, data);
3969 break;
3970 default:
3971 err = -EINVAL;
3972 WARN_ON(1);
3973 }
3974
3975 nla_nest_end(skb, nest);
3976 return err;
3977}
3978EXPORT_SYMBOL_GPL(nft_data_dump);
3979
99633ab2
PNA
3980static int nf_tables_init_net(struct net *net)
3981{
3982 INIT_LIST_HEAD(&net->nft.af_info);
0628b123 3983 INIT_LIST_HEAD(&net->nft.commit_list);
38e029f1 3984 net->nft.base_seq = 1;
99633ab2
PNA
3985 return 0;
3986}
3987
3988static struct pernet_operations nf_tables_net_ops = {
3989 .init = nf_tables_init_net,
3990};
3991
96518518
PM
3992static int __init nf_tables_module_init(void)
3993{
3994 int err;
3995
3996 info = kmalloc(sizeof(struct nft_expr_info) * NFT_RULE_MAXEXPRS,
3997 GFP_KERNEL);
3998 if (info == NULL) {
3999 err = -ENOMEM;
4000 goto err1;
4001 }
4002
4003 err = nf_tables_core_module_init();
4004 if (err < 0)
4005 goto err2;
4006
4007 err = nfnetlink_subsys_register(&nf_tables_subsys);
4008 if (err < 0)
4009 goto err3;
4010
4011 pr_info("nf_tables: (c) 2007-2009 Patrick McHardy <kaber@trash.net>\n");
99633ab2 4012 return register_pernet_subsys(&nf_tables_net_ops);
96518518
PM
4013err3:
4014 nf_tables_core_module_exit();
4015err2:
4016 kfree(info);
4017err1:
4018 return err;
4019}
4020
4021static void __exit nf_tables_module_exit(void)
4022{
99633ab2 4023 unregister_pernet_subsys(&nf_tables_net_ops);
96518518
PM
4024 nfnetlink_subsys_unregister(&nf_tables_subsys);
4025 nf_tables_core_module_exit();
4026 kfree(info);
4027}
4028
4029module_init(nf_tables_module_init);
4030module_exit(nf_tables_module_exit);
4031
4032MODULE_LICENSE("GPL");
4033MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
4034MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFTABLES);