summaryrefslogtreecommitdiffstats
path: root/kernel/linux2.5/include/linux/netfilter_bridge/ebtables.h
blob: c653c35260c5ddc29ff1184b8485fee15d63c30c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
/*
 *  ebtables
 *
 *	Authors:
 *	Bart De Schuymer		<bart.de.schuymer@pandora.be>
 *
 *  ebtables.c,v 2.0, April, 2002
 *
 *  This code is stongly inspired on the iptables code which is
 *  Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
 */

#ifndef __LINUX_BRIDGE_EFF_H
#define __LINUX_BRIDGE_EFF_H
#include <linux/if.h>
#include <linux/netfilter_bridge.h>
#include <linux/if_ether.h>

#define EBT_TABLE_MAXNAMELEN 32
#define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN
#define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN

// verdicts >0 are "branches"
#define EBT_ACCEPT   -1
#define EBT_DROP     -2
#define EBT_CONTINUE -3
#define EBT_RETURN   -4
#define NUM_STANDARD_TARGETS   4

struct ebt_counter
{
	uint64_t pcnt;
};

struct ebt_entries {
	// this field is always set to zero
	// See EBT_ENTRY_OR_ENTRIES.
	// Must be same size as ebt_entry.bitmask
	unsigned int distinguisher;
	// the chain name
	char name[EBT_CHAIN_MAXNAMELEN];
	// counter offset for this chain
	unsigned int counter_offset;
	// one standard (accept, drop, return) per hook
	int policy;
	// nr. of entries
	unsigned int nentries;
	// entry list
	char data[0];
};

// used for the bitmask of struct ebt_entry

// This is a hack to make a difference between an ebt_entry struct and an
// ebt_entries struct when traversing the entries from start to end.
// Using this simplifies the code alot, while still being able to use
// ebt_entries.
// Contrary, iptables doesn't use something like ebt_entries and therefore uses
// different techniques for naming the policy and such. So, iptables doesn't
// need a hack like this.
#define EBT_ENTRY_OR_ENTRIES 0x01
// these are the normal masks
#define EBT_NOPROTO 0x02
#define EBT_802_3 0x04
#define EBT_SOURCEMAC 0x08
#define EBT_DESTMAC 0x10
#define EBT_F_MASK (EBT_NOPROTO | EBT_802_3 | EBT_SOURCEMAC | EBT_DESTMAC \
   | EBT_ENTRY_OR_ENTRIES)

#define EBT_IPROTO 0x01
#define EBT_IIN 0x02
#define EBT_IOUT 0x04
#define EBT_ISOURCE 0x8
#define EBT_IDEST 0x10
#define EBT_ILOGICALIN 0x20
#define EBT_ILOGICALOUT 0x40
#define EBT_INV_MASK (EBT_IPROTO | EBT_IIN | EBT_IOUT | EBT_ILOGICALIN \
   | EBT_ILOGICALOUT | EBT_ISOURCE | EBT_IDEST)

struct ebt_entry_match
{
	union {
		char name[EBT_FUNCTION_MAXNAMELEN];
		struct ebt_match *match;
	} u;
	// size of data
	unsigned int match_size;
	unsigned char data[0];
};

struct ebt_entry_watcher
{
	union {
		char name[EBT_FUNCTION_MAXNAMELEN];
		struct ebt_watcher *watcher;
	} u;
	// size of data
	unsigned int watcher_size;
	unsigned char data[0];
};

struct ebt_entry_target
{
	union {
		char name[EBT_FUNCTION_MAXNAMELEN];
		struct ebt_target *target;
	} u;
	// size of data
	unsigned int target_size;
	unsigned char data[0];
};

#define EBT_STANDARD_TARGET "standard"
struct ebt_standard_target
{
	struct ebt_entry_target target;
	int verdict;
};

