This allows you to obtain all existing sets in all families. After this patch, there are three possible combinations: * Pass table name and family != NFPROTO_UNSPEC, to obtain sets that belong to a table. * Pass family != NFPROTO_UNSPEC, to obtain all sets from a specific family. * Pass family == NFPROTO_UNSPEC, to obtain all sets, no matter what table and family they belong to. Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@xxxxxxxxx> Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- v2: fix some netlink issues by Pablo. net/netfilter/nf_tables_api.c | 64 +++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index dcddc49..d2540f8 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1903,9 +1903,12 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, { struct net *net = sock_net(skb->sk); const struct nfgenmsg *nfmsg = nlmsg_data(nlh); - const struct nft_af_info *afi; + const struct nft_af_info *afi = NULL; const struct nft_table *table = NULL; + if (nfmsg->nfgen_family == AF_UNSPEC) + goto out; + afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); if (IS_ERR(afi)) return PTR_ERR(afi); @@ -1915,7 +1918,7 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, if (IS_ERR(table)) return PTR_ERR(table); } - +out: nft_ctx_init(ctx, skb, nlh, afi, table, NULL, nla); return 0; } @@ -2079,27 +2082,46 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb, { const struct nft_set *set; unsigned int idx = 0, s_idx = cb->args[0]; + const 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 family, cur_family = cb->args[3]; if (cb->args[1]) return skb->len; - list_for_each_entry(table, &ctx->afi->tables, list) { - if (cur_table && cur_table != table) + if (ctx->afi == NULL) + family = NFPROTO_UNSPEC; + else + family = ctx->afi->family; + + list_for_each_entry(afi, &net->nft.af_info, list) { + if (cur_family && afi->family != cur_family) continue; - ctx->table = table; - list_for_each_entry(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; - } + if (family != NFPROTO_UNSPEC && family != afi->family) + continue; + + list_for_each_entry(table, &afi->tables, list) { + if (cur_table && cur_table != table) + continue; + + ctx->table = table; + ctx->afi = afi; + list_for_each_entry(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; + cb->args[3] = afi->family; + goto done; + } cont: - idx++; + idx++; + } } } cb->args[1] = 1; @@ -2138,12 +2160,16 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb, const struct nft_set *set; struct nft_ctx ctx; struct sk_buff *skb2; + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); int err; - /* Verify existance before starting dump */ - err = nft_ctx_init_from_setattr(&ctx, skb, nlh, nla); - if (err < 0) - return err; + if (nfmsg->nfgen_family != AF_UNSPEC) { + /* Verify existance before starting dump */ + err = nft_ctx_init_from_setattr(&ctx, skb, nlh, nla); + if (err < 0) + return err; + } + if (nlh->nlmsg_flags & NLM_F_DUMP) { struct netlink_dump_control c = { -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html