netfilter: nf_tables: remove multihook chains and families
authorPablo Neira Ayuso <pablo@netfilter.org>
Sat, 9 Dec 2017 14:40:25 +0000 (15:40 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 8 Jan 2018 17:01:21 +0000 (18:01 +0100)
Since NFPROTO_INET is handled from the core, we don't need to maintain
extra infrastructure in nf_tables to handle the double hook
registration, one for IPv4 and another for IPv6.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netfilter/nf_tables.h
net/bridge/netfilter/nf_tables_bridge.c
net/ipv4/netfilter/nf_tables_arp.c
net/ipv4/netfilter/nf_tables_ipv4.c
net/ipv6/netfilter/nf_tables_ipv6.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_inet.c
net/netfilter/nf_tables_netdev.c
net/netfilter/nft_compat.c

index 169b562..a3560fd 100644 (file)
@@ -902,8 +902,6 @@ struct nft_stats {
        struct u64_stats_sync   syncp;
 };
 
-#define NFT_HOOK_OPS_MAX               2
-
 /**
  *     struct nft_base_chain - nf_tables base chain
  *
@@ -915,7 +913,7 @@ struct nft_stats {
  *     @dev_name: device name that this base chain is attached to (if any)
  */
 struct nft_base_chain {
-       struct nf_hook_ops              ops[NFT_HOOK_OPS_MAX];
+       struct nf_hook_ops              ops;
        const struct nf_chain_type      *type;
        u8                              policy;
        u8                              flags;
@@ -976,8 +974,6 @@ enum nft_af_flags {
  *     @owner: module owner
  *     @tables: used internally
  *     @flags: family flags
- *     @nops: number of hook ops in this family
- *     @hook_ops_init: initialization function for chain hook ops
  *     @hooks: hookfn overrides for packet validation
  */
 struct nft_af_info {
@@ -987,9 +983,6 @@ struct nft_af_info {
        struct module                   *owner;
        struct list_head                tables;
        u32                             flags;
-       unsigned int                    nops;
-       void                            (*hook_ops_init)(struct nf_hook_ops *,
-                                                        unsigned int);
        nf_hookfn                       *hooks[NF_MAX_HOOKS];
 };
 
index 612bfd0..991d0ab 100644 (file)
@@ -46,7 +46,6 @@ static struct nft_af_info nft_af_bridge __read_mostly = {
        .family         = NFPROTO_BRIDGE,
        .nhooks         = NF_BR_NUMHOOKS,
        .owner          = THIS_MODULE,
-       .nops           = 1,
        .hooks          = {
                [NF_BR_PRE_ROUTING]     = nft_do_chain_bridge,
                [NF_BR_LOCAL_IN]        = nft_do_chain_bridge,
index 3fa7e1b..3090f63 100644 (file)
@@ -31,7 +31,6 @@ static struct nft_af_info nft_af_arp __read_mostly = {
        .family         = NFPROTO_ARP,
        .nhooks         = NF_ARP_NUMHOOKS,
        .owner          = THIS_MODULE,
-       .nops           = 1,
        .hooks          = {
                [NF_ARP_IN]             = nft_do_chain_arp,
                [NF_ARP_OUT]            = nft_do_chain_arp,
index b6223f4..51b363a 100644 (file)
@@ -49,7 +49,6 @@ static struct nft_af_info nft_af_ipv4 __read_mostly = {
        .family         = NFPROTO_IPV4,
        .nhooks         = NF_INET_NUMHOOKS,
        .owner          = THIS_MODULE,
-       .nops           = 1,
        .hooks          = {
                [NF_INET_LOCAL_IN]      = nft_do_chain_ipv4,
                [NF_INET_LOCAL_OUT]     = nft_ipv4_output,
index b1b5d38..78d34a2 100644 (file)
@@ -46,7 +46,6 @@ static struct nft_af_info nft_af_ipv6 __read_mostly = {
        .family         = NFPROTO_IPV6,
        .nhooks         = NF_INET_NUMHOOKS,
        .owner          = THIS_MODULE,
-       .nops           = 1,
        .hooks          = {
                [NF_INET_LOCAL_IN]      = nft_do_chain_ipv6,
                [NF_INET_LOCAL_OUT]     = nft_ipv6_output,
index 7bc1b0c..06fae43 100644 (file)
@@ -139,29 +139,26 @@ static void nft_trans_destroy(struct nft_trans *trans)
        kfree(trans);
 }
 
-static int nf_tables_register_hooks(struct net *net,
-                                   const struct nft_table *table,
-                                   struct nft_chain *chain,
-                                   unsigned int hook_nops)
+static int nf_tables_register_hook(struct net *net,
+                                  const struct nft_table *table,
+                                  struct nft_chain *chain)
 {
        if (table->flags & NFT_TABLE_F_DORMANT ||
            !nft_is_base_chain(chain))
                return 0;
 
-       return nf_register_net_hooks(net, nft_base_chain(chain)->ops,
-                                    hook_nops);
+       return nf_register_net_hook(net, &nft_base_chain(chain)->ops);
 }
 
-static void nf_tables_unregister_hooks(struct net *net,
-                                      const struct nft_table *table,
-                                      struct nft_chain *chain,
-                                      unsigned int hook_nops)
+static void nf_tables_unregister_hook(struct net *net,
+                                     const struct nft_table *table,
+                                     struct nft_chain *chain)
 {
        if (table->flags & NFT_TABLE_F_DORMANT ||
            !nft_is_base_chain(chain))
                return;
 
-       nf_unregister_net_hooks(net, nft_base_chain(chain)->ops, hook_nops);
+       nf_unregister_net_hook(net, &nft_base_chain(chain)->ops);
 }
 
 static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type)
@@ -595,8 +592,7 @@ static void _nf_tables_table_disable(struct net *net,
                if (cnt && i++ == cnt)
                        break;
 
-               nf_unregister_net_hooks(net, nft_base_chain(chain)->ops,
-                                       afi->nops);
+               nf_unregister_net_hook(net, &nft_base_chain(chain)->ops);
        }
 }
 
@@ -613,8 +609,7 @@ static int nf_tables_table_enable(struct net *net,
                if (!nft_is_base_chain(chain))
                        continue;
 
-               err = nf_register_net_hooks(net, nft_base_chain(chain)->ops,
-                                           afi->nops);
+               err = nf_register_net_hook(net, &nft_base_chain(chain)->ops);
                if (err < 0)
                        goto err;
 
@@ -1026,7 +1021,7 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
 
        if (nft_is_base_chain(chain)) {
                const struct nft_base_chain *basechain = nft_base_chain(chain);
-               const struct nf_hook_ops *ops = &basechain->ops[0];
+               const struct nf_hook_ops *ops = &basechain->ops;
                struct nlattr *nest;
 
                nest = nla_nest_start(skb, NFTA_CHAIN_HOOK);
@@ -1252,8 +1247,8 @@ static void nf_tables_chain_destroy(struct nft_chain *chain)
                free_percpu(basechain->stats);
                if (basechain->stats)
                        static_branch_dec(&nft_counters_enabled);
-               if (basechain->ops[0].dev != NULL)
-                       dev_put(basechain->ops[0].dev);
+               if (basechain->ops.dev != NULL)
+                       dev_put(basechain->ops.dev);
                kfree(chain->name);
                kfree(basechain);
        } else {
@@ -1354,7 +1349,6 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
        struct nft_stats __percpu *stats;
        struct net *net = ctx->net;
        struct nft_chain *chain;
-       unsigned int i;
        int err;
 
        if (table->use == UINT_MAX)
@@ -1393,21 +1387,18 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
                basechain->type = hook.type;
                chain = &basechain->chain;
 
-               for (i = 0; i < afi->nops; i++) {
-                       ops = &basechain->ops[i];
-                       ops->pf         = family;
-                       ops->hooknum    = hook.num;
-                       ops->priority   = hook.priority;
-                       ops->priv       = chain;
-                       ops->hook       = afi->hooks[ops->hooknum];
-                       ops->dev        = hook.dev;
-                       if (hookfn)
-                               ops->hook = hookfn;
-                       if (afi->hook_ops_init)
-                               afi->hook_ops_init(ops, i);
-                       if (basechain->type->type == NFT_CHAIN_T_NAT)
-                               ops->nat_hook = true;
-               }
+               ops             = &basechain->ops;
+               ops->pf         = family;
+               ops->hooknum    = hook.num;
+               ops->priority   = hook.priority;
+               ops->priv       = chain;
+               ops->hook       = afi->hooks[ops->hooknum];
+               ops->dev        = hook.dev;
+               if (hookfn)
+                       ops->hook = hookfn;
+
+               if (basechain->type->type == NFT_CHAIN_T_NAT)
+                       ops->nat_hook = true;
 
                chain->flags |= NFT_BASE_CHAIN;
                basechain->policy = policy;
@@ -1425,7 +1416,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
                goto err1;
        }
 
-       err = nf_tables_register_hooks(net, table, chain, afi->nops);
+       err = nf_tables_register_hook(net, table, chain);
        if (err < 0)
                goto err1;
 
@@ -1439,7 +1430,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
 
        return 0;
 err2:
-       nf_tables_unregister_hooks(net, table, chain, afi->nops);
+       nf_tables_unregister_hook(net, table, chain);
 err1:
        nf_tables_chain_destroy(chain);
 
@@ -1452,14 +1443,13 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
        const struct nlattr * const *nla = ctx->nla;
        struct nft_table *table = ctx->table;
        struct nft_chain *chain = ctx->chain;
-       struct nft_af_info *afi = ctx->afi;
        struct nft_base_chain *basechain;
        struct nft_stats *stats = NULL;
        struct nft_chain_hook hook;
        const struct nlattr *name;
        struct nf_hook_ops *ops;
        struct nft_trans *trans;
-       int err, i;
+       int err;
 
        if (nla[NFTA_CHAIN_HOOK]) {
                if (!nft_is_base_chain(chain))
@@ -1476,14 +1466,12 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
                        return -EBUSY;
                }
 
-               for (i = 0; i < afi->nops; i++) {
-                       ops = &basechain->ops[i];
-                       if (ops->hooknum != hook.num ||
-                           ops->priority != hook.priority ||
-                           ops->dev != hook.dev) {
-                               nft_chain_release_hook(&hook);
-                               return -EBUSY;
-                       }
+               ops = &basechain->ops;
+               if (ops->hooknum != hook.num ||
+                   ops->priority != hook.priority ||
+                   ops->dev != hook.dev) {
+                       nft_chain_release_hook(&hook);
+                       return -EBUSY;
                }
                nft_chain_release_hook(&hook);
        }
@@ -5134,10 +5122,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
                case NFT_MSG_DELCHAIN:
                        list_del_rcu(&trans->ctx.chain->list);
                        nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN);
-                       nf_tables_unregister_hooks(trans->ctx.net,
-                                                  trans->ctx.table,
-                                                  trans->ctx.chain,
-                                                  trans->ctx.afi->nops);
+                       nf_tables_unregister_hook(trans->ctx.net,
+                                                 trans->ctx.table,
+                                                 trans->ctx.chain);
                        break;
                case NFT_MSG_NEWRULE:
                        nft_clear(trans->ctx.net, nft_trans_rule(trans));
@@ -5274,10 +5261,9 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
                        } else {
                                trans->ctx.table->use--;
                                list_del_rcu(&trans->ctx.chain->list);
-                               nf_tables_unregister_hooks(trans->ctx.net,
-                                                          trans->ctx.table,
-                                                          trans->ctx.chain,
-                                                          trans->ctx.afi->nops);
+                               nf_tables_unregister_hook(trans->ctx.net,
+                                                         trans->ctx.table,
+                                                         trans->ctx.chain);
                        }
                        break;
                case NFT_MSG_DELCHAIN:
@@ -5378,7 +5364,7 @@ int nft_chain_validate_hooks(const struct nft_chain *chain,
        if (nft_is_base_chain(chain)) {
                basechain = nft_base_chain(chain);
 
-               if ((1 << basechain->ops[0].hooknum) & hook_flags)
+               if ((1 << basechain->ops.hooknum) & hook_flags)
                        return 0;
 
                return -EOPNOTSUPP;
@@ -5866,8 +5852,7 @@ int __nft_release_basechain(struct nft_ctx *ctx)
 
        BUG_ON(!nft_is_base_chain(ctx->chain));
 
-       nf_tables_unregister_hooks(ctx->net, ctx->chain->table, ctx->chain,
-                                  ctx->afi->nops);
+       nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain);
        list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
                list_del(&rule->list);
                ctx->chain->use--;
@@ -5896,8 +5881,7 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
 
        list_for_each_entry_safe(table, nt, &afi->tables, list) {
                list_for_each_entry(chain, &table->chains, list)
-                       nf_tables_unregister_hooks(net, table, chain,
-                                                  afi->nops);
+                       nf_tables_unregister_hook(net, table, chain);
                /* No packets are walking on these chains anymore. */
                ctx.table = table;
                list_for_each_entry(chain, &table->chains, list) {
index c6194b3..edd7829 100644 (file)
@@ -74,7 +74,6 @@ static struct nft_af_info nft_af_inet __read_mostly = {
        .family         = NFPROTO_INET,
        .nhooks         = NF_INET_NUMHOOKS,
        .owner          = THIS_MODULE,
-       .nops           = 1,
        .hooks          = {
                [NF_INET_LOCAL_IN]      = nft_do_chain_inet,
                [NF_INET_LOCAL_OUT]     = nft_inet_output,
index 3cd127d..018e2c5 100644 (file)
@@ -43,7 +43,6 @@ static struct nft_af_info nft_af_netdev __read_mostly = {
        .nhooks         = NF_NETDEV_NUMHOOKS,
        .owner          = THIS_MODULE,
        .flags          = NFT_AF_NEEDS_DEV,
-       .nops           = 1,
        .hooks          = {
                [NF_NETDEV_INGRESS]     = nft_do_chain_netdev,
        },
@@ -98,7 +97,7 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev,
                __nft_release_basechain(ctx);
                break;
        case NETDEV_CHANGENAME:
-               if (dev->ifindex != basechain->ops[0].dev->ifindex)
+               if (dev->ifindex != basechain->ops.dev->ifindex)
                        return;
 
                strncpy(basechain->dev_name, dev->name, IFNAMSIZ);
index b89f4f6..dcff0dc 100644 (file)
@@ -169,7 +169,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
        if (nft_is_base_chain(ctx->chain)) {
                const struct nft_base_chain *basechain =
                                                nft_base_chain(ctx->chain);
-               const struct nf_hook_ops *ops = &basechain->ops[0];
+               const struct nf_hook_ops *ops = &basechain->ops;
 
                par->hook_mask = 1 << ops->hooknum;
        } else {
@@ -302,7 +302,7 @@ static int nft_target_validate(const struct nft_ctx *ctx,
        if (nft_is_base_chain(ctx->chain)) {
                const struct nft_base_chain *basechain =
                                                nft_base_chain(ctx->chain);
-               const struct nf_hook_ops *ops = &basechain->ops[0];
+               const struct nf_hook_ops *ops = &basechain->ops;
 
                hook_mask = 1 << ops->hooknum;
                if (target->hooks && !(hook_mask & target->hooks))
@@ -383,7 +383,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
        if (nft_is_base_chain(ctx->chain)) {
                const struct nft_base_chain *basechain =
                                                nft_base_chain(ctx->chain);
-               const struct nf_hook_ops *ops = &basechain->ops[0];
+               const struct nf_hook_ops *ops = &basechain->ops;
 
                par->hook_mask = 1 << ops->hooknum;
        } else {
@@ -481,7 +481,7 @@ static int nft_match_validate(const struct nft_ctx *ctx,
        if (nft_is_base_chain(ctx->chain)) {
                const struct nft_base_chain *basechain =
                                                nft_base_chain(ctx->chain);
-               const struct nf_hook_ops *ops = &basechain->ops[0];
+               const struct nf_hook_ops *ops = &basechain->ops;
 
                hook_mask = 1 << ops->hooknum;
                if (match->hooks && !(hook_mask & match->hooks))