Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nf_tables: extend NFT_MSG_DELTABLE to support flushing the ruleset

This patch extend the NFT_MSG_DELTABLE call to support flushing the entire
ruleset.

The options now are:
* No family speficied, no table specified: flush all the ruleset.
* Family specified, no table specified: flush all tables in the AF.
* Family specified, table specified: flush the given table.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Arturo Borrero and committed by
Pablo Neira Ayuso
b9ac12ef ee01d542

+68 -4
+68 -4
net/netfilter/nf_tables_api.c
··· 707 707 return 0; 708 708 } 709 709 710 + static int nft_flush_table(struct nft_ctx *ctx) 711 + { 712 + int err; 713 + struct nft_chain *chain, *nc; 714 + struct nft_set *set, *ns; 715 + 716 + list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) { 717 + ctx->chain = chain; 718 + 719 + err = nft_delrule_by_chain(ctx); 720 + if (err < 0) 721 + goto out; 722 + 723 + err = nft_delchain(ctx); 724 + if (err < 0) 725 + goto out; 726 + } 727 + 728 + list_for_each_entry_safe(set, ns, &ctx->table->sets, list) { 729 + if (set->flags & NFT_SET_ANONYMOUS && 730 + !list_empty(&set->bindings)) 731 + continue; 732 + 733 + err = nft_delset(ctx, set); 734 + if (err < 0) 735 + goto out; 736 + } 737 + 738 + err = nft_deltable(ctx); 739 + out: 740 + return err; 741 + } 742 + 743 + static int nft_flush(struct nft_ctx *ctx, int family) 744 + { 745 + struct nft_af_info *afi; 746 + struct nft_table *table, *nt; 747 + const struct nlattr * const *nla = ctx->nla; 748 + int err = 0; 749 + 750 + list_for_each_entry(afi, &ctx->net->nft.af_info, list) { 751 + if (family != AF_UNSPEC && afi->family != family) 752 + continue; 753 + 754 + ctx->afi = afi; 755 + list_for_each_entry_safe(table, nt, &afi->tables, list) { 756 + if (nla[NFTA_TABLE_NAME] && 757 + nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0) 758 + continue; 759 + 760 + ctx->table = table; 761 + 762 + err = nft_flush_table(ctx); 763 + if (err < 0) 764 + goto out; 765 + } 766 + } 767 + out: 768 + return err; 769 + } 770 + 710 771 static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb, 711 772 const struct nlmsghdr *nlh, 712 773 const struct nlattr * const nla[]) ··· 779 718 int family = nfmsg->nfgen_family; 780 719 struct nft_ctx ctx; 781 720 721 + nft_ctx_init(&ctx, skb, nlh, NULL, NULL, NULL, nla); 722 + if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) 723 + return nft_flush(&ctx, family); 724 + 782 725 afi = nf_tables_afinfo_lookup(net, family, false); 783 726 if (IS_ERR(afi)) 784 727 return PTR_ERR(afi); ··· 792 727 return PTR_ERR(table); 793 728 if (table->flags & NFT_TABLE_INACTIVE) 794 729 return -ENOENT; 795 - if (table->use > 0) 796 - return -EBUSY; 797 730 798 - nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla); 731 + ctx.afi = afi; 732 + ctx.table = table; 799 733 800 - return nft_deltable(&ctx); 734 + return nft_flush_table(&ctx); 801 735 } 802 736 803 737 static void nf_tables_table_destroy(struct nft_ctx *ctx)