]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-pom-ng-u32.patch
- typo
[packages/kernel.git] / kernel-pom-ng-u32.patch
CommitLineData
7f651772 1diff -Nru linux-2.6.22/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.22-pom2patch/include/linux/netfilter_ipv4/ipt_u32.h
2--- linux-2.6.22/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
3+++ linux-2.6.22-pom2patch/include/linux/netfilter_ipv4/ipt_u32.h 2007-08-07 18:40:11.000000000 +0200
4@@ -0,0 +1,40 @@
5+#ifndef _IPT_U32_H
6+#define _IPT_U32_H
7+#include <linux/netfilter_ipv4/ip_tables.h>
8+
9+enum ipt_u32_ops
10+{
11+ IPT_U32_AND,
12+ IPT_U32_LEFTSH,
13+ IPT_U32_RIGHTSH,
14+ IPT_U32_AT
15+};
16+
17+struct ipt_u32_location_element
18+{
19+ u_int32_t number;
20+ u_int8_t nextop;
21+};
22+struct ipt_u32_value_element
23+{
24+ u_int32_t min;
25+ u_int32_t max;
26+};
27+/* *** any way to allow for an arbitrary number of elements?
28+ for now I settle for a limit of 10 of each */
29+#define U32MAXSIZE 10
30+struct ipt_u32_test
31+{
32+ u_int8_t nnums;
33+ struct ipt_u32_location_element location[U32MAXSIZE+1];
34+ u_int8_t nvalues;
35+ struct ipt_u32_value_element value[U32MAXSIZE+1];
36+};
37+
38+struct ipt_u32
39+{
40+ u_int8_t ntests;
41+ struct ipt_u32_test tests[U32MAXSIZE+1];
42+};
43+
44+#endif /*_IPT_U32_H*/
45diff -Nru linux-2.6.22/net/ipv4/netfilter/ipt_u32.c linux-2.6.22-pom2patch/net/ipv4/netfilter/ipt_u32.c
46--- linux-2.6.22/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
47+++ linux-2.6.22-pom2patch/net/ipv4/netfilter/ipt_u32.c 2007-08-07 18:40:11.000000000 +0200
48@@ -0,0 +1,237 @@
49+/* Kernel module to match u32 packet content. */
50+
51+/*
52+U32 tests whether quantities of up to 4 bytes extracted from a packet
53+have specified values. The specification of what to extract is general
54+enough to find data at given offsets from tcp headers or payloads.
55+
56+ --u32 tests
57+ The argument amounts to a program in a small language described below.
58+ tests := location = value | tests && location = value
59+ value := range | value , range
60+ range := number | number : number
61+ a single number, n, is interpreted the same as n:n
62+ n:m is interpreted as the range of numbers >=n and <=m
63+ location := number | location operator number
64+ operator := & | << | >> | @
65+
66+ The operators &, <<, >>, && mean the same as in c. The = is really a set
67+ membership operator and the value syntax describes a set. The @ operator
68+ is what allows moving to the next header and is described further below.
69+
70+ *** Until I can find out how to avoid it, there are some artificial limits
71+ on the size of the tests:
72+ - no more than 10 ='s (and 9 &&'s) in the u32 argument
73+ - no more than 10 ranges (and 9 commas) per value
74+ - no more than 10 numbers (and 9 operators) per location
75+
76+ To describe the meaning of location, imagine the following machine that
77+ interprets it. There are three registers:
78+ A is of type char*, initially the address of the IP header
79+ B and C are unsigned 32 bit integers, initially zero
80+
81+ The instructions are:
82+ number B = number;
83+ C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
84+ &number C = C&number
85+ <<number C = C<<number
86+ >>number C = C>>number
87+ @number A = A+C; then do the instruction number
88+ Any access of memory outside [skb->head,skb->end] causes the match to fail.
89+ Otherwise the result of the computation is the final value of C.
90+
91+ Whitespace is allowed but not required in the tests.
92+ However the characters that do occur there are likely to require
93+ shell quoting, so it's a good idea to enclose the arguments in quotes.
94+
95+Example:
96+ match IP packets with total length >= 256
97+ The IP header contains a total length field in bytes 2-3.
98+ --u32 "0&0xFFFF=0x100:0xFFFF"
99+ read bytes 0-3
100+ AND that with FFFF (giving bytes 2-3),
101+ and test whether that's in the range [0x100:0xFFFF]
102+
103+Example: (more realistic, hence more complicated)
104+ match icmp packets with icmp type 0
105+ First test that it's an icmp packet, true iff byte 9 (protocol) = 1
106+ --u32 "6&0xFF=1 && ...
107+ read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
108+ Next test that it's not a fragment.
109+ (If so it might be part of such a packet but we can't always tell.)
110+ n.b. This test is generally needed if you want to match anything
111+ beyond the IP header.
112+ The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
113+ packet (not a fragment). Alternatively, you can allow first fragments
114+ by only testing the last 5 bits of byte 6.
115+ ... 4&0x3FFF=0 && ...
116+ Last test: the first byte past the IP header (the type) is 0
117+ This is where we have to use the @syntax. The length of the IP header
118+ (IHL) in 32 bit words is stored in the right half of byte 0 of the
119+ IP header itself.
120+ ... 0>>22&0x3C@0>>24=0"
121+ The first 0 means read bytes 0-3,
122+ >>22 means shift that 22 bits to the right. Shifting 24 bits would give
123+ the first byte, so only 22 bits is four times that plus a few more bits.
124+ &3C then eliminates the two extra bits on the right and the first four
125+ bits of the first byte.
126+ For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
127+ In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
128+ >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
129+ @ means to use this number as a new offset into the packet, and read
130+ four bytes starting from there. This is the first 4 bytes of the icmp
131+ payload, of which byte 0 is the icmp type. Therefore we simply shift
132+ the value 24 to the right to throw out all but the first byte and compare
133+ the result with 0.
134+
135+Example:
136+ tcp payload bytes 8-12 is any of 1, 2, 5 or 8
137+ First we test that the packet is a tcp packet (similar to icmp).
138+ --u32 "6&0xFF=6 && ...
139+ Next, test that it's not a fragment (same as above).
140+ ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
141+ 0>>22&3C as above computes the number of bytes in the IP header.
142+ @ makes this the new offset into the packet, which is the start of the
143+ tcp header. The length of the tcp header (again in 32 bit words) is
144+ the left half of byte 12 of the tcp header. The 12>>26&3C
145+ computes this length in bytes (similar to the IP header before).
146+ @ makes this the new offset, which is the start of the tcp payload.
147+ Finally 8 reads bytes 8-12 of the payload and = checks whether the
148+ result is any of 1, 2, 5 or 8
149+*/
150+
151+#include <linux/module.h>
152+#include <linux/skbuff.h>
153+
154+#include <linux/netfilter_ipv4/ipt_u32.h>
155+#include <linux/netfilter_ipv4/ip_tables.h>
156+
157+/* #include <asm-i386/timex.h> for timing */
158+
159+MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
160+MODULE_DESCRIPTION("IP tables u32 matching module");
161+MODULE_LICENSE("GPL");
162+
163+/* This is slow, but it's simple. --RR */
164+static char u32_buffer[65536];
165+static DEFINE_SPINLOCK(u32_lock);
166+
167+static int
168+match(const struct sk_buff *skb,
169+ const struct net_device *in,
170+ const struct net_device *out,
171+ const struct xt_match *match,
172+ const void *matchinfo,
173+ int offset,
174+ unsigned int protoff,
175+ int *hotdrop)
176+{
177+ const struct ipt_u32 *data = matchinfo;
178+ int testind, i;
179+ unsigned char* base;
180+ unsigned char* head;
181+ int nnums, nvals;
182+ u_int32_t pos, val;
183+
184+ u_int32_t AttPos;
185+
186+ spin_lock_bh(&u32_lock);
187+
188+ head = skb_header_pointer(skb, 0, skb->len, u32_buffer);
189+ BUG_ON(head == NULL);
190+
191+ base = head;
192+ /* unsigned long long cycles1, cycles2, cycles3, cycles4;
193+ cycles1 = get_cycles(); */
194+ for (testind=0; testind < data->ntests; testind++) {
195+ AttPos = 0;
196+ pos = data->tests[testind].location[0].number;
197+ if (AttPos + pos + 3 > skb->len || AttPos + pos < 0){
198+ spin_unlock_bh(&u32_lock);
199+ return 0;
200+ }
201+ val = (base[pos]<<24) + (base[pos+1]<<16) +
202+ (base[pos+2]<<8) + base[pos+3];
203+ nnums = data->tests[testind].nnums;
204+ for (i=1; i < nnums; i++) {
205+ u_int32_t number = data->tests[testind].location[i].number;
206+ switch (data->tests[testind].location[i].nextop) {
207+ case IPT_U32_AND:
208+ val = val & number;
209+ break;
210+ case IPT_U32_LEFTSH:
211+ val = val << number;
212+ break;
213+ case IPT_U32_RIGHTSH:
214+ val = val >> number;
215+ break;
216+ case IPT_U32_AT:
217+ AttPos += val;
218+ pos = number;
219+ if (AttPos + pos + 3 > skb->len || AttPos + pos < 0) {
220+ spin_unlock_bh(&u32_lock);
221+ return 0;
222+ }
223+
224+ val = (base[AttPos + pos]<<24)
225+ +(base[AttPos + pos + 1]<<16)
226+ +(base[AttPos + pos + 2]<<8)
227+ + base[AttPos + pos + 3];
228+ break;
229+ }
230+ }
231+ nvals = data->tests[testind].nvalues;
232+ for (i=0; i < nvals; i++) {
233+ if ((data->tests[testind].value[i].min <= val) &&
234+ (val <= data->tests[testind].value[i].max)) {
235+ break;
236+ }
237+ }
238+ if (i >= data->tests[testind].nvalues) {
239+ /* cycles2 = get_cycles();
240+ printk("failed %d in %d cycles\n", testind,
241+ cycles2-cycles1); */
242+ spin_unlock_bh(&u32_lock);
243+ return 0;
244+ }
245+ }
246+ /* cycles2 = get_cycles();
247+ printk("succeeded in %d cycles\n", cycles2-cycles1); */
248+ spin_unlock_bh(&u32_lock);
249+ return 1;
250+}
251+
252+static int
253+checkentry(const char *tablename,
254+ const void *ip,
255+ const struct xt_match *match,
256+ void *matchinfo,
257+ /* unsigned int matchsize, */
258+ unsigned int hook_mask)
259+{
260+ if (sizeof(struct ipt_u32) != IPT_ALIGN(sizeof(struct ipt_u32)))
261+ return 0;
262+ return 1;
263+}
264+
265+static struct xt_match u32_match = {
266+ .name = "u32",
267+ .family = AF_INET,
268+ .match = &match,
269+ .matchsize = sizeof(struct ipt_u32),
270+ .checkentry = &checkentry,
271+ .me = THIS_MODULE
272+};
273+
274+static int __init init(void)
275+{
276+ return xt_register_match(&u32_match);
277+}
278+
279+static void __exit fini(void)
280+{
281+ xt_unregister_match(&u32_match);
282+}
283+
284+module_init(init);
285+module_exit(fini);
286diff -Nru linux-2.6.22/net/ipv4/netfilter/Kconfig linux-2.6.22-pom2patch/net/ipv4/netfilter/Kconfig
287--- linux-2.6.22/net/ipv4/netfilter/Kconfig 2007-07-09 01:32:17.000000000 +0200
288+++ linux-2.6.22-pom2patch/net/ipv4/netfilter/Kconfig 2007-08-07 18:40:11.000000000 +0200
289@@ -402,5 +402,18 @@
290 Allows altering the ARP packet payload: source and destination
291 hardware and network addresses.
292
293+config IP_NF_MATCH_U32
294+ tristate 'U32 match support'
295+ depends on IP_NF_IPTABLES
296+ help
297+ U32 allows you to extract quantities of up to 4 bytes from a packet,
298+ AND them with specified masks, shift them by specified amounts and
299+ test whether the results are in any of a set of specified ranges.
300+ The specification of what to extract is general enough to skip over
301+ headers with lengths stored in the packet, as in IP or TCP header
302+ lengths.
303+
304+ Details and examples are in the kernel module source.
305+
306 endmenu
307
308diff -Nru linux-2.6.22/net/ipv4/netfilter/Makefile linux-2.6.22-pom2patch/net/ipv4/netfilter/Makefile
309--- linux-2.6.22/net/ipv4/netfilter/Makefile 2007-07-09 01:32:17.000000000 +0200
310+++ linux-2.6.22-pom2patch/net/ipv4/netfilter/Makefile 2007-08-07 18:40:11.000000000 +0200
311@@ -45,6 +45,7 @@
312 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
313 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
314 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
315+obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
316 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
317 obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
318 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
This page took 0.062036 seconds and 4 git commands to generate.