1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/kmod.h>
20#include <linux/module.h>
21#include <linux/vmalloc.h>
22#include <linux/netfilter_bridge/ebtables.h>
23#include <linux/spinlock.h>
24#include <linux/mutex.h>
25#include <asm/uaccess.h>
26#include <linux/smp.h>
27#include <linux/cpumask.h>
28#include <net/sock.h>
29
30#include "../br_private.h"
31
32#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
33 "report to author: "format, ## args)
34
35#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
36 ": out of memory: "format, ## args)
37
38
39
40
41
42
43
44
45
46
47
48
49#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
50#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
51#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
52 COUNTER_OFFSET(n) * cpu))
53
54
55
56static DEFINE_MUTEX(ebt_mutex);
57static LIST_HEAD(ebt_tables);
58static LIST_HEAD(ebt_targets);
59static LIST_HEAD(ebt_matches);
60static LIST_HEAD(ebt_watchers);
61
62static struct ebt_target ebt_standard_target =
63{ {NULL, NULL}, EBT_STANDARD_TARGET, NULL, NULL, NULL, NULL};
64
65static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
66 const struct sk_buff *skb, unsigned int hooknr, const struct net_device *in,
67 const struct net_device *out)
68{
69 w->u.watcher->watcher(skb, hooknr, in, out, w->data,
70 w->watcher_size);
71
72 return 0;
73}
74
75static inline int ebt_do_match (struct ebt_entry_match *m,
76 const struct sk_buff *skb, const struct net_device *in,
77 const struct net_device *out)
78{
79 return m->u.match->match(skb, in, out, m->data,
80 m->match_size);
81}
82
83static inline int ebt_dev_check(char *entry, const struct net_device *device)
84{
85 int i = 0;
86 const char *devname = device->name;
87
88 if (*entry == '\0')
89 return 0;
90 if (!device)
91 return 1;
92
93 while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i])
94 i++;
95 return (devname[i] != entry[i] && entry[i] != 1);
96}
97
98#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
99
100static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
101 const struct net_device *in, const struct net_device *out)
102{
103 int verdict, i;
104
105 if (e->bitmask & EBT_802_3) {
106 if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
107 return 1;
108 } else if (!(e->bitmask & EBT_NOPROTO) &&
109 FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
110 return 1;
111
112 if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
113 return 1;
114 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
115 return 1;
116 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
117 e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN))
118 return 1;
119 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
120 e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT))
121 return 1;
122
123 if (e->bitmask & EBT_SOURCEMAC) {
124 verdict = 0;
125 for (i = 0; i < 6; i++)
126 verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
127 e->sourcemsk[i];
128 if (FWINV2(verdict != 0, EBT_ISOURCE) )
129 return 1;
130 }
131 if (e->bitmask & EBT_DESTMAC) {
132 verdict = 0;
133 for (i = 0; i < 6; i++)
134 verdict |= (h->h_dest[i] ^ e->destmac[i]) &
135 e->destmsk[i];
136 if (FWINV2(verdict != 0, EBT_IDEST) )
137 return 1;
138 }
139 return 0;
140}
141
142
143unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
144 const struct net_device *in, const struct net_device *out,
145 struct ebt_table *table)
146{
147 int i, nentries;
148 struct ebt_entry *point;
149 struct ebt_counter *counter_base, *cb_base;
150 struct ebt_entry_target *t;
151 int verdict, sp = 0;
152 struct ebt_chainstack *cs;
153 struct ebt_entries *chaininfo;
154 char *base;
155 struct ebt_table_info *private;
156
157 read_lock_bh(&table->lock);
158 private = table->private;
159 cb_base = COUNTER_BASE(private->counters, private->nentries,
160 smp_processor_id());
161 if (private->chainstack)
162 cs = private->chainstack[smp_processor_id()];
163 else
164 cs = NULL;
165 chaininfo = private->hook_entry[hook];
166 nentries = private->hook_entry[hook]->nentries;
167 point = (struct ebt_entry *)(private->hook_entry[hook]->data);
168 counter_base = cb_base + private->hook_entry[hook]->counter_offset;
169
170 base = private->entries;
171 i = 0;
172 while (i < nentries) {
173 if (ebt_basic_match(point, eth_hdr(skb), in, out))
174 goto letscontinue;
175
176 if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, in, out) != 0)
177 goto letscontinue;
178
179
180 (*(counter_base + i)).pcnt++;
181 (*(counter_base + i)).bcnt += skb->len;
182
183
184
185 EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, hook, in,
186 out);
187
188 t = (struct ebt_entry_target *)
189 (((char *)point) + point->target_offset);
190
191 if (!t->u.target->target)
192 verdict = ((struct ebt_standard_target *)t)->verdict;
193 else
194 verdict = t->u.target->target(skb, hook,
195 in, out, t->data, t->target_size);
196 if (verdict == EBT_ACCEPT) {
197 read_unlock_bh(&table->lock);
198 return NF_ACCEPT;
199 }
200 if (verdict == EBT_DROP) {
201 read_unlock_bh(&table->lock);
202 return NF_DROP;
203 }
204 if (verdict == EBT_RETURN) {
205letsreturn:
206#ifdef CONFIG_NETFILTER_DEBUG
207 if (sp == 0) {
208 BUGPRINT("RETURN on base chain");
209
210 goto letscontinue;
211 }
212#endif
213 sp--;
214
215 i = cs[sp].n;
216 chaininfo = cs[sp].chaininfo;
217 nentries = chaininfo->nentries;
218 point = cs[sp].e;
219 counter_base = cb_base +
220 chaininfo->counter_offset;
221 continue;
222 }
223 if (verdict == EBT_CONTINUE)
224 goto letscontinue;
225#ifdef CONFIG_NETFILTER_DEBUG
226 if (verdict < 0) {
227 BUGPRINT("bogus standard verdict\n");
228 read_unlock_bh(&table->lock);
229 return NF_DROP;
230 }
231#endif
232
233 cs[sp].n = i + 1;
234 cs[sp].chaininfo = chaininfo;
235 cs[sp].e = (struct ebt_entry *)
236 (((char *)point) + point->next_offset);
237 i = 0;
238 chaininfo = (struct ebt_entries *) (base + verdict);
239#ifdef CONFIG_NETFILTER_DEBUG
240 if (chaininfo->distinguisher) {
241 BUGPRINT("jump to non-chain\n");
242 read_unlock_bh(&table->lock);
243 return NF_DROP;
244 }
245#endif
246 nentries = chaininfo->nentries;
247 point = (struct ebt_entry *)chaininfo->data;
248 counter_base = cb_base + chaininfo->counter_offset;
249 sp++;
250 continue;
251letscontinue:
252 point = (struct ebt_entry *)
253 (((char *)point) + point->next_offset);
254 i++;
255 }
256
257
258 if (chaininfo->policy == EBT_RETURN)
259 goto letsreturn;
260 if (chaininfo->policy == EBT_ACCEPT) {
261 read_unlock_bh(&table->lock);
262 return NF_ACCEPT;
263 }
264 read_unlock_bh(&table->lock);
265 return NF_DROP;
266}
267
268
269static inline void *
270find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
271 struct mutex *mutex)
272{
273 struct {
274 struct list_head list;
275 char name[EBT_FUNCTION_MAXNAMELEN];
276 } *e;
277
278 *error = mutex_lock_interruptible(mutex);
279 if (*error != 0)
280 return NULL;
281
282 list_for_each_entry(e, head, list) {
283 if (strcmp(e->name, name) == 0)
284 return e;
285 }
286 *error = -ENOENT;
287 mutex_unlock(mutex);
288 return NULL;
289}
290
291#ifndef CONFIG_KMOD
292#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
293#else
294static void *
295find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
296 int *error, struct mutex *mutex)
297{
298 void *ret;
299
300 ret = find_inlist_lock_noload(head, name, error, mutex);
301 if (!ret) {
302 request_module("%s%s", prefix, name);
303 ret = find_inlist_lock_noload(head, name, error, mutex);
304 }
305 return ret;
306}
307#endif
308
309static inline struct ebt_table *
310find_table_lock(const char *name, int *error, struct mutex *mutex)
311{
312 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex);
313}
314
315static inline struct ebt_match *
316find_match_lock(const char *name, int *error, struct mutex *mutex)
317{
318 return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex);
319}
320
321static inline struct ebt_watcher *
322find_watcher_lock(const char *name, int *error, struct mutex *mutex)
323{
324 return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex);
325}
326
327static inline struct ebt_target *
328find_target_lock(const char *name, int *error, struct mutex *mutex)
329{
330 return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex);
331}
332
333static inline int
334ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
335 const char *name, unsigned int hookmask, unsigned int *cnt)
336{
337 struct ebt_match *match;
338 size_t left = ((char *)e + e->watchers_offset) - (char *)m;
339 int ret;
340
341 if (left < sizeof(struct ebt_entry_match) ||
342 left - sizeof(struct ebt_entry_match) < m->match_size)
343 return -EINVAL;
344 match = find_match_lock(m->u.name, &ret, &ebt_mutex);
345 if (!match)
346 return ret;
347 m->u.match = match;
348 if (!try_module_get(match->me)) {
349 mutex_unlock(&ebt_mutex);
350 return -ENOENT;
351 }
352 mutex_unlock(&ebt_mutex);
353 if (match->check &&
354 match->check(name, hookmask, e, m->data, m->match_size) != 0) {
355 BUGPRINT("match->check failed\n");
356 module_put(match->me);
357 return -EINVAL;
358 }
359 (*cnt)++;
360 return 0;
361}
362
363static inline int
364ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
365 const char *name, unsigned int hookmask, unsigned int *cnt)
366{
367 struct ebt_watcher *watcher;
368 size_t left = ((char *)e + e->target_offset) - (char *)w;
369 int ret;
370
371 if (left < sizeof(struct ebt_entry_watcher) ||
372 left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
373 return -EINVAL;
374 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
375 if (!watcher)
376 return ret;
377 w->u.watcher = watcher;
378 if (!try_module_get(watcher->me)) {
379 mutex_unlock(&ebt_mutex);
380 return -ENOENT;
381 }
382 mutex_unlock(&ebt_mutex);
383 if (watcher->check &&
384 watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) {
385 BUGPRINT("watcher->check failed\n");
386 module_put(watcher->me);
387 return -EINVAL;
388 }
389 (*cnt)++;
390 return 0;
391}
392
393static int ebt_verify_pointers(struct ebt_replace *repl,
394 struct ebt_table_info *newinfo)
395{
396 unsigned int limit = repl->entries_size;
397 unsigned int valid_hooks = repl->valid_hooks;
398 unsigned int offset = 0;
399 int i;
400
401 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
407 while (offset < limit) {
408 size_t left = limit - offset;
409 struct ebt_entry *e = (void *)newinfo->entries + offset;
410
411 if (left < sizeof(unsigned int))
412 break;
413
414 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
415 if ((valid_hooks & (1 << i)) == 0)
416 continue;
417 if ((char __user *)repl->hook_entry[i] ==
418 repl->entries + offset)
419 break;
420 }
421
422 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
423 if (e->bitmask != 0) {
424
425
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 }
447
448
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 }
456 return 0;
457}
458
459
460
461
462
463static inline int
464ebt_check_entry_size_and_hooks(struct ebt_entry *e,
465 struct ebt_table_info *newinfo,
466 unsigned int *n, unsigned int *cnt,
467 unsigned int *totalcnt, unsigned int *udc_cnt)
468{
469 int i;
470
471 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
472 if ((void *)e == (void *)newinfo->hook_entry[i])
473 break;
474 }
475
476
477 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
478
479
480 if (*n != *cnt) {
481 BUGPRINT("nentries does not equal the nr of entries "
482 "in the chain\n");
483 return -EINVAL;
484 }
485 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
486 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
487
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)
495 (*udc_cnt)++;
496 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
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
512 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
513 BUGPRINT("target size too small\n");
514 return -EINVAL;
515 }
516 (*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
530
531
532static inline int
533ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
534 unsigned int *n, struct ebt_cl_stack *udc)
535{
536 int i;
537
538
539 if (e->bitmask)
540 return 0;
541 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
542 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
543 break;
544 }
545
546 if (i != NF_BR_NUMHOOKS)
547 return 0;
548
549 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
550
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)
564 m->u.match->destroy(m->data, m->match_size);
565 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)
576 w->u.watcher->destroy(w->data, w->watcher_size);
577 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
587 if (e->bitmask == 0)
588 return 0;
589
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)
596 t->u.target->destroy(t->data, t->target_size);
597 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,
604 const char *name, unsigned int *cnt,
605 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
606{
607 struct ebt_entry_target *t;
608 struct ebt_target *target;
609 unsigned int i, j, hook = 0, hookmask = 0;
610 size_t gap;
611 int ret;
612
613
614 if (e->bitmask == 0)
615 return 0;
616
617 if (e->bitmask & ~EBT_F_MASK) {
618 BUGPRINT("Unknown flag for bitmask\n");
619 return -EINVAL;
620 }
621 if (e->invflags & ~EBT_INV_MASK) {
622 BUGPRINT("Unknown flag for inv bitmask\n");
623 return -EINVAL;
624 }
625 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
626 BUGPRINT("NOPROTO & 802_3 not allowed\n");
627 return -EINVAL;
628 }
629
630 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
631 if (!newinfo->hook_entry[i])
632 continue;
633 if ((char *)newinfo->hook_entry[i] < (char *)e)
634 hook = i;
635 else
636 break;
637 }
638
639
640 if (i < NF_BR_NUMHOOKS)
641 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
642 else {
643 for (i = 0; i < udc_cnt; i++)
644 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
645 break;
646 if (i == 0)
647 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
648 else
649 hookmask = cl_s[i - 1].hookmask;
650 }
651 i = 0;
652 ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);
653 if (ret != 0)
654 goto cleanup_matches;
655 j = 0;
656 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
657 if (ret != 0)
658 goto cleanup_watchers;
659 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
660 gap = e->next_offset - e->target_offset;
661 target = find_target_lock(t->u.name, &ret, &ebt_mutex);
662 if (!target)
663 goto cleanup_watchers;
664 if (!try_module_get(target->me)) {
665 mutex_unlock(&ebt_mutex);
666 ret = -ENOENT;
667 goto cleanup_watchers;
668 }
669 mutex_unlock(&ebt_mutex);
670
671 t->u.target = target;
672 if (t->u.target == &ebt_standard_target) {
673 if (gap < sizeof(struct ebt_standard_target)) {
674 BUGPRINT("Standard target size too big\n");
675 ret = -EFAULT;
676 goto cleanup_watchers;
677 }
678 if (((struct ebt_standard_target *)t)->verdict <
679 -NUM_STANDARD_TARGETS) {
680 BUGPRINT("Invalid standard target\n");
681 ret = -EFAULT;
682 goto cleanup_watchers;
683 }
684 } else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
685 (t->u.target->check &&
686 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
687 module_put(t->u.target->me);
688 ret = -EFAULT;
689 goto cleanup_watchers;
690 }
691 (*cnt)++;
692 return 0;
693cleanup_watchers:
694 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);
695cleanup_matches:
696 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i);
697 return ret;
698}
699
700
701
702
703
704
705static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
706 unsigned int udc_cnt, unsigned int hooknr, char *base)
707{
708 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
709 struct ebt_entry *e = (struct ebt_entry *)chain->data;
710 struct ebt_entry_target *t;
711
712 while (pos < nentries || chain_nr != -1) {
713
714 if (pos == nentries) {
715
716 e = cl_s[chain_nr].cs.e;
717 if (cl_s[chain_nr].from != -1)
718 nentries =
719 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
720 else
721 nentries = chain->nentries;
722 pos = cl_s[chain_nr].cs.n;
723
724 cl_s[chain_nr].cs.n = 0;
725 chain_nr = cl_s[chain_nr].from;
726 if (pos == nentries)
727 continue;
728 }
729 t = (struct ebt_entry_target *)
730 (((char *)e) + e->target_offset);
731 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
732 goto letscontinue;
733 if (e->target_offset + sizeof(struct ebt_standard_target) >
734 e->next_offset) {
735 BUGPRINT("Standard target size too big\n");
736 return -1;
737 }
738 verdict = ((struct ebt_standard_target *)t)->verdict;
739 if (verdict >= 0) {
740 struct ebt_entries *hlp2 =
741 (struct ebt_entries *)(base + verdict);
742 for (i = 0; i < udc_cnt; i++)
743 if (hlp2 == cl_s[i].cs.chaininfo)
744 break;
745
746 if (i == udc_cnt) {
747 BUGPRINT("bad destination\n");
748 return -1;
749 }
750 if (cl_s[i].cs.n) {
751 BUGPRINT("loop\n");
752 return -1;
753 }
754 if (cl_s[i].hookmask & (1 << hooknr))
755 goto letscontinue;
756
757 cl_s[i].cs.n = pos + 1;
758 pos = 0;
759 cl_s[i].cs.e = ((void *)e + e->next_offset);
760 e = (struct ebt_entry *)(hlp2->data);
761 nentries = hlp2->nentries;
762 cl_s[i].from = chain_nr;
763 chain_nr = i;
764
765 cl_s[i].hookmask |= (1 << hooknr);
766 continue;
767 }
768letscontinue:
769 e = (void *)e + e->next_offset;
770 pos++;
771 }
772 return 0;
773}
774
775
776static int translate_table(char *name, struct ebt_table_info *newinfo)
777{
778 unsigned int i, j, k, udc_cnt;
779 int ret;
780 struct ebt_cl_stack *cl_s = NULL;
781
782 i = 0;
783 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
784 i++;
785 if (i == NF_BR_NUMHOOKS) {
786 BUGPRINT("No valid hooks specified\n");
787 return -EINVAL;
788 }
789 if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
790 BUGPRINT("Chains don't start at beginning\n");
791 return -EINVAL;
792 }
793
794
795 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
796 if (!newinfo->hook_entry[j])
797 continue;
798 if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
799 BUGPRINT("Hook order must be followed\n");
800 return -EINVAL;
801 }
802 i = j;
803 }
804
805
806 i = 0;
807 j = 0;
808 k = 0;
809
810 udc_cnt = 0;
811 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
812 ebt_check_entry_size_and_hooks, newinfo,
813 &i, &j, &k, &udc_cnt);
814
815 if (ret != 0)
816 return ret;
817
818 if (i != j) {
819 BUGPRINT("nentries does not equal the nr of entries in the "
820 "(last) chain\n");
821 return -EINVAL;
822 }
823 if (k != newinfo->nentries) {
824 BUGPRINT("Total nentries is wrong\n");
825 return -EINVAL;
826 }
827
828
829
830 if (udc_cnt) {
831
832
833 newinfo->chainstack =
834 vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
835 if (!newinfo->chainstack)
836 return -ENOMEM;
837 for_each_possible_cpu(i) {
838 newinfo->chainstack[i] =
839 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
840 if (!newinfo->chainstack[i]) {
841 while (i)
842 vfree(newinfo->chainstack[--i]);
843 vfree(newinfo->chainstack);
844 newinfo->chainstack = NULL;
845 return -ENOMEM;
846 }
847 }
848
849 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
850 if (!cl_s)
851 return -ENOMEM;
852 i = 0;
853 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
854 ebt_get_udc_positions, newinfo, &i, cl_s);
855
856 if (i != udc_cnt) {
857 BUGPRINT("i != udc_cnt\n");
858 vfree(cl_s);
859 return -EFAULT;
860 }
861 }
862
863
864 for (i = 0; i < NF_BR_NUMHOOKS; i++)
865 if (newinfo->hook_entry[i])
866 if (check_chainloops(newinfo->hook_entry[i],
867 cl_s, udc_cnt, i, newinfo->entries)) {
868 vfree(cl_s);
869 return -EINVAL;
870 }
871
872
873
874
875
876
877
878
879
880
881
882
883 i = 0;
884 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
885 ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt);
886 if (ret != 0) {
887 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
888 ebt_cleanup_entry, &i);
889 }
890 vfree(cl_s);
891 return ret;
892}
893
894
895static void get_counters(struct ebt_counter *oldcounters,
896 struct ebt_counter *counters, unsigned int nentries)
897{
898 int i, cpu;
899 struct ebt_counter *counter_base;
900
901
902 memcpy(counters, oldcounters,
903 sizeof(struct ebt_counter) * nentries);
904
905
906 for_each_possible_cpu(cpu) {
907 if (cpu == 0)
908 continue;
909 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
910 for (i = 0; i < nentries; i++) {
911 counters[i].pcnt += counter_base[i].pcnt;
912 counters[i].bcnt += counter_base[i].bcnt;
913 }
914 }
915}
916
917
918static int do_replace(void __user *user, unsigned int len)
919{
920 int ret, i, countersize;
921 struct ebt_table_info *newinfo;
922 struct ebt_replace tmp;
923 struct ebt_table *t;
924 struct ebt_counter *counterstmp = NULL;
925
926 struct ebt_table_info *table;
927
928 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
929 return -EFAULT;
930
931 if (len != sizeof(tmp) + tmp.entries_size) {
932 BUGPRINT("Wrong len argument\n");
933 return -EINVAL;
934 }
935
936 if (tmp.entries_size == 0) {
937 BUGPRINT("Entries_size never zero\n");
938 return -EINVAL;
939 }
940
941 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
942 SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
943 return -ENOMEM;
944 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
945 return -ENOMEM;
946
947 tmp.name[sizeof(tmp.name) - 1] = 0;
948
949 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
950 newinfo = vmalloc(sizeof(*newinfo) + countersize);
951 if (!newinfo)
952 return -ENOMEM;
953
954 if (countersize)
955 memset(newinfo->counters, 0, countersize);
956
957 newinfo->entries = vmalloc(tmp.entries_size);
958 if (!newinfo->entries) {
959 ret = -ENOMEM;
960 goto free_newinfo;
961 }
962 if (copy_from_user(
963 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
964 BUGPRINT("Couldn't copy entries from userspace\n");
965 ret = -EFAULT;
966 goto free_entries;
967 }
968
969
970
971 if (tmp.num_counters) {
972 counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
973 if (!counterstmp) {
974 ret = -ENOMEM;
975 goto free_entries;
976 }
977 }
978 else
979 counterstmp = NULL;
980
981
982 newinfo->chainstack = NULL;
983 ret = ebt_verify_pointers(&tmp, newinfo);
984 if (ret != 0)
985 goto free_counterstmp;
986
987 ret = translate_table(tmp.name, newinfo);
988
989 if (ret != 0)
990 goto free_counterstmp;
991
992 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
993 if (!t) {
994 ret = -ENOENT;
995 goto free_iterate;
996 }
997
998
999 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
1000 goto free_unlock;
1001
1002 if (tmp.num_counters && tmp.num_counters != t->private->nentries) {
1003 BUGPRINT("Wrong nr. of counters requested\n");
1004 ret = -EINVAL;
1005 goto free_unlock;
1006 }
1007
1008
1009 table = t->private;
1010
1011 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
1012 ret = -ENOENT;
1013 goto free_unlock;
1014 } else if (table->nentries && !newinfo->nentries)
1015 module_put(t->me);
1016
1017 write_lock_bh(&t->lock);
1018 if (tmp.num_counters)
1019 get_counters(t->private->counters, counterstmp,
1020 t->private->nentries);
1021
1022 t->private = newinfo;
1023 write_unlock_bh(&t->lock);
1024 mutex_unlock(&ebt_mutex);
1025
1026
1027
1028
1029 if (tmp.num_counters &&
1030 copy_to_user(tmp.counters, counterstmp,
1031 tmp.num_counters * sizeof(struct ebt_counter))) {
1032 BUGPRINT("Couldn't copy counters to userspace\n");
1033 ret = -EFAULT;
1034 }
1035 else
1036 ret = 0;
1037
1038
1039 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
1040 ebt_cleanup_entry, NULL);
1041
1042 vfree(table->entries);
1043 if (table->chainstack) {
1044 for_each_possible_cpu(i)
1045 vfree(table->chainstack[i]);
1046 vfree(table->chainstack);
1047 }
1048 vfree(table);
1049
1050 vfree(counterstmp);
1051 return ret;
1052
1053free_unlock:
1054 mutex_unlock(&ebt_mutex);
1055free_iterate:
1056 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1057 ebt_cleanup_entry, NULL);
1058free_counterstmp:
1059 vfree(counterstmp);
1060
1061 if (newinfo->chainstack) {
1062 for_each_possible_cpu(i)
1063 vfree(newinfo->chainstack[i]);
1064 vfree(newinfo->chainstack);
1065 }
1066free_entries:
1067 vfree(newinfo->entries);
1068free_newinfo:
1069 vfree(newinfo);
1070 return ret;
1071}
1072
1073int ebt_register_target(struct ebt_target *target)
1074{
1075 struct ebt_target *t;
1076 int ret;
1077
1078 ret = mutex_lock_interruptible(&ebt_mutex);
1079 if (ret != 0)
1080 return ret;
1081 list_for_each_entry(t, &ebt_targets, list) {
1082 if (strcmp(t->name, target->name) == 0) {
1083 mutex_unlock(&ebt_mutex);
1084 return -EEXIST;
1085 }
1086 }
1087 list_add(&target->list, &ebt_targets);
1088 mutex_unlock(&ebt_mutex);
1089
1090 return 0;
1091}
1092
1093void ebt_unregister_target(struct ebt_target *target)
1094{
1095 mutex_lock(&ebt_mutex);
1096 list_del(&target->list);
1097 mutex_unlock(&ebt_mutex);
1098}
1099
1100int ebt_register_match(struct ebt_match *match)
1101{
1102 struct ebt_match *m;
1103 int ret;
1104
1105 ret = mutex_lock_interruptible(&ebt_mutex);
1106 if (ret != 0)
1107 return ret;
1108 list_for_each_entry(m, &ebt_matches, list) {
1109 if (strcmp(m->name, match->name) == 0) {
1110 mutex_unlock(&ebt_mutex);
1111 return -EEXIST;
1112 }
1113 }
1114 list_add(&match->list, &ebt_matches);
1115 mutex_unlock(&ebt_mutex);
1116
1117 return 0;
1118}
1119
1120void ebt_unregister_match(struct ebt_match *match)
1121{
1122 mutex_lock(&ebt_mutex);
1123 list_del(&match->list);
1124 mutex_unlock(&ebt_mutex);
1125}
1126
1127int ebt_register_watcher(struct ebt_watcher *watcher)
1128{
1129 struct ebt_watcher *w;
1130 int ret;
1131
1132 ret = mutex_lock_interruptible(&ebt_mutex);
1133 if (ret != 0)
1134 return ret;
1135 list_for_each_entry(w, &ebt_watchers, list) {
1136 if (strcmp(w->name, watcher->name) == 0) {
1137 mutex_unlock(&ebt_mutex);
1138 return -EEXIST;
1139 }
1140 }
1141 list_add(&watcher->list, &ebt_watchers);
1142 mutex_unlock(&ebt_mutex);
1143
1144 return 0;
1145}
1146
1147void ebt_unregister_watcher(struct ebt_watcher *watcher)
1148{
1149 mutex_lock(&ebt_mutex);
1150 list_del(&watcher->list);
1151 mutex_unlock(&ebt_mutex);
1152}
1153
1154int ebt_register_table(struct ebt_table *table)
1155{
1156 struct ebt_table_info *newinfo;
1157 struct ebt_table *t;
1158 struct ebt_replace_kernel *repl;
1159 int ret, i, countersize;
1160 void *p;
1161
1162 if (!table || !(repl = table->table) || !repl->entries ||
1163 repl->entries_size == 0 ||
1164 repl->counters || table->private) {
1165 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1166 return -EINVAL;
1167 }
1168
1169 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
1170 newinfo = vmalloc(sizeof(*newinfo) + countersize);
1171 ret = -ENOMEM;
1172 if (!newinfo)
1173 return -ENOMEM;
1174
1175 p = vmalloc(repl->entries_size);
1176 if (!p)
1177 goto free_newinfo;
1178
1179 memcpy(p, repl->entries, repl->entries_size);
1180 newinfo->entries = p;
1181
1182 newinfo->entries_size = repl->entries_size;
1183 newinfo->nentries = repl->nentries;
1184
1185 if (countersize)
1186 memset(newinfo->counters, 0, countersize);
1187
1188
1189 newinfo->chainstack = NULL;
1190 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1191 if ((repl->valid_hooks & (1 << i)) == 0)
1192 newinfo->hook_entry[i] = NULL;
1193 else
1194 newinfo->hook_entry[i] = p +
1195 ((char *)repl->hook_entry[i] - repl->entries);
1196 }
1197 ret = translate_table(repl->name, newinfo);
1198 if (ret != 0) {
1199 BUGPRINT("Translate_table failed\n");
1200 goto free_chainstack;
1201 }
1202
1203 if (table->check && table->check(newinfo, table->valid_hooks)) {
1204 BUGPRINT("The table doesn't like its own initial data, lol\n");
1205 return -EINVAL;
1206 }
1207
1208 table->private = newinfo;
1209 rwlock_init(&table->lock);
1210 ret = mutex_lock_interruptible(&ebt_mutex);
1211 if (ret != 0)
1212 goto free_chainstack;
1213
1214 list_for_each_entry(t, &ebt_tables, list) {
1215 if (strcmp(t->name, table->name) == 0) {
1216 ret = -EEXIST;
1217 BUGPRINT("Table name already exists\n");
1218 goto free_unlock;
1219 }
1220 }
1221
1222
1223 if (newinfo->nentries && !try_module_get(table->me)) {
1224 ret = -ENOENT;
1225 goto free_unlock;
1226 }
1227 list_add(&table->list, &ebt_tables);
1228 mutex_unlock(&ebt_mutex);
1229 return 0;
1230free_unlock:
1231 mutex_unlock(&ebt_mutex);
1232free_chainstack:
1233 if (newinfo->chainstack) {
1234 for_each_possible_cpu(i)
1235 vfree(newinfo->chainstack[i]);
1236 vfree(newinfo->chainstack);
1237 }
1238 vfree(newinfo->entries);
1239free_newinfo:
1240 vfree(newinfo);
1241 return ret;
1242}
1243
1244void ebt_unregister_table(struct ebt_table *table)
1245{
1246 int i;
1247
1248 if (!table) {
1249 BUGPRINT("Request to unregister NULL table!!!\n");
1250 return;
1251 }
1252 mutex_lock(&ebt_mutex);
1253 list_del(&table->list);
1254 mutex_unlock(&ebt_mutex);
1255 vfree(table->private->entries);
1256 if (table->private->chainstack) {
1257 for_each_possible_cpu(i)
1258 vfree(table->private->chainstack[i]);
1259 vfree(table->private->chainstack);
1260 }
1261 vfree(table->private);
1262}
1263
1264
1265static int update_counters(void __user *user, unsigned int len)
1266{
1267 int i, ret;
1268 struct ebt_counter *tmp;
1269 struct ebt_replace hlp;
1270 struct ebt_table *t;
1271
1272 if (copy_from_user(&hlp, user, sizeof(hlp)))
1273 return -EFAULT;
1274
1275 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1276 return -EINVAL;
1277 if (hlp.num_counters == 0)
1278 return -EINVAL;
1279
1280 if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
1281 MEMPRINT("Update_counters && nomemory\n");
1282 return -ENOMEM;
1283 }
1284
1285 t = find_table_lock(hlp.name, &ret, &ebt_mutex);
1286 if (!t)
1287 goto free_tmp;
1288
1289 if (hlp.num_counters != t->private->nentries) {
1290 BUGPRINT("Wrong nr of counters\n");
1291 ret = -EINVAL;
1292 goto unlock_mutex;
1293 }
1294
1295 if ( copy_from_user(tmp, hlp.counters,
1296 hlp.num_counters * sizeof(struct ebt_counter)) ) {
1297 BUGPRINT("Updata_counters && !cfu\n");
1298 ret = -EFAULT;
1299 goto unlock_mutex;
1300 }
1301
1302
1303 write_lock_bh(&t->lock);
1304
1305
1306 for (i = 0; i < hlp.num_counters; i++) {
1307 t->private->counters[i].pcnt += tmp[i].pcnt;
1308 t->private->counters[i].bcnt += tmp[i].bcnt;
1309 }
1310
1311 write_unlock_bh(&t->lock);
1312 ret = 0;
1313unlock_mutex:
1314 mutex_unlock(&ebt_mutex);
1315free_tmp:
1316 vfree(tmp);
1317 return ret;
1318}
1319
1320static inline int ebt_make_matchname(struct ebt_entry_match *m,
1321 char *base, char __user *ubase)
1322{
1323 char __user *hlp = ubase + ((char *)m - base);
1324 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1325 return -EFAULT;
1326 return 0;
1327}
1328
1329static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
1330 char *base, char __user *ubase)
1331{
1332 char __user *hlp = ubase + ((char *)w - base);
1333 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1334 return -EFAULT;
1335 return 0;
1336}
1337
1338static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase)
1339{
1340 int ret;
1341 char __user *hlp;
1342 struct ebt_entry_target *t;
1343
1344 if (e->bitmask == 0)
1345 return 0;
1346
1347 hlp = ubase + (((char *)e + e->target_offset) - base);
1348 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
1349
1350 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1351 if (ret != 0)
1352 return ret;
1353 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1354 if (ret != 0)
1355 return ret;
1356 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1357 return -EFAULT;
1358 return 0;
1359}
1360
1361
1362static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1363 int *len, int cmd)
1364{
1365 struct ebt_replace tmp;
1366 struct ebt_counter *counterstmp, *oldcounters;
1367 unsigned int entries_size, nentries;
1368 char *entries;
1369
1370 if (cmd == EBT_SO_GET_ENTRIES) {
1371 entries_size = t->private->entries_size;
1372 nentries = t->private->nentries;
1373 entries = t->private->entries;
1374 oldcounters = t->private->counters;
1375 } else {
1376 entries_size = t->table->entries_size;
1377 nentries = t->table->nentries;
1378 entries = t->table->entries;
1379 oldcounters = t->table->counters;
1380 }
1381
1382 if (copy_from_user(&tmp, user, sizeof(tmp))) {
1383 BUGPRINT("Cfu didn't work\n");
1384 return -EFAULT;
1385 }
1386
1387 if (*len != sizeof(struct ebt_replace) + entries_size +
1388 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
1389 BUGPRINT("Wrong size\n");
1390 return -EINVAL;
1391 }
1392
1393 if (tmp.nentries != nentries) {
1394 BUGPRINT("Nentries wrong\n");
1395 return -EINVAL;
1396 }
1397
1398 if (tmp.entries_size != entries_size) {
1399 BUGPRINT("Wrong size\n");
1400 return -EINVAL;
1401 }
1402
1403
1404 if (tmp.num_counters) {
1405 if (tmp.num_counters != nentries) {
1406 BUGPRINT("Num_counters wrong\n");
1407 return -EINVAL;
1408 }
1409 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
1410 if (!counterstmp) {
1411 MEMPRINT("Couldn't copy counters, out of memory\n");
1412 return -ENOMEM;
1413 }
1414 write_lock_bh(&t->lock);
1415 get_counters(oldcounters, counterstmp, nentries);
1416 write_unlock_bh(&t->lock);
1417
1418 if (copy_to_user(tmp.counters, counterstmp,
1419 nentries * sizeof(struct ebt_counter))) {
1420 BUGPRINT("Couldn't copy counters to userspace\n");
1421 vfree(counterstmp);
1422 return -EFAULT;
1423 }
1424 vfree(counterstmp);
1425 }
1426
1427 if (copy_to_user(tmp.entries, entries, entries_size)) {
1428 BUGPRINT("Couldn't copy entries to userspace\n");
1429 return -EFAULT;
1430 }
1431
1432 return EBT_ENTRY_ITERATE(entries, entries_size,
1433 ebt_make_names, entries, tmp.entries);
1434}
1435
1436static int do_ebt_set_ctl(struct sock *sk,
1437 int cmd, void __user *user, unsigned int len)
1438{
1439 int ret;
1440
1441 if (!capable(CAP_NET_ADMIN))
1442 return -EPERM;
1443
1444 switch(cmd) {
1445 case EBT_SO_SET_ENTRIES:
1446 ret = do_replace(user, len);
1447 break;
1448 case EBT_SO_SET_COUNTERS:
1449 ret = update_counters(user, len);
1450 break;
1451 default:
1452 ret = -EINVAL;
1453 }
1454 return ret;
1455}
1456
1457static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1458{
1459 int ret;
1460 struct ebt_replace tmp;
1461 struct ebt_table *t;
1462
1463 if (!capable(CAP_NET_ADMIN))
1464 return -EPERM;
1465
1466 if (copy_from_user(&tmp, user, sizeof(tmp)))
1467 return -EFAULT;
1468
1469 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1470 if (!t)
1471 return ret;
1472
1473 switch(cmd) {
1474 case EBT_SO_GET_INFO:
1475 case EBT_SO_GET_INIT_INFO:
1476 if (*len != sizeof(struct ebt_replace)){
1477 ret = -EINVAL;
1478 mutex_unlock(&ebt_mutex);
1479 break;
1480 }
1481 if (cmd == EBT_SO_GET_INFO) {
1482 tmp.nentries = t->private->nentries;
1483 tmp.entries_size = t->private->entries_size;
1484 tmp.valid_hooks = t->valid_hooks;
1485 } else {
1486 tmp.nentries = t->table->nentries;
1487 tmp.entries_size = t->table->entries_size;
1488 tmp.valid_hooks = t->table->valid_hooks;
1489 }
1490 mutex_unlock(&ebt_mutex);
1491 if (copy_to_user(user, &tmp, *len) != 0){
1492 BUGPRINT("c2u Didn't work\n");
1493 ret = -EFAULT;
1494 break;
1495 }
1496 ret = 0;
1497 break;
1498
1499 case EBT_SO_GET_ENTRIES:
1500 case EBT_SO_GET_INIT_ENTRIES:
1501 ret = copy_everything_to_user(t, user, len, cmd);
1502 mutex_unlock(&ebt_mutex);
1503 break;
1504
1505 default:
1506 mutex_unlock(&ebt_mutex);
1507 ret = -EINVAL;
1508 }
1509
1510 return ret;
1511}
1512
1513static struct nf_sockopt_ops ebt_sockopts =
1514{
1515 .pf = PF_INET,
1516 .set_optmin = EBT_BASE_CTL,
1517 .set_optmax = EBT_SO_SET_MAX + 1,
1518 .set = do_ebt_set_ctl,
1519 .get_optmin = EBT_BASE_CTL,
1520 .get_optmax = EBT_SO_GET_MAX + 1,
1521 .get = do_ebt_get_ctl,
1522 .owner = THIS_MODULE,
1523};
1524
1525static int __init ebtables_init(void)
1526{
1527 int ret;
1528
1529 mutex_lock(&ebt_mutex);
1530 list_add(&ebt_standard_target.list, &ebt_targets);
1531 mutex_unlock(&ebt_mutex);
1532 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
1533 return ret;
1534
1535 printk(KERN_INFO "Ebtables v2.0 registered\n");
1536 return 0;
1537}
1538
1539static void __exit ebtables_fini(void)
1540{
1541 nf_unregister_sockopt(&ebt_sockopts);
1542 printk(KERN_INFO "Ebtables v2.0 unregistered\n");
1543}
1544
1545EXPORT_SYMBOL(ebt_register_table);
1546EXPORT_SYMBOL(ebt_unregister_table);
1547EXPORT_SYMBOL(ebt_register_match);
1548EXPORT_SYMBOL(ebt_unregister_match);
1549EXPORT_SYMBOL(ebt_register_watcher);
1550EXPORT_SYMBOL(ebt_unregister_watcher);
1551EXPORT_SYMBOL(ebt_register_target);
1552EXPORT_SYMBOL(ebt_unregister_target);
1553EXPORT_SYMBOL(ebt_do_table);
1554module_init(ebtables_init);
1555module_exit(ebtables_fini);
1556MODULE_LICENSE("GPL");
1557