Skip to content

Commit

Permalink
netfilter: nf_tables: simplify set dump through netlink
Browse files Browse the repository at this point in the history
This patch uses the cb->data pointer that allows us to store the
context when dumping the set list. Thus, we don't need to parse the
original netlink message containing the dump request for each recvmsg()
call when dumping the set list. The different function flavours
depending on the dump criteria has been also merged into one single
generic function. This saves us ~100 lines of code.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
Pablo Neira Ayuso committed Jul 22, 2014
1 parent 85f5b30 commit 5b96af7
Showing 1 changed file with 27 additions and 104 deletions.
131 changes: 27 additions & 104 deletions net/netfilter/nf_tables_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -2247,87 +2247,15 @@ static int nf_tables_set_notify(const struct nft_ctx *ctx,
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];
struct nft_af_info *afi;
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;
Expand All @@ -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;
Expand All @@ -2379,31 +2313,10 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
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 */
Expand All @@ -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);
}

Expand Down

0 comments on commit 5b96af7

Please sign in to comment.