PageRenderTime 15ms CodeModel.GetById 1ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/net/netfilter/xt_u32.c

http://github.com/mirrors/linux
C | 124 lines | 95 code | 16 blank | 13 comment | 14 complexity | f630b1da79691c8d6659df0649636099 MD5 | raw file
  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");