2 * ipt_u32 - kernel module to match u32 packet content
4 * Original author: Don Cohen <don@isis.cs3-inc.com>
5 * © Jan Engelhardt <jengelh@gmx.de>, 2007
9 U32 tests whether quantities of up to 4 bytes extracted from a packet
10 have specified values. The specification of what to extract is general
11 enough to find data at given offsets from tcp headers or payloads.
14 The argument amounts to a program in a small language described below.
15 tests := location = value | tests && location = value
16 value := range | value , range
17 range := number | number : number
18 a single number, n, is interpreted the same as n:n
19 n:m is interpreted as the range of numbers >=n and <=m
20 location := number | location operator number
21 operator := & | << | >> | @
23 The operators &, <<, >>, && mean the same as in c. The = is really a set
24 membership operator and the value syntax describes a set. The @ operator
25 is what allows moving to the next header and is described further below.
27 *** Until I can find out how to avoid it, there are some artificial limits
28 on the size of the tests:
29 - no more than 10 ='s (and 9 &&'s) in the u32 argument
30 - no more than 10 ranges (and 9 commas) per value
31 - no more than 10 numbers (and 9 operators) per location
33 To describe the meaning of location, imagine the following machine that
34 interprets it. There are three registers:
35 A is of type char*, initially the address of the IP header
36 B and C are unsigned 32 bit integers, initially zero
40 C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
42 <<number C = C<<number
43 >>number C = C>>number
44 @number A = A+C; then do the instruction number
45 Any access of memory outside [skb->head,skb->end] causes the match to fail.
46 Otherwise the result of the computation is the final value of C.
48 Whitespace is allowed but not required in the tests.
49 However the characters that do occur there are likely to require
50 shell quoting, so it's a good idea to enclose the arguments in quotes.
53 match IP packets with total length >= 256
54 The IP header contains a total length field in bytes 2-3.
55 --u32 "0&0xFFFF=0x100:0xFFFF"
57 AND that with FFFF (giving bytes 2-3),
58 and test whether that's in the range [0x100:0xFFFF]
60 Example: (more realistic, hence more complicated)
61 match icmp packets with icmp type 0
62 First test that it's an icmp packet, true iff byte 9 (protocol) = 1
63 --u32 "6&0xFF=1 && ...
64 read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
65 Next test that it's not a fragment.
66 (If so it might be part of such a packet but we can't always tell.)
67 n.b. This test is generally needed if you want to match anything
69 The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
70 packet (not a fragment). Alternatively, you can allow first fragments
71 by only testing the last 5 bits of byte 6.
73 Last test: the first byte past the IP header (the type) is 0
74 This is where we have to use the @syntax. The length of the IP header
75 (IHL) in 32 bit words is stored in the right half of byte 0 of the
77 ... 0>>22&0x3C@0>>24=0"
78 The first 0 means read bytes 0-3,
79 >>22 means shift that 22 bits to the right. Shifting 24 bits would give
80 the first byte, so only 22 bits is four times that plus a few more bits.
81 &3C then eliminates the two extra bits on the right and the first four
82 bits of the first byte.
83 For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
84 In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
85 >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
86 @ means to use this number as a new offset into the packet, and read
87 four bytes starting from there. This is the first 4 bytes of the icmp
88 payload, of which byte 0 is the icmp type. Therefore we simply shift
89 the value 24 to the right to throw out all but the first byte and compare
93 tcp payload bytes 8-12 is any of 1, 2, 5 or 8
94 First we test that the packet is a tcp packet (similar to icmp).
95 --u32 "6&0xFF=6 && ...
96 Next, test that it's not a fragment (same as above).
97 ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
98 0>>22&3C as above computes the number of bytes in the IP header.
99 @ makes this the new offset into the packet, which is the start of the
100 tcp header. The length of the tcp header (again in 32 bit words) is
101 the left half of byte 12 of the tcp header. The 12>>26&3C
102 computes this length in bytes (similar to the IP header before).
103 @ makes this the new offset, which is the start of the tcp payload.
104 Finally 8 reads bytes 8-12 of the payload and = checks whether the
105 result is any of 1, 2, 5 or 8
108 #include <linux/module.h>
109 #include <linux/moduleparam.h>
110 #include <linux/spinlock.h>
111 #include <linux/skbuff.h>
112 #include <linux/types.h>
114 #include <linux/netfilter_ipv4/ipt_u32.h>
115 #include <linux/netfilter_ipv4/ip_tables.h>
117 MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
118 MODULE_DESCRIPTION("netfilter u32 match module");
119 MODULE_LICENSE("GPL");
120 MODULE_ALIAS("ip6t_u32");
122 static int u32_match_it(const struct ipt_u32
*data
,
123 const struct sk_buff
*skb
)
125 const struct ipt_u32_test
*ct
;
126 unsigned int testind
;
136 * Small example: "0 >> 28 == 4 && 8 & 0xFF0000 >> 16 = 6, 17"
137 * (=IPv4 and (TCP or UDP)). Outer loop runs over the "&&" operands.
139 for (testind
= 0; testind
< data
->ntests
; ++testind
) {
140 ct
= &data
->tests
[testind
];
142 pos
= ct
->location
[0].number
;
144 if (skb
->len
< 4 || pos
> skb
->len
- 4)
147 ret
= skb_copy_bits(skb
, pos
, &val
, sizeof(val
));
152 /* Inner loop runs over "&", "<<", ">>" and "@" operands */
153 for (i
= 1; i
< nnums
; ++i
) {
154 u_int32_t number
= ct
->location
[i
].number
;
155 switch (ct
->location
[i
].nextop
) {
162 case IPT_U32_RIGHTSH
:
170 if (at
+ 4 < at
|| skb
->len
< at
+ 4 ||
171 pos
> skb
->len
- at
- 4)
174 ret
= skb_copy_bits(skb
, at
+ pos
, &val
,
182 /* Run over the "," and ":" operands */
184 for (i
= 0; i
< nvals
; ++i
)
185 if (ct
->value
[i
].min
<= val
&& val
<= ct
->value
[i
].max
)
188 if (i
>= ct
->nvalues
)
196 match(const struct sk_buff
*skb
,
197 const struct net_device
*in
,
198 const struct net_device
*out
,
199 const struct xt_match
*match
,
200 const void *matchinfo
,
202 unsigned int protoff
,
205 const struct ipt_u32
*data
= matchinfo
;
208 ret
= u32_match_it(data
, skb
);
209 return ret
^ data
->invert
;
213 checkentry(const char *tablename
,
215 const struct xt_match
*match
,
217 unsigned int hook_mask
)
222 static struct xt_match u32_reg
[] = {
227 .matchsize
= sizeof(struct ipt_u32
),
228 .checkentry
= &checkentry
,
235 .matchsize
= sizeof(struct ipt_u32
),
236 .checkentry
= &checkentry
,
241 static int __init
init(void)
243 return xt_register_matches(u32_reg
, ARRAY_SIZE(u32_reg
));
246 static void __exit
fini(void)
248 xt_unregister_matches(u32_reg
, ARRAY_SIZE(u32_reg
));