blob: b04e288d20f2a25358d782b84fc80c3e3a45ab63 [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
19#include <linux/kmod.h>
20#include <linux/module.h>
21#include <linux/vmalloc.h>
Jan Engelhardt18219d32008-10-08 11:35:13 +020022#include <linux/netfilter/x_tables.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include <linux/netfilter_bridge/ebtables.h>
24#include <linux/spinlock.h>
Patrick McHardydf0933d2006-09-20 11:57:53 -070025#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/uaccess.h>
27#include <linux/smp.h>
David S. Millerc8923c62005-10-13 14:41:23 -070028#include <linux/cpumask.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <net/sock.h>
30/* needed for logical [in,out]-dev filtering */
31#include "../br_private.h"
32
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +090034 "report to author: "format, ## args)
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/* #define BUGPRINT(format, args...) */
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +090037 ": out of memory: "format, ## args)
Linus Torvalds1da177e2005-04-16 15:20:36 -070038/* #define MEMPRINT(format, args...) */
39
40
41
42/*
43 * Each cpu has its own set of counters, so there is no need for write_lock in
44 * the softirq
45 * For reading or updating the counters, the user context needs to
46 * get a write_lock
47 */
48
49/* The size of each set of counters is altered to get cache alignment */
50#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
51#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
52#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
53 COUNTER_OFFSET(n) * cpu))
54
55
56
Ingo Molnar57b47a52006-03-20 22:35:41 -080057static DEFINE_MUTEX(ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058static LIST_HEAD(ebt_tables);
59static LIST_HEAD(ebt_targets);
60static LIST_HEAD(ebt_matches);
61static LIST_HEAD(ebt_watchers);
62
Jan Engelhardt18219d32008-10-08 11:35:13 +020063static struct ebt_target ebt_standard_target = {
64 .name = "standard",
65};
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
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;
Meelis Roos6f5b7ef2006-11-01 18:07:27 -080088 const char *devname = device->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
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 */
Herbert Xu3db05fe2007-10-15 00:53:15 -0700145unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 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) {
Herbert Xu3db05fe2007-10-15 00:53:15 -0700175 if (ebt_basic_match(point, eth_hdr(skb), in, out))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 goto letscontinue;
177
Herbert Xu3db05fe2007-10-15 00:53:15 -0700178 if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, in, out) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 goto letscontinue;
180
181 /* increase counter */
182 (*(counter_base + i)).pcnt++;
Herbert Xu3db05fe2007-10-15 00:53:15 -0700183 (*(counter_base + i)).bcnt += skb->len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
185 /* these should only watch: not modify, nor tell us
186 what to do with the packet */
Herbert Xu3db05fe2007-10-15 00:53:15 -0700187 EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, hook, in,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 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
Herbert Xu3db05fe2007-10-15 00:53:15 -0700196 verdict = t->u.target->target(skb, hook,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 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,
Ingo Molnar57b47a52006-03-20 22:35:41 -0800273 struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274{
Patrick McHardydf0933d2006-09-20 11:57:53 -0700275 struct {
276 struct list_head list;
277 char name[EBT_FUNCTION_MAXNAMELEN];
278 } *e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Ingo Molnar57b47a52006-03-20 22:35:41 -0800280 *error = mutex_lock_interruptible(mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 if (*error != 0)
282 return NULL;
283
Patrick McHardydf0933d2006-09-20 11:57:53 -0700284 list_for_each_entry(e, head, list) {
285 if (strcmp(e->name, name) == 0)
286 return e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 }
Patrick McHardydf0933d2006-09-20 11:57:53 -0700288 *error = -ENOENT;
289 mutex_unlock(mutex);
290 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291}
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,
Ingo Molnar57b47a52006-03-20 22:35:41 -0800298 int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299{
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 *
Ingo Molnar57b47a52006-03-20 22:35:41 -0800312find_table_lock(const char *name, int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313{
314 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex);
315}
316
317static inline struct ebt_match *
Ingo Molnar57b47a52006-03-20 22:35:41 -0800318find_match_lock(const char *name, int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319{
320 return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex);
321}
322
323static inline struct ebt_watcher *
Ingo Molnar57b47a52006-03-20 22:35:41 -0800324find_watcher_lock(const char *name, int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325{
326 return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex);
327}
328
329static inline struct ebt_target *
Ingo Molnar57b47a52006-03-20 22:35:41 -0800330find_target_lock(const char *name, int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331{
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;
Al Viro14197d52006-11-30 19:25:21 -0800340 size_t left = ((char *)e + e->watchers_offset) - (char *)m;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 int ret;
342
Al Viro14197d52006-11-30 19:25:21 -0800343 if (left < sizeof(struct ebt_entry_match) ||
344 left - sizeof(struct ebt_entry_match) < m->match_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 return -EINVAL;
346 match = find_match_lock(m->u.name, &ret, &ebt_mutex);
347 if (!match)
348 return ret;
349 m->u.match = match;
350 if (!try_module_get(match->me)) {
Ingo Molnar57b47a52006-03-20 22:35:41 -0800351 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 return -ENOENT;
353 }
Ingo Molnar57b47a52006-03-20 22:35:41 -0800354 mutex_unlock(&ebt_mutex);
Jan Engelhardt18219d32008-10-08 11:35:13 +0200355 if (XT_ALIGN(match->matchsize) != m->match_size &&
356 match->matchsize != -1) {
357 /*
358 * ebt_among is exempt from centralized matchsize checking
359 * because it uses a dynamic-size data set.
360 */
361 printk(KERN_WARNING "ebtables: %s match: "
362 "invalid size %Zu != %u\n",
363 match->name, XT_ALIGN(match->matchsize), m->match_size);
364 module_put(match->me);
365 return -EINVAL;
366 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 if (match->check &&
368 match->check(name, hookmask, e, m->data, m->match_size) != 0) {
369 BUGPRINT("match->check failed\n");
370 module_put(match->me);
371 return -EINVAL;
372 }
373 (*cnt)++;
374 return 0;
375}
376
377static inline int
378ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
379 const char *name, unsigned int hookmask, unsigned int *cnt)
380{
381 struct ebt_watcher *watcher;
Al Viro14197d52006-11-30 19:25:21 -0800382 size_t left = ((char *)e + e->target_offset) - (char *)w;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 int ret;
384
Al Viro14197d52006-11-30 19:25:21 -0800385 if (left < sizeof(struct ebt_entry_watcher) ||
386 left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 return -EINVAL;
388 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
389 if (!watcher)
390 return ret;
391 w->u.watcher = watcher;
392 if (!try_module_get(watcher->me)) {
Ingo Molnar57b47a52006-03-20 22:35:41 -0800393 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 return -ENOENT;
395 }
Ingo Molnar57b47a52006-03-20 22:35:41 -0800396 mutex_unlock(&ebt_mutex);
Jan Engelhardt18219d32008-10-08 11:35:13 +0200397 if (XT_ALIGN(watcher->targetsize) != w->watcher_size) {
398 printk(KERN_WARNING "ebtables: %s watcher: "
399 "invalid size %Zu != %u\n",
400 watcher->name, XT_ALIGN(watcher->targetsize),
401 w->watcher_size);
402 module_put(watcher->me);
403 return -EINVAL;
404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 if (watcher->check &&
406 watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) {
407 BUGPRINT("watcher->check failed\n");
408 module_put(watcher->me);
409 return -EINVAL;
410 }
411 (*cnt)++;
412 return 0;
413}
414
Al Viro70fe9af2006-11-30 19:26:14 -0800415static int ebt_verify_pointers(struct ebt_replace *repl,
416 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417{
Al Viro70fe9af2006-11-30 19:26:14 -0800418 unsigned int limit = repl->entries_size;
419 unsigned int valid_hooks = repl->valid_hooks;
420 unsigned int offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 int i;
422
Al Viroe4fd77d2006-11-30 19:26:35 -0800423 for (i = 0; i < NF_BR_NUMHOOKS; i++)
424 newinfo->hook_entry[i] = NULL;
425
426 newinfo->entries_size = repl->entries_size;
427 newinfo->nentries = repl->nentries;
428
Al Viro70fe9af2006-11-30 19:26:14 -0800429 while (offset < limit) {
430 size_t left = limit - offset;
431 struct ebt_entry *e = (void *)newinfo->entries + offset;
Al Virobb2ef252006-11-30 19:22:42 -0800432
Al Viro70fe9af2006-11-30 19:26:14 -0800433 if (left < sizeof(unsigned int))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 break;
Al Viro22b440b2006-11-30 19:25:51 -0800435
Al Viro70fe9af2006-11-30 19:26:14 -0800436 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
437 if ((valid_hooks & (1 << i)) == 0)
438 continue;
Al Viro1e419cd2006-11-30 19:28:48 -0800439 if ((char __user *)repl->hook_entry[i] ==
440 repl->entries + offset)
Al Viro70fe9af2006-11-30 19:26:14 -0800441 break;
442 }
443
444 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
445 if (e->bitmask != 0) {
446 /* we make userspace set this right,
447 so there is no misunderstanding */
448 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
449 "in distinguisher\n");
450 return -EINVAL;
451 }
452 if (i != NF_BR_NUMHOOKS)
453 newinfo->hook_entry[i] = (struct ebt_entries *)e;
454 if (left < sizeof(struct ebt_entries))
455 break;
456 offset += sizeof(struct ebt_entries);
457 } else {
458 if (left < sizeof(struct ebt_entry))
459 break;
460 if (left < e->next_offset)
461 break;
462 offset += e->next_offset;
463 }
464 }
465 if (offset != limit) {
466 BUGPRINT("entries_size too small\n");
467 return -EINVAL;
468 }
Al Viroe4fd77d2006-11-30 19:26:35 -0800469
470 /* check if all valid hooks have a chain */
471 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
472 if (!newinfo->hook_entry[i] &&
473 (valid_hooks & (1 << i))) {
474 BUGPRINT("Valid hook without chain\n");
475 return -EINVAL;
476 }
477 }
Al Viro70fe9af2006-11-30 19:26:14 -0800478 return 0;
Al Viro22b440b2006-11-30 19:25:51 -0800479}
480
481/*
482 * this one is very careful, as it is the first function
483 * to parse the userspace data
484 */
485static inline int
486ebt_check_entry_size_and_hooks(struct ebt_entry *e,
Al Viro0e795532006-11-30 19:27:13 -0800487 struct ebt_table_info *newinfo,
488 unsigned int *n, unsigned int *cnt,
489 unsigned int *totalcnt, unsigned int *udc_cnt)
Al Viro22b440b2006-11-30 19:25:51 -0800490{
Al Viro22b440b2006-11-30 19:25:51 -0800491 int i;
492
493 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Viro0e795532006-11-30 19:27:13 -0800494 if ((void *)e == (void *)newinfo->hook_entry[i])
Al Viro22b440b2006-11-30 19:25:51 -0800495 break;
496 }
497 /* beginning of a new chain
498 if i == NF_BR_NUMHOOKS it must be a user defined chain */
499 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 /* this checks if the previous chain has as many entries
501 as it said it has */
502 if (*n != *cnt) {
503 BUGPRINT("nentries does not equal the nr of entries "
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900504 "in the chain\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 return -EINVAL;
506 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
508 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
509 /* only RETURN from udc */
510 if (i != NF_BR_NUMHOOKS ||
511 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
512 BUGPRINT("bad policy\n");
513 return -EINVAL;
514 }
515 }
516 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
517 (*udc_cnt)++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
519 BUGPRINT("counter_offset != totalcnt");
520 return -EINVAL;
521 }
522 *n = ((struct ebt_entries *)e)->nentries;
523 *cnt = 0;
524 return 0;
525 }
526 /* a plain old entry, heh */
527 if (sizeof(struct ebt_entry) > e->watchers_offset ||
528 e->watchers_offset > e->target_offset ||
529 e->target_offset >= e->next_offset) {
530 BUGPRINT("entry offsets not in right order\n");
531 return -EINVAL;
532 }
533 /* this is not checked anywhere else */
534 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
535 BUGPRINT("target size too small\n");
536 return -EINVAL;
537 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 (*cnt)++;
539 (*totalcnt)++;
540 return 0;
541}
542
543struct ebt_cl_stack
544{
545 struct ebt_chainstack cs;
546 int from;
547 unsigned int hookmask;
548};
549
550/*
551 * we need these positions to check that the jumps to a different part of the
552 * entries is a jump to the beginning of a new chain.
553 */
554static inline int
555ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
Al Viro177abc32006-11-30 19:27:32 -0800556 unsigned int *n, struct ebt_cl_stack *udc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557{
558 int i;
559
560 /* we're only interested in chain starts */
Al Viro40642f92006-11-30 19:24:12 -0800561 if (e->bitmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 return 0;
563 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
565 break;
566 }
567 /* only care about udc */
568 if (i != NF_BR_NUMHOOKS)
569 return 0;
570
571 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
572 /* these initialisations are depended on later in check_chainloops() */
573 udc[*n].cs.n = 0;
574 udc[*n].hookmask = 0;
575
576 (*n)++;
577 return 0;
578}
579
580static inline int
581ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
582{
583 if (i && (*i)-- == 0)
584 return 1;
585 if (m->u.match->destroy)
586 m->u.match->destroy(m->data, m->match_size);
587 module_put(m->u.match->me);
588
589 return 0;
590}
591
592static inline int
593ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
594{
595 if (i && (*i)-- == 0)
596 return 1;
597 if (w->u.watcher->destroy)
598 w->u.watcher->destroy(w->data, w->watcher_size);
599 module_put(w->u.watcher->me);
600
601 return 0;
602}
603
604static inline int
605ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
606{
607 struct ebt_entry_target *t;
608
Al Viro40642f92006-11-30 19:24:12 -0800609 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 return 0;
611 /* we're done */
612 if (cnt && (*cnt)-- == 0)
613 return 1;
614 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
615 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);
616 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
617 if (t->u.target->destroy)
618 t->u.target->destroy(t->data, t->target_size);
619 module_put(t->u.target->me);
620
621 return 0;
622}
623
624static inline int
625ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
Al Virof7da79d2006-11-30 19:27:48 -0800626 const char *name, unsigned int *cnt,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
628{
629 struct ebt_entry_target *t;
630 struct ebt_target *target;
631 unsigned int i, j, hook = 0, hookmask = 0;
Chuck Ebbert44f9a2f2007-01-04 12:17:44 -0800632 size_t gap;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 int ret;
634
635 /* don't mess with the struct ebt_entries */
Al Viro40642f92006-11-30 19:24:12 -0800636 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 return 0;
638
639 if (e->bitmask & ~EBT_F_MASK) {
640 BUGPRINT("Unknown flag for bitmask\n");
641 return -EINVAL;
642 }
643 if (e->invflags & ~EBT_INV_MASK) {
644 BUGPRINT("Unknown flag for inv bitmask\n");
645 return -EINVAL;
646 }
647 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
648 BUGPRINT("NOPROTO & 802_3 not allowed\n");
649 return -EINVAL;
650 }
651 /* what hook do we belong to? */
652 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Virof7da79d2006-11-30 19:27:48 -0800653 if (!newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 continue;
655 if ((char *)newinfo->hook_entry[i] < (char *)e)
656 hook = i;
657 else
658 break;
659 }
660 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
661 a base chain */
662 if (i < NF_BR_NUMHOOKS)
663 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
664 else {
665 for (i = 0; i < udc_cnt; i++)
666 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
667 break;
668 if (i == 0)
669 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
670 else
671 hookmask = cl_s[i - 1].hookmask;
672 }
673 i = 0;
674 ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);
675 if (ret != 0)
676 goto cleanup_matches;
677 j = 0;
678 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
679 if (ret != 0)
680 goto cleanup_watchers;
681 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
Chuck Ebbert44f9a2f2007-01-04 12:17:44 -0800682 gap = e->next_offset - e->target_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 target = find_target_lock(t->u.name, &ret, &ebt_mutex);
684 if (!target)
685 goto cleanup_watchers;
686 if (!try_module_get(target->me)) {
Ingo Molnar57b47a52006-03-20 22:35:41 -0800687 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 ret = -ENOENT;
689 goto cleanup_watchers;
690 }
Ingo Molnar57b47a52006-03-20 22:35:41 -0800691 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
693 t->u.target = target;
694 if (t->u.target == &ebt_standard_target) {
Al Viro14197d52006-11-30 19:25:21 -0800695 if (gap < sizeof(struct ebt_standard_target)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 BUGPRINT("Standard target size too big\n");
697 ret = -EFAULT;
698 goto cleanup_watchers;
699 }
700 if (((struct ebt_standard_target *)t)->verdict <
701 -NUM_STANDARD_TARGETS) {
702 BUGPRINT("Invalid standard target\n");
703 ret = -EFAULT;
704 goto cleanup_watchers;
705 }
Jan Engelhardt18219d32008-10-08 11:35:13 +0200706 } else if (t->target_size > gap - sizeof(struct ebt_entry_target)) {
707 module_put(t->u.target->me);
708 ret = -EFAULT;
709 goto cleanup_watchers;
710 } else if (XT_ALIGN(target->targetsize) != t->target_size) {
711 printk(KERN_WARNING "ebtables: %s target: "
712 "invalid size %Zu != %u\n",
713 target->name, XT_ALIGN(target->targetsize),
714 t->target_size);
715 module_put(t->u.target->me);
716 ret = -EINVAL;
717 goto cleanup_watchers;
718 } else if (t->u.target->check &&
719 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 module_put(t->u.target->me);
721 ret = -EFAULT;
722 goto cleanup_watchers;
723 }
724 (*cnt)++;
725 return 0;
726cleanup_watchers:
727 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);
728cleanup_matches:
729 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i);
730 return ret;
731}
732
733/*
734 * checks for loops and sets the hook mask for udc
735 * the hook mask for udc tells us from which base chains the udc can be
736 * accessed. This mask is a parameter to the check() functions of the extensions
737 */
738static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
739 unsigned int udc_cnt, unsigned int hooknr, char *base)
740{
741 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
742 struct ebt_entry *e = (struct ebt_entry *)chain->data;
743 struct ebt_entry_target *t;
744
745 while (pos < nentries || chain_nr != -1) {
746 /* end of udc, go back one 'recursion' step */
747 if (pos == nentries) {
748 /* put back values of the time when this chain was called */
749 e = cl_s[chain_nr].cs.e;
750 if (cl_s[chain_nr].from != -1)
751 nentries =
752 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
753 else
754 nentries = chain->nentries;
755 pos = cl_s[chain_nr].cs.n;
756 /* make sure we won't see a loop that isn't one */
757 cl_s[chain_nr].cs.n = 0;
758 chain_nr = cl_s[chain_nr].from;
759 if (pos == nentries)
760 continue;
761 }
762 t = (struct ebt_entry_target *)
763 (((char *)e) + e->target_offset);
764 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
765 goto letscontinue;
766 if (e->target_offset + sizeof(struct ebt_standard_target) >
767 e->next_offset) {
768 BUGPRINT("Standard target size too big\n");
769 return -1;
770 }
771 verdict = ((struct ebt_standard_target *)t)->verdict;
772 if (verdict >= 0) { /* jump to another chain */
773 struct ebt_entries *hlp2 =
774 (struct ebt_entries *)(base + verdict);
775 for (i = 0; i < udc_cnt; i++)
776 if (hlp2 == cl_s[i].cs.chaininfo)
777 break;
778 /* bad destination or loop */
779 if (i == udc_cnt) {
780 BUGPRINT("bad destination\n");
781 return -1;
782 }
783 if (cl_s[i].cs.n) {
784 BUGPRINT("loop\n");
785 return -1;
786 }
Al Viro98a08242006-11-30 19:24:49 -0800787 if (cl_s[i].hookmask & (1 << hooknr))
788 goto letscontinue;
789 /* this can't be 0, so the loop test is correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 cl_s[i].cs.n = pos + 1;
791 pos = 0;
792 cl_s[i].cs.e = ((void *)e + e->next_offset);
793 e = (struct ebt_entry *)(hlp2->data);
794 nentries = hlp2->nentries;
795 cl_s[i].from = chain_nr;
796 chain_nr = i;
797 /* this udc is accessible from the base chain for hooknr */
798 cl_s[i].hookmask |= (1 << hooknr);
799 continue;
800 }
801letscontinue:
802 e = (void *)e + e->next_offset;
803 pos++;
804 }
805 return 0;
806}
807
808/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
Al Viro1bc23262006-11-30 19:28:08 -0800809static int translate_table(char *name, struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810{
811 unsigned int i, j, k, udc_cnt;
812 int ret;
813 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
814
815 i = 0;
Al Viro1f072c92006-11-30 19:26:53 -0800816 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 i++;
818 if (i == NF_BR_NUMHOOKS) {
819 BUGPRINT("No valid hooks specified\n");
820 return -EINVAL;
821 }
Al Viro1f072c92006-11-30 19:26:53 -0800822 if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 BUGPRINT("Chains don't start at beginning\n");
824 return -EINVAL;
825 }
826 /* make sure chains are ordered after each other in same order
827 as their corresponding hooks */
828 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
Al Viro1f072c92006-11-30 19:26:53 -0800829 if (!newinfo->hook_entry[j])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 continue;
Al Viro1f072c92006-11-30 19:26:53 -0800831 if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 BUGPRINT("Hook order must be followed\n");
833 return -EINVAL;
834 }
835 i = j;
836 }
837
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 /* do some early checkings and initialize some things */
839 i = 0; /* holds the expected nr. of entries for the chain */
840 j = 0; /* holds the up to now counted entries for the chain */
841 k = 0; /* holds the total nr. of entries, should equal
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900842 newinfo->nentries afterwards */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
844 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro0e795532006-11-30 19:27:13 -0800845 ebt_check_entry_size_and_hooks, newinfo,
846 &i, &j, &k, &udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847
848 if (ret != 0)
849 return ret;
850
851 if (i != j) {
852 BUGPRINT("nentries does not equal the nr of entries in the "
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900853 "(last) chain\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 return -EINVAL;
855 }
856 if (k != newinfo->nentries) {
857 BUGPRINT("Total nentries is wrong\n");
858 return -EINVAL;
859 }
860
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 /* get the location of the udc, put them in an array
862 while we're at it, allocate the chainstack */
863 if (udc_cnt) {
864 /* this will get free'd in do_replace()/ebt_register_table()
865 if an error occurs */
Jayachandran C7ad4d2f2006-04-11 17:25:38 -0700866 newinfo->chainstack =
Christoph Lameter53b8a312007-02-20 13:57:51 -0800867 vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 if (!newinfo->chainstack)
869 return -ENOMEM;
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700870 for_each_possible_cpu(i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 newinfo->chainstack[i] =
Jayachandran C18bc89a2006-04-20 00:14:49 -0700872 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 if (!newinfo->chainstack[i]) {
874 while (i)
875 vfree(newinfo->chainstack[--i]);
876 vfree(newinfo->chainstack);
877 newinfo->chainstack = NULL;
878 return -ENOMEM;
879 }
880 }
881
Jayachandran C18bc89a2006-04-20 00:14:49 -0700882 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 if (!cl_s)
884 return -ENOMEM;
885 i = 0; /* the i'th udc */
886 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro177abc32006-11-30 19:27:32 -0800887 ebt_get_udc_positions, newinfo, &i, cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 /* sanity check */
889 if (i != udc_cnt) {
890 BUGPRINT("i != udc_cnt\n");
891 vfree(cl_s);
892 return -EFAULT;
893 }
894 }
895
896 /* Check for loops */
897 for (i = 0; i < NF_BR_NUMHOOKS; i++)
Al Viro1f072c92006-11-30 19:26:53 -0800898 if (newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 if (check_chainloops(newinfo->hook_entry[i],
900 cl_s, udc_cnt, i, newinfo->entries)) {
James Lamanna68d31872005-06-22 22:12:57 -0700901 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 return -EINVAL;
903 }
904
Jan Engelhardt96de0e22007-10-19 23:21:04 +0200905 /* we now know the following (along with E=mc²):
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 - the nr of entries in each chain is right
907 - the size of the allocated space is right
908 - all valid hooks have a corresponding chain
909 - there are no loops
910 - wrong data can still be on the level of a single entry
911 - could be there are jumps to places that are not the
912 beginning of a chain. This can only occur in chains that
913 are not accessible from any base chains, so we don't care. */
914
915 /* used to know what we need to clean up if something goes wrong */
916 i = 0;
917 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro1bc23262006-11-30 19:28:08 -0800918 ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 if (ret != 0) {
920 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
921 ebt_cleanup_entry, &i);
922 }
James Lamanna68d31872005-06-22 22:12:57 -0700923 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 return ret;
925}
926
927/* called under write_lock */
928static void get_counters(struct ebt_counter *oldcounters,
929 struct ebt_counter *counters, unsigned int nentries)
930{
931 int i, cpu;
932 struct ebt_counter *counter_base;
933
934 /* counters of cpu 0 */
935 memcpy(counters, oldcounters,
David S. Millerc8923c62005-10-13 14:41:23 -0700936 sizeof(struct ebt_counter) * nentries);
937
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 /* add other counters to those of cpu 0 */
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700939 for_each_possible_cpu(cpu) {
David S. Millerc8923c62005-10-13 14:41:23 -0700940 if (cpu == 0)
941 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
943 for (i = 0; i < nentries; i++) {
944 counters[i].pcnt += counter_base[i].pcnt;
945 counters[i].bcnt += counter_base[i].bcnt;
946 }
947 }
948}
949
950/* replace the table */
951static int do_replace(void __user *user, unsigned int len)
952{
953 int ret, i, countersize;
954 struct ebt_table_info *newinfo;
955 struct ebt_replace tmp;
956 struct ebt_table *t;
957 struct ebt_counter *counterstmp = NULL;
958 /* used to be able to unlock earlier */
959 struct ebt_table_info *table;
960
961 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
962 return -EFAULT;
963
964 if (len != sizeof(tmp) + tmp.entries_size) {
965 BUGPRINT("Wrong len argument\n");
966 return -EINVAL;
967 }
968
969 if (tmp.entries_size == 0) {
970 BUGPRINT("Entries_size never zero\n");
971 return -EINVAL;
972 }
Kirill Korotaevee4bb812006-02-04 02:16:56 -0800973 /* overflow check */
974 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
975 SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
976 return -ENOMEM;
977 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
978 return -ENOMEM;
979
Christoph Lameter53b8a312007-02-20 13:57:51 -0800980 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
Jayachandran C18bc89a2006-04-20 00:14:49 -0700981 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 if (!newinfo)
983 return -ENOMEM;
984
985 if (countersize)
986 memset(newinfo->counters, 0, countersize);
987
Kris Katterjohn8b3a7002006-01-11 15:56:43 -0800988 newinfo->entries = vmalloc(tmp.entries_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 if (!newinfo->entries) {
990 ret = -ENOMEM;
991 goto free_newinfo;
992 }
993 if (copy_from_user(
994 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
995 BUGPRINT("Couldn't copy entries from userspace\n");
996 ret = -EFAULT;
997 goto free_entries;
998 }
999
1000 /* the user wants counters back
1001 the check on the size is done later, when we have the lock */
1002 if (tmp.num_counters) {
Jayachandran C18bc89a2006-04-20 00:14:49 -07001003 counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 if (!counterstmp) {
1005 ret = -ENOMEM;
1006 goto free_entries;
1007 }
1008 }
1009 else
1010 counterstmp = NULL;
1011
1012 /* this can get initialized by translate_table() */
1013 newinfo->chainstack = NULL;
Al Viro1bc23262006-11-30 19:28:08 -08001014 ret = ebt_verify_pointers(&tmp, newinfo);
1015 if (ret != 0)
1016 goto free_counterstmp;
1017
1018 ret = translate_table(tmp.name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
1020 if (ret != 0)
1021 goto free_counterstmp;
1022
1023 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1024 if (!t) {
1025 ret = -ENOENT;
1026 goto free_iterate;
1027 }
1028
1029 /* the table doesn't like it */
1030 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
1031 goto free_unlock;
1032
1033 if (tmp.num_counters && tmp.num_counters != t->private->nentries) {
1034 BUGPRINT("Wrong nr. of counters requested\n");
1035 ret = -EINVAL;
1036 goto free_unlock;
1037 }
1038
1039 /* we have the mutex lock, so no danger in reading this pointer */
1040 table = t->private;
1041 /* make sure the table can only be rmmod'ed if it contains no rules */
1042 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
1043 ret = -ENOENT;
1044 goto free_unlock;
1045 } else if (table->nentries && !newinfo->nentries)
1046 module_put(t->me);
1047 /* we need an atomic snapshot of the counters */
1048 write_lock_bh(&t->lock);
1049 if (tmp.num_counters)
1050 get_counters(t->private->counters, counterstmp,
1051 t->private->nentries);
1052
1053 t->private = newinfo;
1054 write_unlock_bh(&t->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001055 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 /* so, a user can change the chains while having messed up her counter
1057 allocation. Only reason why this is done is because this way the lock
1058 is held only once, while this doesn't bring the kernel into a
1059 dangerous state. */
1060 if (tmp.num_counters &&
1061 copy_to_user(tmp.counters, counterstmp,
1062 tmp.num_counters * sizeof(struct ebt_counter))) {
1063 BUGPRINT("Couldn't copy counters to userspace\n");
1064 ret = -EFAULT;
1065 }
1066 else
1067 ret = 0;
1068
1069 /* decrease module count and free resources */
1070 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
1071 ebt_cleanup_entry, NULL);
1072
1073 vfree(table->entries);
1074 if (table->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001075 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 vfree(table->chainstack[i]);
1077 vfree(table->chainstack);
1078 }
1079 vfree(table);
1080
James Lamanna68d31872005-06-22 22:12:57 -07001081 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 return ret;
1083
1084free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001085 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086free_iterate:
1087 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1088 ebt_cleanup_entry, NULL);
1089free_counterstmp:
James Lamanna68d31872005-06-22 22:12:57 -07001090 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 /* can be initialized in translate_table() */
1092 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001093 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 vfree(newinfo->chainstack[i]);
1095 vfree(newinfo->chainstack);
1096 }
1097free_entries:
James Lamanna68d31872005-06-22 22:12:57 -07001098 vfree(newinfo->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099free_newinfo:
James Lamanna68d31872005-06-22 22:12:57 -07001100 vfree(newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 return ret;
1102}
1103
1104int ebt_register_target(struct ebt_target *target)
1105{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001106 struct ebt_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 int ret;
1108
Ingo Molnar57b47a52006-03-20 22:35:41 -08001109 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 if (ret != 0)
1111 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001112 list_for_each_entry(t, &ebt_targets, list) {
1113 if (strcmp(t->name, target->name) == 0) {
1114 mutex_unlock(&ebt_mutex);
1115 return -EEXIST;
1116 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001118 list_add(&target->list, &ebt_targets);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001119 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
1121 return 0;
1122}
1123
1124void ebt_unregister_target(struct ebt_target *target)
1125{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001126 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001127 list_del(&target->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001128 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129}
1130
1131int ebt_register_match(struct ebt_match *match)
1132{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001133 struct ebt_match *m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 int ret;
1135
Ingo Molnar57b47a52006-03-20 22:35:41 -08001136 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 if (ret != 0)
1138 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001139 list_for_each_entry(m, &ebt_matches, list) {
1140 if (strcmp(m->name, match->name) == 0) {
1141 mutex_unlock(&ebt_mutex);
1142 return -EEXIST;
1143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001145 list_add(&match->list, &ebt_matches);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001146 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
1148 return 0;
1149}
1150
1151void ebt_unregister_match(struct ebt_match *match)
1152{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001153 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001154 list_del(&match->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001155 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156}
1157
1158int ebt_register_watcher(struct ebt_watcher *watcher)
1159{
Patrick McHardydf0933d2006-09-20 11:57:53 -07001160 struct ebt_watcher *w;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 int ret;
1162
Ingo Molnar57b47a52006-03-20 22:35:41 -08001163 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 if (ret != 0)
1165 return ret;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001166 list_for_each_entry(w, &ebt_watchers, list) {
1167 if (strcmp(w->name, watcher->name) == 0) {
1168 mutex_unlock(&ebt_mutex);
1169 return -EEXIST;
1170 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001172 list_add(&watcher->list, &ebt_watchers);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001173 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
1175 return 0;
1176}
1177
1178void ebt_unregister_watcher(struct ebt_watcher *watcher)
1179{
Ingo Molnar57b47a52006-03-20 22:35:41 -08001180 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001181 list_del(&watcher->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001182 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183}
1184
1185int ebt_register_table(struct ebt_table *table)
1186{
1187 struct ebt_table_info *newinfo;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001188 struct ebt_table *t;
Al Viro1e419cd2006-11-30 19:28:48 -08001189 struct ebt_replace_kernel *repl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 int ret, i, countersize;
Al Virodf07a812006-11-30 19:28:25 -08001191 void *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192
Al Virodf07a812006-11-30 19:28:25 -08001193 if (!table || !(repl = table->table) || !repl->entries ||
1194 repl->entries_size == 0 ||
1195 repl->counters || table->private) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1197 return -EINVAL;
1198 }
1199
Christoph Lameter53b8a312007-02-20 13:57:51 -08001200 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
Jayachandran C18bc89a2006-04-20 00:14:49 -07001201 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 ret = -ENOMEM;
1203 if (!newinfo)
1204 return -ENOMEM;
1205
Al Virodf07a812006-11-30 19:28:25 -08001206 p = vmalloc(repl->entries_size);
1207 if (!p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 goto free_newinfo;
1209
Al Virodf07a812006-11-30 19:28:25 -08001210 memcpy(p, repl->entries, repl->entries_size);
1211 newinfo->entries = p;
1212
1213 newinfo->entries_size = repl->entries_size;
1214 newinfo->nentries = repl->nentries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
1216 if (countersize)
1217 memset(newinfo->counters, 0, countersize);
1218
1219 /* fill in newinfo and parse the entries */
1220 newinfo->chainstack = NULL;
Al Virodf07a812006-11-30 19:28:25 -08001221 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1222 if ((repl->valid_hooks & (1 << i)) == 0)
1223 newinfo->hook_entry[i] = NULL;
1224 else
1225 newinfo->hook_entry[i] = p +
1226 ((char *)repl->hook_entry[i] - repl->entries);
1227 }
1228 ret = translate_table(repl->name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 if (ret != 0) {
1230 BUGPRINT("Translate_table failed\n");
1231 goto free_chainstack;
1232 }
1233
1234 if (table->check && table->check(newinfo, table->valid_hooks)) {
1235 BUGPRINT("The table doesn't like its own initial data, lol\n");
1236 return -EINVAL;
1237 }
1238
1239 table->private = newinfo;
1240 rwlock_init(&table->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001241 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 if (ret != 0)
1243 goto free_chainstack;
1244
Patrick McHardydf0933d2006-09-20 11:57:53 -07001245 list_for_each_entry(t, &ebt_tables, list) {
1246 if (strcmp(t->name, table->name) == 0) {
1247 ret = -EEXIST;
1248 BUGPRINT("Table name already exists\n");
1249 goto free_unlock;
1250 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 }
1252
1253 /* Hold a reference count if the chains aren't empty */
1254 if (newinfo->nentries && !try_module_get(table->me)) {
1255 ret = -ENOENT;
1256 goto free_unlock;
1257 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001258 list_add(&table->list, &ebt_tables);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001259 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 return 0;
1261free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001262 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263free_chainstack:
1264 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001265 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 vfree(newinfo->chainstack[i]);
1267 vfree(newinfo->chainstack);
1268 }
1269 vfree(newinfo->entries);
1270free_newinfo:
1271 vfree(newinfo);
1272 return ret;
1273}
1274
1275void ebt_unregister_table(struct ebt_table *table)
1276{
1277 int i;
1278
1279 if (!table) {
1280 BUGPRINT("Request to unregister NULL table!!!\n");
1281 return;
1282 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001283 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001284 list_del(&table->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001285 mutex_unlock(&ebt_mutex);
James Lamanna68d31872005-06-22 22:12:57 -07001286 vfree(table->private->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 if (table->private->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001288 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 vfree(table->private->chainstack[i]);
1290 vfree(table->private->chainstack);
1291 }
1292 vfree(table->private);
1293}
1294
1295/* userspace just supplied us with counters */
1296static int update_counters(void __user *user, unsigned int len)
1297{
1298 int i, ret;
1299 struct ebt_counter *tmp;
1300 struct ebt_replace hlp;
1301 struct ebt_table *t;
1302
1303 if (copy_from_user(&hlp, user, sizeof(hlp)))
1304 return -EFAULT;
1305
1306 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1307 return -EINVAL;
1308 if (hlp.num_counters == 0)
1309 return -EINVAL;
1310
Jayachandran C18bc89a2006-04-20 00:14:49 -07001311 if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 MEMPRINT("Update_counters && nomemory\n");
1313 return -ENOMEM;
1314 }
1315
1316 t = find_table_lock(hlp.name, &ret, &ebt_mutex);
1317 if (!t)
1318 goto free_tmp;
1319
1320 if (hlp.num_counters != t->private->nentries) {
1321 BUGPRINT("Wrong nr of counters\n");
1322 ret = -EINVAL;
1323 goto unlock_mutex;
1324 }
1325
1326 if ( copy_from_user(tmp, hlp.counters,
1327 hlp.num_counters * sizeof(struct ebt_counter)) ) {
1328 BUGPRINT("Updata_counters && !cfu\n");
1329 ret = -EFAULT;
1330 goto unlock_mutex;
1331 }
1332
1333 /* we want an atomic add of the counters */
1334 write_lock_bh(&t->lock);
1335
1336 /* we add to the counters of the first cpu */
1337 for (i = 0; i < hlp.num_counters; i++) {
1338 t->private->counters[i].pcnt += tmp[i].pcnt;
1339 t->private->counters[i].bcnt += tmp[i].bcnt;
1340 }
1341
1342 write_unlock_bh(&t->lock);
1343 ret = 0;
1344unlock_mutex:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001345 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346free_tmp:
1347 vfree(tmp);
1348 return ret;
1349}
1350
1351static inline int ebt_make_matchname(struct ebt_entry_match *m,
Al Viro1e419cd2006-11-30 19:28:48 -08001352 char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353{
Al Viro1e419cd2006-11-30 19:28:48 -08001354 char __user *hlp = ubase + ((char *)m - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1356 return -EFAULT;
1357 return 0;
1358}
1359
1360static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
Al Viro1e419cd2006-11-30 19:28:48 -08001361 char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362{
Al Viro1e419cd2006-11-30 19:28:48 -08001363 char __user *hlp = ubase + ((char *)w - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1365 return -EFAULT;
1366 return 0;
1367}
1368
Al Viro1e419cd2006-11-30 19:28:48 -08001369static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370{
1371 int ret;
Al Viro1e419cd2006-11-30 19:28:48 -08001372 char __user *hlp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 struct ebt_entry_target *t;
1374
Al Viro40642f92006-11-30 19:24:12 -08001375 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 return 0;
1377
Al Viro1e419cd2006-11-30 19:28:48 -08001378 hlp = ubase + (((char *)e + e->target_offset) - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +09001380
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1382 if (ret != 0)
1383 return ret;
1384 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1385 if (ret != 0)
1386 return ret;
1387 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1388 return -EFAULT;
1389 return 0;
1390}
1391
Ingo Molnar57b47a52006-03-20 22:35:41 -08001392/* called with ebt_mutex locked */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1394 int *len, int cmd)
1395{
1396 struct ebt_replace tmp;
1397 struct ebt_counter *counterstmp, *oldcounters;
1398 unsigned int entries_size, nentries;
1399 char *entries;
1400
1401 if (cmd == EBT_SO_GET_ENTRIES) {
1402 entries_size = t->private->entries_size;
1403 nentries = t->private->nentries;
1404 entries = t->private->entries;
1405 oldcounters = t->private->counters;
1406 } else {
1407 entries_size = t->table->entries_size;
1408 nentries = t->table->nentries;
1409 entries = t->table->entries;
1410 oldcounters = t->table->counters;
1411 }
1412
1413 if (copy_from_user(&tmp, user, sizeof(tmp))) {
1414 BUGPRINT("Cfu didn't work\n");
1415 return -EFAULT;
1416 }
1417
1418 if (*len != sizeof(struct ebt_replace) + entries_size +
1419 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
1420 BUGPRINT("Wrong size\n");
1421 return -EINVAL;
1422 }
1423
1424 if (tmp.nentries != nentries) {
1425 BUGPRINT("Nentries wrong\n");
1426 return -EINVAL;
1427 }
1428
1429 if (tmp.entries_size != entries_size) {
1430 BUGPRINT("Wrong size\n");
1431 return -EINVAL;
1432 }
1433
1434 /* userspace might not need the counters */
1435 if (tmp.num_counters) {
1436 if (tmp.num_counters != nentries) {
1437 BUGPRINT("Num_counters wrong\n");
1438 return -EINVAL;
1439 }
Jayachandran C18bc89a2006-04-20 00:14:49 -07001440 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 if (!counterstmp) {
1442 MEMPRINT("Couldn't copy counters, out of memory\n");
1443 return -ENOMEM;
1444 }
1445 write_lock_bh(&t->lock);
1446 get_counters(oldcounters, counterstmp, nentries);
1447 write_unlock_bh(&t->lock);
1448
1449 if (copy_to_user(tmp.counters, counterstmp,
1450 nentries * sizeof(struct ebt_counter))) {
1451 BUGPRINT("Couldn't copy counters to userspace\n");
1452 vfree(counterstmp);
1453 return -EFAULT;
1454 }
1455 vfree(counterstmp);
1456 }
1457
1458 if (copy_to_user(tmp.entries, entries, entries_size)) {
1459 BUGPRINT("Couldn't copy entries to userspace\n");
1460 return -EFAULT;
1461 }
1462 /* set the match/watcher/target names right */
1463 return EBT_ENTRY_ITERATE(entries, entries_size,
1464 ebt_make_names, entries, tmp.entries);
1465}
1466
1467static int do_ebt_set_ctl(struct sock *sk,
1468 int cmd, void __user *user, unsigned int len)
1469{
1470 int ret;
1471
1472 switch(cmd) {
1473 case EBT_SO_SET_ENTRIES:
1474 ret = do_replace(user, len);
1475 break;
1476 case EBT_SO_SET_COUNTERS:
1477 ret = update_counters(user, len);
1478 break;
1479 default:
1480 ret = -EINVAL;
1481 }
1482 return ret;
1483}
1484
1485static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1486{
1487 int ret;
1488 struct ebt_replace tmp;
1489 struct ebt_table *t;
1490
1491 if (copy_from_user(&tmp, user, sizeof(tmp)))
1492 return -EFAULT;
1493
1494 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1495 if (!t)
1496 return ret;
1497
1498 switch(cmd) {
1499 case EBT_SO_GET_INFO:
1500 case EBT_SO_GET_INIT_INFO:
1501 if (*len != sizeof(struct ebt_replace)){
1502 ret = -EINVAL;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001503 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 break;
1505 }
1506 if (cmd == EBT_SO_GET_INFO) {
1507 tmp.nentries = t->private->nentries;
1508 tmp.entries_size = t->private->entries_size;
1509 tmp.valid_hooks = t->valid_hooks;
1510 } else {
1511 tmp.nentries = t->table->nentries;
1512 tmp.entries_size = t->table->entries_size;
1513 tmp.valid_hooks = t->table->valid_hooks;
1514 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001515 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 if (copy_to_user(user, &tmp, *len) != 0){
1517 BUGPRINT("c2u Didn't work\n");
1518 ret = -EFAULT;
1519 break;
1520 }
1521 ret = 0;
1522 break;
1523
1524 case EBT_SO_GET_ENTRIES:
1525 case EBT_SO_GET_INIT_ENTRIES:
1526 ret = copy_everything_to_user(t, user, len, cmd);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001527 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 break;
1529
1530 default:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001531 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 ret = -EINVAL;
1533 }
1534
1535 return ret;
1536}
1537
1538static struct nf_sockopt_ops ebt_sockopts =
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08001539{
1540 .pf = PF_INET,
1541 .set_optmin = EBT_BASE_CTL,
1542 .set_optmax = EBT_SO_SET_MAX + 1,
1543 .set = do_ebt_set_ctl,
1544 .get_optmin = EBT_BASE_CTL,
1545 .get_optmax = EBT_SO_GET_MAX + 1,
1546 .get = do_ebt_get_ctl,
Neil Horman16fcec32007-09-11 11:28:26 +02001547 .owner = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548};
1549
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001550static int __init ebtables_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551{
1552 int ret;
1553
Ingo Molnar57b47a52006-03-20 22:35:41 -08001554 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001555 list_add(&ebt_standard_target.list, &ebt_targets);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001556 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
1558 return ret;
1559
Patrick McHardya887c1c2007-07-14 20:46:15 -07001560 printk(KERN_INFO "Ebtables v2.0 registered\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 return 0;
1562}
1563
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001564static void __exit ebtables_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565{
1566 nf_unregister_sockopt(&ebt_sockopts);
Patrick McHardya887c1c2007-07-14 20:46:15 -07001567 printk(KERN_INFO "Ebtables v2.0 unregistered\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568}
1569
1570EXPORT_SYMBOL(ebt_register_table);
1571EXPORT_SYMBOL(ebt_unregister_table);
1572EXPORT_SYMBOL(ebt_register_match);
1573EXPORT_SYMBOL(ebt_unregister_match);
1574EXPORT_SYMBOL(ebt_register_watcher);
1575EXPORT_SYMBOL(ebt_unregister_watcher);
1576EXPORT_SYMBOL(ebt_register_target);
1577EXPORT_SYMBOL(ebt_unregister_target);
1578EXPORT_SYMBOL(ebt_do_table);
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001579module_init(ebtables_init);
1580module_exit(ebtables_fini);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581MODULE_LICENSE("GPL");