// one entry
struct ebt_entry {
	// this needs to be the first field
	unsigned int bitmask;
	unsigned int invflags;
	uint16_t ethproto;
	// the physical in-dev
	char in[IFNAMSIZ];
	// the logical in-dev
	char logical_in[IFNAMSIZ];
	// the physical out-dev
	char out[IFNAMSIZ];
	// the logical out-dev
	char logical_out[IFNAMSIZ];
	unsigned char sourcemac[ETH_ALEN];
	unsigned char sourcemsk[ETH_ALEN];
	unsigned char destmac[ETH_ALEN];
	unsigned char destmsk[ETH_ALEN];
	// sizeof ebt_entry + matches
	unsigned int watchers_offset;
	// sizeof ebt_entry + matches + watchers
	unsigned int target_offset;
	// sizeof ebt_entry + matches + watchers + target
	unsigned int next_offset;
	unsigned char elems[0];
};

struct ebt_replace
{
	char name[EBT_TABLE_MAXNAMELEN];
	unsigned int valid_hooks;
	// nr of rules in the table
	unsigned int nentries;
	// total size of the entries
	unsigned int entries_size;
	// start of the chains
	struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
	// nr of counters userspace expects back
	unsigned int num_counters;
	// where the kernel will put the old counters
	struct ebt_counter *counters;
	char *entries;
};

#ifdef __KERNEL__

// [gs]etsockopt numbers
#define EBT_BASE_CTL            128

#define EBT_SO_SET_ENTRIES      (EBT_BASE_CTL)
#define EBT_SO_SET_COUNTERS     (EBT_SO_SET_ENTRIES+1)
#define EBT_SO_SET_MAX          (EBT_SO_SET_COUNTERS+1)

#define EBT_SO_GET_INFO         (EBT_BASE_CTL)
#define EBT_SO_GET_ENTRIES      (EBT_SO_GET_INFO+1)
#define EBT_SO_GET_INIT_INFO    (EBT_SO_GET_ENTRIES+1)
#define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO+1)
#define EBT_SO_GET_MAX          (EBT_SO_GET_INIT_ENTRIES+1)

// return values for match() functions
#define EBT_MATCH 0
#define EBT_NOMATCH 1

struct ebt_match
{
	struct list_head list;
	const char name[EBT_FUNCTION_MAXNAMELEN];
	// 0 == it matches
	int (*match)(const struct sk_buff *skb, const struct net_device *in,
	   const struct net_device *out, const void *matchdata,
	   unsigned int datalen);
	// 0 == let it in
	int (*check)(const char *tablename, unsigned int hookmask,
	   const struct ebt_entry *e, void *matchdata, unsigned int datalen);
	void (*destroy)(void *matchdata, unsigned int datalen);
	struct module *me;
};

struct ebt_watcher
{
	struct list_head list;
	const char name[EBT_FUNCTION_MAXNAMELEN];
	void (*watcher)(const struct sk_buff *skb, const struct net_device *in,
	   const struct net_device *out, const void *watcherdata,
	   unsigned int datalen);
	// 0 == let it in
	int (*check)(const char *tablename, unsigned int hookmask,
	   const struct ebt_entry *e, void *watcherdata, unsigned int datalen);
	void (*destroy)(void *watcherdata, unsigned int datalen);
	struct module *me;
};

struct ebt_target
{
	struct list_head list;
	const char name[EBT_FUNCTION_MAXNAMELEN];
	// returns one of the standard verdicts
	int (*target)(struct sk_buff **pskb, unsigned int hooknr,
	   const struct net_device *in, const struct net_device *out,
	   const void *targetdata, unsigned int datalen);
	// 0 == let it in
	int (*check)(const char *tablename, unsigned int hookmask,
	   const struct ebt_entry *e, void *targetdata, unsigned int datalen);
	void (*destroy)(void *targetdata, unsigned int datalen);
	struct module *me;
};

// used for jumping from and into user defined chains (udc)
struct ebt_chainstack
{
	struct ebt_entries *chaininfo; // pointer to chain data
	struct ebt_entry *e; // pointer to entry data
	unsigned int n; // n'th entry
};

