root/net/netfilter/nft_immediate.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nft_immediate_eval
  2. nft_immediate_init
  3. nft_immediate_activate
  4. nft_immediate_deactivate
  5. nft_immediate_dump
  6. nft_immediate_validate
  7. nft_immediate_offload_verdict
  8. nft_immediate_offload

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
   4  *
   5  * Development of this code funded by Astaro AG (http://www.astaro.com/)
   6  */
   7 
   8 #include <linux/kernel.h>
   9 #include <linux/init.h>
  10 #include <linux/module.h>
  11 #include <linux/netlink.h>
  12 #include <linux/netfilter.h>
  13 #include <linux/netfilter/nf_tables.h>
  14 #include <net/netfilter/nf_tables_core.h>
  15 #include <net/netfilter/nf_tables.h>
  16 #include <net/netfilter/nf_tables_offload.h>
  17 
  18 void nft_immediate_eval(const struct nft_expr *expr,
  19                         struct nft_regs *regs,
  20                         const struct nft_pktinfo *pkt)
  21 {
  22         const struct nft_immediate_expr *priv = nft_expr_priv(expr);
  23 
  24         nft_data_copy(&regs->data[priv->dreg], &priv->data, priv->dlen);
  25 }
  26 
  27 static const struct nla_policy nft_immediate_policy[NFTA_IMMEDIATE_MAX + 1] = {
  28         [NFTA_IMMEDIATE_DREG]   = { .type = NLA_U32 },
  29         [NFTA_IMMEDIATE_DATA]   = { .type = NLA_NESTED },
  30 };
  31 
  32 static int nft_immediate_init(const struct nft_ctx *ctx,
  33                               const struct nft_expr *expr,
  34                               const struct nlattr * const tb[])
  35 {
  36         struct nft_immediate_expr *priv = nft_expr_priv(expr);
  37         struct nft_data_desc desc;
  38         int err;
  39 
  40         if (tb[NFTA_IMMEDIATE_DREG] == NULL ||
  41             tb[NFTA_IMMEDIATE_DATA] == NULL)
  42                 return -EINVAL;
  43 
  44         err = nft_data_init(ctx, &priv->data, sizeof(priv->data), &desc,
  45                             tb[NFTA_IMMEDIATE_DATA]);
  46         if (err < 0)
  47                 return err;
  48 
  49         priv->dlen = desc.len;
  50 
  51         priv->dreg = nft_parse_register(tb[NFTA_IMMEDIATE_DREG]);
  52         err = nft_validate_register_store(ctx, priv->dreg, &priv->data,
  53                                           desc.type, desc.len);
  54         if (err < 0)
  55                 goto err1;
  56 
  57         return 0;
  58 
  59 err1:
  60         nft_data_release(&priv->data, desc.type);
  61         return err;
  62 }
  63 
  64 static void nft_immediate_activate(const struct nft_ctx *ctx,
  65                                    const struct nft_expr *expr)
  66 {
  67         const struct nft_immediate_expr *priv = nft_expr_priv(expr);
  68 
  69         return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
  70 }
  71 
  72 static void nft_immediate_deactivate(const struct nft_ctx *ctx,
  73                                      const struct nft_expr *expr,
  74                                      enum nft_trans_phase phase)
  75 {
  76         const struct nft_immediate_expr *priv = nft_expr_priv(expr);
  77 
  78         if (phase == NFT_TRANS_COMMIT)
  79                 return;
  80 
  81         return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg));
  82 }
  83 
  84 static int nft_immediate_dump(struct sk_buff *skb, const struct nft_expr *expr)
  85 {
  86         const struct nft_immediate_expr *priv = nft_expr_priv(expr);
  87 
  88         if (nft_dump_register(skb, NFTA_IMMEDIATE_DREG, priv->dreg))
  89                 goto nla_put_failure;
  90 
  91         return nft_data_dump(skb, NFTA_IMMEDIATE_DATA, &priv->data,
  92                              nft_dreg_to_type(priv->dreg), priv->dlen);
  93 
  94 nla_put_failure:
  95         return -1;
  96 }
  97 
  98 static int nft_immediate_validate(const struct nft_ctx *ctx,
  99                                   const struct nft_expr *expr,
 100                                   const struct nft_data **d)
 101 {
 102         const struct nft_immediate_expr *priv = nft_expr_priv(expr);
 103         struct nft_ctx *pctx = (struct nft_ctx *)ctx;
 104         const struct nft_data *data;
 105         int err;
 106 
 107         if (priv->dreg != NFT_REG_VERDICT)
 108                 return 0;
 109 
 110         data = &priv->data;
 111 
 112         switch (data->verdict.code) {
 113         case NFT_JUMP:
 114         case NFT_GOTO:
 115                 pctx->level++;
 116                 err = nft_chain_validate(ctx, data->verdict.chain);
 117                 if (err < 0)
 118                         return err;
 119                 pctx->level--;
 120                 break;
 121         default:
 122                 break;
 123         }
 124 
 125         return 0;
 126 }
 127 
 128 static int nft_immediate_offload_verdict(struct nft_offload_ctx *ctx,
 129                                          struct nft_flow_rule *flow,
 130                                          const struct nft_immediate_expr *priv)
 131 {
 132         struct flow_action_entry *entry;
 133         const struct nft_data *data;
 134 
 135         entry = &flow->rule->action.entries[ctx->num_actions++];
 136 
 137         data = &priv->data;
 138         switch (data->verdict.code) {
 139         case NF_ACCEPT:
 140                 entry->id = FLOW_ACTION_ACCEPT;
 141                 break;
 142         case NF_DROP:
 143                 entry->id = FLOW_ACTION_DROP;
 144                 break;
 145         default:
 146                 return -EOPNOTSUPP;
 147         }
 148 
 149         return 0;
 150 }
 151 
 152 static int nft_immediate_offload(struct nft_offload_ctx *ctx,
 153                                  struct nft_flow_rule *flow,
 154                                  const struct nft_expr *expr)
 155 {
 156         const struct nft_immediate_expr *priv = nft_expr_priv(expr);
 157 
 158         if (priv->dreg == NFT_REG_VERDICT)
 159                 return nft_immediate_offload_verdict(ctx, flow, priv);
 160 
 161         memcpy(&ctx->regs[priv->dreg].data, &priv->data, sizeof(priv->data));
 162 
 163         return 0;
 164 }
 165 
 166 static const struct nft_expr_ops nft_imm_ops = {
 167         .type           = &nft_imm_type,
 168         .size           = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)),
 169         .eval           = nft_immediate_eval,
 170         .init           = nft_immediate_init,
 171         .activate       = nft_immediate_activate,
 172         .deactivate     = nft_immediate_deactivate,
 173         .dump           = nft_immediate_dump,
 174         .validate       = nft_immediate_validate,
 175         .offload        = nft_immediate_offload,
 176         .offload_flags  = NFT_OFFLOAD_F_ACTION,
 177 };
 178 
 179 struct nft_expr_type nft_imm_type __read_mostly = {
 180         .name           = "immediate",
 181         .ops            = &nft_imm_ops,
 182         .policy         = nft_immediate_policy,
 183         .maxattr        = NFTA_IMMEDIATE_MAX,
 184         .owner          = THIS_MODULE,
 185 };

/* [<][>][^][v][top][bottom][index][help] */