blob: 9b2bbe5c2a8e90ecc403e82f2b78d966f7059d90 [file] [log] [blame]
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001/*
2 * ebtables
3 *
4 * Author:
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +00005 * Bart De Schuymer <bdschuym@pandora.be>
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00006 *
7 * ebtables.c,v 2.0, July, 2002
8 *
9 * This code is stongly inspired on the iptables code which is
10 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +000018/* used for print_string */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +000019#include <linux/sched.h>
20#include <linux/tty.h>
21
22#include <linux/kmod.h>
23#include <linux/module.h>
24#include <linux/vmalloc.h>
25#include <linux/netfilter_bridge/ebtables.h>
26#include <linux/spinlock.h>
27#include <asm/uaccess.h>
28#include <linux/smp.h>
29#include <net/sock.h>
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +000030/* needed for logical [in,out]-dev filtering */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +000031#include "../br_private.h"
32
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +000033/* list_named_find */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +000034#define ASSERT_READ_LOCK(x)
35#define ASSERT_WRITE_LOCK(x)
36#include <linux/netfilter_ipv4/listhelp.h>
37
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +000038#if 0
39/* use this for remote debugging
40 * Copyright (C) 1998 by Ori Pomerantz
41 * Print the string to the appropriate tty, the one
42 * the current task uses
43 */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +000044static void print_string(char *str)
45{
46 struct tty_struct *my_tty;
47
48 /* The tty for the current task */
49 my_tty = current->tty;
50 if (my_tty != NULL) {
51 (*(my_tty->driver).write)(my_tty, 0, str, strlen(str));
52 (*(my_tty->driver).write)(my_tty, 0, "\015\012", 2);
53 }
54}
55
56#define BUGPRINT(args) print_string(args);
57#else
58#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
59 "report to author: "format, ## args)
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +000060/* #define BUGPRINT(format, args...) */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +000061#endif
62#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
63 ": out of memory: "format, ## args)
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +000064/* #define MEMPRINT(format, args...) */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +000065
66
67
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +000068/*
69 * Each cpu has its own set of counters, so there is no need for write_lock in
70 * the softirq
71 * For reading or updating the counters, the user context needs to
72 * get a write_lock
73 */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +000074
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +000075/* The size of each set of counters is altered to get cache alignment */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +000076#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
77#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
78#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
79 COUNTER_OFFSET(n) * cpu))
80
81
82
83static DECLARE_MUTEX(ebt_mutex);
84static LIST_HEAD(ebt_tables);
85static LIST_HEAD(ebt_targets);
86static LIST_HEAD(ebt_matches);
87static LIST_HEAD(ebt_watchers);
88
89static struct ebt_target ebt_standard_target =
90{ {NULL, NULL}, EBT_STANDARD_TARGET, NULL, NULL, NULL, NULL};
91
92static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
93 const struct sk_buff *skb, const struct net_device *in,
94 const struct net_device *out)
95{
96 w->u.watcher->watcher(skb, in, out, w->data,
97 w->watcher_size);
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +000098 /* watchers don't give a verdict */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +000099 return 0;
100}
101
102static inline int ebt_do_match (struct ebt_entry_match *m,
103 const struct sk_buff *skb, const struct net_device *in,
104 const struct net_device *out)
105{
106 return m->u.match->match(skb, in, out, m->data,
107 m->match_size);
108}
109
110static inline int ebt_dev_check(char *entry, const struct net_device *device)
111{
112 if (*entry == '\0')
113 return 0;
114 if (!device)
115 return 1;
116 return !!strcmp(entry, device->name);
117}
118
119#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000120/* process standard matches */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000121static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
122 const struct net_device *in, const struct net_device *out)
123{
124 int verdict, i;
125
126 if (e->bitmask & EBT_802_3) {
127 if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
128 return 1;
129 } else if (!(e->bitmask & EBT_NOPROTO) &&
130 FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
131 return 1;
132
133 if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
134 return 1;
135 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
136 return 1;
137 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
138 e->logical_in, &in->br_port->br->dev), EBT_ILOGICALIN))
139 return 1;
140 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
141 e->logical_out, &out->br_port->br->dev), EBT_ILOGICALOUT))
142 return 1;
143
144 if (e->bitmask & EBT_SOURCEMAC) {
145 verdict = 0;
146 for (i = 0; i < 6; i++)
147 verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
148 e->sourcemsk[i];
149 if (FWINV2(verdict != 0, EBT_ISOURCE) )
150 return 1;
151 }
152 if (e->bitmask & EBT_DESTMAC) {
153 verdict = 0;
154 for (i = 0; i < 6; i++)
155 verdict |= (h->h_dest[i] ^ e->destmac[i]) &
156 e->destmsk[i];
157 if (FWINV2(verdict != 0, EBT_IDEST) )
158 return 1;
159 }
160 return 0;
161}
162
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000163/* Do some firewalling */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000164unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
165 const struct net_device *in, const struct net_device *out,
166 struct ebt_table *table)
167{
168 int i, nentries;
169 struct ebt_entry *point;
170 struct ebt_counter *counter_base, *cb_base;
171 struct ebt_entry_target *t;
172 int verdict, sp = 0;
173 struct ebt_chainstack *cs;
174 struct ebt_entries *chaininfo;
175 char *base;
176 struct ebt_table_info *private = table->private;
177
178 read_lock_bh(&table->lock);
179 cb_base = COUNTER_BASE(private->counters, private->nentries,
180 smp_processor_id());
181 if (private->chainstack)
182 cs = private->chainstack[smp_processor_id()];
183 else
184 cs = NULL;
185 chaininfo = private->hook_entry[hook];
186 nentries = private->hook_entry[hook]->nentries;
187 point = (struct ebt_entry *)(private->hook_entry[hook]->data);
188 counter_base = cb_base + private->hook_entry[hook]->counter_offset;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000189 /* base for chain jumps */
Bart De Schuymerff3ea7b2002-11-22 19:14:57 +0000190 base = private->entries;
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000191 i = 0;
192 while (i < nentries) {
193 if (ebt_basic_match(point, (**pskb).mac.ethernet, in, out))
194 goto letscontinue;
195
196 if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0)
197 goto letscontinue;
198
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000199 /* increase counter */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000200 (*(counter_base + i)).pcnt++;
Bart De Schuymer0e941912002-10-21 17:15:28 +0000201 (*(counter_base + i)).bcnt+=(**pskb).len;
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000202
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000203 /* these should only watch: not modify, nor tell us
204 what to do with the packet */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000205 EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, in,
206 out);
207
208 t = (struct ebt_entry_target *)
209 (((char *)point) + point->target_offset);
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000210 /* standard target */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000211 if (!t->u.target->target)
212 verdict = ((struct ebt_standard_target *)t)->verdict;
213 else
214 verdict = t->u.target->target(pskb, hook,
215 in, out, t->data, t->target_size);
216 if (verdict == EBT_ACCEPT) {
217 read_unlock_bh(&table->lock);
218 return NF_ACCEPT;
219 }
220 if (verdict == EBT_DROP) {
221 read_unlock_bh(&table->lock);
222 return NF_DROP;
223 }
224 if (verdict == EBT_RETURN) {
225letsreturn:
226#ifdef CONFIG_NETFILTER_DEBUG
227 if (sp == 0) {
228 BUGPRINT("RETURN on base chain");
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000229 /* act like this is EBT_CONTINUE */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000230 goto letscontinue;
231 }
232#endif
233 sp--;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000234 /* put all the local variables right */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000235 i = cs[sp].n;
236 chaininfo = cs[sp].chaininfo;
237 nentries = chaininfo->nentries;
238 point = cs[sp].e;
239 counter_base = cb_base +
240 chaininfo->counter_offset;
241 continue;
242 }
243 if (verdict == EBT_CONTINUE)
244 goto letscontinue;
245#ifdef CONFIG_NETFILTER_DEBUG
246 if (verdict < 0) {
247 BUGPRINT("bogus standard verdict\n");
248 read_unlock_bh(&table->lock);
249 return NF_DROP;
250 }
251#endif
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000252 /* jump to a udc */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000253 cs[sp].n = i + 1;
254 cs[sp].chaininfo = chaininfo;
255 cs[sp].e = (struct ebt_entry *)
256 (((char *)point) + point->next_offset);
257 i = 0;
258 chaininfo = (struct ebt_entries *) (base + verdict);
259#ifdef CONFIG_NETFILTER_DEBUG
260 if (chaininfo->distinguisher) {
261 BUGPRINT("jump to non-chain\n");
262 read_unlock_bh(&table->lock);
263 return NF_DROP;
264 }
265#endif
266 nentries = chaininfo->nentries;
267 point = (struct ebt_entry *)chaininfo->data;
268 counter_base = cb_base + chaininfo->counter_offset;
269 sp++;
270 continue;
271letscontinue:
272 point = (struct ebt_entry *)
273 (((char *)point) + point->next_offset);
274 i++;
275 }
276
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000277 /* I actually like this :) */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000278 if (chaininfo->policy == EBT_RETURN)
279 goto letsreturn;
280 if (chaininfo->policy == EBT_ACCEPT) {
281 read_unlock_bh(&table->lock);
282 return NF_ACCEPT;
283 }
284 read_unlock_bh(&table->lock);
285 return NF_DROP;
286}
287
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000288/* If it succeeds, returns element and locks mutex */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000289static inline void *
290find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
291 struct semaphore *mutex)
292{
293 void *ret;
294
295 *error = down_interruptible(mutex);
296 if (*error != 0)
297 return NULL;
298
299 ret = list_named_find(head, name);
300 if (!ret) {
301 *error = -ENOENT;
302 up(mutex);
303 }
304 return ret;
305}
306
307#ifndef CONFIG_KMOD
308#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
309#else
310static void *
311find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
312 int *error, struct semaphore *mutex)
313{
314 void *ret;
315
316 ret = find_inlist_lock_noload(head, name, error, mutex);
317 if (!ret) {
318 char modulename[EBT_FUNCTION_MAXNAMELEN + strlen(prefix) + 1];
319 strcpy(modulename, prefix);
320 strcat(modulename, name);
321 request_module(modulename);
322 ret = find_inlist_lock_noload(head, name, error, mutex);
323 }
324 return ret;
325}
326#endif
327
328static inline struct ebt_table *
329find_table_lock(const char *name, int *error, struct semaphore *mutex)
330{
331 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex);
332}
333
334static inline struct ebt_match *
335find_match_lock(const char *name, int *error, struct semaphore *mutex)
336{
337 return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex);
338}
339
340static inline struct ebt_watcher *
341find_watcher_lock(const char *name, int *error, struct semaphore *mutex)
342{
343 return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex);
344}
345
346static inline struct ebt_target *
347find_target_lock(const char *name, int *error, struct semaphore *mutex)
348{
349 return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex);
350}
351
352static inline int
353ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
354 const char *name, unsigned int hookmask, unsigned int *cnt)
355{
356 struct ebt_match *match;
357 int ret;
358
359 if (((char *)m) + m->match_size + sizeof(struct ebt_entry_match) >
360 ((char *)e) + e->watchers_offset)
361 return -EINVAL;
362 match = find_match_lock(m->u.name, &ret, &ebt_mutex);
363 if (!match)
364 return ret;
365 m->u.match = match;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000366 if (!try_module_get(match->me)) {
367 up(&ebt_mutex);
368 return -EINVAL;
369 }
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000370 up(&ebt_mutex);
371 if (match->check &&
372 match->check(name, hookmask, e, m->data, m->match_size) != 0) {
373 BUGPRINT("match->check failed\n");
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000374 module_put(match->me);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000375 return -EINVAL;
376 }
377 (*cnt)++;
378 return 0;
379}
380
381static inline int
382ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
383 const char *name, unsigned int hookmask, unsigned int *cnt)
384{
385 struct ebt_watcher *watcher;
386 int ret;
387
388 if (((char *)w) + w->watcher_size + sizeof(struct ebt_entry_watcher) >
389 ((char *)e) + e->target_offset)
390 return -EINVAL;
391 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
392 if (!watcher)
393 return ret;
394 w->u.watcher = watcher;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000395 if (!try_module_get(watcher->me)) {
396 up(&ebt_mutex);
397 return -EINVAL;
398 }
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000399 up(&ebt_mutex);
400 if (watcher->check &&
401 watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) {
402 BUGPRINT("watcher->check failed\n");
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000403 module_put(watcher->me);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000404 return -EINVAL;
405 }
406 (*cnt)++;
407 return 0;
408}
409
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000410/*
411 * this one is very careful, as it is the first function
412 * to parse the userspace data
413 */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000414static inline int
415ebt_check_entry_size_and_hooks(struct ebt_entry *e,
416 struct ebt_table_info *newinfo, char *base, char *limit,
417 struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
418 unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
419{
420 int i;
421
422 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
423 if ((valid_hooks & (1 << i)) == 0)
424 continue;
425 if ( (char *)hook_entries[i] - base ==
426 (char *)e - newinfo->entries)
427 break;
428 }
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000429 /* beginning of a new chain
430 if i == NF_BR_NUMHOOKS it must be a user defined chain */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000431 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
432 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) != 0) {
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000433 /* we make userspace set this right,
434 so there is no misunderstanding */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000435 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
436 "in distinguisher\n");
437 return -EINVAL;
438 }
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000439 /* this checks if the previous chain has as many entries
440 as it said it has */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000441 if (*n != *cnt) {
442 BUGPRINT("nentries does not equal the nr of entries "
443 "in the chain\n");
444 return -EINVAL;
445 }
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000446 /* before we look at the struct, be sure it is not too big */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000447 if ((char *)hook_entries[i] + sizeof(struct ebt_entries)
448 > limit) {
449 BUGPRINT("entries_size too small\n");
450 return -EINVAL;
451 }
452 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
453 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000454 /* only RETURN from udc */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000455 if (i != NF_BR_NUMHOOKS ||
456 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
457 BUGPRINT("bad policy\n");
458 return -EINVAL;
459 }
460 }
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000461 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000462 (*udc_cnt)++;
463 else
464 newinfo->hook_entry[i] = (struct ebt_entries *)e;
465 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
466 BUGPRINT("counter_offset != totalcnt");
467 return -EINVAL;
468 }
469 *n = ((struct ebt_entries *)e)->nentries;
470 *cnt = 0;
471 return 0;
472 }
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000473 /* a plain old entry, heh */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000474 if (sizeof(struct ebt_entry) > e->watchers_offset ||
475 e->watchers_offset > e->target_offset ||
476 e->target_offset >= e->next_offset) {
477 BUGPRINT("entry offsets not in right order\n");
478 return -EINVAL;
479 }
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000480 /* this is not checked anywhere else */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000481 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
482 BUGPRINT("target size too small\n");
483 return -EINVAL;
484 }
485
486 (*cnt)++;
487 (*totalcnt)++;
488 return 0;
489}
490
491struct ebt_cl_stack
492{
493 struct ebt_chainstack cs;
494 int from;
495 unsigned int hookmask;
496};
497
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000498/*
499 * we need these positions to check that the jumps to a different part of the
500 * entries is a jump to the beginning of a new chain.
501 */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000502static inline int
503ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
504 struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks,
505 struct ebt_cl_stack *udc)
506{
507 int i;
508
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000509 /* we're only interested in chain starts */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000510 if (e->bitmask & EBT_ENTRY_OR_ENTRIES)
511 return 0;
512 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
513 if ((valid_hooks & (1 << i)) == 0)
514 continue;
515 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
516 break;
517 }
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000518 /* only care about udc */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000519 if (i != NF_BR_NUMHOOKS)
520 return 0;
521
522 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000523 /* these initialisations are depended on later in check_chainloops() */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000524 udc[*n].cs.n = 0;
525 udc[*n].hookmask = 0;
526
527 (*n)++;
528 return 0;
529}
530
531static inline int
532ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
533{
534 if (i && (*i)-- == 0)
535 return 1;
536 if (m->u.match->destroy)
537 m->u.match->destroy(m->data, m->match_size);
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000538 module_put(m->u.match->me);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000539
540 return 0;
541}
542
543static inline int
544ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
545{
546 if (i && (*i)-- == 0)
547 return 1;
548 if (w->u.watcher->destroy)
549 w->u.watcher->destroy(w->data, w->watcher_size);
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000550 module_put(w->u.watcher->me);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000551
552 return 0;
553}
554
555static inline int
556ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
557{
558 struct ebt_entry_target *t;
559
560 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
561 return 0;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000562 /* we're done */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000563 if (cnt && (*cnt)-- == 0)
564 return 1;
565 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
566 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);
567 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
568 if (t->u.target->destroy)
569 t->u.target->destroy(t->data, t->target_size);
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000570 module_put(t->u.target->me);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000571
572 return 0;
573}
574
575static inline int
576ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
577 const char *name, unsigned int *cnt, unsigned int valid_hooks,
578 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
579{
580 struct ebt_entry_target *t;
581 struct ebt_target *target;
582 unsigned int i, j, hook = 0, hookmask = 0;
583 int ret;
584
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000585 /* don't mess with the struct ebt_entries */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000586 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
587 return 0;
588
589 if (e->bitmask & ~EBT_F_MASK) {
590 BUGPRINT("Unknown flag for bitmask\n");
591 return -EINVAL;
592 }
593 if (e->invflags & ~EBT_INV_MASK) {
594 BUGPRINT("Unknown flag for inv bitmask\n");
595 return -EINVAL;
596 }
597 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
598 BUGPRINT("NOPROTO & 802_3 not allowed\n");
599 return -EINVAL;
600 }
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000601 /* what hook do we belong to? */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000602 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
603 if ((valid_hooks & (1 << i)) == 0)
604 continue;
605 if ((char *)newinfo->hook_entry[i] < (char *)e)
606 hook = i;
607 else
608 break;
609 }
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000610 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
611 a base chain */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000612 if (i < NF_BR_NUMHOOKS)
613 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
614 else {
615 for (i = 0; i < udc_cnt; i++)
616 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
617 break;
618 if (i == 0)
619 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
620 else
621 hookmask = cl_s[i - 1].hookmask;
622 }
623 i = 0;
624 ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);
625 if (ret != 0)
626 goto cleanup_matches;
627 j = 0;
628 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
629 if (ret != 0)
630 goto cleanup_watchers;
631 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
632 target = find_target_lock(t->u.name, &ret, &ebt_mutex);
633 if (!target)
634 goto cleanup_watchers;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000635 if (!try_module_get(target->me)) {
636 up(&ebt_mutex);
637 goto cleanup_watchers;
638 }
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000639 up(&ebt_mutex);
640
641 t->u.target = target;
642 if (t->u.target == &ebt_standard_target) {
643 if (e->target_offset + sizeof(struct ebt_standard_target) >
644 e->next_offset) {
645 BUGPRINT("Standard target size too big\n");
646 ret = -EFAULT;
647 goto cleanup_watchers;
648 }
649 if (((struct ebt_standard_target *)t)->verdict <
650 -NUM_STANDARD_TARGETS) {
651 BUGPRINT("Invalid standard target\n");
652 ret = -EFAULT;
653 goto cleanup_watchers;
654 }
655 } else if ((e->target_offset + t->target_size +
656 sizeof(struct ebt_entry_target) > e->next_offset) ||
657 (t->u.target->check &&
658 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000659 module_put(t->u.target->me);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000660 ret = -EFAULT;
661 goto cleanup_watchers;
662 }
663 (*cnt)++;
664 return 0;
665cleanup_watchers:
666 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);
667cleanup_matches:
668 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i);
669 return ret;
670}
671
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000672/*
673 * checks for loops and sets the hook mask for udc
674 * the hook mask for udc tells us from which base chains the udc can be
675 * accessed. This mask is a parameter to the check() functions of the extensions
676 */
677static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
678 unsigned int udc_cnt, unsigned int hooknr, char *base)
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000679{
680 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
681 struct ebt_entry *e = (struct ebt_entry *)chain->data;
682 struct ebt_entry_target *t;
683
684 while (pos < nentries || chain_nr != -1) {
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000685 /* end of udc, go back one 'recursion' step */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000686 if (pos == nentries) {
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000687 /* put back values of the time when this chain was called */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000688 e = cl_s[chain_nr].cs.e;
689 if (cl_s[chain_nr].from != -1)
690 nentries =
691 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
692 else
693 nentries = chain->nentries;
694 pos = cl_s[chain_nr].cs.n;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000695 /* make sure we won't see a loop that isn't one */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000696 cl_s[chain_nr].cs.n = 0;
697 chain_nr = cl_s[chain_nr].from;
698 if (pos == nentries)
699 continue;
700 }
701 t = (struct ebt_entry_target *)
702 (((char *)e) + e->target_offset);
703 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
704 goto letscontinue;
705 if (e->target_offset + sizeof(struct ebt_standard_target) >
706 e->next_offset) {
707 BUGPRINT("Standard target size too big\n");
708 return -1;
709 }
710 verdict = ((struct ebt_standard_target *)t)->verdict;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000711 if (verdict >= 0) { /* jump to another chain */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000712 struct ebt_entries *hlp2 =
713 (struct ebt_entries *)(base + verdict);
714 for (i = 0; i < udc_cnt; i++)
715 if (hlp2 == cl_s[i].cs.chaininfo)
716 break;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000717 /* bad destination or loop */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000718 if (i == udc_cnt) {
719 BUGPRINT("bad destination\n");
720 return -1;
721 }
722 if (cl_s[i].cs.n) {
723 BUGPRINT("loop\n");
724 return -1;
725 }
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000726 /* this can't be 0, so the above test is correct */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000727 cl_s[i].cs.n = pos + 1;
728 pos = 0;
729 cl_s[i].cs.e = ((void *)e + e->next_offset);
730 e = (struct ebt_entry *)(hlp2->data);
731 nentries = hlp2->nentries;
732 cl_s[i].from = chain_nr;
733 chain_nr = i;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000734 /* this udc is accessible from the base chain for hooknr */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000735 cl_s[i].hookmask |= (1 << hooknr);
736 continue;
737 }
738letscontinue:
739 e = (void *)e + e->next_offset;
740 pos++;
741 }
742 return 0;
743}
744
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000745/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000746static int translate_table(struct ebt_replace *repl,
747 struct ebt_table_info *newinfo)
748{
749 unsigned int i, j, k, udc_cnt;
750 int ret;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000751 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000752
753 i = 0;
754 while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i)))
755 i++;
756 if (i == NF_BR_NUMHOOKS) {
757 BUGPRINT("No valid hooks specified\n");
758 return -EINVAL;
759 }
760 if (repl->hook_entry[i] != (struct ebt_entries *)repl->entries) {
761 BUGPRINT("Chains don't start at beginning\n");
762 return -EINVAL;
763 }
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000764 /* make sure chains are ordered after each other in same order
765 as their corresponding hooks */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000766 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
767 if (!(repl->valid_hooks & (1 << j)))
768 continue;
769 if ( repl->hook_entry[j] <= repl->hook_entry[i] ) {
770 BUGPRINT("Hook order must be followed\n");
771 return -EINVAL;
772 }
773 i = j;
774 }
775
776 for (i = 0; i < NF_BR_NUMHOOKS; i++)
777 newinfo->hook_entry[i] = NULL;
778
779 newinfo->entries_size = repl->entries_size;
780 newinfo->nentries = repl->nentries;
781
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000782 /* do some early checkings and initialize some things */
783 i = 0; /* holds the expected nr. of entries for the chain */
784 j = 0; /* holds the up to now counted entries for the chain */
785 k = 0; /* holds the total nr. of entries, should equal
786 newinfo->nentries afterwards */
787 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000788 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
789 ebt_check_entry_size_and_hooks, newinfo, repl->entries,
790 repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k,
791 &udc_cnt, repl->valid_hooks);
792
793 if (ret != 0)
794 return ret;
795
796 if (i != j) {
797 BUGPRINT("nentries does not equal the nr of entries in the "
798 "(last) chain\n");
799 return -EINVAL;
800 }
801 if (k != newinfo->nentries) {
802 BUGPRINT("Total nentries is wrong\n");
803 return -EINVAL;
804 }
805
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000806 /* check if all valid hooks have a chain */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000807 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
808 if (newinfo->hook_entry[i] == NULL &&
809 (repl->valid_hooks & (1 << i))) {
810 BUGPRINT("Valid hook without chain\n");
811 return -EINVAL;
812 }
813 }
814
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000815 /* get the location of the udc, put them in an array
816 while we're at it, allocate the chainstack */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000817 if (udc_cnt) {
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000818 /* this will get free'd in do_replace()/ebt_register_table()
819 if an error occurs */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000820 newinfo->chainstack = (struct ebt_chainstack **)
821 vmalloc(NR_CPUS * sizeof(struct ebt_chainstack));
822 if (!newinfo->chainstack)
823 return -ENOMEM;
824 for (i = 0; i < NR_CPUS; i++) {
825 newinfo->chainstack[i] =
826 vmalloc(udc_cnt * sizeof(struct ebt_chainstack));
827 if (!newinfo->chainstack[i]) {
828 while (i)
829 vfree(newinfo->chainstack[--i]);
830 vfree(newinfo->chainstack);
831 newinfo->chainstack = NULL;
832 return -ENOMEM;
833 }
834 }
835
836 cl_s = (struct ebt_cl_stack *)
837 vmalloc(udc_cnt * sizeof(struct ebt_cl_stack));
838 if (!cl_s)
839 return -ENOMEM;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000840 i = 0; /* the i'th udc */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000841 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
842 ebt_get_udc_positions, newinfo, repl->hook_entry, &i,
843 repl->valid_hooks, cl_s);
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000844 /* sanity check */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000845 if (i != udc_cnt) {
846 BUGPRINT("i != udc_cnt\n");
847 vfree(cl_s);
848 return -EFAULT;
849 }
850 }
851
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000852 /* Check for loops */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000853 for (i = 0; i < NF_BR_NUMHOOKS; i++)
854 if (repl->valid_hooks & (1 << i))
855 if (check_chainloops(newinfo->hook_entry[i],
856 cl_s, udc_cnt, i, newinfo->entries)) {
857 if (cl_s)
858 vfree(cl_s);
859 return -EINVAL;
860 }
861
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000862 /* we now know the following (along with E=mc²):
863 - the nr of entries in each chain is right
864 - the size of the allocated space is right
865 - all valid hooks have a corresponding chain
866 - there are no loops
867 - wrong data can still be on the level of a single entry
868 - could be there are jumps to places that are not the
869 beginning of a chain. This can only occur in chains that
870 are not accessible from any base chains, so we don't care. */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000871
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000872 /* used to know what we need to clean up if something goes wrong */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000873 i = 0;
874 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
875 ebt_check_entry, newinfo, repl->name, &i, repl->valid_hooks,
876 cl_s, udc_cnt);
877 if (ret != 0) {
878 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
879 ebt_cleanup_entry, &i);
880 }
881 if (cl_s)
882 vfree(cl_s);
883 return ret;
884}
885
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000886/* called under write_lock */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000887static void get_counters(struct ebt_counter *oldcounters,
888 struct ebt_counter *counters, unsigned int nentries)
889{
890 int i, cpu;
891 struct ebt_counter *counter_base;
892
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000893 /* counters of cpu 0 */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000894 memcpy(counters, oldcounters,
895 sizeof(struct ebt_counter) * nentries);
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000896 /* add other counters to those of cpu 0 */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000897 for (cpu = 1; cpu < NR_CPUS; cpu++) {
898 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
Bart De Schuymer0e941912002-10-21 17:15:28 +0000899 for (i = 0; i < nentries; i++) {
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000900 counters[i].pcnt += counter_base[i].pcnt;
Bart De Schuymer0e941912002-10-21 17:15:28 +0000901 counters[i].bcnt += counter_base[i].bcnt;
902 }
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000903 }
904}
905
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000906/* replace the table */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000907static int do_replace(void *user, unsigned int len)
908{
909 int ret, i, countersize;
910 struct ebt_table_info *newinfo;
911 struct ebt_replace tmp;
912 struct ebt_table *t;
913 struct ebt_counter *counterstmp = NULL;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000914 /* used to be able to unlock earlier */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000915 struct ebt_table_info *table;
916
917 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
918 return -EFAULT;
919
920 if (len != sizeof(tmp) + tmp.entries_size) {
921 BUGPRINT("Wrong len argument\n");
922 return -EINVAL;
923 }
924
925 if (tmp.entries_size == 0) {
926 BUGPRINT("Entries_size never zero\n");
927 return -EINVAL;
928 }
929 countersize = COUNTER_OFFSET(tmp.nentries) * NR_CPUS;
930 newinfo = (struct ebt_table_info *)
931 vmalloc(sizeof(struct ebt_table_info) + countersize);
932 if (!newinfo)
933 return -ENOMEM;
934
935 if (countersize)
936 memset(newinfo->counters, 0, countersize);
937
938 newinfo->entries = (char *)vmalloc(tmp.entries_size);
939 if (!newinfo->entries) {
940 ret = -ENOMEM;
941 goto free_newinfo;
942 }
943 if (copy_from_user(
944 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
945 BUGPRINT("Couldn't copy entries from userspace\n");
946 ret = -EFAULT;
947 goto free_entries;
948 }
949
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000950 /* the user wants counters back
951 the check on the size is done later, when we have the lock */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000952 if (tmp.num_counters) {
953 counterstmp = (struct ebt_counter *)
954 vmalloc(tmp.num_counters * sizeof(struct ebt_counter));
955 if (!counterstmp) {
956 ret = -ENOMEM;
957 goto free_entries;
958 }
959 }
960 else
961 counterstmp = NULL;
962
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000963 /* this can get initialized by translate_table() */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000964 newinfo->chainstack = NULL;
965 ret = translate_table(&tmp, newinfo);
966
967 if (ret != 0)
968 goto free_counterstmp;
969
970 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
971 if (!t)
972 goto free_iterate;
973
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000974 /* the table doesn't like it */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000975 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
976 goto free_unlock;
977
978 if (tmp.num_counters && tmp.num_counters != t->private->nentries) {
979 BUGPRINT("Wrong nr. of counters requested\n");
980 ret = -EINVAL;
981 goto free_unlock;
982 }
983
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000984 /* we have the mutex lock, so no danger in reading this pointer */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000985 table = t->private;
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000986 /* we need an atomic snapshot of the counters */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000987 write_lock_bh(&t->lock);
988 if (tmp.num_counters)
989 get_counters(t->private->counters, counterstmp,
990 t->private->nentries);
991
992 t->private = newinfo;
993 write_unlock_bh(&t->lock);
994 up(&ebt_mutex);
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +0000995 /* so, a user can change the chains while having messed up her counter
996 allocation. Only reason why this is done is because this way the lock
997 is held only once, while this doesn't bring the kernel into a
998 dangerous state. */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +0000999 if (tmp.num_counters &&
1000 copy_to_user(tmp.counters, counterstmp,
1001 tmp.num_counters * sizeof(struct ebt_counter))) {
1002 BUGPRINT("Couldn't copy counters to userspace\n");
1003 ret = -EFAULT;
1004 }
1005 else
1006 ret = 0;
1007
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +00001008 /* decrease module count and free resources */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001009 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
1010 ebt_cleanup_entry, NULL);
1011
1012 vfree(table->entries);
1013 if (table->chainstack) {
1014 for (i = 0; i < NR_CPUS; i++)
1015 vfree(table->chainstack[i]);
1016 vfree(table->chainstack);
1017 }
1018 vfree(table);
1019
1020 if (counterstmp)
1021 vfree(counterstmp);
1022 return ret;
1023
1024free_unlock:
1025 up(&ebt_mutex);
1026free_iterate:
1027 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1028 ebt_cleanup_entry, NULL);
1029free_counterstmp:
1030 if (counterstmp)
1031 vfree(counterstmp);
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +00001032 /* can be initialized in translate_table() */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001033 if (newinfo->chainstack) {
1034 for (i = 0; i < NR_CPUS; i++)
1035 vfree(newinfo->chainstack[i]);
1036 vfree(newinfo->chainstack);
1037 }
1038free_entries:
1039 if (newinfo->entries)
1040 vfree(newinfo->entries);
1041free_newinfo:
1042 if (newinfo)
1043 vfree(newinfo);
1044 return ret;
1045}
1046
1047int ebt_register_target(struct ebt_target *target)
1048{
1049 int ret;
1050
1051 ret = down_interruptible(&ebt_mutex);
1052 if (ret != 0)
1053 return ret;
1054 if (!list_named_insert(&ebt_targets, target)) {
1055 up(&ebt_mutex);
1056 return -EEXIST;
1057 }
1058 up(&ebt_mutex);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001059
1060 return 0;
1061}
1062
1063void ebt_unregister_target(struct ebt_target *target)
1064{
1065 down(&ebt_mutex);
1066 LIST_DELETE(&ebt_targets, target);
1067 up(&ebt_mutex);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001068}
1069
1070int ebt_register_match(struct ebt_match *match)
1071{
1072 int ret;
1073
1074 ret = down_interruptible(&ebt_mutex);
1075 if (ret != 0)
1076 return ret;
1077 if (!list_named_insert(&ebt_matches, match)) {
1078 up(&ebt_mutex);
1079 return -EEXIST;
1080 }
1081 up(&ebt_mutex);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001082
1083 return 0;
1084}
1085
1086void ebt_unregister_match(struct ebt_match *match)
1087{
1088 down(&ebt_mutex);
1089 LIST_DELETE(&ebt_matches, match);
1090 up(&ebt_mutex);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001091}
1092
1093int ebt_register_watcher(struct ebt_watcher *watcher)
1094{
1095 int ret;
1096
1097 ret = down_interruptible(&ebt_mutex);
1098 if (ret != 0)
1099 return ret;
1100 if (!list_named_insert(&ebt_watchers, watcher)) {
1101 up(&ebt_mutex);
1102 return -EEXIST;
1103 }
1104 up(&ebt_mutex);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001105
1106 return 0;
1107}
1108
1109void ebt_unregister_watcher(struct ebt_watcher *watcher)
1110{
1111 down(&ebt_mutex);
1112 LIST_DELETE(&ebt_watchers, watcher);
1113 up(&ebt_mutex);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001114}
1115
1116int ebt_register_table(struct ebt_table *table)
1117{
1118 struct ebt_table_info *newinfo;
1119 int ret, i, countersize;
1120
1121 if (!table || !table->table ||!table->table->entries ||
1122 table->table->entries_size == 0 ||
1123 table->table->counters || table->private) {
1124 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1125 return -EINVAL;
1126 }
1127
1128 countersize = COUNTER_OFFSET(table->table->nentries) * NR_CPUS;
1129 newinfo = (struct ebt_table_info *)
1130 vmalloc(sizeof(struct ebt_table_info) + countersize);
1131 ret = -ENOMEM;
1132 if (!newinfo)
1133 return -ENOMEM;
1134
1135 newinfo->entries = (char *)vmalloc(table->table->entries_size);
1136 if (!(newinfo->entries))
1137 goto free_newinfo;
1138
1139 memcpy(newinfo->entries, table->table->entries,
1140 table->table->entries_size);
1141
1142 if (countersize)
1143 memset(newinfo->counters, 0, countersize);
1144
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +00001145 /* fill in newinfo and parse the entries */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001146 newinfo->chainstack = NULL;
1147 ret = translate_table(table->table, newinfo);
1148 if (ret != 0) {
1149 BUGPRINT("Translate_table failed\n");
1150 goto free_chainstack;
1151 }
1152
1153 if (table->check && table->check(newinfo, table->valid_hooks)) {
1154 BUGPRINT("The table doesn't like its own initial data, lol\n");
1155 return -EINVAL;
1156 }
1157
1158 table->private = newinfo;
1159 table->lock = RW_LOCK_UNLOCKED;
1160 ret = down_interruptible(&ebt_mutex);
1161 if (ret != 0)
1162 goto free_chainstack;
1163
1164 if (list_named_find(&ebt_tables, table->name)) {
1165 ret = -EEXIST;
1166 BUGPRINT("Table name already exists\n");
1167 goto free_unlock;
1168 }
1169
1170 list_prepend(&ebt_tables, table);
1171 up(&ebt_mutex);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001172 return 0;
1173free_unlock:
1174 up(&ebt_mutex);
1175free_chainstack:
1176 if (newinfo->chainstack) {
1177 for (i = 0; i < NR_CPUS; i++)
1178 vfree(newinfo->chainstack[i]);
1179 vfree(newinfo->chainstack);
1180 }
1181 vfree(newinfo->entries);
1182free_newinfo:
1183 vfree(newinfo);
1184 return ret;
1185}
1186
1187void ebt_unregister_table(struct ebt_table *table)
1188{
1189 int i;
1190
1191 if (!table) {
1192 BUGPRINT("Request to unregister NULL table!!!\n");
1193 return;
1194 }
1195 down(&ebt_mutex);
1196 LIST_DELETE(&ebt_tables, table);
1197 up(&ebt_mutex);
1198 EBT_ENTRY_ITERATE(table->private->entries,
1199 table->private->entries_size, ebt_cleanup_entry, NULL);
1200 if (table->private->entries)
1201 vfree(table->private->entries);
1202 if (table->private->chainstack) {
1203 for (i = 0; i < NR_CPUS; i++)
1204 vfree(table->private->chainstack[i]);
1205 vfree(table->private->chainstack);
1206 }
1207 vfree(table->private);
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001208}
1209
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +00001210/* userspace just supplied us with counters */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001211static int update_counters(void *user, unsigned int len)
1212{
1213 int i, ret;
1214 struct ebt_counter *tmp;
1215 struct ebt_replace hlp;
1216 struct ebt_table *t;
1217
1218 if (copy_from_user(&hlp, user, sizeof(hlp)))
1219 return -EFAULT;
1220
1221 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1222 return -EINVAL;
1223 if (hlp.num_counters == 0)
1224 return -EINVAL;
1225
1226 if ( !(tmp = (struct ebt_counter *)
1227 vmalloc(hlp.num_counters * sizeof(struct ebt_counter))) ){
1228 MEMPRINT("Update_counters && nomemory\n");
1229 return -ENOMEM;
1230 }
1231
1232 t = find_table_lock(hlp.name, &ret, &ebt_mutex);
1233 if (!t)
1234 goto free_tmp;
1235
1236 if (hlp.num_counters != t->private->nentries) {
1237 BUGPRINT("Wrong nr of counters\n");
1238 ret = -EINVAL;
1239 goto unlock_mutex;
1240 }
1241
1242 if ( copy_from_user(tmp, hlp.counters,
1243 hlp.num_counters * sizeof(struct ebt_counter)) ) {
1244 BUGPRINT("Updata_counters && !cfu\n");
1245 ret = -EFAULT;
1246 goto unlock_mutex;
1247 }
1248
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +00001249 /* we want an atomic add of the counters */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001250 write_lock_bh(&t->lock);
1251
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +00001252 /* we add to the counters of the first cpu */
Bart De Schuymer0e941912002-10-21 17:15:28 +00001253 for (i = 0; i < hlp.num_counters; i++) {
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001254 t->private->counters[i].pcnt += tmp[i].pcnt;
Bart De Schuymer0e941912002-10-21 17:15:28 +00001255 t->private->counters[i].bcnt += tmp[i].bcnt;
1256 }
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001257
1258 write_unlock_bh(&t->lock);
1259 ret = 0;
1260unlock_mutex:
1261 up(&ebt_mutex);
1262free_tmp:
1263 vfree(tmp);
1264 return ret;
1265}
1266
1267static inline int ebt_make_matchname(struct ebt_entry_match *m,
1268 char *base, char *ubase)
1269{
1270 char *hlp = ubase - base + (char *)m;
1271 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1272 return -EFAULT;
1273 return 0;
1274}
1275
1276static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
1277 char *base, char *ubase)
1278{
1279 char *hlp = ubase - base + (char *)w;
1280 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1281 return -EFAULT;
1282 return 0;
1283}
1284
1285static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
1286{
1287 int ret;
1288 char *hlp;
1289 struct ebt_entry_target *t;
1290
1291 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
1292 return 0;
1293
1294 hlp = ubase - base + (char *)e + e->target_offset;
1295 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
1296
1297 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1298 if (ret != 0)
1299 return ret;
1300 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1301 if (ret != 0)
1302 return ret;
1303 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1304 return -EFAULT;
1305 return 0;
1306}
1307
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +00001308/* called with ebt_mutex down */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001309static int copy_everything_to_user(struct ebt_table *t, void *user,
1310 int *len, int cmd)
1311{
1312 struct ebt_replace tmp;
1313 struct ebt_counter *counterstmp, *oldcounters;
1314 unsigned int entries_size, nentries;
1315 char *entries;
1316
1317 if (cmd == EBT_SO_GET_ENTRIES) {
1318 entries_size = t->private->entries_size;
1319 nentries = t->private->nentries;
1320 entries = t->private->entries;
1321 oldcounters = t->private->counters;
1322 } else {
1323 entries_size = t->table->entries_size;
1324 nentries = t->table->nentries;
1325 entries = t->table->entries;
1326 oldcounters = t->table->counters;
1327 }
1328
1329 if (copy_from_user(&tmp, user, sizeof(tmp))) {
1330 BUGPRINT("Cfu didn't work\n");
1331 return -EFAULT;
1332 }
1333
1334 if (*len != sizeof(struct ebt_replace) + entries_size +
1335 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
1336 BUGPRINT("Wrong size\n");
1337 return -EINVAL;
1338 }
1339
1340 if (tmp.nentries != nentries) {
1341 BUGPRINT("Nentries wrong\n");
1342 return -EINVAL;
1343 }
1344
1345 if (tmp.entries_size != entries_size) {
1346 BUGPRINT("Wrong size\n");
1347 return -EINVAL;
1348 }
1349
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +00001350 /* userspace might not need the counters */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001351 if (tmp.num_counters) {
1352 if (tmp.num_counters != nentries) {
1353 BUGPRINT("Num_counters wrong\n");
1354 return -EINVAL;
1355 }
1356 counterstmp = (struct ebt_counter *)
1357 vmalloc(nentries * sizeof(struct ebt_counter));
1358 if (!counterstmp) {
1359 MEMPRINT("Couldn't copy counters, out of memory\n");
1360 return -ENOMEM;
1361 }
1362 write_lock_bh(&t->lock);
1363 get_counters(oldcounters, counterstmp, nentries);
1364 write_unlock_bh(&t->lock);
1365
1366 if (copy_to_user(tmp.counters, counterstmp,
1367 nentries * sizeof(struct ebt_counter))) {
1368 BUGPRINT("Couldn't copy counters to userspace\n");
1369 vfree(counterstmp);
1370 return -EFAULT;
1371 }
1372 vfree(counterstmp);
1373 }
1374
1375 if (copy_to_user(tmp.entries, entries, entries_size)) {
1376 BUGPRINT("Couldn't copy entries to userspace\n");
1377 return -EFAULT;
1378 }
Bart De Schuymerc5f4ccd2003-01-11 15:27:05 +00001379 /* set the match/watcher/target names right */
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001380 return EBT_ENTRY_ITERATE(entries, entries_size,
1381 ebt_make_names, entries, tmp.entries);
1382}
1383
1384static int do_ebt_set_ctl(struct sock *sk,
1385 int cmd, void *user, unsigned int len)
1386{
1387 int ret;
1388
1389 switch(cmd) {
1390 case EBT_SO_SET_ENTRIES:
1391 ret = do_replace(user, len);
1392 break;
1393 case EBT_SO_SET_COUNTERS:
1394 ret = update_counters(user, len);
1395 break;
1396 default:
1397 ret = -EINVAL;
1398 }
1399 return ret;
1400}
1401
1402static int do_ebt_get_ctl(struct sock *sk, int cmd, void *user, int *len)
1403{
1404 int ret;
1405 struct ebt_replace tmp;
1406 struct ebt_table *t;
1407
1408 if (copy_from_user(&tmp, user, sizeof(tmp)))
1409 return -EFAULT;
1410
1411 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1412 if (!t)
1413 return ret;
1414
1415 switch(cmd) {
1416 case EBT_SO_GET_INFO:
1417 case EBT_SO_GET_INIT_INFO:
1418 if (*len != sizeof(struct ebt_replace)){
1419 ret = -EINVAL;
1420 up(&ebt_mutex);
1421 break;
1422 }
1423 if (cmd == EBT_SO_GET_INFO) {
1424 tmp.nentries = t->private->nentries;
1425 tmp.entries_size = t->private->entries_size;
1426 tmp.valid_hooks = t->valid_hooks;
1427 } else {
1428 tmp.nentries = t->table->nentries;
1429 tmp.entries_size = t->table->entries_size;
1430 tmp.valid_hooks = t->table->valid_hooks;
1431 }
1432 up(&ebt_mutex);
1433 if (copy_to_user(user, &tmp, *len) != 0){
1434 BUGPRINT("c2u Didn't work\n");
1435 ret = -EFAULT;
1436 break;
1437 }
1438 ret = 0;
1439 break;
1440
1441 case EBT_SO_GET_ENTRIES:
1442 case EBT_SO_GET_INIT_ENTRIES:
1443 ret = copy_everything_to_user(t, user, len, cmd);
1444 up(&ebt_mutex);
1445 break;
1446
1447 default:
1448 up(&ebt_mutex);
1449 ret = -EINVAL;
1450 }
1451
1452 return ret;
1453}
1454
1455static struct nf_sockopt_ops ebt_sockopts =
1456{ { NULL, NULL }, PF_INET, EBT_BASE_CTL, EBT_SO_SET_MAX + 1, do_ebt_set_ctl,
1457 EBT_BASE_CTL, EBT_SO_GET_MAX + 1, do_ebt_get_ctl, 0, NULL
1458};
1459
1460static int __init init(void)
1461{
1462 int ret;
1463
1464 down(&ebt_mutex);
1465 list_named_insert(&ebt_targets, &ebt_standard_target);
1466 up(&ebt_mutex);
1467 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
1468 return ret;
1469
Bart De Schuymeree10dc52002-12-15 21:44:25 +00001470 printk(KERN_NOTICE "Ebtables v2.0 registered\n");
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001471 return 0;
1472}
1473
1474static void __exit fini(void)
1475{
1476 nf_unregister_sockopt(&ebt_sockopts);
Bart De Schuymeree10dc52002-12-15 21:44:25 +00001477 printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
Bart De Schuymerbfa68d62002-08-23 19:57:34 +00001478}
1479
1480EXPORT_SYMBOL(ebt_register_table);
1481EXPORT_SYMBOL(ebt_unregister_table);
1482EXPORT_SYMBOL(ebt_register_match);
1483EXPORT_SYMBOL(ebt_unregister_match);
1484EXPORT_SYMBOL(ebt_register_watcher);
1485EXPORT_SYMBOL(ebt_unregister_watcher);
1486EXPORT_SYMBOL(ebt_register_target);
1487EXPORT_SYMBOL(ebt_unregister_target);
1488EXPORT_SYMBOL(ebt_do_table);
1489module_init(init);
1490module_exit(fini);
1491MODULE_LICENSE("GPL");