blob: 5ce37b2f5b842b3b1eac2201af05d67fa435a599 [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);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Jan Engelhardt043ef462008-10-08 11:35:15 +020060static struct xt_target ebt_standard_target = {
Jan Engelhardt001a18d2008-10-08 11:35:14 +020061 .name = "standard",
62 .revision = 0,
63 .family = NFPROTO_BRIDGE,
Jan Engelhardt043ef462008-10-08 11:35:15 +020064 .targetsize = sizeof(int),
Jan Engelhardt18219d32008-10-08 11:35:13 +020065};
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
67static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
Jan Engelhardt2d06d4a2008-10-08 11:35:15 +020068 struct sk_buff *skb, unsigned int hooknr, const struct net_device *in,
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 const struct net_device *out)
70{
Jan Engelhardt043ef462008-10-08 11:35:15 +020071 w->u.watcher->target(skb, in, out, hooknr, w->u.watcher, w->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 /* watchers don't give a verdict */
73 return 0;
74}
75
76static inline int ebt_do_match (struct ebt_entry_match *m,
Jan Engelhardtf7108a22008-10-08 11:35:18 +020077 const struct sk_buff *skb, struct xt_match_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -070078{
Jan Engelhardtf7108a22008-10-08 11:35:18 +020079 par->match = m->u.match;
80 par->matchinfo = m->data;
81 return m->u.match->match(skb, par);
Linus Torvalds1da177e2005-04-16 15:20:36 -070082}
83
84static inline int ebt_dev_check(char *entry, const struct net_device *device)
85{
86 int i = 0;
Meelis Roos6f5b7ef2006-11-01 18:07:27 -080087 const char *devname = device->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
89 if (*entry == '\0')
90 return 0;
91 if (!device)
92 return 1;
93 /* 1 is the wildcard token */
94 while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i])
95 i++;
96 return (devname[i] != entry[i] && entry[i] != 1);
97}
98
99#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
100/* process standard matches */
101static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
102 const struct net_device *in, const struct net_device *out)
103{
104 int verdict, i;
105
106 if (e->bitmask & EBT_802_3) {
107 if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
108 return 1;
109 } else if (!(e->bitmask & EBT_NOPROTO) &&
110 FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
111 return 1;
112
113 if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
114 return 1;
115 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
116 return 1;
117 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
118 e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN))
119 return 1;
120 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
121 e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT))
122 return 1;
123
124 if (e->bitmask & EBT_SOURCEMAC) {
125 verdict = 0;
126 for (i = 0; i < 6; i++)
127 verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
128 e->sourcemsk[i];
129 if (FWINV2(verdict != 0, EBT_ISOURCE) )
130 return 1;
131 }
132 if (e->bitmask & EBT_DESTMAC) {
133 verdict = 0;
134 for (i = 0; i < 6; i++)
135 verdict |= (h->h_dest[i] ^ e->destmac[i]) &
136 e->destmsk[i];
137 if (FWINV2(verdict != 0, EBT_IDEST) )
138 return 1;
139 }
140 return 0;
141}
142
143/* Do some firewalling */
Herbert Xu3db05fe2007-10-15 00:53:15 -0700144unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 const struct net_device *in, const struct net_device *out,
146 struct ebt_table *table)
147{
148 int i, nentries;
149 struct ebt_entry *point;
150 struct ebt_counter *counter_base, *cb_base;
151 struct ebt_entry_target *t;
152 int verdict, sp = 0;
153 struct ebt_chainstack *cs;
154 struct ebt_entries *chaininfo;
155 char *base;
156 struct ebt_table_info *private;
Jan Engelhardt5365f802008-10-08 11:35:16 +0200157 bool hotdrop = false;
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200158 struct xt_match_param mtpar;
159
160 mtpar.in = in;
161 mtpar.out = out;
162 mtpar.hotdrop = &hotdrop;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163
164 read_lock_bh(&table->lock);
165 private = table->private;
166 cb_base = COUNTER_BASE(private->counters, private->nentries,
167 smp_processor_id());
168 if (private->chainstack)
169 cs = private->chainstack[smp_processor_id()];
170 else
171 cs = NULL;
172 chaininfo = private->hook_entry[hook];
173 nentries = private->hook_entry[hook]->nentries;
174 point = (struct ebt_entry *)(private->hook_entry[hook]->data);
175 counter_base = cb_base + private->hook_entry[hook]->counter_offset;
176 /* base for chain jumps */
177 base = private->entries;
178 i = 0;
179 while (i < nentries) {
Herbert Xu3db05fe2007-10-15 00:53:15 -0700180 if (ebt_basic_match(point, eth_hdr(skb), in, out))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 goto letscontinue;
182
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200183 if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &mtpar) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 goto letscontinue;
Jan Engelhardt5365f802008-10-08 11:35:16 +0200185 if (hotdrop) {
186 read_unlock_bh(&table->lock);
187 return NF_DROP;
188 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190 /* increase counter */
191 (*(counter_base + i)).pcnt++;
Herbert Xu3db05fe2007-10-15 00:53:15 -0700192 (*(counter_base + i)).bcnt += skb->len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
194 /* these should only watch: not modify, nor tell us
195 what to do with the packet */
Herbert Xu3db05fe2007-10-15 00:53:15 -0700196 EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, hook, in,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 out);
198
199 t = (struct ebt_entry_target *)
200 (((char *)point) + point->target_offset);
201 /* standard target */
202 if (!t->u.target->target)
203 verdict = ((struct ebt_standard_target *)t)->verdict;
204 else
Jan Engelhardt2d06d4a2008-10-08 11:35:15 +0200205 verdict = t->u.target->target(skb, in, out, hook,
Jan Engelhardt043ef462008-10-08 11:35:15 +0200206 t->u.target, t->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 if (verdict == EBT_ACCEPT) {
208 read_unlock_bh(&table->lock);
209 return NF_ACCEPT;
210 }
211 if (verdict == EBT_DROP) {
212 read_unlock_bh(&table->lock);
213 return NF_DROP;
214 }
215 if (verdict == EBT_RETURN) {
216letsreturn:
217#ifdef CONFIG_NETFILTER_DEBUG
218 if (sp == 0) {
219 BUGPRINT("RETURN on base chain");
220 /* act like this is EBT_CONTINUE */
221 goto letscontinue;
222 }
223#endif
224 sp--;
225 /* put all the local variables right */
226 i = cs[sp].n;
227 chaininfo = cs[sp].chaininfo;
228 nentries = chaininfo->nentries;
229 point = cs[sp].e;
230 counter_base = cb_base +
231 chaininfo->counter_offset;
232 continue;
233 }
234 if (verdict == EBT_CONTINUE)
235 goto letscontinue;
236#ifdef CONFIG_NETFILTER_DEBUG
237 if (verdict < 0) {
238 BUGPRINT("bogus standard verdict\n");
239 read_unlock_bh(&table->lock);
240 return NF_DROP;
241 }
242#endif
243 /* jump to a udc */
244 cs[sp].n = i + 1;
245 cs[sp].chaininfo = chaininfo;
246 cs[sp].e = (struct ebt_entry *)
247 (((char *)point) + point->next_offset);
248 i = 0;
249 chaininfo = (struct ebt_entries *) (base + verdict);
250#ifdef CONFIG_NETFILTER_DEBUG
251 if (chaininfo->distinguisher) {
252 BUGPRINT("jump to non-chain\n");
253 read_unlock_bh(&table->lock);
254 return NF_DROP;
255 }
256#endif
257 nentries = chaininfo->nentries;
258 point = (struct ebt_entry *)chaininfo->data;
259 counter_base = cb_base + chaininfo->counter_offset;
260 sp++;
261 continue;
262letscontinue:
263 point = (struct ebt_entry *)
264 (((char *)point) + point->next_offset);
265 i++;
266 }
267
268 /* I actually like this :) */
269 if (chaininfo->policy == EBT_RETURN)
270 goto letsreturn;
271 if (chaininfo->policy == EBT_ACCEPT) {
272 read_unlock_bh(&table->lock);
273 return NF_ACCEPT;
274 }
275 read_unlock_bh(&table->lock);
276 return NF_DROP;
277}
278
279/* If it succeeds, returns element and locks mutex */
280static inline void *
281find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
Ingo Molnar57b47a52006-03-20 22:35:41 -0800282 struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283{
Patrick McHardydf0933d2006-09-20 11:57:53 -0700284 struct {
285 struct list_head list;
286 char name[EBT_FUNCTION_MAXNAMELEN];
287 } *e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288
Ingo Molnar57b47a52006-03-20 22:35:41 -0800289 *error = mutex_lock_interruptible(mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 if (*error != 0)
291 return NULL;
292
Patrick McHardydf0933d2006-09-20 11:57:53 -0700293 list_for_each_entry(e, head, list) {
294 if (strcmp(e->name, name) == 0)
295 return e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 }
Patrick McHardydf0933d2006-09-20 11:57:53 -0700297 *error = -ENOENT;
298 mutex_unlock(mutex);
299 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300}
301
302#ifndef CONFIG_KMOD
303#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
304#else
305static void *
306find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
Ingo Molnar57b47a52006-03-20 22:35:41 -0800307 int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308{
309 void *ret;
310
311 ret = find_inlist_lock_noload(head, name, error, mutex);
312 if (!ret) {
313 request_module("%s%s", prefix, name);
314 ret = find_inlist_lock_noload(head, name, error, mutex);
315 }
316 return ret;
317}
318#endif
319
320static inline struct ebt_table *
Ingo Molnar57b47a52006-03-20 22:35:41 -0800321find_table_lock(const char *name, int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322{
323 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex);
324}
325
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326static inline int
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200327ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par,
328 unsigned int *cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329{
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200330 const struct ebt_entry *e = par->entryinfo;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200331 struct xt_match *match;
Al Viro14197d52006-11-30 19:25:21 -0800332 size_t left = ((char *)e + e->watchers_offset) - (char *)m;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 int ret;
334
Al Viro14197d52006-11-30 19:25:21 -0800335 if (left < sizeof(struct ebt_entry_match) ||
336 left - sizeof(struct ebt_entry_match) < m->match_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 return -EINVAL;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200338
339 match = try_then_request_module(xt_find_match(NFPROTO_BRIDGE,
340 m->u.name, 0), "ebt_%s", m->u.name);
341 if (IS_ERR(match))
342 return PTR_ERR(match);
343 if (match == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 return -ENOENT;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200345 m->u.match = match;
346
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200347 par->match = match;
348 par->matchinfo = m->data;
349 ret = xt_check_match(par, NFPROTO_BRIDGE, m->match_size,
350 e->ethproto, e->invflags & EBT_IPROTO);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200351 if (ret < 0) {
352 module_put(match->me);
353 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 }
Jan Engelhardt043ef462008-10-08 11:35:15 +0200355
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 (*cnt)++;
357 return 0;
358}
359
360static inline int
361ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
362 const char *name, unsigned int hookmask, unsigned int *cnt)
363{
Jan Engelhardt043ef462008-10-08 11:35:15 +0200364 struct xt_target *watcher;
Al Viro14197d52006-11-30 19:25:21 -0800365 size_t left = ((char *)e + e->target_offset) - (char *)w;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 int ret;
367
Al Viro14197d52006-11-30 19:25:21 -0800368 if (left < sizeof(struct ebt_entry_watcher) ||
369 left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 return -EINVAL;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200371
372 watcher = try_then_request_module(
373 xt_find_target(NFPROTO_BRIDGE, w->u.name, 0),
374 "ebt_%s", w->u.name);
375 if (IS_ERR(watcher))
376 return PTR_ERR(watcher);
377 if (watcher == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 return -ENOENT;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200379 w->u.watcher = watcher;
380
381 ret = xt_check_target(watcher, NFPROTO_BRIDGE, w->watcher_size,
Jan Engelhardt367c6792008-10-08 11:35:17 +0200382 name, hookmask, e->ethproto, e->invflags & EBT_IPROTO,
383 e, w->data);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200384 if (ret < 0) {
385 module_put(watcher->me);
386 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 }
Jan Engelhardt043ef462008-10-08 11:35:15 +0200388
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 (*cnt)++;
390 return 0;
391}
392
Al Viro70fe9af2006-11-30 19:26:14 -0800393static int ebt_verify_pointers(struct ebt_replace *repl,
394 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395{
Al Viro70fe9af2006-11-30 19:26:14 -0800396 unsigned int limit = repl->entries_size;
397 unsigned int valid_hooks = repl->valid_hooks;
398 unsigned int offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 int i;
400
Al Viroe4fd77d2006-11-30 19:26:35 -0800401 for (i = 0; i < NF_BR_NUMHOOKS; i++)
402 newinfo->hook_entry[i] = NULL;
403
404 newinfo->entries_size = repl->entries_size;
405 newinfo->nentries = repl->nentries;
406
Al Viro70fe9af2006-11-30 19:26:14 -0800407 while (offset < limit) {
408 size_t left = limit - offset;
409 struct ebt_entry *e = (void *)newinfo->entries + offset;
Al Virobb2ef252006-11-30 19:22:42 -0800410
Al Viro70fe9af2006-11-30 19:26:14 -0800411 if (left < sizeof(unsigned int))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 break;
Al Viro22b440b2006-11-30 19:25:51 -0800413
Al Viro70fe9af2006-11-30 19:26:14 -0800414 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
415 if ((valid_hooks & (1 << i)) == 0)
416 continue;
Al Viro1e419cd2006-11-30 19:28:48 -0800417 if ((char __user *)repl->hook_entry[i] ==
418 repl->entries + offset)
Al Viro70fe9af2006-11-30 19:26:14 -0800419 break;
420 }
421
422 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
423 if (e->bitmask != 0) {
424 /* we make userspace set this right,
425 so there is no misunderstanding */
426 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
427 "in distinguisher\n");
428 return -EINVAL;
429 }
430 if (i != NF_BR_NUMHOOKS)
431 newinfo->hook_entry[i] = (struct ebt_entries *)e;
432 if (left < sizeof(struct ebt_entries))
433 break;
434 offset += sizeof(struct ebt_entries);
435 } else {
436 if (left < sizeof(struct ebt_entry))
437 break;
438 if (left < e->next_offset)
439 break;
440 offset += e->next_offset;
441 }
442 }
443 if (offset != limit) {
444 BUGPRINT("entries_size too small\n");
445 return -EINVAL;
446 }
Al Viroe4fd77d2006-11-30 19:26:35 -0800447
448 /* check if all valid hooks have a chain */
449 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
450 if (!newinfo->hook_entry[i] &&
451 (valid_hooks & (1 << i))) {
452 BUGPRINT("Valid hook without chain\n");
453 return -EINVAL;
454 }
455 }
Al Viro70fe9af2006-11-30 19:26:14 -0800456 return 0;
Al Viro22b440b2006-11-30 19:25:51 -0800457}
458
459/*
460 * this one is very careful, as it is the first function
461 * to parse the userspace data
462 */
463static inline int
464ebt_check_entry_size_and_hooks(struct ebt_entry *e,
Al Viro0e795532006-11-30 19:27:13 -0800465 struct ebt_table_info *newinfo,
466 unsigned int *n, unsigned int *cnt,
467 unsigned int *totalcnt, unsigned int *udc_cnt)
Al Viro22b440b2006-11-30 19:25:51 -0800468{
Al Viro22b440b2006-11-30 19:25:51 -0800469 int i;
470
471 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Viro0e795532006-11-30 19:27:13 -0800472 if ((void *)e == (void *)newinfo->hook_entry[i])
Al Viro22b440b2006-11-30 19:25:51 -0800473 break;
474 }
475 /* beginning of a new chain
476 if i == NF_BR_NUMHOOKS it must be a user defined chain */
477 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 /* this checks if the previous chain has as many entries
479 as it said it has */
480 if (*n != *cnt) {
481 BUGPRINT("nentries does not equal the nr of entries "
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900482 "in the chain\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 return -EINVAL;
484 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
486 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
487 /* only RETURN from udc */
488 if (i != NF_BR_NUMHOOKS ||
489 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
490 BUGPRINT("bad policy\n");
491 return -EINVAL;
492 }
493 }
494 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
495 (*udc_cnt)++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
497 BUGPRINT("counter_offset != totalcnt");
498 return -EINVAL;
499 }
500 *n = ((struct ebt_entries *)e)->nentries;
501 *cnt = 0;
502 return 0;
503 }
504 /* a plain old entry, heh */
505 if (sizeof(struct ebt_entry) > e->watchers_offset ||
506 e->watchers_offset > e->target_offset ||
507 e->target_offset >= e->next_offset) {
508 BUGPRINT("entry offsets not in right order\n");
509 return -EINVAL;
510 }
511 /* this is not checked anywhere else */
512 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
513 BUGPRINT("target size too small\n");
514 return -EINVAL;
515 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 (*cnt)++;
517 (*totalcnt)++;
518 return 0;
519}
520
521struct ebt_cl_stack
522{
523 struct ebt_chainstack cs;
524 int from;
525 unsigned int hookmask;
526};
527
528/*
529 * we need these positions to check that the jumps to a different part of the
530 * entries is a jump to the beginning of a new chain.
531 */
532static inline int
533ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
Al Viro177abc32006-11-30 19:27:32 -0800534 unsigned int *n, struct ebt_cl_stack *udc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535{
536 int i;
537
538 /* we're only interested in chain starts */
Al Viro40642f92006-11-30 19:24:12 -0800539 if (e->bitmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 return 0;
541 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
543 break;
544 }
545 /* only care about udc */
546 if (i != NF_BR_NUMHOOKS)
547 return 0;
548
549 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
550 /* these initialisations are depended on later in check_chainloops() */
551 udc[*n].cs.n = 0;
552 udc[*n].hookmask = 0;
553
554 (*n)++;
555 return 0;
556}
557
558static inline int
559ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
560{
561 if (i && (*i)-- == 0)
562 return 1;
563 if (m->u.match->destroy)
Jan Engelhardt043ef462008-10-08 11:35:15 +0200564 m->u.match->destroy(m->u.match, m->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 module_put(m->u.match->me);
566
567 return 0;
568}
569
570static inline int
571ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
572{
573 if (i && (*i)-- == 0)
574 return 1;
575 if (w->u.watcher->destroy)
Jan Engelhardt043ef462008-10-08 11:35:15 +0200576 w->u.watcher->destroy(w->u.watcher, w->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 module_put(w->u.watcher->me);
578
579 return 0;
580}
581
582static inline int
583ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
584{
585 struct ebt_entry_target *t;
586
Al Viro40642f92006-11-30 19:24:12 -0800587 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 return 0;
589 /* we're done */
590 if (cnt && (*cnt)-- == 0)
591 return 1;
592 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
593 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);
594 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
595 if (t->u.target->destroy)
Jan Engelhardt043ef462008-10-08 11:35:15 +0200596 t->u.target->destroy(t->u.target, t->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 module_put(t->u.target->me);
598
599 return 0;
600}
601
602static inline int
603ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
Al Virof7da79d2006-11-30 19:27:48 -0800604 const char *name, unsigned int *cnt,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
606{
607 struct ebt_entry_target *t;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200608 struct xt_target *target;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 unsigned int i, j, hook = 0, hookmask = 0;
Chuck Ebbert44f9a2f2007-01-04 12:17:44 -0800610 size_t gap;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 int ret;
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200612 struct xt_mtchk_param par;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
614 /* don't mess with the struct ebt_entries */
Al Viro40642f92006-11-30 19:24:12 -0800615 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 return 0;
617
618 if (e->bitmask & ~EBT_F_MASK) {
619 BUGPRINT("Unknown flag for bitmask\n");
620 return -EINVAL;
621 }
622 if (e->invflags & ~EBT_INV_MASK) {
623 BUGPRINT("Unknown flag for inv bitmask\n");
624 return -EINVAL;
625 }
626 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
627 BUGPRINT("NOPROTO & 802_3 not allowed\n");
628 return -EINVAL;
629 }
630 /* what hook do we belong to? */
631 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Virof7da79d2006-11-30 19:27:48 -0800632 if (!newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 continue;
634 if ((char *)newinfo->hook_entry[i] < (char *)e)
635 hook = i;
636 else
637 break;
638 }
639 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
640 a base chain */
641 if (i < NF_BR_NUMHOOKS)
642 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
643 else {
644 for (i = 0; i < udc_cnt; i++)
645 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
646 break;
647 if (i == 0)
648 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
649 else
650 hookmask = cl_s[i - 1].hookmask;
651 }
652 i = 0;
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200653
654 par.table = name;
655 par.entryinfo = e;
656 par.hook_mask = hookmask;
657 ret = EBT_MATCH_ITERATE(e, ebt_check_match, &par, &i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 if (ret != 0)
659 goto cleanup_matches;
660 j = 0;
661 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
662 if (ret != 0)
663 goto cleanup_watchers;
664 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
Chuck Ebbert44f9a2f2007-01-04 12:17:44 -0800665 gap = e->next_offset - e->target_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
Jan Engelhardt043ef462008-10-08 11:35:15 +0200667 target = try_then_request_module(
668 xt_find_target(NFPROTO_BRIDGE, t->u.name, 0),
669 "ebt_%s", t->u.name);
670 if (IS_ERR(target)) {
671 ret = PTR_ERR(target);
Jan Engelhardt001a18d2008-10-08 11:35:14 +0200672 goto cleanup_watchers;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200673 } else if (target == NULL) {
674 ret = -ENOENT;
Jan Engelhardt001a18d2008-10-08 11:35:14 +0200675 goto cleanup_watchers;
676 }
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 t->u.target = target;
679 if (t->u.target == &ebt_standard_target) {
Al Viro14197d52006-11-30 19:25:21 -0800680 if (gap < sizeof(struct ebt_standard_target)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 BUGPRINT("Standard target size too big\n");
682 ret = -EFAULT;
683 goto cleanup_watchers;
684 }
685 if (((struct ebt_standard_target *)t)->verdict <
686 -NUM_STANDARD_TARGETS) {
687 BUGPRINT("Invalid standard target\n");
688 ret = -EFAULT;
689 goto cleanup_watchers;
690 }
Jan Engelhardt18219d32008-10-08 11:35:13 +0200691 } else if (t->target_size > gap - sizeof(struct ebt_entry_target)) {
692 module_put(t->u.target->me);
693 ret = -EFAULT;
694 goto cleanup_watchers;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200695 }
696
697 ret = xt_check_target(target, NFPROTO_BRIDGE, t->target_size,
Jan Engelhardt367c6792008-10-08 11:35:17 +0200698 name, hookmask, e->ethproto, e->invflags & EBT_IPROTO,
699 e, t->data);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200700 if (ret < 0) {
701 module_put(target->me);
Jan Engelhardt18219d32008-10-08 11:35:13 +0200702 goto cleanup_watchers;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 }
704 (*cnt)++;
705 return 0;
706cleanup_watchers:
707 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);
708cleanup_matches:
709 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i);
710 return ret;
711}
712
713/*
714 * checks for loops and sets the hook mask for udc
715 * the hook mask for udc tells us from which base chains the udc can be
716 * accessed. This mask is a parameter to the check() functions of the extensions
717 */
718static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
719 unsigned int udc_cnt, unsigned int hooknr, char *base)
720{
721 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
722 struct ebt_entry *e = (struct ebt_entry *)chain->data;
723 struct ebt_entry_target *t;
724
725 while (pos < nentries || chain_nr != -1) {
726 /* end of udc, go back one 'recursion' step */
727 if (pos == nentries) {
728 /* put back values of the time when this chain was called */
729 e = cl_s[chain_nr].cs.e;
730 if (cl_s[chain_nr].from != -1)
731 nentries =
732 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
733 else
734 nentries = chain->nentries;
735 pos = cl_s[chain_nr].cs.n;
736 /* make sure we won't see a loop that isn't one */
737 cl_s[chain_nr].cs.n = 0;
738 chain_nr = cl_s[chain_nr].from;
739 if (pos == nentries)
740 continue;
741 }
742 t = (struct ebt_entry_target *)
743 (((char *)e) + e->target_offset);
744 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
745 goto letscontinue;
746 if (e->target_offset + sizeof(struct ebt_standard_target) >
747 e->next_offset) {
748 BUGPRINT("Standard target size too big\n");
749 return -1;
750 }
751 verdict = ((struct ebt_standard_target *)t)->verdict;
752 if (verdict >= 0) { /* jump to another chain */
753 struct ebt_entries *hlp2 =
754 (struct ebt_entries *)(base + verdict);
755 for (i = 0; i < udc_cnt; i++)
756 if (hlp2 == cl_s[i].cs.chaininfo)
757 break;
758 /* bad destination or loop */
759 if (i == udc_cnt) {
760 BUGPRINT("bad destination\n");
761 return -1;
762 }
763 if (cl_s[i].cs.n) {
764 BUGPRINT("loop\n");
765 return -1;
766 }
Al Viro98a08242006-11-30 19:24:49 -0800767 if (cl_s[i].hookmask & (1 << hooknr))
768 goto letscontinue;
769 /* this can't be 0, so the loop test is correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 cl_s[i].cs.n = pos + 1;
771 pos = 0;
772 cl_s[i].cs.e = ((void *)e + e->next_offset);
773 e = (struct ebt_entry *)(hlp2->data);
774 nentries = hlp2->nentries;
775 cl_s[i].from = chain_nr;
776 chain_nr = i;
777 /* this udc is accessible from the base chain for hooknr */
778 cl_s[i].hookmask |= (1 << hooknr);
779 continue;
780 }
781letscontinue:
782 e = (void *)e + e->next_offset;
783 pos++;
784 }
785 return 0;
786}
787
788/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
Al Viro1bc23262006-11-30 19:28:08 -0800789static int translate_table(char *name, struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790{
791 unsigned int i, j, k, udc_cnt;
792 int ret;
793 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
794
795 i = 0;
Al Viro1f072c92006-11-30 19:26:53 -0800796 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 i++;
798 if (i == NF_BR_NUMHOOKS) {
799 BUGPRINT("No valid hooks specified\n");
800 return -EINVAL;
801 }
Al Viro1f072c92006-11-30 19:26:53 -0800802 if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 BUGPRINT("Chains don't start at beginning\n");
804 return -EINVAL;
805 }
806 /* make sure chains are ordered after each other in same order
807 as their corresponding hooks */
808 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
Al Viro1f072c92006-11-30 19:26:53 -0800809 if (!newinfo->hook_entry[j])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 continue;
Al Viro1f072c92006-11-30 19:26:53 -0800811 if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 BUGPRINT("Hook order must be followed\n");
813 return -EINVAL;
814 }
815 i = j;
816 }
817
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 /* do some early checkings and initialize some things */
819 i = 0; /* holds the expected nr. of entries for the chain */
820 j = 0; /* holds the up to now counted entries for the chain */
821 k = 0; /* holds the total nr. of entries, should equal
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900822 newinfo->nentries afterwards */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
824 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro0e795532006-11-30 19:27:13 -0800825 ebt_check_entry_size_and_hooks, newinfo,
826 &i, &j, &k, &udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
828 if (ret != 0)
829 return ret;
830
831 if (i != j) {
832 BUGPRINT("nentries does not equal the nr of entries in the "
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900833 "(last) chain\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 return -EINVAL;
835 }
836 if (k != newinfo->nentries) {
837 BUGPRINT("Total nentries is wrong\n");
838 return -EINVAL;
839 }
840
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 /* get the location of the udc, put them in an array
842 while we're at it, allocate the chainstack */
843 if (udc_cnt) {
844 /* this will get free'd in do_replace()/ebt_register_table()
845 if an error occurs */
Jayachandran C7ad4d2f2006-04-11 17:25:38 -0700846 newinfo->chainstack =
Christoph Lameter53b8a312007-02-20 13:57:51 -0800847 vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 if (!newinfo->chainstack)
849 return -ENOMEM;
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700850 for_each_possible_cpu(i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 newinfo->chainstack[i] =
Jayachandran C18bc89a2006-04-20 00:14:49 -0700852 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 if (!newinfo->chainstack[i]) {
854 while (i)
855 vfree(newinfo->chainstack[--i]);
856 vfree(newinfo->chainstack);
857 newinfo->chainstack = NULL;
858 return -ENOMEM;
859 }
860 }
861
Jayachandran C18bc89a2006-04-20 00:14:49 -0700862 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 if (!cl_s)
864 return -ENOMEM;
865 i = 0; /* the i'th udc */
866 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro177abc32006-11-30 19:27:32 -0800867 ebt_get_udc_positions, newinfo, &i, cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 /* sanity check */
869 if (i != udc_cnt) {
870 BUGPRINT("i != udc_cnt\n");
871 vfree(cl_s);
872 return -EFAULT;
873 }
874 }
875
876 /* Check for loops */
877 for (i = 0; i < NF_BR_NUMHOOKS; i++)
Al Viro1f072c92006-11-30 19:26:53 -0800878 if (newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 if (check_chainloops(newinfo->hook_entry[i],
880 cl_s, udc_cnt, i, newinfo->entries)) {
James Lamanna68d31872005-06-22 22:12:57 -0700881 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 return -EINVAL;
883 }
884
Jan Engelhardt96de0e22007-10-19 23:21:04 +0200885 /* we now know the following (along with E=mc²):
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 - the nr of entries in each chain is right
887 - the size of the allocated space is right
888 - all valid hooks have a corresponding chain
889 - there are no loops
890 - wrong data can still be on the level of a single entry
891 - could be there are jumps to places that are not the
892 beginning of a chain. This can only occur in chains that
893 are not accessible from any base chains, so we don't care. */
894
895 /* used to know what we need to clean up if something goes wrong */
896 i = 0;
897 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro1bc23262006-11-30 19:28:08 -0800898 ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 if (ret != 0) {
900 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
901 ebt_cleanup_entry, &i);
902 }
James Lamanna68d31872005-06-22 22:12:57 -0700903 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 return ret;
905}
906
907/* called under write_lock */
908static void get_counters(struct ebt_counter *oldcounters,
909 struct ebt_counter *counters, unsigned int nentries)
910{
911 int i, cpu;
912 struct ebt_counter *counter_base;
913
914 /* counters of cpu 0 */
915 memcpy(counters, oldcounters,
David S. Millerc8923c62005-10-13 14:41:23 -0700916 sizeof(struct ebt_counter) * nentries);
917
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 /* add other counters to those of cpu 0 */
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700919 for_each_possible_cpu(cpu) {
David S. Millerc8923c62005-10-13 14:41:23 -0700920 if (cpu == 0)
921 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
923 for (i = 0; i < nentries; i++) {
924 counters[i].pcnt += counter_base[i].pcnt;
925 counters[i].bcnt += counter_base[i].bcnt;
926 }
927 }
928}
929
930/* replace the table */
931static int do_replace(void __user *user, unsigned int len)
932{
933 int ret, i, countersize;
934 struct ebt_table_info *newinfo;
935 struct ebt_replace tmp;
936 struct ebt_table *t;
937 struct ebt_counter *counterstmp = NULL;
938 /* used to be able to unlock earlier */
939 struct ebt_table_info *table;
940
941 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
942 return -EFAULT;
943
944 if (len != sizeof(tmp) + tmp.entries_size) {
945 BUGPRINT("Wrong len argument\n");
946 return -EINVAL;
947 }
948
949 if (tmp.entries_size == 0) {
950 BUGPRINT("Entries_size never zero\n");
951 return -EINVAL;
952 }
Kirill Korotaevee4bb812006-02-04 02:16:56 -0800953 /* overflow check */
954 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
955 SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
956 return -ENOMEM;
957 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
958 return -ENOMEM;
959
Christoph Lameter53b8a312007-02-20 13:57:51 -0800960 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
Jayachandran C18bc89a2006-04-20 00:14:49 -0700961 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 if (!newinfo)
963 return -ENOMEM;
964
965 if (countersize)
966 memset(newinfo->counters, 0, countersize);
967
Kris Katterjohn8b3a7002006-01-11 15:56:43 -0800968 newinfo->entries = vmalloc(tmp.entries_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 if (!newinfo->entries) {
970 ret = -ENOMEM;
971 goto free_newinfo;
972 }
973 if (copy_from_user(
974 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
975 BUGPRINT("Couldn't copy entries from userspace\n");
976 ret = -EFAULT;
977 goto free_entries;
978 }
979
980 /* the user wants counters back
981 the check on the size is done later, when we have the lock */
982 if (tmp.num_counters) {
Jayachandran C18bc89a2006-04-20 00:14:49 -0700983 counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 if (!counterstmp) {
985 ret = -ENOMEM;
986 goto free_entries;
987 }
988 }
989 else
990 counterstmp = NULL;
991
992 /* this can get initialized by translate_table() */
993 newinfo->chainstack = NULL;
Al Viro1bc23262006-11-30 19:28:08 -0800994 ret = ebt_verify_pointers(&tmp, newinfo);
995 if (ret != 0)
996 goto free_counterstmp;
997
998 ret = translate_table(tmp.name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999
1000 if (ret != 0)
1001 goto free_counterstmp;
1002
1003 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1004 if (!t) {
1005 ret = -ENOENT;
1006 goto free_iterate;
1007 }
1008
1009 /* the table doesn't like it */
1010 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
1011 goto free_unlock;
1012
1013 if (tmp.num_counters && tmp.num_counters != t->private->nentries) {
1014 BUGPRINT("Wrong nr. of counters requested\n");
1015 ret = -EINVAL;
1016 goto free_unlock;
1017 }
1018
1019 /* we have the mutex lock, so no danger in reading this pointer */
1020 table = t->private;
1021 /* make sure the table can only be rmmod'ed if it contains no rules */
1022 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
1023 ret = -ENOENT;
1024 goto free_unlock;
1025 } else if (table->nentries && !newinfo->nentries)
1026 module_put(t->me);
1027 /* we need an atomic snapshot of the counters */
1028 write_lock_bh(&t->lock);
1029 if (tmp.num_counters)
1030 get_counters(t->private->counters, counterstmp,
1031 t->private->nentries);
1032
1033 t->private = newinfo;
1034 write_unlock_bh(&t->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001035 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 /* so, a user can change the chains while having messed up her counter
1037 allocation. Only reason why this is done is because this way the lock
1038 is held only once, while this doesn't bring the kernel into a
1039 dangerous state. */
1040 if (tmp.num_counters &&
1041 copy_to_user(tmp.counters, counterstmp,
1042 tmp.num_counters * sizeof(struct ebt_counter))) {
1043 BUGPRINT("Couldn't copy counters to userspace\n");
1044 ret = -EFAULT;
1045 }
1046 else
1047 ret = 0;
1048
1049 /* decrease module count and free resources */
1050 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
1051 ebt_cleanup_entry, NULL);
1052
1053 vfree(table->entries);
1054 if (table->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001055 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 vfree(table->chainstack[i]);
1057 vfree(table->chainstack);
1058 }
1059 vfree(table);
1060
James Lamanna68d31872005-06-22 22:12:57 -07001061 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 return ret;
1063
1064free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001065 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066free_iterate:
1067 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1068 ebt_cleanup_entry, NULL);
1069free_counterstmp:
James Lamanna68d31872005-06-22 22:12:57 -07001070 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 /* can be initialized in translate_table() */
1072 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001073 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 vfree(newinfo->chainstack[i]);
1075 vfree(newinfo->chainstack);
1076 }
1077free_entries:
James Lamanna68d31872005-06-22 22:12:57 -07001078 vfree(newinfo->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079free_newinfo:
James Lamanna68d31872005-06-22 22:12:57 -07001080 vfree(newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 return ret;
1082}
1083
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084int ebt_register_table(struct ebt_table *table)
1085{
1086 struct ebt_table_info *newinfo;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001087 struct ebt_table *t;
Al Viro1e419cd2006-11-30 19:28:48 -08001088 struct ebt_replace_kernel *repl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 int ret, i, countersize;
Al Virodf07a812006-11-30 19:28:25 -08001090 void *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
Al Virodf07a812006-11-30 19:28:25 -08001092 if (!table || !(repl = table->table) || !repl->entries ||
1093 repl->entries_size == 0 ||
1094 repl->counters || table->private) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1096 return -EINVAL;
1097 }
1098
Christoph Lameter53b8a312007-02-20 13:57:51 -08001099 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
Jayachandran C18bc89a2006-04-20 00:14:49 -07001100 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 ret = -ENOMEM;
1102 if (!newinfo)
1103 return -ENOMEM;
1104
Al Virodf07a812006-11-30 19:28:25 -08001105 p = vmalloc(repl->entries_size);
1106 if (!p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 goto free_newinfo;
1108
Al Virodf07a812006-11-30 19:28:25 -08001109 memcpy(p, repl->entries, repl->entries_size);
1110 newinfo->entries = p;
1111
1112 newinfo->entries_size = repl->entries_size;
1113 newinfo->nentries = repl->nentries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
1115 if (countersize)
1116 memset(newinfo->counters, 0, countersize);
1117
1118 /* fill in newinfo and parse the entries */
1119 newinfo->chainstack = NULL;
Al Virodf07a812006-11-30 19:28:25 -08001120 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1121 if ((repl->valid_hooks & (1 << i)) == 0)
1122 newinfo->hook_entry[i] = NULL;
1123 else
1124 newinfo->hook_entry[i] = p +
1125 ((char *)repl->hook_entry[i] - repl->entries);
1126 }
1127 ret = translate_table(repl->name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 if (ret != 0) {
1129 BUGPRINT("Translate_table failed\n");
1130 goto free_chainstack;
1131 }
1132
1133 if (table->check && table->check(newinfo, table->valid_hooks)) {
1134 BUGPRINT("The table doesn't like its own initial data, lol\n");
1135 return -EINVAL;
1136 }
1137
1138 table->private = newinfo;
1139 rwlock_init(&table->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001140 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 if (ret != 0)
1142 goto free_chainstack;
1143
Patrick McHardydf0933d2006-09-20 11:57:53 -07001144 list_for_each_entry(t, &ebt_tables, list) {
1145 if (strcmp(t->name, table->name) == 0) {
1146 ret = -EEXIST;
1147 BUGPRINT("Table name already exists\n");
1148 goto free_unlock;
1149 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 }
1151
1152 /* Hold a reference count if the chains aren't empty */
1153 if (newinfo->nentries && !try_module_get(table->me)) {
1154 ret = -ENOENT;
1155 goto free_unlock;
1156 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001157 list_add(&table->list, &ebt_tables);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001158 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 return 0;
1160free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001161 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162free_chainstack:
1163 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001164 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 vfree(newinfo->chainstack[i]);
1166 vfree(newinfo->chainstack);
1167 }
1168 vfree(newinfo->entries);
1169free_newinfo:
1170 vfree(newinfo);
1171 return ret;
1172}
1173
1174void ebt_unregister_table(struct ebt_table *table)
1175{
1176 int i;
1177
1178 if (!table) {
1179 BUGPRINT("Request to unregister NULL table!!!\n");
1180 return;
1181 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001182 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001183 list_del(&table->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001184 mutex_unlock(&ebt_mutex);
James Lamanna68d31872005-06-22 22:12:57 -07001185 vfree(table->private->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 if (table->private->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001187 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 vfree(table->private->chainstack[i]);
1189 vfree(table->private->chainstack);
1190 }
1191 vfree(table->private);
1192}
1193
1194/* userspace just supplied us with counters */
1195static int update_counters(void __user *user, unsigned int len)
1196{
1197 int i, ret;
1198 struct ebt_counter *tmp;
1199 struct ebt_replace hlp;
1200 struct ebt_table *t;
1201
1202 if (copy_from_user(&hlp, user, sizeof(hlp)))
1203 return -EFAULT;
1204
1205 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1206 return -EINVAL;
1207 if (hlp.num_counters == 0)
1208 return -EINVAL;
1209
Jayachandran C18bc89a2006-04-20 00:14:49 -07001210 if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 MEMPRINT("Update_counters && nomemory\n");
1212 return -ENOMEM;
1213 }
1214
1215 t = find_table_lock(hlp.name, &ret, &ebt_mutex);
1216 if (!t)
1217 goto free_tmp;
1218
1219 if (hlp.num_counters != t->private->nentries) {
1220 BUGPRINT("Wrong nr of counters\n");
1221 ret = -EINVAL;
1222 goto unlock_mutex;
1223 }
1224
1225 if ( copy_from_user(tmp, hlp.counters,
1226 hlp.num_counters * sizeof(struct ebt_counter)) ) {
1227 BUGPRINT("Updata_counters && !cfu\n");
1228 ret = -EFAULT;
1229 goto unlock_mutex;
1230 }
1231
1232 /* we want an atomic add of the counters */
1233 write_lock_bh(&t->lock);
1234
1235 /* we add to the counters of the first cpu */
1236 for (i = 0; i < hlp.num_counters; i++) {
1237 t->private->counters[i].pcnt += tmp[i].pcnt;
1238 t->private->counters[i].bcnt += tmp[i].bcnt;
1239 }
1240
1241 write_unlock_bh(&t->lock);
1242 ret = 0;
1243unlock_mutex:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001244 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245free_tmp:
1246 vfree(tmp);
1247 return ret;
1248}
1249
1250static inline int ebt_make_matchname(struct ebt_entry_match *m,
Al Viro1e419cd2006-11-30 19:28:48 -08001251 char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252{
Al Viro1e419cd2006-11-30 19:28:48 -08001253 char __user *hlp = ubase + ((char *)m - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1255 return -EFAULT;
1256 return 0;
1257}
1258
1259static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
Al Viro1e419cd2006-11-30 19:28:48 -08001260 char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261{
Al Viro1e419cd2006-11-30 19:28:48 -08001262 char __user *hlp = ubase + ((char *)w - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1264 return -EFAULT;
1265 return 0;
1266}
1267
Al Viro1e419cd2006-11-30 19:28:48 -08001268static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269{
1270 int ret;
Al Viro1e419cd2006-11-30 19:28:48 -08001271 char __user *hlp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 struct ebt_entry_target *t;
1273
Al Viro40642f92006-11-30 19:24:12 -08001274 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 return 0;
1276
Al Viro1e419cd2006-11-30 19:28:48 -08001277 hlp = ubase + (((char *)e + e->target_offset) - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +09001279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1281 if (ret != 0)
1282 return ret;
1283 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1284 if (ret != 0)
1285 return ret;
1286 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1287 return -EFAULT;
1288 return 0;
1289}
1290
Ingo Molnar57b47a52006-03-20 22:35:41 -08001291/* called with ebt_mutex locked */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1293 int *len, int cmd)
1294{
1295 struct ebt_replace tmp;
1296 struct ebt_counter *counterstmp, *oldcounters;
1297 unsigned int entries_size, nentries;
1298 char *entries;
1299
1300 if (cmd == EBT_SO_GET_ENTRIES) {
1301 entries_size = t->private->entries_size;
1302 nentries = t->private->nentries;
1303 entries = t->private->entries;
1304 oldcounters = t->private->counters;
1305 } else {
1306 entries_size = t->table->entries_size;
1307 nentries = t->table->nentries;
1308 entries = t->table->entries;
1309 oldcounters = t->table->counters;
1310 }
1311
1312 if (copy_from_user(&tmp, user, sizeof(tmp))) {
1313 BUGPRINT("Cfu didn't work\n");
1314 return -EFAULT;
1315 }
1316
1317 if (*len != sizeof(struct ebt_replace) + entries_size +
1318 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
1319 BUGPRINT("Wrong size\n");
1320 return -EINVAL;
1321 }
1322
1323 if (tmp.nentries != nentries) {
1324 BUGPRINT("Nentries wrong\n");
1325 return -EINVAL;
1326 }
1327
1328 if (tmp.entries_size != entries_size) {
1329 BUGPRINT("Wrong size\n");
1330 return -EINVAL;
1331 }
1332
1333 /* userspace might not need the counters */
1334 if (tmp.num_counters) {
1335 if (tmp.num_counters != nentries) {
1336 BUGPRINT("Num_counters wrong\n");
1337 return -EINVAL;
1338 }
Jayachandran C18bc89a2006-04-20 00:14:49 -07001339 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 if (!counterstmp) {
1341 MEMPRINT("Couldn't copy counters, out of memory\n");
1342 return -ENOMEM;
1343 }
1344 write_lock_bh(&t->lock);
1345 get_counters(oldcounters, counterstmp, nentries);
1346 write_unlock_bh(&t->lock);
1347
1348 if (copy_to_user(tmp.counters, counterstmp,
1349 nentries * sizeof(struct ebt_counter))) {
1350 BUGPRINT("Couldn't copy counters to userspace\n");
1351 vfree(counterstmp);
1352 return -EFAULT;
1353 }
1354 vfree(counterstmp);
1355 }
1356
1357 if (copy_to_user(tmp.entries, entries, entries_size)) {
1358 BUGPRINT("Couldn't copy entries to userspace\n");
1359 return -EFAULT;
1360 }
1361 /* set the match/watcher/target names right */
1362 return EBT_ENTRY_ITERATE(entries, entries_size,
1363 ebt_make_names, entries, tmp.entries);
1364}
1365
1366static int do_ebt_set_ctl(struct sock *sk,
1367 int cmd, void __user *user, unsigned int len)
1368{
1369 int ret;
1370
1371 switch(cmd) {
1372 case EBT_SO_SET_ENTRIES:
1373 ret = do_replace(user, len);
1374 break;
1375 case EBT_SO_SET_COUNTERS:
1376 ret = update_counters(user, len);
1377 break;
1378 default:
1379 ret = -EINVAL;
1380 }
1381 return ret;
1382}
1383
1384static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1385{
1386 int ret;
1387 struct ebt_replace tmp;
1388 struct ebt_table *t;
1389
1390 if (copy_from_user(&tmp, user, sizeof(tmp)))
1391 return -EFAULT;
1392
1393 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1394 if (!t)
1395 return ret;
1396
1397 switch(cmd) {
1398 case EBT_SO_GET_INFO:
1399 case EBT_SO_GET_INIT_INFO:
1400 if (*len != sizeof(struct ebt_replace)){
1401 ret = -EINVAL;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001402 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 break;
1404 }
1405 if (cmd == EBT_SO_GET_INFO) {
1406 tmp.nentries = t->private->nentries;
1407 tmp.entries_size = t->private->entries_size;
1408 tmp.valid_hooks = t->valid_hooks;
1409 } else {
1410 tmp.nentries = t->table->nentries;
1411 tmp.entries_size = t->table->entries_size;
1412 tmp.valid_hooks = t->table->valid_hooks;
1413 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001414 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 if (copy_to_user(user, &tmp, *len) != 0){
1416 BUGPRINT("c2u Didn't work\n");
1417 ret = -EFAULT;
1418 break;
1419 }
1420 ret = 0;
1421 break;
1422
1423 case EBT_SO_GET_ENTRIES:
1424 case EBT_SO_GET_INIT_ENTRIES:
1425 ret = copy_everything_to_user(t, user, len, cmd);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001426 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 break;
1428
1429 default:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001430 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 ret = -EINVAL;
1432 }
1433
1434 return ret;
1435}
1436
1437static struct nf_sockopt_ops ebt_sockopts =
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08001438{
1439 .pf = PF_INET,
1440 .set_optmin = EBT_BASE_CTL,
1441 .set_optmax = EBT_SO_SET_MAX + 1,
1442 .set = do_ebt_set_ctl,
1443 .get_optmin = EBT_BASE_CTL,
1444 .get_optmax = EBT_SO_GET_MAX + 1,
1445 .get = do_ebt_get_ctl,
Neil Horman16fcec32007-09-11 11:28:26 +02001446 .owner = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447};
1448
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001449static int __init ebtables_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450{
1451 int ret;
1452
Jan Engelhardt043ef462008-10-08 11:35:15 +02001453 ret = xt_register_target(&ebt_standard_target);
1454 if (ret < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 return ret;
Jan Engelhardt043ef462008-10-08 11:35:15 +02001456 ret = nf_register_sockopt(&ebt_sockopts);
1457 if (ret < 0) {
1458 xt_unregister_target(&ebt_standard_target);
1459 return ret;
1460 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
Patrick McHardya887c1c2007-07-14 20:46:15 -07001462 printk(KERN_INFO "Ebtables v2.0 registered\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 return 0;
1464}
1465
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001466static void __exit ebtables_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467{
1468 nf_unregister_sockopt(&ebt_sockopts);
Jan Engelhardt043ef462008-10-08 11:35:15 +02001469 xt_unregister_target(&ebt_standard_target);
Patrick McHardya887c1c2007-07-14 20:46:15 -07001470 printk(KERN_INFO "Ebtables v2.0 unregistered\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471}
1472
1473EXPORT_SYMBOL(ebt_register_table);
1474EXPORT_SYMBOL(ebt_unregister_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475EXPORT_SYMBOL(ebt_do_table);
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001476module_init(ebtables_init);
1477module_exit(ebtables_fini);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478MODULE_LICENSE("GPL");