root/net/netfilter/nft_bitwise.c

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

DEFINITIONS

This source file includes following definitions.
  1. nft_bitwise_eval
  2. nft_bitwise_init
  3. nft_bitwise_dump
  4. nft_bitwise_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 struct nft_bitwise {
  19         enum nft_registers      sreg:8;
  20         enum nft_registers      dreg:8;
  21         u8                      len;
  22         struct nft_data         mask;
  23         struct nft_data         xor;
  24 };
  25 
  26 void nft_bitwise_eval(const struct nft_expr *expr,
  27                       struct nft_regs *regs, const struct nft_pktinfo *pkt)
  28 {
  29         const struct nft_bitwise *priv = nft_expr_priv(expr);
  30         const u32 *src = &regs->data[priv->sreg];
  31         u32 *dst = &regs->data[priv->dreg];
  32         unsigned int i;
  33 
  34         for (i = 0; i < DIV_ROUND_UP(priv->len, 4); i++)
  35                 dst[i] = (src[i] & priv->mask.data[i]) ^ priv->xor.data[i];
  36 }
  37 
  38 static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = {
  39         [NFTA_BITWISE_SREG]     = { .type = NLA_U32 },
  40         [NFTA_BITWISE_DREG]     = { .type = NLA_U32 },
  41         [NFTA_BITWISE_LEN]      = { .type = NLA_U32 },
  42         [NFTA_BITWISE_MASK]     = { .type = NLA_NESTED },
  43         [NFTA_BITWISE_XOR]      = { .type = NLA_NESTED },
  44 };
  45 
  46 static int nft_bitwise_init(const struct nft_ctx *ctx,
  47                             const struct nft_expr *expr,
  48                             const struct nlattr * const tb[])
  49 {
  50         struct nft_bitwise *priv = nft_expr_priv(expr);
  51         struct nft_data_desc d1, d2;
  52         u32 len;
  53         int err;
  54 
  55         if (tb[NFTA_BITWISE_SREG] == NULL ||
  56             tb[NFTA_BITWISE_DREG] == NULL ||
  57             tb[NFTA_BITWISE_LEN] == NULL ||
  58             tb[NFTA_BITWISE_MASK] == NULL ||
  59             tb[NFTA_BITWISE_XOR] == NULL)
  60                 return -EINVAL;
  61 
  62         err = nft_parse_u32_check(tb[NFTA_BITWISE_LEN], U8_MAX, &len);
  63         if (err < 0)
  64                 return err;
  65 
  66         priv->len = len;
  67 
  68         priv->sreg = nft_parse_register(tb[NFTA_BITWISE_SREG]);
  69         err = nft_validate_register_load(priv->sreg, priv->len);
  70         if (err < 0)
  71                 return err;
  72 
  73         priv->dreg = nft_parse_register(tb[NFTA_BITWISE_DREG]);
  74         err = nft_validate_register_store(ctx, priv->dreg, NULL,
  75                                           NFT_DATA_VALUE, priv->len);
  76         if (err < 0)
  77                 return err;
  78 
  79         err = nft_data_init(NULL, &priv->mask, sizeof(priv->mask), &d1,
  80                             tb[NFTA_BITWISE_MASK]);
  81         if (err < 0)
  82                 return err;
  83         if (d1.type != NFT_DATA_VALUE || d1.len != priv->len) {
  84                 err = -EINVAL;
  85                 goto err1;
  86         }
  87 
  88         err = nft_data_init(NULL, &priv->xor, sizeof(priv->xor), &d2,
  89                             tb[NFTA_BITWISE_XOR]);
  90         if (err < 0)
  91                 goto err1;
  92         if (d2.type != NFT_DATA_VALUE || d2.len != priv->len) {
  93                 err = -EINVAL;
  94                 goto err2;
  95         }
  96 
  97         return 0;
  98 err2:
  99         nft_data_release(&priv->xor, d2.type);
 100 err1:
 101         nft_data_release(&priv->mask, d1.type);
 102         return err;
 103 }
 104 
 105 static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr)
 106 {
 107         const struct nft_bitwise *priv = nft_expr_priv(expr);
 108 
 109         if (nft_dump_register(skb, NFTA_BITWISE_SREG, priv->sreg))
 110                 goto nla_put_failure;
 111         if (nft_dump_register(skb, NFTA_BITWISE_DREG, priv->dreg))
 112                 goto nla_put_failure;
 113         if (nla_put_be32(skb, NFTA_BITWISE_LEN, htonl(priv->len)))
 114                 goto nla_put_failure;
 115 
 116         if (nft_data_dump(skb, NFTA_BITWISE_MASK, &priv->mask,
 117                           NFT_DATA_VALUE, priv->len) < 0)
 118                 goto nla_put_failure;
 119 
 120         if (nft_data_dump(skb, NFTA_BITWISE_XOR, &priv->xor,
 121                           NFT_DATA_VALUE, priv->len) < 0)
 122                 goto nla_put_failure;
 123 
 124         return 0;
 125 
 126 nla_put_failure:
 127         return -1;
 128 }
 129 
 130 static struct nft_data zero;
 131 
 132 static int nft_bitwise_offload(struct nft_offload_ctx *ctx,
 133                                struct nft_flow_rule *flow,
 134                                const struct nft_expr *expr)
 135 {
 136         const struct nft_bitwise *priv = nft_expr_priv(expr);
 137         struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
 138 
 139         if (memcmp(&priv->xor, &zero, sizeof(priv->xor)) ||
 140             priv->sreg != priv->dreg || priv->len != reg->len)
 141                 return -EOPNOTSUPP;
 142 
 143         memcpy(&reg->mask, &priv->mask, sizeof(priv->mask));
 144 
 145         return 0;
 146 }
 147 
 148 static const struct nft_expr_ops nft_bitwise_ops = {
 149         .type           = &nft_bitwise_type,
 150         .size           = NFT_EXPR_SIZE(sizeof(struct nft_bitwise)),
 151         .eval           = nft_bitwise_eval,
 152         .init           = nft_bitwise_init,
 153         .dump           = nft_bitwise_dump,
 154         .offload        = nft_bitwise_offload,
 155 };
 156 
 157 struct nft_expr_type nft_bitwise_type __read_mostly = {
 158         .name           = "bitwise",
 159         .ops            = &nft_bitwise_ops,
 160         .policy         = nft_bitwise_policy,
 161         .maxattr        = NFTA_BITWISE_MAX,
 162         .owner          = THIS_MODULE,
 163 };

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