Commit 19eda879a136889110c692dec4c2ab59e0e43cef

Authored by Jan Engelhardt
Committed by Patrick McHardy
1 parent 18219d3f7d

netfilter: change return types of check functions for Ebtables extensions

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>

Showing 20 changed files with 109 additions and 108 deletions Inline Diff

include/linux/netfilter_bridge/ebtables.h
1 /* 1 /*
2 * ebtables 2 * ebtables
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * 6 *
7 * ebtables.c,v 2.0, April, 2002 7 * ebtables.c,v 2.0, April, 2002
8 * 8 *
9 * This code is stongly inspired on the iptables code which is 9 * This code is stongly inspired on the iptables code which is
10 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling 10 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11 */ 11 */
12 12
13 #ifndef __LINUX_BRIDGE_EFF_H 13 #ifndef __LINUX_BRIDGE_EFF_H
14 #define __LINUX_BRIDGE_EFF_H 14 #define __LINUX_BRIDGE_EFF_H
15 #include <linux/if.h> 15 #include <linux/if.h>
16 #include <linux/netfilter_bridge.h> 16 #include <linux/netfilter_bridge.h>
17 #include <linux/if_ether.h> 17 #include <linux/if_ether.h>
18 18
19 #define EBT_TABLE_MAXNAMELEN 32 19 #define EBT_TABLE_MAXNAMELEN 32
20 #define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN 20 #define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN
21 #define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN 21 #define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN
22 22
23 /* verdicts >0 are "branches" */ 23 /* verdicts >0 are "branches" */
24 #define EBT_ACCEPT -1 24 #define EBT_ACCEPT -1
25 #define EBT_DROP -2 25 #define EBT_DROP -2
26 #define EBT_CONTINUE -3 26 #define EBT_CONTINUE -3
27 #define EBT_RETURN -4 27 #define EBT_RETURN -4
28 #define NUM_STANDARD_TARGETS 4 28 #define NUM_STANDARD_TARGETS 4
29 /* ebtables target modules store the verdict inside an int. We can 29 /* ebtables target modules store the verdict inside an int. We can
30 * reclaim a part of this int for backwards compatible extensions. 30 * reclaim a part of this int for backwards compatible extensions.
31 * The 4 lsb are more than enough to store the verdict. */ 31 * The 4 lsb are more than enough to store the verdict. */
32 #define EBT_VERDICT_BITS 0x0000000F 32 #define EBT_VERDICT_BITS 0x0000000F
33 33
34 struct ebt_counter 34 struct ebt_counter
35 { 35 {
36 uint64_t pcnt; 36 uint64_t pcnt;
37 uint64_t bcnt; 37 uint64_t bcnt;
38 }; 38 };
39 39
40 struct ebt_replace 40 struct ebt_replace
41 { 41 {
42 char name[EBT_TABLE_MAXNAMELEN]; 42 char name[EBT_TABLE_MAXNAMELEN];
43 unsigned int valid_hooks; 43 unsigned int valid_hooks;
44 /* nr of rules in the table */ 44 /* nr of rules in the table */
45 unsigned int nentries; 45 unsigned int nentries;
46 /* total size of the entries */ 46 /* total size of the entries */
47 unsigned int entries_size; 47 unsigned int entries_size;
48 /* start of the chains */ 48 /* start of the chains */
49 struct ebt_entries __user *hook_entry[NF_BR_NUMHOOKS]; 49 struct ebt_entries __user *hook_entry[NF_BR_NUMHOOKS];
50 /* nr of counters userspace expects back */ 50 /* nr of counters userspace expects back */
51 unsigned int num_counters; 51 unsigned int num_counters;
52 /* where the kernel will put the old counters */ 52 /* where the kernel will put the old counters */
53 struct ebt_counter __user *counters; 53 struct ebt_counter __user *counters;
54 char __user *entries; 54 char __user *entries;
55 }; 55 };
56 56
57 struct ebt_replace_kernel 57 struct ebt_replace_kernel
58 { 58 {
59 char name[EBT_TABLE_MAXNAMELEN]; 59 char name[EBT_TABLE_MAXNAMELEN];
60 unsigned int valid_hooks; 60 unsigned int valid_hooks;
61 /* nr of rules in the table */ 61 /* nr of rules in the table */
62 unsigned int nentries; 62 unsigned int nentries;
63 /* total size of the entries */ 63 /* total size of the entries */
64 unsigned int entries_size; 64 unsigned int entries_size;
65 /* start of the chains */ 65 /* start of the chains */
66 struct ebt_entries *hook_entry[NF_BR_NUMHOOKS]; 66 struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
67 /* nr of counters userspace expects back */ 67 /* nr of counters userspace expects back */
68 unsigned int num_counters; 68 unsigned int num_counters;
69 /* where the kernel will put the old counters */ 69 /* where the kernel will put the old counters */
70 struct ebt_counter *counters; 70 struct ebt_counter *counters;
71 char *entries; 71 char *entries;
72 }; 72 };
73 73
74 struct ebt_entries { 74 struct ebt_entries {
75 /* this field is always set to zero 75 /* this field is always set to zero
76 * See EBT_ENTRY_OR_ENTRIES. 76 * See EBT_ENTRY_OR_ENTRIES.
77 * Must be same size as ebt_entry.bitmask */ 77 * Must be same size as ebt_entry.bitmask */
78 unsigned int distinguisher; 78 unsigned int distinguisher;
79 /* the chain name */ 79 /* the chain name */
80 char name[EBT_CHAIN_MAXNAMELEN]; 80 char name[EBT_CHAIN_MAXNAMELEN];
81 /* counter offset for this chain */ 81 /* counter offset for this chain */
82 unsigned int counter_offset; 82 unsigned int counter_offset;
83 /* one standard (accept, drop, return) per hook */ 83 /* one standard (accept, drop, return) per hook */
84 int policy; 84 int policy;
85 /* nr. of entries */ 85 /* nr. of entries */
86 unsigned int nentries; 86 unsigned int nentries;
87 /* entry list */ 87 /* entry list */
88 char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); 88 char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
89 }; 89 };
90 90
91 /* used for the bitmask of struct ebt_entry */ 91 /* used for the bitmask of struct ebt_entry */
92 92
93 /* This is a hack to make a difference between an ebt_entry struct and an 93 /* This is a hack to make a difference between an ebt_entry struct and an
94 * ebt_entries struct when traversing the entries from start to end. 94 * ebt_entries struct when traversing the entries from start to end.
95 * Using this simplifies the code alot, while still being able to use 95 * Using this simplifies the code alot, while still being able to use
96 * ebt_entries. 96 * ebt_entries.
97 * Contrary, iptables doesn't use something like ebt_entries and therefore uses 97 * Contrary, iptables doesn't use something like ebt_entries and therefore uses
98 * different techniques for naming the policy and such. So, iptables doesn't 98 * different techniques for naming the policy and such. So, iptables doesn't
99 * need a hack like this. 99 * need a hack like this.
100 */ 100 */
101 #define EBT_ENTRY_OR_ENTRIES 0x01 101 #define EBT_ENTRY_OR_ENTRIES 0x01
102 /* these are the normal masks */ 102 /* these are the normal masks */
103 #define EBT_NOPROTO 0x02 103 #define EBT_NOPROTO 0x02
104 #define EBT_802_3 0x04 104 #define EBT_802_3 0x04
105 #define EBT_SOURCEMAC 0x08 105 #define EBT_SOURCEMAC 0x08
106 #define EBT_DESTMAC 0x10 106 #define EBT_DESTMAC 0x10
107 #define EBT_F_MASK (EBT_NOPROTO | EBT_802_3 | EBT_SOURCEMAC | EBT_DESTMAC \ 107 #define EBT_F_MASK (EBT_NOPROTO | EBT_802_3 | EBT_SOURCEMAC | EBT_DESTMAC \
108 | EBT_ENTRY_OR_ENTRIES) 108 | EBT_ENTRY_OR_ENTRIES)
109 109
110 #define EBT_IPROTO 0x01 110 #define EBT_IPROTO 0x01
111 #define EBT_IIN 0x02 111 #define EBT_IIN 0x02
112 #define EBT_IOUT 0x04 112 #define EBT_IOUT 0x04
113 #define EBT_ISOURCE 0x8 113 #define EBT_ISOURCE 0x8
114 #define EBT_IDEST 0x10 114 #define EBT_IDEST 0x10
115 #define EBT_ILOGICALIN 0x20 115 #define EBT_ILOGICALIN 0x20
116 #define EBT_ILOGICALOUT 0x40 116 #define EBT_ILOGICALOUT 0x40
117 #define EBT_INV_MASK (EBT_IPROTO | EBT_IIN | EBT_IOUT | EBT_ILOGICALIN \ 117 #define EBT_INV_MASK (EBT_IPROTO | EBT_IIN | EBT_IOUT | EBT_ILOGICALIN \
118 | EBT_ILOGICALOUT | EBT_ISOURCE | EBT_IDEST) 118 | EBT_ILOGICALOUT | EBT_ISOURCE | EBT_IDEST)
119 119
120 struct ebt_entry_match 120 struct ebt_entry_match
121 { 121 {
122 union { 122 union {
123 char name[EBT_FUNCTION_MAXNAMELEN]; 123 char name[EBT_FUNCTION_MAXNAMELEN];
124 struct ebt_match *match; 124 struct ebt_match *match;
125 } u; 125 } u;
126 /* size of data */ 126 /* size of data */
127 unsigned int match_size; 127 unsigned int match_size;
128 unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); 128 unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
129 }; 129 };
130 130
131 struct ebt_entry_watcher 131 struct ebt_entry_watcher
132 { 132 {
133 union { 133 union {
134 char name[EBT_FUNCTION_MAXNAMELEN]; 134 char name[EBT_FUNCTION_MAXNAMELEN];
135 struct ebt_watcher *watcher; 135 struct ebt_watcher *watcher;
136 } u; 136 } u;
137 /* size of data */ 137 /* size of data */
138 unsigned int watcher_size; 138 unsigned int watcher_size;
139 unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); 139 unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
140 }; 140 };
141 141
142 struct ebt_entry_target 142 struct ebt_entry_target
143 { 143 {
144 union { 144 union {
145 char name[EBT_FUNCTION_MAXNAMELEN]; 145 char name[EBT_FUNCTION_MAXNAMELEN];
146 struct ebt_target *target; 146 struct ebt_target *target;
147 } u; 147 } u;
148 /* size of data */ 148 /* size of data */
149 unsigned int target_size; 149 unsigned int target_size;
150 unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); 150 unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
151 }; 151 };
152 152
153 #define EBT_STANDARD_TARGET "standard" 153 #define EBT_STANDARD_TARGET "standard"
154 struct ebt_standard_target 154 struct ebt_standard_target
155 { 155 {
156 struct ebt_entry_target target; 156 struct ebt_entry_target target;
157 int verdict; 157 int verdict;
158 }; 158 };
159 159
160 /* one entry */ 160 /* one entry */
161 struct ebt_entry { 161 struct ebt_entry {
162 /* this needs to be the first field */ 162 /* this needs to be the first field */
163 unsigned int bitmask; 163 unsigned int bitmask;
164 unsigned int invflags; 164 unsigned int invflags;
165 __be16 ethproto; 165 __be16 ethproto;
166 /* the physical in-dev */ 166 /* the physical in-dev */
167 char in[IFNAMSIZ]; 167 char in[IFNAMSIZ];
168 /* the logical in-dev */ 168 /* the logical in-dev */
169 char logical_in[IFNAMSIZ]; 169 char logical_in[IFNAMSIZ];
170 /* the physical out-dev */ 170 /* the physical out-dev */
171 char out[IFNAMSIZ]; 171 char out[IFNAMSIZ];
172 /* the logical out-dev */ 172 /* the logical out-dev */
173 char logical_out[IFNAMSIZ]; 173 char logical_out[IFNAMSIZ];
174 unsigned char sourcemac[ETH_ALEN]; 174 unsigned char sourcemac[ETH_ALEN];
175 unsigned char sourcemsk[ETH_ALEN]; 175 unsigned char sourcemsk[ETH_ALEN];
176 unsigned char destmac[ETH_ALEN]; 176 unsigned char destmac[ETH_ALEN];
177 unsigned char destmsk[ETH_ALEN]; 177 unsigned char destmsk[ETH_ALEN];
178 /* sizeof ebt_entry + matches */ 178 /* sizeof ebt_entry + matches */
179 unsigned int watchers_offset; 179 unsigned int watchers_offset;
180 /* sizeof ebt_entry + matches + watchers */ 180 /* sizeof ebt_entry + matches + watchers */
181 unsigned int target_offset; 181 unsigned int target_offset;
182 /* sizeof ebt_entry + matches + watchers + target */ 182 /* sizeof ebt_entry + matches + watchers + target */
183 unsigned int next_offset; 183 unsigned int next_offset;
184 unsigned char elems[0] __attribute__ ((aligned (__alignof__(struct ebt_replace)))); 184 unsigned char elems[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
185 }; 185 };
186 186
187 /* {g,s}etsockopt numbers */ 187 /* {g,s}etsockopt numbers */
188 #define EBT_BASE_CTL 128 188 #define EBT_BASE_CTL 128
189 189
190 #define EBT_SO_SET_ENTRIES (EBT_BASE_CTL) 190 #define EBT_SO_SET_ENTRIES (EBT_BASE_CTL)
191 #define EBT_SO_SET_COUNTERS (EBT_SO_SET_ENTRIES+1) 191 #define EBT_SO_SET_COUNTERS (EBT_SO_SET_ENTRIES+1)
192 #define EBT_SO_SET_MAX (EBT_SO_SET_COUNTERS+1) 192 #define EBT_SO_SET_MAX (EBT_SO_SET_COUNTERS+1)
193 193
194 #define EBT_SO_GET_INFO (EBT_BASE_CTL) 194 #define EBT_SO_GET_INFO (EBT_BASE_CTL)
195 #define EBT_SO_GET_ENTRIES (EBT_SO_GET_INFO+1) 195 #define EBT_SO_GET_ENTRIES (EBT_SO_GET_INFO+1)
196 #define EBT_SO_GET_INIT_INFO (EBT_SO_GET_ENTRIES+1) 196 #define EBT_SO_GET_INIT_INFO (EBT_SO_GET_ENTRIES+1)
197 #define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO+1) 197 #define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO+1)
198 #define EBT_SO_GET_MAX (EBT_SO_GET_INIT_ENTRIES+1) 198 #define EBT_SO_GET_MAX (EBT_SO_GET_INIT_ENTRIES+1)
199 199
200 #ifdef __KERNEL__ 200 #ifdef __KERNEL__
201 201
202 /* return values for match() functions */ 202 /* return values for match() functions */
203 #define EBT_MATCH 0 203 #define EBT_MATCH 0
204 #define EBT_NOMATCH 1 204 #define EBT_NOMATCH 1
205 205
206 struct ebt_match 206 struct ebt_match
207 { 207 {
208 struct list_head list; 208 struct list_head list;
209 const char name[EBT_FUNCTION_MAXNAMELEN]; 209 const char name[EBT_FUNCTION_MAXNAMELEN];
210 /* 0 == it matches */ 210 /* 0 == it matches */
211 int (*match)(const struct sk_buff *skb, const struct net_device *in, 211 int (*match)(const struct sk_buff *skb, const struct net_device *in,
212 const struct net_device *out, const void *matchdata, 212 const struct net_device *out, const void *matchdata,
213 unsigned int datalen); 213 unsigned int datalen);
214 /* 0 == let it in */ 214 bool (*check)(const char *tablename, unsigned int hookmask,
215 int (*check)(const char *tablename, unsigned int hookmask,
216 const struct ebt_entry *e, void *matchdata, unsigned int datalen); 215 const struct ebt_entry *e, void *matchdata, unsigned int datalen);
217 void (*destroy)(void *matchdata, unsigned int datalen); 216 void (*destroy)(void *matchdata, unsigned int datalen);
218 unsigned int matchsize; 217 unsigned int matchsize;
219 struct module *me; 218 struct module *me;
220 }; 219 };
221 220
222 struct ebt_watcher 221 struct ebt_watcher
223 { 222 {
224 struct list_head list; 223 struct list_head list;
225 const char name[EBT_FUNCTION_MAXNAMELEN]; 224 const char name[EBT_FUNCTION_MAXNAMELEN];
226 void (*watcher)(const struct sk_buff *skb, unsigned int hooknr, 225 void (*watcher)(const struct sk_buff *skb, unsigned int hooknr,
227 const struct net_device *in, const struct net_device *out, 226 const struct net_device *in, const struct net_device *out,
228 const void *watcherdata, unsigned int datalen); 227 const void *watcherdata, unsigned int datalen);
229 /* 0 == let it in */ 228 bool (*check)(const char *tablename, unsigned int hookmask,
230 int (*check)(const char *tablename, unsigned int hookmask,
231 const struct ebt_entry *e, void *watcherdata, unsigned int datalen); 229 const struct ebt_entry *e, void *watcherdata, unsigned int datalen);
232 void (*destroy)(void *watcherdata, unsigned int datalen); 230 void (*destroy)(void *watcherdata, unsigned int datalen);
233 unsigned int targetsize; 231 unsigned int targetsize;
234 struct module *me; 232 struct module *me;
235 }; 233 };
236 234
237 struct ebt_target 235 struct ebt_target
238 { 236 {
239 struct list_head list; 237 struct list_head list;
240 const char name[EBT_FUNCTION_MAXNAMELEN]; 238 const char name[EBT_FUNCTION_MAXNAMELEN];
241 /* returns one of the standard verdicts */ 239 /* returns one of the standard verdicts */
242 int (*target)(struct sk_buff *skb, unsigned int hooknr, 240 int (*target)(struct sk_buff *skb, unsigned int hooknr,
243 const struct net_device *in, const struct net_device *out, 241 const struct net_device *in, const struct net_device *out,
244 const void *targetdata, unsigned int datalen); 242 const void *targetdata, unsigned int datalen);
245 /* 0 == let it in */ 243 bool (*check)(const char *tablename, unsigned int hookmask,
246 int (*check)(const char *tablename, unsigned int hookmask,
247 const struct ebt_entry *e, void *targetdata, unsigned int datalen); 244 const struct ebt_entry *e, void *targetdata, unsigned int datalen);
248 void (*destroy)(void *targetdata, unsigned int datalen); 245 void (*destroy)(void *targetdata, unsigned int datalen);
249 unsigned int targetsize; 246 unsigned int targetsize;
250 struct module *me; 247 struct module *me;
251 }; 248 };
252 249
253 /* used for jumping from and into user defined chains (udc) */ 250 /* used for jumping from and into user defined chains (udc) */
254 struct ebt_chainstack 251 struct ebt_chainstack
255 { 252 {
256 struct ebt_entries *chaininfo; /* pointer to chain data */ 253 struct ebt_entries *chaininfo; /* pointer to chain data */
257 struct ebt_entry *e; /* pointer to entry data */ 254 struct ebt_entry *e; /* pointer to entry data */
258 unsigned int n; /* n'th entry */ 255 unsigned int n; /* n'th entry */
259 }; 256 };
260 257
261 struct ebt_table_info 258 struct ebt_table_info
262 { 259 {
263 /* total size of the entries */ 260 /* total size of the entries */
264 unsigned int entries_size; 261 unsigned int entries_size;
265 unsigned int nentries; 262 unsigned int nentries;
266 /* pointers to the start of the chains */ 263 /* pointers to the start of the chains */
267 struct ebt_entries *hook_entry[NF_BR_NUMHOOKS]; 264 struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
268 /* room to maintain the stack used for jumping from and into udc */ 265 /* room to maintain the stack used for jumping from and into udc */
269 struct ebt_chainstack **chainstack; 266 struct ebt_chainstack **chainstack;
270 char *entries; 267 char *entries;
271 struct ebt_counter counters[0] ____cacheline_aligned; 268 struct ebt_counter counters[0] ____cacheline_aligned;
272 }; 269 };
273 270
274 struct ebt_table 271 struct ebt_table
275 { 272 {
276 struct list_head list; 273 struct list_head list;
277 char name[EBT_TABLE_MAXNAMELEN]; 274 char name[EBT_TABLE_MAXNAMELEN];
278 struct ebt_replace_kernel *table; 275 struct ebt_replace_kernel *table;
279 unsigned int valid_hooks; 276 unsigned int valid_hooks;
280 rwlock_t lock; 277 rwlock_t lock;
281 /* e.g. could be the table explicitly only allows certain 278 /* e.g. could be the table explicitly only allows certain
282 * matches, targets, ... 0 == let it in */ 279 * matches, targets, ... 0 == let it in */
283 int (*check)(const struct ebt_table_info *info, 280 int (*check)(const struct ebt_table_info *info,
284 unsigned int valid_hooks); 281 unsigned int valid_hooks);
285 /* the data used by the kernel */ 282 /* the data used by the kernel */
286 struct ebt_table_info *private; 283 struct ebt_table_info *private;
287 struct module *me; 284 struct module *me;
288 }; 285 };
289 286
290 #define EBT_ALIGN(s) (((s) + (__alignof__(struct ebt_replace)-1)) & \ 287 #define EBT_ALIGN(s) (((s) + (__alignof__(struct ebt_replace)-1)) & \
291 ~(__alignof__(struct ebt_replace)-1)) 288 ~(__alignof__(struct ebt_replace)-1))
292 extern int ebt_register_table(struct ebt_table *table); 289 extern int ebt_register_table(struct ebt_table *table);
293 extern void ebt_unregister_table(struct ebt_table *table); 290 extern void ebt_unregister_table(struct ebt_table *table);
294 extern int ebt_register_match(struct ebt_match *match); 291 extern int ebt_register_match(struct ebt_match *match);
295 extern void ebt_unregister_match(struct ebt_match *match); 292 extern void ebt_unregister_match(struct ebt_match *match);
296 extern int ebt_register_watcher(struct ebt_watcher *watcher); 293 extern int ebt_register_watcher(struct ebt_watcher *watcher);
297 extern void ebt_unregister_watcher(struct ebt_watcher *watcher); 294 extern void ebt_unregister_watcher(struct ebt_watcher *watcher);
298 extern int ebt_register_target(struct ebt_target *target); 295 extern int ebt_register_target(struct ebt_target *target);
299 extern void ebt_unregister_target(struct ebt_target *target); 296 extern void ebt_unregister_target(struct ebt_target *target);
300 extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb, 297 extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb,
301 const struct net_device *in, const struct net_device *out, 298 const struct net_device *in, const struct net_device *out,
302 struct ebt_table *table); 299 struct ebt_table *table);
303 300
304 /* Used in the kernel match() functions */ 301 /* Used in the kernel match() functions */
305 #define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg)) 302 #define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg))
306 /* True if the hook mask denotes that the rule is in a base chain, 303 /* True if the hook mask denotes that the rule is in a base chain,
307 * used in the check() functions */ 304 * used in the check() functions */
308 #define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS)) 305 #define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS))
309 /* Clear the bit in the hook mask that tells if the rule is on a base chain */ 306 /* Clear the bit in the hook mask that tells if the rule is on a base chain */
310 #define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS)) 307 #define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS))
311 /* True if the target is not a standard target */ 308 /* True if the target is not a standard target */
312 #define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0) 309 #define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0)
313 310
314 #endif /* __KERNEL__ */ 311 #endif /* __KERNEL__ */
315 312
316 /* blatently stolen from ip_tables.h 313 /* blatently stolen from ip_tables.h
317 * fn returns 0 to continue iteration */ 314 * fn returns 0 to continue iteration */
318 #define EBT_MATCH_ITERATE(e, fn, args...) \ 315 #define EBT_MATCH_ITERATE(e, fn, args...) \
319 ({ \ 316 ({ \
320 unsigned int __i; \ 317 unsigned int __i; \
321 int __ret = 0; \ 318 int __ret = 0; \
322 struct ebt_entry_match *__match; \ 319 struct ebt_entry_match *__match; \
323 \ 320 \
324 for (__i = sizeof(struct ebt_entry); \ 321 for (__i = sizeof(struct ebt_entry); \
325 __i < (e)->watchers_offset; \ 322 __i < (e)->watchers_offset; \
326 __i += __match->match_size + \ 323 __i += __match->match_size + \
327 sizeof(struct ebt_entry_match)) { \ 324 sizeof(struct ebt_entry_match)) { \
328 __match = (void *)(e) + __i; \ 325 __match = (void *)(e) + __i; \
329 \ 326 \
330 __ret = fn(__match , ## args); \ 327 __ret = fn(__match , ## args); \
331 if (__ret != 0) \ 328 if (__ret != 0) \
332 break; \ 329 break; \
333 } \ 330 } \
334 if (__ret == 0) { \ 331 if (__ret == 0) { \
335 if (__i != (e)->watchers_offset) \ 332 if (__i != (e)->watchers_offset) \
336 __ret = -EINVAL; \ 333 __ret = -EINVAL; \
337 } \ 334 } \
338 __ret; \ 335 __ret; \
339 }) 336 })
340 337
341 #define EBT_WATCHER_ITERATE(e, fn, args...) \ 338 #define EBT_WATCHER_ITERATE(e, fn, args...) \
342 ({ \ 339 ({ \
343 unsigned int __i; \ 340 unsigned int __i; \
344 int __ret = 0; \ 341 int __ret = 0; \
345 struct ebt_entry_watcher *__watcher; \ 342 struct ebt_entry_watcher *__watcher; \
346 \ 343 \
347 for (__i = e->watchers_offset; \ 344 for (__i = e->watchers_offset; \
348 __i < (e)->target_offset; \ 345 __i < (e)->target_offset; \
349 __i += __watcher->watcher_size + \ 346 __i += __watcher->watcher_size + \
350 sizeof(struct ebt_entry_watcher)) { \ 347 sizeof(struct ebt_entry_watcher)) { \
351 __watcher = (void *)(e) + __i; \ 348 __watcher = (void *)(e) + __i; \
352 \ 349 \
353 __ret = fn(__watcher , ## args); \ 350 __ret = fn(__watcher , ## args); \
354 if (__ret != 0) \ 351 if (__ret != 0) \
355 break; \ 352 break; \
356 } \ 353 } \
357 if (__ret == 0) { \ 354 if (__ret == 0) { \
358 if (__i != (e)->target_offset) \ 355 if (__i != (e)->target_offset) \
359 __ret = -EINVAL; \ 356 __ret = -EINVAL; \
360 } \ 357 } \
361 __ret; \ 358 __ret; \
362 }) 359 })
363 360
364 #define EBT_ENTRY_ITERATE(entries, size, fn, args...) \ 361 #define EBT_ENTRY_ITERATE(entries, size, fn, args...) \
365 ({ \ 362 ({ \
366 unsigned int __i; \ 363 unsigned int __i; \
367 int __ret = 0; \ 364 int __ret = 0; \
368 struct ebt_entry *__entry; \ 365 struct ebt_entry *__entry; \
369 \ 366 \
370 for (__i = 0; __i < (size);) { \ 367 for (__i = 0; __i < (size);) { \
371 __entry = (void *)(entries) + __i; \ 368 __entry = (void *)(entries) + __i; \
372 __ret = fn(__entry , ## args); \ 369 __ret = fn(__entry , ## args); \
373 if (__ret != 0) \ 370 if (__ret != 0) \
374 break; \ 371 break; \
375 if (__entry->bitmask != 0) \ 372 if (__entry->bitmask != 0) \
376 __i += __entry->next_offset; \ 373 __i += __entry->next_offset; \
377 else \ 374 else \
378 __i += sizeof(struct ebt_entries); \ 375 __i += sizeof(struct ebt_entries); \
379 } \ 376 } \
380 if (__ret == 0) { \ 377 if (__ret == 0) { \
381 if (__i != (size)) \ 378 if (__i != (size)) \
382 __ret = -EINVAL; \ 379 __ret = -EINVAL; \
383 } \ 380 } \
384 __ret; \ 381 __ret; \
385 }) 382 })
386 383
387 #endif 384 #endif
388 385
net/bridge/netfilter/ebt_802_3.c
1 /* 1 /*
2 * 802_3 2 * 802_3
3 * 3 *
4 * Author: 4 * Author:
5 * Chris Vitale csv@bluetail.com 5 * Chris Vitale csv@bluetail.com
6 * 6 *
7 * May 2003 7 * May 2003
8 * 8 *
9 */ 9 */
10 #include <linux/module.h> 10 #include <linux/module.h>
11 #include <linux/netfilter/x_tables.h> 11 #include <linux/netfilter/x_tables.h>
12 #include <linux/netfilter_bridge/ebtables.h> 12 #include <linux/netfilter_bridge/ebtables.h>
13 #include <linux/netfilter_bridge/ebt_802_3.h> 13 #include <linux/netfilter_bridge/ebt_802_3.h>
14 14
15 static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device *in, 15 static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device *in,
16 const struct net_device *out, const void *data, unsigned int datalen) 16 const struct net_device *out, const void *data, unsigned int datalen)
17 { 17 {
18 const struct ebt_802_3_info *info = data; 18 const struct ebt_802_3_info *info = data;
19 const struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb); 19 const struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb);
20 __be16 type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type; 20 __be16 type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;
21 21
22 if (info->bitmask & EBT_802_3_SAP) { 22 if (info->bitmask & EBT_802_3_SAP) {
23 if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP)) 23 if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP))
24 return EBT_NOMATCH; 24 return EBT_NOMATCH;
25 if (FWINV(info->sap != hdr->llc.ui.dsap, EBT_802_3_SAP)) 25 if (FWINV(info->sap != hdr->llc.ui.dsap, EBT_802_3_SAP))
26 return EBT_NOMATCH; 26 return EBT_NOMATCH;
27 } 27 }
28 28
29 if (info->bitmask & EBT_802_3_TYPE) { 29 if (info->bitmask & EBT_802_3_TYPE) {
30 if (!(hdr->llc.ui.dsap == CHECK_TYPE && hdr->llc.ui.ssap == CHECK_TYPE)) 30 if (!(hdr->llc.ui.dsap == CHECK_TYPE && hdr->llc.ui.ssap == CHECK_TYPE))
31 return EBT_NOMATCH; 31 return EBT_NOMATCH;
32 if (FWINV(info->type != type, EBT_802_3_TYPE)) 32 if (FWINV(info->type != type, EBT_802_3_TYPE))
33 return EBT_NOMATCH; 33 return EBT_NOMATCH;
34 } 34 }
35 35
36 return EBT_MATCH; 36 return EBT_MATCH;
37 } 37 }
38 38
39 static struct ebt_match filter_802_3; 39 static struct ebt_match filter_802_3;
40 static int ebt_802_3_check(const char *tablename, unsigned int hookmask, 40 static bool ebt_802_3_check(const char *tablename, unsigned int hookmask,
41 const struct ebt_entry *e, void *data, unsigned int datalen) 41 const struct ebt_entry *e, void *data, unsigned int datalen)
42 { 42 {
43 const struct ebt_802_3_info *info = data; 43 const struct ebt_802_3_info *info = data;
44 44
45 if (info->bitmask & ~EBT_802_3_MASK || info->invflags & ~EBT_802_3_MASK) 45 if (info->bitmask & ~EBT_802_3_MASK || info->invflags & ~EBT_802_3_MASK)
46 return -EINVAL; 46 return false;
47 47
48 return 0; 48 return true;
49 } 49 }
50 50
51 static struct ebt_match filter_802_3 __read_mostly = { 51 static struct ebt_match filter_802_3 __read_mostly = {
52 .name = EBT_802_3_MATCH, 52 .name = EBT_802_3_MATCH,
53 .match = ebt_filter_802_3, 53 .match = ebt_filter_802_3,
54 .check = ebt_802_3_check, 54 .check = ebt_802_3_check,
55 .matchsize = XT_ALIGN(sizeof(struct ebt_802_3_info)), 55 .matchsize = XT_ALIGN(sizeof(struct ebt_802_3_info)),
56 .me = THIS_MODULE, 56 .me = THIS_MODULE,
57 }; 57 };
58 58
59 static int __init ebt_802_3_init(void) 59 static int __init ebt_802_3_init(void)
60 { 60 {
61 return ebt_register_match(&filter_802_3); 61 return ebt_register_match(&filter_802_3);
62 } 62 }
63 63
64 static void __exit ebt_802_3_fini(void) 64 static void __exit ebt_802_3_fini(void)
65 { 65 {
66 ebt_unregister_match(&filter_802_3); 66 ebt_unregister_match(&filter_802_3);
67 } 67 }
68 68
69 module_init(ebt_802_3_init); 69 module_init(ebt_802_3_init);
70 module_exit(ebt_802_3_fini); 70 module_exit(ebt_802_3_fini);
71 MODULE_DESCRIPTION("Ebtables: DSAP/SSAP field and SNAP type matching"); 71 MODULE_DESCRIPTION("Ebtables: DSAP/SSAP field and SNAP type matching");
72 MODULE_LICENSE("GPL"); 72 MODULE_LICENSE("GPL");
73 73
net/bridge/netfilter/ebt_among.c
1 /* 1 /*
2 * ebt_among 2 * ebt_among
3 * 3 *
4 * Authors: 4 * Authors:
5 * Grzegorz Borowiak <grzes@gnu.univ.gda.pl> 5 * Grzegorz Borowiak <grzes@gnu.univ.gda.pl>
6 * 6 *
7 * August, 2003 7 * August, 2003
8 * 8 *
9 */ 9 */
10 10
11 #include <linux/netfilter_bridge/ebtables.h> 11 #include <linux/netfilter_bridge/ebtables.h>
12 #include <linux/netfilter_bridge/ebt_among.h> 12 #include <linux/netfilter_bridge/ebt_among.h>
13 #include <linux/ip.h> 13 #include <linux/ip.h>
14 #include <linux/if_arp.h> 14 #include <linux/if_arp.h>
15 #include <linux/module.h> 15 #include <linux/module.h>
16 16
17 static int ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh, 17 static int ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh,
18 const char *mac, __be32 ip) 18 const char *mac, __be32 ip)
19 { 19 {
20 /* You may be puzzled as to how this code works. 20 /* You may be puzzled as to how this code works.
21 * Some tricks were used, refer to 21 * Some tricks were used, refer to
22 * include/linux/netfilter_bridge/ebt_among.h 22 * include/linux/netfilter_bridge/ebt_among.h
23 * as there you can find a solution of this mystery. 23 * as there you can find a solution of this mystery.
24 */ 24 */
25 const struct ebt_mac_wormhash_tuple *p; 25 const struct ebt_mac_wormhash_tuple *p;
26 int start, limit, i; 26 int start, limit, i;
27 uint32_t cmp[2] = { 0, 0 }; 27 uint32_t cmp[2] = { 0, 0 };
28 int key = ((const unsigned char *)mac)[5]; 28 int key = ((const unsigned char *)mac)[5];
29 29
30 memcpy(((char *) cmp) + 2, mac, 6); 30 memcpy(((char *) cmp) + 2, mac, 6);
31 start = wh->table[key]; 31 start = wh->table[key];
32 limit = wh->table[key + 1]; 32 limit = wh->table[key + 1];
33 if (ip) { 33 if (ip) {
34 for (i = start; i < limit; i++) { 34 for (i = start; i < limit; i++) {
35 p = &wh->pool[i]; 35 p = &wh->pool[i];
36 if (cmp[1] == p->cmp[1] && cmp[0] == p->cmp[0]) { 36 if (cmp[1] == p->cmp[1] && cmp[0] == p->cmp[0]) {
37 if (p->ip == 0 || p->ip == ip) { 37 if (p->ip == 0 || p->ip == ip) {
38 return 1; 38 return 1;
39 } 39 }
40 } 40 }
41 } 41 }
42 } else { 42 } else {
43 for (i = start; i < limit; i++) { 43 for (i = start; i < limit; i++) {
44 p = &wh->pool[i]; 44 p = &wh->pool[i];
45 if (cmp[1] == p->cmp[1] && cmp[0] == p->cmp[0]) { 45 if (cmp[1] == p->cmp[1] && cmp[0] == p->cmp[0]) {
46 if (p->ip == 0) { 46 if (p->ip == 0) {
47 return 1; 47 return 1;
48 } 48 }
49 } 49 }
50 } 50 }
51 } 51 }
52 return 0; 52 return 0;
53 } 53 }
54 54
55 static int ebt_mac_wormhash_check_integrity(const struct ebt_mac_wormhash 55 static int ebt_mac_wormhash_check_integrity(const struct ebt_mac_wormhash
56 *wh) 56 *wh)
57 { 57 {
58 int i; 58 int i;
59 59
60 for (i = 0; i < 256; i++) { 60 for (i = 0; i < 256; i++) {
61 if (wh->table[i] > wh->table[i + 1]) 61 if (wh->table[i] > wh->table[i + 1])
62 return -0x100 - i; 62 return -0x100 - i;
63 if (wh->table[i] < 0) 63 if (wh->table[i] < 0)
64 return -0x200 - i; 64 return -0x200 - i;
65 if (wh->table[i] > wh->poolsize) 65 if (wh->table[i] > wh->poolsize)
66 return -0x300 - i; 66 return -0x300 - i;
67 } 67 }
68 if (wh->table[256] > wh->poolsize) 68 if (wh->table[256] > wh->poolsize)
69 return -0xc00; 69 return -0xc00;
70 return 0; 70 return 0;
71 } 71 }
72 72
73 static int get_ip_dst(const struct sk_buff *skb, __be32 *addr) 73 static int get_ip_dst(const struct sk_buff *skb, __be32 *addr)
74 { 74 {
75 if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) { 75 if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
76 const struct iphdr *ih; 76 const struct iphdr *ih;
77 struct iphdr _iph; 77 struct iphdr _iph;
78 78
79 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); 79 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
80 if (ih == NULL) 80 if (ih == NULL)
81 return -1; 81 return -1;
82 *addr = ih->daddr; 82 *addr = ih->daddr;
83 } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { 83 } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
84 const struct arphdr *ah; 84 const struct arphdr *ah;
85 struct arphdr _arph; 85 struct arphdr _arph;
86 const __be32 *bp; 86 const __be32 *bp;
87 __be32 buf; 87 __be32 buf;
88 88
89 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); 89 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
90 if (ah == NULL || 90 if (ah == NULL ||
91 ah->ar_pln != sizeof(__be32) || 91 ah->ar_pln != sizeof(__be32) ||
92 ah->ar_hln != ETH_ALEN) 92 ah->ar_hln != ETH_ALEN)
93 return -1; 93 return -1;
94 bp = skb_header_pointer(skb, sizeof(struct arphdr) + 94 bp = skb_header_pointer(skb, sizeof(struct arphdr) +
95 2 * ETH_ALEN + sizeof(__be32), 95 2 * ETH_ALEN + sizeof(__be32),
96 sizeof(__be32), &buf); 96 sizeof(__be32), &buf);
97 if (bp == NULL) 97 if (bp == NULL)
98 return -1; 98 return -1;
99 *addr = *bp; 99 *addr = *bp;
100 } 100 }
101 return 0; 101 return 0;
102 } 102 }
103 103
104 static int get_ip_src(const struct sk_buff *skb, __be32 *addr) 104 static int get_ip_src(const struct sk_buff *skb, __be32 *addr)
105 { 105 {
106 if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) { 106 if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
107 const struct iphdr *ih; 107 const struct iphdr *ih;
108 struct iphdr _iph; 108 struct iphdr _iph;
109 109
110 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); 110 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
111 if (ih == NULL) 111 if (ih == NULL)
112 return -1; 112 return -1;
113 *addr = ih->saddr; 113 *addr = ih->saddr;
114 } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { 114 } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
115 const struct arphdr *ah; 115 const struct arphdr *ah;
116 struct arphdr _arph; 116 struct arphdr _arph;
117 const __be32 *bp; 117 const __be32 *bp;
118 __be32 buf; 118 __be32 buf;
119 119
120 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); 120 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
121 if (ah == NULL || 121 if (ah == NULL ||
122 ah->ar_pln != sizeof(__be32) || 122 ah->ar_pln != sizeof(__be32) ||
123 ah->ar_hln != ETH_ALEN) 123 ah->ar_hln != ETH_ALEN)
124 return -1; 124 return -1;
125 bp = skb_header_pointer(skb, sizeof(struct arphdr) + 125 bp = skb_header_pointer(skb, sizeof(struct arphdr) +
126 ETH_ALEN, sizeof(__be32), &buf); 126 ETH_ALEN, sizeof(__be32), &buf);
127 if (bp == NULL) 127 if (bp == NULL)
128 return -1; 128 return -1;
129 *addr = *bp; 129 *addr = *bp;
130 } 130 }
131 return 0; 131 return 0;
132 } 132 }
133 133
134 static int ebt_filter_among(const struct sk_buff *skb, 134 static int ebt_filter_among(const struct sk_buff *skb,
135 const struct net_device *in, 135 const struct net_device *in,
136 const struct net_device *out, const void *data, 136 const struct net_device *out, const void *data,
137 unsigned int datalen) 137 unsigned int datalen)
138 { 138 {
139 const struct ebt_among_info *info = data; 139 const struct ebt_among_info *info = data;
140 const char *dmac, *smac; 140 const char *dmac, *smac;
141 const struct ebt_mac_wormhash *wh_dst, *wh_src; 141 const struct ebt_mac_wormhash *wh_dst, *wh_src;
142 __be32 dip = 0, sip = 0; 142 __be32 dip = 0, sip = 0;
143 143
144 wh_dst = ebt_among_wh_dst(info); 144 wh_dst = ebt_among_wh_dst(info);
145 wh_src = ebt_among_wh_src(info); 145 wh_src = ebt_among_wh_src(info);
146 146
147 if (wh_src) { 147 if (wh_src) {
148 smac = eth_hdr(skb)->h_source; 148 smac = eth_hdr(skb)->h_source;
149 if (get_ip_src(skb, &sip)) 149 if (get_ip_src(skb, &sip))
150 return EBT_NOMATCH; 150 return EBT_NOMATCH;
151 if (!(info->bitmask & EBT_AMONG_SRC_NEG)) { 151 if (!(info->bitmask & EBT_AMONG_SRC_NEG)) {
152 /* we match only if it contains */ 152 /* we match only if it contains */
153 if (!ebt_mac_wormhash_contains(wh_src, smac, sip)) 153 if (!ebt_mac_wormhash_contains(wh_src, smac, sip))
154 return EBT_NOMATCH; 154 return EBT_NOMATCH;
155 } else { 155 } else {
156 /* we match only if it DOES NOT contain */ 156 /* we match only if it DOES NOT contain */
157 if (ebt_mac_wormhash_contains(wh_src, smac, sip)) 157 if (ebt_mac_wormhash_contains(wh_src, smac, sip))
158 return EBT_NOMATCH; 158 return EBT_NOMATCH;
159 } 159 }
160 } 160 }
161 161
162 if (wh_dst) { 162 if (wh_dst) {
163 dmac = eth_hdr(skb)->h_dest; 163 dmac = eth_hdr(skb)->h_dest;
164 if (get_ip_dst(skb, &dip)) 164 if (get_ip_dst(skb, &dip))
165 return EBT_NOMATCH; 165 return EBT_NOMATCH;
166 if (!(info->bitmask & EBT_AMONG_DST_NEG)) { 166 if (!(info->bitmask & EBT_AMONG_DST_NEG)) {
167 /* we match only if it contains */ 167 /* we match only if it contains */
168 if (!ebt_mac_wormhash_contains(wh_dst, dmac, dip)) 168 if (!ebt_mac_wormhash_contains(wh_dst, dmac, dip))
169 return EBT_NOMATCH; 169 return EBT_NOMATCH;
170 } else { 170 } else {
171 /* we match only if it DOES NOT contain */ 171 /* we match only if it DOES NOT contain */
172 if (ebt_mac_wormhash_contains(wh_dst, dmac, dip)) 172 if (ebt_mac_wormhash_contains(wh_dst, dmac, dip))
173 return EBT_NOMATCH; 173 return EBT_NOMATCH;
174 } 174 }
175 } 175 }
176 176
177 return EBT_MATCH; 177 return EBT_MATCH;
178 } 178 }
179 179
180 static int ebt_among_check(const char *tablename, unsigned int hookmask, 180 static bool
181 const struct ebt_entry *e, void *data, 181 ebt_among_check(const char *tablename, unsigned int hookmask,
182 unsigned int datalen) 182 const struct ebt_entry *e, void *data,
183 unsigned int datalen)
183 { 184 {
184 const struct ebt_among_info *info = data; 185 const struct ebt_among_info *info = data;
185 int expected_length = sizeof(struct ebt_among_info); 186 int expected_length = sizeof(struct ebt_among_info);
186 const struct ebt_mac_wormhash *wh_dst, *wh_src; 187 const struct ebt_mac_wormhash *wh_dst, *wh_src;
187 int err; 188 int err;
188 189
189 wh_dst = ebt_among_wh_dst(info); 190 wh_dst = ebt_among_wh_dst(info);
190 wh_src = ebt_among_wh_src(info); 191 wh_src = ebt_among_wh_src(info);
191 expected_length += ebt_mac_wormhash_size(wh_dst); 192 expected_length += ebt_mac_wormhash_size(wh_dst);
192 expected_length += ebt_mac_wormhash_size(wh_src); 193 expected_length += ebt_mac_wormhash_size(wh_src);
193 194
194 if (datalen != EBT_ALIGN(expected_length)) { 195 if (datalen != EBT_ALIGN(expected_length)) {
195 printk(KERN_WARNING 196 printk(KERN_WARNING
196 "ebtables: among: wrong size: %d " 197 "ebtables: among: wrong size: %d "
197 "against expected %d, rounded to %Zd\n", 198 "against expected %d, rounded to %Zd\n",
198 datalen, expected_length, 199 datalen, expected_length,
199 EBT_ALIGN(expected_length)); 200 EBT_ALIGN(expected_length));
200 return -EINVAL; 201 return false;
201 } 202 }
202 if (wh_dst && (err = ebt_mac_wormhash_check_integrity(wh_dst))) { 203 if (wh_dst && (err = ebt_mac_wormhash_check_integrity(wh_dst))) {
203 printk(KERN_WARNING 204 printk(KERN_WARNING
204 "ebtables: among: dst integrity fail: %x\n", -err); 205 "ebtables: among: dst integrity fail: %x\n", -err);
205 return -EINVAL; 206 return false;
206 } 207 }
207 if (wh_src && (err = ebt_mac_wormhash_check_integrity(wh_src))) { 208 if (wh_src && (err = ebt_mac_wormhash_check_integrity(wh_src))) {
208 printk(KERN_WARNING 209 printk(KERN_WARNING
209 "ebtables: among: src integrity fail: %x\n", -err); 210 "ebtables: among: src integrity fail: %x\n", -err);
210 return -EINVAL; 211 return false;
211 } 212 }
212 return 0; 213 return true;
213 } 214 }
214 215
215 static struct ebt_match filter_among __read_mostly = { 216 static struct ebt_match filter_among __read_mostly = {
216 .name = EBT_AMONG_MATCH, 217 .name = EBT_AMONG_MATCH,
217 .match = ebt_filter_among, 218 .match = ebt_filter_among,
218 .check = ebt_among_check, 219 .check = ebt_among_check,
219 .matchsize = -1, /* special case */ 220 .matchsize = -1, /* special case */
220 .me = THIS_MODULE, 221 .me = THIS_MODULE,
221 }; 222 };
222 223
223 static int __init ebt_among_init(void) 224 static int __init ebt_among_init(void)
224 { 225 {
225 return ebt_register_match(&filter_among); 226 return ebt_register_match(&filter_among);
226 } 227 }
227 228
228 static void __exit ebt_among_fini(void) 229 static void __exit ebt_among_fini(void)
229 { 230 {
230 ebt_unregister_match(&filter_among); 231 ebt_unregister_match(&filter_among);
231 } 232 }
232 233
233 module_init(ebt_among_init); 234 module_init(ebt_among_init);
234 module_exit(ebt_among_fini); 235 module_exit(ebt_among_fini);
235 MODULE_DESCRIPTION("Ebtables: Combined MAC/IP address list matching"); 236 MODULE_DESCRIPTION("Ebtables: Combined MAC/IP address list matching");
236 MODULE_LICENSE("GPL"); 237 MODULE_LICENSE("GPL");
237 238
net/bridge/netfilter/ebt_arp.c
1 /* 1 /*
2 * ebt_arp 2 * ebt_arp
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * Tim Gardner <timg@tpi.com> 6 * Tim Gardner <timg@tpi.com>
7 * 7 *
8 * April, 2002 8 * April, 2002
9 * 9 *
10 */ 10 */
11 #include <linux/if_arp.h> 11 #include <linux/if_arp.h>
12 #include <linux/if_ether.h> 12 #include <linux/if_ether.h>
13 #include <linux/module.h> 13 #include <linux/module.h>
14 #include <linux/netfilter/x_tables.h> 14 #include <linux/netfilter/x_tables.h>
15 #include <linux/netfilter_bridge/ebtables.h> 15 #include <linux/netfilter_bridge/ebtables.h>
16 #include <linux/netfilter_bridge/ebt_arp.h> 16 #include <linux/netfilter_bridge/ebt_arp.h>
17 17
18 static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in, 18 static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in,
19 const struct net_device *out, const void *data, unsigned int datalen) 19 const struct net_device *out, const void *data, unsigned int datalen)
20 { 20 {
21 const struct ebt_arp_info *info = data; 21 const struct ebt_arp_info *info = data;
22 const struct arphdr *ah; 22 const struct arphdr *ah;
23 struct arphdr _arph; 23 struct arphdr _arph;
24 24
25 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); 25 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
26 if (ah == NULL) 26 if (ah == NULL)
27 return EBT_NOMATCH; 27 return EBT_NOMATCH;
28 if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode != 28 if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode !=
29 ah->ar_op, EBT_ARP_OPCODE)) 29 ah->ar_op, EBT_ARP_OPCODE))
30 return EBT_NOMATCH; 30 return EBT_NOMATCH;
31 if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype != 31 if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype !=
32 ah->ar_hrd, EBT_ARP_HTYPE)) 32 ah->ar_hrd, EBT_ARP_HTYPE))
33 return EBT_NOMATCH; 33 return EBT_NOMATCH;
34 if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype != 34 if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype !=
35 ah->ar_pro, EBT_ARP_PTYPE)) 35 ah->ar_pro, EBT_ARP_PTYPE))
36 return EBT_NOMATCH; 36 return EBT_NOMATCH;
37 37
38 if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_GRAT)) { 38 if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_GRAT)) {
39 const __be32 *sap, *dap; 39 const __be32 *sap, *dap;
40 __be32 saddr, daddr; 40 __be32 saddr, daddr;
41 41
42 if (ah->ar_pln != sizeof(__be32) || ah->ar_pro != htons(ETH_P_IP)) 42 if (ah->ar_pln != sizeof(__be32) || ah->ar_pro != htons(ETH_P_IP))
43 return EBT_NOMATCH; 43 return EBT_NOMATCH;
44 sap = skb_header_pointer(skb, sizeof(struct arphdr) + 44 sap = skb_header_pointer(skb, sizeof(struct arphdr) +
45 ah->ar_hln, sizeof(saddr), 45 ah->ar_hln, sizeof(saddr),
46 &saddr); 46 &saddr);
47 if (sap == NULL) 47 if (sap == NULL)
48 return EBT_NOMATCH; 48 return EBT_NOMATCH;
49 dap = skb_header_pointer(skb, sizeof(struct arphdr) + 49 dap = skb_header_pointer(skb, sizeof(struct arphdr) +
50 2*ah->ar_hln+sizeof(saddr), 50 2*ah->ar_hln+sizeof(saddr),
51 sizeof(daddr), &daddr); 51 sizeof(daddr), &daddr);
52 if (dap == NULL) 52 if (dap == NULL)
53 return EBT_NOMATCH; 53 return EBT_NOMATCH;
54 if (info->bitmask & EBT_ARP_SRC_IP && 54 if (info->bitmask & EBT_ARP_SRC_IP &&
55 FWINV(info->saddr != (*sap & info->smsk), EBT_ARP_SRC_IP)) 55 FWINV(info->saddr != (*sap & info->smsk), EBT_ARP_SRC_IP))
56 return EBT_NOMATCH; 56 return EBT_NOMATCH;
57 if (info->bitmask & EBT_ARP_DST_IP && 57 if (info->bitmask & EBT_ARP_DST_IP &&
58 FWINV(info->daddr != (*dap & info->dmsk), EBT_ARP_DST_IP)) 58 FWINV(info->daddr != (*dap & info->dmsk), EBT_ARP_DST_IP))
59 return EBT_NOMATCH; 59 return EBT_NOMATCH;
60 if (info->bitmask & EBT_ARP_GRAT && 60 if (info->bitmask & EBT_ARP_GRAT &&
61 FWINV(*dap != *sap, EBT_ARP_GRAT)) 61 FWINV(*dap != *sap, EBT_ARP_GRAT))
62 return EBT_NOMATCH; 62 return EBT_NOMATCH;
63 } 63 }
64 64
65 if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) { 65 if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) {
66 const unsigned char *mp; 66 const unsigned char *mp;
67 unsigned char _mac[ETH_ALEN]; 67 unsigned char _mac[ETH_ALEN];
68 uint8_t verdict, i; 68 uint8_t verdict, i;
69 69
70 if (ah->ar_hln != ETH_ALEN || ah->ar_hrd != htons(ARPHRD_ETHER)) 70 if (ah->ar_hln != ETH_ALEN || ah->ar_hrd != htons(ARPHRD_ETHER))
71 return EBT_NOMATCH; 71 return EBT_NOMATCH;
72 if (info->bitmask & EBT_ARP_SRC_MAC) { 72 if (info->bitmask & EBT_ARP_SRC_MAC) {
73 mp = skb_header_pointer(skb, sizeof(struct arphdr), 73 mp = skb_header_pointer(skb, sizeof(struct arphdr),
74 sizeof(_mac), &_mac); 74 sizeof(_mac), &_mac);
75 if (mp == NULL) 75 if (mp == NULL)
76 return EBT_NOMATCH; 76 return EBT_NOMATCH;
77 verdict = 0; 77 verdict = 0;
78 for (i = 0; i < 6; i++) 78 for (i = 0; i < 6; i++)
79 verdict |= (mp[i] ^ info->smaddr[i]) & 79 verdict |= (mp[i] ^ info->smaddr[i]) &
80 info->smmsk[i]; 80 info->smmsk[i];
81 if (FWINV(verdict != 0, EBT_ARP_SRC_MAC)) 81 if (FWINV(verdict != 0, EBT_ARP_SRC_MAC))
82 return EBT_NOMATCH; 82 return EBT_NOMATCH;
83 } 83 }
84 84
85 if (info->bitmask & EBT_ARP_DST_MAC) { 85 if (info->bitmask & EBT_ARP_DST_MAC) {
86 mp = skb_header_pointer(skb, sizeof(struct arphdr) + 86 mp = skb_header_pointer(skb, sizeof(struct arphdr) +
87 ah->ar_hln + ah->ar_pln, 87 ah->ar_hln + ah->ar_pln,
88 sizeof(_mac), &_mac); 88 sizeof(_mac), &_mac);
89 if (mp == NULL) 89 if (mp == NULL)
90 return EBT_NOMATCH; 90 return EBT_NOMATCH;
91 verdict = 0; 91 verdict = 0;
92 for (i = 0; i < 6; i++) 92 for (i = 0; i < 6; i++)
93 verdict |= (mp[i] ^ info->dmaddr[i]) & 93 verdict |= (mp[i] ^ info->dmaddr[i]) &
94 info->dmmsk[i]; 94 info->dmmsk[i];
95 if (FWINV(verdict != 0, EBT_ARP_DST_MAC)) 95 if (FWINV(verdict != 0, EBT_ARP_DST_MAC))
96 return EBT_NOMATCH; 96 return EBT_NOMATCH;
97 } 97 }
98 } 98 }
99 99
100 return EBT_MATCH; 100 return EBT_MATCH;
101 } 101 }
102 102
103 static int ebt_arp_check(const char *tablename, unsigned int hookmask, 103 static bool ebt_arp_check(const char *tablename, unsigned int hookmask,
104 const struct ebt_entry *e, void *data, unsigned int datalen) 104 const struct ebt_entry *e, void *data, unsigned int datalen)
105 { 105 {
106 const struct ebt_arp_info *info = data; 106 const struct ebt_arp_info *info = data;
107 107
108 if ((e->ethproto != htons(ETH_P_ARP) && 108 if ((e->ethproto != htons(ETH_P_ARP) &&
109 e->ethproto != htons(ETH_P_RARP)) || 109 e->ethproto != htons(ETH_P_RARP)) ||
110 e->invflags & EBT_IPROTO) 110 e->invflags & EBT_IPROTO)
111 return -EINVAL; 111 return false;
112 if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK) 112 if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK)
113 return -EINVAL; 113 return false;
114 return 0; 114 return true;
115 } 115 }
116 116
117 static struct ebt_match filter_arp __read_mostly = { 117 static struct ebt_match filter_arp __read_mostly = {
118 .name = EBT_ARP_MATCH, 118 .name = EBT_ARP_MATCH,
119 .match = ebt_filter_arp, 119 .match = ebt_filter_arp,
120 .check = ebt_arp_check, 120 .check = ebt_arp_check,
121 .matchsize = XT_ALIGN(sizeof(struct ebt_arp_info)), 121 .matchsize = XT_ALIGN(sizeof(struct ebt_arp_info)),
122 .me = THIS_MODULE, 122 .me = THIS_MODULE,
123 }; 123 };
124 124
125 static int __init ebt_arp_init(void) 125 static int __init ebt_arp_init(void)
126 { 126 {
127 return ebt_register_match(&filter_arp); 127 return ebt_register_match(&filter_arp);
128 } 128 }
129 129
130 static void __exit ebt_arp_fini(void) 130 static void __exit ebt_arp_fini(void)
131 { 131 {
132 ebt_unregister_match(&filter_arp); 132 ebt_unregister_match(&filter_arp);
133 } 133 }
134 134
135 module_init(ebt_arp_init); 135 module_init(ebt_arp_init);
136 module_exit(ebt_arp_fini); 136 module_exit(ebt_arp_fini);
137 MODULE_DESCRIPTION("Ebtables: ARP protocol packet match"); 137 MODULE_DESCRIPTION("Ebtables: ARP protocol packet match");
138 MODULE_LICENSE("GPL"); 138 MODULE_LICENSE("GPL");
139 139
net/bridge/netfilter/ebt_arpreply.c
1 /* 1 /*
2 * ebt_arpreply 2 * ebt_arpreply
3 * 3 *
4 * Authors: 4 * Authors:
5 * Grzegorz Borowiak <grzes@gnu.univ.gda.pl> 5 * Grzegorz Borowiak <grzes@gnu.univ.gda.pl>
6 * Bart De Schuymer <bdschuym@pandora.be> 6 * Bart De Schuymer <bdschuym@pandora.be>
7 * 7 *
8 * August, 2003 8 * August, 2003
9 * 9 *
10 */ 10 */
11 #include <linux/if_arp.h> 11 #include <linux/if_arp.h>
12 #include <net/arp.h> 12 #include <net/arp.h>
13 #include <linux/module.h> 13 #include <linux/module.h>
14 #include <linux/netfilter/x_tables.h> 14 #include <linux/netfilter/x_tables.h>
15 #include <linux/netfilter_bridge/ebtables.h> 15 #include <linux/netfilter_bridge/ebtables.h>
16 #include <linux/netfilter_bridge/ebt_arpreply.h> 16 #include <linux/netfilter_bridge/ebt_arpreply.h>
17 17
18 static int ebt_target_reply(struct sk_buff *skb, unsigned int hooknr, 18 static int ebt_target_reply(struct sk_buff *skb, unsigned int hooknr,
19 const struct net_device *in, const struct net_device *out, 19 const struct net_device *in, const struct net_device *out,
20 const void *data, unsigned int datalen) 20 const void *data, unsigned int datalen)
21 { 21 {
22 struct ebt_arpreply_info *info = (void *)data; 22 struct ebt_arpreply_info *info = (void *)data;
23 const __be32 *siptr, *diptr; 23 const __be32 *siptr, *diptr;
24 __be32 _sip, _dip; 24 __be32 _sip, _dip;
25 const struct arphdr *ap; 25 const struct arphdr *ap;
26 struct arphdr _ah; 26 struct arphdr _ah;
27 const unsigned char *shp; 27 const unsigned char *shp;
28 unsigned char _sha[ETH_ALEN]; 28 unsigned char _sha[ETH_ALEN];
29 29
30 ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); 30 ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
31 if (ap == NULL) 31 if (ap == NULL)
32 return EBT_DROP; 32 return EBT_DROP;
33 33
34 if (ap->ar_op != htons(ARPOP_REQUEST) || 34 if (ap->ar_op != htons(ARPOP_REQUEST) ||
35 ap->ar_hln != ETH_ALEN || 35 ap->ar_hln != ETH_ALEN ||
36 ap->ar_pro != htons(ETH_P_IP) || 36 ap->ar_pro != htons(ETH_P_IP) ||
37 ap->ar_pln != 4) 37 ap->ar_pln != 4)
38 return EBT_CONTINUE; 38 return EBT_CONTINUE;
39 39
40 shp = skb_header_pointer(skb, sizeof(_ah), ETH_ALEN, &_sha); 40 shp = skb_header_pointer(skb, sizeof(_ah), ETH_ALEN, &_sha);
41 if (shp == NULL) 41 if (shp == NULL)
42 return EBT_DROP; 42 return EBT_DROP;
43 43
44 siptr = skb_header_pointer(skb, sizeof(_ah) + ETH_ALEN, 44 siptr = skb_header_pointer(skb, sizeof(_ah) + ETH_ALEN,
45 sizeof(_sip), &_sip); 45 sizeof(_sip), &_sip);
46 if (siptr == NULL) 46 if (siptr == NULL)
47 return EBT_DROP; 47 return EBT_DROP;
48 48
49 diptr = skb_header_pointer(skb, 49 diptr = skb_header_pointer(skb,
50 sizeof(_ah) + 2 * ETH_ALEN + sizeof(_sip), 50 sizeof(_ah) + 2 * ETH_ALEN + sizeof(_sip),
51 sizeof(_dip), &_dip); 51 sizeof(_dip), &_dip);
52 if (diptr == NULL) 52 if (diptr == NULL)
53 return EBT_DROP; 53 return EBT_DROP;
54 54
55 arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)in, 55 arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)in,
56 *diptr, shp, info->mac, shp); 56 *diptr, shp, info->mac, shp);
57 57
58 return info->target; 58 return info->target;
59 } 59 }
60 60
61 static int ebt_target_reply_check(const char *tablename, unsigned int hookmask, 61 static bool ebt_target_reply_check(const char *tablename, unsigned int hookmask,
62 const struct ebt_entry *e, void *data, unsigned int datalen) 62 const struct ebt_entry *e, void *data, unsigned int datalen)
63 { 63 {
64 const struct ebt_arpreply_info *info = data; 64 const struct ebt_arpreply_info *info = data;
65 65
66 if (BASE_CHAIN && info->target == EBT_RETURN) 66 if (BASE_CHAIN && info->target == EBT_RETURN)
67 return -EINVAL; 67 return false;
68 if (e->ethproto != htons(ETH_P_ARP) || 68 if (e->ethproto != htons(ETH_P_ARP) ||
69 e->invflags & EBT_IPROTO) 69 e->invflags & EBT_IPROTO)
70 return -EINVAL; 70 return false;
71 CLEAR_BASE_CHAIN_BIT; 71 CLEAR_BASE_CHAIN_BIT;
72 if (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING)) 72 if (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING))
73 return -EINVAL; 73 return false;
74 return 0; 74 return true;
75 } 75 }
76 76
77 static struct ebt_target reply_target __read_mostly = { 77 static struct ebt_target reply_target __read_mostly = {
78 .name = EBT_ARPREPLY_TARGET, 78 .name = EBT_ARPREPLY_TARGET,
79 .target = ebt_target_reply, 79 .target = ebt_target_reply,
80 .check = ebt_target_reply_check, 80 .check = ebt_target_reply_check,
81 .targetsize = XT_ALIGN(sizeof(struct ebt_arpreply_info)), 81 .targetsize = XT_ALIGN(sizeof(struct ebt_arpreply_info)),
82 .me = THIS_MODULE, 82 .me = THIS_MODULE,
83 }; 83 };
84 84
85 static int __init ebt_arpreply_init(void) 85 static int __init ebt_arpreply_init(void)
86 { 86 {
87 return ebt_register_target(&reply_target); 87 return ebt_register_target(&reply_target);
88 } 88 }
89 89
90 static void __exit ebt_arpreply_fini(void) 90 static void __exit ebt_arpreply_fini(void)
91 { 91 {
92 ebt_unregister_target(&reply_target); 92 ebt_unregister_target(&reply_target);
93 } 93 }
94 94
95 module_init(ebt_arpreply_init); 95 module_init(ebt_arpreply_init);
96 module_exit(ebt_arpreply_fini); 96 module_exit(ebt_arpreply_fini);
97 MODULE_DESCRIPTION("Ebtables: ARP reply target"); 97 MODULE_DESCRIPTION("Ebtables: ARP reply target");
98 MODULE_LICENSE("GPL"); 98 MODULE_LICENSE("GPL");
99 99
net/bridge/netfilter/ebt_dnat.c
1 /* 1 /*
2 * ebt_dnat 2 * ebt_dnat
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * 6 *
7 * June, 2002 7 * June, 2002
8 * 8 *
9 */ 9 */
10 #include <linux/module.h> 10 #include <linux/module.h>
11 #include <net/sock.h> 11 #include <net/sock.h>
12 #include <linux/netfilter.h> 12 #include <linux/netfilter.h>
13 #include <linux/netfilter/x_tables.h> 13 #include <linux/netfilter/x_tables.h>
14 #include <linux/netfilter_bridge/ebtables.h> 14 #include <linux/netfilter_bridge/ebtables.h>
15 #include <linux/netfilter_bridge/ebt_nat.h> 15 #include <linux/netfilter_bridge/ebt_nat.h>
16 16
17 static int ebt_target_dnat(struct sk_buff *skb, unsigned int hooknr, 17 static int ebt_target_dnat(struct sk_buff *skb, unsigned int hooknr,
18 const struct net_device *in, const struct net_device *out, 18 const struct net_device *in, const struct net_device *out,
19 const void *data, unsigned int datalen) 19 const void *data, unsigned int datalen)
20 { 20 {
21 const struct ebt_nat_info *info = data; 21 const struct ebt_nat_info *info = data;
22 22
23 if (!skb_make_writable(skb, 0)) 23 if (!skb_make_writable(skb, 0))
24 return EBT_DROP; 24 return EBT_DROP;
25 25
26 memcpy(eth_hdr(skb)->h_dest, info->mac, ETH_ALEN); 26 memcpy(eth_hdr(skb)->h_dest, info->mac, ETH_ALEN);
27 return info->target; 27 return info->target;
28 } 28 }
29 29
30 static int ebt_target_dnat_check(const char *tablename, unsigned int hookmask, 30 static bool ebt_target_dnat_check(const char *tablename, unsigned int hookmask,
31 const struct ebt_entry *e, void *data, unsigned int datalen) 31 const struct ebt_entry *e, void *data, unsigned int datalen)
32 { 32 {
33 const struct ebt_nat_info *info = data; 33 const struct ebt_nat_info *info = data;
34 34
35 if (BASE_CHAIN && info->target == EBT_RETURN) 35 if (BASE_CHAIN && info->target == EBT_RETURN)
36 return -EINVAL; 36 return false;
37 CLEAR_BASE_CHAIN_BIT; 37 CLEAR_BASE_CHAIN_BIT;
38 if ( (strcmp(tablename, "nat") || 38 if ( (strcmp(tablename, "nat") ||
39 (hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))) && 39 (hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))) &&
40 (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) ) 40 (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) )
41 return -EINVAL; 41 return false;
42 if (INVALID_TARGET) 42 if (INVALID_TARGET)
43 return -EINVAL; 43 return false;
44 return 0; 44 return true;
45 } 45 }
46 46
47 static struct ebt_target dnat __read_mostly = { 47 static struct ebt_target dnat __read_mostly = {
48 .name = EBT_DNAT_TARGET, 48 .name = EBT_DNAT_TARGET,
49 .target = ebt_target_dnat, 49 .target = ebt_target_dnat,
50 .check = ebt_target_dnat_check, 50 .check = ebt_target_dnat_check,
51 .targetsize = XT_ALIGN(sizeof(struct ebt_nat_info)), 51 .targetsize = XT_ALIGN(sizeof(struct ebt_nat_info)),
52 .me = THIS_MODULE, 52 .me = THIS_MODULE,
53 }; 53 };
54 54
55 static int __init ebt_dnat_init(void) 55 static int __init ebt_dnat_init(void)
56 { 56 {
57 return ebt_register_target(&dnat); 57 return ebt_register_target(&dnat);
58 } 58 }
59 59
60 static void __exit ebt_dnat_fini(void) 60 static void __exit ebt_dnat_fini(void)
61 { 61 {
62 ebt_unregister_target(&dnat); 62 ebt_unregister_target(&dnat);
63 } 63 }
64 64
65 module_init(ebt_dnat_init); 65 module_init(ebt_dnat_init);
66 module_exit(ebt_dnat_fini); 66 module_exit(ebt_dnat_fini);
67 MODULE_DESCRIPTION("Ebtables: Destination MAC address translation"); 67 MODULE_DESCRIPTION("Ebtables: Destination MAC address translation");
68 MODULE_LICENSE("GPL"); 68 MODULE_LICENSE("GPL");
69 69
net/bridge/netfilter/ebt_ip.c
1 /* 1 /*
2 * ebt_ip 2 * ebt_ip
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * 6 *
7 * April, 2002 7 * April, 2002
8 * 8 *
9 * Changes: 9 * Changes:
10 * added ip-sport and ip-dport 10 * added ip-sport and ip-dport
11 * Innominate Security Technologies AG <mhopf@innominate.com> 11 * Innominate Security Technologies AG <mhopf@innominate.com>
12 * September, 2002 12 * September, 2002
13 */ 13 */
14 #include <linux/ip.h> 14 #include <linux/ip.h>
15 #include <net/ip.h> 15 #include <net/ip.h>
16 #include <linux/in.h> 16 #include <linux/in.h>
17 #include <linux/module.h> 17 #include <linux/module.h>
18 #include <linux/netfilter/x_tables.h> 18 #include <linux/netfilter/x_tables.h>
19 #include <linux/netfilter_bridge/ebtables.h> 19 #include <linux/netfilter_bridge/ebtables.h>
20 #include <linux/netfilter_bridge/ebt_ip.h> 20 #include <linux/netfilter_bridge/ebt_ip.h>
21 21
22 struct tcpudphdr { 22 struct tcpudphdr {
23 __be16 src; 23 __be16 src;
24 __be16 dst; 24 __be16 dst;
25 }; 25 };
26 26
27 static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in, 27 static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
28 const struct net_device *out, const void *data, 28 const struct net_device *out, const void *data,
29 unsigned int datalen) 29 unsigned int datalen)
30 { 30 {
31 const struct ebt_ip_info *info = data; 31 const struct ebt_ip_info *info = data;
32 const struct iphdr *ih; 32 const struct iphdr *ih;
33 struct iphdr _iph; 33 struct iphdr _iph;
34 const struct tcpudphdr *pptr; 34 const struct tcpudphdr *pptr;
35 struct tcpudphdr _ports; 35 struct tcpudphdr _ports;
36 36
37 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); 37 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
38 if (ih == NULL) 38 if (ih == NULL)
39 return EBT_NOMATCH; 39 return EBT_NOMATCH;
40 if (info->bitmask & EBT_IP_TOS && 40 if (info->bitmask & EBT_IP_TOS &&
41 FWINV(info->tos != ih->tos, EBT_IP_TOS)) 41 FWINV(info->tos != ih->tos, EBT_IP_TOS))
42 return EBT_NOMATCH; 42 return EBT_NOMATCH;
43 if (info->bitmask & EBT_IP_SOURCE && 43 if (info->bitmask & EBT_IP_SOURCE &&
44 FWINV((ih->saddr & info->smsk) != 44 FWINV((ih->saddr & info->smsk) !=
45 info->saddr, EBT_IP_SOURCE)) 45 info->saddr, EBT_IP_SOURCE))
46 return EBT_NOMATCH; 46 return EBT_NOMATCH;
47 if ((info->bitmask & EBT_IP_DEST) && 47 if ((info->bitmask & EBT_IP_DEST) &&
48 FWINV((ih->daddr & info->dmsk) != 48 FWINV((ih->daddr & info->dmsk) !=
49 info->daddr, EBT_IP_DEST)) 49 info->daddr, EBT_IP_DEST))
50 return EBT_NOMATCH; 50 return EBT_NOMATCH;
51 if (info->bitmask & EBT_IP_PROTO) { 51 if (info->bitmask & EBT_IP_PROTO) {
52 if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO)) 52 if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO))
53 return EBT_NOMATCH; 53 return EBT_NOMATCH;
54 if (!(info->bitmask & EBT_IP_DPORT) && 54 if (!(info->bitmask & EBT_IP_DPORT) &&
55 !(info->bitmask & EBT_IP_SPORT)) 55 !(info->bitmask & EBT_IP_SPORT))
56 return EBT_MATCH; 56 return EBT_MATCH;
57 if (ntohs(ih->frag_off) & IP_OFFSET) 57 if (ntohs(ih->frag_off) & IP_OFFSET)
58 return EBT_NOMATCH; 58 return EBT_NOMATCH;
59 pptr = skb_header_pointer(skb, ih->ihl*4, 59 pptr = skb_header_pointer(skb, ih->ihl*4,
60 sizeof(_ports), &_ports); 60 sizeof(_ports), &_ports);
61 if (pptr == NULL) 61 if (pptr == NULL)
62 return EBT_NOMATCH; 62 return EBT_NOMATCH;
63 if (info->bitmask & EBT_IP_DPORT) { 63 if (info->bitmask & EBT_IP_DPORT) {
64 u32 dst = ntohs(pptr->dst); 64 u32 dst = ntohs(pptr->dst);
65 if (FWINV(dst < info->dport[0] || 65 if (FWINV(dst < info->dport[0] ||
66 dst > info->dport[1], 66 dst > info->dport[1],
67 EBT_IP_DPORT)) 67 EBT_IP_DPORT))
68 return EBT_NOMATCH; 68 return EBT_NOMATCH;
69 } 69 }
70 if (info->bitmask & EBT_IP_SPORT) { 70 if (info->bitmask & EBT_IP_SPORT) {
71 u32 src = ntohs(pptr->src); 71 u32 src = ntohs(pptr->src);
72 if (FWINV(src < info->sport[0] || 72 if (FWINV(src < info->sport[0] ||
73 src > info->sport[1], 73 src > info->sport[1],
74 EBT_IP_SPORT)) 74 EBT_IP_SPORT))
75 return EBT_NOMATCH; 75 return EBT_NOMATCH;
76 } 76 }
77 } 77 }
78 return EBT_MATCH; 78 return EBT_MATCH;
79 } 79 }
80 80
81 static int ebt_ip_check(const char *tablename, unsigned int hookmask, 81 static bool ebt_ip_check(const char *tablename, unsigned int hookmask,
82 const struct ebt_entry *e, void *data, unsigned int datalen) 82 const struct ebt_entry *e, void *data, unsigned int datalen)
83 { 83 {
84 const struct ebt_ip_info *info = data; 84 const struct ebt_ip_info *info = data;
85 85
86 if (e->ethproto != htons(ETH_P_IP) || 86 if (e->ethproto != htons(ETH_P_IP) ||
87 e->invflags & EBT_IPROTO) 87 e->invflags & EBT_IPROTO)
88 return -EINVAL; 88 return false;
89 if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK) 89 if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
90 return -EINVAL; 90 return false;
91 if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) { 91 if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) {
92 if (info->invflags & EBT_IP_PROTO) 92 if (info->invflags & EBT_IP_PROTO)
93 return -EINVAL; 93 return false;
94 if (info->protocol != IPPROTO_TCP && 94 if (info->protocol != IPPROTO_TCP &&
95 info->protocol != IPPROTO_UDP && 95 info->protocol != IPPROTO_UDP &&
96 info->protocol != IPPROTO_UDPLITE && 96 info->protocol != IPPROTO_UDPLITE &&
97 info->protocol != IPPROTO_SCTP && 97 info->protocol != IPPROTO_SCTP &&
98 info->protocol != IPPROTO_DCCP) 98 info->protocol != IPPROTO_DCCP)
99 return -EINVAL; 99 return false;
100 } 100 }
101 if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1]) 101 if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1])
102 return -EINVAL; 102 return false;
103 if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1]) 103 if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1])
104 return -EINVAL; 104 return false;
105 return 0; 105 return true;
106 } 106 }
107 107
108 static struct ebt_match filter_ip __read_mostly = { 108 static struct ebt_match filter_ip __read_mostly = {
109 .name = EBT_IP_MATCH, 109 .name = EBT_IP_MATCH,
110 .match = ebt_filter_ip, 110 .match = ebt_filter_ip,
111 .check = ebt_ip_check, 111 .check = ebt_ip_check,
112 .matchsize = XT_ALIGN(sizeof(struct ebt_ip_info)), 112 .matchsize = XT_ALIGN(sizeof(struct ebt_ip_info)),
113 .me = THIS_MODULE, 113 .me = THIS_MODULE,
114 }; 114 };
115 115
116 static int __init ebt_ip_init(void) 116 static int __init ebt_ip_init(void)
117 { 117 {
118 return ebt_register_match(&filter_ip); 118 return ebt_register_match(&filter_ip);
119 } 119 }
120 120
121 static void __exit ebt_ip_fini(void) 121 static void __exit ebt_ip_fini(void)
122 { 122 {
123 ebt_unregister_match(&filter_ip); 123 ebt_unregister_match(&filter_ip);
124 } 124 }
125 125
126 module_init(ebt_ip_init); 126 module_init(ebt_ip_init);
127 module_exit(ebt_ip_fini); 127 module_exit(ebt_ip_fini);
128 MODULE_DESCRIPTION("Ebtables: IPv4 protocol packet match"); 128 MODULE_DESCRIPTION("Ebtables: IPv4 protocol packet match");
129 MODULE_LICENSE("GPL"); 129 MODULE_LICENSE("GPL");
130 130
net/bridge/netfilter/ebt_ip6.c
1 /* 1 /*
2 * ebt_ip6 2 * ebt_ip6
3 * 3 *
4 * Authors: 4 * Authors:
5 * Manohar Castelino <manohar.r.castelino@intel.com> 5 * Manohar Castelino <manohar.r.castelino@intel.com>
6 * Kuo-Lang Tseng <kuo-lang.tseng@intel.com> 6 * Kuo-Lang Tseng <kuo-lang.tseng@intel.com>
7 * Jan Engelhardt <jengelh@computergmbh.de> 7 * Jan Engelhardt <jengelh@computergmbh.de>
8 * 8 *
9 * Summary: 9 * Summary:
10 * This is just a modification of the IPv4 code written by 10 * This is just a modification of the IPv4 code written by
11 * Bart De Schuymer <bdschuym@pandora.be> 11 * Bart De Schuymer <bdschuym@pandora.be>
12 * with the changes required to support IPv6 12 * with the changes required to support IPv6
13 * 13 *
14 * Jan, 2008 14 * Jan, 2008
15 */ 15 */
16 #include <linux/ipv6.h> 16 #include <linux/ipv6.h>
17 #include <net/ipv6.h> 17 #include <net/ipv6.h>
18 #include <linux/in.h> 18 #include <linux/in.h>
19 #include <linux/module.h> 19 #include <linux/module.h>
20 #include <net/dsfield.h> 20 #include <net/dsfield.h>
21 #include <linux/netfilter/x_tables.h> 21 #include <linux/netfilter/x_tables.h>
22 #include <linux/netfilter_bridge/ebtables.h> 22 #include <linux/netfilter_bridge/ebtables.h>
23 #include <linux/netfilter_bridge/ebt_ip6.h> 23 #include <linux/netfilter_bridge/ebt_ip6.h>
24 24
25 struct tcpudphdr { 25 struct tcpudphdr {
26 __be16 src; 26 __be16 src;
27 __be16 dst; 27 __be16 dst;
28 }; 28 };
29 29
30 static int ebt_filter_ip6(const struct sk_buff *skb, 30 static int ebt_filter_ip6(const struct sk_buff *skb,
31 const struct net_device *in, 31 const struct net_device *in,
32 const struct net_device *out, const void *data, 32 const struct net_device *out, const void *data,
33 unsigned int datalen) 33 unsigned int datalen)
34 { 34 {
35 const struct ebt_ip6_info *info = (struct ebt_ip6_info *)data; 35 const struct ebt_ip6_info *info = (struct ebt_ip6_info *)data;
36 const struct ipv6hdr *ih6; 36 const struct ipv6hdr *ih6;
37 struct ipv6hdr _ip6h; 37 struct ipv6hdr _ip6h;
38 const struct tcpudphdr *pptr; 38 const struct tcpudphdr *pptr;
39 struct tcpudphdr _ports; 39 struct tcpudphdr _ports;
40 struct in6_addr tmp_addr; 40 struct in6_addr tmp_addr;
41 int i; 41 int i;
42 42
43 ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); 43 ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h);
44 if (ih6 == NULL) 44 if (ih6 == NULL)
45 return EBT_NOMATCH; 45 return EBT_NOMATCH;
46 if (info->bitmask & EBT_IP6_TCLASS && 46 if (info->bitmask & EBT_IP6_TCLASS &&
47 FWINV(info->tclass != ipv6_get_dsfield(ih6), EBT_IP6_TCLASS)) 47 FWINV(info->tclass != ipv6_get_dsfield(ih6), EBT_IP6_TCLASS))
48 return EBT_NOMATCH; 48 return EBT_NOMATCH;
49 for (i = 0; i < 4; i++) 49 for (i = 0; i < 4; i++)
50 tmp_addr.in6_u.u6_addr32[i] = ih6->saddr.in6_u.u6_addr32[i] & 50 tmp_addr.in6_u.u6_addr32[i] = ih6->saddr.in6_u.u6_addr32[i] &
51 info->smsk.in6_u.u6_addr32[i]; 51 info->smsk.in6_u.u6_addr32[i];
52 if (info->bitmask & EBT_IP6_SOURCE && 52 if (info->bitmask & EBT_IP6_SOURCE &&
53 FWINV((ipv6_addr_cmp(&tmp_addr, &info->saddr) != 0), 53 FWINV((ipv6_addr_cmp(&tmp_addr, &info->saddr) != 0),
54 EBT_IP6_SOURCE)) 54 EBT_IP6_SOURCE))
55 return EBT_NOMATCH; 55 return EBT_NOMATCH;
56 for (i = 0; i < 4; i++) 56 for (i = 0; i < 4; i++)
57 tmp_addr.in6_u.u6_addr32[i] = ih6->daddr.in6_u.u6_addr32[i] & 57 tmp_addr.in6_u.u6_addr32[i] = ih6->daddr.in6_u.u6_addr32[i] &
58 info->dmsk.in6_u.u6_addr32[i]; 58 info->dmsk.in6_u.u6_addr32[i];
59 if (info->bitmask & EBT_IP6_DEST && 59 if (info->bitmask & EBT_IP6_DEST &&
60 FWINV((ipv6_addr_cmp(&tmp_addr, &info->daddr) != 0), EBT_IP6_DEST)) 60 FWINV((ipv6_addr_cmp(&tmp_addr, &info->daddr) != 0), EBT_IP6_DEST))
61 return EBT_NOMATCH; 61 return EBT_NOMATCH;
62 if (info->bitmask & EBT_IP6_PROTO) { 62 if (info->bitmask & EBT_IP6_PROTO) {
63 uint8_t nexthdr = ih6->nexthdr; 63 uint8_t nexthdr = ih6->nexthdr;
64 int offset_ph; 64 int offset_ph;
65 65
66 offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr); 66 offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr);
67 if (offset_ph == -1) 67 if (offset_ph == -1)
68 return EBT_NOMATCH; 68 return EBT_NOMATCH;
69 if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) 69 if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO))
70 return EBT_NOMATCH; 70 return EBT_NOMATCH;
71 if (!(info->bitmask & EBT_IP6_DPORT) && 71 if (!(info->bitmask & EBT_IP6_DPORT) &&
72 !(info->bitmask & EBT_IP6_SPORT)) 72 !(info->bitmask & EBT_IP6_SPORT))
73 return EBT_MATCH; 73 return EBT_MATCH;
74 pptr = skb_header_pointer(skb, offset_ph, sizeof(_ports), 74 pptr = skb_header_pointer(skb, offset_ph, sizeof(_ports),
75 &_ports); 75 &_ports);
76 if (pptr == NULL) 76 if (pptr == NULL)
77 return EBT_NOMATCH; 77 return EBT_NOMATCH;
78 if (info->bitmask & EBT_IP6_DPORT) { 78 if (info->bitmask & EBT_IP6_DPORT) {
79 u32 dst = ntohs(pptr->dst); 79 u32 dst = ntohs(pptr->dst);
80 if (FWINV(dst < info->dport[0] || 80 if (FWINV(dst < info->dport[0] ||
81 dst > info->dport[1], EBT_IP6_DPORT)) 81 dst > info->dport[1], EBT_IP6_DPORT))
82 return EBT_NOMATCH; 82 return EBT_NOMATCH;
83 } 83 }
84 if (info->bitmask & EBT_IP6_SPORT) { 84 if (info->bitmask & EBT_IP6_SPORT) {
85 u32 src = ntohs(pptr->src); 85 u32 src = ntohs(pptr->src);
86 if (FWINV(src < info->sport[0] || 86 if (FWINV(src < info->sport[0] ||
87 src > info->sport[1], EBT_IP6_SPORT)) 87 src > info->sport[1], EBT_IP6_SPORT))
88 return EBT_NOMATCH; 88 return EBT_NOMATCH;
89 } 89 }
90 return EBT_MATCH; 90 return EBT_MATCH;
91 } 91 }
92 return EBT_MATCH; 92 return EBT_MATCH;
93 } 93 }
94 94
95 static int ebt_ip6_check(const char *tablename, unsigned int hookmask, 95 static bool ebt_ip6_check(const char *tablename, unsigned int hookmask,
96 const struct ebt_entry *e, void *data, unsigned int datalen) 96 const struct ebt_entry *e, void *data, unsigned int datalen)
97 { 97 {
98 struct ebt_ip6_info *info = (struct ebt_ip6_info *)data; 98 struct ebt_ip6_info *info = (struct ebt_ip6_info *)data;
99 99
100 if (e->ethproto != htons(ETH_P_IPV6) || e->invflags & EBT_IPROTO) 100 if (e->ethproto != htons(ETH_P_IPV6) || e->invflags & EBT_IPROTO)
101 return -EINVAL; 101 return false;
102 if (info->bitmask & ~EBT_IP6_MASK || info->invflags & ~EBT_IP6_MASK) 102 if (info->bitmask & ~EBT_IP6_MASK || info->invflags & ~EBT_IP6_MASK)
103 return -EINVAL; 103 return false;
104 if (info->bitmask & (EBT_IP6_DPORT | EBT_IP6_SPORT)) { 104 if (info->bitmask & (EBT_IP6_DPORT | EBT_IP6_SPORT)) {
105 if (info->invflags & EBT_IP6_PROTO) 105 if (info->invflags & EBT_IP6_PROTO)
106 return -EINVAL; 106 return false;
107 if (info->protocol != IPPROTO_TCP && 107 if (info->protocol != IPPROTO_TCP &&
108 info->protocol != IPPROTO_UDP && 108 info->protocol != IPPROTO_UDP &&
109 info->protocol != IPPROTO_UDPLITE && 109 info->protocol != IPPROTO_UDPLITE &&
110 info->protocol != IPPROTO_SCTP && 110 info->protocol != IPPROTO_SCTP &&
111 info->protocol != IPPROTO_DCCP) 111 info->protocol != IPPROTO_DCCP)
112 return -EINVAL; 112 return false;
113 } 113 }
114 if (info->bitmask & EBT_IP6_DPORT && info->dport[0] > info->dport[1]) 114 if (info->bitmask & EBT_IP6_DPORT && info->dport[0] > info->dport[1])
115 return -EINVAL; 115 return false;
116 if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1]) 116 if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1])
117 return -EINVAL; 117 return false;
118 return 0; 118 return true;
119 } 119 }
120 120
121 static struct ebt_match filter_ip6 = 121 static struct ebt_match filter_ip6 =
122 { 122 {
123 .name = EBT_IP6_MATCH, 123 .name = EBT_IP6_MATCH,
124 .match = ebt_filter_ip6, 124 .match = ebt_filter_ip6,
125 .check = ebt_ip6_check, 125 .check = ebt_ip6_check,
126 .matchsize = XT_ALIGN(sizeof(struct ebt_ip6_info)), 126 .matchsize = XT_ALIGN(sizeof(struct ebt_ip6_info)),
127 .me = THIS_MODULE, 127 .me = THIS_MODULE,
128 }; 128 };
129 129
130 static int __init ebt_ip6_init(void) 130 static int __init ebt_ip6_init(void)
131 { 131 {
132 return ebt_register_match(&filter_ip6); 132 return ebt_register_match(&filter_ip6);
133 } 133 }
134 134
135 static void __exit ebt_ip6_fini(void) 135 static void __exit ebt_ip6_fini(void)
136 { 136 {
137 ebt_unregister_match(&filter_ip6); 137 ebt_unregister_match(&filter_ip6);
138 } 138 }
139 139
140 module_init(ebt_ip6_init); 140 module_init(ebt_ip6_init);
141 module_exit(ebt_ip6_fini); 141 module_exit(ebt_ip6_fini);
142 MODULE_DESCRIPTION("Ebtables: IPv6 protocol packet match"); 142 MODULE_DESCRIPTION("Ebtables: IPv6 protocol packet match");
143 MODULE_LICENSE("GPL"); 143 MODULE_LICENSE("GPL");
144 144
net/bridge/netfilter/ebt_limit.c
1 /* 1 /*
2 * ebt_limit 2 * ebt_limit
3 * 3 *
4 * Authors: 4 * Authors:
5 * Tom Marshall <tommy@home.tig-grr.com> 5 * Tom Marshall <tommy@home.tig-grr.com>
6 * 6 *
7 * Mostly copied from netfilter's ipt_limit.c, see that file for 7 * Mostly copied from netfilter's ipt_limit.c, see that file for
8 * more explanation 8 * more explanation
9 * 9 *
10 * September, 2003 10 * September, 2003
11 * 11 *
12 */ 12 */
13 #include <linux/module.h> 13 #include <linux/module.h>
14 #include <linux/netdevice.h> 14 #include <linux/netdevice.h>
15 #include <linux/spinlock.h> 15 #include <linux/spinlock.h>
16 #include <linux/netfilter/x_tables.h> 16 #include <linux/netfilter/x_tables.h>
17 #include <linux/netfilter_bridge/ebtables.h> 17 #include <linux/netfilter_bridge/ebtables.h>
18 #include <linux/netfilter_bridge/ebt_limit.h> 18 #include <linux/netfilter_bridge/ebt_limit.h>
19 19
20 static DEFINE_SPINLOCK(limit_lock); 20 static DEFINE_SPINLOCK(limit_lock);
21 21
22 #define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24)) 22 #define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
23 23
24 #define _POW2_BELOW2(x) ((x)|((x)>>1)) 24 #define _POW2_BELOW2(x) ((x)|((x)>>1))
25 #define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2)) 25 #define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
26 #define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4)) 26 #define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
27 #define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8)) 27 #define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
28 #define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16)) 28 #define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
29 #define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1) 29 #define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
30 30
31 #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) 31 #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
32 32
33 static int ebt_limit_match(const struct sk_buff *skb, 33 static int ebt_limit_match(const struct sk_buff *skb,
34 const struct net_device *in, const struct net_device *out, 34 const struct net_device *in, const struct net_device *out,
35 const void *data, unsigned int datalen) 35 const void *data, unsigned int datalen)
36 { 36 {
37 struct ebt_limit_info *info = (struct ebt_limit_info *)data; 37 struct ebt_limit_info *info = (struct ebt_limit_info *)data;
38 unsigned long now = jiffies; 38 unsigned long now = jiffies;
39 39
40 spin_lock_bh(&limit_lock); 40 spin_lock_bh(&limit_lock);
41 info->credit += (now - xchg(&info->prev, now)) * CREDITS_PER_JIFFY; 41 info->credit += (now - xchg(&info->prev, now)) * CREDITS_PER_JIFFY;
42 if (info->credit > info->credit_cap) 42 if (info->credit > info->credit_cap)
43 info->credit = info->credit_cap; 43 info->credit = info->credit_cap;
44 44
45 if (info->credit >= info->cost) { 45 if (info->credit >= info->cost) {
46 /* We're not limited. */ 46 /* We're not limited. */
47 info->credit -= info->cost; 47 info->credit -= info->cost;
48 spin_unlock_bh(&limit_lock); 48 spin_unlock_bh(&limit_lock);
49 return EBT_MATCH; 49 return EBT_MATCH;
50 } 50 }
51 51
52 spin_unlock_bh(&limit_lock); 52 spin_unlock_bh(&limit_lock);
53 return EBT_NOMATCH; 53 return EBT_NOMATCH;
54 } 54 }
55 55
56 /* Precision saver. */ 56 /* Precision saver. */
57 static u_int32_t 57 static u_int32_t
58 user2credits(u_int32_t user) 58 user2credits(u_int32_t user)
59 { 59 {
60 /* If multiplying would overflow... */ 60 /* If multiplying would overflow... */
61 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) 61 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
62 /* Divide first. */ 62 /* Divide first. */
63 return (user / EBT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; 63 return (user / EBT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
64 64
65 return (user * HZ * CREDITS_PER_JIFFY) / EBT_LIMIT_SCALE; 65 return (user * HZ * CREDITS_PER_JIFFY) / EBT_LIMIT_SCALE;
66 } 66 }
67 67
68 static int ebt_limit_check(const char *tablename, unsigned int hookmask, 68 static bool ebt_limit_check(const char *tablename, unsigned int hookmask,
69 const struct ebt_entry *e, void *data, unsigned int datalen) 69 const struct ebt_entry *e, void *data, unsigned int datalen)
70 { 70 {
71 struct ebt_limit_info *info = data; 71 struct ebt_limit_info *info = data;
72 72
73 /* Check for overflow. */ 73 /* Check for overflow. */
74 if (info->burst == 0 || 74 if (info->burst == 0 ||
75 user2credits(info->avg * info->burst) < user2credits(info->avg)) { 75 user2credits(info->avg * info->burst) < user2credits(info->avg)) {
76 printk("Overflow in ebt_limit, try lower: %u/%u\n", 76 printk("Overflow in ebt_limit, try lower: %u/%u\n",
77 info->avg, info->burst); 77 info->avg, info->burst);
78 return -EINVAL; 78 return false;
79 } 79 }
80 80
81 /* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */ 81 /* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */
82 info->prev = jiffies; 82 info->prev = jiffies;
83 info->credit = user2credits(info->avg * info->burst); 83 info->credit = user2credits(info->avg * info->burst);
84 info->credit_cap = user2credits(info->avg * info->burst); 84 info->credit_cap = user2credits(info->avg * info->burst);
85 info->cost = user2credits(info->avg); 85 info->cost = user2credits(info->avg);
86 return 0; 86 return true;
87 } 87 }
88 88
89 static struct ebt_match ebt_limit_reg __read_mostly = { 89 static struct ebt_match ebt_limit_reg __read_mostly = {
90 .name = EBT_LIMIT_MATCH, 90 .name = EBT_LIMIT_MATCH,
91 .match = ebt_limit_match, 91 .match = ebt_limit_match,
92 .check = ebt_limit_check, 92 .check = ebt_limit_check,
93 .matchsize = XT_ALIGN(sizeof(struct ebt_limit_info)), 93 .matchsize = XT_ALIGN(sizeof(struct ebt_limit_info)),
94 .me = THIS_MODULE, 94 .me = THIS_MODULE,
95 }; 95 };
96 96
97 static int __init ebt_limit_init(void) 97 static int __init ebt_limit_init(void)
98 { 98 {
99 return ebt_register_match(&ebt_limit_reg); 99 return ebt_register_match(&ebt_limit_reg);
100 } 100 }
101 101
102 static void __exit ebt_limit_fini(void) 102 static void __exit ebt_limit_fini(void)
103 { 103 {
104 ebt_unregister_match(&ebt_limit_reg); 104 ebt_unregister_match(&ebt_limit_reg);
105 } 105 }
106 106
107 module_init(ebt_limit_init); 107 module_init(ebt_limit_init);
108 module_exit(ebt_limit_fini); 108 module_exit(ebt_limit_fini);
109 MODULE_DESCRIPTION("Ebtables: Rate-limit match"); 109 MODULE_DESCRIPTION("Ebtables: Rate-limit match");
110 MODULE_LICENSE("GPL"); 110 MODULE_LICENSE("GPL");
111 111
net/bridge/netfilter/ebt_log.c
1 /* 1 /*
2 * ebt_log 2 * ebt_log
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * Harald Welte <laforge@netfilter.org> 6 * Harald Welte <laforge@netfilter.org>
7 * 7 *
8 * April, 2002 8 * April, 2002
9 * 9 *
10 */ 10 */
11 #include <linux/module.h> 11 #include <linux/module.h>
12 #include <linux/ip.h> 12 #include <linux/ip.h>
13 #include <linux/in.h> 13 #include <linux/in.h>
14 #include <linux/if_arp.h> 14 #include <linux/if_arp.h>
15 #include <linux/spinlock.h> 15 #include <linux/spinlock.h>
16 #include <net/netfilter/nf_log.h> 16 #include <net/netfilter/nf_log.h>
17 #include <linux/ipv6.h> 17 #include <linux/ipv6.h>
18 #include <net/ipv6.h> 18 #include <net/ipv6.h>
19 #include <linux/in6.h> 19 #include <linux/in6.h>
20 #include <linux/netfilter/x_tables.h> 20 #include <linux/netfilter/x_tables.h>
21 #include <linux/netfilter_bridge/ebtables.h> 21 #include <linux/netfilter_bridge/ebtables.h>
22 #include <linux/netfilter_bridge/ebt_log.h> 22 #include <linux/netfilter_bridge/ebt_log.h>
23 #include <linux/netfilter.h> 23 #include <linux/netfilter.h>
24 24
25 static DEFINE_SPINLOCK(ebt_log_lock); 25 static DEFINE_SPINLOCK(ebt_log_lock);
26 26
27 static int ebt_log_check(const char *tablename, unsigned int hookmask, 27 static bool ebt_log_check(const char *tablename, unsigned int hookmask,
28 const struct ebt_entry *e, void *data, unsigned int datalen) 28 const struct ebt_entry *e, void *data, unsigned int datalen)
29 { 29 {
30 struct ebt_log_info *info = data; 30 struct ebt_log_info *info = data;
31 31
32 if (info->bitmask & ~EBT_LOG_MASK) 32 if (info->bitmask & ~EBT_LOG_MASK)
33 return -EINVAL; 33 return false;
34 if (info->loglevel >= 8) 34 if (info->loglevel >= 8)
35 return -EINVAL; 35 return false;
36 info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0'; 36 info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0';
37 return 0; 37 return true;
38 } 38 }
39 39
40 struct tcpudphdr 40 struct tcpudphdr
41 { 41 {
42 __be16 src; 42 __be16 src;
43 __be16 dst; 43 __be16 dst;
44 }; 44 };
45 45
46 struct arppayload 46 struct arppayload
47 { 47 {
48 unsigned char mac_src[ETH_ALEN]; 48 unsigned char mac_src[ETH_ALEN];
49 unsigned char ip_src[4]; 49 unsigned char ip_src[4];
50 unsigned char mac_dst[ETH_ALEN]; 50 unsigned char mac_dst[ETH_ALEN];
51 unsigned char ip_dst[4]; 51 unsigned char ip_dst[4];
52 }; 52 };
53 53
54 static void print_MAC(const unsigned char *p) 54 static void print_MAC(const unsigned char *p)
55 { 55 {
56 int i; 56 int i;
57 57
58 for (i = 0; i < ETH_ALEN; i++, p++) 58 for (i = 0; i < ETH_ALEN; i++, p++)
59 printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':'); 59 printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':');
60 } 60 }
61 61
62 static void 62 static void
63 print_ports(const struct sk_buff *skb, uint8_t protocol, int offset) 63 print_ports(const struct sk_buff *skb, uint8_t protocol, int offset)
64 { 64 {
65 if (protocol == IPPROTO_TCP || 65 if (protocol == IPPROTO_TCP ||
66 protocol == IPPROTO_UDP || 66 protocol == IPPROTO_UDP ||
67 protocol == IPPROTO_UDPLITE || 67 protocol == IPPROTO_UDPLITE ||
68 protocol == IPPROTO_SCTP || 68 protocol == IPPROTO_SCTP ||
69 protocol == IPPROTO_DCCP) { 69 protocol == IPPROTO_DCCP) {
70 const struct tcpudphdr *pptr; 70 const struct tcpudphdr *pptr;
71 struct tcpudphdr _ports; 71 struct tcpudphdr _ports;
72 72
73 pptr = skb_header_pointer(skb, offset, 73 pptr = skb_header_pointer(skb, offset,
74 sizeof(_ports), &_ports); 74 sizeof(_ports), &_ports);
75 if (pptr == NULL) { 75 if (pptr == NULL) {
76 printk(" INCOMPLETE TCP/UDP header"); 76 printk(" INCOMPLETE TCP/UDP header");
77 return; 77 return;
78 } 78 }
79 printk(" SPT=%u DPT=%u", ntohs(pptr->src), ntohs(pptr->dst)); 79 printk(" SPT=%u DPT=%u", ntohs(pptr->src), ntohs(pptr->dst));
80 } 80 }
81 } 81 }
82 82
83 #define myNIPQUAD(a) a[0], a[1], a[2], a[3] 83 #define myNIPQUAD(a) a[0], a[1], a[2], a[3]
84 static void 84 static void
85 ebt_log_packet(u_int8_t pf, unsigned int hooknum, 85 ebt_log_packet(u_int8_t pf, unsigned int hooknum,
86 const struct sk_buff *skb, const struct net_device *in, 86 const struct sk_buff *skb, const struct net_device *in,
87 const struct net_device *out, const struct nf_loginfo *loginfo, 87 const struct net_device *out, const struct nf_loginfo *loginfo,
88 const char *prefix) 88 const char *prefix)
89 { 89 {
90 unsigned int bitmask; 90 unsigned int bitmask;
91 91
92 spin_lock_bh(&ebt_log_lock); 92 spin_lock_bh(&ebt_log_lock);
93 printk("<%c>%s IN=%s OUT=%s MAC source = ", '0' + loginfo->u.log.level, 93 printk("<%c>%s IN=%s OUT=%s MAC source = ", '0' + loginfo->u.log.level,
94 prefix, in ? in->name : "", out ? out->name : ""); 94 prefix, in ? in->name : "", out ? out->name : "");
95 95
96 print_MAC(eth_hdr(skb)->h_source); 96 print_MAC(eth_hdr(skb)->h_source);
97 printk("MAC dest = "); 97 printk("MAC dest = ");
98 print_MAC(eth_hdr(skb)->h_dest); 98 print_MAC(eth_hdr(skb)->h_dest);
99 99
100 printk("proto = 0x%04x", ntohs(eth_hdr(skb)->h_proto)); 100 printk("proto = 0x%04x", ntohs(eth_hdr(skb)->h_proto));
101 101
102 if (loginfo->type == NF_LOG_TYPE_LOG) 102 if (loginfo->type == NF_LOG_TYPE_LOG)
103 bitmask = loginfo->u.log.logflags; 103 bitmask = loginfo->u.log.logflags;
104 else 104 else
105 bitmask = NF_LOG_MASK; 105 bitmask = NF_LOG_MASK;
106 106
107 if ((bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto == 107 if ((bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto ==
108 htons(ETH_P_IP)){ 108 htons(ETH_P_IP)){
109 const struct iphdr *ih; 109 const struct iphdr *ih;
110 struct iphdr _iph; 110 struct iphdr _iph;
111 111
112 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); 112 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
113 if (ih == NULL) { 113 if (ih == NULL) {
114 printk(" INCOMPLETE IP header"); 114 printk(" INCOMPLETE IP header");
115 goto out; 115 goto out;
116 } 116 }
117 printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u, IP " 117 printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u, IP "
118 "tos=0x%02X, IP proto=%d", NIPQUAD(ih->saddr), 118 "tos=0x%02X, IP proto=%d", NIPQUAD(ih->saddr),
119 NIPQUAD(ih->daddr), ih->tos, ih->protocol); 119 NIPQUAD(ih->daddr), ih->tos, ih->protocol);
120 print_ports(skb, ih->protocol, ih->ihl*4); 120 print_ports(skb, ih->protocol, ih->ihl*4);
121 goto out; 121 goto out;
122 } 122 }
123 123
124 #if defined(CONFIG_BRIDGE_EBT_IP6) || defined(CONFIG_BRIDGE_EBT_IP6_MODULE) 124 #if defined(CONFIG_BRIDGE_EBT_IP6) || defined(CONFIG_BRIDGE_EBT_IP6_MODULE)
125 if ((bitmask & EBT_LOG_IP6) && eth_hdr(skb)->h_proto == 125 if ((bitmask & EBT_LOG_IP6) && eth_hdr(skb)->h_proto ==
126 htons(ETH_P_IPV6)) { 126 htons(ETH_P_IPV6)) {
127 const struct ipv6hdr *ih; 127 const struct ipv6hdr *ih;
128 struct ipv6hdr _iph; 128 struct ipv6hdr _iph;
129 uint8_t nexthdr; 129 uint8_t nexthdr;
130 int offset_ph; 130 int offset_ph;
131 131
132 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); 132 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
133 if (ih == NULL) { 133 if (ih == NULL) {
134 printk(" INCOMPLETE IPv6 header"); 134 printk(" INCOMPLETE IPv6 header");
135 goto out; 135 goto out;
136 } 136 }
137 printk(" IPv6 SRC=%x:%x:%x:%x:%x:%x:%x:%x " 137 printk(" IPv6 SRC=%x:%x:%x:%x:%x:%x:%x:%x "
138 "IPv6 DST=%x:%x:%x:%x:%x:%x:%x:%x, IPv6 " 138 "IPv6 DST=%x:%x:%x:%x:%x:%x:%x:%x, IPv6 "
139 "priority=0x%01X, Next Header=%d", NIP6(ih->saddr), 139 "priority=0x%01X, Next Header=%d", NIP6(ih->saddr),
140 NIP6(ih->daddr), ih->priority, ih->nexthdr); 140 NIP6(ih->daddr), ih->priority, ih->nexthdr);
141 nexthdr = ih->nexthdr; 141 nexthdr = ih->nexthdr;
142 offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr); 142 offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr);
143 if (offset_ph == -1) 143 if (offset_ph == -1)
144 goto out; 144 goto out;
145 print_ports(skb, nexthdr, offset_ph); 145 print_ports(skb, nexthdr, offset_ph);
146 goto out; 146 goto out;
147 } 147 }
148 #endif 148 #endif
149 149
150 if ((bitmask & EBT_LOG_ARP) && 150 if ((bitmask & EBT_LOG_ARP) &&
151 ((eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) || 151 ((eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) ||
152 (eth_hdr(skb)->h_proto == htons(ETH_P_RARP)))) { 152 (eth_hdr(skb)->h_proto == htons(ETH_P_RARP)))) {
153 const struct arphdr *ah; 153 const struct arphdr *ah;
154 struct arphdr _arph; 154 struct arphdr _arph;
155 155
156 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); 156 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
157 if (ah == NULL) { 157 if (ah == NULL) {
158 printk(" INCOMPLETE ARP header"); 158 printk(" INCOMPLETE ARP header");
159 goto out; 159 goto out;
160 } 160 }
161 printk(" ARP HTYPE=%d, PTYPE=0x%04x, OPCODE=%d", 161 printk(" ARP HTYPE=%d, PTYPE=0x%04x, OPCODE=%d",
162 ntohs(ah->ar_hrd), ntohs(ah->ar_pro), 162 ntohs(ah->ar_hrd), ntohs(ah->ar_pro),
163 ntohs(ah->ar_op)); 163 ntohs(ah->ar_op));
164 164
165 /* If it's for Ethernet and the lengths are OK, 165 /* If it's for Ethernet and the lengths are OK,
166 * then log the ARP payload */ 166 * then log the ARP payload */
167 if (ah->ar_hrd == htons(1) && 167 if (ah->ar_hrd == htons(1) &&
168 ah->ar_hln == ETH_ALEN && 168 ah->ar_hln == ETH_ALEN &&
169 ah->ar_pln == sizeof(__be32)) { 169 ah->ar_pln == sizeof(__be32)) {
170 const struct arppayload *ap; 170 const struct arppayload *ap;
171 struct arppayload _arpp; 171 struct arppayload _arpp;
172 172
173 ap = skb_header_pointer(skb, sizeof(_arph), 173 ap = skb_header_pointer(skb, sizeof(_arph),
174 sizeof(_arpp), &_arpp); 174 sizeof(_arpp), &_arpp);
175 if (ap == NULL) { 175 if (ap == NULL) {
176 printk(" INCOMPLETE ARP payload"); 176 printk(" INCOMPLETE ARP payload");
177 goto out; 177 goto out;
178 } 178 }
179 printk(" ARP MAC SRC="); 179 printk(" ARP MAC SRC=");
180 print_MAC(ap->mac_src); 180 print_MAC(ap->mac_src);
181 printk(" ARP IP SRC=%u.%u.%u.%u", 181 printk(" ARP IP SRC=%u.%u.%u.%u",
182 myNIPQUAD(ap->ip_src)); 182 myNIPQUAD(ap->ip_src));
183 printk(" ARP MAC DST="); 183 printk(" ARP MAC DST=");
184 print_MAC(ap->mac_dst); 184 print_MAC(ap->mac_dst);
185 printk(" ARP IP DST=%u.%u.%u.%u", 185 printk(" ARP IP DST=%u.%u.%u.%u",
186 myNIPQUAD(ap->ip_dst)); 186 myNIPQUAD(ap->ip_dst));
187 } 187 }
188 } 188 }
189 out: 189 out:
190 printk("\n"); 190 printk("\n");
191 spin_unlock_bh(&ebt_log_lock); 191 spin_unlock_bh(&ebt_log_lock);
192 192
193 } 193 }
194 194
195 static void ebt_log(const struct sk_buff *skb, unsigned int hooknr, 195 static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
196 const struct net_device *in, const struct net_device *out, 196 const struct net_device *in, const struct net_device *out,
197 const void *data, unsigned int datalen) 197 const void *data, unsigned int datalen)
198 { 198 {
199 const struct ebt_log_info *info = data; 199 const struct ebt_log_info *info = data;
200 struct nf_loginfo li; 200 struct nf_loginfo li;
201 201
202 li.type = NF_LOG_TYPE_LOG; 202 li.type = NF_LOG_TYPE_LOG;
203 li.u.log.level = info->loglevel; 203 li.u.log.level = info->loglevel;
204 li.u.log.logflags = info->bitmask; 204 li.u.log.logflags = info->bitmask;
205 205
206 if (info->bitmask & EBT_LOG_NFLOG) 206 if (info->bitmask & EBT_LOG_NFLOG)
207 nf_log_packet(NFPROTO_BRIDGE, hooknr, skb, in, out, &li, 207 nf_log_packet(NFPROTO_BRIDGE, hooknr, skb, in, out, &li,
208 "%s", info->prefix); 208 "%s", info->prefix);
209 else 209 else
210 ebt_log_packet(NFPROTO_BRIDGE, hooknr, skb, in, out, &li, 210 ebt_log_packet(NFPROTO_BRIDGE, hooknr, skb, in, out, &li,
211 info->prefix); 211 info->prefix);
212 } 212 }
213 213
214 static struct ebt_watcher log = 214 static struct ebt_watcher log =
215 { 215 {
216 .name = EBT_LOG_WATCHER, 216 .name = EBT_LOG_WATCHER,
217 .watcher = ebt_log, 217 .watcher = ebt_log,
218 .check = ebt_log_check, 218 .check = ebt_log_check,
219 .targetsize = XT_ALIGN(sizeof(struct ebt_log_info)), 219 .targetsize = XT_ALIGN(sizeof(struct ebt_log_info)),
220 .me = THIS_MODULE, 220 .me = THIS_MODULE,
221 }; 221 };
222 222
223 static const struct nf_logger ebt_log_logger = { 223 static const struct nf_logger ebt_log_logger = {
224 .name = "ebt_log", 224 .name = "ebt_log",
225 .logfn = &ebt_log_packet, 225 .logfn = &ebt_log_packet,
226 .me = THIS_MODULE, 226 .me = THIS_MODULE,
227 }; 227 };
228 228
229 static int __init ebt_log_init(void) 229 static int __init ebt_log_init(void)
230 { 230 {
231 int ret; 231 int ret;
232 232
233 ret = ebt_register_watcher(&log); 233 ret = ebt_register_watcher(&log);
234 if (ret < 0) 234 if (ret < 0)
235 return ret; 235 return ret;
236 nf_log_register(NFPROTO_BRIDGE, &ebt_log_logger); 236 nf_log_register(NFPROTO_BRIDGE, &ebt_log_logger);
237 return 0; 237 return 0;
238 } 238 }
239 239
240 static void __exit ebt_log_fini(void) 240 static void __exit ebt_log_fini(void)
241 { 241 {
242 nf_log_unregister(&ebt_log_logger); 242 nf_log_unregister(&ebt_log_logger);
243 ebt_unregister_watcher(&log); 243 ebt_unregister_watcher(&log);
244 } 244 }
245 245
246 module_init(ebt_log_init); 246 module_init(ebt_log_init);
247 module_exit(ebt_log_fini); 247 module_exit(ebt_log_fini);
248 MODULE_DESCRIPTION("Ebtables: Packet logging to syslog"); 248 MODULE_DESCRIPTION("Ebtables: Packet logging to syslog");
249 MODULE_LICENSE("GPL"); 249 MODULE_LICENSE("GPL");
250 250
net/bridge/netfilter/ebt_mark.c
1 /* 1 /*
2 * ebt_mark 2 * ebt_mark
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * 6 *
7 * July, 2002 7 * July, 2002
8 * 8 *
9 */ 9 */
10 10
11 /* The mark target can be used in any chain, 11 /* The mark target can be used in any chain,
12 * I believe adding a mangle table just for marking is total overkill. 12 * I believe adding a mangle table just for marking is total overkill.
13 * Marking a frame doesn't really change anything in the frame anyway. 13 * Marking a frame doesn't really change anything in the frame anyway.
14 */ 14 */
15 15
16 #include <linux/module.h> 16 #include <linux/module.h>
17 #include <linux/netfilter/x_tables.h> 17 #include <linux/netfilter/x_tables.h>
18 #include <linux/netfilter_bridge/ebtables.h> 18 #include <linux/netfilter_bridge/ebtables.h>
19 #include <linux/netfilter_bridge/ebt_mark_t.h> 19 #include <linux/netfilter_bridge/ebt_mark_t.h>
20 20
21 static int ebt_target_mark(struct sk_buff *skb, unsigned int hooknr, 21 static int ebt_target_mark(struct sk_buff *skb, unsigned int hooknr,
22 const struct net_device *in, const struct net_device *out, 22 const struct net_device *in, const struct net_device *out,
23 const void *data, unsigned int datalen) 23 const void *data, unsigned int datalen)
24 { 24 {
25 const struct ebt_mark_t_info *info = data; 25 const struct ebt_mark_t_info *info = data;
26 int action = info->target & -16; 26 int action = info->target & -16;
27 27
28 if (action == MARK_SET_VALUE) 28 if (action == MARK_SET_VALUE)
29 skb->mark = info->mark; 29 skb->mark = info->mark;
30 else if (action == MARK_OR_VALUE) 30 else if (action == MARK_OR_VALUE)
31 skb->mark |= info->mark; 31 skb->mark |= info->mark;
32 else if (action == MARK_AND_VALUE) 32 else if (action == MARK_AND_VALUE)
33 skb->mark &= info->mark; 33 skb->mark &= info->mark;
34 else 34 else
35 skb->mark ^= info->mark; 35 skb->mark ^= info->mark;
36 36
37 return info->target | ~EBT_VERDICT_BITS; 37 return info->target | ~EBT_VERDICT_BITS;
38 } 38 }
39 39
40 static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, 40 static bool ebt_target_mark_check(const char *tablename, unsigned int hookmask,
41 const struct ebt_entry *e, void *data, unsigned int datalen) 41 const struct ebt_entry *e, void *data, unsigned int datalen)
42 { 42 {
43 const struct ebt_mark_t_info *info = data; 43 const struct ebt_mark_t_info *info = data;
44 int tmp; 44 int tmp;
45 45
46 tmp = info->target | ~EBT_VERDICT_BITS; 46 tmp = info->target | ~EBT_VERDICT_BITS;
47 if (BASE_CHAIN && tmp == EBT_RETURN) 47 if (BASE_CHAIN && tmp == EBT_RETURN)
48 return -EINVAL; 48 return false;
49 CLEAR_BASE_CHAIN_BIT; 49 CLEAR_BASE_CHAIN_BIT;
50 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) 50 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
51 return -EINVAL; 51 return false;
52 tmp = info->target & ~EBT_VERDICT_BITS; 52 tmp = info->target & ~EBT_VERDICT_BITS;
53 if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE && 53 if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
54 tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE) 54 tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE)
55 return -EINVAL; 55 return false;
56 return 0; 56 return true;
57 } 57 }
58 58
59 static struct ebt_target mark_target __read_mostly = { 59 static struct ebt_target mark_target __read_mostly = {
60 .name = EBT_MARK_TARGET, 60 .name = EBT_MARK_TARGET,
61 .target = ebt_target_mark, 61 .target = ebt_target_mark,
62 .check = ebt_target_mark_check, 62 .check = ebt_target_mark_check,
63 .targetsize = XT_ALIGN(sizeof(struct ebt_mark_t_info)), 63 .targetsize = XT_ALIGN(sizeof(struct ebt_mark_t_info)),
64 .me = THIS_MODULE, 64 .me = THIS_MODULE,
65 }; 65 };
66 66
67 static int __init ebt_mark_init(void) 67 static int __init ebt_mark_init(void)
68 { 68 {
69 return ebt_register_target(&mark_target); 69 return ebt_register_target(&mark_target);
70 } 70 }
71 71
72 static void __exit ebt_mark_fini(void) 72 static void __exit ebt_mark_fini(void)
73 { 73 {
74 ebt_unregister_target(&mark_target); 74 ebt_unregister_target(&mark_target);
75 } 75 }
76 76
77 module_init(ebt_mark_init); 77 module_init(ebt_mark_init);
78 module_exit(ebt_mark_fini); 78 module_exit(ebt_mark_fini);
79 MODULE_DESCRIPTION("Ebtables: Packet mark modification"); 79 MODULE_DESCRIPTION("Ebtables: Packet mark modification");
80 MODULE_LICENSE("GPL"); 80 MODULE_LICENSE("GPL");
81 81
net/bridge/netfilter/ebt_mark_m.c
1 /* 1 /*
2 * ebt_mark_m 2 * ebt_mark_m
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * 6 *
7 * July, 2002 7 * July, 2002
8 * 8 *
9 */ 9 */
10 #include <linux/module.h> 10 #include <linux/module.h>
11 #include <linux/netfilter/x_tables.h> 11 #include <linux/netfilter/x_tables.h>
12 #include <linux/netfilter_bridge/ebtables.h> 12 #include <linux/netfilter_bridge/ebtables.h>
13 #include <linux/netfilter_bridge/ebt_mark_m.h> 13 #include <linux/netfilter_bridge/ebt_mark_m.h>
14 14
15 static int ebt_filter_mark(const struct sk_buff *skb, 15 static int ebt_filter_mark(const struct sk_buff *skb,
16 const struct net_device *in, const struct net_device *out, const void *data, 16 const struct net_device *in, const struct net_device *out, const void *data,
17 unsigned int datalen) 17 unsigned int datalen)
18 { 18 {
19 const struct ebt_mark_m_info *info = data; 19 const struct ebt_mark_m_info *info = data;
20 20
21 if (info->bitmask & EBT_MARK_OR) 21 if (info->bitmask & EBT_MARK_OR)
22 return !(!!(skb->mark & info->mask) ^ info->invert); 22 return !(!!(skb->mark & info->mask) ^ info->invert);
23 return !(((skb->mark & info->mask) == info->mark) ^ info->invert); 23 return !(((skb->mark & info->mask) == info->mark) ^ info->invert);
24 } 24 }
25 25
26 static int ebt_mark_check(const char *tablename, unsigned int hookmask, 26 static bool ebt_mark_check(const char *tablename, unsigned int hookmask,
27 const struct ebt_entry *e, void *data, unsigned int datalen) 27 const struct ebt_entry *e, void *data, unsigned int datalen)
28 { 28 {
29 const struct ebt_mark_m_info *info = data; 29 const struct ebt_mark_m_info *info = data;
30 30
31 if (info->bitmask & ~EBT_MARK_MASK) 31 if (info->bitmask & ~EBT_MARK_MASK)
32 return -EINVAL; 32 return false;
33 if ((info->bitmask & EBT_MARK_OR) && (info->bitmask & EBT_MARK_AND)) 33 if ((info->bitmask & EBT_MARK_OR) && (info->bitmask & EBT_MARK_AND))
34 return -EINVAL; 34 return false;
35 if (!info->bitmask) 35 if (!info->bitmask)
36 return -EINVAL; 36 return false;
37 return 0; 37 return true;
38 } 38 }
39 39
40 static struct ebt_match filter_mark __read_mostly = { 40 static struct ebt_match filter_mark __read_mostly = {
41 .name = EBT_MARK_MATCH, 41 .name = EBT_MARK_MATCH,
42 .match = ebt_filter_mark, 42 .match = ebt_filter_mark,
43 .check = ebt_mark_check, 43 .check = ebt_mark_check,
44 .matchsize = XT_ALIGN(sizeof(struct ebt_mark_m_info)), 44 .matchsize = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
45 .me = THIS_MODULE, 45 .me = THIS_MODULE,
46 }; 46 };
47 47
48 static int __init ebt_mark_m_init(void) 48 static int __init ebt_mark_m_init(void)
49 { 49 {
50 return ebt_register_match(&filter_mark); 50 return ebt_register_match(&filter_mark);
51 } 51 }
52 52
53 static void __exit ebt_mark_m_fini(void) 53 static void __exit ebt_mark_m_fini(void)
54 { 54 {
55 ebt_unregister_match(&filter_mark); 55 ebt_unregister_match(&filter_mark);
56 } 56 }
57 57
58 module_init(ebt_mark_m_init); 58 module_init(ebt_mark_m_init);
59 module_exit(ebt_mark_m_fini); 59 module_exit(ebt_mark_m_fini);
60 MODULE_DESCRIPTION("Ebtables: Packet mark match"); 60 MODULE_DESCRIPTION("Ebtables: Packet mark match");
61 MODULE_LICENSE("GPL"); 61 MODULE_LICENSE("GPL");
62 62
net/bridge/netfilter/ebt_nflog.c
1 /* 1 /*
2 * ebt_nflog 2 * ebt_nflog
3 * 3 *
4 * Author: 4 * Author:
5 * Peter Warasin <peter@endian.com> 5 * Peter Warasin <peter@endian.com>
6 * 6 *
7 * February, 2008 7 * February, 2008
8 * 8 *
9 * Based on: 9 * Based on:
10 * xt_NFLOG.c, (C) 2006 by Patrick McHardy <kaber@trash.net> 10 * xt_NFLOG.c, (C) 2006 by Patrick McHardy <kaber@trash.net>
11 * ebt_ulog.c, (C) 2004 by Bart De Schuymer <bdschuym@pandora.be> 11 * ebt_ulog.c, (C) 2004 by Bart De Schuymer <bdschuym@pandora.be>
12 * 12 *
13 */ 13 */
14 14
15 #include <linux/module.h> 15 #include <linux/module.h>
16 #include <linux/spinlock.h> 16 #include <linux/spinlock.h>
17 #include <linux/netfilter/x_tables.h> 17 #include <linux/netfilter/x_tables.h>
18 #include <linux/netfilter_bridge/ebtables.h> 18 #include <linux/netfilter_bridge/ebtables.h>
19 #include <linux/netfilter_bridge/ebt_nflog.h> 19 #include <linux/netfilter_bridge/ebt_nflog.h>
20 #include <net/netfilter/nf_log.h> 20 #include <net/netfilter/nf_log.h>
21 21
22 static void ebt_nflog(const struct sk_buff *skb, 22 static void ebt_nflog(const struct sk_buff *skb,
23 unsigned int hooknr, 23 unsigned int hooknr,
24 const struct net_device *in, 24 const struct net_device *in,
25 const struct net_device *out, 25 const struct net_device *out,
26 const void *data, unsigned int datalen) 26 const void *data, unsigned int datalen)
27 { 27 {
28 struct ebt_nflog_info *info = (struct ebt_nflog_info *)data; 28 struct ebt_nflog_info *info = (struct ebt_nflog_info *)data;
29 struct nf_loginfo li; 29 struct nf_loginfo li;
30 30
31 li.type = NF_LOG_TYPE_ULOG; 31 li.type = NF_LOG_TYPE_ULOG;
32 li.u.ulog.copy_len = info->len; 32 li.u.ulog.copy_len = info->len;
33 li.u.ulog.group = info->group; 33 li.u.ulog.group = info->group;
34 li.u.ulog.qthreshold = info->threshold; 34 li.u.ulog.qthreshold = info->threshold;
35 35
36 nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, "%s", info->prefix); 36 nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, "%s", info->prefix);
37 } 37 }
38 38
39 static int ebt_nflog_check(const char *tablename, 39 static bool ebt_nflog_check(const char *tablename,
40 unsigned int hookmask, 40 unsigned int hookmask,
41 const struct ebt_entry *e, 41 const struct ebt_entry *e,
42 void *data, unsigned int datalen) 42 void *data, unsigned int datalen)
43 { 43 {
44 struct ebt_nflog_info *info = (struct ebt_nflog_info *)data; 44 struct ebt_nflog_info *info = (struct ebt_nflog_info *)data;
45 45
46 if (info->flags & ~EBT_NFLOG_MASK) 46 if (info->flags & ~EBT_NFLOG_MASK)
47 return -EINVAL; 47 return false;
48 info->prefix[EBT_NFLOG_PREFIX_SIZE - 1] = '\0'; 48 info->prefix[EBT_NFLOG_PREFIX_SIZE - 1] = '\0';
49 return 0; 49 return true;
50 } 50 }
51 51
52 static struct ebt_watcher nflog __read_mostly = { 52 static struct ebt_watcher nflog __read_mostly = {
53 .name = EBT_NFLOG_WATCHER, 53 .name = EBT_NFLOG_WATCHER,
54 .watcher = ebt_nflog, 54 .watcher = ebt_nflog,
55 .check = ebt_nflog_check, 55 .check = ebt_nflog_check,
56 .targetsize = XT_ALIGN(sizeof(struct ebt_nflog_info)), 56 .targetsize = XT_ALIGN(sizeof(struct ebt_nflog_info)),
57 .me = THIS_MODULE, 57 .me = THIS_MODULE,
58 }; 58 };
59 59
60 static int __init ebt_nflog_init(void) 60 static int __init ebt_nflog_init(void)
61 { 61 {
62 return ebt_register_watcher(&nflog); 62 return ebt_register_watcher(&nflog);
63 } 63 }
64 64
65 static void __exit ebt_nflog_fini(void) 65 static void __exit ebt_nflog_fini(void)
66 { 66 {
67 ebt_unregister_watcher(&nflog); 67 ebt_unregister_watcher(&nflog);
68 } 68 }
69 69
70 module_init(ebt_nflog_init); 70 module_init(ebt_nflog_init);
71 module_exit(ebt_nflog_fini); 71 module_exit(ebt_nflog_fini);
72 MODULE_LICENSE("GPL"); 72 MODULE_LICENSE("GPL");
73 MODULE_AUTHOR("Peter Warasin <peter@endian.com>"); 73 MODULE_AUTHOR("Peter Warasin <peter@endian.com>");
74 MODULE_DESCRIPTION("ebtables NFLOG netfilter logging module"); 74 MODULE_DESCRIPTION("ebtables NFLOG netfilter logging module");
75 75
net/bridge/netfilter/ebt_pkttype.c
1 /* 1 /*
2 * ebt_pkttype 2 * ebt_pkttype
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * 6 *
7 * April, 2003 7 * April, 2003
8 * 8 *
9 */ 9 */
10 #include <linux/module.h> 10 #include <linux/module.h>
11 #include <linux/netfilter/x_tables.h> 11 #include <linux/netfilter/x_tables.h>
12 #include <linux/netfilter_bridge/ebtables.h> 12 #include <linux/netfilter_bridge/ebtables.h>
13 #include <linux/netfilter_bridge/ebt_pkttype.h> 13 #include <linux/netfilter_bridge/ebt_pkttype.h>
14 14
15 static int ebt_filter_pkttype(const struct sk_buff *skb, 15 static int ebt_filter_pkttype(const struct sk_buff *skb,
16 const struct net_device *in, 16 const struct net_device *in,
17 const struct net_device *out, 17 const struct net_device *out,
18 const void *data, 18 const void *data,
19 unsigned int datalen) 19 unsigned int datalen)
20 { 20 {
21 const struct ebt_pkttype_info *info = data; 21 const struct ebt_pkttype_info *info = data;
22 22
23 return (skb->pkt_type != info->pkt_type) ^ info->invert; 23 return (skb->pkt_type != info->pkt_type) ^ info->invert;
24 } 24 }
25 25
26 static int ebt_pkttype_check(const char *tablename, unsigned int hookmask, 26 static bool ebt_pkttype_check(const char *tablename, unsigned int hookmask,
27 const struct ebt_entry *e, void *data, unsigned int datalen) 27 const struct ebt_entry *e, void *data, unsigned int datalen)
28 { 28 {
29 const struct ebt_pkttype_info *info = data; 29 const struct ebt_pkttype_info *info = data;
30 30
31 if (info->invert != 0 && info->invert != 1) 31 if (info->invert != 0 && info->invert != 1)
32 return -EINVAL; 32 return false;
33 /* Allow any pkt_type value */ 33 /* Allow any pkt_type value */
34 return 0; 34 return true;
35 } 35 }
36 36
37 static struct ebt_match filter_pkttype __read_mostly = { 37 static struct ebt_match filter_pkttype __read_mostly = {
38 .name = EBT_PKTTYPE_MATCH, 38 .name = EBT_PKTTYPE_MATCH,
39 .match = ebt_filter_pkttype, 39 .match = ebt_filter_pkttype,
40 .check = ebt_pkttype_check, 40 .check = ebt_pkttype_check,
41 .matchsize = XT_ALIGN(sizeof(struct ebt_pkttype_info)), 41 .matchsize = XT_ALIGN(sizeof(struct ebt_pkttype_info)),
42 .me = THIS_MODULE, 42 .me = THIS_MODULE,
43 }; 43 };
44 44
45 static int __init ebt_pkttype_init(void) 45 static int __init ebt_pkttype_init(void)
46 { 46 {
47 return ebt_register_match(&filter_pkttype); 47 return ebt_register_match(&filter_pkttype);
48 } 48 }
49 49
50 static void __exit ebt_pkttype_fini(void) 50 static void __exit ebt_pkttype_fini(void)
51 { 51 {
52 ebt_unregister_match(&filter_pkttype); 52 ebt_unregister_match(&filter_pkttype);
53 } 53 }
54 54
55 module_init(ebt_pkttype_init); 55 module_init(ebt_pkttype_init);
56 module_exit(ebt_pkttype_fini); 56 module_exit(ebt_pkttype_fini);
57 MODULE_DESCRIPTION("Ebtables: Link layer packet type match"); 57 MODULE_DESCRIPTION("Ebtables: Link layer packet type match");
58 MODULE_LICENSE("GPL"); 58 MODULE_LICENSE("GPL");
59 59
net/bridge/netfilter/ebt_redirect.c
1 /* 1 /*
2 * ebt_redirect 2 * ebt_redirect
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * 6 *
7 * April, 2002 7 * April, 2002
8 * 8 *
9 */ 9 */
10 #include <linux/module.h> 10 #include <linux/module.h>
11 #include <net/sock.h> 11 #include <net/sock.h>
12 #include "../br_private.h" 12 #include "../br_private.h"
13 #include <linux/netfilter.h> 13 #include <linux/netfilter.h>
14 #include <linux/netfilter/x_tables.h> 14 #include <linux/netfilter/x_tables.h>
15 #include <linux/netfilter_bridge/ebtables.h> 15 #include <linux/netfilter_bridge/ebtables.h>
16 #include <linux/netfilter_bridge/ebt_redirect.h> 16 #include <linux/netfilter_bridge/ebt_redirect.h>
17 17
18 static int ebt_target_redirect(struct sk_buff *skb, unsigned int hooknr, 18 static int ebt_target_redirect(struct sk_buff *skb, unsigned int hooknr,
19 const struct net_device *in, const struct net_device *out, 19 const struct net_device *in, const struct net_device *out,
20 const void *data, unsigned int datalen) 20 const void *data, unsigned int datalen)
21 { 21 {
22 const struct ebt_redirect_info *info = data; 22 const struct ebt_redirect_info *info = data;
23 23
24 if (!skb_make_writable(skb, 0)) 24 if (!skb_make_writable(skb, 0))
25 return EBT_DROP; 25 return EBT_DROP;
26 26
27 if (hooknr != NF_BR_BROUTING) 27 if (hooknr != NF_BR_BROUTING)
28 memcpy(eth_hdr(skb)->h_dest, 28 memcpy(eth_hdr(skb)->h_dest,
29 in->br_port->br->dev->dev_addr, ETH_ALEN); 29 in->br_port->br->dev->dev_addr, ETH_ALEN);
30 else 30 else
31 memcpy(eth_hdr(skb)->h_dest, in->dev_addr, ETH_ALEN); 31 memcpy(eth_hdr(skb)->h_dest, in->dev_addr, ETH_ALEN);
32 skb->pkt_type = PACKET_HOST; 32 skb->pkt_type = PACKET_HOST;
33 return info->target; 33 return info->target;
34 } 34 }
35 35
36 static int ebt_target_redirect_check(const char *tablename, unsigned int hookmask, 36 static bool ebt_target_redirect_check(const char *tablename, unsigned int hookmask,
37 const struct ebt_entry *e, void *data, unsigned int datalen) 37 const struct ebt_entry *e, void *data, unsigned int datalen)
38 { 38 {
39 const struct ebt_redirect_info *info = data; 39 const struct ebt_redirect_info *info = data;
40 40
41 if (BASE_CHAIN && info->target == EBT_RETURN) 41 if (BASE_CHAIN && info->target == EBT_RETURN)
42 return -EINVAL; 42 return false;
43 CLEAR_BASE_CHAIN_BIT; 43 CLEAR_BASE_CHAIN_BIT;
44 if ( (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING)) && 44 if ( (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING)) &&
45 (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) ) 45 (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) )
46 return -EINVAL; 46 return false;
47 if (INVALID_TARGET) 47 if (INVALID_TARGET)
48 return -EINVAL; 48 return false;
49 return 0; 49 return true;
50 } 50 }
51 51
52 static struct ebt_target redirect_target __read_mostly = { 52 static struct ebt_target redirect_target __read_mostly = {
53 .name = EBT_REDIRECT_TARGET, 53 .name = EBT_REDIRECT_TARGET,
54 .target = ebt_target_redirect, 54 .target = ebt_target_redirect,
55 .check = ebt_target_redirect_check, 55 .check = ebt_target_redirect_check,
56 .targetsize = XT_ALIGN(sizeof(struct ebt_redirect_info)), 56 .targetsize = XT_ALIGN(sizeof(struct ebt_redirect_info)),
57 .me = THIS_MODULE, 57 .me = THIS_MODULE,
58 }; 58 };
59 59
60 static int __init ebt_redirect_init(void) 60 static int __init ebt_redirect_init(void)
61 { 61 {
62 return ebt_register_target(&redirect_target); 62 return ebt_register_target(&redirect_target);
63 } 63 }
64 64
65 static void __exit ebt_redirect_fini(void) 65 static void __exit ebt_redirect_fini(void)
66 { 66 {
67 ebt_unregister_target(&redirect_target); 67 ebt_unregister_target(&redirect_target);
68 } 68 }
69 69
70 module_init(ebt_redirect_init); 70 module_init(ebt_redirect_init);
71 module_exit(ebt_redirect_fini); 71 module_exit(ebt_redirect_fini);
72 MODULE_DESCRIPTION("Ebtables: Packet redirection to localhost"); 72 MODULE_DESCRIPTION("Ebtables: Packet redirection to localhost");
73 MODULE_LICENSE("GPL"); 73 MODULE_LICENSE("GPL");
74 74
net/bridge/netfilter/ebt_snat.c
1 /* 1 /*
2 * ebt_snat 2 * ebt_snat
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * 6 *
7 * June, 2002 7 * June, 2002
8 * 8 *
9 */ 9 */
10 #include <linux/module.h> 10 #include <linux/module.h>
11 #include <net/sock.h> 11 #include <net/sock.h>
12 #include <linux/if_arp.h> 12 #include <linux/if_arp.h>
13 #include <net/arp.h> 13 #include <net/arp.h>
14 #include <linux/netfilter.h> 14 #include <linux/netfilter.h>
15 #include <linux/netfilter/x_tables.h> 15 #include <linux/netfilter/x_tables.h>
16 #include <linux/netfilter_bridge/ebtables.h> 16 #include <linux/netfilter_bridge/ebtables.h>
17 #include <linux/netfilter_bridge/ebt_nat.h> 17 #include <linux/netfilter_bridge/ebt_nat.h>
18 18
19 static int ebt_target_snat(struct sk_buff *skb, unsigned int hooknr, 19 static int ebt_target_snat(struct sk_buff *skb, unsigned int hooknr,
20 const struct net_device *in, const struct net_device *out, 20 const struct net_device *in, const struct net_device *out,
21 const void *data, unsigned int datalen) 21 const void *data, unsigned int datalen)
22 { 22 {
23 const struct ebt_nat_info *info = data; 23 const struct ebt_nat_info *info = data;
24 24
25 if (!skb_make_writable(skb, 0)) 25 if (!skb_make_writable(skb, 0))
26 return EBT_DROP; 26 return EBT_DROP;
27 27
28 memcpy(eth_hdr(skb)->h_source, info->mac, ETH_ALEN); 28 memcpy(eth_hdr(skb)->h_source, info->mac, ETH_ALEN);
29 if (!(info->target & NAT_ARP_BIT) && 29 if (!(info->target & NAT_ARP_BIT) &&
30 eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { 30 eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
31 const struct arphdr *ap; 31 const struct arphdr *ap;
32 struct arphdr _ah; 32 struct arphdr _ah;
33 33
34 ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); 34 ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
35 if (ap == NULL) 35 if (ap == NULL)
36 return EBT_DROP; 36 return EBT_DROP;
37 if (ap->ar_hln != ETH_ALEN) 37 if (ap->ar_hln != ETH_ALEN)
38 goto out; 38 goto out;
39 if (skb_store_bits(skb, sizeof(_ah), info->mac,ETH_ALEN)) 39 if (skb_store_bits(skb, sizeof(_ah), info->mac,ETH_ALEN))
40 return EBT_DROP; 40 return EBT_DROP;
41 } 41 }
42 out: 42 out:
43 return info->target | ~EBT_VERDICT_BITS; 43 return info->target | ~EBT_VERDICT_BITS;
44 } 44 }
45 45
46 static int ebt_target_snat_check(const char *tablename, unsigned int hookmask, 46 static bool ebt_target_snat_check(const char *tablename, unsigned int hookmask,
47 const struct ebt_entry *e, void *data, unsigned int datalen) 47 const struct ebt_entry *e, void *data, unsigned int datalen)
48 { 48 {
49 const struct ebt_nat_info *info = data; 49 const struct ebt_nat_info *info = data;
50 int tmp; 50 int tmp;
51 51
52 tmp = info->target | ~EBT_VERDICT_BITS; 52 tmp = info->target | ~EBT_VERDICT_BITS;
53 if (BASE_CHAIN && tmp == EBT_RETURN) 53 if (BASE_CHAIN && tmp == EBT_RETURN)
54 return -EINVAL; 54 return false;
55 CLEAR_BASE_CHAIN_BIT; 55 CLEAR_BASE_CHAIN_BIT;
56 if (strcmp(tablename, "nat")) 56 if (strcmp(tablename, "nat"))
57 return -EINVAL; 57 return false;
58 if (hookmask & ~(1 << NF_BR_POST_ROUTING)) 58 if (hookmask & ~(1 << NF_BR_POST_ROUTING))
59 return -EINVAL; 59 return false;
60 60
61 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) 61 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
62 return -EINVAL; 62 return false;
63 tmp = info->target | EBT_VERDICT_BITS; 63 tmp = info->target | EBT_VERDICT_BITS;
64 if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT) 64 if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT)
65 return -EINVAL; 65 return false;
66 return 0; 66 return true;
67 } 67 }
68 68
69 static struct ebt_target snat __read_mostly = { 69 static struct ebt_target snat __read_mostly = {
70 .name = EBT_SNAT_TARGET, 70 .name = EBT_SNAT_TARGET,
71 .target = ebt_target_snat, 71 .target = ebt_target_snat,
72 .check = ebt_target_snat_check, 72 .check = ebt_target_snat_check,
73 .targetsize = XT_ALIGN(sizeof(struct ebt_nat_info)), 73 .targetsize = XT_ALIGN(sizeof(struct ebt_nat_info)),
74 .me = THIS_MODULE, 74 .me = THIS_MODULE,
75 }; 75 };
76 76
77 static int __init ebt_snat_init(void) 77 static int __init ebt_snat_init(void)
78 { 78 {
79 return ebt_register_target(&snat); 79 return ebt_register_target(&snat);
80 } 80 }
81 81
82 static void __exit ebt_snat_fini(void) 82 static void __exit ebt_snat_fini(void)
83 { 83 {
84 ebt_unregister_target(&snat); 84 ebt_unregister_target(&snat);
85 } 85 }
86 86
87 module_init(ebt_snat_init); 87 module_init(ebt_snat_init);
88 module_exit(ebt_snat_fini); 88 module_exit(ebt_snat_fini);
89 MODULE_DESCRIPTION("Ebtables: Source MAC address translation"); 89 MODULE_DESCRIPTION("Ebtables: Source MAC address translation");
90 MODULE_LICENSE("GPL"); 90 MODULE_LICENSE("GPL");
91 91
net/bridge/netfilter/ebt_stp.c
1 /* 1 /*
2 * ebt_stp 2 * ebt_stp
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * Stephen Hemminger <shemminger@osdl.org> 6 * Stephen Hemminger <shemminger@osdl.org>
7 * 7 *
8 * July, 2003 8 * July, 2003
9 */ 9 */
10 #include <linux/etherdevice.h> 10 #include <linux/etherdevice.h>
11 #include <linux/module.h> 11 #include <linux/module.h>
12 #include <linux/netfilter/x_tables.h> 12 #include <linux/netfilter/x_tables.h>
13 #include <linux/netfilter_bridge/ebtables.h> 13 #include <linux/netfilter_bridge/ebtables.h>
14 #include <linux/netfilter_bridge/ebt_stp.h> 14 #include <linux/netfilter_bridge/ebt_stp.h>
15 15
16 #define BPDU_TYPE_CONFIG 0 16 #define BPDU_TYPE_CONFIG 0
17 #define BPDU_TYPE_TCN 0x80 17 #define BPDU_TYPE_TCN 0x80
18 18
19 struct stp_header { 19 struct stp_header {
20 uint8_t dsap; 20 uint8_t dsap;
21 uint8_t ssap; 21 uint8_t ssap;
22 uint8_t ctrl; 22 uint8_t ctrl;
23 uint8_t pid; 23 uint8_t pid;
24 uint8_t vers; 24 uint8_t vers;
25 uint8_t type; 25 uint8_t type;
26 }; 26 };
27 27
28 struct stp_config_pdu { 28 struct stp_config_pdu {
29 uint8_t flags; 29 uint8_t flags;
30 uint8_t root[8]; 30 uint8_t root[8];
31 uint8_t root_cost[4]; 31 uint8_t root_cost[4];
32 uint8_t sender[8]; 32 uint8_t sender[8];
33 uint8_t port[2]; 33 uint8_t port[2];
34 uint8_t msg_age[2]; 34 uint8_t msg_age[2];
35 uint8_t max_age[2]; 35 uint8_t max_age[2];
36 uint8_t hello_time[2]; 36 uint8_t hello_time[2];
37 uint8_t forward_delay[2]; 37 uint8_t forward_delay[2];
38 }; 38 };
39 39
40 #define NR16(p) (p[0] << 8 | p[1]) 40 #define NR16(p) (p[0] << 8 | p[1])
41 #define NR32(p) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]) 41 #define NR32(p) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3])
42 42
43 static int ebt_filter_config(const struct ebt_stp_info *info, 43 static int ebt_filter_config(const struct ebt_stp_info *info,
44 const struct stp_config_pdu *stpc) 44 const struct stp_config_pdu *stpc)
45 { 45 {
46 const struct ebt_stp_config_info *c; 46 const struct ebt_stp_config_info *c;
47 uint16_t v16; 47 uint16_t v16;
48 uint32_t v32; 48 uint32_t v32;
49 int verdict, i; 49 int verdict, i;
50 50
51 c = &info->config; 51 c = &info->config;
52 if ((info->bitmask & EBT_STP_FLAGS) && 52 if ((info->bitmask & EBT_STP_FLAGS) &&
53 FWINV(c->flags != stpc->flags, EBT_STP_FLAGS)) 53 FWINV(c->flags != stpc->flags, EBT_STP_FLAGS))
54 return EBT_NOMATCH; 54 return EBT_NOMATCH;
55 if (info->bitmask & EBT_STP_ROOTPRIO) { 55 if (info->bitmask & EBT_STP_ROOTPRIO) {
56 v16 = NR16(stpc->root); 56 v16 = NR16(stpc->root);
57 if (FWINV(v16 < c->root_priol || 57 if (FWINV(v16 < c->root_priol ||
58 v16 > c->root_priou, EBT_STP_ROOTPRIO)) 58 v16 > c->root_priou, EBT_STP_ROOTPRIO))
59 return EBT_NOMATCH; 59 return EBT_NOMATCH;
60 } 60 }
61 if (info->bitmask & EBT_STP_ROOTADDR) { 61 if (info->bitmask & EBT_STP_ROOTADDR) {
62 verdict = 0; 62 verdict = 0;
63 for (i = 0; i < 6; i++) 63 for (i = 0; i < 6; i++)
64 verdict |= (stpc->root[2+i] ^ c->root_addr[i]) & 64 verdict |= (stpc->root[2+i] ^ c->root_addr[i]) &
65 c->root_addrmsk[i]; 65 c->root_addrmsk[i];
66 if (FWINV(verdict != 0, EBT_STP_ROOTADDR)) 66 if (FWINV(verdict != 0, EBT_STP_ROOTADDR))
67 return EBT_NOMATCH; 67 return EBT_NOMATCH;
68 } 68 }
69 if (info->bitmask & EBT_STP_ROOTCOST) { 69 if (info->bitmask & EBT_STP_ROOTCOST) {
70 v32 = NR32(stpc->root_cost); 70 v32 = NR32(stpc->root_cost);
71 if (FWINV(v32 < c->root_costl || 71 if (FWINV(v32 < c->root_costl ||
72 v32 > c->root_costu, EBT_STP_ROOTCOST)) 72 v32 > c->root_costu, EBT_STP_ROOTCOST))
73 return EBT_NOMATCH; 73 return EBT_NOMATCH;
74 } 74 }
75 if (info->bitmask & EBT_STP_SENDERPRIO) { 75 if (info->bitmask & EBT_STP_SENDERPRIO) {
76 v16 = NR16(stpc->sender); 76 v16 = NR16(stpc->sender);
77 if (FWINV(v16 < c->sender_priol || 77 if (FWINV(v16 < c->sender_priol ||
78 v16 > c->sender_priou, EBT_STP_SENDERPRIO)) 78 v16 > c->sender_priou, EBT_STP_SENDERPRIO))
79 return EBT_NOMATCH; 79 return EBT_NOMATCH;
80 } 80 }
81 if (info->bitmask & EBT_STP_SENDERADDR) { 81 if (info->bitmask & EBT_STP_SENDERADDR) {
82 verdict = 0; 82 verdict = 0;
83 for (i = 0; i < 6; i++) 83 for (i = 0; i < 6; i++)
84 verdict |= (stpc->sender[2+i] ^ c->sender_addr[i]) & 84 verdict |= (stpc->sender[2+i] ^ c->sender_addr[i]) &
85 c->sender_addrmsk[i]; 85 c->sender_addrmsk[i];
86 if (FWINV(verdict != 0, EBT_STP_SENDERADDR)) 86 if (FWINV(verdict != 0, EBT_STP_SENDERADDR))
87 return EBT_NOMATCH; 87 return EBT_NOMATCH;
88 } 88 }
89 if (info->bitmask & EBT_STP_PORT) { 89 if (info->bitmask & EBT_STP_PORT) {
90 v16 = NR16(stpc->port); 90 v16 = NR16(stpc->port);
91 if (FWINV(v16 < c->portl || 91 if (FWINV(v16 < c->portl ||
92 v16 > c->portu, EBT_STP_PORT)) 92 v16 > c->portu, EBT_STP_PORT))
93 return EBT_NOMATCH; 93 return EBT_NOMATCH;
94 } 94 }
95 if (info->bitmask & EBT_STP_MSGAGE) { 95 if (info->bitmask & EBT_STP_MSGAGE) {
96 v16 = NR16(stpc->msg_age); 96 v16 = NR16(stpc->msg_age);
97 if (FWINV(v16 < c->msg_agel || 97 if (FWINV(v16 < c->msg_agel ||
98 v16 > c->msg_ageu, EBT_STP_MSGAGE)) 98 v16 > c->msg_ageu, EBT_STP_MSGAGE))
99 return EBT_NOMATCH; 99 return EBT_NOMATCH;
100 } 100 }
101 if (info->bitmask & EBT_STP_MAXAGE) { 101 if (info->bitmask & EBT_STP_MAXAGE) {
102 v16 = NR16(stpc->max_age); 102 v16 = NR16(stpc->max_age);
103 if (FWINV(v16 < c->max_agel || 103 if (FWINV(v16 < c->max_agel ||
104 v16 > c->max_ageu, EBT_STP_MAXAGE)) 104 v16 > c->max_ageu, EBT_STP_MAXAGE))
105 return EBT_NOMATCH; 105 return EBT_NOMATCH;
106 } 106 }
107 if (info->bitmask & EBT_STP_HELLOTIME) { 107 if (info->bitmask & EBT_STP_HELLOTIME) {
108 v16 = NR16(stpc->hello_time); 108 v16 = NR16(stpc->hello_time);
109 if (FWINV(v16 < c->hello_timel || 109 if (FWINV(v16 < c->hello_timel ||
110 v16 > c->hello_timeu, EBT_STP_HELLOTIME)) 110 v16 > c->hello_timeu, EBT_STP_HELLOTIME))
111 return EBT_NOMATCH; 111 return EBT_NOMATCH;
112 } 112 }
113 if (info->bitmask & EBT_STP_FWDD) { 113 if (info->bitmask & EBT_STP_FWDD) {
114 v16 = NR16(stpc->forward_delay); 114 v16 = NR16(stpc->forward_delay);
115 if (FWINV(v16 < c->forward_delayl || 115 if (FWINV(v16 < c->forward_delayl ||
116 v16 > c->forward_delayu, EBT_STP_FWDD)) 116 v16 > c->forward_delayu, EBT_STP_FWDD))
117 return EBT_NOMATCH; 117 return EBT_NOMATCH;
118 } 118 }
119 return EBT_MATCH; 119 return EBT_MATCH;
120 } 120 }
121 121
122 static int ebt_filter_stp(const struct sk_buff *skb, const struct net_device *in, 122 static int ebt_filter_stp(const struct sk_buff *skb, const struct net_device *in,
123 const struct net_device *out, const void *data, unsigned int datalen) 123 const struct net_device *out, const void *data, unsigned int datalen)
124 { 124 {
125 const struct ebt_stp_info *info = data; 125 const struct ebt_stp_info *info = data;
126 const struct stp_header *sp; 126 const struct stp_header *sp;
127 struct stp_header _stph; 127 struct stp_header _stph;
128 const uint8_t header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00}; 128 const uint8_t header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
129 129
130 sp = skb_header_pointer(skb, 0, sizeof(_stph), &_stph); 130 sp = skb_header_pointer(skb, 0, sizeof(_stph), &_stph);
131 if (sp == NULL) 131 if (sp == NULL)
132 return EBT_NOMATCH; 132 return EBT_NOMATCH;
133 133
134 /* The stp code only considers these */ 134 /* The stp code only considers these */
135 if (memcmp(sp, header, sizeof(header))) 135 if (memcmp(sp, header, sizeof(header)))
136 return EBT_NOMATCH; 136 return EBT_NOMATCH;
137 137
138 if (info->bitmask & EBT_STP_TYPE 138 if (info->bitmask & EBT_STP_TYPE
139 && FWINV(info->type != sp->type, EBT_STP_TYPE)) 139 && FWINV(info->type != sp->type, EBT_STP_TYPE))
140 return EBT_NOMATCH; 140 return EBT_NOMATCH;
141 141
142 if (sp->type == BPDU_TYPE_CONFIG && 142 if (sp->type == BPDU_TYPE_CONFIG &&
143 info->bitmask & EBT_STP_CONFIG_MASK) { 143 info->bitmask & EBT_STP_CONFIG_MASK) {
144 const struct stp_config_pdu *st; 144 const struct stp_config_pdu *st;
145 struct stp_config_pdu _stpc; 145 struct stp_config_pdu _stpc;
146 146
147 st = skb_header_pointer(skb, sizeof(_stph), 147 st = skb_header_pointer(skb, sizeof(_stph),
148 sizeof(_stpc), &_stpc); 148 sizeof(_stpc), &_stpc);
149 if (st == NULL) 149 if (st == NULL)
150 return EBT_NOMATCH; 150 return EBT_NOMATCH;
151 return ebt_filter_config(info, st); 151 return ebt_filter_config(info, st);
152 } 152 }
153 return EBT_MATCH; 153 return EBT_MATCH;
154 } 154 }
155 155
156 static int ebt_stp_check(const char *tablename, unsigned int hookmask, 156 static bool ebt_stp_check(const char *tablename, unsigned int hookmask,
157 const struct ebt_entry *e, void *data, unsigned int datalen) 157 const struct ebt_entry *e, void *data, unsigned int datalen)
158 { 158 {
159 const struct ebt_stp_info *info = data; 159 const struct ebt_stp_info *info = data;
160 const uint8_t bridge_ula[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}; 160 const uint8_t bridge_ula[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00};
161 const uint8_t msk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 161 const uint8_t msk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
162 162
163 if (info->bitmask & ~EBT_STP_MASK || info->invflags & ~EBT_STP_MASK || 163 if (info->bitmask & ~EBT_STP_MASK || info->invflags & ~EBT_STP_MASK ||
164 !(info->bitmask & EBT_STP_MASK)) 164 !(info->bitmask & EBT_STP_MASK))
165 return -EINVAL; 165 return false;
166 /* Make sure the match only receives stp frames */ 166 /* Make sure the match only receives stp frames */
167 if (compare_ether_addr(e->destmac, bridge_ula) || 167 if (compare_ether_addr(e->destmac, bridge_ula) ||
168 compare_ether_addr(e->destmsk, msk) || !(e->bitmask & EBT_DESTMAC)) 168 compare_ether_addr(e->destmsk, msk) || !(e->bitmask & EBT_DESTMAC))
169 return -EINVAL; 169 return false;
170 170
171 return 0; 171 return true;
172 } 172 }
173 173
174 static struct ebt_match filter_stp __read_mostly = { 174 static struct ebt_match filter_stp __read_mostly = {
175 .name = EBT_STP_MATCH, 175 .name = EBT_STP_MATCH,
176 .match = ebt_filter_stp, 176 .match = ebt_filter_stp,
177 .check = ebt_stp_check, 177 .check = ebt_stp_check,
178 .matchsize = XT_ALIGN(sizeof(struct ebt_stp_info)), 178 .matchsize = XT_ALIGN(sizeof(struct ebt_stp_info)),
179 .me = THIS_MODULE, 179 .me = THIS_MODULE,
180 }; 180 };
181 181
182 static int __init ebt_stp_init(void) 182 static int __init ebt_stp_init(void)
183 { 183 {
184 return ebt_register_match(&filter_stp); 184 return ebt_register_match(&filter_stp);
185 } 185 }
186 186
187 static void __exit ebt_stp_fini(void) 187 static void __exit ebt_stp_fini(void)
188 { 188 {
189 ebt_unregister_match(&filter_stp); 189 ebt_unregister_match(&filter_stp);
190 } 190 }
191 191
192 module_init(ebt_stp_init); 192 module_init(ebt_stp_init);
193 module_exit(ebt_stp_fini); 193 module_exit(ebt_stp_fini);
194 MODULE_DESCRIPTION("Ebtables: Spanning Tree Protocol packet match"); 194 MODULE_DESCRIPTION("Ebtables: Spanning Tree Protocol packet match");
195 MODULE_LICENSE("GPL"); 195 MODULE_LICENSE("GPL");
196 196
net/bridge/netfilter/ebt_ulog.c
1 /* 1 /*
2 * netfilter module for userspace bridged Ethernet frames logging daemons 2 * netfilter module for userspace bridged Ethernet frames logging daemons
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * Harald Welte <laforge@netfilter.org> 6 * Harald Welte <laforge@netfilter.org>
7 * 7 *
8 * November, 2004 8 * November, 2004
9 * 9 *
10 * Based on ipt_ULOG.c, which is 10 * Based on ipt_ULOG.c, which is
11 * (C) 2000-2002 by Harald Welte <laforge@netfilter.org> 11 * (C) 2000-2002 by Harald Welte <laforge@netfilter.org>
12 * 12 *
13 * This module accepts two parameters: 13 * This module accepts two parameters:
14 * 14 *
15 * nlbufsiz: 15 * nlbufsiz:
16 * The parameter specifies how big the buffer for each netlink multicast 16 * The parameter specifies how big the buffer for each netlink multicast
17 * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will 17 * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will
18 * get accumulated in the kernel until they are sent to userspace. It is 18 * get accumulated in the kernel until they are sent to userspace. It is
19 * NOT possible to allocate more than 128kB, and it is strongly discouraged, 19 * NOT possible to allocate more than 128kB, and it is strongly discouraged,
20 * because atomically allocating 128kB inside the network rx softirq is not 20 * because atomically allocating 128kB inside the network rx softirq is not
21 * reliable. Please also keep in mind that this buffer size is allocated for 21 * reliable. Please also keep in mind that this buffer size is allocated for
22 * each nlgroup you are using, so the total kernel memory usage increases 22 * each nlgroup you are using, so the total kernel memory usage increases
23 * by that factor. 23 * by that factor.
24 * 24 *
25 * flushtimeout: 25 * flushtimeout:
26 * Specify, after how many hundredths of a second the queue should be 26 * Specify, after how many hundredths of a second the queue should be
27 * flushed even if it is not full yet. 27 * flushed even if it is not full yet.
28 * 28 *
29 */ 29 */
30 30
31 #include <linux/module.h> 31 #include <linux/module.h>
32 #include <linux/spinlock.h> 32 #include <linux/spinlock.h>
33 #include <linux/socket.h> 33 #include <linux/socket.h>
34 #include <linux/skbuff.h> 34 #include <linux/skbuff.h>
35 #include <linux/kernel.h> 35 #include <linux/kernel.h>
36 #include <linux/timer.h> 36 #include <linux/timer.h>
37 #include <linux/netlink.h> 37 #include <linux/netlink.h>
38 #include <linux/netdevice.h> 38 #include <linux/netdevice.h>
39 #include <linux/netfilter/x_tables.h> 39 #include <linux/netfilter/x_tables.h>
40 #include <linux/netfilter_bridge/ebtables.h> 40 #include <linux/netfilter_bridge/ebtables.h>
41 #include <linux/netfilter_bridge/ebt_ulog.h> 41 #include <linux/netfilter_bridge/ebt_ulog.h>
42 #include <net/netfilter/nf_log.h> 42 #include <net/netfilter/nf_log.h>
43 #include <net/sock.h> 43 #include <net/sock.h>
44 #include "../br_private.h" 44 #include "../br_private.h"
45 45
46 #define PRINTR(format, args...) do { if (net_ratelimit()) \ 46 #define PRINTR(format, args...) do { if (net_ratelimit()) \
47 printk(format , ## args); } while (0) 47 printk(format , ## args); } while (0)
48 48
49 static unsigned int nlbufsiz = NLMSG_GOODSIZE; 49 static unsigned int nlbufsiz = NLMSG_GOODSIZE;
50 module_param(nlbufsiz, uint, 0600); 50 module_param(nlbufsiz, uint, 0600);
51 MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) " 51 MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) "
52 "(defaults to 4096)"); 52 "(defaults to 4096)");
53 53
54 static unsigned int flushtimeout = 10; 54 static unsigned int flushtimeout = 10;
55 module_param(flushtimeout, uint, 0600); 55 module_param(flushtimeout, uint, 0600);
56 MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths ofa second) " 56 MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths ofa second) "
57 "(defaults to 10)"); 57 "(defaults to 10)");
58 58
59 typedef struct { 59 typedef struct {
60 unsigned int qlen; /* number of nlmsgs' in the skb */ 60 unsigned int qlen; /* number of nlmsgs' in the skb */
61 struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */ 61 struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */
62 struct sk_buff *skb; /* the pre-allocated skb */ 62 struct sk_buff *skb; /* the pre-allocated skb */
63 struct timer_list timer; /* the timer function */ 63 struct timer_list timer; /* the timer function */
64 spinlock_t lock; /* the per-queue lock */ 64 spinlock_t lock; /* the per-queue lock */
65 } ebt_ulog_buff_t; 65 } ebt_ulog_buff_t;
66 66
67 static ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS]; 67 static ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS];
68 static struct sock *ebtulognl; 68 static struct sock *ebtulognl;
69 69
70 /* send one ulog_buff_t to userspace */ 70 /* send one ulog_buff_t to userspace */
71 static void ulog_send(unsigned int nlgroup) 71 static void ulog_send(unsigned int nlgroup)
72 { 72 {
73 ebt_ulog_buff_t *ub = &ulog_buffers[nlgroup]; 73 ebt_ulog_buff_t *ub = &ulog_buffers[nlgroup];
74 74
75 if (timer_pending(&ub->timer)) 75 if (timer_pending(&ub->timer))
76 del_timer(&ub->timer); 76 del_timer(&ub->timer);
77 77
78 if (!ub->skb) 78 if (!ub->skb)
79 return; 79 return;
80 80
81 /* last nlmsg needs NLMSG_DONE */ 81 /* last nlmsg needs NLMSG_DONE */
82 if (ub->qlen > 1) 82 if (ub->qlen > 1)
83 ub->lastnlh->nlmsg_type = NLMSG_DONE; 83 ub->lastnlh->nlmsg_type = NLMSG_DONE;
84 84
85 NETLINK_CB(ub->skb).dst_group = nlgroup + 1; 85 NETLINK_CB(ub->skb).dst_group = nlgroup + 1;
86 netlink_broadcast(ebtulognl, ub->skb, 0, nlgroup + 1, GFP_ATOMIC); 86 netlink_broadcast(ebtulognl, ub->skb, 0, nlgroup + 1, GFP_ATOMIC);
87 87
88 ub->qlen = 0; 88 ub->qlen = 0;
89 ub->skb = NULL; 89 ub->skb = NULL;
90 } 90 }
91 91
92 /* timer function to flush queue in flushtimeout time */ 92 /* timer function to flush queue in flushtimeout time */
93 static void ulog_timer(unsigned long data) 93 static void ulog_timer(unsigned long data)
94 { 94 {
95 spin_lock_bh(&ulog_buffers[data].lock); 95 spin_lock_bh(&ulog_buffers[data].lock);
96 if (ulog_buffers[data].skb) 96 if (ulog_buffers[data].skb)
97 ulog_send(data); 97 ulog_send(data);
98 spin_unlock_bh(&ulog_buffers[data].lock); 98 spin_unlock_bh(&ulog_buffers[data].lock);
99 } 99 }
100 100
101 static struct sk_buff *ulog_alloc_skb(unsigned int size) 101 static struct sk_buff *ulog_alloc_skb(unsigned int size)
102 { 102 {
103 struct sk_buff *skb; 103 struct sk_buff *skb;
104 unsigned int n; 104 unsigned int n;
105 105
106 n = max(size, nlbufsiz); 106 n = max(size, nlbufsiz);
107 skb = alloc_skb(n, GFP_ATOMIC); 107 skb = alloc_skb(n, GFP_ATOMIC);
108 if (!skb) { 108 if (!skb) {
109 PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer " 109 PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer "
110 "of size %ub!\n", n); 110 "of size %ub!\n", n);
111 if (n > size) { 111 if (n > size) {
112 /* try to allocate only as much as we need for 112 /* try to allocate only as much as we need for
113 * current packet */ 113 * current packet */
114 skb = alloc_skb(size, GFP_ATOMIC); 114 skb = alloc_skb(size, GFP_ATOMIC);
115 if (!skb) 115 if (!skb)
116 PRINTR(KERN_ERR "ebt_ulog: can't even allocate " 116 PRINTR(KERN_ERR "ebt_ulog: can't even allocate "
117 "buffer of size %ub\n", size); 117 "buffer of size %ub\n", size);
118 } 118 }
119 } 119 }
120 120
121 return skb; 121 return skb;
122 } 122 }
123 123
124 static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb, 124 static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
125 const struct net_device *in, const struct net_device *out, 125 const struct net_device *in, const struct net_device *out,
126 const struct ebt_ulog_info *uloginfo, const char *prefix) 126 const struct ebt_ulog_info *uloginfo, const char *prefix)
127 { 127 {
128 ebt_ulog_packet_msg_t *pm; 128 ebt_ulog_packet_msg_t *pm;
129 size_t size, copy_len; 129 size_t size, copy_len;
130 struct nlmsghdr *nlh; 130 struct nlmsghdr *nlh;
131 unsigned int group = uloginfo->nlgroup; 131 unsigned int group = uloginfo->nlgroup;
132 ebt_ulog_buff_t *ub = &ulog_buffers[group]; 132 ebt_ulog_buff_t *ub = &ulog_buffers[group];
133 spinlock_t *lock = &ub->lock; 133 spinlock_t *lock = &ub->lock;
134 ktime_t kt; 134 ktime_t kt;
135 135
136 if ((uloginfo->cprange == 0) || 136 if ((uloginfo->cprange == 0) ||
137 (uloginfo->cprange > skb->len + ETH_HLEN)) 137 (uloginfo->cprange > skb->len + ETH_HLEN))
138 copy_len = skb->len + ETH_HLEN; 138 copy_len = skb->len + ETH_HLEN;
139 else 139 else
140 copy_len = uloginfo->cprange; 140 copy_len = uloginfo->cprange;
141 141
142 size = NLMSG_SPACE(sizeof(*pm) + copy_len); 142 size = NLMSG_SPACE(sizeof(*pm) + copy_len);
143 if (size > nlbufsiz) { 143 if (size > nlbufsiz) {
144 PRINTR("ebt_ulog: Size %Zd needed, but nlbufsiz=%d\n", 144 PRINTR("ebt_ulog: Size %Zd needed, but nlbufsiz=%d\n",
145 size, nlbufsiz); 145 size, nlbufsiz);
146 return; 146 return;
147 } 147 }
148 148
149 spin_lock_bh(lock); 149 spin_lock_bh(lock);
150 150
151 if (!ub->skb) { 151 if (!ub->skb) {
152 if (!(ub->skb = ulog_alloc_skb(size))) 152 if (!(ub->skb = ulog_alloc_skb(size)))
153 goto alloc_failure; 153 goto alloc_failure;
154 } else if (size > skb_tailroom(ub->skb)) { 154 } else if (size > skb_tailroom(ub->skb)) {
155 ulog_send(group); 155 ulog_send(group);
156 156
157 if (!(ub->skb = ulog_alloc_skb(size))) 157 if (!(ub->skb = ulog_alloc_skb(size)))
158 goto alloc_failure; 158 goto alloc_failure;
159 } 159 }
160 160
161 nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, 0, 161 nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, 0,
162 size - NLMSG_ALIGN(sizeof(*nlh))); 162 size - NLMSG_ALIGN(sizeof(*nlh)));
163 ub->qlen++; 163 ub->qlen++;
164 164
165 pm = NLMSG_DATA(nlh); 165 pm = NLMSG_DATA(nlh);
166 166
167 /* Fill in the ulog data */ 167 /* Fill in the ulog data */
168 pm->version = EBT_ULOG_VERSION; 168 pm->version = EBT_ULOG_VERSION;
169 kt = ktime_get_real(); 169 kt = ktime_get_real();
170 pm->stamp = ktime_to_timeval(kt); 170 pm->stamp = ktime_to_timeval(kt);
171 if (ub->qlen == 1) 171 if (ub->qlen == 1)
172 ub->skb->tstamp = kt; 172 ub->skb->tstamp = kt;
173 pm->data_len = copy_len; 173 pm->data_len = copy_len;
174 pm->mark = skb->mark; 174 pm->mark = skb->mark;
175 pm->hook = hooknr; 175 pm->hook = hooknr;
176 if (uloginfo->prefix != NULL) 176 if (uloginfo->prefix != NULL)
177 strcpy(pm->prefix, uloginfo->prefix); 177 strcpy(pm->prefix, uloginfo->prefix);
178 else 178 else
179 *(pm->prefix) = '\0'; 179 *(pm->prefix) = '\0';
180 180
181 if (in) { 181 if (in) {
182 strcpy(pm->physindev, in->name); 182 strcpy(pm->physindev, in->name);
183 /* If in isn't a bridge, then physindev==indev */ 183 /* If in isn't a bridge, then physindev==indev */
184 if (in->br_port) 184 if (in->br_port)
185 strcpy(pm->indev, in->br_port->br->dev->name); 185 strcpy(pm->indev, in->br_port->br->dev->name);
186 else 186 else
187 strcpy(pm->indev, in->name); 187 strcpy(pm->indev, in->name);
188 } else 188 } else
189 pm->indev[0] = pm->physindev[0] = '\0'; 189 pm->indev[0] = pm->physindev[0] = '\0';
190 190
191 if (out) { 191 if (out) {
192 /* If out exists, then out is a bridge port */ 192 /* If out exists, then out is a bridge port */
193 strcpy(pm->physoutdev, out->name); 193 strcpy(pm->physoutdev, out->name);
194 strcpy(pm->outdev, out->br_port->br->dev->name); 194 strcpy(pm->outdev, out->br_port->br->dev->name);
195 } else 195 } else
196 pm->outdev[0] = pm->physoutdev[0] = '\0'; 196 pm->outdev[0] = pm->physoutdev[0] = '\0';
197 197
198 if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0) 198 if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0)
199 BUG(); 199 BUG();
200 200
201 if (ub->qlen > 1) 201 if (ub->qlen > 1)
202 ub->lastnlh->nlmsg_flags |= NLM_F_MULTI; 202 ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
203 203
204 ub->lastnlh = nlh; 204 ub->lastnlh = nlh;
205 205
206 if (ub->qlen >= uloginfo->qthreshold) 206 if (ub->qlen >= uloginfo->qthreshold)
207 ulog_send(group); 207 ulog_send(group);
208 else if (!timer_pending(&ub->timer)) { 208 else if (!timer_pending(&ub->timer)) {
209 ub->timer.expires = jiffies + flushtimeout * HZ / 100; 209 ub->timer.expires = jiffies + flushtimeout * HZ / 100;
210 add_timer(&ub->timer); 210 add_timer(&ub->timer);
211 } 211 }
212 212
213 unlock: 213 unlock:
214 spin_unlock_bh(lock); 214 spin_unlock_bh(lock);
215 215
216 return; 216 return;
217 217
218 nlmsg_failure: 218 nlmsg_failure:
219 printk(KERN_CRIT "ebt_ulog: error during NLMSG_PUT. This should " 219 printk(KERN_CRIT "ebt_ulog: error during NLMSG_PUT. This should "
220 "not happen, please report to author.\n"); 220 "not happen, please report to author.\n");
221 goto unlock; 221 goto unlock;
222 alloc_failure: 222 alloc_failure:
223 goto unlock; 223 goto unlock;
224 } 224 }
225 225
226 /* this function is registered with the netfilter core */ 226 /* this function is registered with the netfilter core */
227 static void ebt_log_packet(u_int8_t pf, unsigned int hooknum, 227 static void ebt_log_packet(u_int8_t pf, unsigned int hooknum,
228 const struct sk_buff *skb, const struct net_device *in, 228 const struct sk_buff *skb, const struct net_device *in,
229 const struct net_device *out, const struct nf_loginfo *li, 229 const struct net_device *out, const struct nf_loginfo *li,
230 const char *prefix) 230 const char *prefix)
231 { 231 {
232 struct ebt_ulog_info loginfo; 232 struct ebt_ulog_info loginfo;
233 233
234 if (!li || li->type != NF_LOG_TYPE_ULOG) { 234 if (!li || li->type != NF_LOG_TYPE_ULOG) {
235 loginfo.nlgroup = EBT_ULOG_DEFAULT_NLGROUP; 235 loginfo.nlgroup = EBT_ULOG_DEFAULT_NLGROUP;
236 loginfo.cprange = 0; 236 loginfo.cprange = 0;
237 loginfo.qthreshold = EBT_ULOG_DEFAULT_QTHRESHOLD; 237 loginfo.qthreshold = EBT_ULOG_DEFAULT_QTHRESHOLD;
238 loginfo.prefix[0] = '\0'; 238 loginfo.prefix[0] = '\0';
239 } else { 239 } else {
240 loginfo.nlgroup = li->u.ulog.group; 240 loginfo.nlgroup = li->u.ulog.group;
241 loginfo.cprange = li->u.ulog.copy_len; 241 loginfo.cprange = li->u.ulog.copy_len;
242 loginfo.qthreshold = li->u.ulog.qthreshold; 242 loginfo.qthreshold = li->u.ulog.qthreshold;
243 strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix)); 243 strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
244 } 244 }
245 245
246 ebt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); 246 ebt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
247 } 247 }
248 248
249 static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr, 249 static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr,
250 const struct net_device *in, const struct net_device *out, 250 const struct net_device *in, const struct net_device *out,
251 const void *data, unsigned int datalen) 251 const void *data, unsigned int datalen)
252 { 252 {
253 const struct ebt_ulog_info *uloginfo = data; 253 const struct ebt_ulog_info *uloginfo = data;
254 254
255 ebt_ulog_packet(hooknr, skb, in, out, uloginfo, NULL); 255 ebt_ulog_packet(hooknr, skb, in, out, uloginfo, NULL);
256 } 256 }
257 257
258 258 static bool ebt_ulog_check(const char *tablename, unsigned int hookmask,
259 static int ebt_ulog_check(const char *tablename, unsigned int hookmask,
260 const struct ebt_entry *e, void *data, unsigned int datalen) 259 const struct ebt_entry *e, void *data, unsigned int datalen)
261 { 260 {
262 struct ebt_ulog_info *uloginfo = data; 261 struct ebt_ulog_info *uloginfo = data;
263 262
264 if (uloginfo->nlgroup > 31) 263 if (uloginfo->nlgroup > 31)
265 return -EINVAL; 264 return false;
266 265
267 uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0'; 266 uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0';
268 267
269 if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN) 268 if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN)
270 uloginfo->qthreshold = EBT_ULOG_MAX_QLEN; 269 uloginfo->qthreshold = EBT_ULOG_MAX_QLEN;
271 270
272 return 0; 271 return 0;
273 } 272 }
274 273
275 static struct ebt_watcher ulog __read_mostly = { 274 static struct ebt_watcher ulog __read_mostly = {
276 .name = EBT_ULOG_WATCHER, 275 .name = EBT_ULOG_WATCHER,
277 .watcher = ebt_ulog, 276 .watcher = ebt_ulog,
278 .check = ebt_ulog_check, 277 .check = ebt_ulog_check,
279 .targetsize = XT_ALIGN(sizeof(struct ebt_ulog_info)), 278 .targetsize = XT_ALIGN(sizeof(struct ebt_ulog_info)),
280 .me = THIS_MODULE, 279 .me = THIS_MODULE,
281 }; 280 };
282 281
283 static const struct nf_logger ebt_ulog_logger = { 282 static const struct nf_logger ebt_ulog_logger = {
284 .name = EBT_ULOG_WATCHER, 283 .name = EBT_ULOG_WATCHER,
285 .logfn = &ebt_log_packet, 284 .logfn = &ebt_log_packet,
286 .me = THIS_MODULE, 285 .me = THIS_MODULE,
287 }; 286 };
288 287
289 static int __init ebt_ulog_init(void) 288 static int __init ebt_ulog_init(void)
290 { 289 {
291 int i, ret = 0; 290 bool ret = true;
291 int i;
292 292
293 if (nlbufsiz >= 128*1024) { 293 if (nlbufsiz >= 128*1024) {
294 printk(KERN_NOTICE "ebt_ulog: Netlink buffer has to be <= 128kB," 294 printk(KERN_NOTICE "ebt_ulog: Netlink buffer has to be <= 128kB,"
295 " please try a smaller nlbufsiz parameter.\n"); 295 " please try a smaller nlbufsiz parameter.\n");
296 return -EINVAL; 296 return false;
297 } 297 }
298 298
299 /* initialize ulog_buffers */ 299 /* initialize ulog_buffers */
300 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { 300 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
301 setup_timer(&ulog_buffers[i].timer, ulog_timer, i); 301 setup_timer(&ulog_buffers[i].timer, ulog_timer, i);
302 spin_lock_init(&ulog_buffers[i].lock); 302 spin_lock_init(&ulog_buffers[i].lock);
303 } 303 }
304 304
305 ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG, 305 ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG,
306 EBT_ULOG_MAXNLGROUPS, NULL, NULL, 306 EBT_ULOG_MAXNLGROUPS, NULL, NULL,
307 THIS_MODULE); 307 THIS_MODULE);
308 if (!ebtulognl) 308 if (!ebtulognl) {
309 ret = -ENOMEM; 309 printk(KERN_WARNING KBUILD_MODNAME ": out of memory trying to "
310 else if ((ret = ebt_register_watcher(&ulog))) 310 "call netlink_kernel_create\n");
311 ret = false;
312 } else if (ebt_register_watcher(&ulog) != 0) {
311 netlink_kernel_release(ebtulognl); 313 netlink_kernel_release(ebtulognl);
314 }
312 315
313 if (ret == 0) 316 if (ret)
314 nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger); 317 nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger);
315 318
316 return ret; 319 return ret;
317 } 320 }
318 321
319 static void __exit ebt_ulog_fini(void) 322 static void __exit ebt_ulog_fini(void)
320 { 323 {
321 ebt_ulog_buff_t *ub; 324 ebt_ulog_buff_t *ub;
322 int i; 325 int i;
323 326
324 nf_log_unregister(&ebt_ulog_logger); 327 nf_log_unregister(&ebt_ulog_logger);
325 ebt_unregister_watcher(&ulog); 328 ebt_unregister_watcher(&ulog);
326 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { 329 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
327 ub = &ulog_buffers[i]; 330 ub = &ulog_buffers[i];
328 if (timer_pending(&ub->timer)) 331 if (timer_pending(&ub->timer))
329 del_timer(&ub->timer); 332 del_timer(&ub->timer);
330 spin_lock_bh(&ub->lock); 333 spin_lock_bh(&ub->lock);
331 if (ub->skb) { 334 if (ub->skb) {
332 kfree_skb(ub->skb); 335 kfree_skb(ub->skb);
333 ub->skb = NULL; 336 ub->skb = NULL;
334 } 337 }
335 spin_unlock_bh(&ub->lock); 338 spin_unlock_bh(&ub->lock);
336 } 339 }
337 netlink_kernel_release(ebtulognl); 340 netlink_kernel_release(ebtulognl);
338 } 341 }
339 342
340 module_init(ebt_ulog_init); 343 module_init(ebt_ulog_init);
341 module_exit(ebt_ulog_fini); 344 module_exit(ebt_ulog_fini);
342 MODULE_LICENSE("GPL"); 345 MODULE_LICENSE("GPL");
343 MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); 346 MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
344 MODULE_DESCRIPTION("Ebtables: Packet logging to netlink using ULOG"); 347 MODULE_DESCRIPTION("Ebtables: Packet logging to netlink using ULOG");
net/bridge/netfilter/ebt_vlan.c
1 /* 1 /*
2 * Description: EBTables 802.1Q match extension kernelspace module. 2 * Description: EBTables 802.1Q match extension kernelspace module.
3 * Authors: Nick Fedchik <nick@fedchik.org.ua> 3 * Authors: Nick Fedchik <nick@fedchik.org.ua>
4 * Bart De Schuymer <bdschuym@pandora.be> 4 * Bart De Schuymer <bdschuym@pandora.be>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or 8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. 9 * (at your option) any later version.
10 * 10 *
11 * This program is distributed in the hope that it will be useful, 11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License 16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */ 19 */
20 20
21 #include <linux/if_ether.h> 21 #include <linux/if_ether.h>
22 #include <linux/if_vlan.h> 22 #include <linux/if_vlan.h>
23 #include <linux/module.h> 23 #include <linux/module.h>
24 #include <linux/moduleparam.h> 24 #include <linux/moduleparam.h>
25 #include <linux/netfilter/x_tables.h> 25 #include <linux/netfilter/x_tables.h>
26 #include <linux/netfilter_bridge/ebtables.h> 26 #include <linux/netfilter_bridge/ebtables.h>
27 #include <linux/netfilter_bridge/ebt_vlan.h> 27 #include <linux/netfilter_bridge/ebt_vlan.h>
28 28
29 static int debug; 29 static int debug;
30 #define MODULE_VERS "0.6" 30 #define MODULE_VERS "0.6"
31 31
32 module_param(debug, int, 0); 32 module_param(debug, int, 0);
33 MODULE_PARM_DESC(debug, "debug=1 is turn on debug messages"); 33 MODULE_PARM_DESC(debug, "debug=1 is turn on debug messages");
34 MODULE_AUTHOR("Nick Fedchik <nick@fedchik.org.ua>"); 34 MODULE_AUTHOR("Nick Fedchik <nick@fedchik.org.ua>");
35 MODULE_DESCRIPTION("Ebtables: 802.1Q VLAN tag match"); 35 MODULE_DESCRIPTION("Ebtables: 802.1Q VLAN tag match");
36 MODULE_LICENSE("GPL"); 36 MODULE_LICENSE("GPL");
37 37
38 38
39 #define DEBUG_MSG(args...) if (debug) printk (KERN_DEBUG "ebt_vlan: " args) 39 #define DEBUG_MSG(args...) if (debug) printk (KERN_DEBUG "ebt_vlan: " args)
40 #define GET_BITMASK(_BIT_MASK_) info->bitmask & _BIT_MASK_ 40 #define GET_BITMASK(_BIT_MASK_) info->bitmask & _BIT_MASK_
41 #define EXIT_ON_MISMATCH(_MATCH_,_MASK_) {if (!((info->_MATCH_ == _MATCH_)^!!(info->invflags & _MASK_))) return EBT_NOMATCH;} 41 #define EXIT_ON_MISMATCH(_MATCH_,_MASK_) {if (!((info->_MATCH_ == _MATCH_)^!!(info->invflags & _MASK_))) return EBT_NOMATCH;}
42 42
43 static int 43 static int
44 ebt_filter_vlan(const struct sk_buff *skb, 44 ebt_filter_vlan(const struct sk_buff *skb,
45 const struct net_device *in, 45 const struct net_device *in,
46 const struct net_device *out, 46 const struct net_device *out,
47 const void *data, unsigned int datalen) 47 const void *data, unsigned int datalen)
48 { 48 {
49 const struct ebt_vlan_info *info = data; 49 const struct ebt_vlan_info *info = data;
50 const struct vlan_hdr *fp; 50 const struct vlan_hdr *fp;
51 struct vlan_hdr _frame; 51 struct vlan_hdr _frame;
52 52
53 unsigned short TCI; /* Whole TCI, given from parsed frame */ 53 unsigned short TCI; /* Whole TCI, given from parsed frame */
54 unsigned short id; /* VLAN ID, given from frame TCI */ 54 unsigned short id; /* VLAN ID, given from frame TCI */
55 unsigned char prio; /* user_priority, given from frame TCI */ 55 unsigned char prio; /* user_priority, given from frame TCI */
56 /* VLAN encapsulated Type/Length field, given from orig frame */ 56 /* VLAN encapsulated Type/Length field, given from orig frame */
57 __be16 encap; 57 __be16 encap;
58 58
59 fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame); 59 fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
60 if (fp == NULL) 60 if (fp == NULL)
61 return EBT_NOMATCH; 61 return EBT_NOMATCH;
62 62
63 /* Tag Control Information (TCI) consists of the following elements: 63 /* Tag Control Information (TCI) consists of the following elements:
64 * - User_priority. The user_priority field is three bits in length, 64 * - User_priority. The user_priority field is three bits in length,
65 * interpreted as a binary number. 65 * interpreted as a binary number.
66 * - Canonical Format Indicator (CFI). The Canonical Format Indicator 66 * - Canonical Format Indicator (CFI). The Canonical Format Indicator
67 * (CFI) is a single bit flag value. Currently ignored. 67 * (CFI) is a single bit flag value. Currently ignored.
68 * - VLAN Identifier (VID). The VID is encoded as 68 * - VLAN Identifier (VID). The VID is encoded as
69 * an unsigned binary number. */ 69 * an unsigned binary number. */
70 TCI = ntohs(fp->h_vlan_TCI); 70 TCI = ntohs(fp->h_vlan_TCI);
71 id = TCI & VLAN_VID_MASK; 71 id = TCI & VLAN_VID_MASK;
72 prio = (TCI >> 13) & 0x7; 72 prio = (TCI >> 13) & 0x7;
73 encap = fp->h_vlan_encapsulated_proto; 73 encap = fp->h_vlan_encapsulated_proto;
74 74
75 /* Checking VLAN Identifier (VID) */ 75 /* Checking VLAN Identifier (VID) */
76 if (GET_BITMASK(EBT_VLAN_ID)) 76 if (GET_BITMASK(EBT_VLAN_ID))
77 EXIT_ON_MISMATCH(id, EBT_VLAN_ID); 77 EXIT_ON_MISMATCH(id, EBT_VLAN_ID);
78 78
79 /* Checking user_priority */ 79 /* Checking user_priority */
80 if (GET_BITMASK(EBT_VLAN_PRIO)) 80 if (GET_BITMASK(EBT_VLAN_PRIO))
81 EXIT_ON_MISMATCH(prio, EBT_VLAN_PRIO); 81 EXIT_ON_MISMATCH(prio, EBT_VLAN_PRIO);
82 82
83 /* Checking Encapsulated Proto (Length/Type) field */ 83 /* Checking Encapsulated Proto (Length/Type) field */
84 if (GET_BITMASK(EBT_VLAN_ENCAP)) 84 if (GET_BITMASK(EBT_VLAN_ENCAP))
85 EXIT_ON_MISMATCH(encap, EBT_VLAN_ENCAP); 85 EXIT_ON_MISMATCH(encap, EBT_VLAN_ENCAP);
86 86
87 return EBT_MATCH; 87 return EBT_MATCH;
88 } 88 }
89 89
90 static int 90 static bool
91 ebt_check_vlan(const char *tablename, 91 ebt_check_vlan(const char *tablename,
92 unsigned int hooknr, 92 unsigned int hooknr,
93 const struct ebt_entry *e, void *data, unsigned int datalen) 93 const struct ebt_entry *e, void *data, unsigned int datalen)
94 { 94 {
95 struct ebt_vlan_info *info = data; 95 struct ebt_vlan_info *info = data;
96 96
97 /* Is it 802.1Q frame checked? */ 97 /* Is it 802.1Q frame checked? */
98 if (e->ethproto != htons(ETH_P_8021Q)) { 98 if (e->ethproto != htons(ETH_P_8021Q)) {
99 DEBUG_MSG 99 DEBUG_MSG
100 ("passed entry proto %2.4X is not 802.1Q (8100)\n", 100 ("passed entry proto %2.4X is not 802.1Q (8100)\n",
101 (unsigned short) ntohs(e->ethproto)); 101 (unsigned short) ntohs(e->ethproto));
102 return -EINVAL; 102 return false;
103 } 103 }
104 104
105 /* Check for bitmask range 105 /* Check for bitmask range
106 * True if even one bit is out of mask */ 106 * True if even one bit is out of mask */
107 if (info->bitmask & ~EBT_VLAN_MASK) { 107 if (info->bitmask & ~EBT_VLAN_MASK) {
108 DEBUG_MSG("bitmask %2X is out of mask (%2X)\n", 108 DEBUG_MSG("bitmask %2X is out of mask (%2X)\n",
109 info->bitmask, EBT_VLAN_MASK); 109 info->bitmask, EBT_VLAN_MASK);
110 return -EINVAL; 110 return false;
111 } 111 }
112 112
113 /* Check for inversion flags range */ 113 /* Check for inversion flags range */
114 if (info->invflags & ~EBT_VLAN_MASK) { 114 if (info->invflags & ~EBT_VLAN_MASK) {
115 DEBUG_MSG("inversion flags %2X is out of mask (%2X)\n", 115 DEBUG_MSG("inversion flags %2X is out of mask (%2X)\n",
116 info->invflags, EBT_VLAN_MASK); 116 info->invflags, EBT_VLAN_MASK);
117 return -EINVAL; 117 return false;
118 } 118 }
119 119
120 /* Reserved VLAN ID (VID) values 120 /* Reserved VLAN ID (VID) values
121 * ----------------------------- 121 * -----------------------------
122 * 0 - The null VLAN ID. 122 * 0 - The null VLAN ID.
123 * 1 - The default Port VID (PVID) 123 * 1 - The default Port VID (PVID)
124 * 0x0FFF - Reserved for implementation use. 124 * 0x0FFF - Reserved for implementation use.
125 * if_vlan.h: VLAN_GROUP_ARRAY_LEN 4096. */ 125 * if_vlan.h: VLAN_GROUP_ARRAY_LEN 4096. */
126 if (GET_BITMASK(EBT_VLAN_ID)) { 126 if (GET_BITMASK(EBT_VLAN_ID)) {
127 if (!!info->id) { /* if id!=0 => check vid range */ 127 if (!!info->id) { /* if id!=0 => check vid range */
128 if (info->id > VLAN_GROUP_ARRAY_LEN) { 128 if (info->id > VLAN_GROUP_ARRAY_LEN) {
129 DEBUG_MSG 129 DEBUG_MSG
130 ("id %d is out of range (1-4096)\n", 130 ("id %d is out of range (1-4096)\n",
131 info->id); 131 info->id);
132 return -EINVAL; 132 return false;
133 } 133 }
134 /* Note: This is valid VLAN-tagged frame point. 134 /* Note: This is valid VLAN-tagged frame point.
135 * Any value of user_priority are acceptable, 135 * Any value of user_priority are acceptable,
136 * but should be ignored according to 802.1Q Std. 136 * but should be ignored according to 802.1Q Std.
137 * So we just drop the prio flag. */ 137 * So we just drop the prio flag. */
138 info->bitmask &= ~EBT_VLAN_PRIO; 138 info->bitmask &= ~EBT_VLAN_PRIO;
139 } 139 }
140 /* Else, id=0 (null VLAN ID) => user_priority range (any?) */ 140 /* Else, id=0 (null VLAN ID) => user_priority range (any?) */
141 } 141 }
142 142
143 if (GET_BITMASK(EBT_VLAN_PRIO)) { 143 if (GET_BITMASK(EBT_VLAN_PRIO)) {
144 if ((unsigned char) info->prio > 7) { 144 if ((unsigned char) info->prio > 7) {
145 DEBUG_MSG("prio %d is out of range (0-7)\n", 145 DEBUG_MSG("prio %d is out of range (0-7)\n",
146 info->prio); 146 info->prio);
147 return -EINVAL; 147 return false;
148 } 148 }
149 } 149 }
150 /* Check for encapsulated proto range - it is possible to be 150 /* Check for encapsulated proto range - it is possible to be
151 * any value for u_short range. 151 * any value for u_short range.
152 * if_ether.h: ETH_ZLEN 60 - Min. octets in frame sans FCS */ 152 * if_ether.h: ETH_ZLEN 60 - Min. octets in frame sans FCS */
153 if (GET_BITMASK(EBT_VLAN_ENCAP)) { 153 if (GET_BITMASK(EBT_VLAN_ENCAP)) {
154 if ((unsigned short) ntohs(info->encap) < ETH_ZLEN) { 154 if ((unsigned short) ntohs(info->encap) < ETH_ZLEN) {
155 DEBUG_MSG 155 DEBUG_MSG
156 ("encap frame length %d is less than minimal\n", 156 ("encap frame length %d is less than minimal\n",
157 ntohs(info->encap)); 157 ntohs(info->encap));
158 return -EINVAL; 158 return false;
159 } 159 }
160 } 160 }
161 161
162 return 0; 162 return true;
163 } 163 }
164 164
165 static struct ebt_match filter_vlan __read_mostly = { 165 static struct ebt_match filter_vlan __read_mostly = {
166 .name = EBT_VLAN_MATCH, 166 .name = EBT_VLAN_MATCH,
167 .match = ebt_filter_vlan, 167 .match = ebt_filter_vlan,
168 .check = ebt_check_vlan, 168 .check = ebt_check_vlan,
169 .matchsize = XT_ALIGN(sizeof(struct ebt_vlan_info)), 169 .matchsize = XT_ALIGN(sizeof(struct ebt_vlan_info)),
170 .me = THIS_MODULE, 170 .me = THIS_MODULE,
171 }; 171 };
172 172
173 static int __init ebt_vlan_init(void) 173 static int __init ebt_vlan_init(void)
174 { 174 {
175 DEBUG_MSG("ebtables 802.1Q extension module v" 175 DEBUG_MSG("ebtables 802.1Q extension module v"
176 MODULE_VERS "\n"); 176 MODULE_VERS "\n");
177 DEBUG_MSG("module debug=%d\n", !!debug); 177 DEBUG_MSG("module debug=%d\n", !!debug);
178 return ebt_register_match(&filter_vlan); 178 return ebt_register_match(&filter_vlan);
179 } 179 }
180 180
181 static void __exit ebt_vlan_fini(void) 181 static void __exit ebt_vlan_fini(void)
182 { 182 {
183 ebt_unregister_match(&filter_vlan); 183 ebt_unregister_match(&filter_vlan);
184 } 184 }
185 185
186 module_init(ebt_vlan_init); 186 module_init(ebt_vlan_init);
187 module_exit(ebt_vlan_fini); 187 module_exit(ebt_vlan_fini);
188 188
net/bridge/netfilter/ebtables.c
1 /* 1 /*
2 * ebtables 2 * ebtables
3 * 3 *
4 * Author: 4 * Author:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * 6 *
7 * ebtables.c,v 2.0, July, 2002 7 * ebtables.c,v 2.0, July, 2002
8 * 8 *
9 * This code is stongly inspired on the iptables code which is 9 * This code is stongly inspired on the iptables code which is
10 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling 10 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11 * 11 *
12 * This program is free software; you can redistribute it and/or 12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License 13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version. 15 * 2 of the License, or (at your option) any later version.
16 */ 16 */
17 17
18 18
19 #include <linux/kmod.h> 19 #include <linux/kmod.h>
20 #include <linux/module.h> 20 #include <linux/module.h>
21 #include <linux/vmalloc.h> 21 #include <linux/vmalloc.h>
22 #include <linux/netfilter/x_tables.h> 22 #include <linux/netfilter/x_tables.h>
23 #include <linux/netfilter_bridge/ebtables.h> 23 #include <linux/netfilter_bridge/ebtables.h>
24 #include <linux/spinlock.h> 24 #include <linux/spinlock.h>
25 #include <linux/mutex.h> 25 #include <linux/mutex.h>
26 #include <asm/uaccess.h> 26 #include <asm/uaccess.h>
27 #include <linux/smp.h> 27 #include <linux/smp.h>
28 #include <linux/cpumask.h> 28 #include <linux/cpumask.h>
29 #include <net/sock.h> 29 #include <net/sock.h>
30 /* needed for logical [in,out]-dev filtering */ 30 /* needed for logical [in,out]-dev filtering */
31 #include "../br_private.h" 31 #include "../br_private.h"
32 32
33 #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\ 33 #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
34 "report to author: "format, ## args) 34 "report to author: "format, ## args)
35 /* #define BUGPRINT(format, args...) */ 35 /* #define BUGPRINT(format, args...) */
36 #define MEMPRINT(format, args...) printk("kernel msg: ebtables "\ 36 #define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
37 ": out of memory: "format, ## args) 37 ": out of memory: "format, ## args)
38 /* #define MEMPRINT(format, args...) */ 38 /* #define MEMPRINT(format, args...) */
39 39
40 40
41 41
42 /* 42 /*
43 * Each cpu has its own set of counters, so there is no need for write_lock in 43 * Each cpu has its own set of counters, so there is no need for write_lock in
44 * the softirq 44 * the softirq
45 * For reading or updating the counters, the user context needs to 45 * For reading or updating the counters, the user context needs to
46 * get a write_lock 46 * get a write_lock
47 */ 47 */
48 48
49 /* The size of each set of counters is altered to get cache alignment */ 49 /* The size of each set of counters is altered to get cache alignment */
50 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) 50 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
51 #define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter))) 51 #define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
52 #define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \ 52 #define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
53 COUNTER_OFFSET(n) * cpu)) 53 COUNTER_OFFSET(n) * cpu))
54 54
55 55
56 56
57 static DEFINE_MUTEX(ebt_mutex); 57 static DEFINE_MUTEX(ebt_mutex);
58 static LIST_HEAD(ebt_tables); 58 static LIST_HEAD(ebt_tables);
59 static LIST_HEAD(ebt_targets); 59 static LIST_HEAD(ebt_targets);
60 static LIST_HEAD(ebt_matches); 60 static LIST_HEAD(ebt_matches);
61 static LIST_HEAD(ebt_watchers); 61 static LIST_HEAD(ebt_watchers);
62 62
63 static struct ebt_target ebt_standard_target = { 63 static struct ebt_target ebt_standard_target = {
64 .name = "standard", 64 .name = "standard",
65 }; 65 };
66 66
67 static inline int ebt_do_watcher (struct ebt_entry_watcher *w, 67 static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
68 const struct sk_buff *skb, unsigned int hooknr, const struct net_device *in, 68 const struct sk_buff *skb, unsigned int hooknr, const struct net_device *in,
69 const struct net_device *out) 69 const struct net_device *out)
70 { 70 {
71 w->u.watcher->watcher(skb, hooknr, in, out, w->data, 71 w->u.watcher->watcher(skb, hooknr, in, out, w->data,
72 w->watcher_size); 72 w->watcher_size);
73 /* watchers don't give a verdict */ 73 /* watchers don't give a verdict */
74 return 0; 74 return 0;
75 } 75 }
76 76
77 static inline int ebt_do_match (struct ebt_entry_match *m, 77 static inline int ebt_do_match (struct ebt_entry_match *m,
78 const struct sk_buff *skb, const struct net_device *in, 78 const struct sk_buff *skb, const struct net_device *in,
79 const struct net_device *out) 79 const struct net_device *out)
80 { 80 {
81 return m->u.match->match(skb, in, out, m->data, 81 return m->u.match->match(skb, in, out, m->data,
82 m->match_size); 82 m->match_size);
83 } 83 }
84 84
85 static inline int ebt_dev_check(char *entry, const struct net_device *device) 85 static inline int ebt_dev_check(char *entry, const struct net_device *device)
86 { 86 {
87 int i = 0; 87 int i = 0;
88 const char *devname = device->name; 88 const char *devname = device->name;
89 89
90 if (*entry == '\0') 90 if (*entry == '\0')
91 return 0; 91 return 0;
92 if (!device) 92 if (!device)
93 return 1; 93 return 1;
94 /* 1 is the wildcard token */ 94 /* 1 is the wildcard token */
95 while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i]) 95 while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i])
96 i++; 96 i++;
97 return (devname[i] != entry[i] && entry[i] != 1); 97 return (devname[i] != entry[i] && entry[i] != 1);
98 } 98 }
99 99
100 #define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg)) 100 #define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
101 /* process standard matches */ 101 /* process standard matches */
102 static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h, 102 static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
103 const struct net_device *in, const struct net_device *out) 103 const struct net_device *in, const struct net_device *out)
104 { 104 {
105 int verdict, i; 105 int verdict, i;
106 106
107 if (e->bitmask & EBT_802_3) { 107 if (e->bitmask & EBT_802_3) {
108 if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO)) 108 if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
109 return 1; 109 return 1;
110 } else if (!(e->bitmask & EBT_NOPROTO) && 110 } else if (!(e->bitmask & EBT_NOPROTO) &&
111 FWINV2(e->ethproto != h->h_proto, EBT_IPROTO)) 111 FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
112 return 1; 112 return 1;
113 113
114 if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN)) 114 if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
115 return 1; 115 return 1;
116 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT)) 116 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
117 return 1; 117 return 1;
118 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check( 118 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
119 e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN)) 119 e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN))
120 return 1; 120 return 1;
121 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check( 121 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
122 e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT)) 122 e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT))
123 return 1; 123 return 1;
124 124
125 if (e->bitmask & EBT_SOURCEMAC) { 125 if (e->bitmask & EBT_SOURCEMAC) {
126 verdict = 0; 126 verdict = 0;
127 for (i = 0; i < 6; i++) 127 for (i = 0; i < 6; i++)
128 verdict |= (h->h_source[i] ^ e->sourcemac[i]) & 128 verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
129 e->sourcemsk[i]; 129 e->sourcemsk[i];
130 if (FWINV2(verdict != 0, EBT_ISOURCE) ) 130 if (FWINV2(verdict != 0, EBT_ISOURCE) )
131 return 1; 131 return 1;
132 } 132 }
133 if (e->bitmask & EBT_DESTMAC) { 133 if (e->bitmask & EBT_DESTMAC) {
134 verdict = 0; 134 verdict = 0;
135 for (i = 0; i < 6; i++) 135 for (i = 0; i < 6; i++)
136 verdict |= (h->h_dest[i] ^ e->destmac[i]) & 136 verdict |= (h->h_dest[i] ^ e->destmac[i]) &
137 e->destmsk[i]; 137 e->destmsk[i];
138 if (FWINV2(verdict != 0, EBT_IDEST) ) 138 if (FWINV2(verdict != 0, EBT_IDEST) )
139 return 1; 139 return 1;
140 } 140 }
141 return 0; 141 return 0;
142 } 142 }
143 143
144 /* Do some firewalling */ 144 /* Do some firewalling */
145 unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, 145 unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
146 const struct net_device *in, const struct net_device *out, 146 const struct net_device *in, const struct net_device *out,
147 struct ebt_table *table) 147 struct ebt_table *table)
148 { 148 {
149 int i, nentries; 149 int i, nentries;
150 struct ebt_entry *point; 150 struct ebt_entry *point;
151 struct ebt_counter *counter_base, *cb_base; 151 struct ebt_counter *counter_base, *cb_base;
152 struct ebt_entry_target *t; 152 struct ebt_entry_target *t;
153 int verdict, sp = 0; 153 int verdict, sp = 0;
154 struct ebt_chainstack *cs; 154 struct ebt_chainstack *cs;
155 struct ebt_entries *chaininfo; 155 struct ebt_entries *chaininfo;
156 char *base; 156 char *base;
157 struct ebt_table_info *private; 157 struct ebt_table_info *private;
158 158
159 read_lock_bh(&table->lock); 159 read_lock_bh(&table->lock);
160 private = table->private; 160 private = table->private;
161 cb_base = COUNTER_BASE(private->counters, private->nentries, 161 cb_base = COUNTER_BASE(private->counters, private->nentries,
162 smp_processor_id()); 162 smp_processor_id());
163 if (private->chainstack) 163 if (private->chainstack)
164 cs = private->chainstack[smp_processor_id()]; 164 cs = private->chainstack[smp_processor_id()];
165 else 165 else
166 cs = NULL; 166 cs = NULL;
167 chaininfo = private->hook_entry[hook]; 167 chaininfo = private->hook_entry[hook];
168 nentries = private->hook_entry[hook]->nentries; 168 nentries = private->hook_entry[hook]->nentries;
169 point = (struct ebt_entry *)(private->hook_entry[hook]->data); 169 point = (struct ebt_entry *)(private->hook_entry[hook]->data);
170 counter_base = cb_base + private->hook_entry[hook]->counter_offset; 170 counter_base = cb_base + private->hook_entry[hook]->counter_offset;
171 /* base for chain jumps */ 171 /* base for chain jumps */
172 base = private->entries; 172 base = private->entries;
173 i = 0; 173 i = 0;
174 while (i < nentries) { 174 while (i < nentries) {
175 if (ebt_basic_match(point, eth_hdr(skb), in, out)) 175 if (ebt_basic_match(point, eth_hdr(skb), in, out))
176 goto letscontinue; 176 goto letscontinue;
177 177
178 if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, in, out) != 0) 178 if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, in, out) != 0)
179 goto letscontinue; 179 goto letscontinue;
180 180
181 /* increase counter */ 181 /* increase counter */
182 (*(counter_base + i)).pcnt++; 182 (*(counter_base + i)).pcnt++;
183 (*(counter_base + i)).bcnt += skb->len; 183 (*(counter_base + i)).bcnt += skb->len;
184 184
185 /* these should only watch: not modify, nor tell us 185 /* these should only watch: not modify, nor tell us
186 what to do with the packet */ 186 what to do with the packet */
187 EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, hook, in, 187 EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, hook, in,
188 out); 188 out);
189 189
190 t = (struct ebt_entry_target *) 190 t = (struct ebt_entry_target *)
191 (((char *)point) + point->target_offset); 191 (((char *)point) + point->target_offset);
192 /* standard target */ 192 /* standard target */
193 if (!t->u.target->target) 193 if (!t->u.target->target)
194 verdict = ((struct ebt_standard_target *)t)->verdict; 194 verdict = ((struct ebt_standard_target *)t)->verdict;
195 else 195 else
196 verdict = t->u.target->target(skb, hook, 196 verdict = t->u.target->target(skb, hook,
197 in, out, t->data, t->target_size); 197 in, out, t->data, t->target_size);
198 if (verdict == EBT_ACCEPT) { 198 if (verdict == EBT_ACCEPT) {
199 read_unlock_bh(&table->lock); 199 read_unlock_bh(&table->lock);
200 return NF_ACCEPT; 200 return NF_ACCEPT;
201 } 201 }
202 if (verdict == EBT_DROP) { 202 if (verdict == EBT_DROP) {
203 read_unlock_bh(&table->lock); 203 read_unlock_bh(&table->lock);
204 return NF_DROP; 204 return NF_DROP;
205 } 205 }
206 if (verdict == EBT_RETURN) { 206 if (verdict == EBT_RETURN) {
207 letsreturn: 207 letsreturn:
208 #ifdef CONFIG_NETFILTER_DEBUG 208 #ifdef CONFIG_NETFILTER_DEBUG
209 if (sp == 0) { 209 if (sp == 0) {
210 BUGPRINT("RETURN on base chain"); 210 BUGPRINT("RETURN on base chain");
211 /* act like this is EBT_CONTINUE */ 211 /* act like this is EBT_CONTINUE */
212 goto letscontinue; 212 goto letscontinue;
213 } 213 }
214 #endif 214 #endif
215 sp--; 215 sp--;
216 /* put all the local variables right */ 216 /* put all the local variables right */
217 i = cs[sp].n; 217 i = cs[sp].n;
218 chaininfo = cs[sp].chaininfo; 218 chaininfo = cs[sp].chaininfo;
219 nentries = chaininfo->nentries; 219 nentries = chaininfo->nentries;
220 point = cs[sp].e; 220 point = cs[sp].e;
221 counter_base = cb_base + 221 counter_base = cb_base +
222 chaininfo->counter_offset; 222 chaininfo->counter_offset;
223 continue; 223 continue;
224 } 224 }
225 if (verdict == EBT_CONTINUE) 225 if (verdict == EBT_CONTINUE)
226 goto letscontinue; 226 goto letscontinue;
227 #ifdef CONFIG_NETFILTER_DEBUG 227 #ifdef CONFIG_NETFILTER_DEBUG
228 if (verdict < 0) { 228 if (verdict < 0) {
229 BUGPRINT("bogus standard verdict\n"); 229 BUGPRINT("bogus standard verdict\n");
230 read_unlock_bh(&table->lock); 230 read_unlock_bh(&table->lock);
231 return NF_DROP; 231 return NF_DROP;
232 } 232 }
233 #endif 233 #endif
234 /* jump to a udc */ 234 /* jump to a udc */
235 cs[sp].n = i + 1; 235 cs[sp].n = i + 1;
236 cs[sp].chaininfo = chaininfo; 236 cs[sp].chaininfo = chaininfo;
237 cs[sp].e = (struct ebt_entry *) 237 cs[sp].e = (struct ebt_entry *)
238 (((char *)point) + point->next_offset); 238 (((char *)point) + point->next_offset);
239 i = 0; 239 i = 0;
240 chaininfo = (struct ebt_entries *) (base + verdict); 240 chaininfo = (struct ebt_entries *) (base + verdict);
241 #ifdef CONFIG_NETFILTER_DEBUG 241 #ifdef CONFIG_NETFILTER_DEBUG
242 if (chaininfo->distinguisher) { 242 if (chaininfo->distinguisher) {
243 BUGPRINT("jump to non-chain\n"); 243 BUGPRINT("jump to non-chain\n");
244 read_unlock_bh(&table->lock); 244 read_unlock_bh(&table->lock);
245 return NF_DROP; 245 return NF_DROP;
246 } 246 }
247 #endif 247 #endif
248 nentries = chaininfo->nentries; 248 nentries = chaininfo->nentries;
249 point = (struct ebt_entry *)chaininfo->data; 249 point = (struct ebt_entry *)chaininfo->data;
250 counter_base = cb_base + chaininfo->counter_offset; 250 counter_base = cb_base + chaininfo->counter_offset;
251 sp++; 251 sp++;
252 continue; 252 continue;
253 letscontinue: 253 letscontinue:
254 point = (struct ebt_entry *) 254 point = (struct ebt_entry *)
255 (((char *)point) + point->next_offset); 255 (((char *)point) + point->next_offset);
256 i++; 256 i++;
257 } 257 }
258 258
259 /* I actually like this :) */ 259 /* I actually like this :) */
260 if (chaininfo->policy == EBT_RETURN) 260 if (chaininfo->policy == EBT_RETURN)
261 goto letsreturn; 261 goto letsreturn;
262 if (chaininfo->policy == EBT_ACCEPT) { 262 if (chaininfo->policy == EBT_ACCEPT) {
263 read_unlock_bh(&table->lock); 263 read_unlock_bh(&table->lock);
264 return NF_ACCEPT; 264 return NF_ACCEPT;
265 } 265 }
266 read_unlock_bh(&table->lock); 266 read_unlock_bh(&table->lock);
267 return NF_DROP; 267 return NF_DROP;
268 } 268 }
269 269
270 /* If it succeeds, returns element and locks mutex */ 270 /* If it succeeds, returns element and locks mutex */
271 static inline void * 271 static inline void *
272 find_inlist_lock_noload(struct list_head *head, const char *name, int *error, 272 find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
273 struct mutex *mutex) 273 struct mutex *mutex)
274 { 274 {
275 struct { 275 struct {
276 struct list_head list; 276 struct list_head list;
277 char name[EBT_FUNCTION_MAXNAMELEN]; 277 char name[EBT_FUNCTION_MAXNAMELEN];
278 } *e; 278 } *e;
279 279
280 *error = mutex_lock_interruptible(mutex); 280 *error = mutex_lock_interruptible(mutex);
281 if (*error != 0) 281 if (*error != 0)
282 return NULL; 282 return NULL;
283 283
284 list_for_each_entry(e, head, list) { 284 list_for_each_entry(e, head, list) {
285 if (strcmp(e->name, name) == 0) 285 if (strcmp(e->name, name) == 0)
286 return e; 286 return e;
287 } 287 }
288 *error = -ENOENT; 288 *error = -ENOENT;
289 mutex_unlock(mutex); 289 mutex_unlock(mutex);
290 return NULL; 290 return NULL;
291 } 291 }
292 292
293 #ifndef CONFIG_KMOD 293 #ifndef CONFIG_KMOD
294 #define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m)) 294 #define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
295 #else 295 #else
296 static void * 296 static void *
297 find_inlist_lock(struct list_head *head, const char *name, const char *prefix, 297 find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
298 int *error, struct mutex *mutex) 298 int *error, struct mutex *mutex)
299 { 299 {
300 void *ret; 300 void *ret;
301 301
302 ret = find_inlist_lock_noload(head, name, error, mutex); 302 ret = find_inlist_lock_noload(head, name, error, mutex);
303 if (!ret) { 303 if (!ret) {
304 request_module("%s%s", prefix, name); 304 request_module("%s%s", prefix, name);
305 ret = find_inlist_lock_noload(head, name, error, mutex); 305 ret = find_inlist_lock_noload(head, name, error, mutex);
306 } 306 }
307 return ret; 307 return ret;
308 } 308 }
309 #endif 309 #endif
310 310
311 static inline struct ebt_table * 311 static inline struct ebt_table *
312 find_table_lock(const char *name, int *error, struct mutex *mutex) 312 find_table_lock(const char *name, int *error, struct mutex *mutex)
313 { 313 {
314 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex); 314 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex);
315 } 315 }
316 316
317 static inline struct ebt_match * 317 static inline struct ebt_match *
318 find_match_lock(const char *name, int *error, struct mutex *mutex) 318 find_match_lock(const char *name, int *error, struct mutex *mutex)
319 { 319 {
320 return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex); 320 return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex);
321 } 321 }
322 322
323 static inline struct ebt_watcher * 323 static inline struct ebt_watcher *
324 find_watcher_lock(const char *name, int *error, struct mutex *mutex) 324 find_watcher_lock(const char *name, int *error, struct mutex *mutex)
325 { 325 {
326 return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex); 326 return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex);
327 } 327 }
328 328
329 static inline struct ebt_target * 329 static inline struct ebt_target *
330 find_target_lock(const char *name, int *error, struct mutex *mutex) 330 find_target_lock(const char *name, int *error, struct mutex *mutex)
331 { 331 {
332 return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex); 332 return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex);
333 } 333 }
334 334
335 static inline int 335 static inline int
336 ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e, 336 ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
337 const char *name, unsigned int hookmask, unsigned int *cnt) 337 const char *name, unsigned int hookmask, unsigned int *cnt)
338 { 338 {
339 struct ebt_match *match; 339 struct ebt_match *match;
340 size_t left = ((char *)e + e->watchers_offset) - (char *)m; 340 size_t left = ((char *)e + e->watchers_offset) - (char *)m;
341 int ret; 341 int ret;
342 342
343 if (left < sizeof(struct ebt_entry_match) || 343 if (left < sizeof(struct ebt_entry_match) ||
344 left - sizeof(struct ebt_entry_match) < m->match_size) 344 left - sizeof(struct ebt_entry_match) < m->match_size)
345 return -EINVAL; 345 return -EINVAL;
346 match = find_match_lock(m->u.name, &ret, &ebt_mutex); 346 match = find_match_lock(m->u.name, &ret, &ebt_mutex);
347 if (!match) 347 if (!match)
348 return ret; 348 return ret;
349 m->u.match = match; 349 m->u.match = match;
350 if (!try_module_get(match->me)) { 350 if (!try_module_get(match->me)) {
351 mutex_unlock(&ebt_mutex); 351 mutex_unlock(&ebt_mutex);
352 return -ENOENT; 352 return -ENOENT;
353 } 353 }
354 mutex_unlock(&ebt_mutex); 354 mutex_unlock(&ebt_mutex);
355 if (XT_ALIGN(match->matchsize) != m->match_size && 355 if (XT_ALIGN(match->matchsize) != m->match_size &&
356 match->matchsize != -1) { 356 match->matchsize != -1) {
357 /* 357 /*
358 * ebt_among is exempt from centralized matchsize checking 358 * ebt_among is exempt from centralized matchsize checking
359 * because it uses a dynamic-size data set. 359 * because it uses a dynamic-size data set.
360 */ 360 */
361 printk(KERN_WARNING "ebtables: %s match: " 361 printk(KERN_WARNING "ebtables: %s match: "
362 "invalid size %Zu != %u\n", 362 "invalid size %Zu != %u\n",
363 match->name, XT_ALIGN(match->matchsize), m->match_size); 363 match->name, XT_ALIGN(match->matchsize), m->match_size);
364 module_put(match->me); 364 module_put(match->me);
365 return -EINVAL; 365 return -EINVAL;
366 } 366 }
367 if (match->check && 367 if (match->check &&
368 match->check(name, hookmask, e, m->data, m->match_size) != 0) { 368 !match->check(name, hookmask, e, m->data, m->match_size)) {
369 BUGPRINT("match->check failed\n"); 369 BUGPRINT("match->check failed\n");
370 module_put(match->me); 370 module_put(match->me);
371 return -EINVAL; 371 return -EINVAL;
372 } 372 }
373 (*cnt)++; 373 (*cnt)++;
374 return 0; 374 return 0;
375 } 375 }
376 376
377 static inline int 377 static inline int
378 ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, 378 ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
379 const char *name, unsigned int hookmask, unsigned int *cnt) 379 const char *name, unsigned int hookmask, unsigned int *cnt)
380 { 380 {
381 struct ebt_watcher *watcher; 381 struct ebt_watcher *watcher;
382 size_t left = ((char *)e + e->target_offset) - (char *)w; 382 size_t left = ((char *)e + e->target_offset) - (char *)w;
383 int ret; 383 int ret;
384 384
385 if (left < sizeof(struct ebt_entry_watcher) || 385 if (left < sizeof(struct ebt_entry_watcher) ||
386 left - sizeof(struct ebt_entry_watcher) < w->watcher_size) 386 left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
387 return -EINVAL; 387 return -EINVAL;
388 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex); 388 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
389 if (!watcher) 389 if (!watcher)
390 return ret; 390 return ret;
391 w->u.watcher = watcher; 391 w->u.watcher = watcher;
392 if (!try_module_get(watcher->me)) { 392 if (!try_module_get(watcher->me)) {
393 mutex_unlock(&ebt_mutex); 393 mutex_unlock(&ebt_mutex);
394 return -ENOENT; 394 return -ENOENT;
395 } 395 }
396 mutex_unlock(&ebt_mutex); 396 mutex_unlock(&ebt_mutex);
397 if (XT_ALIGN(watcher->targetsize) != w->watcher_size) { 397 if (XT_ALIGN(watcher->targetsize) != w->watcher_size) {
398 printk(KERN_WARNING "ebtables: %s watcher: " 398 printk(KERN_WARNING "ebtables: %s watcher: "
399 "invalid size %Zu != %u\n", 399 "invalid size %Zu != %u\n",
400 watcher->name, XT_ALIGN(watcher->targetsize), 400 watcher->name, XT_ALIGN(watcher->targetsize),
401 w->watcher_size); 401 w->watcher_size);
402 module_put(watcher->me); 402 module_put(watcher->me);
403 return -EINVAL; 403 return -EINVAL;
404 } 404 }
405 if (watcher->check && 405 if (watcher->check &&
406 watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) { 406 !watcher->check(name, hookmask, e, w->data, w->watcher_size)) {
407 BUGPRINT("watcher->check failed\n"); 407 BUGPRINT("watcher->check failed\n");
408 module_put(watcher->me); 408 module_put(watcher->me);
409 return -EINVAL; 409 return -EINVAL;
410 } 410 }
411 (*cnt)++; 411 (*cnt)++;
412 return 0; 412 return 0;
413 } 413 }
414 414
415 static int ebt_verify_pointers(struct ebt_replace *repl, 415 static int ebt_verify_pointers(struct ebt_replace *repl,
416 struct ebt_table_info *newinfo) 416 struct ebt_table_info *newinfo)
417 { 417 {
418 unsigned int limit = repl->entries_size; 418 unsigned int limit = repl->entries_size;
419 unsigned int valid_hooks = repl->valid_hooks; 419 unsigned int valid_hooks = repl->valid_hooks;
420 unsigned int offset = 0; 420 unsigned int offset = 0;
421 int i; 421 int i;
422 422
423 for (i = 0; i < NF_BR_NUMHOOKS; i++) 423 for (i = 0; i < NF_BR_NUMHOOKS; i++)
424 newinfo->hook_entry[i] = NULL; 424 newinfo->hook_entry[i] = NULL;
425 425
426 newinfo->entries_size = repl->entries_size; 426 newinfo->entries_size = repl->entries_size;
427 newinfo->nentries = repl->nentries; 427 newinfo->nentries = repl->nentries;
428 428
429 while (offset < limit) { 429 while (offset < limit) {
430 size_t left = limit - offset; 430 size_t left = limit - offset;
431 struct ebt_entry *e = (void *)newinfo->entries + offset; 431 struct ebt_entry *e = (void *)newinfo->entries + offset;
432 432
433 if (left < sizeof(unsigned int)) 433 if (left < sizeof(unsigned int))
434 break; 434 break;
435 435
436 for (i = 0; i < NF_BR_NUMHOOKS; i++) { 436 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
437 if ((valid_hooks & (1 << i)) == 0) 437 if ((valid_hooks & (1 << i)) == 0)
438 continue; 438 continue;
439 if ((char __user *)repl->hook_entry[i] == 439 if ((char __user *)repl->hook_entry[i] ==
440 repl->entries + offset) 440 repl->entries + offset)
441 break; 441 break;
442 } 442 }
443 443
444 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) { 444 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
445 if (e->bitmask != 0) { 445 if (e->bitmask != 0) {
446 /* we make userspace set this right, 446 /* we make userspace set this right,
447 so there is no misunderstanding */ 447 so there is no misunderstanding */
448 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set " 448 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
449 "in distinguisher\n"); 449 "in distinguisher\n");
450 return -EINVAL; 450 return -EINVAL;
451 } 451 }
452 if (i != NF_BR_NUMHOOKS) 452 if (i != NF_BR_NUMHOOKS)
453 newinfo->hook_entry[i] = (struct ebt_entries *)e; 453 newinfo->hook_entry[i] = (struct ebt_entries *)e;
454 if (left < sizeof(struct ebt_entries)) 454 if (left < sizeof(struct ebt_entries))
455 break; 455 break;
456 offset += sizeof(struct ebt_entries); 456 offset += sizeof(struct ebt_entries);
457 } else { 457 } else {
458 if (left < sizeof(struct ebt_entry)) 458 if (left < sizeof(struct ebt_entry))
459 break; 459 break;
460 if (left < e->next_offset) 460 if (left < e->next_offset)
461 break; 461 break;
462 offset += e->next_offset; 462 offset += e->next_offset;
463 } 463 }
464 } 464 }
465 if (offset != limit) { 465 if (offset != limit) {
466 BUGPRINT("entries_size too small\n"); 466 BUGPRINT("entries_size too small\n");
467 return -EINVAL; 467 return -EINVAL;
468 } 468 }
469 469
470 /* check if all valid hooks have a chain */ 470 /* check if all valid hooks have a chain */
471 for (i = 0; i < NF_BR_NUMHOOKS; i++) { 471 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
472 if (!newinfo->hook_entry[i] && 472 if (!newinfo->hook_entry[i] &&
473 (valid_hooks & (1 << i))) { 473 (valid_hooks & (1 << i))) {
474 BUGPRINT("Valid hook without chain\n"); 474 BUGPRINT("Valid hook without chain\n");
475 return -EINVAL; 475 return -EINVAL;
476 } 476 }
477 } 477 }
478 return 0; 478 return 0;
479 } 479 }
480 480
481 /* 481 /*
482 * this one is very careful, as it is the first function 482 * this one is very careful, as it is the first function
483 * to parse the userspace data 483 * to parse the userspace data
484 */ 484 */
485 static inline int 485 static inline int
486 ebt_check_entry_size_and_hooks(struct ebt_entry *e, 486 ebt_check_entry_size_and_hooks(struct ebt_entry *e,
487 struct ebt_table_info *newinfo, 487 struct ebt_table_info *newinfo,
488 unsigned int *n, unsigned int *cnt, 488 unsigned int *n, unsigned int *cnt,
489 unsigned int *totalcnt, unsigned int *udc_cnt) 489 unsigned int *totalcnt, unsigned int *udc_cnt)
490 { 490 {
491 int i; 491 int i;
492 492
493 for (i = 0; i < NF_BR_NUMHOOKS; i++) { 493 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
494 if ((void *)e == (void *)newinfo->hook_entry[i]) 494 if ((void *)e == (void *)newinfo->hook_entry[i])
495 break; 495 break;
496 } 496 }
497 /* beginning of a new chain 497 /* beginning of a new chain
498 if i == NF_BR_NUMHOOKS it must be a user defined chain */ 498 if i == NF_BR_NUMHOOKS it must be a user defined chain */
499 if (i != NF_BR_NUMHOOKS || !e->bitmask) { 499 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
500 /* this checks if the previous chain has as many entries 500 /* this checks if the previous chain has as many entries
501 as it said it has */ 501 as it said it has */
502 if (*n != *cnt) { 502 if (*n != *cnt) {
503 BUGPRINT("nentries does not equal the nr of entries " 503 BUGPRINT("nentries does not equal the nr of entries "
504 "in the chain\n"); 504 "in the chain\n");
505 return -EINVAL; 505 return -EINVAL;
506 } 506 }
507 if (((struct ebt_entries *)e)->policy != EBT_DROP && 507 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
508 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) { 508 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
509 /* only RETURN from udc */ 509 /* only RETURN from udc */
510 if (i != NF_BR_NUMHOOKS || 510 if (i != NF_BR_NUMHOOKS ||
511 ((struct ebt_entries *)e)->policy != EBT_RETURN) { 511 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
512 BUGPRINT("bad policy\n"); 512 BUGPRINT("bad policy\n");
513 return -EINVAL; 513 return -EINVAL;
514 } 514 }
515 } 515 }
516 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */ 516 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
517 (*udc_cnt)++; 517 (*udc_cnt)++;
518 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) { 518 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
519 BUGPRINT("counter_offset != totalcnt"); 519 BUGPRINT("counter_offset != totalcnt");
520 return -EINVAL; 520 return -EINVAL;
521 } 521 }
522 *n = ((struct ebt_entries *)e)->nentries; 522 *n = ((struct ebt_entries *)e)->nentries;
523 *cnt = 0; 523 *cnt = 0;
524 return 0; 524 return 0;
525 } 525 }
526 /* a plain old entry, heh */ 526 /* a plain old entry, heh */
527 if (sizeof(struct ebt_entry) > e->watchers_offset || 527 if (sizeof(struct ebt_entry) > e->watchers_offset ||
528 e->watchers_offset > e->target_offset || 528 e->watchers_offset > e->target_offset ||
529 e->target_offset >= e->next_offset) { 529 e->target_offset >= e->next_offset) {
530 BUGPRINT("entry offsets not in right order\n"); 530 BUGPRINT("entry offsets not in right order\n");
531 return -EINVAL; 531 return -EINVAL;
532 } 532 }
533 /* this is not checked anywhere else */ 533 /* this is not checked anywhere else */
534 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) { 534 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
535 BUGPRINT("target size too small\n"); 535 BUGPRINT("target size too small\n");
536 return -EINVAL; 536 return -EINVAL;
537 } 537 }
538 (*cnt)++; 538 (*cnt)++;
539 (*totalcnt)++; 539 (*totalcnt)++;
540 return 0; 540 return 0;
541 } 541 }
542 542
543 struct ebt_cl_stack 543 struct ebt_cl_stack
544 { 544 {
545 struct ebt_chainstack cs; 545 struct ebt_chainstack cs;
546 int from; 546 int from;
547 unsigned int hookmask; 547 unsigned int hookmask;
548 }; 548 };
549 549
550 /* 550 /*
551 * we need these positions to check that the jumps to a different part of the 551 * we need these positions to check that the jumps to a different part of the
552 * entries is a jump to the beginning of a new chain. 552 * entries is a jump to the beginning of a new chain.
553 */ 553 */
554 static inline int 554 static inline int
555 ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo, 555 ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
556 unsigned int *n, struct ebt_cl_stack *udc) 556 unsigned int *n, struct ebt_cl_stack *udc)
557 { 557 {
558 int i; 558 int i;
559 559
560 /* we're only interested in chain starts */ 560 /* we're only interested in chain starts */
561 if (e->bitmask) 561 if (e->bitmask)
562 return 0; 562 return 0;
563 for (i = 0; i < NF_BR_NUMHOOKS; i++) { 563 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
564 if (newinfo->hook_entry[i] == (struct ebt_entries *)e) 564 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
565 break; 565 break;
566 } 566 }
567 /* only care about udc */ 567 /* only care about udc */
568 if (i != NF_BR_NUMHOOKS) 568 if (i != NF_BR_NUMHOOKS)
569 return 0; 569 return 0;
570 570
571 udc[*n].cs.chaininfo = (struct ebt_entries *)e; 571 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
572 /* these initialisations are depended on later in check_chainloops() */ 572 /* these initialisations are depended on later in check_chainloops() */
573 udc[*n].cs.n = 0; 573 udc[*n].cs.n = 0;
574 udc[*n].hookmask = 0; 574 udc[*n].hookmask = 0;
575 575
576 (*n)++; 576 (*n)++;
577 return 0; 577 return 0;
578 } 578 }
579 579
580 static inline int 580 static inline int
581 ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i) 581 ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
582 { 582 {
583 if (i && (*i)-- == 0) 583 if (i && (*i)-- == 0)
584 return 1; 584 return 1;
585 if (m->u.match->destroy) 585 if (m->u.match->destroy)
586 m->u.match->destroy(m->data, m->match_size); 586 m->u.match->destroy(m->data, m->match_size);
587 module_put(m->u.match->me); 587 module_put(m->u.match->me);
588 588
589 return 0; 589 return 0;
590 } 590 }
591 591
592 static inline int 592 static inline int
593 ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i) 593 ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
594 { 594 {
595 if (i && (*i)-- == 0) 595 if (i && (*i)-- == 0)
596 return 1; 596 return 1;
597 if (w->u.watcher->destroy) 597 if (w->u.watcher->destroy)
598 w->u.watcher->destroy(w->data, w->watcher_size); 598 w->u.watcher->destroy(w->data, w->watcher_size);
599 module_put(w->u.watcher->me); 599 module_put(w->u.watcher->me);
600 600
601 return 0; 601 return 0;
602 } 602 }
603 603
604 static inline int 604 static inline int
605 ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt) 605 ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
606 { 606 {
607 struct ebt_entry_target *t; 607 struct ebt_entry_target *t;
608 608
609 if (e->bitmask == 0) 609 if (e->bitmask == 0)
610 return 0; 610 return 0;
611 /* we're done */ 611 /* we're done */
612 if (cnt && (*cnt)-- == 0) 612 if (cnt && (*cnt)-- == 0)
613 return 1; 613 return 1;
614 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL); 614 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
615 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL); 615 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);
616 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); 616 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
617 if (t->u.target->destroy) 617 if (t->u.target->destroy)
618 t->u.target->destroy(t->data, t->target_size); 618 t->u.target->destroy(t->data, t->target_size);
619 module_put(t->u.target->me); 619 module_put(t->u.target->me);
620 620
621 return 0; 621 return 0;
622 } 622 }
623 623
624 static inline int 624 static inline int
625 ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, 625 ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
626 const char *name, unsigned int *cnt, 626 const char *name, unsigned int *cnt,
627 struct ebt_cl_stack *cl_s, unsigned int udc_cnt) 627 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
628 { 628 {
629 struct ebt_entry_target *t; 629 struct ebt_entry_target *t;
630 struct ebt_target *target; 630 struct ebt_target *target;
631 unsigned int i, j, hook = 0, hookmask = 0; 631 unsigned int i, j, hook = 0, hookmask = 0;
632 size_t gap; 632 size_t gap;
633 int ret; 633 int ret;
634 634
635 /* don't mess with the struct ebt_entries */ 635 /* don't mess with the struct ebt_entries */
636 if (e->bitmask == 0) 636 if (e->bitmask == 0)
637 return 0; 637 return 0;
638 638
639 if (e->bitmask & ~EBT_F_MASK) { 639 if (e->bitmask & ~EBT_F_MASK) {
640 BUGPRINT("Unknown flag for bitmask\n"); 640 BUGPRINT("Unknown flag for bitmask\n");
641 return -EINVAL; 641 return -EINVAL;
642 } 642 }
643 if (e->invflags & ~EBT_INV_MASK) { 643 if (e->invflags & ~EBT_INV_MASK) {
644 BUGPRINT("Unknown flag for inv bitmask\n"); 644 BUGPRINT("Unknown flag for inv bitmask\n");
645 return -EINVAL; 645 return -EINVAL;
646 } 646 }
647 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) { 647 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
648 BUGPRINT("NOPROTO & 802_3 not allowed\n"); 648 BUGPRINT("NOPROTO & 802_3 not allowed\n");
649 return -EINVAL; 649 return -EINVAL;
650 } 650 }
651 /* what hook do we belong to? */ 651 /* what hook do we belong to? */
652 for (i = 0; i < NF_BR_NUMHOOKS; i++) { 652 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
653 if (!newinfo->hook_entry[i]) 653 if (!newinfo->hook_entry[i])
654 continue; 654 continue;
655 if ((char *)newinfo->hook_entry[i] < (char *)e) 655 if ((char *)newinfo->hook_entry[i] < (char *)e)
656 hook = i; 656 hook = i;
657 else 657 else
658 break; 658 break;
659 } 659 }
660 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on 660 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
661 a base chain */ 661 a base chain */
662 if (i < NF_BR_NUMHOOKS) 662 if (i < NF_BR_NUMHOOKS)
663 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS); 663 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
664 else { 664 else {
665 for (i = 0; i < udc_cnt; i++) 665 for (i = 0; i < udc_cnt; i++)
666 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e) 666 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
667 break; 667 break;
668 if (i == 0) 668 if (i == 0)
669 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS); 669 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
670 else 670 else
671 hookmask = cl_s[i - 1].hookmask; 671 hookmask = cl_s[i - 1].hookmask;
672 } 672 }
673 i = 0; 673 i = 0;
674 ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i); 674 ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);
675 if (ret != 0) 675 if (ret != 0)
676 goto cleanup_matches; 676 goto cleanup_matches;
677 j = 0; 677 j = 0;
678 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j); 678 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
679 if (ret != 0) 679 if (ret != 0)
680 goto cleanup_watchers; 680 goto cleanup_watchers;
681 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); 681 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
682 gap = e->next_offset - e->target_offset; 682 gap = e->next_offset - e->target_offset;
683 target = find_target_lock(t->u.name, &ret, &ebt_mutex); 683 target = find_target_lock(t->u.name, &ret, &ebt_mutex);
684 if (!target) 684 if (!target)
685 goto cleanup_watchers; 685 goto cleanup_watchers;
686 if (!try_module_get(target->me)) { 686 if (!try_module_get(target->me)) {
687 mutex_unlock(&ebt_mutex); 687 mutex_unlock(&ebt_mutex);
688 ret = -ENOENT; 688 ret = -ENOENT;
689 goto cleanup_watchers; 689 goto cleanup_watchers;
690 } 690 }
691 mutex_unlock(&ebt_mutex); 691 mutex_unlock(&ebt_mutex);
692 692
693 t->u.target = target; 693 t->u.target = target;
694 if (t->u.target == &ebt_standard_target) { 694 if (t->u.target == &ebt_standard_target) {
695 if (gap < sizeof(struct ebt_standard_target)) { 695 if (gap < sizeof(struct ebt_standard_target)) {
696 BUGPRINT("Standard target size too big\n"); 696 BUGPRINT("Standard target size too big\n");
697 ret = -EFAULT; 697 ret = -EFAULT;
698 goto cleanup_watchers; 698 goto cleanup_watchers;
699 } 699 }
700 if (((struct ebt_standard_target *)t)->verdict < 700 if (((struct ebt_standard_target *)t)->verdict <
701 -NUM_STANDARD_TARGETS) { 701 -NUM_STANDARD_TARGETS) {
702 BUGPRINT("Invalid standard target\n"); 702 BUGPRINT("Invalid standard target\n");
703 ret = -EFAULT; 703 ret = -EFAULT;
704 goto cleanup_watchers; 704 goto cleanup_watchers;
705 } 705 }
706 } else if (t->target_size > gap - sizeof(struct ebt_entry_target)) { 706 } else if (t->target_size > gap - sizeof(struct ebt_entry_target)) {
707 module_put(t->u.target->me); 707 module_put(t->u.target->me);
708 ret = -EFAULT; 708 ret = -EFAULT;
709 goto cleanup_watchers; 709 goto cleanup_watchers;
710 } else if (XT_ALIGN(target->targetsize) != t->target_size) { 710 } else if (XT_ALIGN(target->targetsize) != t->target_size) {
711 printk(KERN_WARNING "ebtables: %s target: " 711 printk(KERN_WARNING "ebtables: %s target: "
712 "invalid size %Zu != %u\n", 712 "invalid size %Zu != %u\n",
713 target->name, XT_ALIGN(target->targetsize), 713 target->name, XT_ALIGN(target->targetsize),
714 t->target_size); 714 t->target_size);
715 module_put(t->u.target->me); 715 module_put(t->u.target->me);
716 ret = -EINVAL; 716 ret = -EINVAL;
717 goto cleanup_watchers; 717 goto cleanup_watchers;
718 } else if (t->u.target->check && 718 } else if (t->u.target->check &&
719 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0) { 719 !t->u.target->check(name, hookmask, e, t->data, t->target_size)) {
720 module_put(t->u.target->me); 720 module_put(t->u.target->me);
721 ret = -EFAULT; 721 ret = -EFAULT;
722 goto cleanup_watchers; 722 goto cleanup_watchers;
723 } 723 }
724 (*cnt)++; 724 (*cnt)++;
725 return 0; 725 return 0;
726 cleanup_watchers: 726 cleanup_watchers:
727 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j); 727 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);
728 cleanup_matches: 728 cleanup_matches:
729 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i); 729 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i);
730 return ret; 730 return ret;
731 } 731 }
732 732
733 /* 733 /*
734 * checks for loops and sets the hook mask for udc 734 * checks for loops and sets the hook mask for udc
735 * the hook mask for udc tells us from which base chains the udc can be 735 * the hook mask for udc tells us from which base chains the udc can be
736 * accessed. This mask is a parameter to the check() functions of the extensions 736 * accessed. This mask is a parameter to the check() functions of the extensions
737 */ 737 */
738 static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s, 738 static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
739 unsigned int udc_cnt, unsigned int hooknr, char *base) 739 unsigned int udc_cnt, unsigned int hooknr, char *base)
740 { 740 {
741 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict; 741 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
742 struct ebt_entry *e = (struct ebt_entry *)chain->data; 742 struct ebt_entry *e = (struct ebt_entry *)chain->data;
743 struct ebt_entry_target *t; 743 struct ebt_entry_target *t;
744 744
745 while (pos < nentries || chain_nr != -1) { 745 while (pos < nentries || chain_nr != -1) {
746 /* end of udc, go back one 'recursion' step */ 746 /* end of udc, go back one 'recursion' step */
747 if (pos == nentries) { 747 if (pos == nentries) {
748 /* put back values of the time when this chain was called */ 748 /* put back values of the time when this chain was called */
749 e = cl_s[chain_nr].cs.e; 749 e = cl_s[chain_nr].cs.e;
750 if (cl_s[chain_nr].from != -1) 750 if (cl_s[chain_nr].from != -1)
751 nentries = 751 nentries =
752 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries; 752 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
753 else 753 else
754 nentries = chain->nentries; 754 nentries = chain->nentries;
755 pos = cl_s[chain_nr].cs.n; 755 pos = cl_s[chain_nr].cs.n;
756 /* make sure we won't see a loop that isn't one */ 756 /* make sure we won't see a loop that isn't one */
757 cl_s[chain_nr].cs.n = 0; 757 cl_s[chain_nr].cs.n = 0;
758 chain_nr = cl_s[chain_nr].from; 758 chain_nr = cl_s[chain_nr].from;
759 if (pos == nentries) 759 if (pos == nentries)
760 continue; 760 continue;
761 } 761 }
762 t = (struct ebt_entry_target *) 762 t = (struct ebt_entry_target *)
763 (((char *)e) + e->target_offset); 763 (((char *)e) + e->target_offset);
764 if (strcmp(t->u.name, EBT_STANDARD_TARGET)) 764 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
765 goto letscontinue; 765 goto letscontinue;
766 if (e->target_offset + sizeof(struct ebt_standard_target) > 766 if (e->target_offset + sizeof(struct ebt_standard_target) >
767 e->next_offset) { 767 e->next_offset) {
768 BUGPRINT("Standard target size too big\n"); 768 BUGPRINT("Standard target size too big\n");
769 return -1; 769 return -1;
770 } 770 }
771 verdict = ((struct ebt_standard_target *)t)->verdict; 771 verdict = ((struct ebt_standard_target *)t)->verdict;
772 if (verdict >= 0) { /* jump to another chain */ 772 if (verdict >= 0) { /* jump to another chain */
773 struct ebt_entries *hlp2 = 773 struct ebt_entries *hlp2 =
774 (struct ebt_entries *)(base + verdict); 774 (struct ebt_entries *)(base + verdict);
775 for (i = 0; i < udc_cnt; i++) 775 for (i = 0; i < udc_cnt; i++)
776 if (hlp2 == cl_s[i].cs.chaininfo) 776 if (hlp2 == cl_s[i].cs.chaininfo)
777 break; 777 break;
778 /* bad destination or loop */ 778 /* bad destination or loop */
779 if (i == udc_cnt) { 779 if (i == udc_cnt) {
780 BUGPRINT("bad destination\n"); 780 BUGPRINT("bad destination\n");
781 return -1; 781 return -1;
782 } 782 }
783 if (cl_s[i].cs.n) { 783 if (cl_s[i].cs.n) {
784 BUGPRINT("loop\n"); 784 BUGPRINT("loop\n");
785 return -1; 785 return -1;
786 } 786 }
787 if (cl_s[i].hookmask & (1 << hooknr)) 787 if (cl_s[i].hookmask & (1 << hooknr))
788 goto letscontinue; 788 goto letscontinue;
789 /* this can't be 0, so the loop test is correct */ 789 /* this can't be 0, so the loop test is correct */
790 cl_s[i].cs.n = pos + 1; 790 cl_s[i].cs.n = pos + 1;
791 pos = 0; 791 pos = 0;
792 cl_s[i].cs.e = ((void *)e + e->next_offset); 792 cl_s[i].cs.e = ((void *)e + e->next_offset);
793 e = (struct ebt_entry *)(hlp2->data); 793 e = (struct ebt_entry *)(hlp2->data);
794 nentries = hlp2->nentries; 794 nentries = hlp2->nentries;
795 cl_s[i].from = chain_nr; 795 cl_s[i].from = chain_nr;
796 chain_nr = i; 796 chain_nr = i;
797 /* this udc is accessible from the base chain for hooknr */ 797 /* this udc is accessible from the base chain for hooknr */
798 cl_s[i].hookmask |= (1 << hooknr); 798 cl_s[i].hookmask |= (1 << hooknr);
799 continue; 799 continue;
800 } 800 }
801 letscontinue: 801 letscontinue:
802 e = (void *)e + e->next_offset; 802 e = (void *)e + e->next_offset;
803 pos++; 803 pos++;
804 } 804 }
805 return 0; 805 return 0;
806 } 806 }
807 807
808 /* do the parsing of the table/chains/entries/matches/watchers/targets, heh */ 808 /* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
809 static int translate_table(char *name, struct ebt_table_info *newinfo) 809 static int translate_table(char *name, struct ebt_table_info *newinfo)
810 { 810 {
811 unsigned int i, j, k, udc_cnt; 811 unsigned int i, j, k, udc_cnt;
812 int ret; 812 int ret;
813 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */ 813 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
814 814
815 i = 0; 815 i = 0;
816 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i]) 816 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
817 i++; 817 i++;
818 if (i == NF_BR_NUMHOOKS) { 818 if (i == NF_BR_NUMHOOKS) {
819 BUGPRINT("No valid hooks specified\n"); 819 BUGPRINT("No valid hooks specified\n");
820 return -EINVAL; 820 return -EINVAL;
821 } 821 }
822 if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) { 822 if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
823 BUGPRINT("Chains don't start at beginning\n"); 823 BUGPRINT("Chains don't start at beginning\n");
824 return -EINVAL; 824 return -EINVAL;
825 } 825 }
826 /* make sure chains are ordered after each other in same order 826 /* make sure chains are ordered after each other in same order
827 as their corresponding hooks */ 827 as their corresponding hooks */
828 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) { 828 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
829 if (!newinfo->hook_entry[j]) 829 if (!newinfo->hook_entry[j])
830 continue; 830 continue;
831 if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) { 831 if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
832 BUGPRINT("Hook order must be followed\n"); 832 BUGPRINT("Hook order must be followed\n");
833 return -EINVAL; 833 return -EINVAL;
834 } 834 }
835 i = j; 835 i = j;
836 } 836 }
837 837
838 /* do some early checkings and initialize some things */ 838 /* do some early checkings and initialize some things */
839 i = 0; /* holds the expected nr. of entries for the chain */ 839 i = 0; /* holds the expected nr. of entries for the chain */
840 j = 0; /* holds the up to now counted entries for the chain */ 840 j = 0; /* holds the up to now counted entries for the chain */
841 k = 0; /* holds the total nr. of entries, should equal 841 k = 0; /* holds the total nr. of entries, should equal
842 newinfo->nentries afterwards */ 842 newinfo->nentries afterwards */
843 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */ 843 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
844 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 844 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
845 ebt_check_entry_size_and_hooks, newinfo, 845 ebt_check_entry_size_and_hooks, newinfo,
846 &i, &j, &k, &udc_cnt); 846 &i, &j, &k, &udc_cnt);
847 847
848 if (ret != 0) 848 if (ret != 0)
849 return ret; 849 return ret;
850 850
851 if (i != j) { 851 if (i != j) {
852 BUGPRINT("nentries does not equal the nr of entries in the " 852 BUGPRINT("nentries does not equal the nr of entries in the "
853 "(last) chain\n"); 853 "(last) chain\n");
854 return -EINVAL; 854 return -EINVAL;
855 } 855 }
856 if (k != newinfo->nentries) { 856 if (k != newinfo->nentries) {
857 BUGPRINT("Total nentries is wrong\n"); 857 BUGPRINT("Total nentries is wrong\n");
858 return -EINVAL; 858 return -EINVAL;
859 } 859 }
860 860
861 /* get the location of the udc, put them in an array 861 /* get the location of the udc, put them in an array
862 while we're at it, allocate the chainstack */ 862 while we're at it, allocate the chainstack */
863 if (udc_cnt) { 863 if (udc_cnt) {
864 /* this will get free'd in do_replace()/ebt_register_table() 864 /* this will get free'd in do_replace()/ebt_register_table()
865 if an error occurs */ 865 if an error occurs */
866 newinfo->chainstack = 866 newinfo->chainstack =
867 vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack))); 867 vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
868 if (!newinfo->chainstack) 868 if (!newinfo->chainstack)
869 return -ENOMEM; 869 return -ENOMEM;
870 for_each_possible_cpu(i) { 870 for_each_possible_cpu(i) {
871 newinfo->chainstack[i] = 871 newinfo->chainstack[i] =
872 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0]))); 872 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
873 if (!newinfo->chainstack[i]) { 873 if (!newinfo->chainstack[i]) {
874 while (i) 874 while (i)
875 vfree(newinfo->chainstack[--i]); 875 vfree(newinfo->chainstack[--i]);
876 vfree(newinfo->chainstack); 876 vfree(newinfo->chainstack);
877 newinfo->chainstack = NULL; 877 newinfo->chainstack = NULL;
878 return -ENOMEM; 878 return -ENOMEM;
879 } 879 }
880 } 880 }
881 881
882 cl_s = vmalloc(udc_cnt * sizeof(*cl_s)); 882 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
883 if (!cl_s) 883 if (!cl_s)
884 return -ENOMEM; 884 return -ENOMEM;
885 i = 0; /* the i'th udc */ 885 i = 0; /* the i'th udc */
886 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 886 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
887 ebt_get_udc_positions, newinfo, &i, cl_s); 887 ebt_get_udc_positions, newinfo, &i, cl_s);
888 /* sanity check */ 888 /* sanity check */
889 if (i != udc_cnt) { 889 if (i != udc_cnt) {
890 BUGPRINT("i != udc_cnt\n"); 890 BUGPRINT("i != udc_cnt\n");
891 vfree(cl_s); 891 vfree(cl_s);
892 return -EFAULT; 892 return -EFAULT;
893 } 893 }
894 } 894 }
895 895
896 /* Check for loops */ 896 /* Check for loops */
897 for (i = 0; i < NF_BR_NUMHOOKS; i++) 897 for (i = 0; i < NF_BR_NUMHOOKS; i++)
898 if (newinfo->hook_entry[i]) 898 if (newinfo->hook_entry[i])
899 if (check_chainloops(newinfo->hook_entry[i], 899 if (check_chainloops(newinfo->hook_entry[i],
900 cl_s, udc_cnt, i, newinfo->entries)) { 900 cl_s, udc_cnt, i, newinfo->entries)) {
901 vfree(cl_s); 901 vfree(cl_s);
902 return -EINVAL; 902 return -EINVAL;
903 } 903 }
904 904
905 /* we now know the following (along with E=mcยฒ): 905 /* we now know the following (along with E=mcยฒ):
906 - the nr of entries in each chain is right 906 - the nr of entries in each chain is right
907 - the size of the allocated space is right 907 - the size of the allocated space is right
908 - all valid hooks have a corresponding chain 908 - all valid hooks have a corresponding chain
909 - there are no loops 909 - there are no loops
910 - wrong data can still be on the level of a single entry 910 - wrong data can still be on the level of a single entry
911 - could be there are jumps to places that are not the 911 - could be there are jumps to places that are not the
912 beginning of a chain. This can only occur in chains that 912 beginning of a chain. This can only occur in chains that
913 are not accessible from any base chains, so we don't care. */ 913 are not accessible from any base chains, so we don't care. */
914 914
915 /* used to know what we need to clean up if something goes wrong */ 915 /* used to know what we need to clean up if something goes wrong */
916 i = 0; 916 i = 0;
917 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 917 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
918 ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt); 918 ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt);
919 if (ret != 0) { 919 if (ret != 0) {
920 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 920 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
921 ebt_cleanup_entry, &i); 921 ebt_cleanup_entry, &i);
922 } 922 }
923 vfree(cl_s); 923 vfree(cl_s);
924 return ret; 924 return ret;
925 } 925 }
926 926
927 /* called under write_lock */ 927 /* called under write_lock */
928 static void get_counters(struct ebt_counter *oldcounters, 928 static void get_counters(struct ebt_counter *oldcounters,
929 struct ebt_counter *counters, unsigned int nentries) 929 struct ebt_counter *counters, unsigned int nentries)
930 { 930 {
931 int i, cpu; 931 int i, cpu;
932 struct ebt_counter *counter_base; 932 struct ebt_counter *counter_base;
933 933
934 /* counters of cpu 0 */ 934 /* counters of cpu 0 */
935 memcpy(counters, oldcounters, 935 memcpy(counters, oldcounters,
936 sizeof(struct ebt_counter) * nentries); 936 sizeof(struct ebt_counter) * nentries);
937 937
938 /* add other counters to those of cpu 0 */ 938 /* add other counters to those of cpu 0 */
939 for_each_possible_cpu(cpu) { 939 for_each_possible_cpu(cpu) {
940 if (cpu == 0) 940 if (cpu == 0)
941 continue; 941 continue;
942 counter_base = COUNTER_BASE(oldcounters, nentries, cpu); 942 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
943 for (i = 0; i < nentries; i++) { 943 for (i = 0; i < nentries; i++) {
944 counters[i].pcnt += counter_base[i].pcnt; 944 counters[i].pcnt += counter_base[i].pcnt;
945 counters[i].bcnt += counter_base[i].bcnt; 945 counters[i].bcnt += counter_base[i].bcnt;
946 } 946 }
947 } 947 }
948 } 948 }
949 949
950 /* replace the table */ 950 /* replace the table */
951 static int do_replace(void __user *user, unsigned int len) 951 static int do_replace(void __user *user, unsigned int len)
952 { 952 {
953 int ret, i, countersize; 953 int ret, i, countersize;
954 struct ebt_table_info *newinfo; 954 struct ebt_table_info *newinfo;
955 struct ebt_replace tmp; 955 struct ebt_replace tmp;
956 struct ebt_table *t; 956 struct ebt_table *t;
957 struct ebt_counter *counterstmp = NULL; 957 struct ebt_counter *counterstmp = NULL;
958 /* used to be able to unlock earlier */ 958 /* used to be able to unlock earlier */
959 struct ebt_table_info *table; 959 struct ebt_table_info *table;
960 960
961 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 961 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
962 return -EFAULT; 962 return -EFAULT;
963 963
964 if (len != sizeof(tmp) + tmp.entries_size) { 964 if (len != sizeof(tmp) + tmp.entries_size) {
965 BUGPRINT("Wrong len argument\n"); 965 BUGPRINT("Wrong len argument\n");
966 return -EINVAL; 966 return -EINVAL;
967 } 967 }
968 968
969 if (tmp.entries_size == 0) { 969 if (tmp.entries_size == 0) {
970 BUGPRINT("Entries_size never zero\n"); 970 BUGPRINT("Entries_size never zero\n");
971 return -EINVAL; 971 return -EINVAL;
972 } 972 }
973 /* overflow check */ 973 /* overflow check */
974 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS - 974 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
975 SMP_CACHE_BYTES) / sizeof(struct ebt_counter)) 975 SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
976 return -ENOMEM; 976 return -ENOMEM;
977 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) 977 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
978 return -ENOMEM; 978 return -ENOMEM;
979 979
980 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids; 980 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
981 newinfo = vmalloc(sizeof(*newinfo) + countersize); 981 newinfo = vmalloc(sizeof(*newinfo) + countersize);
982 if (!newinfo) 982 if (!newinfo)
983 return -ENOMEM; 983 return -ENOMEM;
984 984
985 if (countersize) 985 if (countersize)
986 memset(newinfo->counters, 0, countersize); 986 memset(newinfo->counters, 0, countersize);
987 987
988 newinfo->entries = vmalloc(tmp.entries_size); 988 newinfo->entries = vmalloc(tmp.entries_size);
989 if (!newinfo->entries) { 989 if (!newinfo->entries) {
990 ret = -ENOMEM; 990 ret = -ENOMEM;
991 goto free_newinfo; 991 goto free_newinfo;
992 } 992 }
993 if (copy_from_user( 993 if (copy_from_user(
994 newinfo->entries, tmp.entries, tmp.entries_size) != 0) { 994 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
995 BUGPRINT("Couldn't copy entries from userspace\n"); 995 BUGPRINT("Couldn't copy entries from userspace\n");
996 ret = -EFAULT; 996 ret = -EFAULT;
997 goto free_entries; 997 goto free_entries;
998 } 998 }
999 999
1000 /* the user wants counters back 1000 /* the user wants counters back
1001 the check on the size is done later, when we have the lock */ 1001 the check on the size is done later, when we have the lock */
1002 if (tmp.num_counters) { 1002 if (tmp.num_counters) {
1003 counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp)); 1003 counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
1004 if (!counterstmp) { 1004 if (!counterstmp) {
1005 ret = -ENOMEM; 1005 ret = -ENOMEM;
1006 goto free_entries; 1006 goto free_entries;
1007 } 1007 }
1008 } 1008 }
1009 else 1009 else
1010 counterstmp = NULL; 1010 counterstmp = NULL;
1011 1011
1012 /* this can get initialized by translate_table() */ 1012 /* this can get initialized by translate_table() */
1013 newinfo->chainstack = NULL; 1013 newinfo->chainstack = NULL;
1014 ret = ebt_verify_pointers(&tmp, newinfo); 1014 ret = ebt_verify_pointers(&tmp, newinfo);
1015 if (ret != 0) 1015 if (ret != 0)
1016 goto free_counterstmp; 1016 goto free_counterstmp;
1017 1017
1018 ret = translate_table(tmp.name, newinfo); 1018 ret = translate_table(tmp.name, newinfo);
1019 1019
1020 if (ret != 0) 1020 if (ret != 0)
1021 goto free_counterstmp; 1021 goto free_counterstmp;
1022 1022
1023 t = find_table_lock(tmp.name, &ret, &ebt_mutex); 1023 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1024 if (!t) { 1024 if (!t) {
1025 ret = -ENOENT; 1025 ret = -ENOENT;
1026 goto free_iterate; 1026 goto free_iterate;
1027 } 1027 }
1028 1028
1029 /* the table doesn't like it */ 1029 /* the table doesn't like it */
1030 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks))) 1030 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
1031 goto free_unlock; 1031 goto free_unlock;
1032 1032
1033 if (tmp.num_counters && tmp.num_counters != t->private->nentries) { 1033 if (tmp.num_counters && tmp.num_counters != t->private->nentries) {
1034 BUGPRINT("Wrong nr. of counters requested\n"); 1034 BUGPRINT("Wrong nr. of counters requested\n");
1035 ret = -EINVAL; 1035 ret = -EINVAL;
1036 goto free_unlock; 1036 goto free_unlock;
1037 } 1037 }
1038 1038
1039 /* we have the mutex lock, so no danger in reading this pointer */ 1039 /* we have the mutex lock, so no danger in reading this pointer */
1040 table = t->private; 1040 table = t->private;
1041 /* make sure the table can only be rmmod'ed if it contains no rules */ 1041 /* make sure the table can only be rmmod'ed if it contains no rules */
1042 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) { 1042 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
1043 ret = -ENOENT; 1043 ret = -ENOENT;
1044 goto free_unlock; 1044 goto free_unlock;
1045 } else if (table->nentries && !newinfo->nentries) 1045 } else if (table->nentries && !newinfo->nentries)
1046 module_put(t->me); 1046 module_put(t->me);
1047 /* we need an atomic snapshot of the counters */ 1047 /* we need an atomic snapshot of the counters */
1048 write_lock_bh(&t->lock); 1048 write_lock_bh(&t->lock);
1049 if (tmp.num_counters) 1049 if (tmp.num_counters)
1050 get_counters(t->private->counters, counterstmp, 1050 get_counters(t->private->counters, counterstmp,
1051 t->private->nentries); 1051 t->private->nentries);
1052 1052
1053 t->private = newinfo; 1053 t->private = newinfo;
1054 write_unlock_bh(&t->lock); 1054 write_unlock_bh(&t->lock);
1055 mutex_unlock(&ebt_mutex); 1055 mutex_unlock(&ebt_mutex);
1056 /* so, a user can change the chains while having messed up her counter 1056 /* so, a user can change the chains while having messed up her counter
1057 allocation. Only reason why this is done is because this way the lock 1057 allocation. Only reason why this is done is because this way the lock
1058 is held only once, while this doesn't bring the kernel into a 1058 is held only once, while this doesn't bring the kernel into a
1059 dangerous state. */ 1059 dangerous state. */
1060 if (tmp.num_counters && 1060 if (tmp.num_counters &&
1061 copy_to_user(tmp.counters, counterstmp, 1061 copy_to_user(tmp.counters, counterstmp,
1062 tmp.num_counters * sizeof(struct ebt_counter))) { 1062 tmp.num_counters * sizeof(struct ebt_counter))) {
1063 BUGPRINT("Couldn't copy counters to userspace\n"); 1063 BUGPRINT("Couldn't copy counters to userspace\n");
1064 ret = -EFAULT; 1064 ret = -EFAULT;
1065 } 1065 }
1066 else 1066 else
1067 ret = 0; 1067 ret = 0;
1068 1068
1069 /* decrease module count and free resources */ 1069 /* decrease module count and free resources */
1070 EBT_ENTRY_ITERATE(table->entries, table->entries_size, 1070 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
1071 ebt_cleanup_entry, NULL); 1071 ebt_cleanup_entry, NULL);
1072 1072
1073 vfree(table->entries); 1073 vfree(table->entries);
1074 if (table->chainstack) { 1074 if (table->chainstack) {
1075 for_each_possible_cpu(i) 1075 for_each_possible_cpu(i)
1076 vfree(table->chainstack[i]); 1076 vfree(table->chainstack[i]);
1077 vfree(table->chainstack); 1077 vfree(table->chainstack);
1078 } 1078 }
1079 vfree(table); 1079 vfree(table);
1080 1080
1081 vfree(counterstmp); 1081 vfree(counterstmp);
1082 return ret; 1082 return ret;
1083 1083
1084 free_unlock: 1084 free_unlock:
1085 mutex_unlock(&ebt_mutex); 1085 mutex_unlock(&ebt_mutex);
1086 free_iterate: 1086 free_iterate:
1087 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 1087 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1088 ebt_cleanup_entry, NULL); 1088 ebt_cleanup_entry, NULL);
1089 free_counterstmp: 1089 free_counterstmp:
1090 vfree(counterstmp); 1090 vfree(counterstmp);
1091 /* can be initialized in translate_table() */ 1091 /* can be initialized in translate_table() */
1092 if (newinfo->chainstack) { 1092 if (newinfo->chainstack) {
1093 for_each_possible_cpu(i) 1093 for_each_possible_cpu(i)
1094 vfree(newinfo->chainstack[i]); 1094 vfree(newinfo->chainstack[i]);
1095 vfree(newinfo->chainstack); 1095 vfree(newinfo->chainstack);
1096 } 1096 }
1097 free_entries: 1097 free_entries:
1098 vfree(newinfo->entries); 1098 vfree(newinfo->entries);
1099 free_newinfo: 1099 free_newinfo:
1100 vfree(newinfo); 1100 vfree(newinfo);
1101 return ret; 1101 return ret;
1102 } 1102 }
1103 1103
1104 int ebt_register_target(struct ebt_target *target) 1104 int ebt_register_target(struct ebt_target *target)
1105 { 1105 {
1106 struct ebt_target *t; 1106 struct ebt_target *t;
1107 int ret; 1107 int ret;
1108 1108
1109 ret = mutex_lock_interruptible(&ebt_mutex); 1109 ret = mutex_lock_interruptible(&ebt_mutex);
1110 if (ret != 0) 1110 if (ret != 0)
1111 return ret; 1111 return ret;
1112 list_for_each_entry(t, &ebt_targets, list) { 1112 list_for_each_entry(t, &ebt_targets, list) {
1113 if (strcmp(t->name, target->name) == 0) { 1113 if (strcmp(t->name, target->name) == 0) {
1114 mutex_unlock(&ebt_mutex); 1114 mutex_unlock(&ebt_mutex);
1115 return -EEXIST; 1115 return -EEXIST;
1116 } 1116 }
1117 } 1117 }
1118 list_add(&target->list, &ebt_targets); 1118 list_add(&target->list, &ebt_targets);
1119 mutex_unlock(&ebt_mutex); 1119 mutex_unlock(&ebt_mutex);
1120 1120
1121 return 0; 1121 return 0;
1122 } 1122 }
1123 1123
1124 void ebt_unregister_target(struct ebt_target *target) 1124 void ebt_unregister_target(struct ebt_target *target)
1125 { 1125 {
1126 mutex_lock(&ebt_mutex); 1126 mutex_lock(&ebt_mutex);
1127 list_del(&target->list); 1127 list_del(&target->list);
1128 mutex_unlock(&ebt_mutex); 1128 mutex_unlock(&ebt_mutex);
1129 } 1129 }
1130 1130
1131 int ebt_register_match(struct ebt_match *match) 1131 int ebt_register_match(struct ebt_match *match)
1132 { 1132 {
1133 struct ebt_match *m; 1133 struct ebt_match *m;
1134 int ret; 1134 int ret;
1135 1135
1136 ret = mutex_lock_interruptible(&ebt_mutex); 1136 ret = mutex_lock_interruptible(&ebt_mutex);
1137 if (ret != 0) 1137 if (ret != 0)
1138 return ret; 1138 return ret;
1139 list_for_each_entry(m, &ebt_matches, list) { 1139 list_for_each_entry(m, &ebt_matches, list) {
1140 if (strcmp(m->name, match->name) == 0) { 1140 if (strcmp(m->name, match->name) == 0) {
1141 mutex_unlock(&ebt_mutex); 1141 mutex_unlock(&ebt_mutex);
1142 return -EEXIST; 1142 return -EEXIST;
1143 } 1143 }
1144 } 1144 }
1145 list_add(&match->list, &ebt_matches); 1145 list_add(&match->list, &ebt_matches);
1146 mutex_unlock(&ebt_mutex); 1146 mutex_unlock(&ebt_mutex);
1147 1147
1148 return 0; 1148 return 0;
1149 } 1149 }
1150 1150
1151 void ebt_unregister_match(struct ebt_match *match) 1151 void ebt_unregister_match(struct ebt_match *match)
1152 { 1152 {
1153 mutex_lock(&ebt_mutex); 1153 mutex_lock(&ebt_mutex);
1154 list_del(&match->list); 1154 list_del(&match->list);
1155 mutex_unlock(&ebt_mutex); 1155 mutex_unlock(&ebt_mutex);
1156 } 1156 }
1157 1157
1158 int ebt_register_watcher(struct ebt_watcher *watcher) 1158 int ebt_register_watcher(struct ebt_watcher *watcher)
1159 { 1159 {
1160 struct ebt_watcher *w; 1160 struct ebt_watcher *w;
1161 int ret; 1161 int ret;
1162 1162
1163 ret = mutex_lock_interruptible(&ebt_mutex); 1163 ret = mutex_lock_interruptible(&ebt_mutex);
1164 if (ret != 0) 1164 if (ret != 0)
1165 return ret; 1165 return ret;
1166 list_for_each_entry(w, &ebt_watchers, list) { 1166 list_for_each_entry(w, &ebt_watchers, list) {
1167 if (strcmp(w->name, watcher->name) == 0) { 1167 if (strcmp(w->name, watcher->name) == 0) {
1168 mutex_unlock(&ebt_mutex); 1168 mutex_unlock(&ebt_mutex);
1169 return -EEXIST; 1169 return -EEXIST;
1170 } 1170 }
1171 } 1171 }
1172 list_add(&watcher->list, &ebt_watchers); 1172 list_add(&watcher->list, &ebt_watchers);
1173 mutex_unlock(&ebt_mutex); 1173 mutex_unlock(&ebt_mutex);
1174 1174
1175 return 0; 1175 return 0;
1176 } 1176 }
1177 1177
1178 void ebt_unregister_watcher(struct ebt_watcher *watcher) 1178 void ebt_unregister_watcher(struct ebt_watcher *watcher)
1179 { 1179 {
1180 mutex_lock(&ebt_mutex); 1180 mutex_lock(&ebt_mutex);
1181 list_del(&watcher->list); 1181 list_del(&watcher->list);
1182 mutex_unlock(&ebt_mutex); 1182 mutex_unlock(&ebt_mutex);
1183 } 1183 }
1184 1184
1185 int ebt_register_table(struct ebt_table *table) 1185 int ebt_register_table(struct ebt_table *table)
1186 { 1186 {
1187 struct ebt_table_info *newinfo; 1187 struct ebt_table_info *newinfo;
1188 struct ebt_table *t; 1188 struct ebt_table *t;
1189 struct ebt_replace_kernel *repl; 1189 struct ebt_replace_kernel *repl;
1190 int ret, i, countersize; 1190 int ret, i, countersize;
1191 void *p; 1191 void *p;
1192 1192
1193 if (!table || !(repl = table->table) || !repl->entries || 1193 if (!table || !(repl = table->table) || !repl->entries ||
1194 repl->entries_size == 0 || 1194 repl->entries_size == 0 ||
1195 repl->counters || table->private) { 1195 repl->counters || table->private) {
1196 BUGPRINT("Bad table data for ebt_register_table!!!\n"); 1196 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1197 return -EINVAL; 1197 return -EINVAL;
1198 } 1198 }
1199 1199
1200 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids; 1200 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
1201 newinfo = vmalloc(sizeof(*newinfo) + countersize); 1201 newinfo = vmalloc(sizeof(*newinfo) + countersize);
1202 ret = -ENOMEM; 1202 ret = -ENOMEM;
1203 if (!newinfo) 1203 if (!newinfo)
1204 return -ENOMEM; 1204 return -ENOMEM;
1205 1205
1206 p = vmalloc(repl->entries_size); 1206 p = vmalloc(repl->entries_size);
1207 if (!p) 1207 if (!p)
1208 goto free_newinfo; 1208 goto free_newinfo;
1209 1209
1210 memcpy(p, repl->entries, repl->entries_size); 1210 memcpy(p, repl->entries, repl->entries_size);
1211 newinfo->entries = p; 1211 newinfo->entries = p;
1212 1212
1213 newinfo->entries_size = repl->entries_size; 1213 newinfo->entries_size = repl->entries_size;
1214 newinfo->nentries = repl->nentries; 1214 newinfo->nentries = repl->nentries;
1215 1215
1216 if (countersize) 1216 if (countersize)
1217 memset(newinfo->counters, 0, countersize); 1217 memset(newinfo->counters, 0, countersize);
1218 1218
1219 /* fill in newinfo and parse the entries */ 1219 /* fill in newinfo and parse the entries */
1220 newinfo->chainstack = NULL; 1220 newinfo->chainstack = NULL;
1221 for (i = 0; i < NF_BR_NUMHOOKS; i++) { 1221 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1222 if ((repl->valid_hooks & (1 << i)) == 0) 1222 if ((repl->valid_hooks & (1 << i)) == 0)
1223 newinfo->hook_entry[i] = NULL; 1223 newinfo->hook_entry[i] = NULL;
1224 else 1224 else
1225 newinfo->hook_entry[i] = p + 1225 newinfo->hook_entry[i] = p +
1226 ((char *)repl->hook_entry[i] - repl->entries); 1226 ((char *)repl->hook_entry[i] - repl->entries);
1227 } 1227 }
1228 ret = translate_table(repl->name, newinfo); 1228 ret = translate_table(repl->name, newinfo);
1229 if (ret != 0) { 1229 if (ret != 0) {
1230 BUGPRINT("Translate_table failed\n"); 1230 BUGPRINT("Translate_table failed\n");
1231 goto free_chainstack; 1231 goto free_chainstack;
1232 } 1232 }
1233 1233
1234 if (table->check && table->check(newinfo, table->valid_hooks)) { 1234 if (table->check && table->check(newinfo, table->valid_hooks)) {
1235 BUGPRINT("The table doesn't like its own initial data, lol\n"); 1235 BUGPRINT("The table doesn't like its own initial data, lol\n");
1236 return -EINVAL; 1236 return -EINVAL;
1237 } 1237 }
1238 1238
1239 table->private = newinfo; 1239 table->private = newinfo;
1240 rwlock_init(&table->lock); 1240 rwlock_init(&table->lock);
1241 ret = mutex_lock_interruptible(&ebt_mutex); 1241 ret = mutex_lock_interruptible(&ebt_mutex);
1242 if (ret != 0) 1242 if (ret != 0)
1243 goto free_chainstack; 1243 goto free_chainstack;
1244 1244
1245 list_for_each_entry(t, &ebt_tables, list) { 1245 list_for_each_entry(t, &ebt_tables, list) {
1246 if (strcmp(t->name, table->name) == 0) { 1246 if (strcmp(t->name, table->name) == 0) {
1247 ret = -EEXIST; 1247 ret = -EEXIST;
1248 BUGPRINT("Table name already exists\n"); 1248 BUGPRINT("Table name already exists\n");
1249 goto free_unlock; 1249 goto free_unlock;
1250 } 1250 }
1251 } 1251 }
1252 1252
1253 /* Hold a reference count if the chains aren't empty */ 1253 /* Hold a reference count if the chains aren't empty */
1254 if (newinfo->nentries && !try_module_get(table->me)) { 1254 if (newinfo->nentries && !try_module_get(table->me)) {
1255 ret = -ENOENT; 1255 ret = -ENOENT;
1256 goto free_unlock; 1256 goto free_unlock;
1257 } 1257 }
1258 list_add(&table->list, &ebt_tables); 1258 list_add(&table->list, &ebt_tables);
1259 mutex_unlock(&ebt_mutex); 1259 mutex_unlock(&ebt_mutex);
1260 return 0; 1260 return 0;
1261 free_unlock: 1261 free_unlock:
1262 mutex_unlock(&ebt_mutex); 1262 mutex_unlock(&ebt_mutex);
1263 free_chainstack: 1263 free_chainstack:
1264 if (newinfo->chainstack) { 1264 if (newinfo->chainstack) {
1265 for_each_possible_cpu(i) 1265 for_each_possible_cpu(i)
1266 vfree(newinfo->chainstack[i]); 1266 vfree(newinfo->chainstack[i]);
1267 vfree(newinfo->chainstack); 1267 vfree(newinfo->chainstack);
1268 } 1268 }
1269 vfree(newinfo->entries); 1269 vfree(newinfo->entries);
1270 free_newinfo: 1270 free_newinfo:
1271 vfree(newinfo); 1271 vfree(newinfo);
1272 return ret; 1272 return ret;
1273 } 1273 }
1274 1274
1275 void ebt_unregister_table(struct ebt_table *table) 1275 void ebt_unregister_table(struct ebt_table *table)
1276 { 1276 {
1277 int i; 1277 int i;
1278 1278
1279 if (!table) { 1279 if (!table) {
1280 BUGPRINT("Request to unregister NULL table!!!\n"); 1280 BUGPRINT("Request to unregister NULL table!!!\n");
1281 return; 1281 return;
1282 } 1282 }
1283 mutex_lock(&ebt_mutex); 1283 mutex_lock(&ebt_mutex);
1284 list_del(&table->list); 1284 list_del(&table->list);
1285 mutex_unlock(&ebt_mutex); 1285 mutex_unlock(&ebt_mutex);
1286 vfree(table->private->entries); 1286 vfree(table->private->entries);
1287 if (table->private->chainstack) { 1287 if (table->private->chainstack) {
1288 for_each_possible_cpu(i) 1288 for_each_possible_cpu(i)
1289 vfree(table->private->chainstack[i]); 1289 vfree(table->private->chainstack[i]);
1290 vfree(table->private->chainstack); 1290 vfree(table->private->chainstack);
1291 } 1291 }
1292 vfree(table->private); 1292 vfree(table->private);
1293 } 1293 }
1294 1294
1295 /* userspace just supplied us with counters */ 1295 /* userspace just supplied us with counters */
1296 static int update_counters(void __user *user, unsigned int len) 1296 static int update_counters(void __user *user, unsigned int len)
1297 { 1297 {
1298 int i, ret; 1298 int i, ret;
1299 struct ebt_counter *tmp; 1299 struct ebt_counter *tmp;
1300 struct ebt_replace hlp; 1300 struct ebt_replace hlp;
1301 struct ebt_table *t; 1301 struct ebt_table *t;
1302 1302
1303 if (copy_from_user(&hlp, user, sizeof(hlp))) 1303 if (copy_from_user(&hlp, user, sizeof(hlp)))
1304 return -EFAULT; 1304 return -EFAULT;
1305 1305
1306 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter)) 1306 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1307 return -EINVAL; 1307 return -EINVAL;
1308 if (hlp.num_counters == 0) 1308 if (hlp.num_counters == 0)
1309 return -EINVAL; 1309 return -EINVAL;
1310 1310
1311 if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) { 1311 if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
1312 MEMPRINT("Update_counters && nomemory\n"); 1312 MEMPRINT("Update_counters && nomemory\n");
1313 return -ENOMEM; 1313 return -ENOMEM;
1314 } 1314 }
1315 1315
1316 t = find_table_lock(hlp.name, &ret, &ebt_mutex); 1316 t = find_table_lock(hlp.name, &ret, &ebt_mutex);
1317 if (!t) 1317 if (!t)
1318 goto free_tmp; 1318 goto free_tmp;
1319 1319
1320 if (hlp.num_counters != t->private->nentries) { 1320 if (hlp.num_counters != t->private->nentries) {
1321 BUGPRINT("Wrong nr of counters\n"); 1321 BUGPRINT("Wrong nr of counters\n");
1322 ret = -EINVAL; 1322 ret = -EINVAL;
1323 goto unlock_mutex; 1323 goto unlock_mutex;
1324 } 1324 }
1325 1325
1326 if ( copy_from_user(tmp, hlp.counters, 1326 if ( copy_from_user(tmp, hlp.counters,
1327 hlp.num_counters * sizeof(struct ebt_counter)) ) { 1327 hlp.num_counters * sizeof(struct ebt_counter)) ) {
1328 BUGPRINT("Updata_counters && !cfu\n"); 1328 BUGPRINT("Updata_counters && !cfu\n");
1329 ret = -EFAULT; 1329 ret = -EFAULT;
1330 goto unlock_mutex; 1330 goto unlock_mutex;
1331 } 1331 }
1332 1332
1333 /* we want an atomic add of the counters */ 1333 /* we want an atomic add of the counters */
1334 write_lock_bh(&t->lock); 1334 write_lock_bh(&t->lock);
1335 1335
1336 /* we add to the counters of the first cpu */ 1336 /* we add to the counters of the first cpu */
1337 for (i = 0; i < hlp.num_counters; i++) { 1337 for (i = 0; i < hlp.num_counters; i++) {
1338 t->private->counters[i].pcnt += tmp[i].pcnt; 1338 t->private->counters[i].pcnt += tmp[i].pcnt;
1339 t->private->counters[i].bcnt += tmp[i].bcnt; 1339 t->private->counters[i].bcnt += tmp[i].bcnt;
1340 } 1340 }
1341 1341
1342 write_unlock_bh(&t->lock); 1342 write_unlock_bh(&t->lock);
1343 ret = 0; 1343 ret = 0;
1344 unlock_mutex: 1344 unlock_mutex:
1345 mutex_unlock(&ebt_mutex); 1345 mutex_unlock(&ebt_mutex);
1346 free_tmp: 1346 free_tmp:
1347 vfree(tmp); 1347 vfree(tmp);
1348 return ret; 1348 return ret;
1349 } 1349 }
1350 1350
1351 static inline int ebt_make_matchname(struct ebt_entry_match *m, 1351 static inline int ebt_make_matchname(struct ebt_entry_match *m,
1352 char *base, char __user *ubase) 1352 char *base, char __user *ubase)
1353 { 1353 {
1354 char __user *hlp = ubase + ((char *)m - base); 1354 char __user *hlp = ubase + ((char *)m - base);
1355 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN)) 1355 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1356 return -EFAULT; 1356 return -EFAULT;
1357 return 0; 1357 return 0;
1358 } 1358 }
1359 1359
1360 static inline int ebt_make_watchername(struct ebt_entry_watcher *w, 1360 static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
1361 char *base, char __user *ubase) 1361 char *base, char __user *ubase)
1362 { 1362 {
1363 char __user *hlp = ubase + ((char *)w - base); 1363 char __user *hlp = ubase + ((char *)w - base);
1364 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN)) 1364 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1365 return -EFAULT; 1365 return -EFAULT;
1366 return 0; 1366 return 0;
1367 } 1367 }
1368 1368
1369 static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase) 1369 static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase)
1370 { 1370 {
1371 int ret; 1371 int ret;
1372 char __user *hlp; 1372 char __user *hlp;
1373 struct ebt_entry_target *t; 1373 struct ebt_entry_target *t;
1374 1374
1375 if (e->bitmask == 0) 1375 if (e->bitmask == 0)
1376 return 0; 1376 return 0;
1377 1377
1378 hlp = ubase + (((char *)e + e->target_offset) - base); 1378 hlp = ubase + (((char *)e + e->target_offset) - base);
1379 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); 1379 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
1380 1380
1381 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase); 1381 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1382 if (ret != 0) 1382 if (ret != 0)
1383 return ret; 1383 return ret;
1384 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase); 1384 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1385 if (ret != 0) 1385 if (ret != 0)
1386 return ret; 1386 return ret;
1387 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN)) 1387 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1388 return -EFAULT; 1388 return -EFAULT;
1389 return 0; 1389 return 0;
1390 } 1390 }
1391 1391
1392 /* called with ebt_mutex locked */ 1392 /* called with ebt_mutex locked */
1393 static int copy_everything_to_user(struct ebt_table *t, void __user *user, 1393 static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1394 int *len, int cmd) 1394 int *len, int cmd)
1395 { 1395 {
1396 struct ebt_replace tmp; 1396 struct ebt_replace tmp;
1397 struct ebt_counter *counterstmp, *oldcounters; 1397 struct ebt_counter *counterstmp, *oldcounters;
1398 unsigned int entries_size, nentries; 1398 unsigned int entries_size, nentries;
1399 char *entries; 1399 char *entries;
1400 1400
1401 if (cmd == EBT_SO_GET_ENTRIES) { 1401 if (cmd == EBT_SO_GET_ENTRIES) {
1402 entries_size = t->private->entries_size; 1402 entries_size = t->private->entries_size;
1403 nentries = t->private->nentries; 1403 nentries = t->private->nentries;
1404 entries = t->private->entries; 1404 entries = t->private->entries;
1405 oldcounters = t->private->counters; 1405 oldcounters = t->private->counters;
1406 } else { 1406 } else {
1407 entries_size = t->table->entries_size; 1407 entries_size = t->table->entries_size;
1408 nentries = t->table->nentries; 1408 nentries = t->table->nentries;
1409 entries = t->table->entries; 1409 entries = t->table->entries;
1410 oldcounters = t->table->counters; 1410 oldcounters = t->table->counters;
1411 } 1411 }
1412 1412
1413 if (copy_from_user(&tmp, user, sizeof(tmp))) { 1413 if (copy_from_user(&tmp, user, sizeof(tmp))) {
1414 BUGPRINT("Cfu didn't work\n"); 1414 BUGPRINT("Cfu didn't work\n");
1415 return -EFAULT; 1415 return -EFAULT;
1416 } 1416 }
1417 1417
1418 if (*len != sizeof(struct ebt_replace) + entries_size + 1418 if (*len != sizeof(struct ebt_replace) + entries_size +
1419 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) { 1419 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
1420 BUGPRINT("Wrong size\n"); 1420 BUGPRINT("Wrong size\n");
1421 return -EINVAL; 1421 return -EINVAL;
1422 } 1422 }
1423 1423
1424 if (tmp.nentries != nentries) { 1424 if (tmp.nentries != nentries) {
1425 BUGPRINT("Nentries wrong\n"); 1425 BUGPRINT("Nentries wrong\n");
1426 return -EINVAL; 1426 return -EINVAL;
1427 } 1427 }
1428 1428
1429 if (tmp.entries_size != entries_size) { 1429 if (tmp.entries_size != entries_size) {
1430 BUGPRINT("Wrong size\n"); 1430 BUGPRINT("Wrong size\n");
1431 return -EINVAL; 1431 return -EINVAL;
1432 } 1432 }
1433 1433
1434 /* userspace might not need the counters */ 1434 /* userspace might not need the counters */
1435 if (tmp.num_counters) { 1435 if (tmp.num_counters) {
1436 if (tmp.num_counters != nentries) { 1436 if (tmp.num_counters != nentries) {
1437 BUGPRINT("Num_counters wrong\n"); 1437 BUGPRINT("Num_counters wrong\n");
1438 return -EINVAL; 1438 return -EINVAL;
1439 } 1439 }
1440 counterstmp = vmalloc(nentries * sizeof(*counterstmp)); 1440 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
1441 if (!counterstmp) { 1441 if (!counterstmp) {
1442 MEMPRINT("Couldn't copy counters, out of memory\n"); 1442 MEMPRINT("Couldn't copy counters, out of memory\n");
1443 return -ENOMEM; 1443 return -ENOMEM;
1444 } 1444 }
1445 write_lock_bh(&t->lock); 1445 write_lock_bh(&t->lock);
1446 get_counters(oldcounters, counterstmp, nentries); 1446 get_counters(oldcounters, counterstmp, nentries);
1447 write_unlock_bh(&t->lock); 1447 write_unlock_bh(&t->lock);
1448 1448
1449 if (copy_to_user(tmp.counters, counterstmp, 1449 if (copy_to_user(tmp.counters, counterstmp,
1450 nentries * sizeof(struct ebt_counter))) { 1450 nentries * sizeof(struct ebt_counter))) {
1451 BUGPRINT("Couldn't copy counters to userspace\n"); 1451 BUGPRINT("Couldn't copy counters to userspace\n");
1452 vfree(counterstmp); 1452 vfree(counterstmp);
1453 return -EFAULT; 1453 return -EFAULT;
1454 } 1454 }
1455 vfree(counterstmp); 1455 vfree(counterstmp);
1456 } 1456 }
1457 1457
1458 if (copy_to_user(tmp.entries, entries, entries_size)) { 1458 if (copy_to_user(tmp.entries, entries, entries_size)) {
1459 BUGPRINT("Couldn't copy entries to userspace\n"); 1459 BUGPRINT("Couldn't copy entries to userspace\n");
1460 return -EFAULT; 1460 return -EFAULT;
1461 } 1461 }
1462 /* set the match/watcher/target names right */ 1462 /* set the match/watcher/target names right */
1463 return EBT_ENTRY_ITERATE(entries, entries_size, 1463 return EBT_ENTRY_ITERATE(entries, entries_size,
1464 ebt_make_names, entries, tmp.entries); 1464 ebt_make_names, entries, tmp.entries);
1465 } 1465 }
1466 1466
1467 static int do_ebt_set_ctl(struct sock *sk, 1467 static int do_ebt_set_ctl(struct sock *sk,
1468 int cmd, void __user *user, unsigned int len) 1468 int cmd, void __user *user, unsigned int len)
1469 { 1469 {
1470 int ret; 1470 int ret;
1471 1471
1472 switch(cmd) { 1472 switch(cmd) {
1473 case EBT_SO_SET_ENTRIES: 1473 case EBT_SO_SET_ENTRIES:
1474 ret = do_replace(user, len); 1474 ret = do_replace(user, len);
1475 break; 1475 break;
1476 case EBT_SO_SET_COUNTERS: 1476 case EBT_SO_SET_COUNTERS:
1477 ret = update_counters(user, len); 1477 ret = update_counters(user, len);
1478 break; 1478 break;
1479 default: 1479 default:
1480 ret = -EINVAL; 1480 ret = -EINVAL;
1481 } 1481 }
1482 return ret; 1482 return ret;
1483 } 1483 }
1484 1484
1485 static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) 1485 static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1486 { 1486 {
1487 int ret; 1487 int ret;
1488 struct ebt_replace tmp; 1488 struct ebt_replace tmp;
1489 struct ebt_table *t; 1489 struct ebt_table *t;
1490 1490
1491 if (copy_from_user(&tmp, user, sizeof(tmp))) 1491 if (copy_from_user(&tmp, user, sizeof(tmp)))
1492 return -EFAULT; 1492 return -EFAULT;
1493 1493
1494 t = find_table_lock(tmp.name, &ret, &ebt_mutex); 1494 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1495 if (!t) 1495 if (!t)
1496 return ret; 1496 return ret;
1497 1497
1498 switch(cmd) { 1498 switch(cmd) {
1499 case EBT_SO_GET_INFO: 1499 case EBT_SO_GET_INFO:
1500 case EBT_SO_GET_INIT_INFO: 1500 case EBT_SO_GET_INIT_INFO:
1501 if (*len != sizeof(struct ebt_replace)){ 1501 if (*len != sizeof(struct ebt_replace)){
1502 ret = -EINVAL; 1502 ret = -EINVAL;
1503 mutex_unlock(&ebt_mutex); 1503 mutex_unlock(&ebt_mutex);
1504 break; 1504 break;
1505 } 1505 }
1506 if (cmd == EBT_SO_GET_INFO) { 1506 if (cmd == EBT_SO_GET_INFO) {
1507 tmp.nentries = t->private->nentries; 1507 tmp.nentries = t->private->nentries;
1508 tmp.entries_size = t->private->entries_size; 1508 tmp.entries_size = t->private->entries_size;
1509 tmp.valid_hooks = t->valid_hooks; 1509 tmp.valid_hooks = t->valid_hooks;
1510 } else { 1510 } else {
1511 tmp.nentries = t->table->nentries; 1511 tmp.nentries = t->table->nentries;
1512 tmp.entries_size = t->table->entries_size; 1512 tmp.entries_size = t->table->entries_size;
1513 tmp.valid_hooks = t->table->valid_hooks; 1513 tmp.valid_hooks = t->table->valid_hooks;
1514 } 1514 }
1515 mutex_unlock(&ebt_mutex); 1515 mutex_unlock(&ebt_mutex);
1516 if (copy_to_user(user, &tmp, *len) != 0){ 1516 if (copy_to_user(user, &tmp, *len) != 0){
1517 BUGPRINT("c2u Didn't work\n"); 1517 BUGPRINT("c2u Didn't work\n");
1518 ret = -EFAULT; 1518 ret = -EFAULT;
1519 break; 1519 break;
1520 } 1520 }
1521 ret = 0; 1521 ret = 0;
1522 break; 1522 break;
1523 1523
1524 case EBT_SO_GET_ENTRIES: 1524 case EBT_SO_GET_ENTRIES:
1525 case EBT_SO_GET_INIT_ENTRIES: 1525 case EBT_SO_GET_INIT_ENTRIES:
1526 ret = copy_everything_to_user(t, user, len, cmd); 1526 ret = copy_everything_to_user(t, user, len, cmd);
1527 mutex_unlock(&ebt_mutex); 1527 mutex_unlock(&ebt_mutex);
1528 break; 1528 break;
1529 1529
1530 default: 1530 default:
1531 mutex_unlock(&ebt_mutex); 1531 mutex_unlock(&ebt_mutex);
1532 ret = -EINVAL; 1532 ret = -EINVAL;
1533 } 1533 }
1534 1534
1535 return ret; 1535 return ret;
1536 } 1536 }
1537 1537
1538 static struct nf_sockopt_ops ebt_sockopts = 1538 static struct nf_sockopt_ops ebt_sockopts =
1539 { 1539 {
1540 .pf = PF_INET, 1540 .pf = PF_INET,
1541 .set_optmin = EBT_BASE_CTL, 1541 .set_optmin = EBT_BASE_CTL,
1542 .set_optmax = EBT_SO_SET_MAX + 1, 1542 .set_optmax = EBT_SO_SET_MAX + 1,
1543 .set = do_ebt_set_ctl, 1543 .set = do_ebt_set_ctl,
1544 .get_optmin = EBT_BASE_CTL, 1544 .get_optmin = EBT_BASE_CTL,
1545 .get_optmax = EBT_SO_GET_MAX + 1, 1545 .get_optmax = EBT_SO_GET_MAX + 1,
1546 .get = do_ebt_get_ctl, 1546 .get = do_ebt_get_ctl,
1547 .owner = THIS_MODULE, 1547 .owner = THIS_MODULE,
1548 }; 1548 };
1549 1549
1550 static int __init ebtables_init(void) 1550 static int __init ebtables_init(void)
1551 { 1551 {
1552 int ret; 1552 int ret;
1553 1553
1554 mutex_lock(&ebt_mutex); 1554 mutex_lock(&ebt_mutex);
1555 list_add(&ebt_standard_target.list, &ebt_targets); 1555 list_add(&ebt_standard_target.list, &ebt_targets);
1556 mutex_unlock(&ebt_mutex); 1556 mutex_unlock(&ebt_mutex);
1557 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) 1557 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
1558 return ret; 1558 return ret;
1559 1559
1560 printk(KERN_INFO "Ebtables v2.0 registered\n"); 1560 printk(KERN_INFO "Ebtables v2.0 registered\n");
1561 return 0; 1561 return 0;
1562 } 1562 }
1563 1563
1564 static void __exit ebtables_fini(void) 1564 static void __exit ebtables_fini(void)
1565 { 1565 {
1566 nf_unregister_sockopt(&ebt_sockopts); 1566 nf_unregister_sockopt(&ebt_sockopts);
1567 printk(KERN_INFO "Ebtables v2.0 unregistered\n"); 1567 printk(KERN_INFO "Ebtables v2.0 unregistered\n");
1568 } 1568 }
1569 1569
1570 EXPORT_SYMBOL(ebt_register_table); 1570 EXPORT_SYMBOL(ebt_register_table);
1571 EXPORT_SYMBOL(ebt_unregister_table); 1571 EXPORT_SYMBOL(ebt_unregister_table);
1572 EXPORT_SYMBOL(ebt_register_match); 1572 EXPORT_SYMBOL(ebt_register_match);
1573 EXPORT_SYMBOL(ebt_unregister_match); 1573 EXPORT_SYMBOL(ebt_unregister_match);
1574 EXPORT_SYMBOL(ebt_register_watcher); 1574 EXPORT_SYMBOL(ebt_register_watcher);
1575 EXPORT_SYMBOL(ebt_unregister_watcher); 1575 EXPORT_SYMBOL(ebt_unregister_watcher);
1576 EXPORT_SYMBOL(ebt_register_target); 1576 EXPORT_SYMBOL(ebt_register_target);
1577 EXPORT_SYMBOL(ebt_unregister_target); 1577 EXPORT_SYMBOL(ebt_unregister_target);
1578 EXPORT_SYMBOL(ebt_do_table); 1578 EXPORT_SYMBOL(ebt_do_table);
1579 module_init(ebtables_init); 1579 module_init(ebtables_init);
1580 module_exit(ebtables_fini); 1580 module_exit(ebtables_fini);
1581 MODULE_LICENSE("GPL"); 1581 MODULE_LICENSE("GPL");
1582 1582