blob: 136ed7d4bd7320fc679e21720c5cfd33fb072f52 [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;
Meelis Roos6f5b7ef2006-11-01 18:07:27 -080089 const char *devname = device->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
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;
Al Viro14197d52006-11-30 19:25:21 -0800341 size_t left = ((char *)e + e->watchers_offset) - (char *)m;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 int ret;
343
Al Viro14197d52006-11-30 19:25:21 -0800344 if (left < sizeof(struct ebt_entry_match) ||
345 left - sizeof(struct ebt_entry_match) < m->match_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 return -EINVAL;
347 match = find_match_lock(m->u.name, &ret, &ebt_mutex);
348 if (!match)
349 return ret;
350 m->u.match = match;
351 if (!try_module_get(match->me)) {
Ingo Molnar57b47a52006-03-20 22:35:41 -0800352 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 return -ENOENT;
354 }
Ingo Molnar57b47a52006-03-20 22:35:41 -0800355 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 if (match->check &&
357 match->check(name, hookmask, e, m->data, m->match_size) != 0) {
358 BUGPRINT("match->check failed\n");
359 module_put(match->me);
360 return -EINVAL;
361 }
362 (*cnt)++;
363 return 0;
364}
365
366static inline int
367ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
368 const char *name, unsigned int hookmask, unsigned int *cnt)
369{
370 struct ebt_watcher *watcher;
Al Viro14197d52006-11-30 19:25:21 -0800371 size_t left = ((char *)e + e->target_offset) - (char *)w;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 int ret;
373
Al Viro14197d52006-11-30 19:25:21 -0800374 if (left < sizeof(struct ebt_entry_watcher) ||
375 left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 return -EINVAL;
377 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
378 if (!watcher)
379 return ret;
380 w->u.watcher = watcher;
381 if (!try_module_get(watcher->me)) {
Ingo Molnar57b47a52006-03-20 22:35:41 -0800382 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 return -ENOENT;
384 }
Ingo Molnar57b47a52006-03-20 22:35:41 -0800385 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 if (watcher->check &&
387 watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) {
388 BUGPRINT("watcher->check failed\n");
389 module_put(watcher->me);
390 return -EINVAL;
391 }
392 (*cnt)++;
393 return 0;
394}
395
396/*
397 * this one is very careful, as it is the first function
398 * to parse the userspace data
399 */
400static inline int
401ebt_check_entry_size_and_hooks(struct ebt_entry *e,
402 struct ebt_table_info *newinfo, char *base, char *limit,
403 struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
404 unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
405{
Al Virobb2ef252006-11-30 19:22:42 -0800406 unsigned int offset = (char *)e - newinfo->entries;
407 size_t left = (limit - base) - offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 int i;
409
Al Virobb2ef252006-11-30 19:22:42 -0800410 if (left < sizeof(unsigned int))
411 goto Esmall;
412
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
414 if ((valid_hooks & (1 << i)) == 0)
415 continue;
Al Virobb2ef252006-11-30 19:22:42 -0800416 if ((char *)hook_entries[i] == base + offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 break;
418 }
419 /* beginning of a new chain
420 if i == NF_BR_NUMHOOKS it must be a user defined chain */
421 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
Al Viro40642f92006-11-30 19:24:12 -0800422 if (e->bitmask != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 /* we make userspace set this right,
424 so there is no misunderstanding */
425 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
426 "in distinguisher\n");
427 return -EINVAL;
428 }
429 /* this checks if the previous chain has as many entries
430 as it said it has */
431 if (*n != *cnt) {
432 BUGPRINT("nentries does not equal the nr of entries "
433 "in the chain\n");
434 return -EINVAL;
435 }
436 /* before we look at the struct, be sure it is not too big */
Al Virobb2ef252006-11-30 19:22:42 -0800437 if (left < sizeof(struct ebt_entries))
438 goto Esmall;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
440 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
441 /* only RETURN from udc */
442 if (i != NF_BR_NUMHOOKS ||
443 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
444 BUGPRINT("bad policy\n");
445 return -EINVAL;
446 }
447 }
448 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
449 (*udc_cnt)++;
450 else
451 newinfo->hook_entry[i] = (struct ebt_entries *)e;
452 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
453 BUGPRINT("counter_offset != totalcnt");
454 return -EINVAL;
455 }
456 *n = ((struct ebt_entries *)e)->nentries;
457 *cnt = 0;
458 return 0;
459 }
460 /* a plain old entry, heh */
Al Virobb2ef252006-11-30 19:22:42 -0800461 if (left < sizeof(struct ebt_entry))
462 goto Esmall;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 if (sizeof(struct ebt_entry) > e->watchers_offset ||
464 e->watchers_offset > e->target_offset ||
465 e->target_offset >= e->next_offset) {
466 BUGPRINT("entry offsets not in right order\n");
467 return -EINVAL;
468 }
469 /* this is not checked anywhere else */
470 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
471 BUGPRINT("target size too small\n");
472 return -EINVAL;
473 }
Al Virobb2ef252006-11-30 19:22:42 -0800474 if (left < e->next_offset)
475 goto Esmall;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
477 (*cnt)++;
478 (*totalcnt)++;
479 return 0;
Al Virobb2ef252006-11-30 19:22:42 -0800480
481Esmall:
482 BUGPRINT("entries_size too small\n");
483 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484}
485
486struct ebt_cl_stack
487{
488 struct ebt_chainstack cs;
489 int from;
490 unsigned int hookmask;
491};
492
493/*
494 * we need these positions to check that the jumps to a different part of the
495 * entries is a jump to the beginning of a new chain.
496 */
497static inline int
498ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
499 struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks,
500 struct ebt_cl_stack *udc)
501{
502 int i;
503
504 /* we're only interested in chain starts */
Al Viro40642f92006-11-30 19:24:12 -0800505 if (e->bitmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 return 0;
507 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
508 if ((valid_hooks & (1 << i)) == 0)
509 continue;
510 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
511 break;
512 }
513 /* only care about udc */
514 if (i != NF_BR_NUMHOOKS)
515 return 0;
516
517 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
518 /* these initialisations are depended on later in check_chainloops() */
519 udc[*n].cs.n = 0;
520 udc[*n].hookmask = 0;
521
522 (*n)++;
523 return 0;
524}
525
526static inline int
527ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
528{
529 if (i && (*i)-- == 0)
530 return 1;
531 if (m->u.match->destroy)
532 m->u.match->destroy(m->data, m->match_size);
533 module_put(m->u.match->me);
534
535 return 0;
536}
537
538static inline int
539ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
540{
541 if (i && (*i)-- == 0)
542 return 1;
543 if (w->u.watcher->destroy)
544 w->u.watcher->destroy(w->data, w->watcher_size);
545 module_put(w->u.watcher->me);
546
547 return 0;
548}
549
550static inline int
551ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
552{
553 struct ebt_entry_target *t;
554
Al Viro40642f92006-11-30 19:24:12 -0800555 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 return 0;
557 /* we're done */
558 if (cnt && (*cnt)-- == 0)
559 return 1;
560 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
561 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);
562 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
563 if (t->u.target->destroy)
564 t->u.target->destroy(t->data, t->target_size);
565 module_put(t->u.target->me);
566
567 return 0;
568}
569
570static inline int
571ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
572 const char *name, unsigned int *cnt, unsigned int valid_hooks,
573 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
574{
575 struct ebt_entry_target *t;
576 struct ebt_target *target;
577 unsigned int i, j, hook = 0, hookmask = 0;
Al Viro14197d52006-11-30 19:25:21 -0800578 size_t gap = e->next_offset - e->target_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 int ret;
580
581 /* don't mess with the struct ebt_entries */
Al Viro40642f92006-11-30 19:24:12 -0800582 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 return 0;
584
585 if (e->bitmask & ~EBT_F_MASK) {
586 BUGPRINT("Unknown flag for bitmask\n");
587 return -EINVAL;
588 }
589 if (e->invflags & ~EBT_INV_MASK) {
590 BUGPRINT("Unknown flag for inv bitmask\n");
591 return -EINVAL;
592 }
593 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
594 BUGPRINT("NOPROTO & 802_3 not allowed\n");
595 return -EINVAL;
596 }
597 /* what hook do we belong to? */
598 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
599 if ((valid_hooks & (1 << i)) == 0)
600 continue;
601 if ((char *)newinfo->hook_entry[i] < (char *)e)
602 hook = i;
603 else
604 break;
605 }
606 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
607 a base chain */
608 if (i < NF_BR_NUMHOOKS)
609 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
610 else {
611 for (i = 0; i < udc_cnt; i++)
612 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
613 break;
614 if (i == 0)
615 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
616 else
617 hookmask = cl_s[i - 1].hookmask;
618 }
619 i = 0;
620 ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);
621 if (ret != 0)
622 goto cleanup_matches;
623 j = 0;
624 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
625 if (ret != 0)
626 goto cleanup_watchers;
627 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
628 target = find_target_lock(t->u.name, &ret, &ebt_mutex);
629 if (!target)
630 goto cleanup_watchers;
631 if (!try_module_get(target->me)) {
Ingo Molnar57b47a52006-03-20 22:35:41 -0800632 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 ret = -ENOENT;
634 goto cleanup_watchers;
635 }
Ingo Molnar57b47a52006-03-20 22:35:41 -0800636 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
638 t->u.target = target;
639 if (t->u.target == &ebt_standard_target) {
Al Viro14197d52006-11-30 19:25:21 -0800640 if (gap < sizeof(struct ebt_standard_target)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 BUGPRINT("Standard target size too big\n");
642 ret = -EFAULT;
643 goto cleanup_watchers;
644 }
645 if (((struct ebt_standard_target *)t)->verdict <
646 -NUM_STANDARD_TARGETS) {
647 BUGPRINT("Invalid standard target\n");
648 ret = -EFAULT;
649 goto cleanup_watchers;
650 }
Al Viro14197d52006-11-30 19:25:21 -0800651 } else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 (t->u.target->check &&
653 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
654 module_put(t->u.target->me);
655 ret = -EFAULT;
656 goto cleanup_watchers;
657 }
658 (*cnt)++;
659 return 0;
660cleanup_watchers:
661 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);
662cleanup_matches:
663 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i);
664 return ret;
665}
666
667/*
668 * checks for loops and sets the hook mask for udc
669 * the hook mask for udc tells us from which base chains the udc can be
670 * accessed. This mask is a parameter to the check() functions of the extensions
671 */
672static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
673 unsigned int udc_cnt, unsigned int hooknr, char *base)
674{
675 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
676 struct ebt_entry *e = (struct ebt_entry *)chain->data;
677 struct ebt_entry_target *t;
678
679 while (pos < nentries || chain_nr != -1) {
680 /* end of udc, go back one 'recursion' step */
681 if (pos == nentries) {
682 /* put back values of the time when this chain was called */
683 e = cl_s[chain_nr].cs.e;
684 if (cl_s[chain_nr].from != -1)
685 nentries =
686 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
687 else
688 nentries = chain->nentries;
689 pos = cl_s[chain_nr].cs.n;
690 /* make sure we won't see a loop that isn't one */
691 cl_s[chain_nr].cs.n = 0;
692 chain_nr = cl_s[chain_nr].from;
693 if (pos == nentries)
694 continue;
695 }
696 t = (struct ebt_entry_target *)
697 (((char *)e) + e->target_offset);
698 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
699 goto letscontinue;
700 if (e->target_offset + sizeof(struct ebt_standard_target) >
701 e->next_offset) {
702 BUGPRINT("Standard target size too big\n");
703 return -1;
704 }
705 verdict = ((struct ebt_standard_target *)t)->verdict;
706 if (verdict >= 0) { /* jump to another chain */
707 struct ebt_entries *hlp2 =
708 (struct ebt_entries *)(base + verdict);
709 for (i = 0; i < udc_cnt; i++)
710 if (hlp2 == cl_s[i].cs.chaininfo)
711 break;
712 /* bad destination or loop */
713 if (i == udc_cnt) {
714 BUGPRINT("bad destination\n");
715 return -1;
716 }
717 if (cl_s[i].cs.n) {
718 BUGPRINT("loop\n");
719 return -1;
720 }
Al Viro98a08242006-11-30 19:24:49 -0800721 if (cl_s[i].hookmask & (1 << hooknr))
722 goto letscontinue;
723 /* this can't be 0, so the loop test is correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 cl_s[i].cs.n = pos + 1;
725 pos = 0;
726 cl_s[i].cs.e = ((void *)e + e->next_offset);
727 e = (struct ebt_entry *)(hlp2->data);
728 nentries = hlp2->nentries;
729 cl_s[i].from = chain_nr;
730 chain_nr = i;
731 /* this udc is accessible from the base chain for hooknr */
732 cl_s[i].hookmask |= (1 << hooknr);
733 continue;
734 }
735letscontinue:
736 e = (void *)e + e->next_offset;
737 pos++;
738 }
739 return 0;
740}
741
742/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
743static int translate_table(struct ebt_replace *repl,
744 struct ebt_table_info *newinfo)
745{
746 unsigned int i, j, k, udc_cnt;
747 int ret;
748 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
749
750 i = 0;
751 while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i)))
752 i++;
753 if (i == NF_BR_NUMHOOKS) {
754 BUGPRINT("No valid hooks specified\n");
755 return -EINVAL;
756 }
757 if (repl->hook_entry[i] != (struct ebt_entries *)repl->entries) {
758 BUGPRINT("Chains don't start at beginning\n");
759 return -EINVAL;
760 }
761 /* make sure chains are ordered after each other in same order
762 as their corresponding hooks */
763 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
764 if (!(repl->valid_hooks & (1 << j)))
765 continue;
766 if ( repl->hook_entry[j] <= repl->hook_entry[i] ) {
767 BUGPRINT("Hook order must be followed\n");
768 return -EINVAL;
769 }
770 i = j;
771 }
772
773 for (i = 0; i < NF_BR_NUMHOOKS; i++)
774 newinfo->hook_entry[i] = NULL;
775
776 newinfo->entries_size = repl->entries_size;
777 newinfo->nentries = repl->nentries;
778
779 /* do some early checkings and initialize some things */
780 i = 0; /* holds the expected nr. of entries for the chain */
781 j = 0; /* holds the up to now counted entries for the chain */
782 k = 0; /* holds the total nr. of entries, should equal
783 newinfo->nentries afterwards */
784 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
785 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
786 ebt_check_entry_size_and_hooks, newinfo, repl->entries,
787 repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k,
788 &udc_cnt, repl->valid_hooks);
789
790 if (ret != 0)
791 return ret;
792
793 if (i != j) {
794 BUGPRINT("nentries does not equal the nr of entries in the "
795 "(last) chain\n");
796 return -EINVAL;
797 }
798 if (k != newinfo->nentries) {
799 BUGPRINT("Total nentries is wrong\n");
800 return -EINVAL;
801 }
802
803 /* check if all valid hooks have a chain */
804 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
805 if (newinfo->hook_entry[i] == NULL &&
806 (repl->valid_hooks & (1 << i))) {
807 BUGPRINT("Valid hook without chain\n");
808 return -EINVAL;
809 }
810 }
811
812 /* get the location of the udc, put them in an array
813 while we're at it, allocate the chainstack */
814 if (udc_cnt) {
815 /* this will get free'd in do_replace()/ebt_register_table()
816 if an error occurs */
Jayachandran C7ad4d2f2006-04-11 17:25:38 -0700817 newinfo->chainstack =
818 vmalloc((highest_possible_processor_id()+1)
819 * sizeof(*(newinfo->chainstack)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 if (!newinfo->chainstack)
821 return -ENOMEM;
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700822 for_each_possible_cpu(i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 newinfo->chainstack[i] =
Jayachandran C18bc89a2006-04-20 00:14:49 -0700824 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 if (!newinfo->chainstack[i]) {
826 while (i)
827 vfree(newinfo->chainstack[--i]);
828 vfree(newinfo->chainstack);
829 newinfo->chainstack = NULL;
830 return -ENOMEM;
831 }
832 }
833
Jayachandran C18bc89a2006-04-20 00:14:49 -0700834 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 if (!cl_s)
836 return -ENOMEM;
837 i = 0; /* the i'th udc */
838 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
839 ebt_get_udc_positions, newinfo, repl->hook_entry, &i,
840 repl->valid_hooks, cl_s);
841 /* sanity check */
842 if (i != udc_cnt) {
843 BUGPRINT("i != udc_cnt\n");
844 vfree(cl_s);
845 return -EFAULT;
846 }
847 }
848
849 /* Check for loops */
850 for (i = 0; i < NF_BR_NUMHOOKS; i++)
851 if (repl->valid_hooks & (1 << i))
852 if (check_chainloops(newinfo->hook_entry[i],
853 cl_s, udc_cnt, i, newinfo->entries)) {
James Lamanna68d31872005-06-22 22:12:57 -0700854 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 return -EINVAL;
856 }
857
858 /* we now know the following (along with E=mc²):
859 - the nr of entries in each chain is right
860 - the size of the allocated space is right
861 - all valid hooks have a corresponding chain
862 - there are no loops
863 - wrong data can still be on the level of a single entry
864 - could be there are jumps to places that are not the
865 beginning of a chain. This can only occur in chains that
866 are not accessible from any base chains, so we don't care. */
867
868 /* used to know what we need to clean up if something goes wrong */
869 i = 0;
870 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
871 ebt_check_entry, newinfo, repl->name, &i, repl->valid_hooks,
872 cl_s, udc_cnt);
873 if (ret != 0) {
874 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
875 ebt_cleanup_entry, &i);
876 }
James Lamanna68d31872005-06-22 22:12:57 -0700877 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 return ret;
879}
880
881/* called under write_lock */
882static void get_counters(struct ebt_counter *oldcounters,
883 struct ebt_counter *counters, unsigned int nentries)
884{
885 int i, cpu;
886 struct ebt_counter *counter_base;
887
888 /* counters of cpu 0 */
889 memcpy(counters, oldcounters,
David S. Millerc8923c62005-10-13 14:41:23 -0700890 sizeof(struct ebt_counter) * nentries);
891
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 /* add other counters to those of cpu 0 */
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700893 for_each_possible_cpu(cpu) {
David S. Millerc8923c62005-10-13 14:41:23 -0700894 if (cpu == 0)
895 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
897 for (i = 0; i < nentries; i++) {
898 counters[i].pcnt += counter_base[i].pcnt;
899 counters[i].bcnt += counter_base[i].bcnt;
900 }
901 }
902}
903
904/* replace the table */
905static int do_replace(void __user *user, unsigned int len)
906{
907 int ret, i, countersize;
908 struct ebt_table_info *newinfo;
909 struct ebt_replace tmp;
910 struct ebt_table *t;
911 struct ebt_counter *counterstmp = NULL;
912 /* used to be able to unlock earlier */
913 struct ebt_table_info *table;
914
915 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
916 return -EFAULT;
917
918 if (len != sizeof(tmp) + tmp.entries_size) {
919 BUGPRINT("Wrong len argument\n");
920 return -EINVAL;
921 }
922
923 if (tmp.entries_size == 0) {
924 BUGPRINT("Entries_size never zero\n");
925 return -EINVAL;
926 }
Kirill Korotaevee4bb812006-02-04 02:16:56 -0800927 /* overflow check */
928 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
929 SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
930 return -ENOMEM;
931 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
932 return -ENOMEM;
933
David S. Millerc8923c62005-10-13 14:41:23 -0700934 countersize = COUNTER_OFFSET(tmp.nentries) *
935 (highest_possible_processor_id()+1);
Jayachandran C18bc89a2006-04-20 00:14:49 -0700936 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 if (!newinfo)
938 return -ENOMEM;
939
940 if (countersize)
941 memset(newinfo->counters, 0, countersize);
942
Kris Katterjohn8b3a7002006-01-11 15:56:43 -0800943 newinfo->entries = vmalloc(tmp.entries_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 if (!newinfo->entries) {
945 ret = -ENOMEM;
946 goto free_newinfo;
947 }
948 if (copy_from_user(
949 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
950 BUGPRINT("Couldn't copy entries from userspace\n");
951 ret = -EFAULT;
952 goto free_entries;
953 }
954
955 /* the user wants counters back
956 the check on the size is done later, when we have the lock */
957 if (tmp.num_counters) {
Jayachandran C18bc89a2006-04-20 00:14:49 -0700958 counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 if (!counterstmp) {
960 ret = -ENOMEM;
961 goto free_entries;
962 }
963 }
964 else
965 counterstmp = NULL;
966
967 /* this can get initialized by translate_table() */
968 newinfo->chainstack = NULL;
969 ret = translate_table(&tmp, newinfo);
970
971 if (ret != 0)
972 goto free_counterstmp;
973
974 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
975 if (!t) {
976 ret = -ENOENT;
977 goto free_iterate;
978 }
979
980 /* the table doesn't like it */
981 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
982 goto free_unlock;
983
984 if (tmp.num_counters && tmp.num_counters != t->private->nentries) {
985 BUGPRINT("Wrong nr. of counters requested\n");
986 ret = -EINVAL;
987 goto free_unlock;
988 }
989
990 /* we have the mutex lock, so no danger in reading this pointer */
991 table = t->private;
992 /* make sure the table can only be rmmod'ed if it contains no rules */
993 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
994 ret = -ENOENT;
995 goto free_unlock;
996 } else if (table->nentries && !newinfo->nentries)
997 module_put(t->me);
998 /* we need an atomic snapshot of the counters */
999 write_lock_bh(&t->lock);
1000 if (tmp.num_counters)
1001 get_counters(t->private->counters, counterstmp,
1002 t->private->nentries);
1003
1004 t->private = newinfo;
1005 write_unlock_bh(&t->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001006 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 /* so, a user can change the chains while having messed up her counter
1008 allocation. Only reason why this is done is because this way the lock
1009 is held only once, while this doesn't bring the kernel into a
1010 dangerous state. */
1011 if (tmp.num_counters &&
1012 copy_to_user(tmp.counters, counterstmp,
1013 tmp.num_counters * sizeof(struct ebt_counter))) {
1014 BUGPRINT("Couldn't copy counters to userspace\n");
1015 ret = -EFAULT;
1016 }
1017 else
1018 ret = 0;
1019
1020 /* decrease module count and free resources */
1021 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
1022 ebt_cleanup_entry, NULL);
1023
1024 vfree(table->entries);
1025 if (table->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001026 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 vfree(table->chainstack[i]);
1028 vfree(table->chainstack);
1029 }
1030 vfree(table);
1031
James Lamanna68d31872005-06-22 22:12:57 -07001032 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 return ret;
1034
1035free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001036 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037free_iterate:
1038 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1039 ebt_cleanup_entry, NULL);
1040free_counterstmp:
James Lamanna68d31872005-06-22 22:12:57 -07001041 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 /* can be initialized in translate_table() */
1043 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001044 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 vfree(newinfo->chainstack[i]);
1046 vfree(newinfo->chainstack);
1047 }
1048free_entries:
James Lamanna68d31872005-06-22 22:12:57 -07001049 vfree(newinfo->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050free_newinfo:
James Lamanna68d31872005-06-22 22:12:57 -07001051 vfree(newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 return ret;
1053}
1054
1055int ebt_register_target(struct ebt_target *target)
1056{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001057 struct ebt_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 int ret;
1059
Ingo Molnar57b47a52006-03-20 22:35:41 -08001060 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 if (ret != 0)
1062 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001063 list_for_each_entry(t, &ebt_targets, list) {
1064 if (strcmp(t->name, target->name) == 0) {
1065 mutex_unlock(&ebt_mutex);
1066 return -EEXIST;
1067 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001069 list_add(&target->list, &ebt_targets);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001070 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
1072 return 0;
1073}
1074
1075void ebt_unregister_target(struct ebt_target *target)
1076{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001077 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001078 list_del(&target->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001079 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080}
1081
1082int ebt_register_match(struct ebt_match *match)
1083{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001084 struct ebt_match *m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 int ret;
1086
Ingo Molnar57b47a52006-03-20 22:35:41 -08001087 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 if (ret != 0)
1089 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001090 list_for_each_entry(m, &ebt_matches, list) {
1091 if (strcmp(m->name, match->name) == 0) {
1092 mutex_unlock(&ebt_mutex);
1093 return -EEXIST;
1094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001096 list_add(&match->list, &ebt_matches);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001097 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098
1099 return 0;
1100}
1101
1102void ebt_unregister_match(struct ebt_match *match)
1103{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001104 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001105 list_del(&match->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001106 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107}
1108
1109int ebt_register_watcher(struct ebt_watcher *watcher)
1110{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001111 struct ebt_watcher *w;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 int ret;
1113
Ingo Molnar57b47a52006-03-20 22:35:41 -08001114 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 if (ret != 0)
1116 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001117 list_for_each_entry(w, &ebt_watchers, list) {
1118 if (strcmp(w->name, watcher->name) == 0) {
1119 mutex_unlock(&ebt_mutex);
1120 return -EEXIST;
1121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001123 list_add(&watcher->list, &ebt_watchers);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001124 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
1126 return 0;
1127}
1128
1129void ebt_unregister_watcher(struct ebt_watcher *watcher)
1130{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001131 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001132 list_del(&watcher->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001133 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134}
1135
1136int ebt_register_table(struct ebt_table *table)
1137{
1138 struct ebt_table_info *newinfo;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001139 struct ebt_table *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 int ret, i, countersize;
1141
1142 if (!table || !table->table ||!table->table->entries ||
1143 table->table->entries_size == 0 ||
1144 table->table->counters || table->private) {
1145 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1146 return -EINVAL;
1147 }
1148
David S. Millerc8923c62005-10-13 14:41:23 -07001149 countersize = COUNTER_OFFSET(table->table->nentries) *
1150 (highest_possible_processor_id()+1);
Jayachandran C18bc89a2006-04-20 00:14:49 -07001151 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 ret = -ENOMEM;
1153 if (!newinfo)
1154 return -ENOMEM;
1155
Kris Katterjohn8b3a7002006-01-11 15:56:43 -08001156 newinfo->entries = vmalloc(table->table->entries_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 if (!(newinfo->entries))
1158 goto free_newinfo;
1159
1160 memcpy(newinfo->entries, table->table->entries,
1161 table->table->entries_size);
1162
1163 if (countersize)
1164 memset(newinfo->counters, 0, countersize);
1165
1166 /* fill in newinfo and parse the entries */
1167 newinfo->chainstack = NULL;
1168 ret = translate_table(table->table, newinfo);
1169 if (ret != 0) {
1170 BUGPRINT("Translate_table failed\n");
1171 goto free_chainstack;
1172 }
1173
1174 if (table->check && table->check(newinfo, table->valid_hooks)) {
1175 BUGPRINT("The table doesn't like its own initial data, lol\n");
1176 return -EINVAL;
1177 }
1178
1179 table->private = newinfo;
1180 rwlock_init(&table->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001181 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 if (ret != 0)
1183 goto free_chainstack;
1184
Patrick McHardydf0933d2006-09-20 11:57:53 -07001185 list_for_each_entry(t, &ebt_tables, list) {
1186 if (strcmp(t->name, table->name) == 0) {
1187 ret = -EEXIST;
1188 BUGPRINT("Table name already exists\n");
1189 goto free_unlock;
1190 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 }
1192
1193 /* Hold a reference count if the chains aren't empty */
1194 if (newinfo->nentries && !try_module_get(table->me)) {
1195 ret = -ENOENT;
1196 goto free_unlock;
1197 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001198 list_add(&table->list, &ebt_tables);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001199 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 return 0;
1201free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001202 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203free_chainstack:
1204 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001205 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 vfree(newinfo->chainstack[i]);
1207 vfree(newinfo->chainstack);
1208 }
1209 vfree(newinfo->entries);
1210free_newinfo:
1211 vfree(newinfo);
1212 return ret;
1213}
1214
1215void ebt_unregister_table(struct ebt_table *table)
1216{
1217 int i;
1218
1219 if (!table) {
1220 BUGPRINT("Request to unregister NULL table!!!\n");
1221 return;
1222 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001223 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001224 list_del(&table->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001225 mutex_unlock(&ebt_mutex);
James Lamanna68d31872005-06-22 22:12:57 -07001226 vfree(table->private->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 if (table->private->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001228 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 vfree(table->private->chainstack[i]);
1230 vfree(table->private->chainstack);
1231 }
1232 vfree(table->private);
1233}
1234
1235/* userspace just supplied us with counters */
1236static int update_counters(void __user *user, unsigned int len)
1237{
1238 int i, ret;
1239 struct ebt_counter *tmp;
1240 struct ebt_replace hlp;
1241 struct ebt_table *t;
1242
1243 if (copy_from_user(&hlp, user, sizeof(hlp)))
1244 return -EFAULT;
1245
1246 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1247 return -EINVAL;
1248 if (hlp.num_counters == 0)
1249 return -EINVAL;
1250
Jayachandran C18bc89a2006-04-20 00:14:49 -07001251 if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 MEMPRINT("Update_counters && nomemory\n");
1253 return -ENOMEM;
1254 }
1255
1256 t = find_table_lock(hlp.name, &ret, &ebt_mutex);
1257 if (!t)
1258 goto free_tmp;
1259
1260 if (hlp.num_counters != t->private->nentries) {
1261 BUGPRINT("Wrong nr of counters\n");
1262 ret = -EINVAL;
1263 goto unlock_mutex;
1264 }
1265
1266 if ( copy_from_user(tmp, hlp.counters,
1267 hlp.num_counters * sizeof(struct ebt_counter)) ) {
1268 BUGPRINT("Updata_counters && !cfu\n");
1269 ret = -EFAULT;
1270 goto unlock_mutex;
1271 }
1272
1273 /* we want an atomic add of the counters */
1274 write_lock_bh(&t->lock);
1275
1276 /* we add to the counters of the first cpu */
1277 for (i = 0; i < hlp.num_counters; i++) {
1278 t->private->counters[i].pcnt += tmp[i].pcnt;
1279 t->private->counters[i].bcnt += tmp[i].bcnt;
1280 }
1281
1282 write_unlock_bh(&t->lock);
1283 ret = 0;
1284unlock_mutex:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001285 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286free_tmp:
1287 vfree(tmp);
1288 return ret;
1289}
1290
1291static inline int ebt_make_matchname(struct ebt_entry_match *m,
1292 char *base, char *ubase)
1293{
1294 char *hlp = ubase - base + (char *)m;
1295 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1296 return -EFAULT;
1297 return 0;
1298}
1299
1300static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
1301 char *base, char *ubase)
1302{
1303 char *hlp = ubase - base + (char *)w;
1304 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1305 return -EFAULT;
1306 return 0;
1307}
1308
1309static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
1310{
1311 int ret;
1312 char *hlp;
1313 struct ebt_entry_target *t;
1314
Al Viro40642f92006-11-30 19:24:12 -08001315 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 return 0;
1317
1318 hlp = ubase - base + (char *)e + e->target_offset;
1319 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
1320
1321 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1322 if (ret != 0)
1323 return ret;
1324 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1325 if (ret != 0)
1326 return ret;
1327 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1328 return -EFAULT;
1329 return 0;
1330}
1331
Ingo Molnar57b47a52006-03-20 22:35:41 -08001332/* called with ebt_mutex locked */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1334 int *len, int cmd)
1335{
1336 struct ebt_replace tmp;
1337 struct ebt_counter *counterstmp, *oldcounters;
1338 unsigned int entries_size, nentries;
1339 char *entries;
1340
1341 if (cmd == EBT_SO_GET_ENTRIES) {
1342 entries_size = t->private->entries_size;
1343 nentries = t->private->nentries;
1344 entries = t->private->entries;
1345 oldcounters = t->private->counters;
1346 } else {
1347 entries_size = t->table->entries_size;
1348 nentries = t->table->nentries;
1349 entries = t->table->entries;
1350 oldcounters = t->table->counters;
1351 }
1352
1353 if (copy_from_user(&tmp, user, sizeof(tmp))) {
1354 BUGPRINT("Cfu didn't work\n");
1355 return -EFAULT;
1356 }
1357
1358 if (*len != sizeof(struct ebt_replace) + entries_size +
1359 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
1360 BUGPRINT("Wrong size\n");
1361 return -EINVAL;
1362 }
1363
1364 if (tmp.nentries != nentries) {
1365 BUGPRINT("Nentries wrong\n");
1366 return -EINVAL;
1367 }
1368
1369 if (tmp.entries_size != entries_size) {
1370 BUGPRINT("Wrong size\n");
1371 return -EINVAL;
1372 }
1373
1374 /* userspace might not need the counters */
1375 if (tmp.num_counters) {
1376 if (tmp.num_counters != nentries) {
1377 BUGPRINT("Num_counters wrong\n");
1378 return -EINVAL;
1379 }
Jayachandran C18bc89a2006-04-20 00:14:49 -07001380 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 if (!counterstmp) {
1382 MEMPRINT("Couldn't copy counters, out of memory\n");
1383 return -ENOMEM;
1384 }
1385 write_lock_bh(&t->lock);
1386 get_counters(oldcounters, counterstmp, nentries);
1387 write_unlock_bh(&t->lock);
1388
1389 if (copy_to_user(tmp.counters, counterstmp,
1390 nentries * sizeof(struct ebt_counter))) {
1391 BUGPRINT("Couldn't copy counters to userspace\n");
1392 vfree(counterstmp);
1393 return -EFAULT;
1394 }
1395 vfree(counterstmp);
1396 }
1397
1398 if (copy_to_user(tmp.entries, entries, entries_size)) {
1399 BUGPRINT("Couldn't copy entries to userspace\n");
1400 return -EFAULT;
1401 }
1402 /* set the match/watcher/target names right */
1403 return EBT_ENTRY_ITERATE(entries, entries_size,
1404 ebt_make_names, entries, tmp.entries);
1405}
1406
1407static int do_ebt_set_ctl(struct sock *sk,
1408 int cmd, void __user *user, unsigned int len)
1409{
1410 int ret;
1411
1412 switch(cmd) {
1413 case EBT_SO_SET_ENTRIES:
1414 ret = do_replace(user, len);
1415 break;
1416 case EBT_SO_SET_COUNTERS:
1417 ret = update_counters(user, len);
1418 break;
1419 default:
1420 ret = -EINVAL;
1421 }
1422 return ret;
1423}
1424
1425static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1426{
1427 int ret;
1428 struct ebt_replace tmp;
1429 struct ebt_table *t;
1430
1431 if (copy_from_user(&tmp, user, sizeof(tmp)))
1432 return -EFAULT;
1433
1434 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1435 if (!t)
1436 return ret;
1437
1438 switch(cmd) {
1439 case EBT_SO_GET_INFO:
1440 case EBT_SO_GET_INIT_INFO:
1441 if (*len != sizeof(struct ebt_replace)){
1442 ret = -EINVAL;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001443 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 break;
1445 }
1446 if (cmd == EBT_SO_GET_INFO) {
1447 tmp.nentries = t->private->nentries;
1448 tmp.entries_size = t->private->entries_size;
1449 tmp.valid_hooks = t->valid_hooks;
1450 } else {
1451 tmp.nentries = t->table->nentries;
1452 tmp.entries_size = t->table->entries_size;
1453 tmp.valid_hooks = t->table->valid_hooks;
1454 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001455 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 if (copy_to_user(user, &tmp, *len) != 0){
1457 BUGPRINT("c2u Didn't work\n");
1458 ret = -EFAULT;
1459 break;
1460 }
1461 ret = 0;
1462 break;
1463
1464 case EBT_SO_GET_ENTRIES:
1465 case EBT_SO_GET_INIT_ENTRIES:
1466 ret = copy_everything_to_user(t, user, len, cmd);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001467 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 break;
1469
1470 default:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001471 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 ret = -EINVAL;
1473 }
1474
1475 return ret;
1476}
1477
1478static struct nf_sockopt_ops ebt_sockopts =
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08001479{
1480 .pf = PF_INET,
1481 .set_optmin = EBT_BASE_CTL,
1482 .set_optmax = EBT_SO_SET_MAX + 1,
1483 .set = do_ebt_set_ctl,
1484 .get_optmin = EBT_BASE_CTL,
1485 .get_optmax = EBT_SO_GET_MAX + 1,
1486 .get = do_ebt_get_ctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487};
1488
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001489static int __init ebtables_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490{
1491 int ret;
1492
Ingo Molnar57b47a52006-03-20 22:35:41 -08001493 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001494 list_add(&ebt_standard_target.list, &ebt_targets);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001495 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
1497 return ret;
1498
1499 printk(KERN_NOTICE "Ebtables v2.0 registered\n");
1500 return 0;
1501}
1502
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001503static void __exit ebtables_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504{
1505 nf_unregister_sockopt(&ebt_sockopts);
1506 printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
1507}
1508
1509EXPORT_SYMBOL(ebt_register_table);
1510EXPORT_SYMBOL(ebt_unregister_table);
1511EXPORT_SYMBOL(ebt_register_match);
1512EXPORT_SYMBOL(ebt_unregister_match);
1513EXPORT_SYMBOL(ebt_register_watcher);
1514EXPORT_SYMBOL(ebt_unregister_watcher);
1515EXPORT_SYMBOL(ebt_register_target);
1516EXPORT_SYMBOL(ebt_unregister_target);
1517EXPORT_SYMBOL(ebt_do_table);
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001518module_init(ebtables_init);
1519module_exit(ebtables_fini);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520MODULE_LICENSE("GPL");