Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
[cascardo/linux.git] / net / netfilter / nf_tables_netdev.c
index edb3502..b6605e0 100644 (file)
@@ -139,7 +139,7 @@ err:
 
 static void nf_tables_netdev_exit_net(struct net *net)
 {
-       nft_unregister_afinfo(net->nft.netdev);
+       nft_unregister_afinfo(net, net->nft.netdev);
        kfree(net->nft.netdev);
 }
 
@@ -156,35 +156,17 @@ static const struct nf_chain_type nft_filter_chain_netdev = {
        .hook_mask      = (1 << NF_NETDEV_INGRESS),
 };
 
-static void nft_netdev_event(unsigned long event, struct nft_af_info *afi,
-                            struct net_device *dev, struct nft_table *table,
-                            struct nft_base_chain *basechain)
+static void nft_netdev_event(unsigned long event, struct net_device *dev,
+                            struct nft_ctx *ctx)
 {
-       switch (event) {
-       case NETDEV_REGISTER:
-               if (strcmp(basechain->dev_name, dev->name) != 0)
-                       return;
+       struct nft_base_chain *basechain = nft_base_chain(ctx->chain);
 
-               BUG_ON(!(basechain->flags & NFT_BASECHAIN_DISABLED));
-
-               dev_hold(dev);
-               basechain->ops[0].dev = dev;
-               basechain->flags &= ~NFT_BASECHAIN_DISABLED;
-               if (!(table->flags & NFT_TABLE_F_DORMANT))
-                       nft_register_basechain(basechain, afi->nops);
-               break;
+       switch (event) {
        case NETDEV_UNREGISTER:
                if (strcmp(basechain->dev_name, dev->name) != 0)
                        return;
 
-               BUG_ON(basechain->flags & NFT_BASECHAIN_DISABLED);
-
-               if (!(table->flags & NFT_TABLE_F_DORMANT))
-                       nft_unregister_basechain(basechain, afi->nops);
-
-               dev_put(basechain->ops[0].dev);
-               basechain->ops[0].dev = NULL;
-               basechain->flags |= NFT_BASECHAIN_DISABLED;
+               __nft_release_basechain(ctx);
                break;
        case NETDEV_CHANGENAME:
                if (dev->ifindex != basechain->ops[0].dev->ifindex)
@@ -201,20 +183,29 @@ static int nf_tables_netdev_event(struct notifier_block *this,
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct nft_af_info *afi;
        struct nft_table *table;
-       struct nft_chain *chain;
+       struct nft_chain *chain, *nr;
+       struct nft_ctx ctx = {
+               .net    = dev_net(dev),
+       };
+
+       if (event != NETDEV_UNREGISTER &&
+           event != NETDEV_CHANGENAME)
+               return NOTIFY_DONE;
 
        nfnl_lock(NFNL_SUBSYS_NFTABLES);
        list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) {
+               ctx.afi = afi;
                if (afi->family != NFPROTO_NETDEV)
                        continue;
 
                list_for_each_entry(table, &afi->tables, list) {
-                       list_for_each_entry(chain, &table->chains, list) {
+                       ctx.table = table;
+                       list_for_each_entry_safe(chain, nr, &table->chains, list) {
                                if (!(chain->flags & NFT_BASE_CHAIN))
                                        continue;
 
-                               nft_netdev_event(event, afi, dev, table,
-                                                nft_base_chain(chain));
+                               ctx.chain = chain;
+                               nft_netdev_event(event, dev, &ctx);
                        }
                }
        }