blob: 3df55b2bd91d7a8357254c5ab05a4d740f06fbb4 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ebtables
3 *
4 * Author:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
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
18/* used for print_string */
19#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>
Patrick McHardydf0933d2006-09-20 11:57:53 -070027#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <asm/uaccess.h>
29#include <linux/smp.h>
David S. Millerc8923c62005-10-13 14:41:23 -070030#include <linux/cpumask.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <net/sock.h>
32/* needed for logical [in,out]-dev filtering */
33#include "../br_private.h"
34
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
36 "report to author: "format, ## args)
37/* #define BUGPRINT(format, args...) */
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
39 ": out of memory: "format, ## args)
40/* #define MEMPRINT(format, args...) */
41
42
43
44/*
45 * Each cpu has its own set of counters, so there is no need for write_lock in
46 * the softirq
47 * For reading or updating the counters, the user context needs to
48 * get a write_lock
49 */
50
51/* The size of each set of counters is altered to get cache alignment */
52#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
53#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
54#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
55 COUNTER_OFFSET(n) * cpu))
56
57
58
Ingo Molnar57b47a52006-03-20 22:35:41 -080059static DEFINE_MUTEX(ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060static LIST_HEAD(ebt_tables);
61static LIST_HEAD(ebt_targets);
62static LIST_HEAD(ebt_matches);
63static LIST_HEAD(ebt_watchers);
64
65static struct ebt_target ebt_standard_target =
66{ {NULL, NULL}, EBT_STANDARD_TARGET, NULL, NULL, NULL, NULL};
67
68static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
69 const struct sk_buff *skb, unsigned int hooknr, const struct net_device *in,
70 const struct net_device *out)
71{
72 w->u.watcher->watcher(skb, hooknr, in, out, w->data,
73 w->watcher_size);
74 /* watchers don't give a verdict */
75 return 0;
76}
77
78static inline int ebt_do_match (struct ebt_entry_match *m,
79 const struct sk_buff *skb, const struct net_device *in,
80 const struct net_device *out)
81{
82 return m->u.match->match(skb, in, out, m->data,
83 m->match_size);
84}
85
86static inline int ebt_dev_check(char *entry, const struct net_device *device)
87{
88 int i = 0;
89 char *devname = device->name;
90
91 if (*entry == '\0')
92 return 0;
93 if (!device)
94 return 1;
95 /* 1 is the wildcard token */
96 while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i])
97 i++;
98 return (devname[i] != entry[i] && entry[i] != 1);
99}
100
101#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
102/* process standard matches */
103static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
104 const struct net_device *in, const struct net_device *out)
105{
106 int verdict, i;
107
108 if (e->bitmask & EBT_802_3) {
109 if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
110 return 1;
111 } else if (!(e->bitmask & EBT_NOPROTO) &&
112 FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
113 return 1;
114
115 if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
116 return 1;
117 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
118 return 1;
119 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
120 e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN))
121 return 1;
122 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
123 e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT))
124 return 1;
125
126 if (e->bitmask & EBT_SOURCEMAC) {
127 verdict = 0;
128 for (i = 0; i < 6; i++)
129 verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
130 e->sourcemsk[i];
131 if (FWINV2(verdict != 0, EBT_ISOURCE) )
132 return 1;
133 }
134 if (e->bitmask & EBT_DESTMAC) {
135 verdict = 0;
136 for (i = 0; i < 6; i++)
137 verdict |= (h->h_dest[i] ^ e->destmac[i]) &
138 e->destmsk[i];
139 if (FWINV2(verdict != 0, EBT_IDEST) )
140 return 1;
141 }
142 return 0;
143}
144
145/* Do some firewalling */
146unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
147 const struct net_device *in, const struct net_device *out,
148 struct ebt_table *table)
149{
150 int i, nentries;
151 struct ebt_entry *point;
152 struct ebt_counter *counter_base, *cb_base;
153 struct ebt_entry_target *t;
154 int verdict, sp = 0;
155 struct ebt_chainstack *cs;
156 struct ebt_entries *chaininfo;
157 char *base;
158 struct ebt_table_info *private;
159
160 read_lock_bh(&table->lock);
161 private = table->private;
162 cb_base = COUNTER_BASE(private->counters, private->nentries,
163 smp_processor_id());
164 if (private->chainstack)
165 cs = private->chainstack[smp_processor_id()];
166 else
167 cs = NULL;
168 chaininfo = private->hook_entry[hook];
169 nentries = private->hook_entry[hook]->nentries;
170 point = (struct ebt_entry *)(private->hook_entry[hook]->data);
171 counter_base = cb_base + private->hook_entry[hook]->counter_offset;
172 /* base for chain jumps */
173 base = private->entries;
174 i = 0;
175 while (i < nentries) {
176 if (ebt_basic_match(point, eth_hdr(*pskb), in, out))
177 goto letscontinue;
178
179 if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0)
180 goto letscontinue;
181
182 /* increase counter */
183 (*(counter_base + i)).pcnt++;
184 (*(counter_base + i)).bcnt+=(**pskb).len;
185
186 /* these should only watch: not modify, nor tell us
187 what to do with the packet */
188 EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, hook, in,
189 out);
190
191 t = (struct ebt_entry_target *)
192 (((char *)point) + point->target_offset);
193 /* standard target */
194 if (!t->u.target->target)
195 verdict = ((struct ebt_standard_target *)t)->verdict;
196 else
197 verdict = t->u.target->target(pskb, hook,
198 in, out, t->data, t->target_size);
199 if (verdict == EBT_ACCEPT) {
200 read_unlock_bh(&table->lock);
201 return NF_ACCEPT;
202 }
203 if (verdict == EBT_DROP) {
204 read_unlock_bh(&table->lock);
205 return NF_DROP;
206 }
207 if (verdict == EBT_RETURN) {
208letsreturn:
209#ifdef CONFIG_NETFILTER_DEBUG
210 if (sp == 0) {
211 BUGPRINT("RETURN on base chain");
212 /* act like this is EBT_CONTINUE */
213 goto letscontinue;
214 }
215#endif
216 sp--;
217 /* put all the local variables right */
218 i = cs[sp].n;
219 chaininfo = cs[sp].chaininfo;
220 nentries = chaininfo->nentries;
221 point = cs[sp].e;
222 counter_base = cb_base +
223 chaininfo->counter_offset;
224 continue;
225 }
226 if (verdict == EBT_CONTINUE)
227 goto letscontinue;
228#ifdef CONFIG_NETFILTER_DEBUG
229 if (verdict < 0) {
230 BUGPRINT("bogus standard verdict\n");
231 read_unlock_bh(&table->lock);
232 return NF_DROP;
233 }
234#endif
235 /* jump to a udc */
236 cs[sp].n = i + 1;
237 cs[sp].chaininfo = chaininfo;
238 cs[sp].e = (struct ebt_entry *)
239 (((char *)point) + point->next_offset);
240 i = 0;
241 chaininfo = (struct ebt_entries *) (base + verdict);
242#ifdef CONFIG_NETFILTER_DEBUG
243 if (chaininfo->distinguisher) {
244 BUGPRINT("jump to non-chain\n");
245 read_unlock_bh(&table->lock);
246 return NF_DROP;
247 }
248#endif
249 nentries = chaininfo->nentries;
250 point = (struct ebt_entry *)chaininfo->data;
251 counter_base = cb_base + chaininfo->counter_offset;
252 sp++;
253 continue;
254letscontinue:
255 point = (struct ebt_entry *)
256 (((char *)point) + point->next_offset);
257 i++;
258 }
259
260 /* I actually like this :) */
261 if (chaininfo->policy == EBT_RETURN)
262 goto letsreturn;
263 if (chaininfo->policy == EBT_ACCEPT) {
264 read_unlock_bh(&table->lock);
265 return NF_ACCEPT;
266 }
267 read_unlock_bh(&table->lock);
268 return NF_DROP;
269}
270
271/* If it succeeds, returns element and locks mutex */
272static inline void *
273find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
Ingo Molnar57b47a52006-03-20 22:35:41 -0800274 struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275{
Patrick McHardydf0933d2006-09-20 11:57:53 -0700276 struct {
277 struct list_head list;
278 char name[EBT_FUNCTION_MAXNAMELEN];
279 } *e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
Ingo Molnar57b47a52006-03-20 22:35:41 -0800281 *error = mutex_lock_interruptible(mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 if (*error != 0)
283 return NULL;
284
Patrick McHardydf0933d2006-09-20 11:57:53 -0700285 list_for_each_entry(e, head, list) {
286 if (strcmp(e->name, name) == 0)
287 return e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 }
Patrick McHardydf0933d2006-09-20 11:57:53 -0700289 *error = -ENOENT;
290 mutex_unlock(mutex);
291 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292}
293
294#ifndef CONFIG_KMOD
295#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
296#else
297static void *
298find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
Ingo Molnar57b47a52006-03-20 22:35:41 -0800299 int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300{
301 void *ret;
302
303 ret = find_inlist_lock_noload(head, name, error, mutex);
304 if (!ret) {
305 request_module("%s%s", prefix, name);
306 ret = find_inlist_lock_noload(head, name, error, mutex);
307 }
308 return ret;
309}
310#endif
311
312static inline struct ebt_table *
Ingo Molnar57b47a52006-03-20 22:35:41 -0800313find_table_lock(const char *name, int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314{
315 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex);
316}
317
318static inline struct ebt_match *
Ingo Molnar57b47a52006-03-20 22:35:41 -0800319find_match_lock(const char *name, int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320{
321 return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex);
322}
323
324static inline struct ebt_watcher *
Ingo Molnar57b47a52006-03-20 22:35:41 -0800325find_watcher_lock(const char *name, int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326{
327 return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex);
328}
329
330static inline struct ebt_target *
Ingo Molnar57b47a52006-03-20 22:35:41 -0800331find_target_lock(const char *name, int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332{
333 return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex);
334}
335
336static inline int
337ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
338 const char *name, unsigned int hookmask, unsigned int *cnt)
339{
340 struct ebt_match *match;
341 int ret;
342
343 if (((char *)m) + m->match_size + sizeof(struct ebt_entry_match) >
344 ((char *)e) + e->watchers_offset)
345 return -EINVAL;
346 match = find_match_lock(m->u.name, &ret, &ebt_mutex);
347 if (!match)
348 return ret;
349 m->u.match = match;
350 if (!try_module_get(match->me)) {
Ingo Molnar57b47a52006-03-20 22:35:41 -0800351 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 return -ENOENT;
353 }
Ingo Molnar57b47a52006-03-20 22:35:41 -0800354 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 if (match->check &&
356 match->check(name, hookmask, e, m->data, m->match_size) != 0) {
357 BUGPRINT("match->check failed\n");
358 module_put(match->me);
359 return -EINVAL;
360 }
361 (*cnt)++;
362 return 0;
363}
364
365static inline int
366ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
367 const char *name, unsigned int hookmask, unsigned int *cnt)
368{
369 struct ebt_watcher *watcher;
370 int ret;
371
372 if (((char *)w) + w->watcher_size + sizeof(struct ebt_entry_watcher) >
373 ((char *)e) + e->target_offset)
374 return -EINVAL;
375 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
376 if (!watcher)
377 return ret;
378 w->u.watcher = watcher;
379 if (!try_module_get(watcher->me)) {
Ingo Molnar57b47a52006-03-20 22:35:41 -0800380 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 return -ENOENT;
382 }
Ingo Molnar57b47a52006-03-20 22:35:41 -0800383 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 if (watcher->check &&
385 watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) {
386 BUGPRINT("watcher->check failed\n");
387 module_put(watcher->me);
388 return -EINVAL;
389 }
390 (*cnt)++;
391 return 0;
392}
393
394/*
395 * this one is very careful, as it is the first function
396 * to parse the userspace data
397 */
398static inline int
399ebt_check_entry_size_and_hooks(struct ebt_entry *e,
400 struct ebt_table_info *newinfo, char *base, char *limit,
401 struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
402 unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
403{
404 int i;
405
406 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
407 if ((valid_hooks & (1 << i)) == 0)
408 continue;
409 if ( (char *)hook_entries[i] - base ==
410 (char *)e - newinfo->entries)
411 break;
412 }
413 /* beginning of a new chain
414 if i == NF_BR_NUMHOOKS it must be a user defined chain */
415 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
416 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) != 0) {
417 /* we make userspace set this right,
418 so there is no misunderstanding */
419 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
420 "in distinguisher\n");
421 return -EINVAL;
422 }
423 /* this checks if the previous chain has as many entries
424 as it said it has */
425 if (*n != *cnt) {
426 BUGPRINT("nentries does not equal the nr of entries "
427 "in the chain\n");
428 return -EINVAL;
429 }
430 /* before we look at the struct, be sure it is not too big */
431 if ((char *)hook_entries[i] + sizeof(struct ebt_entries)
432 > limit) {
433 BUGPRINT("entries_size too small\n");
434 return -EINVAL;
435 }
436 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
437 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
438 /* only RETURN from udc */
439 if (i != NF_BR_NUMHOOKS ||
440 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
441 BUGPRINT("bad policy\n");
442 return -EINVAL;
443 }
444 }
445 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
446 (*udc_cnt)++;
447 else
448 newinfo->hook_entry[i] = (struct ebt_entries *)e;
449 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
450 BUGPRINT("counter_offset != totalcnt");
451 return -EINVAL;
452 }
453 *n = ((struct ebt_entries *)e)->nentries;
454 *cnt = 0;
455 return 0;
456 }
457 /* a plain old entry, heh */
458 if (sizeof(struct ebt_entry) > e->watchers_offset ||
459 e->watchers_offset > e->target_offset ||
460 e->target_offset >= e->next_offset) {
461 BUGPRINT("entry offsets not in right order\n");
462 return -EINVAL;
463 }
464 /* this is not checked anywhere else */
465 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
466 BUGPRINT("target size too small\n");
467 return -EINVAL;
468 }
469
470 (*cnt)++;
471 (*totalcnt)++;
472 return 0;
473}
474
475struct ebt_cl_stack
476{
477 struct ebt_chainstack cs;
478 int from;
479 unsigned int hookmask;
480};
481
482/*
483 * we need these positions to check that the jumps to a different part of the
484 * entries is a jump to the beginning of a new chain.
485 */
486static inline int
487ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
488 struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks,
489 struct ebt_cl_stack *udc)
490{
491 int i;
492
493 /* we're only interested in chain starts */
494 if (e->bitmask & EBT_ENTRY_OR_ENTRIES)
495 return 0;
496 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
497 if ((valid_hooks & (1 << i)) == 0)
498 continue;
499 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
500 break;
501 }
502 /* only care about udc */
503 if (i != NF_BR_NUMHOOKS)
504 return 0;
505
506 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
507 /* these initialisations are depended on later in check_chainloops() */
508 udc[*n].cs.n = 0;
509 udc[*n].hookmask = 0;
510
511 (*n)++;
512 return 0;
513}
514
515static inline int
516ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
517{
518 if (i && (*i)-- == 0)
519 return 1;
520 if (m->u.match->destroy)
521 m->u.match->destroy(m->data, m->match_size);
522 module_put(m->u.match->me);
523
524 return 0;
525}
526
527static inline int
528ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
529{
530 if (i && (*i)-- == 0)
531 return 1;
532 if (w->u.watcher->destroy)
533 w->u.watcher->destroy(w->data, w->watcher_size);
534 module_put(w->u.watcher->me);
535
536 return 0;
537}
538
539static inline int
540ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
541{
542 struct ebt_entry_target *t;
543
544 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
545 return 0;
546 /* we're done */
547 if (cnt && (*cnt)-- == 0)
548 return 1;
549 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
550 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);
551 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
552 if (t->u.target->destroy)
553 t->u.target->destroy(t->data, t->target_size);
554 module_put(t->u.target->me);
555
556 return 0;
557}
558
559static inline int
560ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
561 const char *name, unsigned int *cnt, unsigned int valid_hooks,
562 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
563{
564 struct ebt_entry_target *t;
565 struct ebt_target *target;
566 unsigned int i, j, hook = 0, hookmask = 0;
567 int ret;
568
569 /* don't mess with the struct ebt_entries */
570 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
571 return 0;
572
573 if (e->bitmask & ~EBT_F_MASK) {
574 BUGPRINT("Unknown flag for bitmask\n");
575 return -EINVAL;
576 }
577 if (e->invflags & ~EBT_INV_MASK) {
578 BUGPRINT("Unknown flag for inv bitmask\n");
579 return -EINVAL;
580 }
581 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
582 BUGPRINT("NOPROTO & 802_3 not allowed\n");
583 return -EINVAL;
584 }
585 /* what hook do we belong to? */
586 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
587 if ((valid_hooks & (1 << i)) == 0)
588 continue;
589 if ((char *)newinfo->hook_entry[i] < (char *)e)
590 hook = i;
591 else
592 break;
593 }
594 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
595 a base chain */
596 if (i < NF_BR_NUMHOOKS)
597 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
598 else {
599 for (i = 0; i < udc_cnt; i++)
600 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
601 break;
602 if (i == 0)
603 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
604 else
605 hookmask = cl_s[i - 1].hookmask;
606 }
607 i = 0;
608 ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);
609 if (ret != 0)
610 goto cleanup_matches;
611 j = 0;
612 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
613 if (ret != 0)
614 goto cleanup_watchers;
615 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
616 target = find_target_lock(t->u.name, &ret, &ebt_mutex);
617 if (!target)
618 goto cleanup_watchers;
619 if (!try_module_get(target->me)) {
Ingo Molnar57b47a52006-03-20 22:35:41 -0800620 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 ret = -ENOENT;
622 goto cleanup_watchers;
623 }
Ingo Molnar57b47a52006-03-20 22:35:41 -0800624 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625
626 t->u.target = target;
627 if (t->u.target == &ebt_standard_target) {
628 if (e->target_offset + sizeof(struct ebt_standard_target) >
629 e->next_offset) {
630 BUGPRINT("Standard target size too big\n");
631 ret = -EFAULT;
632 goto cleanup_watchers;
633 }
634 if (((struct ebt_standard_target *)t)->verdict <
635 -NUM_STANDARD_TARGETS) {
636 BUGPRINT("Invalid standard target\n");
637 ret = -EFAULT;
638 goto cleanup_watchers;
639 }
640 } else if ((e->target_offset + t->target_size +
641 sizeof(struct ebt_entry_target) > e->next_offset) ||
642 (t->u.target->check &&
643 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
644 module_put(t->u.target->me);
645 ret = -EFAULT;
646 goto cleanup_watchers;
647 }
648 (*cnt)++;
649 return 0;
650cleanup_watchers:
651 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);
652cleanup_matches:
653 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i);
654 return ret;
655}
656
657/*
658 * checks for loops and sets the hook mask for udc
659 * the hook mask for udc tells us from which base chains the udc can be
660 * accessed. This mask is a parameter to the check() functions of the extensions
661 */
662static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
663 unsigned int udc_cnt, unsigned int hooknr, char *base)
664{
665 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
666 struct ebt_entry *e = (struct ebt_entry *)chain->data;
667 struct ebt_entry_target *t;
668
669 while (pos < nentries || chain_nr != -1) {
670 /* end of udc, go back one 'recursion' step */
671 if (pos == nentries) {
672 /* put back values of the time when this chain was called */
673 e = cl_s[chain_nr].cs.e;
674 if (cl_s[chain_nr].from != -1)
675 nentries =
676 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
677 else
678 nentries = chain->nentries;
679 pos = cl_s[chain_nr].cs.n;
680 /* make sure we won't see a loop that isn't one */
681 cl_s[chain_nr].cs.n = 0;
682 chain_nr = cl_s[chain_nr].from;
683 if (pos == nentries)
684 continue;
685 }
686 t = (struct ebt_entry_target *)
687 (((char *)e) + e->target_offset);
688 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
689 goto letscontinue;
690 if (e->target_offset + sizeof(struct ebt_standard_target) >
691 e->next_offset) {
692 BUGPRINT("Standard target size too big\n");
693 return -1;
694 }
695 verdict = ((struct ebt_standard_target *)t)->verdict;
696 if (verdict >= 0) { /* jump to another chain */
697 struct ebt_entries *hlp2 =
698 (struct ebt_entries *)(base + verdict);
699 for (i = 0; i < udc_cnt; i++)
700 if (hlp2 == cl_s[i].cs.chaininfo)
701 break;
702 /* bad destination or loop */
703 if (i == udc_cnt) {
704 BUGPRINT("bad destination\n");
705 return -1;
706 }
707 if (cl_s[i].cs.n) {
708 BUGPRINT("loop\n");
709 return -1;
710 }
711 /* this can't be 0, so the above test is correct */
712 cl_s[i].cs.n = pos + 1;
713 pos = 0;
714 cl_s[i].cs.e = ((void *)e + e->next_offset);
715 e = (struct ebt_entry *)(hlp2->data);
716 nentries = hlp2->nentries;
717 cl_s[i].from = chain_nr;
718 chain_nr = i;
719 /* this udc is accessible from the base chain for hooknr */
720 cl_s[i].hookmask |= (1 << hooknr);
721 continue;
722 }
723letscontinue:
724 e = (void *)e + e->next_offset;
725 pos++;
726 }
727 return 0;
728}
729
730/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
731static int translate_table(struct ebt_replace *repl,
732 struct ebt_table_info *newinfo)
733{
734 unsigned int i, j, k, udc_cnt;
735 int ret;
736 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
737
738 i = 0;
739 while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i)))
740 i++;
741 if (i == NF_BR_NUMHOOKS) {
742 BUGPRINT("No valid hooks specified\n");
743 return -EINVAL;
744 }
745 if (repl->hook_entry[i] != (struct ebt_entries *)repl->entries) {
746 BUGPRINT("Chains don't start at beginning\n");
747 return -EINVAL;
748 }
749 /* make sure chains are ordered after each other in same order
750 as their corresponding hooks */
751 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
752 if (!(repl->valid_hooks & (1 << j)))
753 continue;
754 if ( repl->hook_entry[j] <= repl->hook_entry[i] ) {
755 BUGPRINT("Hook order must be followed\n");
756 return -EINVAL;
757 }
758 i = j;
759 }
760
761 for (i = 0; i < NF_BR_NUMHOOKS; i++)
762 newinfo->hook_entry[i] = NULL;
763
764 newinfo->entries_size = repl->entries_size;
765 newinfo->nentries = repl->nentries;
766
767 /* do some early checkings and initialize some things */
768 i = 0; /* holds the expected nr. of entries for the chain */
769 j = 0; /* holds the up to now counted entries for the chain */
770 k = 0; /* holds the total nr. of entries, should equal
771 newinfo->nentries afterwards */
772 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
773 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
774 ebt_check_entry_size_and_hooks, newinfo, repl->entries,
775 repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k,
776 &udc_cnt, repl->valid_hooks);
777
778 if (ret != 0)
779 return ret;
780
781 if (i != j) {
782 BUGPRINT("nentries does not equal the nr of entries in the "
783 "(last) chain\n");
784 return -EINVAL;
785 }
786 if (k != newinfo->nentries) {
787 BUGPRINT("Total nentries is wrong\n");
788 return -EINVAL;
789 }
790
791 /* check if all valid hooks have a chain */
792 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
793 if (newinfo->hook_entry[i] == NULL &&
794 (repl->valid_hooks & (1 << i))) {
795 BUGPRINT("Valid hook without chain\n");
796 return -EINVAL;
797 }
798 }
799
800 /* get the location of the udc, put them in an array
801 while we're at it, allocate the chainstack */
802 if (udc_cnt) {
803 /* this will get free'd in do_replace()/ebt_register_table()
804 if an error occurs */
Jayachandran C7ad4d2f2006-04-11 17:25:38 -0700805 newinfo->chainstack =
806 vmalloc((highest_possible_processor_id()+1)
807 * sizeof(*(newinfo->chainstack)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 if (!newinfo->chainstack)
809 return -ENOMEM;
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700810 for_each_possible_cpu(i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 newinfo->chainstack[i] =
Jayachandran C18bc89a2006-04-20 00:14:49 -0700812 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 if (!newinfo->chainstack[i]) {
814 while (i)
815 vfree(newinfo->chainstack[--i]);
816 vfree(newinfo->chainstack);
817 newinfo->chainstack = NULL;
818 return -ENOMEM;
819 }
820 }
821
Jayachandran C18bc89a2006-04-20 00:14:49 -0700822 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 if (!cl_s)
824 return -ENOMEM;
825 i = 0; /* the i'th udc */
826 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
827 ebt_get_udc_positions, newinfo, repl->hook_entry, &i,
828 repl->valid_hooks, cl_s);
829 /* sanity check */
830 if (i != udc_cnt) {
831 BUGPRINT("i != udc_cnt\n");
832 vfree(cl_s);
833 return -EFAULT;
834 }
835 }
836
837 /* Check for loops */
838 for (i = 0; i < NF_BR_NUMHOOKS; i++)
839 if (repl->valid_hooks & (1 << i))
840 if (check_chainloops(newinfo->hook_entry[i],
841 cl_s, udc_cnt, i, newinfo->entries)) {
James Lamanna68d31872005-06-22 22:12:57 -0700842 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 return -EINVAL;
844 }
845
846 /* we now know the following (along with E=mc²):
847 - the nr of entries in each chain is right
848 - the size of the allocated space is right
849 - all valid hooks have a corresponding chain
850 - there are no loops
851 - wrong data can still be on the level of a single entry
852 - could be there are jumps to places that are not the
853 beginning of a chain. This can only occur in chains that
854 are not accessible from any base chains, so we don't care. */
855
856 /* used to know what we need to clean up if something goes wrong */
857 i = 0;
858 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
859 ebt_check_entry, newinfo, repl->name, &i, repl->valid_hooks,
860 cl_s, udc_cnt);
861 if (ret != 0) {
862 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
863 ebt_cleanup_entry, &i);
864 }
James Lamanna68d31872005-06-22 22:12:57 -0700865 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 return ret;
867}
868
869/* called under write_lock */
870static void get_counters(struct ebt_counter *oldcounters,
871 struct ebt_counter *counters, unsigned int nentries)
872{
873 int i, cpu;
874 struct ebt_counter *counter_base;
875
876 /* counters of cpu 0 */
877 memcpy(counters, oldcounters,
David S. Millerc8923c62005-10-13 14:41:23 -0700878 sizeof(struct ebt_counter) * nentries);
879
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 /* add other counters to those of cpu 0 */
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700881 for_each_possible_cpu(cpu) {
David S. Millerc8923c62005-10-13 14:41:23 -0700882 if (cpu == 0)
883 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
885 for (i = 0; i < nentries; i++) {
886 counters[i].pcnt += counter_base[i].pcnt;
887 counters[i].bcnt += counter_base[i].bcnt;
888 }
889 }
890}
891
892/* replace the table */
893static int do_replace(void __user *user, unsigned int len)
894{
895 int ret, i, countersize;
896 struct ebt_table_info *newinfo;
897 struct ebt_replace tmp;
898 struct ebt_table *t;
899 struct ebt_counter *counterstmp = NULL;
900 /* used to be able to unlock earlier */
901 struct ebt_table_info *table;
902
903 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
904 return -EFAULT;
905
906 if (len != sizeof(tmp) + tmp.entries_size) {
907 BUGPRINT("Wrong len argument\n");
908 return -EINVAL;
909 }
910
911 if (tmp.entries_size == 0) {
912 BUGPRINT("Entries_size never zero\n");
913 return -EINVAL;
914 }
Kirill Korotaevee4bb812006-02-04 02:16:56 -0800915 /* overflow check */
916 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
917 SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
918 return -ENOMEM;
919 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
920 return -ENOMEM;
921
David S. Millerc8923c62005-10-13 14:41:23 -0700922 countersize = COUNTER_OFFSET(tmp.nentries) *
923 (highest_possible_processor_id()+1);
Jayachandran C18bc89a2006-04-20 00:14:49 -0700924 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 if (!newinfo)
926 return -ENOMEM;
927
928 if (countersize)
929 memset(newinfo->counters, 0, countersize);
930
Kris Katterjohn8b3a7002006-01-11 15:56:43 -0800931 newinfo->entries = vmalloc(tmp.entries_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 if (!newinfo->entries) {
933 ret = -ENOMEM;
934 goto free_newinfo;
935 }
936 if (copy_from_user(
937 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
938 BUGPRINT("Couldn't copy entries from userspace\n");
939 ret = -EFAULT;
940 goto free_entries;
941 }
942
943 /* the user wants counters back
944 the check on the size is done later, when we have the lock */
945 if (tmp.num_counters) {
Jayachandran C18bc89a2006-04-20 00:14:49 -0700946 counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 if (!counterstmp) {
948 ret = -ENOMEM;
949 goto free_entries;
950 }
951 }
952 else
953 counterstmp = NULL;
954
955 /* this can get initialized by translate_table() */
956 newinfo->chainstack = NULL;
957 ret = translate_table(&tmp, newinfo);
958
959 if (ret != 0)
960 goto free_counterstmp;
961
962 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
963 if (!t) {
964 ret = -ENOENT;
965 goto free_iterate;
966 }
967
968 /* the table doesn't like it */
969 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
970 goto free_unlock;
971
972 if (tmp.num_counters && tmp.num_counters != t->private->nentries) {
973 BUGPRINT("Wrong nr. of counters requested\n");
974 ret = -EINVAL;
975 goto free_unlock;
976 }
977
978 /* we have the mutex lock, so no danger in reading this pointer */
979 table = t->private;
980 /* make sure the table can only be rmmod'ed if it contains no rules */
981 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
982 ret = -ENOENT;
983 goto free_unlock;
984 } else if (table->nentries && !newinfo->nentries)
985 module_put(t->me);
986 /* we need an atomic snapshot of the counters */
987 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);
Ingo Molnar57b47a52006-03-20 22:35:41 -0800994 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 /* 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. */
999 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
1008 /* decrease module count and free resources */
1009 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
1010 ebt_cleanup_entry, NULL);
1011
1012 vfree(table->entries);
1013 if (table->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001014 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 vfree(table->chainstack[i]);
1016 vfree(table->chainstack);
1017 }
1018 vfree(table);
1019
James Lamanna68d31872005-06-22 22:12:57 -07001020 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 return ret;
1022
1023free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001024 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025free_iterate:
1026 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1027 ebt_cleanup_entry, NULL);
1028free_counterstmp:
James Lamanna68d31872005-06-22 22:12:57 -07001029 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 /* can be initialized in translate_table() */
1031 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001032 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 vfree(newinfo->chainstack[i]);
1034 vfree(newinfo->chainstack);
1035 }
1036free_entries:
James Lamanna68d31872005-06-22 22:12:57 -07001037 vfree(newinfo->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038free_newinfo:
James Lamanna68d31872005-06-22 22:12:57 -07001039 vfree(newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 return ret;
1041}
1042
1043int ebt_register_target(struct ebt_target *target)
1044{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001045 struct ebt_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 int ret;
1047
Ingo Molnar57b47a52006-03-20 22:35:41 -08001048 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 if (ret != 0)
1050 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001051 list_for_each_entry(t, &ebt_targets, list) {
1052 if (strcmp(t->name, target->name) == 0) {
1053 mutex_unlock(&ebt_mutex);
1054 return -EEXIST;
1055 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001057 list_add(&target->list, &ebt_targets);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001058 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
1060 return 0;
1061}
1062
1063void ebt_unregister_target(struct ebt_target *target)
1064{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001065 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001066 list_del(&target->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001067 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068}
1069
1070int ebt_register_match(struct ebt_match *match)
1071{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001072 struct ebt_match *m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 int ret;
1074
Ingo Molnar57b47a52006-03-20 22:35:41 -08001075 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 if (ret != 0)
1077 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001078 list_for_each_entry(m, &ebt_matches, list) {
1079 if (strcmp(m->name, match->name) == 0) {
1080 mutex_unlock(&ebt_mutex);
1081 return -EEXIST;
1082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001084 list_add(&match->list, &ebt_matches);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001085 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086
1087 return 0;
1088}
1089
1090void ebt_unregister_match(struct ebt_match *match)
1091{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001092 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001093 list_del(&match->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001094 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095}
1096
1097int ebt_register_watcher(struct ebt_watcher *watcher)
1098{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001099 struct ebt_watcher *w;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 int ret;
1101
Ingo Molnar57b47a52006-03-20 22:35:41 -08001102 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 if (ret != 0)
1104 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001105 list_for_each_entry(w, &ebt_watchers, list) {
1106 if (strcmp(w->name, watcher->name) == 0) {
1107 mutex_unlock(&ebt_mutex);
1108 return -EEXIST;
1109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001111 list_add(&watcher->list, &ebt_watchers);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001112 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
1114 return 0;
1115}
1116
1117void ebt_unregister_watcher(struct ebt_watcher *watcher)
1118{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001119 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001120 list_del(&watcher->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001121 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122}
1123
1124int ebt_register_table(struct ebt_table *table)
1125{
1126 struct ebt_table_info *newinfo;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001127 struct ebt_table *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 int ret, i, countersize;
1129
1130 if (!table || !table->table ||!table->table->entries ||
1131 table->table->entries_size == 0 ||
1132 table->table->counters || table->private) {
1133 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1134 return -EINVAL;
1135 }
1136
David S. Millerc8923c62005-10-13 14:41:23 -07001137 countersize = COUNTER_OFFSET(table->table->nentries) *
1138 (highest_possible_processor_id()+1);
Jayachandran C18bc89a2006-04-20 00:14:49 -07001139 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 ret = -ENOMEM;
1141 if (!newinfo)
1142 return -ENOMEM;
1143
Kris Katterjohn8b3a7002006-01-11 15:56:43 -08001144 newinfo->entries = vmalloc(table->table->entries_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 if (!(newinfo->entries))
1146 goto free_newinfo;
1147
1148 memcpy(newinfo->entries, table->table->entries,
1149 table->table->entries_size);
1150
1151 if (countersize)
1152 memset(newinfo->counters, 0, countersize);
1153
1154 /* fill in newinfo and parse the entries */
1155 newinfo->chainstack = NULL;
1156 ret = translate_table(table->table, newinfo);
1157 if (ret != 0) {
1158 BUGPRINT("Translate_table failed\n");
1159 goto free_chainstack;
1160 }
1161
1162 if (table->check && table->check(newinfo, table->valid_hooks)) {
1163 BUGPRINT("The table doesn't like its own initial data, lol\n");
1164 return -EINVAL;
1165 }
1166
1167 table->private = newinfo;
1168 rwlock_init(&table->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001169 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 if (ret != 0)
1171 goto free_chainstack;
1172
Patrick McHardydf0933d2006-09-20 11:57:53 -07001173 list_for_each_entry(t, &ebt_tables, list) {
1174 if (strcmp(t->name, table->name) == 0) {
1175 ret = -EEXIST;
1176 BUGPRINT("Table name already exists\n");
1177 goto free_unlock;
1178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 }
1180
1181 /* Hold a reference count if the chains aren't empty */
1182 if (newinfo->nentries && !try_module_get(table->me)) {
1183 ret = -ENOENT;
1184 goto free_unlock;
1185 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001186 list_add(&table->list, &ebt_tables);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001187 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 return 0;
1189free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001190 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191free_chainstack:
1192 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001193 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 vfree(newinfo->chainstack[i]);
1195 vfree(newinfo->chainstack);
1196 }
1197 vfree(newinfo->entries);
1198free_newinfo:
1199 vfree(newinfo);
1200 return ret;
1201}
1202
1203void ebt_unregister_table(struct ebt_table *table)
1204{
1205 int i;
1206
1207 if (!table) {
1208 BUGPRINT("Request to unregister NULL table!!!\n");
1209 return;
1210 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001211 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001212 list_del(&table->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001213 mutex_unlock(&ebt_mutex);
James Lamanna68d31872005-06-22 22:12:57 -07001214 vfree(table->private->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 if (table->private->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001216 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 vfree(table->private->chainstack[i]);
1218 vfree(table->private->chainstack);
1219 }
1220 vfree(table->private);
1221}
1222
1223/* userspace just supplied us with counters */
1224static int update_counters(void __user *user, unsigned int len)
1225{
1226 int i, ret;
1227 struct ebt_counter *tmp;
1228 struct ebt_replace hlp;
1229 struct ebt_table *t;
1230
1231 if (copy_from_user(&hlp, user, sizeof(hlp)))
1232 return -EFAULT;
1233
1234 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1235 return -EINVAL;
1236 if (hlp.num_counters == 0)
1237 return -EINVAL;
1238
Jayachandran C18bc89a2006-04-20 00:14:49 -07001239 if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 MEMPRINT("Update_counters && nomemory\n");
1241 return -ENOMEM;
1242 }
1243
1244 t = find_table_lock(hlp.name, &ret, &ebt_mutex);
1245 if (!t)
1246 goto free_tmp;
1247
1248 if (hlp.num_counters != t->private->nentries) {
1249 BUGPRINT("Wrong nr of counters\n");
1250 ret = -EINVAL;
1251 goto unlock_mutex;
1252 }
1253
1254 if ( copy_from_user(tmp, hlp.counters,
1255 hlp.num_counters * sizeof(struct ebt_counter)) ) {
1256 BUGPRINT("Updata_counters && !cfu\n");
1257 ret = -EFAULT;
1258 goto unlock_mutex;
1259 }
1260
1261 /* we want an atomic add of the counters */
1262 write_lock_bh(&t->lock);
1263
1264 /* we add to the counters of the first cpu */
1265 for (i = 0; i < hlp.num_counters; i++) {
1266 t->private->counters[i].pcnt += tmp[i].pcnt;
1267 t->private->counters[i].bcnt += tmp[i].bcnt;
1268 }
1269
1270 write_unlock_bh(&t->lock);
1271 ret = 0;
1272unlock_mutex:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001273 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274free_tmp:
1275 vfree(tmp);
1276 return ret;
1277}
1278
1279static inline int ebt_make_matchname(struct ebt_entry_match *m,
1280 char *base, char *ubase)
1281{
1282 char *hlp = ubase - base + (char *)m;
1283 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1284 return -EFAULT;
1285 return 0;
1286}
1287
1288static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
1289 char *base, char *ubase)
1290{
1291 char *hlp = ubase - base + (char *)w;
1292 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1293 return -EFAULT;
1294 return 0;
1295}
1296
1297static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
1298{
1299 int ret;
1300 char *hlp;
1301 struct ebt_entry_target *t;
1302
1303 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
1304 return 0;
1305
1306 hlp = ubase - base + (char *)e + e->target_offset;
1307 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
1308
1309 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1310 if (ret != 0)
1311 return ret;
1312 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1313 if (ret != 0)
1314 return ret;
1315 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1316 return -EFAULT;
1317 return 0;
1318}
1319
Ingo Molnar57b47a52006-03-20 22:35:41 -08001320/* called with ebt_mutex locked */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1322 int *len, int cmd)
1323{
1324 struct ebt_replace tmp;
1325 struct ebt_counter *counterstmp, *oldcounters;
1326 unsigned int entries_size, nentries;
1327 char *entries;
1328
1329 if (cmd == EBT_SO_GET_ENTRIES) {
1330 entries_size = t->private->entries_size;
1331 nentries = t->private->nentries;
1332 entries = t->private->entries;
1333 oldcounters = t->private->counters;
1334 } else {
1335 entries_size = t->table->entries_size;
1336 nentries = t->table->nentries;
1337 entries = t->table->entries;
1338 oldcounters = t->table->counters;
1339 }
1340
1341 if (copy_from_user(&tmp, user, sizeof(tmp))) {
1342 BUGPRINT("Cfu didn't work\n");
1343 return -EFAULT;
1344 }
1345
1346 if (*len != sizeof(struct ebt_replace) + entries_size +
1347 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
1348 BUGPRINT("Wrong size\n");
1349 return -EINVAL;
1350 }
1351
1352 if (tmp.nentries != nentries) {
1353 BUGPRINT("Nentries wrong\n");
1354 return -EINVAL;
1355 }
1356
1357 if (tmp.entries_size != entries_size) {
1358 BUGPRINT("Wrong size\n");
1359 return -EINVAL;
1360 }
1361
1362 /* userspace might not need the counters */
1363 if (tmp.num_counters) {
1364 if (tmp.num_counters != nentries) {
1365 BUGPRINT("Num_counters wrong\n");
1366 return -EINVAL;
1367 }
Jayachandran C18bc89a2006-04-20 00:14:49 -07001368 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 if (!counterstmp) {
1370 MEMPRINT("Couldn't copy counters, out of memory\n");
1371 return -ENOMEM;
1372 }
1373 write_lock_bh(&t->lock);
1374 get_counters(oldcounters, counterstmp, nentries);
1375 write_unlock_bh(&t->lock);
1376
1377 if (copy_to_user(tmp.counters, counterstmp,
1378 nentries * sizeof(struct ebt_counter))) {
1379 BUGPRINT("Couldn't copy counters to userspace\n");
1380 vfree(counterstmp);
1381 return -EFAULT;
1382 }
1383 vfree(counterstmp);
1384 }
1385
1386 if (copy_to_user(tmp.entries, entries, entries_size)) {
1387 BUGPRINT("Couldn't copy entries to userspace\n");
1388 return -EFAULT;
1389 }
1390 /* set the match/watcher/target names right */
1391 return EBT_ENTRY_ITERATE(entries, entries_size,
1392 ebt_make_names, entries, tmp.entries);
1393}
1394
1395static int do_ebt_set_ctl(struct sock *sk,
1396 int cmd, void __user *user, unsigned int len)
1397{
1398 int ret;
1399
1400 switch(cmd) {
1401 case EBT_SO_SET_ENTRIES:
1402 ret = do_replace(user, len);
1403 break;
1404 case EBT_SO_SET_COUNTERS:
1405 ret = update_counters(user, len);
1406 break;
1407 default:
1408 ret = -EINVAL;
1409 }
1410 return ret;
1411}
1412
1413static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1414{
1415 int ret;
1416 struct ebt_replace tmp;
1417 struct ebt_table *t;
1418
1419 if (copy_from_user(&tmp, user, sizeof(tmp)))
1420 return -EFAULT;
1421
1422 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1423 if (!t)
1424 return ret;
1425
1426 switch(cmd) {
1427 case EBT_SO_GET_INFO:
1428 case EBT_SO_GET_INIT_INFO:
1429 if (*len != sizeof(struct ebt_replace)){
1430 ret = -EINVAL;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001431 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 break;
1433 }
1434 if (cmd == EBT_SO_GET_INFO) {
1435 tmp.nentries = t->private->nentries;
1436 tmp.entries_size = t->private->entries_size;
1437 tmp.valid_hooks = t->valid_hooks;
1438 } else {
1439 tmp.nentries = t->table->nentries;
1440 tmp.entries_size = t->table->entries_size;
1441 tmp.valid_hooks = t->table->valid_hooks;
1442 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001443 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 if (copy_to_user(user, &tmp, *len) != 0){
1445 BUGPRINT("c2u Didn't work\n");
1446 ret = -EFAULT;
1447 break;
1448 }
1449 ret = 0;
1450 break;
1451
1452 case EBT_SO_GET_ENTRIES:
1453 case EBT_SO_GET_INIT_ENTRIES:
1454 ret = copy_everything_to_user(t, user, len, cmd);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001455 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 break;
1457
1458 default:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001459 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 ret = -EINVAL;
1461 }
1462
1463 return ret;
1464}
1465
1466static struct nf_sockopt_ops ebt_sockopts =
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08001467{
1468 .pf = PF_INET,
1469 .set_optmin = EBT_BASE_CTL,
1470 .set_optmax = EBT_SO_SET_MAX + 1,
1471 .set = do_ebt_set_ctl,
1472 .get_optmin = EBT_BASE_CTL,
1473 .get_optmax = EBT_SO_GET_MAX + 1,
1474 .get = do_ebt_get_ctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475};
1476
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001477static int __init ebtables_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478{
1479 int ret;
1480
Ingo Molnar57b47a52006-03-20 22:35:41 -08001481 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001482 list_add(&ebt_standard_target.list, &ebt_targets);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001483 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
1485 return ret;
1486
1487 printk(KERN_NOTICE "Ebtables v2.0 registered\n");
1488 return 0;
1489}
1490
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001491static void __exit ebtables_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492{
1493 nf_unregister_sockopt(&ebt_sockopts);
1494 printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
1495}
1496
1497EXPORT_SYMBOL(ebt_register_table);
1498EXPORT_SYMBOL(ebt_unregister_table);
1499EXPORT_SYMBOL(ebt_register_match);
1500EXPORT_SYMBOL(ebt_unregister_match);
1501EXPORT_SYMBOL(ebt_register_watcher);
1502EXPORT_SYMBOL(ebt_unregister_watcher);
1503EXPORT_SYMBOL(ebt_register_target);
1504EXPORT_SYMBOL(ebt_unregister_target);
1505EXPORT_SYMBOL(ebt_do_table);
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001506module_init(ebtables_init);
1507module_exit(ebtables_fini);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508MODULE_LICENSE("GPL");