Skip to content

Commit 1b50b8a

Browse files
Jan EngelhardtDavid S. Miller
authored andcommitted
[NETFILTER]: Add u32 match
Along comes... xt_u32, a revamped ipt_u32 from POM-NG, Plus: * 2007-06-02: added ipv6 support * 2007-06-05: uses kmalloc for the big buffer * 2007-06-05: added inversion * 2007-06-20: use skb_copy_bits() and get rid of the big buffer and lock (suggested by Pablo Neira Ayuso) Signed-off-by: Jan Engelhardt <[email protected]> Signed-off-by: Patrick McHardy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f4a607b commit 1b50b8a

File tree

4 files changed

+189
-0
lines changed

4 files changed

+189
-0
lines changed

include/linux/netfilter/xt_u32.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#ifndef _XT_U32_H
2+
#define _XT_U32_H 1
3+
4+
enum xt_u32_ops {
5+
XT_U32_AND,
6+
XT_U32_LEFTSH,
7+
XT_U32_RIGHTSH,
8+
XT_U32_AT,
9+
};
10+
11+
struct xt_u32_location_element {
12+
u_int32_t number;
13+
u_int8_t nextop;
14+
};
15+
16+
struct xt_u32_value_element {
17+
u_int32_t min;
18+
u_int32_t max;
19+
};
20+
21+
/*
22+
* Any way to allow for an arbitrary number of elements?
23+
* For now, I settle with a limit of 10 each.
24+
*/
25+
#define XT_U32_MAXSIZE 10
26+
27+
struct xt_u32_test {
28+
struct xt_u32_location_element location[XT_U32_MAXSIZE+1];
29+
struct xt_u32_value_element value[XT_U32_MAXSIZE+1];
30+
u_int8_t nnums;
31+
u_int8_t nvalues;
32+
};
33+
34+
struct xt_u32 {
35+
struct xt_u32_test tests[XT_U32_MAXSIZE+1];
36+
u_int8_t ntests;
37+
u_int8_t invert;
38+
};
39+
40+
#endif /* _XT_U32_H */

net/netfilter/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,19 @@ config NETFILTER_XT_MATCH_TCPMSS
635635

636636
To compile it as a module, choose M here. If unsure, say N.
637637

638+
config NETFILTER_XT_MATCH_U32
639+
tristate '"u32" match support'
640+
depends on NETFILTER_XTABLES
641+
---help---
642+
u32 allows you to extract quantities of up to 4 bytes from a packet,
643+
AND them with specified masks, shift them by specified amounts and
644+
test whether the results are in any of a set of specified ranges.
645+
The specification of what to extract is general enough to skip over
646+
headers with lengths stored in the packet, as in IP or TCP header
647+
lengths.
648+
649+
Details and examples are in the kernel module source.
650+
638651
config NETFILTER_XT_MATCH_HASHLIMIT
639652
tristate '"hashlimit" match support'
640653
depends on NETFILTER_XTABLES && (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)

net/netfilter/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,5 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
7272
obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
7373
obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
7474
obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
75+
obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o
7576
obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o

