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/* Local copy of the kernel file, needed for Sparc64 support */
14#ifndef __LINUX_BRIDGE_EFF_H
15#define __LINUX_BRIDGE_EFF_H
16#include <linux/if.h>
17#include <linux/netfilter_bridge.h>
18#include <linux/if_ether.h>
19
20#define EBT_TABLE_MAXNAMELEN 32
21#define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN
22#define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN
23
24/* verdicts >0 are "branches" */
25#define EBT_ACCEPT   -1
26#define EBT_DROP     -2
27#define EBT_CONTINUE -3
28#define EBT_RETURN   -4
29#define NUM_STANDARD_TARGETS   4
30/* ebtables target modules store the verdict inside an int. We can
31 * reclaim a part of this int for backwards compatible extensions.
32 * The 4 lsb are more than enough to store the verdict. */
33#define EBT_VERDICT_BITS 0x0000000F
34
35struct ebt_counter
36{
37	uint64_t pcnt;
38	uint64_t bcnt;
39};
40
41struct ebt_replace
42{
43	char name[EBT_TABLE_MAXNAMELEN];
44	unsigned int valid_hooks;
45	/* nr of rules in the table */
46	unsigned int nentries;
47	/* total size of the entries */
48	unsigned int entries_size;
49	/* start of the chains */
50#ifdef KERNEL_64_USERSPACE_32
51	uint64_t hook_entry[NF_BR_NUMHOOKS];
52#else
53	struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
54#endif
55	/* nr of counters userspace expects back */
56	unsigned int num_counters;
57	/* where the kernel will put the old counters */
58#ifdef KERNEL_64_USERSPACE_32
59	uint64_t counters;
60	uint64_t entries;
61#else
62	struct ebt_counter *counters;
63	char *entries;
64#endif
65};
66
67struct ebt_entries {
68	/* this field is always set to zero
69	 * See EBT_ENTRY_OR_ENTRIES.
70	 * Must be same size as ebt_entry.bitmask */
71	unsigned int distinguisher;
72	/* the chain name */
73	char name[EBT_CHAIN_MAXNAMELEN];
74	/* counter offset for this chain */
75	unsigned int counter_offset;
76	/* one standard (accept, drop, return) per hook */
77	int policy;
78	/* nr. of entries */
79	unsigned int nentries;
80	/* entry list */
81	char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
82};
83
84/* used for the bitmask of struct ebt_entry */
85
86/* This is a hack to make a difference between an ebt_entry struct and an
87 * ebt_entries struct when traversing the entries from start to end.
88 * Using this simplifies the code alot, while still being able to use
89 * ebt_entries.
90 * Contrary, iptables doesn't use something like ebt_entries and therefore uses
91 * different techniques for naming the policy and such. So, iptables doesn't
92 * need a hack like this.
93 */
94#define EBT_ENTRY_OR_ENTRIES 0x01
95/* these are the normal masks */
96#define EBT_NOPROTO 0x02
97#define EBT_802_3 0x04
98#define EBT_SOURCEMAC 0x08
99#define EBT_DESTMAC 0x10
100#define EBT_F_MASK (EBT_NOPROTO | EBT_802_3 | EBT_SOURCEMAC | EBT_DESTMAC \
101   | EBT_ENTRY_OR_ENTRIES)
102
103#define EBT_IPROTO 0x01
104#define EBT_IIN 0x02
105#define EBT_IOUT 0x04
106#define EBT_ISOURCE 0x8
107#define EBT_IDEST 0x10
108#define EBT_ILOGICALIN 0x20
109#define EBT_ILOGICALOUT 0x40
110#define EBT_INV_MASK (EBT_IPROTO | EBT_IIN | EBT_IOUT | EBT_ILOGICALIN \
111   | EBT_ILOGICALOUT | EBT_ISOURCE | EBT_IDEST)
112
113struct ebt_entry_match
114{
115	union {
116		char name[EBT_FUNCTION_MAXNAMELEN];
117		struct ebt_match *match;
118	} u;
119	/* size of data */
120	unsigned int match_size;
121#ifdef KERNEL_64_USERSPACE_32
122	unsigned int pad;
123#endif
124	unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
125};
126
127struct ebt_entry_watcher
128{
129	union {
130		char name[EBT_FUNCTION_MAXNAMELEN];
131		struct ebt_watcher *watcher;
132	} u;
133	/* size of data */
134	unsigned int watcher_size;
135#ifdef KERNEL_64_USERSPACE_32
136	unsigned int pad;
137#endif
138	unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
139};
140
141struct ebt_entry_target
142{
143	union {
144		char name[EBT_FUNCTION_MAXNAMELEN];
145		struct ebt_target *target;
146	} u;
147	/* size of data */
148	unsigned int target_size;
149#ifdef KERNEL_64_USERSPACE_32
150	unsigned int pad;
151#endif
152	unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
153};
154
155#define EBT_STANDARD_TARGET "standard"
156struct ebt_standard_target
157{
158	struct ebt_entry_target target;
159	int verdict;
160#ifdef KERNEL_64_USERSPACE_32
161	unsigned int pad;
162#endif
163};
164
165/* one entry */
166struct ebt_entry {
167	/* this needs to be the first field */
168	unsigned int bitmask;
169	unsigned int invflags;
170	uint16_t ethproto;
171	/* the physical in-dev */
172	char in[IFNAMSIZ];
173	/* the logical in-dev */
174	char logical_in[IFNAMSIZ];
175	/* the physical out-dev */
176	char out[IFNAMSIZ];
177	/* the logical out-dev */
178	char logical_out[IFNAMSIZ];
179	unsigned char sourcemac[ETH_ALEN];
180	unsigned char sourcemsk[ETH_ALEN];
181	unsigned char destmac[ETH_ALEN];
182	unsigned char destmsk[ETH_ALEN];
183	/* sizeof ebt_entry + matches */
184	unsigned int watchers_offset;
185	/* sizeof ebt_entry + matches + watchers */
186	unsigned int target_offset;
187	/* sizeof ebt_entry + matches + watchers + target */
188	unsigned int next_offset;
189	unsigned char elems[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
190};
191
192/* {g,s}etsockopt numbers */
193#define EBT_BASE_CTL            128
194
195#define EBT_SO_SET_ENTRIES      (EBT_BASE_CTL)
196#define EBT_SO_SET_COUNTERS     (EBT_SO_SET_ENTRIES+1)
197#define EBT_SO_SET_MAX          (EBT_SO_SET_COUNTERS+1)
198
199#define EBT_SO_GET_INFO         (EBT_BASE_CTL)
200#define EBT_SO_GET_ENTRIES      (EBT_SO_GET_INFO+1)
201#define EBT_SO_GET_INIT_INFO    (EBT_SO_GET_ENTRIES+1)
202#define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO+1)
203#define EBT_SO_GET_MAX          (EBT_SO_GET_INIT_ENTRIES+1)
204
205/* blatently stolen from ip_tables.h
206 * fn returns 0 to continue iteration */
207#define EBT_MATCH_ITERATE(e, fn, args...)                   \
208({                                                          \
209	unsigned int __i;                                   \
210	int __ret = 0;                                      \
211	struct ebt_entry_match *__match;                    \
212	                                                    \
213	for (__i = sizeof(struct ebt_entry);                \
214	     __i < (e)->watchers_offset;                    \
215	     __i += __match->match_size +                   \
216	     sizeof(struct ebt_entry_match)) {              \
217		__match = (void *)(e) + __i;                \
218		                                            \
219		__ret = fn(__match , ## args);              \
220		if (__ret != 0)                             \
221			break;                              \
222	}                                                   \
223	if (__ret == 0) {                                   \
224		if (__i != (e)->watchers_offset)            \
225			__ret = -EINVAL;                    \
226	}                                                   \
227	__ret;                                              \
228})
229
230#define EBT_WATCHER_ITERATE(e, fn, args...)                 \
231({                                                          \
232	unsigned int __i;                                   \
233	int __ret = 0;                                      \
234	struct ebt_entry_watcher *__watcher;                \
235	                                                    \
236	for (__i = e->watchers_offset;                      \
237	     __i < (e)->target_offset;                      \
238	     __i += __watcher->watcher_size +               \
239	     sizeof(struct ebt_entry_watcher)) {            \
240		__watcher = (void *)(e) + __i;              \
241		                                            \
242		__ret = fn(__watcher , ## args);            \
243		if (__ret != 0)                             \
244			break;                              \
245	}                                                   \
246	if (__ret == 0) {                                   \
247		if (__i != (e)->target_offset)              \
248			__ret = -EINVAL;                    \
249	}                                                   \
250	__ret;                                              \
251})
252
253#define EBT_ENTRY_ITERATE(entries, size, fn, args...)       \
254({                                                          \
255	unsigned int __i;                                   \
256	int __ret = 0;                                      \
257	struct ebt_entry *__entry;                          \
258	                                                    \
259	for (__i = 0; __i < (size);) {                      \
260		__entry = (void *)(entries) + __i;          \
261		__ret = fn(__entry , ## args);              \
262		if (__ret != 0)                             \
263			break;                              \
264		if (__entry->bitmask != 0)                  \
265			__i += __entry->next_offset;        \
266		else                                        \
267			__i += sizeof(struct ebt_entries);  \
268	}                                                   \
269	if (__ret == 0) {                                   \
270		if (__i != (size))                          \
271			__ret = -EINVAL;                    \
272	}                                                   \
273	__ret;                                              \
274})
275
276#endif
277