linux/net/netfilter/xt_u32.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *      xt_u32 - kernel module to match u32 packet content
   4 *
   5 *      Original author: Don Cohen <don@isis.cs3-inc.com>
   6 *      (C) CC Computer Consultants GmbH, 2007
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/moduleparam.h>
  11#include <linux/spinlock.h>
  12#include <linux/skbuff.h>
  13#include <linux/types.h>
  14#include <linux/netfilter/x_tables.h>
  15#include <linux/netfilter/xt_u32.h>
  16
  17static bool u32_match_it(const struct xt_u32 *data,
  18                         const struct sk_buff *skb)
  19{
  20        const struct xt_u32_test *ct;
  21        unsigned int testind;
  22        unsigned int nnums;
  23        unsigned int nvals;
  24        unsigned int i;
  25        __be32 n;
  26        u_int32_t pos;
  27        u_int32_t val;
  28        u_int32_t at;
  29
  30        /*
  31         * Small example: "0 >> 28 == 4 && 8 & 0xFF0000 >> 16 = 6, 17"
  32         * (=IPv4 and (TCP or UDP)). Outer loop runs over the "&&" operands.
  33         */
  34        for (testind = 0; testind < data->ntests; ++testind) {
  35                ct  = &data->tests[testind];
  36                at  = 0;
  37                pos = ct->location[0].number;
  38
  39                if (skb->len < 4 || pos > skb->len - 4)
  40                        return false;
  41
  42                if (skb_copy_bits(skb, pos, &n, sizeof(n)) < 0)
  43                        BUG();
  44                val   = ntohl(n);
  45                nnums = ct->nnums;
  46
  47                /* Inner loop runs over "&", "<<", ">>" and "@" operands */
  48                for (i = 1; i < nnums; ++i) {
  49                        u_int32_t number = ct->location[i].number;
  50                        switch (ct->location[i].nextop) {
  51                        case XT_U32_AND:
  52                                val &= number;
  53                                break;
  54                        case XT_U32_LEFTSH:
  55                                val <<= number;
  56                                break;
  57                        case XT_U32_RIGHTSH:
  58                                val >>= number;
  59                                break;
  60                        case XT_U32_AT:
  61                                if (at + val < at)
  62                                        return false;
  63                                at += val;
  64                                pos = number;
  65                                if (at + 4 < at || skb->len < at + 4 ||
  66                                    pos > skb->len - at - 4)
  67                                        return false;
  68
  69                                if (skb_copy_bits(skb, at + pos, &n,
  70                                                    sizeof(n)) < 0)
  71                                        BUG();
  72                                val = ntohl(n);
  73                                break;
  74                        }
  75                }
  76
  77                /* Run over the "," and ":" operands */
  78                nvals = ct->nvalues;
  79                for (i = 0; i < nvals; ++i)
  80                        if (ct->value[i].min <= val && val <= ct->value[i].max)
  81                                break;
  82
  83                if (i >= ct->nvalues)
  84                        return false;
  85        }
  86
  87        return true;
  88}
  89
  90static bool u32_mt(const struct sk_buff *skb, struct xt_action_param *par)
  91{
  92        const struct xt_u32 *data = par->matchinfo;
  93        bool ret;
  94
  95        ret = u32_match_it(data, skb);
  96        return ret ^ data->invert;
  97}
  98
  99static struct xt_match xt_u32_mt_reg __read_mostly = {
 100        .name       = "u32",
 101        .revision   = 0,
 102        .family     = NFPROTO_UNSPEC,
 103        .match      = u32_mt,
 104        .matchsize  = sizeof(struct xt_u32),
 105        .me         = THIS_MODULE,
 106};
 107
 108static int __init u32_mt_init(void)
 109{
 110        return xt_register_match(&xt_u32_mt_reg);
 111}
 112
 113static void __exit u32_mt_exit(void)
 114{
 115        xt_unregister_match(&xt_u32_mt_reg);
 116}
 117
 118module_init(u32_mt_init);
 119module_exit(u32_mt_exit);
 120MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
 121MODULE_DESCRIPTION("Xtables: arbitrary byte matching");
 122MODULE_LICENSE("GPL");
 123MODULE_ALIAS("ipt_u32");
 124MODULE_ALIAS("ip6t_u32");
 125