blob: bee558a41800e2700a4f00e84e06224f57d368b0 [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 Viroe4fd77d2006-11-30 19:26:35 -0800404 for (i = 0; i < NF_BR_NUMHOOKS; i++)
405 newinfo->hook_entry[i] = NULL;
406
407 newinfo->entries_size = repl->entries_size;
408 newinfo->nentries = repl->nentries;
409
Al Viro70fe9af2006-11-30 19:26:14 -0800410 while (offset < limit) {
411 size_t left = limit - offset;
412 struct ebt_entry *e = (void *)newinfo->entries + offset;
Al Virobb2ef252006-11-30 19:22:42 -0800413
Al Viro70fe9af2006-11-30 19:26:14 -0800414 if (left < sizeof(unsigned int))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 break;
Al Viro22b440b2006-11-30 19:25:51 -0800416
Al Viro70fe9af2006-11-30 19:26:14 -0800417 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
418 if ((valid_hooks & (1 << i)) == 0)
419 continue;
Al Viro1e419cd2006-11-30 19:28:48 -0800420 if ((char __user *)repl->hook_entry[i] ==
421 repl->entries + offset)
Al Viro70fe9af2006-11-30 19:26:14 -0800422 break;
423 }
424
425 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
426 if (e->bitmask != 0) {
427 /* we make userspace set this right,
428 so there is no misunderstanding */
429 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
430 "in distinguisher\n");
431 return -EINVAL;
432 }
433 if (i != NF_BR_NUMHOOKS)
434 newinfo->hook_entry[i] = (struct ebt_entries *)e;
435 if (left < sizeof(struct ebt_entries))
436 break;
437 offset += sizeof(struct ebt_entries);
438 } else {
439 if (left < sizeof(struct ebt_entry))
440 break;
441 if (left < e->next_offset)
442 break;
443 offset += e->next_offset;
444 }
445 }
446 if (offset != limit) {
447 BUGPRINT("entries_size too small\n");
448 return -EINVAL;
449 }
Al Viroe4fd77d2006-11-30 19:26:35 -0800450
451 /* check if all valid hooks have a chain */
452 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
453 if (!newinfo->hook_entry[i] &&
454 (valid_hooks & (1 << i))) {
455 BUGPRINT("Valid hook without chain\n");
456 return -EINVAL;
457 }
458 }
Al Viro70fe9af2006-11-30 19:26:14 -0800459 return 0;
Al Viro22b440b2006-11-30 19:25:51 -0800460}
461
462/*
463 * this one is very careful, as it is the first function
464 * to parse the userspace data
465 */
466static inline int
467ebt_check_entry_size_and_hooks(struct ebt_entry *e,
Al Viro0e795532006-11-30 19:27:13 -0800468 struct ebt_table_info *newinfo,
469 unsigned int *n, unsigned int *cnt,
470 unsigned int *totalcnt, unsigned int *udc_cnt)
Al Viro22b440b2006-11-30 19:25:51 -0800471{
Al Viro22b440b2006-11-30 19:25:51 -0800472 int i;
473
474 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Viro0e795532006-11-30 19:27:13 -0800475 if ((void *)e == (void *)newinfo->hook_entry[i])
Al Viro22b440b2006-11-30 19:25:51 -0800476 break;
477 }
478 /* beginning of a new chain
479 if i == NF_BR_NUMHOOKS it must be a user defined chain */
480 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 /* this checks if the previous chain has as many entries
482 as it said it has */
483 if (*n != *cnt) {
484 BUGPRINT("nentries does not equal the nr of entries "
485 "in the chain\n");
486 return -EINVAL;
487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
489 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
490 /* only RETURN from udc */
491 if (i != NF_BR_NUMHOOKS ||
492 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
493 BUGPRINT("bad policy\n");
494 return -EINVAL;
495 }
496 }
497 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
498 (*udc_cnt)++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
500 BUGPRINT("counter_offset != totalcnt");
501 return -EINVAL;
502 }
503 *n = ((struct ebt_entries *)e)->nentries;
504 *cnt = 0;
505 return 0;
506 }
507 /* a plain old entry, heh */
508 if (sizeof(struct ebt_entry) > e->watchers_offset ||
509 e->watchers_offset > e->target_offset ||
510 e->target_offset >= e->next_offset) {
511 BUGPRINT("entry offsets not in right order\n");
512 return -EINVAL;
513 }
514 /* this is not checked anywhere else */
515 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
516 BUGPRINT("target size too small\n");
517 return -EINVAL;
518 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 (*cnt)++;
520 (*totalcnt)++;
521 return 0;
522}
523
524struct ebt_cl_stack
525{
526 struct ebt_chainstack cs;
527 int from;
528 unsigned int hookmask;
529};
530
531/*
532 * we need these positions to check that the jumps to a different part of the
533 * entries is a jump to the beginning of a new chain.
534 */
535static inline int
536ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
Al Viro177abc32006-11-30 19:27:32 -0800537 unsigned int *n, struct ebt_cl_stack *udc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538{
539 int i;
540
541 /* we're only interested in chain starts */
Al Viro40642f92006-11-30 19:24:12 -0800542 if (e->bitmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 return 0;
544 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
546 break;
547 }
548 /* only care about udc */
549 if (i != NF_BR_NUMHOOKS)
550 return 0;
551
552 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
553 /* these initialisations are depended on later in check_chainloops() */
554 udc[*n].cs.n = 0;
555 udc[*n].hookmask = 0;
556
557 (*n)++;
558 return 0;
559}
560
561static inline int
562ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
563{
564 if (i && (*i)-- == 0)
565 return 1;
566 if (m->u.match->destroy)
567 m->u.match->destroy(m->data, m->match_size);
568 module_put(m->u.match->me);
569
570 return 0;
571}
572
573static inline int
574ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
575{
576 if (i && (*i)-- == 0)
577 return 1;
578 if (w->u.watcher->destroy)
579 w->u.watcher->destroy(w->data, w->watcher_size);
580 module_put(w->u.watcher->me);
581
582 return 0;
583}
584
585static inline int
586ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
587{
588 struct ebt_entry_target *t;
589
Al Viro40642f92006-11-30 19:24:12 -0800590 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 return 0;
592 /* we're done */
593 if (cnt && (*cnt)-- == 0)
594 return 1;
595 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
596 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);
597 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
598 if (t->u.target->destroy)
599 t->u.target->destroy(t->data, t->target_size);
600 module_put(t->u.target->me);
601
602 return 0;
603}
604
605static inline int
606ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
Al Virof7da79d2006-11-30 19:27:48 -0800607 const char *name, unsigned int *cnt,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
609{
610 struct ebt_entry_target *t;
611 struct ebt_target *target;
612 unsigned int i, j, hook = 0, hookmask = 0;
Al Viro14197d52006-11-30 19:25:21 -0800613 size_t gap = e->next_offset - e->target_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 int ret;
615
616 /* don't mess with the struct ebt_entries */
Al Viro40642f92006-11-30 19:24:12 -0800617 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 return 0;
619
620 if (e->bitmask & ~EBT_F_MASK) {
621 BUGPRINT("Unknown flag for bitmask\n");
622 return -EINVAL;
623 }
624 if (e->invflags & ~EBT_INV_MASK) {
625 BUGPRINT("Unknown flag for inv bitmask\n");
626 return -EINVAL;
627 }
628 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
629 BUGPRINT("NOPROTO & 802_3 not allowed\n");
630 return -EINVAL;
631 }
632 /* what hook do we belong to? */
633 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Virof7da79d2006-11-30 19:27:48 -0800634 if (!newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 continue;
636 if ((char *)newinfo->hook_entry[i] < (char *)e)
637 hook = i;
638 else
639 break;
640 }
641 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
642 a base chain */
643 if (i < NF_BR_NUMHOOKS)
644 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
645 else {
646 for (i = 0; i < udc_cnt; i++)
647 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
648 break;
649 if (i == 0)
650 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
651 else
652 hookmask = cl_s[i - 1].hookmask;
653 }
654 i = 0;
655 ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);
656 if (ret != 0)
657 goto cleanup_matches;
658 j = 0;
659 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
660 if (ret != 0)
661 goto cleanup_watchers;
662 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
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)) {
Ingo Molnar57b47a52006-03-20 22:35:41 -0800667 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 ret = -ENOENT;
669 goto cleanup_watchers;
670 }
Ingo Molnar57b47a52006-03-20 22:35:41 -0800671 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672
673 t->u.target = target;
674 if (t->u.target == &ebt_standard_target) {
Al Viro14197d52006-11-30 19:25:21 -0800675 if (gap < sizeof(struct ebt_standard_target)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 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 }
Al Viro14197d52006-11-30 19:25:21 -0800686 } else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 (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 }
Al Viro98a08242006-11-30 19:24:49 -0800756 if (cl_s[i].hookmask & (1 << hooknr))
757 goto letscontinue;
758 /* this can't be 0, so the loop test is correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 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 */
Al Viro1bc23262006-11-30 19:28:08 -0800778static int translate_table(char *name, struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779{
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;
Al Viro1f072c92006-11-30 19:26:53 -0800785 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 i++;
787 if (i == NF_BR_NUMHOOKS) {
788 BUGPRINT("No valid hooks specified\n");
789 return -EINVAL;
790 }
Al Viro1f072c92006-11-30 19:26:53 -0800791 if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 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++) {
Al Viro1f072c92006-11-30 19:26:53 -0800798 if (!newinfo->hook_entry[j])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 continue;
Al Viro1f072c92006-11-30 19:26:53 -0800800 if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 BUGPRINT("Hook order must be followed\n");
802 return -EINVAL;
803 }
804 i = j;
805 }
806
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 /* 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
811 newinfo->nentries afterwards */
812 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
813 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro0e795532006-11-30 19:27:13 -0800814 ebt_check_entry_size_and_hooks, newinfo,
815 &i, &j, &k, &udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
817 if (ret != 0)
818 return ret;
819
820 if (i != j) {
821 BUGPRINT("nentries does not equal the nr of entries in the "
822 "(last) chain\n");
823 return -EINVAL;
824 }
825 if (k != newinfo->nentries) {
826 BUGPRINT("Total nentries is wrong\n");
827 return -EINVAL;
828 }
829
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 /* 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 */
Jayachandran C7ad4d2f2006-04-11 17:25:38 -0700835 newinfo->chainstack =
836 vmalloc((highest_possible_processor_id()+1)
837 * sizeof(*(newinfo->chainstack)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 if (!newinfo->chainstack)
839 return -ENOMEM;
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700840 for_each_possible_cpu(i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 newinfo->chainstack[i] =
Jayachandran C18bc89a2006-04-20 00:14:49 -0700842 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 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
Jayachandran C18bc89a2006-04-20 00:14:49 -0700852 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 if (!cl_s)
854 return -ENOMEM;
855 i = 0; /* the i'th udc */
856 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro177abc32006-11-30 19:27:32 -0800857 ebt_get_udc_positions, newinfo, &i, cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 /* 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++)
Al Viro1f072c92006-11-30 19:26:53 -0800868 if (newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 if (check_chainloops(newinfo->hook_entry[i],
870 cl_s, udc_cnt, i, newinfo->entries)) {
James Lamanna68d31872005-06-22 22:12:57 -0700871 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 return -EINVAL;
873 }
874
875 /* we now know the following (along with E=mc²):
876 - the nr of entries in each chain is right
877 - the size of the allocated space is right
878 - all valid hooks have a corresponding chain
879 - there are no loops
880 - wrong data can still be on the level of a single entry
881 - could be there are jumps to places that are not the
882 beginning of a chain. This can only occur in chains that
883 are not accessible from any base chains, so we don't care. */
884
885 /* used to know what we need to clean up if something goes wrong */
886 i = 0;
887 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro1bc23262006-11-30 19:28:08 -0800888 ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 if (ret != 0) {
890 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
891 ebt_cleanup_entry, &i);
892 }
James Lamanna68d31872005-06-22 22:12:57 -0700893 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 return ret;
895}
896
897/* called under write_lock */
898static void get_counters(struct ebt_counter *oldcounters,
899 struct ebt_counter *counters, unsigned int nentries)
900{
901 int i, cpu;
902 struct ebt_counter *counter_base;
903
904 /* counters of cpu 0 */
905 memcpy(counters, oldcounters,
David S. Millerc8923c62005-10-13 14:41:23 -0700906 sizeof(struct ebt_counter) * nentries);
907
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 /* add other counters to those of cpu 0 */
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700909 for_each_possible_cpu(cpu) {
David S. Millerc8923c62005-10-13 14:41:23 -0700910 if (cpu == 0)
911 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
913 for (i = 0; i < nentries; i++) {
914 counters[i].pcnt += counter_base[i].pcnt;
915 counters[i].bcnt += counter_base[i].bcnt;
916 }
917 }
918}
919
920/* replace the table */
921static int do_replace(void __user *user, unsigned int len)
922{
923 int ret, i, countersize;
924 struct ebt_table_info *newinfo;
925 struct ebt_replace tmp;
926 struct ebt_table *t;
927 struct ebt_counter *counterstmp = NULL;
928 /* used to be able to unlock earlier */
929 struct ebt_table_info *table;
930
931 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
932 return -EFAULT;
933
934 if (len != sizeof(tmp) + tmp.entries_size) {
935 BUGPRINT("Wrong len argument\n");
936 return -EINVAL;
937 }
938
939 if (tmp.entries_size == 0) {
940 BUGPRINT("Entries_size never zero\n");
941 return -EINVAL;
942 }
Kirill Korotaevee4bb812006-02-04 02:16:56 -0800943 /* overflow check */
944 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
945 SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
946 return -ENOMEM;
947 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
948 return -ENOMEM;
949
David S. Millerc8923c62005-10-13 14:41:23 -0700950 countersize = COUNTER_OFFSET(tmp.nentries) *
951 (highest_possible_processor_id()+1);
Jayachandran C18bc89a2006-04-20 00:14:49 -0700952 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 if (!newinfo)
954 return -ENOMEM;
955
956 if (countersize)
957 memset(newinfo->counters, 0, countersize);
958
Kris Katterjohn8b3a7002006-01-11 15:56:43 -0800959 newinfo->entries = vmalloc(tmp.entries_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 if (!newinfo->entries) {
961 ret = -ENOMEM;
962 goto free_newinfo;
963 }
964 if (copy_from_user(
965 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
966 BUGPRINT("Couldn't copy entries from userspace\n");
967 ret = -EFAULT;
968 goto free_entries;
969 }
970
971 /* the user wants counters back
972 the check on the size is done later, when we have the lock */
973 if (tmp.num_counters) {
Jayachandran C18bc89a2006-04-20 00:14:49 -0700974 counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 if (!counterstmp) {
976 ret = -ENOMEM;
977 goto free_entries;
978 }
979 }
980 else
981 counterstmp = NULL;
982
983 /* this can get initialized by translate_table() */
984 newinfo->chainstack = NULL;
Al Viro1bc23262006-11-30 19:28:08 -0800985 ret = ebt_verify_pointers(&tmp, newinfo);
986 if (ret != 0)
987 goto free_counterstmp;
988
989 ret = translate_table(tmp.name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990
991 if (ret != 0)
992 goto free_counterstmp;
993
994 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
995 if (!t) {
996 ret = -ENOENT;
997 goto free_iterate;
998 }
999
1000 /* the table doesn't like it */
1001 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
1002 goto free_unlock;
1003
1004 if (tmp.num_counters && tmp.num_counters != t->private->nentries) {
1005 BUGPRINT("Wrong nr. of counters requested\n");
1006 ret = -EINVAL;
1007 goto free_unlock;
1008 }
1009
1010 /* we have the mutex lock, so no danger in reading this pointer */
1011 table = t->private;
1012 /* make sure the table can only be rmmod'ed if it contains no rules */
1013 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
1014 ret = -ENOENT;
1015 goto free_unlock;
1016 } else if (table->nentries && !newinfo->nentries)
1017 module_put(t->me);
1018 /* we need an atomic snapshot of the counters */
1019 write_lock_bh(&t->lock);
1020 if (tmp.num_counters)
1021 get_counters(t->private->counters, counterstmp,
1022 t->private->nentries);
1023
1024 t->private = newinfo;
1025 write_unlock_bh(&t->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001026 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 /* so, a user can change the chains while having messed up her counter
1028 allocation. Only reason why this is done is because this way the lock
1029 is held only once, while this doesn't bring the kernel into a
1030 dangerous state. */
1031 if (tmp.num_counters &&
1032 copy_to_user(tmp.counters, counterstmp,
1033 tmp.num_counters * sizeof(struct ebt_counter))) {
1034 BUGPRINT("Couldn't copy counters to userspace\n");
1035 ret = -EFAULT;
1036 }
1037 else
1038 ret = 0;
1039
1040 /* decrease module count and free resources */
1041 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
1042 ebt_cleanup_entry, NULL);
1043
1044 vfree(table->entries);
1045 if (table->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001046 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 vfree(table->chainstack[i]);
1048 vfree(table->chainstack);
1049 }
1050 vfree(table);
1051
James Lamanna68d31872005-06-22 22:12:57 -07001052 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 return ret;
1054
1055free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001056 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057free_iterate:
1058 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1059 ebt_cleanup_entry, NULL);
1060free_counterstmp:
James Lamanna68d31872005-06-22 22:12:57 -07001061 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 /* can be initialized in translate_table() */
1063 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001064 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 vfree(newinfo->chainstack[i]);
1066 vfree(newinfo->chainstack);
1067 }
1068free_entries:
James Lamanna68d31872005-06-22 22:12:57 -07001069 vfree(newinfo->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070free_newinfo:
James Lamanna68d31872005-06-22 22:12:57 -07001071 vfree(newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 return ret;
1073}
1074
1075int ebt_register_target(struct ebt_target *target)
1076{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001077 struct ebt_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 int ret;
1079
Ingo Molnar57b47a52006-03-20 22:35:41 -08001080 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 if (ret != 0)
1082 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001083 list_for_each_entry(t, &ebt_targets, list) {
1084 if (strcmp(t->name, target->name) == 0) {
1085 mutex_unlock(&ebt_mutex);
1086 return -EEXIST;
1087 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001089 list_add(&target->list, &ebt_targets);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001090 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
1092 return 0;
1093}
1094
1095void ebt_unregister_target(struct ebt_target *target)
1096{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001097 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001098 list_del(&target->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001099 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100}
1101
1102int ebt_register_match(struct ebt_match *match)
1103{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001104 struct ebt_match *m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 int ret;
1106
Ingo Molnar57b47a52006-03-20 22:35:41 -08001107 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 if (ret != 0)
1109 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001110 list_for_each_entry(m, &ebt_matches, list) {
1111 if (strcmp(m->name, match->name) == 0) {
1112 mutex_unlock(&ebt_mutex);
1113 return -EEXIST;
1114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001116 list_add(&match->list, &ebt_matches);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001117 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
1119 return 0;
1120}
1121
1122void ebt_unregister_match(struct ebt_match *match)
1123{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001124 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001125 list_del(&match->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001126 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127}
1128
1129int ebt_register_watcher(struct ebt_watcher *watcher)
1130{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001131 struct ebt_watcher *w;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 int ret;
1133
Ingo Molnar57b47a52006-03-20 22:35:41 -08001134 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 if (ret != 0)
1136 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001137 list_for_each_entry(w, &ebt_watchers, list) {
1138 if (strcmp(w->name, watcher->name) == 0) {
1139 mutex_unlock(&ebt_mutex);
1140 return -EEXIST;
1141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001143 list_add(&watcher->list, &ebt_watchers);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001144 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
1146 return 0;
1147}
1148
1149void ebt_unregister_watcher(struct ebt_watcher *watcher)
1150{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001151 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001152 list_del(&watcher->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001153 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154}
1155
1156int ebt_register_table(struct ebt_table *table)
1157{
1158 struct ebt_table_info *newinfo;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001159 struct ebt_table *t;
Al Viro1e419cd2006-11-30 19:28:48 -08001160 struct ebt_replace_kernel *repl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 int ret, i, countersize;
Al Virodf07a812006-11-30 19:28:25 -08001162 void *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
Al Virodf07a812006-11-30 19:28:25 -08001164 if (!table || !(repl = table->table) || !repl->entries ||
1165 repl->entries_size == 0 ||
1166 repl->counters || table->private) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1168 return -EINVAL;
1169 }
1170
Al Virodf07a812006-11-30 19:28:25 -08001171 countersize = COUNTER_OFFSET(repl->nentries) *
David S. Millerc8923c62005-10-13 14:41:23 -07001172 (highest_possible_processor_id()+1);
Jayachandran C18bc89a2006-04-20 00:14:49 -07001173 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 ret = -ENOMEM;
1175 if (!newinfo)
1176 return -ENOMEM;
1177
Al Virodf07a812006-11-30 19:28:25 -08001178 p = vmalloc(repl->entries_size);
1179 if (!p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 goto free_newinfo;
1181
Al Virodf07a812006-11-30 19:28:25 -08001182 memcpy(p, repl->entries, repl->entries_size);
1183 newinfo->entries = p;
1184
1185 newinfo->entries_size = repl->entries_size;
1186 newinfo->nentries = repl->nentries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187
1188 if (countersize)
1189 memset(newinfo->counters, 0, countersize);
1190
1191 /* fill in newinfo and parse the entries */
1192 newinfo->chainstack = NULL;
Al Virodf07a812006-11-30 19:28:25 -08001193 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1194 if ((repl->valid_hooks & (1 << i)) == 0)
1195 newinfo->hook_entry[i] = NULL;
1196 else
1197 newinfo->hook_entry[i] = p +
1198 ((char *)repl->hook_entry[i] - repl->entries);
1199 }
1200 ret = translate_table(repl->name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 if (ret != 0) {
1202 BUGPRINT("Translate_table failed\n");
1203 goto free_chainstack;
1204 }
1205
1206 if (table->check && table->check(newinfo, table->valid_hooks)) {
1207 BUGPRINT("The table doesn't like its own initial data, lol\n");
1208 return -EINVAL;
1209 }
1210
1211 table->private = newinfo;
1212 rwlock_init(&table->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001213 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 if (ret != 0)
1215 goto free_chainstack;
1216
Patrick McHardydf0933d2006-09-20 11:57:53 -07001217 list_for_each_entry(t, &ebt_tables, list) {
1218 if (strcmp(t->name, table->name) == 0) {
1219 ret = -EEXIST;
1220 BUGPRINT("Table name already exists\n");
1221 goto free_unlock;
1222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 }
1224
1225 /* Hold a reference count if the chains aren't empty */
1226 if (newinfo->nentries && !try_module_get(table->me)) {
1227 ret = -ENOENT;
1228 goto free_unlock;
1229 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001230 list_add(&table->list, &ebt_tables);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001231 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 return 0;
1233free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001234 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235free_chainstack:
1236 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001237 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 vfree(newinfo->chainstack[i]);
1239 vfree(newinfo->chainstack);
1240 }
1241 vfree(newinfo->entries);
1242free_newinfo:
1243 vfree(newinfo);
1244 return ret;
1245}
1246
1247void ebt_unregister_table(struct ebt_table *table)
1248{
1249 int i;
1250
1251 if (!table) {
1252 BUGPRINT("Request to unregister NULL table!!!\n");
1253 return;
1254 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001255 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001256 list_del(&table->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001257 mutex_unlock(&ebt_mutex);
James Lamanna68d31872005-06-22 22:12:57 -07001258 vfree(table->private->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 if (table->private->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001260 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 vfree(table->private->chainstack[i]);
1262 vfree(table->private->chainstack);
1263 }
1264 vfree(table->private);
1265}
1266
1267/* userspace just supplied us with counters */
1268static int update_counters(void __user *user, unsigned int len)
1269{
1270 int i, ret;
1271 struct ebt_counter *tmp;
1272 struct ebt_replace hlp;
1273 struct ebt_table *t;
1274
1275 if (copy_from_user(&hlp, user, sizeof(hlp)))
1276 return -EFAULT;
1277
1278 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1279 return -EINVAL;
1280 if (hlp.num_counters == 0)
1281 return -EINVAL;
1282
Jayachandran C18bc89a2006-04-20 00:14:49 -07001283 if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 MEMPRINT("Update_counters && nomemory\n");
1285 return -ENOMEM;
1286 }
1287
1288 t = find_table_lock(hlp.name, &ret, &ebt_mutex);
1289 if (!t)
1290 goto free_tmp;
1291
1292 if (hlp.num_counters != t->private->nentries) {
1293 BUGPRINT("Wrong nr of counters\n");
1294 ret = -EINVAL;
1295 goto unlock_mutex;
1296 }
1297
1298 if ( copy_from_user(tmp, hlp.counters,
1299 hlp.num_counters * sizeof(struct ebt_counter)) ) {
1300 BUGPRINT("Updata_counters && !cfu\n");
1301 ret = -EFAULT;
1302 goto unlock_mutex;
1303 }
1304
1305 /* we want an atomic add of the counters */
1306 write_lock_bh(&t->lock);
1307
1308 /* we add to the counters of the first cpu */
1309 for (i = 0; i < hlp.num_counters; i++) {
1310 t->private->counters[i].pcnt += tmp[i].pcnt;
1311 t->private->counters[i].bcnt += tmp[i].bcnt;
1312 }
1313
1314 write_unlock_bh(&t->lock);
1315 ret = 0;
1316unlock_mutex:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001317 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318free_tmp:
1319 vfree(tmp);
1320 return ret;
1321}
1322
1323static inline int ebt_make_matchname(struct ebt_entry_match *m,
Al Viro1e419cd2006-11-30 19:28:48 -08001324 char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325{
Al Viro1e419cd2006-11-30 19:28:48 -08001326 char __user *hlp = ubase + ((char *)m - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1328 return -EFAULT;
1329 return 0;
1330}
1331
1332static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
Al Viro1e419cd2006-11-30 19:28:48 -08001333 char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334{
Al Viro1e419cd2006-11-30 19:28:48 -08001335 char __user *hlp = ubase + ((char *)w - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1337 return -EFAULT;
1338 return 0;
1339}
1340
Al Viro1e419cd2006-11-30 19:28:48 -08001341static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342{
1343 int ret;
Al Viro1e419cd2006-11-30 19:28:48 -08001344 char __user *hlp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 struct ebt_entry_target *t;
1346
Al Viro40642f92006-11-30 19:24:12 -08001347 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 return 0;
1349
Al Viro1e419cd2006-11-30 19:28:48 -08001350 hlp = ubase + (((char *)e + e->target_offset) - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
1352
1353 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1354 if (ret != 0)
1355 return ret;
1356 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1357 if (ret != 0)
1358 return ret;
1359 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1360 return -EFAULT;
1361 return 0;
1362}
1363
Ingo Molnar57b47a52006-03-20 22:35:41 -08001364/* called with ebt_mutex locked */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1366 int *len, int cmd)
1367{
1368 struct ebt_replace tmp;
1369 struct ebt_counter *counterstmp, *oldcounters;
1370 unsigned int entries_size, nentries;
1371 char *entries;
1372
1373 if (cmd == EBT_SO_GET_ENTRIES) {
1374 entries_size = t->private->entries_size;
1375 nentries = t->private->nentries;
1376 entries = t->private->entries;
1377 oldcounters = t->private->counters;
1378 } else {
1379 entries_size = t->table->entries_size;
1380 nentries = t->table->nentries;
1381 entries = t->table->entries;
1382 oldcounters = t->table->counters;
1383 }
1384
1385 if (copy_from_user(&tmp, user, sizeof(tmp))) {
1386 BUGPRINT("Cfu didn't work\n");
1387 return -EFAULT;
1388 }
1389
1390 if (*len != sizeof(struct ebt_replace) + entries_size +
1391 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
1392 BUGPRINT("Wrong size\n");
1393 return -EINVAL;
1394 }
1395
1396 if (tmp.nentries != nentries) {
1397 BUGPRINT("Nentries wrong\n");
1398 return -EINVAL;
1399 }
1400
1401 if (tmp.entries_size != entries_size) {
1402 BUGPRINT("Wrong size\n");
1403 return -EINVAL;
1404 }
1405
1406 /* userspace might not need the counters */
1407 if (tmp.num_counters) {
1408 if (tmp.num_counters != nentries) {
1409 BUGPRINT("Num_counters wrong\n");
1410 return -EINVAL;
1411 }
Jayachandran C18bc89a2006-04-20 00:14:49 -07001412 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 if (!counterstmp) {
1414 MEMPRINT("Couldn't copy counters, out of memory\n");
1415 return -ENOMEM;
1416 }
1417 write_lock_bh(&t->lock);
1418 get_counters(oldcounters, counterstmp, nentries);
1419 write_unlock_bh(&t->lock);
1420
1421 if (copy_to_user(tmp.counters, counterstmp,
1422 nentries * sizeof(struct ebt_counter))) {
1423 BUGPRINT("Couldn't copy counters to userspace\n");
1424 vfree(counterstmp);
1425 return -EFAULT;
1426 }
1427 vfree(counterstmp);
1428 }
1429
1430 if (copy_to_user(tmp.entries, entries, entries_size)) {
1431 BUGPRINT("Couldn't copy entries to userspace\n");
1432 return -EFAULT;
1433 }
1434 /* set the match/watcher/target names right */
1435 return EBT_ENTRY_ITERATE(entries, entries_size,
1436 ebt_make_names, entries, tmp.entries);
1437}
1438
1439static int do_ebt_set_ctl(struct sock *sk,
1440 int cmd, void __user *user, unsigned int len)
1441{
1442 int ret;
1443
1444 switch(cmd) {
1445 case EBT_SO_SET_ENTRIES:
1446 ret = do_replace(user, len);
1447 break;
1448 case EBT_SO_SET_COUNTERS:
1449 ret = update_counters(user, len);
1450 break;
1451 default:
1452 ret = -EINVAL;
1453 }
1454 return ret;
1455}
1456
1457static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1458{
1459 int ret;
1460 struct ebt_replace tmp;
1461 struct ebt_table *t;
1462
1463 if (copy_from_user(&tmp, user, sizeof(tmp)))
1464 return -EFAULT;
1465
1466 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1467 if (!t)
1468 return ret;
1469
1470 switch(cmd) {
1471 case EBT_SO_GET_INFO:
1472 case EBT_SO_GET_INIT_INFO:
1473 if (*len != sizeof(struct ebt_replace)){
1474 ret = -EINVAL;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001475 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 break;
1477 }
1478 if (cmd == EBT_SO_GET_INFO) {
1479 tmp.nentries = t->private->nentries;
1480 tmp.entries_size = t->private->entries_size;
1481 tmp.valid_hooks = t->valid_hooks;
1482 } else {
1483 tmp.nentries = t->table->nentries;
1484 tmp.entries_size = t->table->entries_size;
1485 tmp.valid_hooks = t->table->valid_hooks;
1486 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001487 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 if (copy_to_user(user, &tmp, *len) != 0){
1489 BUGPRINT("c2u Didn't work\n");
1490 ret = -EFAULT;
1491 break;
1492 }
1493 ret = 0;
1494 break;
1495
1496 case EBT_SO_GET_ENTRIES:
1497 case EBT_SO_GET_INIT_ENTRIES:
1498 ret = copy_everything_to_user(t, user, len, cmd);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001499 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 break;
1501
1502 default:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001503 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 ret = -EINVAL;
1505 }
1506
1507 return ret;
1508}
1509
1510static struct nf_sockopt_ops ebt_sockopts =
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08001511{
1512 .pf = PF_INET,
1513 .set_optmin = EBT_BASE_CTL,
1514 .set_optmax = EBT_SO_SET_MAX + 1,
1515 .set = do_ebt_set_ctl,
1516 .get_optmin = EBT_BASE_CTL,
1517 .get_optmax = EBT_SO_GET_MAX + 1,
1518 .get = do_ebt_get_ctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519};
1520
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001521static int __init ebtables_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522{
1523 int ret;
1524
Ingo Molnar57b47a52006-03-20 22:35:41 -08001525 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001526 list_add(&ebt_standard_target.list, &ebt_targets);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001527 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
1529 return ret;
1530
1531 printk(KERN_NOTICE "Ebtables v2.0 registered\n");
1532 return 0;
1533}
1534
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001535static void __exit ebtables_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536{
1537 nf_unregister_sockopt(&ebt_sockopts);
1538 printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
1539}
1540
1541EXPORT_SYMBOL(ebt_register_table);
1542EXPORT_SYMBOL(ebt_unregister_table);
1543EXPORT_SYMBOL(ebt_register_match);
1544EXPORT_SYMBOL(ebt_unregister_match);
1545EXPORT_SYMBOL(ebt_register_watcher);
1546EXPORT_SYMBOL(ebt_unregister_watcher);
1547EXPORT_SYMBOL(ebt_register_target);
1548EXPORT_SYMBOL(ebt_unregister_target);
1549EXPORT_SYMBOL(ebt_do_table);
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001550module_init(ebtables_init);
1551module_exit(ebtables_fini);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552MODULE_LICENSE("GPL");