|
@@ -2247,80 +2247,7 @@ err:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static int nf_tables_dump_sets_table(struct nft_ctx *ctx, struct sk_buff *skb,
|
|
|
- struct netlink_callback *cb)
|
|
|
-{
|
|
|
- const struct nft_set *set;
|
|
|
- unsigned int idx = 0, s_idx = cb->args[0];
|
|
|
-
|
|
|
- if (cb->args[1])
|
|
|
- return skb->len;
|
|
|
-
|
|
|
- rcu_read_lock();
|
|
|
- cb->seq = ctx->net->nft.base_seq;
|
|
|
-
|
|
|
- list_for_each_entry_rcu(set, &ctx->table->sets, list) {
|
|
|
- if (idx < s_idx)
|
|
|
- goto cont;
|
|
|
- if (nf_tables_fill_set(skb, ctx, set, NFT_MSG_NEWSET,
|
|
|
- NLM_F_MULTI) < 0) {
|
|
|
- cb->args[0] = idx;
|
|
|
- goto done;
|
|
|
- }
|
|
|
- nl_dump_check_consistent(cb, nlmsg_hdr(skb));
|
|
|
-cont:
|
|
|
- idx++;
|
|
|
- }
|
|
|
- cb->args[1] = 1;
|
|
|
-done:
|
|
|
- rcu_read_unlock();
|
|
|
- return skb->len;
|
|
|
-}
|
|
|
-
|
|
|
-static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb,
|
|
|
- struct netlink_callback *cb)
|
|
|
-{
|
|
|
- const struct nft_set *set;
|
|
|
- unsigned int idx, s_idx = cb->args[0];
|
|
|
- struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
|
|
|
-
|
|
|
- if (cb->args[1])
|
|
|
- return skb->len;
|
|
|
-
|
|
|
- rcu_read_lock();
|
|
|
- cb->seq = ctx->net->nft.base_seq;
|
|
|
-
|
|
|
- list_for_each_entry_rcu(table, &ctx->afi->tables, list) {
|
|
|
- if (cur_table) {
|
|
|
- if (cur_table != table)
|
|
|
- continue;
|
|
|
-
|
|
|
- cur_table = NULL;
|
|
|
- }
|
|
|
- ctx->table = table;
|
|
|
- idx = 0;
|
|
|
- list_for_each_entry_rcu(set, &ctx->table->sets, list) {
|
|
|
- if (idx < s_idx)
|
|
|
- goto cont;
|
|
|
- if (nf_tables_fill_set(skb, ctx, set, NFT_MSG_NEWSET,
|
|
|
- NLM_F_MULTI) < 0) {
|
|
|
- cb->args[0] = idx;
|
|
|
- cb->args[2] = (unsigned long) table;
|
|
|
- goto done;
|
|
|
- }
|
|
|
- nl_dump_check_consistent(cb, nlmsg_hdr(skb));
|
|
|
-cont:
|
|
|
- idx++;
|
|
|
- }
|
|
|
- }
|
|
|
- cb->args[1] = 1;
|
|
|
-done:
|
|
|
- rcu_read_unlock();
|
|
|
- return skb->len;
|
|
|
-}
|
|
|
-
|
|
|
-static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
|
|
|
- struct netlink_callback *cb)
|
|
|
+static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
{
|
|
|
const struct nft_set *set;
|
|
|
unsigned int idx, s_idx = cb->args[0];
|
|
@@ -2328,6 +2255,7 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
|
|
|
struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
|
|
|
struct net *net = sock_net(skb->sk);
|
|
|
int cur_family = cb->args[3];
|
|
|
+ struct nft_ctx *ctx = cb->data, ctx_set;
|
|
|
|
|
|
if (cb->args[1])
|
|
|
return skb->len;
|
|
@@ -2336,28 +2264,34 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
|
|
|
cb->seq = net->nft.base_seq;
|
|
|
|
|
|
list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
|
|
|
+ if (ctx->afi && ctx->afi != afi)
|
|
|
+ continue;
|
|
|
+
|
|
|
if (cur_family) {
|
|
|
if (afi->family != cur_family)
|
|
|
continue;
|
|
|
|
|
|
cur_family = 0;
|
|
|
}
|
|
|
-
|
|
|
list_for_each_entry_rcu(table, &afi->tables, list) {
|
|
|
+ if (ctx->table && ctx->table != table)
|
|
|
+ continue;
|
|
|
+
|
|
|
if (cur_table) {
|
|
|
if (cur_table != table)
|
|
|
continue;
|
|
|
|
|
|
cur_table = NULL;
|
|
|
}
|
|
|
-
|
|
|
- ctx->table = table;
|
|
|
- ctx->afi = afi;
|
|
|
idx = 0;
|
|
|
- list_for_each_entry_rcu(set, &ctx->table->sets, list) {
|
|
|
+ list_for_each_entry_rcu(set, &table->sets, list) {
|
|
|
if (idx < s_idx)
|
|
|
goto cont;
|
|
|
- if (nf_tables_fill_set(skb, ctx, set,
|
|
|
+
|
|
|
+ ctx_set = *ctx;
|
|
|
+ ctx_set.table = table;
|
|
|
+ ctx_set.afi = afi;
|
|
|
+ if (nf_tables_fill_set(skb, &ctx_set, set,
|
|
|
NFT_MSG_NEWSET,
|
|
|
NLM_F_MULTI) < 0) {
|
|
|
cb->args[0] = idx;
|
|
@@ -2379,31 +2313,10 @@ done:
|
|
|
return skb->len;
|
|
|
}
|
|
|
|
|
|
-static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
+static int nf_tables_dump_sets_done(struct netlink_callback *cb)
|
|
|
{
|
|
|
- const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
|
|
|
- struct nlattr *nla[NFTA_SET_MAX + 1];
|
|
|
- struct nft_ctx ctx;
|
|
|
- int err, ret;
|
|
|
-
|
|
|
- err = nlmsg_parse(cb->nlh, sizeof(*nfmsg), nla, NFTA_SET_MAX,
|
|
|
- nft_set_policy);
|
|
|
- if (err < 0)
|
|
|
- return err;
|
|
|
-
|
|
|
- err = nft_ctx_init_from_setattr(&ctx, cb->skb, cb->nlh, (void *)nla);
|
|
|
- if (err < 0)
|
|
|
- return err;
|
|
|
-
|
|
|
- if (ctx.table == NULL) {
|
|
|
- if (ctx.afi == NULL)
|
|
|
- ret = nf_tables_dump_sets_all(&ctx, skb, cb);
|
|
|
- else
|
|
|
- ret = nf_tables_dump_sets_family(&ctx, skb, cb);
|
|
|
- } else
|
|
|
- ret = nf_tables_dump_sets_table(&ctx, skb, cb);
|
|
|
-
|
|
|
- return ret;
|
|
|
+ kfree(cb->data);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
#define NFT_SET_INACTIVE (1 << 15) /* Internal set flag */
|
|
@@ -2426,7 +2339,17 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
|
|
|
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
|
|
struct netlink_dump_control c = {
|
|
|
.dump = nf_tables_dump_sets,
|
|
|
+ .done = nf_tables_dump_sets_done,
|
|
|
};
|
|
|
+ struct nft_ctx *ctx_dump;
|
|
|
+
|
|
|
+ ctx_dump = kmalloc(sizeof(*ctx_dump), GFP_KERNEL);
|
|
|
+ if (ctx_dump == NULL)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ *ctx_dump = ctx;
|
|
|
+ c.data = ctx_dump;
|
|
|
+
|
|
|
return netlink_dump_start(nlsk, skb, nlh, &c);
|
|
|
}
|
|
|
|
|
@@ -3150,6 +3073,9 @@ static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb,
|
|
|
struct nft_ctx ctx;
|
|
|
int rem, err = 0;
|
|
|
|
|
|
+ if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, true);
|
|
|
if (err < 0)
|
|
|
return err;
|
|
@@ -3233,6 +3159,9 @@ static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb,
|
|
|
struct nft_ctx ctx;
|
|
|
int rem, err = 0;
|
|
|
|
|
|
+ if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, false);
|
|
|
if (err < 0)
|
|
|
return err;
|