blob: 2eba40f54233a5917b2120778a85c1a1d76664ed [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
Al Viro70fe9af2006-11-30 19:26:14 -0800396static int ebt_verify_pointers(struct ebt_replace *repl,
397 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398{
Al Viro70fe9af2006-11-30 19:26:14 -0800399 unsigned int limit = repl->entries_size;
400 unsigned int valid_hooks = repl->valid_hooks;
401 unsigned int offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 int i;
403
Al Viro70fe9af2006-11-30 19:26:14 -0800404 while (offset < limit) {
405 size_t left = limit - offset;
406 struct ebt_entry *e = (void *)newinfo->entries + offset;
Al Virobb2ef252006-11-30 19:22:42 -0800407
Al Viro70fe9af2006-11-30 19:26:14 -0800408 if (left < sizeof(unsigned int))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 break;
Al Viro22b440b2006-11-30 19:25:51 -0800410
Al Viro70fe9af2006-11-30 19:26:14 -0800411 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
412 if ((valid_hooks & (1 << i)) == 0)
413 continue;
414 if ((char *)repl->hook_entry[i] == repl->entries + offset)
415 break;
416 }
417
418 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
419 if (e->bitmask != 0) {
420 /* we make userspace set this right,
421 so there is no misunderstanding */
422 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
423 "in distinguisher\n");
424 return -EINVAL;
425 }
426 if (i != NF_BR_NUMHOOKS)
427 newinfo->hook_entry[i] = (struct ebt_entries *)e;
428 if (left < sizeof(struct ebt_entries))
429 break;
430 offset += sizeof(struct ebt_entries);
431 } else {
432 if (left < sizeof(struct ebt_entry))
433 break;
434 if (left < e->next_offset)
435 break;
436 offset += e->next_offset;
437 }
438 }
439 if (offset != limit) {
440 BUGPRINT("entries_size too small\n");
441 return -EINVAL;
442 }
443 return 0;
Al Viro22b440b2006-11-30 19:25:51 -0800444}
445
446/*
447 * this one is very careful, as it is the first function
448 * to parse the userspace data
449 */
450static inline int
451ebt_check_entry_size_and_hooks(struct ebt_entry *e,
452 struct ebt_table_info *newinfo, char *base,
453 struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
454 unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
455{
456 unsigned int offset = (char *)e - newinfo->entries;
457 int i;
458
459 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
460 if ((valid_hooks & (1 << i)) == 0)
461 continue;
462 if ((char *)hook_entries[i] == base + offset)
463 break;
464 }
465 /* beginning of a new chain
466 if i == NF_BR_NUMHOOKS it must be a user defined chain */
467 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 /* this checks if the previous chain has as many entries
469 as it said it has */
470 if (*n != *cnt) {
471 BUGPRINT("nentries does not equal the nr of entries "
472 "in the chain\n");
473 return -EINVAL;
474 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
476 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
477 /* only RETURN from udc */
478 if (i != NF_BR_NUMHOOKS ||
479 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
480 BUGPRINT("bad policy\n");
481 return -EINVAL;
482 }
483 }
484 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
485 (*udc_cnt)++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
487 BUGPRINT("counter_offset != totalcnt");
488 return -EINVAL;
489 }
490 *n = ((struct ebt_entries *)e)->nentries;
491 *cnt = 0;
492 return 0;
493 }
494 /* a plain old entry, heh */
495 if (sizeof(struct ebt_entry) > e->watchers_offset ||
496 e->watchers_offset > e->target_offset ||
497 e->target_offset >= e->next_offset) {
498 BUGPRINT("entry offsets not in right order\n");
499 return -EINVAL;
500 }
501 /* this is not checked anywhere else */
502 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
503 BUGPRINT("target size too small\n");
504 return -EINVAL;
505 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 (*cnt)++;
507 (*totalcnt)++;
508 return 0;
509}
510
511struct ebt_cl_stack
512{
513 struct ebt_chainstack cs;
514 int from;
515 unsigned int hookmask;
516};
517
518/*
519 * we need these positions to check that the jumps to a different part of the
520 * entries is a jump to the beginning of a new chain.
521 */
522static inline int
523ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
524 struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks,
525 struct ebt_cl_stack *udc)
526{
527 int i;
528
529 /* we're only interested in chain starts */
Al Viro40642f92006-11-30 19:24:12 -0800530 if (e->bitmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 return 0;
532 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
533 if ((valid_hooks & (1 << i)) == 0)
534 continue;
535 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
536 break;
537 }
538 /* only care about udc */
539 if (i != NF_BR_NUMHOOKS)
540 return 0;
541
542 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
543 /* these initialisations are depended on later in check_chainloops() */
544 udc[*n].cs.n = 0;
545 udc[*n].hookmask = 0;
546
547 (*n)++;
548 return 0;
549}
550
551static inline int
552ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
553{
554 if (i && (*i)-- == 0)
555 return 1;
556 if (m->u.match->destroy)
557 m->u.match->destroy(m->data, m->match_size);
558 module_put(m->u.match->me);
559
560 return 0;
561}
562
563static inline int
564ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
565{
566 if (i && (*i)-- == 0)
567 return 1;
568 if (w->u.watcher->destroy)
569 w->u.watcher->destroy(w->data, w->watcher_size);
570 module_put(w->u.watcher->me);
571
572 return 0;
573}
574
575static inline int
576ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
577{
578 struct ebt_entry_target *t;
579
Al Viro40642f92006-11-30 19:24:12 -0800580 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 return 0;
582 /* we're done */
583 if (cnt && (*cnt)-- == 0)
584 return 1;
585 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
586 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);
587 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
588 if (t->u.target->destroy)
589 t->u.target->destroy(t->data, t->target_size);
590 module_put(t->u.target->me);
591
592 return 0;
593}
594
595static inline int
596ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
597 const char *name, unsigned int *cnt, unsigned int valid_hooks,
598 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
599{
600 struct ebt_entry_target *t;
601 struct ebt_target *target;
602 unsigned int i, j, hook = 0, hookmask = 0;
Al Viro14197d52006-11-30 19:25:21 -0800603 size_t gap = e->next_offset - e->target_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 int ret;
605
606 /* don't mess with the struct ebt_entries */
Al Viro40642f92006-11-30 19:24:12 -0800607 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 return 0;
609
610 if (e->bitmask & ~EBT_F_MASK) {
611 BUGPRINT("Unknown flag for bitmask\n");
612 return -EINVAL;
613 }
614 if (e->invflags & ~EBT_INV_MASK) {
615 BUGPRINT("Unknown flag for inv bitmask\n");
616 return -EINVAL;
617 }
618 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
619 BUGPRINT("NOPROTO & 802_3 not allowed\n");
620 return -EINVAL;
621 }
622 /* what hook do we belong to? */
623 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
624 if ((valid_hooks & (1 << i)) == 0)
625 continue;
626 if ((char *)newinfo->hook_entry[i] < (char *)e)
627 hook = i;
628 else
629 break;
630 }
631 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
632 a base chain */
633 if (i < NF_BR_NUMHOOKS)
634 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
635 else {
636 for (i = 0; i < udc_cnt; i++)
637 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
638 break;
639 if (i == 0)
640 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
641 else
642 hookmask = cl_s[i - 1].hookmask;
643 }
644 i = 0;
645 ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);
646 if (ret != 0)
647 goto cleanup_matches;
648 j = 0;
649 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
650 if (ret != 0)
651 goto cleanup_watchers;
652 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
653 target = find_target_lock(t->u.name, &ret, &ebt_mutex);
654 if (!target)
655 goto cleanup_watchers;
656 if (!try_module_get(target->me)) {
Ingo Molnar57b47a52006-03-20 22:35:41 -0800657 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 ret = -ENOENT;
659 goto cleanup_watchers;
660 }
Ingo Molnar57b47a52006-03-20 22:35:41 -0800661 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
663 t->u.target = target;
664 if (t->u.target == &ebt_standard_target) {
Al Viro14197d52006-11-30 19:25:21 -0800665 if (gap < sizeof(struct ebt_standard_target)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 BUGPRINT("Standard target size too big\n");
667 ret = -EFAULT;
668 goto cleanup_watchers;
669 }
670 if (((struct ebt_standard_target *)t)->verdict <
671 -NUM_STANDARD_TARGETS) {
672 BUGPRINT("Invalid standard target\n");
673 ret = -EFAULT;
674 goto cleanup_watchers;
675 }
Al Viro14197d52006-11-30 19:25:21 -0800676 } else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 (t->u.target->check &&
678 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
679 module_put(t->u.target->me);
680 ret = -EFAULT;
681 goto cleanup_watchers;
682 }
683 (*cnt)++;
684 return 0;
685cleanup_watchers:
686 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);
687cleanup_matches:
688 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i);
689 return ret;
690}
691
692/*
693 * checks for loops and sets the hook mask for udc
694 * the hook mask for udc tells us from which base chains the udc can be
695 * accessed. This mask is a parameter to the check() functions of the extensions
696 */
697static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
698 unsigned int udc_cnt, unsigned int hooknr, char *base)
699{
700 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
701 struct ebt_entry *e = (struct ebt_entry *)chain->data;
702 struct ebt_entry_target *t;
703
704 while (pos < nentries || chain_nr != -1) {
705 /* end of udc, go back one 'recursion' step */
706 if (pos == nentries) {
707 /* put back values of the time when this chain was called */
708 e = cl_s[chain_nr].cs.e;
709 if (cl_s[chain_nr].from != -1)
710 nentries =
711 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
712 else
713 nentries = chain->nentries;
714 pos = cl_s[chain_nr].cs.n;
715 /* make sure we won't see a loop that isn't one */
716 cl_s[chain_nr].cs.n = 0;
717 chain_nr = cl_s[chain_nr].from;
718 if (pos == nentries)
719 continue;
720 }
721 t = (struct ebt_entry_target *)
722 (((char *)e) + e->target_offset);
723 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
724 goto letscontinue;
725 if (e->target_offset + sizeof(struct ebt_standard_target) >
726 e->next_offset) {
727 BUGPRINT("Standard target size too big\n");
728 return -1;
729 }
730 verdict = ((struct ebt_standard_target *)t)->verdict;
731 if (verdict >= 0) { /* jump to another chain */
732 struct ebt_entries *hlp2 =
733 (struct ebt_entries *)(base + verdict);
734 for (i = 0; i < udc_cnt; i++)
735 if (hlp2 == cl_s[i].cs.chaininfo)
736 break;
737 /* bad destination or loop */
738 if (i == udc_cnt) {
739 BUGPRINT("bad destination\n");
740 return -1;
741 }
742 if (cl_s[i].cs.n) {
743 BUGPRINT("loop\n");
744 return -1;
745 }
Al Viro98a08242006-11-30 19:24:49 -0800746 if (cl_s[i].hookmask & (1 << hooknr))
747 goto letscontinue;
748 /* this can't be 0, so the loop test is correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 cl_s[i].cs.n = pos + 1;
750 pos = 0;
751 cl_s[i].cs.e = ((void *)e + e->next_offset);
752 e = (struct ebt_entry *)(hlp2->data);
753 nentries = hlp2->nentries;
754 cl_s[i].from = chain_nr;
755 chain_nr = i;
756 /* this udc is accessible from the base chain for hooknr */
757 cl_s[i].hookmask |= (1 << hooknr);
758 continue;
759 }
760letscontinue:
761 e = (void *)e + e->next_offset;
762 pos++;
763 }
764 return 0;
765}
766
767/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
768static int translate_table(struct ebt_replace *repl,
769 struct ebt_table_info *newinfo)
770{
771 unsigned int i, j, k, udc_cnt;
772 int ret;
773 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
774
775 i = 0;
776 while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i)))
777 i++;
778 if (i == NF_BR_NUMHOOKS) {
779 BUGPRINT("No valid hooks specified\n");
780 return -EINVAL;
781 }
782 if (repl->hook_entry[i] != (struct ebt_entries *)repl->entries) {
783 BUGPRINT("Chains don't start at beginning\n");
784 return -EINVAL;
785 }
786 /* make sure chains are ordered after each other in same order
787 as their corresponding hooks */
788 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
789 if (!(repl->valid_hooks & (1 << j)))
790 continue;
791 if ( repl->hook_entry[j] <= repl->hook_entry[i] ) {
792 BUGPRINT("Hook order must be followed\n");
793 return -EINVAL;
794 }
795 i = j;
796 }
797
798 for (i = 0; i < NF_BR_NUMHOOKS; i++)
799 newinfo->hook_entry[i] = NULL;
800
801 newinfo->entries_size = repl->entries_size;
802 newinfo->nentries = repl->nentries;
803
Al Viro70fe9af2006-11-30 19:26:14 -0800804 ret = ebt_verify_pointers(repl, newinfo);
Al Viro22b440b2006-11-30 19:25:51 -0800805 if (ret != 0)
806 return ret;
807
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 /* do some early checkings and initialize some things */
809 i = 0; /* holds the expected nr. of entries for the chain */
810 j = 0; /* holds the up to now counted entries for the chain */
811 k = 0; /* holds the total nr. of entries, should equal
812 newinfo->nentries afterwards */
813 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
814 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
815 ebt_check_entry_size_and_hooks, newinfo, repl->entries,
Al Viro22b440b2006-11-30 19:25:51 -0800816 repl->hook_entry, &i, &j, &k,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 &udc_cnt, repl->valid_hooks);
818
819 if (ret != 0)
820 return ret;
821
822 if (i != j) {
823 BUGPRINT("nentries does not equal the nr of entries in the "
824 "(last) chain\n");
825 return -EINVAL;
826 }
827 if (k != newinfo->nentries) {
828 BUGPRINT("Total nentries is wrong\n");
829 return -EINVAL;
830 }
831
832 /* check if all valid hooks have a chain */
833 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
834 if (newinfo->hook_entry[i] == NULL &&
835 (repl->valid_hooks & (1 << i))) {
836 BUGPRINT("Valid hook without chain\n");
837 return -EINVAL;
838 }
839 }
840
841 /* get the location of the udc, put them in an array
842 while we're at it, allocate the chainstack */
843 if (udc_cnt) {
844 /* this will get free'd in do_replace()/ebt_register_table()
845 if an error occurs */
Jayachandran C7ad4d2f2006-04-11 17:25:38 -0700846 newinfo->chainstack =
847 vmalloc((highest_possible_processor_id()+1)
848 * sizeof(*(newinfo->chainstack)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 if (!newinfo->chainstack)
850 return -ENOMEM;
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700851 for_each_possible_cpu(i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 newinfo->chainstack[i] =
Jayachandran C18bc89a2006-04-20 00:14:49 -0700853 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 if (!newinfo->chainstack[i]) {
855 while (i)
856 vfree(newinfo->chainstack[--i]);
857 vfree(newinfo->chainstack);
858 newinfo->chainstack = NULL;
859 return -ENOMEM;
860 }
861 }
862
Jayachandran C18bc89a2006-04-20 00:14:49 -0700863 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 if (!cl_s)
865 return -ENOMEM;
866 i = 0; /* the i'th udc */
867 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
868 ebt_get_udc_positions, newinfo, repl->hook_entry, &i,
869 repl->valid_hooks, cl_s);
870 /* sanity check */
871 if (i != udc_cnt) {
872 BUGPRINT("i != udc_cnt\n");
873 vfree(cl_s);
874 return -EFAULT;
875 }
876 }
877
878 /* Check for loops */
879 for (i = 0; i < NF_BR_NUMHOOKS; i++)
880 if (repl->valid_hooks & (1 << i))
881 if (check_chainloops(newinfo->hook_entry[i],
882 cl_s, udc_cnt, i, newinfo->entries)) {
James Lamanna68d31872005-06-22 22:12:57 -0700883 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 return -EINVAL;
885 }
886
887 /* we now know the following (along with E=mc²):
888 - the nr of entries in each chain is right
889 - the size of the allocated space is right
890 - all valid hooks have a corresponding chain
891 - there are no loops
892 - wrong data can still be on the level of a single entry
893 - could be there are jumps to places that are not the
894 beginning of a chain. This can only occur in chains that
895 are not accessible from any base chains, so we don't care. */
896
897 /* used to know what we need to clean up if something goes wrong */
898 i = 0;
899 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
900 ebt_check_entry, newinfo, repl->name, &i, repl->valid_hooks,
901 cl_s, udc_cnt);
902 if (ret != 0) {
903 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
904 ebt_cleanup_entry, &i);
905 }
James Lamanna68d31872005-06-22 22:12:57 -0700906 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 return ret;
908}
909
910/* called under write_lock */
911static void get_counters(struct ebt_counter *oldcounters,
912 struct ebt_counter *counters, unsigned int nentries)
913{
914 int i, cpu;
915 struct ebt_counter *counter_base;
916
917 /* counters of cpu 0 */
918 memcpy(counters, oldcounters,
David S. Millerc8923c62005-10-13 14:41:23 -0700919 sizeof(struct ebt_counter) * nentries);
920
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 /* add other counters to those of cpu 0 */
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700922 for_each_possible_cpu(cpu) {
David S. Millerc8923c62005-10-13 14:41:23 -0700923 if (cpu == 0)
924 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
926 for (i = 0; i < nentries; i++) {
927 counters[i].pcnt += counter_base[i].pcnt;
928 counters[i].bcnt += counter_base[i].bcnt;
929 }
930 }
931}
932
933/* replace the table */
934static int do_replace(void __user *user, unsigned int len)
935{
936 int ret, i, countersize;
937 struct ebt_table_info *newinfo;
938 struct ebt_replace tmp;
939 struct ebt_table *t;
940 struct ebt_counter *counterstmp = NULL;
941 /* used to be able to unlock earlier */
942 struct ebt_table_info *table;
943
944 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
945 return -EFAULT;
946
947 if (len != sizeof(tmp) + tmp.entries_size) {
948 BUGPRINT("Wrong len argument\n");
949 return -EINVAL;
950 }
951
952 if (tmp.entries_size == 0) {
953 BUGPRINT("Entries_size never zero\n");
954 return -EINVAL;
955 }
Kirill Korotaevee4bb812006-02-04 02:16:56 -0800956 /* overflow check */
957 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
958 SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
959 return -ENOMEM;
960 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
961 return -ENOMEM;
962
David S. Millerc8923c62005-10-13 14:41:23 -0700963 countersize = COUNTER_OFFSET(tmp.nentries) *
964 (highest_possible_processor_id()+1);
Jayachandran C18bc89a2006-04-20 00:14:49 -0700965 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 if (!newinfo)
967 return -ENOMEM;
968
969 if (countersize)
970 memset(newinfo->counters, 0, countersize);
971
Kris Katterjohn8b3a7002006-01-11 15:56:43 -0800972 newinfo->entries = vmalloc(tmp.entries_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 if (!newinfo->entries) {
974 ret = -ENOMEM;
975 goto free_newinfo;
976 }
977 if (copy_from_user(
978 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
979 BUGPRINT("Couldn't copy entries from userspace\n");
980 ret = -EFAULT;
981 goto free_entries;
982 }
983
984 /* the user wants counters back
985 the check on the size is done later, when we have the lock */
986 if (tmp.num_counters) {
Jayachandran C18bc89a2006-04-20 00:14:49 -0700987 counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 if (!counterstmp) {
989 ret = -ENOMEM;
990 goto free_entries;
991 }
992 }
993 else
994 counterstmp = NULL;
995
996 /* this can get initialized by translate_table() */
997 newinfo->chainstack = NULL;
998 ret = translate_table(&tmp, newinfo);
999
1000 if (ret != 0)
1001 goto free_counterstmp;
1002
1003 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1004 if (!t) {
1005 ret = -ENOENT;
1006 goto free_iterate;
1007 }
1008
1009 /* the table doesn't like it */
1010 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
1011 goto free_unlock;
1012
1013 if (tmp.num_counters && tmp.num_counters != t->private->nentries) {
1014 BUGPRINT("Wrong nr. of counters requested\n");
1015 ret = -EINVAL;
1016 goto free_unlock;
1017 }
1018
1019 /* we have the mutex lock, so no danger in reading this pointer */
1020 table = t->private;
1021 /* make sure the table can only be rmmod'ed if it contains no rules */
1022 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
1023 ret = -ENOENT;
1024 goto free_unlock;
1025 } else if (table->nentries && !newinfo->nentries)
1026 module_put(t->me);
1027 /* we need an atomic snapshot of the counters */
1028 write_lock_bh(&t->lock);
1029 if (tmp.num_counters)
1030 get_counters(t->private->counters, counterstmp,
1031 t->private->nentries);
1032
1033 t->private = newinfo;
1034 write_unlock_bh(&t->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001035 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 /* so, a user can change the chains while having messed up her counter
1037 allocation. Only reason why this is done is because this way the lock
1038 is held only once, while this doesn't bring the kernel into a
1039 dangerous state. */
1040 if (tmp.num_counters &&
1041 copy_to_user(tmp.counters, counterstmp,
1042 tmp.num_counters * sizeof(struct ebt_counter))) {
1043 BUGPRINT("Couldn't copy counters to userspace\n");
1044 ret = -EFAULT;
1045 }
1046 else
1047 ret = 0;
1048
1049 /* decrease module count and free resources */
1050 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
1051 ebt_cleanup_entry, NULL);
1052
1053 vfree(table->entries);
1054 if (table->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001055 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 vfree(table->chainstack[i]);
1057 vfree(table->chainstack);
1058 }
1059 vfree(table);
1060
James Lamanna68d31872005-06-22 22:12:57 -07001061 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 return ret;
1063
1064free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001065 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066free_iterate:
1067 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1068 ebt_cleanup_entry, NULL);
1069free_counterstmp:
James Lamanna68d31872005-06-22 22:12:57 -07001070 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 /* can be initialized in translate_table() */
1072 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001073 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 vfree(newinfo->chainstack[i]);
1075 vfree(newinfo->chainstack);
1076 }
1077free_entries:
James Lamanna68d31872005-06-22 22:12:57 -07001078 vfree(newinfo->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079free_newinfo:
James Lamanna68d31872005-06-22 22:12:57 -07001080 vfree(newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 return ret;
1082}
1083
1084int ebt_register_target(struct ebt_target *target)
1085{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001086 struct ebt_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 int ret;
1088
Ingo Molnar57b47a52006-03-20 22:35:41 -08001089 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 if (ret != 0)
1091 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001092 list_for_each_entry(t, &ebt_targets, list) {
1093 if (strcmp(t->name, target->name) == 0) {
1094 mutex_unlock(&ebt_mutex);
1095 return -EEXIST;
1096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001098 list_add(&target->list, &ebt_targets);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001099 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
1101 return 0;
1102}
1103
1104void ebt_unregister_target(struct ebt_target *target)
1105{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001106 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001107 list_del(&target->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001108 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109}
1110
1111int ebt_register_match(struct ebt_match *match)
1112{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001113 struct ebt_match *m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 int ret;
1115
Ingo Molnar57b47a52006-03-20 22:35:41 -08001116 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 if (ret != 0)
1118 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001119 list_for_each_entry(m, &ebt_matches, list) {
1120 if (strcmp(m->name, match->name) == 0) {
1121 mutex_unlock(&ebt_mutex);
1122 return -EEXIST;
1123 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001125 list_add(&match->list, &ebt_matches);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001126 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127
1128 return 0;
1129}
1130
1131void ebt_unregister_match(struct ebt_match *match)
1132{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001133 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001134 list_del(&match->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001135 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136}
1137
1138int ebt_register_watcher(struct ebt_watcher *watcher)
1139{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001140 struct ebt_watcher *w;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 int ret;
1142
Ingo Molnar57b47a52006-03-20 22:35:41 -08001143 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 if (ret != 0)
1145 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001146 list_for_each_entry(w, &ebt_watchers, list) {
1147 if (strcmp(w->name, watcher->name) == 0) {
1148 mutex_unlock(&ebt_mutex);
1149 return -EEXIST;
1150 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001152 list_add(&watcher->list, &ebt_watchers);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001153 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
1155 return 0;
1156}
1157
1158void ebt_unregister_watcher(struct ebt_watcher *watcher)
1159{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001160 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001161 list_del(&watcher->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001162 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163}
1164
1165int ebt_register_table(struct ebt_table *table)
1166{
1167 struct ebt_table_info *newinfo;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001168 struct ebt_table *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 int ret, i, countersize;
1170
1171 if (!table || !table->table ||!table->table->entries ||
1172 table->table->entries_size == 0 ||
1173 table->table->counters || table->private) {
1174 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1175 return -EINVAL;
1176 }
1177
David S. Millerc8923c62005-10-13 14:41:23 -07001178 countersize = COUNTER_OFFSET(table->table->nentries) *
1179 (highest_possible_processor_id()+1);
Jayachandran C18bc89a2006-04-20 00:14:49 -07001180 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 ret = -ENOMEM;
1182 if (!newinfo)
1183 return -ENOMEM;
1184
Kris Katterjohn8b3a7002006-01-11 15:56:43 -08001185 newinfo->entries = vmalloc(table->table->entries_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 if (!(newinfo->entries))
1187 goto free_newinfo;
1188
1189 memcpy(newinfo->entries, table->table->entries,
1190 table->table->entries_size);
1191
1192 if (countersize)
1193 memset(newinfo->counters, 0, countersize);
1194
1195 /* fill in newinfo and parse the entries */
1196 newinfo->chainstack = NULL;
1197 ret = translate_table(table->table, newinfo);
1198 if (ret != 0) {
1199 BUGPRINT("Translate_table failed\n");
1200 goto free_chainstack;
1201 }
1202
1203 if (table->check && table->check(newinfo, table->valid_hooks)) {
1204 BUGPRINT("The table doesn't like its own initial data, lol\n");
1205 return -EINVAL;
1206 }
1207
1208 table->private = newinfo;
1209 rwlock_init(&table->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001210 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 if (ret != 0)
1212 goto free_chainstack;
1213
Patrick McHardydf0933d2006-09-20 11:57:53 -07001214 list_for_each_entry(t, &ebt_tables, list) {
1215 if (strcmp(t->name, table->name) == 0) {
1216 ret = -EEXIST;
1217 BUGPRINT("Table name already exists\n");
1218 goto free_unlock;
1219 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 }
1221
1222 /* Hold a reference count if the chains aren't empty */
1223 if (newinfo->nentries && !try_module_get(table->me)) {
1224 ret = -ENOENT;
1225 goto free_unlock;
1226 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001227 list_add(&table->list, &ebt_tables);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001228 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 return 0;
1230free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001231 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232free_chainstack:
1233 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001234 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 vfree(newinfo->chainstack[i]);
1236 vfree(newinfo->chainstack);
1237 }
1238 vfree(newinfo->entries);
1239free_newinfo:
1240 vfree(newinfo);
1241 return ret;
1242}
1243
1244void ebt_unregister_table(struct ebt_table *table)
1245{
1246 int i;
1247
1248 if (!table) {
1249 BUGPRINT("Request to unregister NULL table!!!\n");
1250 return;
1251 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001252 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001253 list_del(&table->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001254 mutex_unlock(&ebt_mutex);
James Lamanna68d31872005-06-22 22:12:57 -07001255 vfree(table->private->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 if (table->private->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001257 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 vfree(table->private->chainstack[i]);
1259 vfree(table->private->chainstack);
1260 }
1261 vfree(table->private);
1262}
1263
1264/* userspace just supplied us with counters */
1265static int update_counters(void __user *user, unsigned int len)
1266{
1267 int i, ret;
1268 struct ebt_counter *tmp;
1269 struct ebt_replace hlp;
1270 struct ebt_table *t;
1271
1272 if (copy_from_user(&hlp, user, sizeof(hlp)))
1273 return -EFAULT;
1274
1275 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1276 return -EINVAL;
1277 if (hlp.num_counters == 0)
1278 return -EINVAL;
1279
Jayachandran C18bc89a2006-04-20 00:14:49 -07001280 if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 MEMPRINT("Update_counters && nomemory\n");
1282 return -ENOMEM;
1283 }
1284
1285 t = find_table_lock(hlp.name, &ret, &ebt_mutex);
1286 if (!t)
1287 goto free_tmp;
1288
1289 if (hlp.num_counters != t->private->nentries) {
1290 BUGPRINT("Wrong nr of counters\n");
1291 ret = -EINVAL;
1292 goto unlock_mutex;
1293 }
1294
1295 if ( copy_from_user(tmp, hlp.counters,
1296 hlp.num_counters * sizeof(struct ebt_counter)) ) {
1297 BUGPRINT("Updata_counters && !cfu\n");
1298 ret = -EFAULT;
1299 goto unlock_mutex;
1300 }
1301
1302 /* we want an atomic add of the counters */
1303 write_lock_bh(&t->lock);
1304
1305 /* we add to the counters of the first cpu */
1306 for (i = 0; i < hlp.num_counters; i++) {
1307 t->private->counters[i].pcnt += tmp[i].pcnt;
1308 t->private->counters[i].bcnt += tmp[i].bcnt;
1309 }
1310
1311 write_unlock_bh(&t->lock);
1312 ret = 0;
1313unlock_mutex:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001314 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315free_tmp:
1316 vfree(tmp);
1317 return ret;
1318}
1319
1320static inline int ebt_make_matchname(struct ebt_entry_match *m,
1321 char *base, char *ubase)
1322{
1323 char *hlp = ubase - base + (char *)m;
1324 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1325 return -EFAULT;
1326 return 0;
1327}
1328
1329static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
1330 char *base, char *ubase)
1331{
1332 char *hlp = ubase - base + (char *)w;
1333 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1334 return -EFAULT;
1335 return 0;
1336}
1337
1338static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
1339{
1340 int ret;
1341 char *hlp;
1342 struct ebt_entry_target *t;
1343
Al Viro40642f92006-11-30 19:24:12 -08001344 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 return 0;
1346
1347 hlp = ubase - base + (char *)e + e->target_offset;
1348 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
1349
1350 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1351 if (ret != 0)
1352 return ret;
1353 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1354 if (ret != 0)
1355 return ret;
1356 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1357 return -EFAULT;
1358 return 0;
1359}
1360
Ingo Molnar57b47a52006-03-20 22:35:41 -08001361/* called with ebt_mutex locked */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1363 int *len, int cmd)
1364{
1365 struct ebt_replace tmp;
1366 struct ebt_counter *counterstmp, *oldcounters;
1367 unsigned int entries_size, nentries;
1368 char *entries;
1369
1370 if (cmd == EBT_SO_GET_ENTRIES) {
1371 entries_size = t->private->entries_size;
1372 nentries = t->private->nentries;
1373 entries = t->private->entries;
1374 oldcounters = t->private->counters;
1375 } else {
1376 entries_size = t->table->entries_size;
1377 nentries = t->table->nentries;
1378 entries = t->table->entries;
1379 oldcounters = t->table->counters;
1380 }
1381
1382 if (copy_from_user(&tmp, user, sizeof(tmp))) {
1383 BUGPRINT("Cfu didn't work\n");
1384 return -EFAULT;
1385 }
1386
1387 if (*len != sizeof(struct ebt_replace) + entries_size +
1388 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
1389 BUGPRINT("Wrong size\n");
1390 return -EINVAL;
1391 }
1392
1393 if (tmp.nentries != nentries) {
1394 BUGPRINT("Nentries wrong\n");
1395 return -EINVAL;
1396 }
1397
1398 if (tmp.entries_size != entries_size) {
1399 BUGPRINT("Wrong size\n");
1400 return -EINVAL;
1401 }
1402
1403 /* userspace might not need the counters */
1404 if (tmp.num_counters) {
1405 if (tmp.num_counters != nentries) {
1406 BUGPRINT("Num_counters wrong\n");
1407 return -EINVAL;
1408 }
Jayachandran C18bc89a2006-04-20 00:14:49 -07001409 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 if (!counterstmp) {
1411 MEMPRINT("Couldn't copy counters, out of memory\n");
1412 return -ENOMEM;
1413 }
1414 write_lock_bh(&t->lock);
1415 get_counters(oldcounters, counterstmp, nentries);
1416 write_unlock_bh(&t->lock);
1417
1418 if (copy_to_user(tmp.counters, counterstmp,
1419 nentries * sizeof(struct ebt_counter))) {
1420 BUGPRINT("Couldn't copy counters to userspace\n");
1421 vfree(counterstmp);
1422 return -EFAULT;
1423 }
1424 vfree(counterstmp);
1425 }
1426
1427 if (copy_to_user(tmp.entries, entries, entries_size)) {
1428 BUGPRINT("Couldn't copy entries to userspace\n");
1429 return -EFAULT;
1430 }
1431 /* set the match/watcher/target names right */
1432 return EBT_ENTRY_ITERATE(entries, entries_size,
1433 ebt_make_names, entries, tmp.entries);
1434}
1435
1436static int do_ebt_set_ctl(struct sock *sk,
1437 int cmd, void __user *user, unsigned int len)
1438{
1439 int ret;
1440
1441 switch(cmd) {
1442 case EBT_SO_SET_ENTRIES:
1443 ret = do_replace(user, len);
1444 break;
1445 case EBT_SO_SET_COUNTERS:
1446 ret = update_counters(user, len);
1447 break;
1448 default:
1449 ret = -EINVAL;
1450 }
1451 return ret;
1452}
1453
1454static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1455{
1456 int ret;
1457 struct ebt_replace tmp;
1458 struct ebt_table *t;
1459
1460 if (copy_from_user(&tmp, user, sizeof(tmp)))
1461 return -EFAULT;
1462
1463 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1464 if (!t)
1465 return ret;
1466
1467 switch(cmd) {
1468 case EBT_SO_GET_INFO:
1469 case EBT_SO_GET_INIT_INFO:
1470 if (*len != sizeof(struct ebt_replace)){
1471 ret = -EINVAL;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001472 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 break;
1474 }
1475 if (cmd == EBT_SO_GET_INFO) {
1476 tmp.nentries = t->private->nentries;
1477 tmp.entries_size = t->private->entries_size;
1478 tmp.valid_hooks = t->valid_hooks;
1479 } else {
1480 tmp.nentries = t->table->nentries;
1481 tmp.entries_size = t->table->entries_size;
1482 tmp.valid_hooks = t->table->valid_hooks;
1483 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001484 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 if (copy_to_user(user, &tmp, *len) != 0){
1486 BUGPRINT("c2u Didn't work\n");
1487 ret = -EFAULT;
1488 break;
1489 }
1490 ret = 0;
1491 break;
1492
1493 case EBT_SO_GET_ENTRIES:
1494 case EBT_SO_GET_INIT_ENTRIES:
1495 ret = copy_everything_to_user(t, user, len, cmd);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001496 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 break;
1498
1499 default:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001500 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 ret = -EINVAL;
1502 }
1503
1504 return ret;
1505}
1506
1507static struct nf_sockopt_ops ebt_sockopts =
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08001508{
1509 .pf = PF_INET,
1510 .set_optmin = EBT_BASE_CTL,
1511 .set_optmax = EBT_SO_SET_MAX + 1,
1512 .set = do_ebt_set_ctl,
1513 .get_optmin = EBT_BASE_CTL,
1514 .get_optmax = EBT_SO_GET_MAX + 1,
1515 .get = do_ebt_get_ctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516};
1517
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001518static int __init ebtables_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519{
1520 int ret;
1521
Ingo Molnar57b47a52006-03-20 22:35:41 -08001522 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001523 list_add(&ebt_standard_target.list, &ebt_targets);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001524 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
1526 return ret;
1527
1528 printk(KERN_NOTICE "Ebtables v2.0 registered\n");
1529 return 0;
1530}
1531
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001532static void __exit ebtables_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533{
1534 nf_unregister_sockopt(&ebt_sockopts);
1535 printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
1536}
1537
1538EXPORT_SYMBOL(ebt_register_table);
1539EXPORT_SYMBOL(ebt_unregister_table);
1540EXPORT_SYMBOL(ebt_register_match);
1541EXPORT_SYMBOL(ebt_unregister_match);
1542EXPORT_SYMBOL(ebt_register_watcher);
1543EXPORT_SYMBOL(ebt_unregister_watcher);
1544EXPORT_SYMBOL(ebt_register_target);
1545EXPORT_SYMBOL(ebt_unregister_target);
1546EXPORT_SYMBOL(ebt_do_table);
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001547module_init(ebtables_init);
1548module_exit(ebtables_fini);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549MODULE_LICENSE("GPL");