net/netfilter/xt_u32.c

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* xt_u32 - kernel module to match u32 packet content
3+
*
4+
* Original author: Don Cohen <[email protected]>
5+
* © Jan Engelhardt <[email protected]>, 2007
6+
*/
7+
8+
#include <linux/module.h>
9+
#include <linux/moduleparam.h>
10+
#include <linux/spinlock.h>
11+
#include <linux/skbuff.h>
12+
#include <linux/types.h>
13+
#include <linux/netfilter/x_tables.h>
14+
#include <linux/netfilter/xt_u32.h>
15+
16+
static bool u32_match_it(const struct xt_u32 *data,
17+
const struct sk_buff *skb)
18+
{
19+
const struct xt_u32_test *ct;
20+
unsigned int testind;
21+
unsigned int nnums;
22+
unsigned int nvals;
23+
unsigned int i;
24+
u_int32_t pos;
25+
u_int32_t val;
26+
u_int32_t at;
27+
int ret;
28+
29+
/*
30+
* Small example: "0 >> 28 == 4 && 8 & 0xFF0000 >> 16 = 6, 17"
31+
* (=IPv4 and (TCP or UDP)). Outer loop runs over the "&&" operands.
32+
*/
33+
for (testind = 0; testind < data->ntests; ++testind) {
34+
ct = &data->tests[testind];
35+
at = 0;
36+
pos = ct->location[0].number;
37+
38+
if (skb->len < 4 || pos > skb->len - 4);
39+
return false;
40+
41+
ret = skb_copy_bits(skb, pos, &val, sizeof(val));
42+
BUG_ON(ret < 0);
43+
val = ntohl(val);
44+
nnums = ct->nnums;
45+
46+
/* Inner loop runs over "&", "<<", ">>" and "@" operands */
47+
for (i = 1; i < nnums; ++i) {
48+
u_int32_t number = ct->location[i].number;
49+
switch (ct->location[i].nextop) {
50+
case XT_U32_AND:
51+
val &= number;
52+
break;
53+
case XT_U32_LEFTSH:
54+
val <<= number;
55+
break;
56+
case XT_U32_RIGHTSH:
57+
val >>= number;
58+
break;
59+
case XT_U32_AT:
60+
if (at + val < at)
61+
return false;
62+
at += val;
63+
pos = number;
64+
if (at + 4 < at || skb->len < at + 4 ||
65+
pos > skb->len - at - 4)
66+
return false;
67+
68+
ret = skb_copy_bits(skb, at + pos, &val,
69+
sizeof(val));
70+
BUG_ON(ret < 0);
71+
val = ntohl(val);
72+
break;
73+
}
74+
}
75+
76+
/* Run over the "," and ":" operands */
77+
nvals = ct->nvalues;
78+
for (i = 0; i < nvals; ++i)
79+
if (ct->value[i].min <= val && val <= ct->value[i].max)
80+
break;
81+
82+
if (i >= ct->nvalues)
83+
return false;
84+
}
85+
86+
return true;
87+
}
88+
89+
static bool u32_match(const struct sk_buff *skb,
90+
const struct net_device *in,
91+
const struct net_device *out,
92+
const struct xt_match *match, const void *matchinfo,
93+
int offset, unsigned int protoff, bool *hotdrop)
94+
{
95+
const struct xt_u32 *data = matchinfo;
96+
bool ret;
97+
98+
ret = u32_match_it(data, skb);
99+
return ret ^ data->invert;
100+
}
101+
102+
static struct xt_match u32_reg[] = {
103+
{
104+
.name = "u32",
105+
.family = AF_INET,
106+
.match = u32_match,
107+
.matchsize = sizeof(struct xt_u32),
108+
.me = THIS_MODULE,
109+
},
110+
{
111+
.name = "u32",
112+
.family = AF_INET6,
113+
.match = u32_match,
114+
.matchsize = sizeof(struct xt_u32),
115+
.me = THIS_MODULE,
116+
},
117+
};
118+
119+
static int __init xt_u32_init(void)
120+
{
121+
return xt_register_matches(u32_reg, ARRAY_SIZE(u32_reg));
122+
}
123+
124+
static void __exit xt_u32_exit(void)
125+
{
126+
xt_unregister_matches(u32_reg, ARRAY_SIZE(u32_reg));
127+
}
128+
129+
module_init(xt_u32_init);
130+
module_exit(xt_u32_exit);
131+
MODULE_AUTHOR("Jan Engelhardt <[email protected]>");
132+
MODULE_DESCRIPTION("netfilter u32 match module");
133+
MODULE_LICENSE("GPL");
134+
MODULE_ALIAS("ipt_u32");
135+
MODULE_ALIAS("ip6t_u32");

0 commit comments

Comments
 (0)