struct ebt_table_info
{
	// total size of the entries
	unsigned int entries_size;
	unsigned int nentries;
	// pointers to the start of the chains
	struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
	// room to maintain the stack used for jumping from and into udc
	struct ebt_chainstack **chainstack;
	char *entries;
	struct ebt_counter counters[0] ____cacheline_aligned;
};

struct ebt_table
{
	struct list_head list;
	char name[EBT_TABLE_MAXNAMELEN];
	struct ebt_replace *table;
	unsigned int valid_hooks;
	rwlock_t lock;
	// e.g. could be the table explicitly only allows certain
	// matches, targets, ... 0 == let it in
	int (*check)(const struct ebt_table_info *info,
	   unsigned int valid_hooks);
	// the data used by the kernel
	struct ebt_table_info *private;
};

extern int ebt_register_table(struct ebt_table *table);
extern void ebt_unregister_table(struct ebt_table *table);
extern int ebt_register_match(struct ebt_match *match);
extern void ebt_unregister_match(struct ebt_match *match);
extern int ebt_register_watcher(struct ebt_watcher *watcher);
extern void ebt_unregister_watcher(struct ebt_watcher *watcher);
extern int ebt_register_target(struct ebt_target *target);
extern void ebt_unregister_target(struct ebt_target *target);
extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff **pskb,
   const struct net_device *in, const struct net_device *out,
   struct ebt_table *table);

   // Used in the kernel match() functions
#define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg))
// True if the hook mask denotes that the rule is in a base chain,
// used in the check() functions
#define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS))
// Clear the bit in the hook mask that tells if the rule is on a base chain
#define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS))
// True if the target is not a standard target
#define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0)

#endif /* __KERNEL__ */

// blatently stolen from ip_tables.h
// fn returns 0 to continue iteration
#define EBT_MATCH_ITERATE(e, fn, args...)                   \
({                                                          \
	unsigned int __i;                                   \
	int __ret = 0;                                      \
	struct ebt_entry_match *__match;                    \
	                                                    \
	for (__i = sizeof(struct ebt_entry);                \
	     __i < (e)->watchers_offset;                    \
	     __i += __match->match_size +                   \
	     sizeof(struct ebt_entry_match)) {              \
		__match = (void *)(e) + __i;                \
		                                            \
		__ret = fn(__match , ## args);              \
		if (__ret != 0)                             \
			break;                              \
	}                                                   \
	if (__ret == 0) {                                   \
		if (__i != (e)->watchers_offset)            \
			__ret = -EINVAL;                    \
	}                                                   \
	__ret;                                              \
})

#define EBT_WATCHER_ITERATE(e, fn, args...)                 \
({                                                          \
	unsigned int __i;                                   \
	int __ret = 0;                                      \
	struct ebt_entry_watcher *__watcher;                \
	                                                    \
	for (__i = e->watchers_offset;                      \
	     __i < (e)->target_offset;                      \
	     __i += __watcher->watcher_size +               \
	     sizeof(struct ebt_entry_watcher)) {            \
		__watcher = (void *)(e) + __i;              \
		                                            \
		__ret = fn(__watcher , ## args);            \
		if (__ret != 0)                             \
			break;                              \
	}                                                   \
	if (__ret == 0) {                                   \
		if (__i != (e)->target_offset)              \
			__ret = -EINVAL;                    \
	}                                                   \
	__ret;                                              \
})

#define EBT_ENTRY_ITERATE(entries, size, fn, args...)       \
({                                                          \
	unsigned int __i;                                   \
	int __ret = 0;                                      \
	struct ebt_entry *__entry;                          \
	                                                    \
	for (__i = 0; __i < (size);) {                      \
		__entry = (void *)(entries) + __i;          \
		__ret = fn(__entry , ## args);              \
		if (__ret != 0)                             \
			break;                              \
		if (__entry->bitmask != 0)                  \
			__i += __entry->next_offset;        \
		else                                        \
			__i += sizeof(struct ebt_entries);  \
	}                                                   \
	if (__ret == 0) {                                   \
		if (__i != (size))                          \
			__ret = -EINVAL;                    \
	}                                                   \
	__ret;                                              \
})

#endif