linux/net/netfilter/nft_bitwise.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 * Development of this code funded by Astaro AG (http://www.astaro.com/)
   9 */
  10
  11#include <linux/kernel.h>
  12#include <linux/init.h>
  13#include <linux/module.h>
  14#include <linux/netlink.h>
  15#include <linux/netfilter.h>
  16#include <linux/netfilter/nf_tables.h>
  17#include <net/netfilter/nf_tables_core.h>
  18#include <net/netfilter/nf_tables.h>
  19
  20struct nft_bitwise {
  21        enum nft_registers      sreg:8;
  22        enum nft_registers      dreg:8;
  23        u8                      len;
  24        struct nft_data         mask;
  25        struct nft_data         xor;
  26};
  27
  28static void nft_bitwise_eval(const struct nft_expr *expr,
  29                             struct nft_data data[NFT_REG_MAX + 1],
  30                             const struct nft_pktinfo *pkt)
  31{
  32        const struct nft_bitwise *priv = nft_expr_priv(expr);
  33        const struct nft_data *src = &data[priv->sreg];
  34        struct nft_data *dst = &data[priv->dreg];
  35        unsigned int i;
  36
  37        for (i = 0; i < DIV_ROUND_UP(priv->len, 4); i++) {
  38                dst->data[i] = (src->data[i] & priv->mask.data[i]) ^
  39                               priv->xor.data[i];
  40        }
  41}
  42
  43static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = {
  44        [NFTA_BITWISE_SREG]     = { .type = NLA_U32 },
  45        [NFTA_BITWISE_DREG]     = { .type = NLA_U32 },
  46        [NFTA_BITWISE_LEN]      = { .type = NLA_U32 },
  47        [NFTA_BITWISE_MASK]     = { .type = NLA_NESTED },
  48        [NFTA_BITWISE_XOR]      = { .type = NLA_NESTED },
  49};
  50
  51static int nft_bitwise_init(const struct nft_ctx *ctx,
  52                            const struct nft_expr *expr,
  53                            const struct nlattr * const tb[])
  54{
  55        struct nft_bitwise *priv = nft_expr_priv(expr);
  56        struct nft_data_desc d1, d2;
  57        int err;
  58
  59        if (tb[NFTA_BITWISE_SREG] == NULL ||
  60            tb[NFTA_BITWISE_DREG] == NULL ||
  61            tb[NFTA_BITWISE_LEN] == NULL ||
  62            tb[NFTA_BITWISE_MASK] == NULL ||
  63            tb[NFTA_BITWISE_XOR] == NULL)
  64                return -EINVAL;
  65
  66        priv->sreg = ntohl(nla_get_be32(tb[NFTA_BITWISE_SREG]));
  67        err = nft_validate_input_register(priv->sreg);
  68        if (err < 0)
  69                return err;
  70
  71        priv->dreg = ntohl(nla_get_be32(tb[NFTA_BITWISE_DREG]));
  72        err = nft_validate_output_register(priv->dreg);
  73        if (err < 0)
  74                return err;
  75        err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE);
  76        if (err < 0)
  77                return err;
  78
  79        priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN]));
  80
  81        err = nft_data_init(NULL, &priv->mask, &d1, tb[NFTA_BITWISE_MASK]);
  82        if (err < 0)
  83                return err;
  84        if (d1.len != priv->len)
  85                return -EINVAL;
  86
  87        err = nft_data_init(NULL, &priv->xor, &d2, tb[NFTA_BITWISE_XOR]);
  88        if (err < 0)
  89                return err;
  90        if (d2.len != priv->len)
  91                return -EINVAL;
  92
  93        return 0;
  94}
  95
  96static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr)
  97{
  98        const struct nft_bitwise *priv = nft_expr_priv(expr);
  99
 100        if (nla_put_be32(skb, NFTA_BITWISE_SREG, htonl(priv->sreg)))
 101                goto nla_put_failure;
 102        if (nla_put_be32(skb, NFTA_BITWISE_DREG, htonl(priv->dreg)))
 103                goto nla_put_failure;
 104        if (nla_put_be32(skb, NFTA_BITWISE_LEN, htonl(priv->len)))
 105                goto nla_put_failure;
 106
 107        if (nft_data_dump(skb, NFTA_BITWISE_MASK, &priv->mask,
 108                          NFT_DATA_VALUE, priv->len) < 0)
 109                goto nla_put_failure;
 110
 111        if (nft_data_dump(skb, NFTA_BITWISE_XOR, &priv->xor,
 112                          NFT_DATA_VALUE, priv->len) < 0)
 113                goto nla_put_failure;
 114
 115        return 0;
 116
 117nla_put_failure:
 118        return -1;
 119}
 120
 121static struct nft_expr_type nft_bitwise_type;
 122static const struct nft_expr_ops nft_bitwise_ops = {
 123        .type           = &nft_bitwise_type,
 124        .size           = NFT_EXPR_SIZE(sizeof(struct nft_bitwise)),
 125        .eval           = nft_bitwise_eval,
 126        .init           = nft_bitwise_init,
 127        .dump           = nft_bitwise_dump,
 128};
 129
 130static struct nft_expr_type nft_bitwise_type __read_mostly = {
 131        .name           = "bitwise",
 132        .ops            = &nft_bitwise_ops,
 133        .policy         = nft_bitwise_policy,
 134        .maxattr        = NFTA_BITWISE_MAX,
 135        .owner          = THIS_MODULE,
 136};
 137
 138int __init nft_bitwise_module_init(void)
 139{
 140        return nft_register_expr(&nft_bitwise_type);
 141}
 142
 143void nft_bitwise_module_exit(void)
 144{
 145        nft_unregister_expr(&nft_bitwise_type);
 146}
 147