Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * ebtables | |
3 | * | |
4 | * Authors: | |
5 | * Bart De Schuymer <bdschuym@pandora.be> | |
6 | * | |
7 | * ebtables.c,v 2.0, April, 2002 | |
8 | * | |
9 | * This code is stongly inspired on the iptables code which is | |
10 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling | |
11 | */ | |
12 | ||
13 | #ifndef __LINUX_BRIDGE_EFF_H | |
14 | #define __LINUX_BRIDGE_EFF_H | |
15 | #include <linux/if.h> | |
16 | #include <linux/netfilter_bridge.h> | |
17 | #include <linux/if_ether.h> | |
18 | ||
19 | #define EBT_TABLE_MAXNAMELEN 32 | |
20 | #define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN | |
21 | #define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN | |
22 | ||
23 | /* verdicts >0 are "branches" */ | |
24 | #define EBT_ACCEPT -1 | |
25 | #define EBT_DROP -2 | |
26 | #define EBT_CONTINUE -3 | |
27 | #define EBT_RETURN -4 | |
28 | #define NUM_STANDARD_TARGETS 4 | |
d12cdc3c BDS |
29 | /* ebtables target modules store the verdict inside an int. We can |
30 | * reclaim a part of this int for backwards compatible extensions. | |
31 | * The 4 lsb are more than enough to store the verdict. */ | |
32 | #define EBT_VERDICT_BITS 0x0000000F | |
1da177e4 LT |
33 | |
34 | struct ebt_counter | |
35 | { | |
36 | uint64_t pcnt; | |
37 | uint64_t bcnt; | |
38 | }; | |
39 | ||
40 | struct ebt_replace | |
41 | { | |
42 | char name[EBT_TABLE_MAXNAMELEN]; | |
43 | unsigned int valid_hooks; | |
44 | /* nr of rules in the table */ | |
45 | unsigned int nentries; | |
46 | /* total size of the entries */ | |
47 | unsigned int entries_size; | |
48 | /* start of the chains */ | |
49 | struct ebt_entries *hook_entry[NF_BR_NUMHOOKS]; | |
50 | /* nr of counters userspace expects back */ | |
51 | unsigned int num_counters; | |
52 | /* where the kernel will put the old counters */ | |
53 | struct ebt_counter *counters; | |
54 | char *entries; | |
55 | }; | |
56 | ||
57 | struct ebt_entries { | |
58 | /* this field is always set to zero | |
59 | * See EBT_ENTRY_OR_ENTRIES. | |
60 | * Must be same size as ebt_entry.bitmask */ | |
61 | unsigned int distinguisher; | |
62 | /* the chain name */ | |
63 | char name[EBT_CHAIN_MAXNAMELEN]; | |
64 | /* counter offset for this chain */ | |
65 | unsigned int counter_offset; | |
66 | /* one standard (accept, drop, return) per hook */ | |
67 | int policy; | |
68 | /* nr. of entries */ | |
69 | unsigned int nentries; | |
70 | /* entry list */ | |
71 | char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); | |
72 | }; | |
73 | ||
74 | /* used for the bitmask of struct ebt_entry */ | |
75 | ||
76 | /* This is a hack to make a difference between an ebt_entry struct and an | |
77 | * ebt_entries struct when traversing the entries from start to end. | |
78 | * Using this simplifies the code alot, while still being able to use | |
79 | * ebt_entries. | |
80 | * Contrary, iptables doesn't use something like ebt_entries and therefore uses | |
81 | * different techniques for naming the policy and such. So, iptables doesn't | |
82 | * need a hack like this. | |
83 | */ | |
84 | #define EBT_ENTRY_OR_ENTRIES 0x01 | |
85 | /* these are the normal masks */ | |
86 | #define EBT_NOPROTO 0x02 | |
87 | #define EBT_802_3 0x04 | |
88 | #define EBT_SOURCEMAC 0x08 | |
89 | #define EBT_DESTMAC 0x10 | |
90 | #define EBT_F_MASK (EBT_NOPROTO | EBT_802_3 | EBT_SOURCEMAC | EBT_DESTMAC \ | |
91 | | EBT_ENTRY_OR_ENTRIES) | |
92 | ||
93 | #define EBT_IPROTO 0x01 | |
94 | #define EBT_IIN 0x02 | |
95 | #define EBT_IOUT 0x04 | |
96 | #define EBT_ISOURCE 0x8 | |
97 | #define EBT_IDEST 0x10 | |
98 | #define EBT_ILOGICALIN 0x20 | |
99 | #define EBT_ILOGICALOUT 0x40 | |
100 | #define EBT_INV_MASK (EBT_IPROTO | EBT_IIN | EBT_IOUT | EBT_ILOGICALIN \ | |
101 | | EBT_ILOGICALOUT | EBT_ISOURCE | EBT_IDEST) | |
102 | ||
103 | struct ebt_entry_match | |
104 | { | |
105 | union { | |
106 | char name[EBT_FUNCTION_MAXNAMELEN]; | |
107 | struct ebt_match *match; | |
108 | } u; | |
109 | /* size of data */ | |
110 | unsigned int match_size; | |
111 | unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); | |
112 | }; | |
113 | ||
114 | struct ebt_entry_watcher | |
115 | { | |
116 | union { | |
117 | char name[EBT_FUNCTION_MAXNAMELEN]; | |
118 | struct ebt_watcher *watcher; | |
119 | } u; | |
120 | /* size of data */ | |
121 | unsigned int watcher_size; | |
122 | unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); | |
123 | }; | |
124 | ||
125 | struct ebt_entry_target | |
126 | { | |
127 | union { | |
128 | char name[EBT_FUNCTION_MAXNAMELEN]; | |
129 | struct ebt_target *target; | |
130 | } u; | |
131 | /* size of data */ | |
132 | unsigned int target_size; | |
133 | unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); | |
134 | }; | |
135 | ||
136 | #define EBT_STANDARD_TARGET "standard" | |
137 | struct ebt_standard_target | |
138 | { | |
139 | struct ebt_entry_target target; | |
140 | int verdict; | |
141 | }; | |
142 | ||
143 | /* one entry */ | |
144 | struct ebt_entry { | |
145 | /* this needs to be the first field */ | |
146 | unsigned int bitmask; | |
147 | unsigned int invflags; | |
47c183fa | 148 | __be16 ethproto; |
1da177e4 LT |
149 | /* the physical in-dev */ |
150 | char in[IFNAMSIZ]; | |
151 | /* the logical in-dev */ | |
152 | char logical_in[IFNAMSIZ]; | |
153 | /* the physical out-dev */ | |
154 | char out[IFNAMSIZ]; | |
155 | /* the logical out-dev */ | |
156 | char logical_out[IFNAMSIZ]; | |
157 | unsigned char sourcemac[ETH_ALEN]; | |
158 | unsigned char sourcemsk[ETH_ALEN]; | |
159 | unsigned char destmac[ETH_ALEN]; | |
160 | unsigned char destmsk[ETH_ALEN]; | |
161 | /* sizeof ebt_entry + matches */ | |
162 | unsigned int watchers_offset; | |
163 | /* sizeof ebt_entry + matches + watchers */ | |
164 | unsigned int target_offset; | |
165 | /* sizeof ebt_entry + matches + watchers + target */ | |
166 | unsigned int next_offset; | |
167 | unsigned char elems[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); | |
168 | }; | |
169 | ||
170 | /* {g,s}etsockopt numbers */ | |
171 | #define EBT_BASE_CTL 128 | |
172 | ||
173 | #define EBT_SO_SET_ENTRIES (EBT_BASE_CTL) | |
174 | #define EBT_SO_SET_COUNTERS (EBT_SO_SET_ENTRIES+1) | |
175 | #define EBT_SO_SET_MAX (EBT_SO_SET_COUNTERS+1) | |
176 | ||
177 | #define EBT_SO_GET_INFO (EBT_BASE_CTL) | |
178 | #define EBT_SO_GET_ENTRIES (EBT_SO_GET_INFO+1) | |
179 | #define EBT_SO_GET_INIT_INFO (EBT_SO_GET_ENTRIES+1) | |
180 | #define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO+1) | |
181 | #define EBT_SO_GET_MAX (EBT_SO_GET_INIT_ENTRIES+1) | |
182 | ||
183 | #ifdef __KERNEL__ | |
184 | ||
185 | /* return values for match() functions */ | |
186 | #define EBT_MATCH 0 | |
187 | #define EBT_NOMATCH 1 | |
188 | ||
189 | struct ebt_match | |
190 | { | |
191 | struct list_head list; | |
192 | const char name[EBT_FUNCTION_MAXNAMELEN]; | |
193 | /* 0 == it matches */ | |
194 | int (*match)(const struct sk_buff *skb, const struct net_device *in, | |
195 | const struct net_device *out, const void *matchdata, | |
196 | unsigned int datalen); | |
197 | /* 0 == let it in */ | |
198 | int (*check)(const char *tablename, unsigned int hookmask, | |
199 | const struct ebt_entry *e, void *matchdata, unsigned int datalen); | |
200 | void (*destroy)(void *matchdata, unsigned int datalen); | |
201 | struct module *me; | |
202 | }; | |
203 | ||
204 | struct ebt_watcher | |
205 | { | |
206 | struct list_head list; | |
207 | const char name[EBT_FUNCTION_MAXNAMELEN]; | |
208 | void (*watcher)(const struct sk_buff *skb, unsigned int hooknr, | |
209 | const struct net_device *in, const struct net_device *out, | |
210 | const void *watcherdata, unsigned int datalen); | |
211 | /* 0 == let it in */ | |
212 | int (*check)(const char *tablename, unsigned int hookmask, | |
213 | const struct ebt_entry *e, void *watcherdata, unsigned int datalen); | |
214 | void (*destroy)(void *watcherdata, unsigned int datalen); | |
215 | struct module *me; | |
216 | }; | |
217 | ||
218 | struct ebt_target | |
219 | { | |
220 | struct list_head list; | |
221 | const char name[EBT_FUNCTION_MAXNAMELEN]; | |
222 | /* returns one of the standard verdicts */ | |
223 | int (*target)(struct sk_buff **pskb, unsigned int hooknr, | |
224 | const struct net_device *in, const struct net_device *out, | |
225 | const void *targetdata, unsigned int datalen); | |
226 | /* 0 == let it in */ | |
227 | int (*check)(const char *tablename, unsigned int hookmask, | |
228 | const struct ebt_entry *e, void *targetdata, unsigned int datalen); | |
229 | void (*destroy)(void *targetdata, unsigned int datalen); | |
230 | struct module *me; | |
231 | }; | |
232 | ||
233 | /* used for jumping from and into user defined chains (udc) */ | |
234 | struct ebt_chainstack | |
235 | { | |
236 | struct ebt_entries *chaininfo; /* pointer to chain data */ | |
237 | struct ebt_entry *e; /* pointer to entry data */ | |
238 | unsigned int n; /* n'th entry */ | |
239 | }; | |
240 | ||
241 | struct ebt_table_info | |
242 | { | |
243 | /* total size of the entries */ | |
244 | unsigned int entries_size; | |
245 | unsigned int nentries; | |
246 | /* pointers to the start of the chains */ | |
247 | struct ebt_entries *hook_entry[NF_BR_NUMHOOKS]; | |
248 | /* room to maintain the stack used for jumping from and into udc */ | |
249 | struct ebt_chainstack **chainstack; | |
250 | char *entries; | |
251 | struct ebt_counter counters[0] ____cacheline_aligned; | |
252 | }; | |
253 | ||
254 | struct ebt_table | |
255 | { | |
256 | struct list_head list; | |
257 | char name[EBT_TABLE_MAXNAMELEN]; | |
258 | struct ebt_replace *table; | |
259 | unsigned int valid_hooks; | |
260 | rwlock_t lock; | |
261 | /* e.g. could be the table explicitly only allows certain | |
262 | * matches, targets, ... 0 == let it in */ | |
263 | int (*check)(const struct ebt_table_info *info, | |
264 | unsigned int valid_hooks); | |
265 | /* the data used by the kernel */ | |
266 | struct ebt_table_info *private; | |
267 | struct module *me; | |
268 | }; | |
269 | ||
270 | #define EBT_ALIGN(s) (((s) + (__alignof__(struct ebt_replace)-1)) & \ | |
271 | ~(__alignof__(struct ebt_replace)-1)) | |
272 | extern int ebt_register_table(struct ebt_table *table); | |
273 | extern void ebt_unregister_table(struct ebt_table *table); | |
274 | extern int ebt_register_match(struct ebt_match *match); | |
275 | extern void ebt_unregister_match(struct ebt_match *match); | |
276 | extern int ebt_register_watcher(struct ebt_watcher *watcher); | |
277 | extern void ebt_unregister_watcher(struct ebt_watcher *watcher); | |
278 | extern int ebt_register_target(struct ebt_target *target); | |
279 | extern void ebt_unregister_target(struct ebt_target *target); | |
280 | extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff **pskb, | |
281 | const struct net_device *in, const struct net_device *out, | |
282 | struct ebt_table *table); | |
283 | ||
284 | /* Used in the kernel match() functions */ | |
285 | #define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg)) | |
286 | /* True if the hook mask denotes that the rule is in a base chain, | |
287 | * used in the check() functions */ | |
288 | #define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS)) | |
289 | /* Clear the bit in the hook mask that tells if the rule is on a base chain */ | |
290 | #define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS)) | |
291 | /* True if the target is not a standard target */ | |
292 | #define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0) | |
293 | ||
294 | #endif /* __KERNEL__ */ | |
295 | ||
296 | /* blatently stolen from ip_tables.h | |
297 | * fn returns 0 to continue iteration */ | |
298 | #define EBT_MATCH_ITERATE(e, fn, args...) \ | |
299 | ({ \ | |
300 | unsigned int __i; \ | |
301 | int __ret = 0; \ | |
302 | struct ebt_entry_match *__match; \ | |
303 | \ | |
304 | for (__i = sizeof(struct ebt_entry); \ | |
305 | __i < (e)->watchers_offset; \ | |
306 | __i += __match->match_size + \ | |
307 | sizeof(struct ebt_entry_match)) { \ | |
308 | __match = (void *)(e) + __i; \ | |
309 | \ | |
310 | __ret = fn(__match , ## args); \ | |
311 | if (__ret != 0) \ | |
312 | break; \ | |
313 | } \ | |
314 | if (__ret == 0) { \ | |
315 | if (__i != (e)->watchers_offset) \ | |
316 | __ret = -EINVAL; \ | |
317 | } \ | |
318 | __ret; \ | |
319 | }) | |
320 | ||
321 | #define EBT_WATCHER_ITERATE(e, fn, args...) \ | |
322 | ({ \ | |
323 | unsigned int __i; \ | |
324 | int __ret = 0; \ | |
325 | struct ebt_entry_watcher *__watcher; \ | |
326 | \ | |
327 | for (__i = e->watchers_offset; \ | |
328 | __i < (e)->target_offset; \ | |
329 | __i += __watcher->watcher_size + \ | |
330 | sizeof(struct ebt_entry_watcher)) { \ | |
331 | __watcher = (void *)(e) + __i; \ | |
332 | \ | |
333 | __ret = fn(__watcher , ## args); \ | |
334 | if (__ret != 0) \ | |
335 | break; \ | |
336 | } \ | |
337 | if (__ret == 0) { \ | |
338 | if (__i != (e)->target_offset) \ | |
339 | __ret = -EINVAL; \ | |
340 | } \ | |
341 | __ret; \ | |
342 | }) | |
343 | ||
344 | #define EBT_ENTRY_ITERATE(entries, size, fn, args...) \ | |
345 | ({ \ | |
346 | unsigned int __i; \ | |
347 | int __ret = 0; \ | |
348 | struct ebt_entry *__entry; \ | |
349 | \ | |
350 | for (__i = 0; __i < (size);) { \ | |
351 | __entry = (void *)(entries) + __i; \ | |
352 | __ret = fn(__entry , ## args); \ | |
353 | if (__ret != 0) \ | |
354 | break; \ | |
355 | if (__entry->bitmask != 0) \ | |
356 | __i += __entry->next_offset; \ | |
357 | else \ | |
358 | __i += sizeof(struct ebt_entries); \ | |
359 | } \ | |
360 | if (__ret == 0) { \ | |
361 | if (__i != (size)) \ | |
362 | __ret = -EINVAL; \ | |
363 | } \ | |
364 | __ret; \ | |
365 | }) | |
366 | ||
367 | #endif |