Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
423 | giacomo | 1 | /* |
2 | * 25-Jul-1998 Major changes to allow for ip chain table |
||
3 | * |
||
4 | * 3-Jan-2000 Named tables to allow packet selection for different uses. |
||
5 | */ |
||
6 | |||
7 | /* |
||
8 | * Format of an IP6 firewall descriptor |
||
9 | * |
||
10 | * src, dst, src_mask, dst_mask are always stored in network byte order. |
||
11 | * flags are stored in host byte order (of course). |
||
12 | * Port numbers are stored in HOST byte order. |
||
13 | */ |
||
14 | |||
15 | #ifndef _IP6_TABLES_H |
||
16 | #define _IP6_TABLES_H |
||
17 | |||
18 | #ifdef __KERNEL__ |
||
19 | #include <linux/if.h> |
||
20 | #include <linux/types.h> |
||
21 | #include <linux/in6.h> |
||
22 | #include <linux/ipv6.h> |
||
23 | #include <linux/skbuff.h> |
||
24 | #endif |
||
25 | #include <linux/netfilter_ipv6.h> |
||
26 | |||
27 | #define IP6T_FUNCTION_MAXNAMELEN 30 |
||
28 | #define IP6T_TABLE_MAXNAMELEN 32 |
||
29 | |||
30 | /* Yes, Virginia, you have to zero the padding. */ |
||
31 | struct ip6t_ip6 { |
||
32 | /* Source and destination IP6 addr */ |
||
33 | struct in6_addr src, dst; |
||
34 | /* Mask for src and dest IP6 addr */ |
||
35 | struct in6_addr smsk, dmsk; |
||
36 | char iniface[IFNAMSIZ], outiface[IFNAMSIZ]; |
||
37 | unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ]; |
||
38 | |||
39 | /* ARGH, HopByHop uses 0, so can't do 0 = ANY, |
||
40 | instead IP6T_F_NOPROTO must be set */ |
||
41 | u_int16_t proto; |
||
42 | /* TOS to match iff flags & IP6T_F_TOS */ |
||
43 | u_int8_t tos; |
||
44 | |||
45 | /* Flags word */ |
||
46 | u_int8_t flags; |
||
47 | /* Inverse flags */ |
||
48 | u_int8_t invflags; |
||
49 | }; |
||
50 | |||
51 | /* FIXME: If alignment in kernel different from userspace? --RR */ |
||
52 | struct ip6t_entry_match |
||
53 | { |
||
54 | union { |
||
55 | struct { |
||
56 | u_int16_t match_size; |
||
57 | |||
58 | /* Used by userspace */ |
||
59 | char name[IP6T_FUNCTION_MAXNAMELEN]; |
||
60 | } user; |
||
61 | struct { |
||
62 | u_int16_t match_size; |
||
63 | |||
64 | /* Used inside the kernel */ |
||
65 | struct ip6t_match *match; |
||
66 | } kernel; |
||
67 | |||
68 | /* Total length */ |
||
69 | u_int16_t match_size; |
||
70 | } u; |
||
71 | |||
72 | unsigned char data[0]; |
||
73 | }; |
||
74 | |||
75 | struct ip6t_entry_target |
||
76 | { |
||
77 | union { |
||
78 | struct { |
||
79 | u_int16_t target_size; |
||
80 | |||
81 | /* Used by userspace */ |
||
82 | char name[IP6T_FUNCTION_MAXNAMELEN]; |
||
83 | } user; |
||
84 | struct { |
||
85 | u_int16_t target_size; |
||
86 | |||
87 | /* Used inside the kernel */ |
||
88 | struct ip6t_target *target; |
||
89 | } kernel; |
||
90 | |||
91 | /* Total length */ |
||
92 | u_int16_t target_size; |
||
93 | } u; |
||
94 | |||
95 | unsigned char data[0]; |
||
96 | }; |
||
97 | |||
98 | struct ip6t_standard_target |
||
99 | { |
||
100 | struct ip6t_entry_target target; |
||
101 | int verdict; |
||
102 | }; |
||
103 | |||
104 | struct ip6t_counters |
||
105 | { |
||
106 | u_int64_t pcnt, bcnt; /* Packet and byte counters */ |
||
107 | }; |
||
108 | |||
109 | /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */ |
||
110 | #define IP6T_F_PROTO 0x01 /* Set if rule cares about upper |
||
111 | protocols */ |
||
112 | #define IP6T_F_TOS 0x02 /* Match the TOS. */ |
||
113 | #define IP6T_F_MASK 0x03 /* All possible flag bits mask. */ |
||
114 | |||
115 | /* Values for "inv" field in struct ip6t_ip6. */ |
||
116 | #define IP6T_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ |
||
117 | #define IP6T_INV_VIA_OUT 0x02 /* Invert the sense of OUT IFACE */ |
||
118 | #define IP6T_INV_TOS 0x04 /* Invert the sense of TOS. */ |
||
119 | #define IP6T_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ |
||
120 | #define IP6T_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ |
||
121 | #define IP6T_INV_FRAG 0x20 /* Invert the sense of FRAG. */ |
||
122 | #define IP6T_INV_PROTO 0x40 /* Invert the sense of PROTO. */ |
||
123 | #define IP6T_INV_MASK 0x7F /* All possible flag bits mask. */ |
||
124 | |||
125 | /* This structure defines each of the firewall rules. Consists of 3 |
||
126 | parts which are 1) general IP header stuff 2) match specific |
||
127 | stuff 3) the target to perform if the rule matches */ |
||
128 | struct ip6t_entry |
||
129 | { |
||
130 | struct ip6t_ip6 ipv6; |
||
131 | |||
132 | /* Mark with fields that we care about. */ |
||
133 | unsigned int nfcache; |
||
134 | |||
135 | /* Size of ipt_entry + matches */ |
||
136 | u_int16_t target_offset; |
||
137 | /* Size of ipt_entry + matches + target */ |
||
138 | u_int16_t next_offset; |
||
139 | |||
140 | /* Back pointer */ |
||
141 | unsigned int comefrom; |
||
142 | |||
143 | /* Packet and byte counters. */ |
||
144 | struct ip6t_counters counters; |
||
145 | |||
146 | /* The matches (if any), then the target. */ |
||
147 | unsigned char elems[0]; |
||
148 | }; |
||
149 | |||
150 | /* |
||
151 | * New IP firewall options for [gs]etsockopt at the RAW IP level. |
||
152 | * Unlike BSD Linux inherits IP options so you don't have to use |
||
153 | * a raw socket for this. Instead we check rights in the calls. */ |
||
154 | #define IP6T_BASE_CTL 64 /* base for firewall socket options */ |
||
155 | |||
156 | #define IP6T_SO_SET_REPLACE (IP6T_BASE_CTL) |
||
157 | #define IP6T_SO_SET_ADD_COUNTERS (IP6T_BASE_CTL + 1) |
||
158 | #define IP6T_SO_SET_MAX IP6T_SO_SET_ADD_COUNTERS |
||
159 | |||
160 | #define IP6T_SO_GET_INFO (IP6T_BASE_CTL) |
||
161 | #define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1) |
||
162 | #define IP6T_SO_GET_MAX IP6T_SO_GET_ENTRIES |
||
163 | |||
164 | /* CONTINUE verdict for targets */ |
||
165 | #define IP6T_CONTINUE 0xFFFFFFFF |
||
166 | |||
167 | /* For standard target */ |
||
168 | #define IP6T_RETURN (-NF_MAX_VERDICT - 1) |
||
169 | |||
170 | /* TCP matching stuff */ |
||
171 | struct ip6t_tcp |
||
172 | { |
||
173 | u_int16_t spts[2]; /* Source port range. */ |
||
174 | u_int16_t dpts[2]; /* Destination port range. */ |
||
175 | u_int8_t option; /* TCP Option iff non-zero*/ |
||
176 | u_int8_t flg_mask; /* TCP flags mask byte */ |
||
177 | u_int8_t flg_cmp; /* TCP flags compare byte */ |
||
178 | u_int8_t invflags; /* Inverse flags */ |
||
179 | }; |
||
180 | |||
181 | /* Values for "inv" field in struct ipt_tcp. */ |
||
182 | #define IP6T_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ |
||
183 | #define IP6T_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ |
||
184 | #define IP6T_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ |
||
185 | #define IP6T_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ |
||
186 | #define IP6T_TCP_INV_MASK 0x0F /* All possible flags. */ |
||
187 | |||
188 | /* UDP matching stuff */ |
||
189 | struct ip6t_udp |
||
190 | { |
||
191 | u_int16_t spts[2]; /* Source port range. */ |
||
192 | u_int16_t dpts[2]; /* Destination port range. */ |
||
193 | u_int8_t invflags; /* Inverse flags */ |
||
194 | }; |
||
195 | |||
196 | /* Values for "invflags" field in struct ipt_udp. */ |
||
197 | #define IP6T_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ |
||
198 | #define IP6T_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ |
||
199 | #define IP6T_UDP_INV_MASK 0x03 /* All possible flags. */ |
||
200 | |||
201 | /* ICMP matching stuff */ |
||
202 | struct ip6t_icmp |
||
203 | { |
||
204 | u_int8_t type; /* type to match */ |
||
205 | u_int8_t code[2]; /* range of code */ |
||
206 | u_int8_t invflags; /* Inverse flags */ |
||
207 | }; |
||
208 | |||
209 | /* Values for "inv" field for struct ipt_icmp. */ |
||
210 | #define IP6T_ICMP_INV 0x01 /* Invert the sense of type/code test */ |
||
211 | |||
212 | /* The argument to IP6T_SO_GET_INFO */ |
||
213 | struct ip6t_getinfo |
||
214 | { |
||
215 | /* Which table: caller fills this in. */ |
||
216 | char name[IP6T_TABLE_MAXNAMELEN]; |
||
217 | |||
218 | /* Kernel fills these in. */ |
||
219 | /* Which hook entry points are valid: bitmask */ |
||
220 | unsigned int valid_hooks; |
||
221 | |||
222 | /* Hook entry points: one per netfilter hook. */ |
||
223 | unsigned int hook_entry[NF_IP6_NUMHOOKS]; |
||
224 | |||
225 | /* Underflow points. */ |
||
226 | unsigned int underflow[NF_IP6_NUMHOOKS]; |
||
227 | |||
228 | /* Number of entries */ |
||
229 | unsigned int num_entries; |
||
230 | |||
231 | /* Size of entries. */ |
||
232 | unsigned int size; |
||
233 | }; |
||
234 | |||
235 | /* The argument to IP6T_SO_SET_REPLACE. */ |
||
236 | struct ip6t_replace |
||
237 | { |
||
238 | /* Which table. */ |
||
239 | char name[IP6T_TABLE_MAXNAMELEN]; |
||
240 | |||
241 | /* Which hook entry points are valid: bitmask. You can't |
||
242 | change this. */ |
||
243 | unsigned int valid_hooks; |
||
244 | |||
245 | /* Number of entries */ |
||
246 | unsigned int num_entries; |
||
247 | |||
248 | /* Total size of new entries */ |
||
249 | unsigned int size; |
||
250 | |||
251 | /* Hook entry points. */ |
||
252 | unsigned int hook_entry[NF_IP6_NUMHOOKS]; |
||
253 | |||
254 | /* Underflow points. */ |
||
255 | unsigned int underflow[NF_IP6_NUMHOOKS]; |
||
256 | |||
257 | /* Information about old entries: */ |
||
258 | /* Number of counters (must be equal to current number of entries). */ |
||
259 | unsigned int num_counters; |
||
260 | /* The old entries' counters. */ |
||
261 | struct ip6t_counters *counters; |
||
262 | |||
263 | /* The entries (hang off end: not really an array). */ |
||
264 | struct ip6t_entry entries[0]; |
||
265 | }; |
||
266 | |||
267 | /* The argument to IP6T_SO_ADD_COUNTERS. */ |
||
268 | struct ip6t_counters_info |
||
269 | { |
||
270 | /* Which table. */ |
||
271 | char name[IP6T_TABLE_MAXNAMELEN]; |
||
272 | |||
273 | unsigned int num_counters; |
||
274 | |||
275 | /* The counters (actually `number' of these). */ |
||
276 | struct ip6t_counters counters[0]; |
||
277 | }; |
||
278 | |||
279 | /* The argument to IP6T_SO_GET_ENTRIES. */ |
||
280 | struct ip6t_get_entries |
||
281 | { |
||
282 | /* Which table: user fills this in. */ |
||
283 | char name[IP6T_TABLE_MAXNAMELEN]; |
||
284 | |||
285 | /* User fills this in: total entry size. */ |
||
286 | unsigned int size; |
||
287 | |||
288 | /* The entries. */ |
||
289 | struct ip6t_entry entrytable[0]; |
||
290 | }; |
||
291 | |||
292 | /* Standard return verdict, or do jump. */ |
||
293 | #define IP6T_STANDARD_TARGET "" |
||
294 | /* Error verdict. */ |
||
295 | #define IP6T_ERROR_TARGET "ERROR" |
||
296 | |||
297 | /* Helper functions */ |
||
298 | static __inline__ struct ip6t_entry_target * |
||
299 | ip6t_get_target(struct ip6t_entry *e) |
||
300 | { |
||
301 | return (void *)e + e->target_offset; |
||
302 | } |
||
303 | |||
304 | /* fn returns 0 to continue iteration */ |
||
305 | #define IP6T_MATCH_ITERATE(e, fn, args...) \ |
||
306 | ({ \ |
||
307 | unsigned int __i; \ |
||
308 | int __ret = 0; \ |
||
309 | struct ip6t_entry_match *__m; \ |
||
310 | \ |
||
311 | for (__i = sizeof(struct ip6t_entry); \ |
||
312 | __i < (e)->target_offset; \ |
||
313 | __i += __m->u.match_size) { \ |
||
314 | __m = (void *)(e) + __i; \ |
||
315 | \ |
||
316 | __ret = fn(__m , ## args); \ |
||
317 | if (__ret != 0) \ |
||
318 | break; \ |
||
319 | } \ |
||
320 | __ret; \ |
||
321 | }) |
||
322 | |||
323 | /* fn returns 0 to continue iteration */ |
||
324 | #define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \ |
||
325 | ({ \ |
||
326 | unsigned int __i; \ |
||
327 | int __ret = 0; \ |
||
328 | struct ip6t_entry *__e; \ |
||
329 | \ |
||
330 | for (__i = 0; __i < (size); __i += __e->next_offset) { \ |
||
331 | __e = (void *)(entries) + __i; \ |
||
332 | \ |
||
333 | __ret = fn(__e , ## args); \ |
||
334 | if (__ret != 0) \ |
||
335 | break; \ |
||
336 | } \ |
||
337 | __ret; \ |
||
338 | }) |
||
339 | |||
340 | /* |
||
341 | * Main firewall chains definitions and global var's definitions. |
||
342 | */ |
||
343 | |||
344 | #ifdef __KERNEL__ |
||
345 | |||
346 | #include <linux/init.h> |
||
347 | extern void ip6t_init(void) __init; |
||
348 | |||
349 | struct ip6t_match |
||
350 | { |
||
351 | struct list_head list; |
||
352 | |||
353 | const char name[IP6T_FUNCTION_MAXNAMELEN]; |
||
354 | |||
355 | /* Return true or false: return FALSE and set *hotdrop = 1 to |
||
356 | force immediate packet drop. */ |
||
357 | int (*match)(const struct sk_buff *skb, |
||
358 | const struct net_device *in, |
||
359 | const struct net_device *out, |
||
360 | const void *matchinfo, |
||
361 | int offset, |
||
362 | const void *hdr, |
||
363 | u_int16_t datalen, |
||
364 | int *hotdrop); |
||
365 | |||
366 | /* Called when user tries to insert an entry of this type. */ |
||
367 | /* Should return true or false. */ |
||
368 | int (*checkentry)(const char *tablename, |
||
369 | const struct ip6t_ip6 *ip, |
||
370 | void *matchinfo, |
||
371 | unsigned int matchinfosize, |
||
372 | unsigned int hook_mask); |
||
373 | |||
374 | /* Called when entry of this type deleted. */ |
||
375 | void (*destroy)(void *matchinfo, unsigned int matchinfosize); |
||
376 | |||
377 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ |
||
378 | struct module *me; |
||
379 | }; |
||
380 | |||
381 | /* Registration hooks for targets. */ |
||
382 | struct ip6t_target |
||
383 | { |
||
384 | struct list_head list; |
||
385 | |||
386 | const char name[IP6T_FUNCTION_MAXNAMELEN]; |
||
387 | |||
388 | /* Returns verdict. */ |
||
389 | unsigned int (*target)(struct sk_buff **pskb, |
||
390 | unsigned int hooknum, |
||
391 | const struct net_device *in, |
||
392 | const struct net_device *out, |
||
393 | const void *targinfo, |
||
394 | void *userdata); |
||
395 | |||
396 | /* Called when user tries to insert an entry of this type: |
||
397 | hook_mask is a bitmask of hooks from which it can be |
||
398 | called. */ |
||
399 | /* Should return true or false. */ |
||
400 | int (*checkentry)(const char *tablename, |
||
401 | const struct ip6t_entry *e, |
||
402 | void *targinfo, |
||
403 | unsigned int targinfosize, |
||
404 | unsigned int hook_mask); |
||
405 | |||
406 | /* Called when entry of this type deleted. */ |
||
407 | void (*destroy)(void *targinfo, unsigned int targinfosize); |
||
408 | |||
409 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ |
||
410 | struct module *me; |
||
411 | }; |
||
412 | |||
413 | extern int ip6t_register_target(struct ip6t_target *target); |
||
414 | extern void ip6t_unregister_target(struct ip6t_target *target); |
||
415 | |||
416 | extern int ip6t_register_match(struct ip6t_match *match); |
||
417 | extern void ip6t_unregister_match(struct ip6t_match *match); |
||
418 | |||
419 | /* Furniture shopping... */ |
||
420 | struct ip6t_table |
||
421 | { |
||
422 | struct list_head list; |
||
423 | |||
424 | /* A unique name... */ |
||
425 | char name[IP6T_TABLE_MAXNAMELEN]; |
||
426 | |||
427 | /* Seed table: copied in register_table */ |
||
428 | struct ip6t_replace *table; |
||
429 | |||
430 | /* What hooks you will enter on */ |
||
431 | unsigned int valid_hooks; |
||
432 | |||
433 | /* Lock for the curtain */ |
||
434 | rwlock_t lock; |
||
435 | |||
436 | /* Man behind the curtain... */ |
||
437 | struct ip6t_table_info *private; |
||
438 | |||
439 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ |
||
440 | struct module *me; |
||
441 | }; |
||
442 | |||
443 | extern int ip6t_register_table(struct ip6t_table *table); |
||
444 | extern void ip6t_unregister_table(struct ip6t_table *table); |
||
445 | extern unsigned int ip6t_do_table(struct sk_buff **pskb, |
||
446 | unsigned int hook, |
||
447 | const struct net_device *in, |
||
448 | const struct net_device *out, |
||
449 | struct ip6t_table *table, |
||
450 | void *userdata); |
||
451 | |||
452 | /* Check for an extension */ |
||
453 | extern int ip6t_ext_hdr(u8 nexthdr); |
||
454 | |||
455 | #define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1)) |
||
456 | |||
457 | #endif /*__KERNEL__*/ |
||
458 | #endif /* _IP6_TABLES_H */ |