]> bbs.cooldavid.org Git - net-next-2.6.git/blame - net/bridge/netfilter/ebtables.c
[PATCH] Replace highest_possible_node_id() with nr_node_ids
[net-next-2.6.git] / net / bridge / netfilter / ebtables.c
CommitLineData
1da177e4
LT
1/*
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 */
1da177e4
LT
19#include <linux/tty.h>
20
21#include <linux/kmod.h>
22#include <linux/module.h>
23#include <linux/vmalloc.h>
24#include <linux/netfilter_bridge/ebtables.h>
25#include <linux/spinlock.h>
df0933dc 26#include <linux/mutex.h>
1da177e4
LT
27#include <asm/uaccess.h>
28#include <linux/smp.h>
c8923c6b 29#include <linux/cpumask.h>
1da177e4
LT
30#include <net/sock.h>
31/* needed for logical [in,out]-dev filtering */
32#include "../br_private.h"
33
1da177e4 34#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
9d6f229f 35 "report to author: "format, ## args)
1da177e4 36/* #define BUGPRINT(format, args...) */
1da177e4 37#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
9d6f229f 38 ": out of memory: "format, ## args)
1da177e4
LT
39/* #define MEMPRINT(format, args...) */
40
41
42
43/*
44 * Each cpu has its own set of counters, so there is no need for write_lock in
45 * the softirq
46 * For reading or updating the counters, the user context needs to
47 * get a write_lock
48 */
49
50/* The size of each set of counters is altered to get cache alignment */
51#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
52#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
53#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
54 COUNTER_OFFSET(n) * cpu))
55
56
57
57b47a53 58static DEFINE_MUTEX(ebt_mutex);
1da177e4
LT
59static LIST_HEAD(ebt_tables);
60static LIST_HEAD(ebt_targets);
61static LIST_HEAD(ebt_matches);
62static LIST_HEAD(ebt_watchers);
63
64static struct ebt_target ebt_standard_target =
65{ {NULL, NULL}, EBT_STANDARD_TARGET, NULL, NULL, NULL, NULL};
66
67static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
68 const struct sk_buff *skb, unsigned int hooknr, const struct net_device *in,
69 const struct net_device *out)
70{
71 w->u.watcher->watcher(skb, hooknr, in, out, w->data,
72 w->watcher_size);
73 /* watchers don't give a verdict */
74 return 0;
75}
76
77static inline int ebt_do_match (struct ebt_entry_match *m,
78 const struct sk_buff *skb, const struct net_device *in,
79 const struct net_device *out)
80{
81 return m->u.match->match(skb, in, out, m->data,
82 m->match_size);
83}
84
85static inline int ebt_dev_check(char *entry, const struct net_device *device)
86{
87 int i = 0;
6f5b7ef6 88 const char *devname = device->name;
1da177e4
LT
89
90 if (*entry == '\0')
91 return 0;
92 if (!device)
93 return 1;
94 /* 1 is the wildcard token */
95 while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i])
96 i++;
97 return (devname[i] != entry[i] && entry[i] != 1);
98}
99
100#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
101/* process standard matches */
102static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
103 const struct net_device *in, const struct net_device *out)
104{
105 int verdict, i;
106
107 if (e->bitmask & EBT_802_3) {
108 if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
109 return 1;
110 } else if (!(e->bitmask & EBT_NOPROTO) &&
111 FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
112 return 1;
113
114 if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
115 return 1;
116 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
117 return 1;
118 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
119 e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN))
120 return 1;
121 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
122 e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT))
123 return 1;
124
125 if (e->bitmask & EBT_SOURCEMAC) {
126 verdict = 0;
127 for (i = 0; i < 6; i++)
128 verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
129 e->sourcemsk[i];
130 if (FWINV2(verdict != 0, EBT_ISOURCE) )
131 return 1;
132 }
133 if (e->bitmask & EBT_DESTMAC) {
134 verdict = 0;
135 for (i = 0; i < 6; i++)
136 verdict |= (h->h_dest[i] ^ e->destmac[i]) &
137 e->destmsk[i];
138 if (FWINV2(verdict != 0, EBT_IDEST) )
139 return 1;
140 }
141 return 0;
142}
143
144/* Do some firewalling */
145unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
146 const struct net_device *in, const struct net_device *out,
147 struct ebt_table *table)
148{
149 int i, nentries;
150 struct ebt_entry *point;
151 struct ebt_counter *counter_base, *cb_base;
152 struct ebt_entry_target *t;
153 int verdict, sp = 0;
154 struct ebt_chainstack *cs;
155 struct ebt_entries *chaininfo;
156 char *base;
157 struct ebt_table_info *private;
158
159 read_lock_bh(&table->lock);
160 private = table->private;
161 cb_base = COUNTER_BASE(private->counters, private->nentries,
162 smp_processor_id());
163 if (private->chainstack)
164 cs = private->chainstack[smp_processor_id()];
165 else
166 cs = NULL;
167 chaininfo = private->hook_entry[hook];
168 nentries = private->hook_entry[hook]->nentries;
169 point = (struct ebt_entry *)(private->hook_entry[hook]->data);
170 counter_base = cb_base + private->hook_entry[hook]->counter_offset;
171 /* base for chain jumps */
172 base = private->entries;
173 i = 0;
174 while (i < nentries) {
175 if (ebt_basic_match(point, eth_hdr(*pskb), in, out))
176 goto letscontinue;
177
178 if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0)
179 goto letscontinue;
180
181 /* increase counter */
182 (*(counter_base + i)).pcnt++;
183 (*(counter_base + i)).bcnt+=(**pskb).len;
184
185 /* these should only watch: not modify, nor tell us
186 what to do with the packet */
187 EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, hook, in,
188 out);
189
190 t = (struct ebt_entry_target *)
191 (((char *)point) + point->target_offset);
192 /* standard target */
193 if (!t->u.target->target)
194 verdict = ((struct ebt_standard_target *)t)->verdict;
195 else
196 verdict = t->u.target->target(pskb, hook,
197 in, out, t->data, t->target_size);
198 if (verdict == EBT_ACCEPT) {
199 read_unlock_bh(&table->lock);
200 return NF_ACCEPT;
201 }
202 if (verdict == EBT_DROP) {
203 read_unlock_bh(&table->lock);
204 return NF_DROP;
205 }
206 if (verdict == EBT_RETURN) {
207letsreturn:
208#ifdef CONFIG_NETFILTER_DEBUG
209 if (sp == 0) {
210 BUGPRINT("RETURN on base chain");
211 /* act like this is EBT_CONTINUE */
212 goto letscontinue;
213 }
214#endif
215 sp--;
216 /* put all the local variables right */
217 i = cs[sp].n;
218 chaininfo = cs[sp].chaininfo;
219 nentries = chaininfo->nentries;
220 point = cs[sp].e;
221 counter_base = cb_base +
222 chaininfo->counter_offset;
223 continue;
224 }
225 if (verdict == EBT_CONTINUE)
226 goto letscontinue;
227#ifdef CONFIG_NETFILTER_DEBUG
228 if (verdict < 0) {
229 BUGPRINT("bogus standard verdict\n");
230 read_unlock_bh(&table->lock);
231 return NF_DROP;
232 }
233#endif
234 /* jump to a udc */
235 cs[sp].n = i + 1;
236 cs[sp].chaininfo = chaininfo;
237 cs[sp].e = (struct ebt_entry *)
238 (((char *)point) + point->next_offset);
239 i = 0;
240 chaininfo = (struct ebt_entries *) (base + verdict);
241#ifdef CONFIG_NETFILTER_DEBUG
242 if (chaininfo->distinguisher) {
243 BUGPRINT("jump to non-chain\n");
244 read_unlock_bh(&table->lock);
245 return NF_DROP;
246 }
247#endif
248 nentries = chaininfo->nentries;
249 point = (struct ebt_entry *)chaininfo->data;
250 counter_base = cb_base + chaininfo->counter_offset;
251 sp++;
252 continue;
253letscontinue:
254 point = (struct ebt_entry *)
255 (((char *)point) + point->next_offset);
256 i++;
257 }
258
259 /* I actually like this :) */
260 if (chaininfo->policy == EBT_RETURN)
261 goto letsreturn;
262 if (chaininfo->policy == EBT_ACCEPT) {
263 read_unlock_bh(&table->lock);
264 return NF_ACCEPT;
265 }
266 read_unlock_bh(&table->lock);
267 return NF_DROP;
268}
269
270/* If it succeeds, returns element and locks mutex */
271static inline void *
272find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
57b47a53 273 struct mutex *mutex)
1da177e4 274{
df0933dc
PM
275 struct {
276 struct list_head list;
277 char name[EBT_FUNCTION_MAXNAMELEN];
278 } *e;
1da177e4 279
57b47a53 280 *error = mutex_lock_interruptible(mutex);
1da177e4
LT
281 if (*error != 0)
282 return NULL;
283
df0933dc
PM
284 list_for_each_entry(e, head, list) {
285 if (strcmp(e->name, name) == 0)
286 return e;
1da177e4 287 }
df0933dc
PM
288 *error = -ENOENT;
289 mutex_unlock(mutex);
290 return NULL;
1da177e4
LT
291}
292
293#ifndef CONFIG_KMOD
294#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
295#else
296static void *
297find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
57b47a53 298 int *error, struct mutex *mutex)
1da177e4
LT
299{
300 void *ret;
301
302 ret = find_inlist_lock_noload(head, name, error, mutex);
303 if (!ret) {
304 request_module("%s%s", prefix, name);
305 ret = find_inlist_lock_noload(head, name, error, mutex);
306 }
307 return ret;
308}
309#endif
310
311static inline struct ebt_table *
57b47a53 312find_table_lock(const char *name, int *error, struct mutex *mutex)
1da177e4
LT
313{
314 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex);
315}
316
317static inline struct ebt_match *
57b47a53 318find_match_lock(const char *name, int *error, struct mutex *mutex)
1da177e4
LT
319{
320 return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex);
321}
322
323static inline struct ebt_watcher *
57b47a53 324find_watcher_lock(const char *name, int *error, struct mutex *mutex)
1da177e4
LT
325{
326 return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex);
327}
328
329static inline struct ebt_target *
57b47a53 330find_target_lock(const char *name, int *error, struct mutex *mutex)
1da177e4
LT
331{
332 return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex);
333}
334
335static inline int
336ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
337 const char *name, unsigned int hookmask, unsigned int *cnt)
338{
339 struct ebt_match *match;
14197d54 340 size_t left = ((char *)e + e->watchers_offset) - (char *)m;
1da177e4
LT
341 int ret;
342
14197d54
AV
343 if (left < sizeof(struct ebt_entry_match) ||
344 left - sizeof(struct ebt_entry_match) < m->match_size)
1da177e4
LT
345 return -EINVAL;
346 match = find_match_lock(m->u.name, &ret, &ebt_mutex);
347 if (!match)
348 return ret;
349 m->u.match = match;
350 if (!try_module_get(match->me)) {
57b47a53 351 mutex_unlock(&ebt_mutex);
1da177e4
LT
352 return -ENOENT;
353 }
57b47a53 354 mutex_unlock(&ebt_mutex);
1da177e4
LT
355 if (match->check &&
356 match->check(name, hookmask, e, m->data, m->match_size) != 0) {
357 BUGPRINT("match->check failed\n");
358 module_put(match->me);
359 return -EINVAL;
360 }
361 (*cnt)++;
362 return 0;
363}
364
365static inline int
366ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
367 const char *name, unsigned int hookmask, unsigned int *cnt)
368{
369 struct ebt_watcher *watcher;
14197d54 370 size_t left = ((char *)e + e->target_offset) - (char *)w;
1da177e4
LT
371 int ret;
372
14197d54
AV
373 if (left < sizeof(struct ebt_entry_watcher) ||
374 left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
1da177e4
LT
375 return -EINVAL;
376 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
377 if (!watcher)
378 return ret;
379 w->u.watcher = watcher;
380 if (!try_module_get(watcher->me)) {
57b47a53 381 mutex_unlock(&ebt_mutex);
1da177e4
LT
382 return -ENOENT;
383 }
57b47a53 384 mutex_unlock(&ebt_mutex);
1da177e4
LT
385 if (watcher->check &&
386 watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) {
387 BUGPRINT("watcher->check failed\n");
388 module_put(watcher->me);
389 return -EINVAL;
390 }
391 (*cnt)++;
392 return 0;
393}
394
70fe9af4
AV
395static int ebt_verify_pointers(struct ebt_replace *repl,
396 struct ebt_table_info *newinfo)
1da177e4 397{
70fe9af4
AV
398 unsigned int limit = repl->entries_size;
399 unsigned int valid_hooks = repl->valid_hooks;
400 unsigned int offset = 0;
1da177e4
LT
401 int i;
402
e4fd77de
AV
403 for (i = 0; i < NF_BR_NUMHOOKS; i++)
404 newinfo->hook_entry[i] = NULL;
405
406 newinfo->entries_size = repl->entries_size;
407 newinfo->nentries = repl->nentries;
408
70fe9af4
AV
409 while (offset < limit) {
410 size_t left = limit - offset;
411 struct ebt_entry *e = (void *)newinfo->entries + offset;
bb2ef25c 412
70fe9af4 413 if (left < sizeof(unsigned int))
1da177e4 414 break;
70fe9af4
AV
415
416 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
417 if ((valid_hooks & (1 << i)) == 0)
418 continue;
1e419cd9
AV
419 if ((char __user *)repl->hook_entry[i] ==
420 repl->entries + offset)
70fe9af4
AV
421 break;
422 }
423
424 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
425 if (e->bitmask != 0) {
426 /* we make userspace set this right,
427 so there is no misunderstanding */
428 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
429 "in distinguisher\n");
430 return -EINVAL;
431 }
432 if (i != NF_BR_NUMHOOKS)
433 newinfo->hook_entry[i] = (struct ebt_entries *)e;
434 if (left < sizeof(struct ebt_entries))
435 break;
436 offset += sizeof(struct ebt_entries);
437 } else {
438 if (left < sizeof(struct ebt_entry))
439 break;
440 if (left < e->next_offset)
441 break;
442 offset += e->next_offset;
1da177e4 443 }
22b440bf 444 }
70fe9af4
AV
445 if (offset != limit) {
446 BUGPRINT("entries_size too small\n");
447 return -EINVAL;
448 }
e4fd77de
AV
449
450 /* check if all valid hooks have a chain */
451 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
452 if (!newinfo->hook_entry[i] &&
453 (valid_hooks & (1 << i))) {
454 BUGPRINT("Valid hook without chain\n");
455 return -EINVAL;
456 }
457 }
22b440bf 458 return 0;
22b440bf
AV
459}
460
461/*
462 * this one is very careful, as it is the first function
463 * to parse the userspace data
464 */
465static inline int
466ebt_check_entry_size_and_hooks(struct ebt_entry *e,
0e795531
AV
467 struct ebt_table_info *newinfo,
468 unsigned int *n, unsigned int *cnt,
469 unsigned int *totalcnt, unsigned int *udc_cnt)
22b440bf 470{
22b440bf
AV
471 int i;
472
473 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
0e795531 474 if ((void *)e == (void *)newinfo->hook_entry[i])
22b440bf
AV
475 break;
476 }
477 /* beginning of a new chain
478 if i == NF_BR_NUMHOOKS it must be a user defined chain */
479 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
1da177e4
LT
480 /* this checks if the previous chain has as many entries
481 as it said it has */
482 if (*n != *cnt) {
483 BUGPRINT("nentries does not equal the nr of entries "
9d6f229f 484 "in the chain\n");
1da177e4
LT
485 return -EINVAL;
486 }
1da177e4
LT
487 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
488 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
489 /* only RETURN from udc */
490 if (i != NF_BR_NUMHOOKS ||
491 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
492 BUGPRINT("bad policy\n");
493 return -EINVAL;
494 }
495 }
496 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
497 (*udc_cnt)++;
1da177e4
LT
498 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
499 BUGPRINT("counter_offset != totalcnt");
500 return -EINVAL;
501 }
502 *n = ((struct ebt_entries *)e)->nentries;
503 *cnt = 0;
504 return 0;
505 }
506 /* a plain old entry, heh */
507 if (sizeof(struct ebt_entry) > e->watchers_offset ||
508 e->watchers_offset > e->target_offset ||
509 e->target_offset >= e->next_offset) {
510 BUGPRINT("entry offsets not in right order\n");
511 return -EINVAL;
512 }
513 /* this is not checked anywhere else */
514 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
515 BUGPRINT("target size too small\n");
516 return -EINVAL;
517 }
1da177e4
LT
518 (*cnt)++;
519 (*totalcnt)++;
520 return 0;
521}
522
523struct ebt_cl_stack
524{
525 struct ebt_chainstack cs;
526 int from;
527 unsigned int hookmask;
528};
529
530/*
531 * we need these positions to check that the jumps to a different part of the
532 * entries is a jump to the beginning of a new chain.
533 */
534static inline int
535ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
177abc34 536 unsigned int *n, struct ebt_cl_stack *udc)
1da177e4
LT
537{
538 int i;
539
540 /* we're only interested in chain starts */
40642f95 541 if (e->bitmask)
1da177e4
LT
542 return 0;
543 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1da177e4
LT
544 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
545 break;
546 }
547 /* only care about udc */
548 if (i != NF_BR_NUMHOOKS)
549 return 0;
550
551 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
552 /* these initialisations are depended on later in check_chainloops() */
553 udc[*n].cs.n = 0;
554 udc[*n].hookmask = 0;
555
556 (*n)++;
557 return 0;
558}
559
560static inline int
561ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
562{
563 if (i && (*i)-- == 0)
564 return 1;
565 if (m->u.match->destroy)
566 m->u.match->destroy(m->data, m->match_size);
567 module_put(m->u.match->me);
568
569 return 0;
570}
571
572static inline int
573ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
574{
575 if (i && (*i)-- == 0)
576 return 1;
577 if (w->u.watcher->destroy)
578 w->u.watcher->destroy(w->data, w->watcher_size);
579 module_put(w->u.watcher->me);
580
581 return 0;
582}
583
584static inline int
585ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
586{
587 struct ebt_entry_target *t;
588
40642f95 589 if (e->bitmask == 0)
1da177e4
LT
590 return 0;
591 /* we're done */
592 if (cnt && (*cnt)-- == 0)
593 return 1;
594 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
595 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);
596 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
597 if (t->u.target->destroy)
598 t->u.target->destroy(t->data, t->target_size);
599 module_put(t->u.target->me);
600
601 return 0;
602}
603
604static inline int
605ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
f7da79d9 606 const char *name, unsigned int *cnt,
1da177e4
LT
607 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
608{
609 struct ebt_entry_target *t;
610 struct ebt_target *target;
611 unsigned int i, j, hook = 0, hookmask = 0;
44f9a2fd 612 size_t gap;
1da177e4
LT
613 int ret;
614
615 /* don't mess with the struct ebt_entries */
40642f95 616 if (e->bitmask == 0)
1da177e4
LT
617 return 0;
618
619 if (e->bitmask & ~EBT_F_MASK) {
620 BUGPRINT("Unknown flag for bitmask\n");
621 return -EINVAL;
622 }
623 if (e->invflags & ~EBT_INV_MASK) {
624 BUGPRINT("Unknown flag for inv bitmask\n");
625 return -EINVAL;
626 }
627 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
628 BUGPRINT("NOPROTO & 802_3 not allowed\n");
629 return -EINVAL;
630 }
631 /* what hook do we belong to? */
632 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
f7da79d9 633 if (!newinfo->hook_entry[i])
1da177e4
LT
634 continue;
635 if ((char *)newinfo->hook_entry[i] < (char *)e)
636 hook = i;
637 else
638 break;
639 }
640 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
641 a base chain */
642 if (i < NF_BR_NUMHOOKS)
643 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
644 else {
645 for (i = 0; i < udc_cnt; i++)
646 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
647 break;
648 if (i == 0)
649 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
650 else
651 hookmask = cl_s[i - 1].hookmask;
652 }
653 i = 0;
654 ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);
655 if (ret != 0)
656 goto cleanup_matches;
657 j = 0;
658 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
659 if (ret != 0)
660 goto cleanup_watchers;
661 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
44f9a2fd 662 gap = e->next_offset - e->target_offset;
1da177e4
LT
663 target = find_target_lock(t->u.name, &ret, &ebt_mutex);
664 if (!target)
665 goto cleanup_watchers;
666 if (!try_module_get(target->me)) {
57b47a53 667 mutex_unlock(&ebt_mutex);
1da177e4
LT
668 ret = -ENOENT;
669 goto cleanup_watchers;
670 }
57b47a53 671 mutex_unlock(&ebt_mutex);
1da177e4
LT
672
673 t->u.target = target;
674 if (t->u.target == &ebt_standard_target) {
14197d54 675 if (gap < sizeof(struct ebt_standard_target)) {
1da177e4
LT
676 BUGPRINT("Standard target size too big\n");
677 ret = -EFAULT;
678 goto cleanup_watchers;
679 }
680 if (((struct ebt_standard_target *)t)->verdict <
681 -NUM_STANDARD_TARGETS) {
682 BUGPRINT("Invalid standard target\n");
683 ret = -EFAULT;
684 goto cleanup_watchers;
685 }
14197d54 686 } else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
1da177e4
LT
687 (t->u.target->check &&
688 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
689 module_put(t->u.target->me);
690 ret = -EFAULT;
691 goto cleanup_watchers;
692 }
693 (*cnt)++;
694 return 0;
695cleanup_watchers:
696 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);
697cleanup_matches:
698 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i);
699 return ret;
700}
701
702/*
703 * checks for loops and sets the hook mask for udc
704 * the hook mask for udc tells us from which base chains the udc can be
705 * accessed. This mask is a parameter to the check() functions of the extensions
706 */
707static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
708 unsigned int udc_cnt, unsigned int hooknr, char *base)
709{
710 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
711 struct ebt_entry *e = (struct ebt_entry *)chain->data;
712 struct ebt_entry_target *t;
713
714 while (pos < nentries || chain_nr != -1) {
715 /* end of udc, go back one 'recursion' step */
716 if (pos == nentries) {
717 /* put back values of the time when this chain was called */
718 e = cl_s[chain_nr].cs.e;
719 if (cl_s[chain_nr].from != -1)
720 nentries =
721 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
722 else
723 nentries = chain->nentries;
724 pos = cl_s[chain_nr].cs.n;
725 /* make sure we won't see a loop that isn't one */
726 cl_s[chain_nr].cs.n = 0;
727 chain_nr = cl_s[chain_nr].from;
728 if (pos == nentries)
729 continue;
730 }
731 t = (struct ebt_entry_target *)
732 (((char *)e) + e->target_offset);
733 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
734 goto letscontinue;
735 if (e->target_offset + sizeof(struct ebt_standard_target) >
736 e->next_offset) {
737 BUGPRINT("Standard target size too big\n");
738 return -1;
739 }
740 verdict = ((struct ebt_standard_target *)t)->verdict;
741 if (verdict >= 0) { /* jump to another chain */
742 struct ebt_entries *hlp2 =
743 (struct ebt_entries *)(base + verdict);
744 for (i = 0; i < udc_cnt; i++)
745 if (hlp2 == cl_s[i].cs.chaininfo)
746 break;
747 /* bad destination or loop */
748 if (i == udc_cnt) {
749 BUGPRINT("bad destination\n");
750 return -1;
751 }
752 if (cl_s[i].cs.n) {
753 BUGPRINT("loop\n");
754 return -1;
755 }
98a0824a
AV
756 if (cl_s[i].hookmask & (1 << hooknr))
757 goto letscontinue;
758 /* this can't be 0, so the loop test is correct */
1da177e4
LT
759 cl_s[i].cs.n = pos + 1;
760 pos = 0;
761 cl_s[i].cs.e = ((void *)e + e->next_offset);
762 e = (struct ebt_entry *)(hlp2->data);
763 nentries = hlp2->nentries;
764 cl_s[i].from = chain_nr;
765 chain_nr = i;
766 /* this udc is accessible from the base chain for hooknr */
767 cl_s[i].hookmask |= (1 << hooknr);
768 continue;
769 }
770letscontinue:
771 e = (void *)e + e->next_offset;
772 pos++;
773 }
774 return 0;
775}
776
777/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
1bc2326c 778static int translate_table(char *name, struct ebt_table_info *newinfo)
1da177e4
LT
779{
780 unsigned int i, j, k, udc_cnt;
781 int ret;
782 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
783
784 i = 0;
1f072c96 785 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
1da177e4
LT
786 i++;
787 if (i == NF_BR_NUMHOOKS) {
788 BUGPRINT("No valid hooks specified\n");
789 return -EINVAL;
790 }
1f072c96 791 if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
1da177e4
LT
792 BUGPRINT("Chains don't start at beginning\n");
793 return -EINVAL;
794 }
795 /* make sure chains are ordered after each other in same order
796 as their corresponding hooks */
797 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
1f072c96 798 if (!newinfo->hook_entry[j])
1da177e4 799 continue;
1f072c96 800 if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
1da177e4
LT
801 BUGPRINT("Hook order must be followed\n");
802 return -EINVAL;
803 }
804 i = j;
805 }
806
1da177e4
LT
807 /* do some early checkings and initialize some things */
808 i = 0; /* holds the expected nr. of entries for the chain */
809 j = 0; /* holds the up to now counted entries for the chain */
810 k = 0; /* holds the total nr. of entries, should equal
9d6f229f 811 newinfo->nentries afterwards */
1da177e4
LT
812 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
813 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
0e795531
AV
814 ebt_check_entry_size_and_hooks, newinfo,
815 &i, &j, &k, &udc_cnt);
1da177e4
LT
816
817 if (ret != 0)
818 return ret;
819
820 if (i != j) {
821 BUGPRINT("nentries does not equal the nr of entries in the "
9d6f229f 822 "(last) chain\n");
1da177e4
LT
823 return -EINVAL;
824 }
825 if (k != newinfo->nentries) {
826 BUGPRINT("Total nentries is wrong\n");
827 return -EINVAL;
828 }
829
1da177e4
LT
830 /* get the location of the udc, put them in an array
831 while we're at it, allocate the chainstack */
832 if (udc_cnt) {
833 /* this will get free'd in do_replace()/ebt_register_table()
834 if an error occurs */
7ad4d2f6
J
835 newinfo->chainstack =
836 vmalloc((highest_possible_processor_id()+1)
9d6f229f 837 * sizeof(*(newinfo->chainstack)));
1da177e4
LT
838 if (!newinfo->chainstack)
839 return -ENOMEM;
6f912042 840 for_each_possible_cpu(i) {
1da177e4 841 newinfo->chainstack[i] =
18bc89aa 842 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
1da177e4
LT
843 if (!newinfo->chainstack[i]) {
844 while (i)
845 vfree(newinfo->chainstack[--i]);
846 vfree(newinfo->chainstack);
847 newinfo->chainstack = NULL;
848 return -ENOMEM;
849 }
850 }
851
18bc89aa 852 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
1da177e4
LT
853 if (!cl_s)
854 return -ENOMEM;
855 i = 0; /* the i'th udc */
856 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
177abc34 857 ebt_get_udc_positions, newinfo, &i, cl_s);
1da177e4
LT
858 /* sanity check */
859 if (i != udc_cnt) {
860 BUGPRINT("i != udc_cnt\n");
861 vfree(cl_s);
862 return -EFAULT;
863 }
864 }
865
866 /* Check for loops */
867 for (i = 0; i < NF_BR_NUMHOOKS; i++)
1f072c96 868 if (newinfo->hook_entry[i])
1da177e4
LT
869 if (check_chainloops(newinfo->hook_entry[i],
870 cl_s, udc_cnt, i, newinfo->entries)) {
68d31872 871 vfree(cl_s);
1da177e4
LT
872 return -EINVAL;
873 }
874
875