Commit 980e2c9b authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/net-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 4cf14800 44032573
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ebtables * ebtables
* *
* Author: * Author:
* Bart De Schuymer <bart.de.schuymer@pandora.be> * Bart De Schuymer <bdschuym@pandora.be>
* *
* ebtables.c,v 2.0, July, 2002 * ebtables.c,v 2.0, July, 2002
* *
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
// used for print_string /* used for print_string */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/tty.h> #include <linux/tty.h>
...@@ -27,18 +27,20 @@ ...@@ -27,18 +27,20 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <net/sock.h> #include <net/sock.h>
// needed for logical [in,out]-dev filtering /* needed for logical [in,out]-dev filtering */
#include "../br_private.h" #include "../br_private.h"
// list_named_find /* list_named_find */
#define ASSERT_READ_LOCK(x) #define ASSERT_READ_LOCK(x)
#define ASSERT_WRITE_LOCK(x) #define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/listhelp.h> #include <linux/netfilter_ipv4/listhelp.h>
#if 0 // use this for remote debugging #if 0
// Copyright (C) 1998 by Ori Pomerantz /* use this for remote debugging
// Print the string to the appropriate tty, the one * Copyright (C) 1998 by Ori Pomerantz
// the current task uses * Print the string to the appropriate tty, the one
* the current task uses
*/
static void print_string(char *str) static void print_string(char *str)
{ {
struct tty_struct *my_tty; struct tty_struct *my_tty;
...@@ -55,20 +57,22 @@ static void print_string(char *str) ...@@ -55,20 +57,22 @@ static void print_string(char *str)
#else #else
#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\ #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
"report to author: "format, ## args) "report to author: "format, ## args)
// #define BUGPRINT(format, args...) /* #define BUGPRINT(format, args...) */
#endif #endif
#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\ #define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
": out of memory: "format, ## args) ": out of memory: "format, ## args)
// #define MEMPRINT(format, args...) /* #define MEMPRINT(format, args...) */
// Each cpu has its own set of counters, so there is no need for write_lock in /*
// the softirq * Each cpu has its own set of counters, so there is no need for write_lock in
// For reading or updating the counters, the user context needs to * the softirq
// get a write_lock * For reading or updating the counters, the user context needs to
* get a write_lock
*/
// The size of each set of counters is altered to get cache alignment /* The size of each set of counters is altered to get cache alignment */
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter))) #define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \ #define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
...@@ -91,7 +95,7 @@ static inline int ebt_do_watcher (struct ebt_entry_watcher *w, ...@@ -91,7 +95,7 @@ static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
{ {
w->u.watcher->watcher(skb, in, out, w->data, w->u.watcher->watcher(skb, in, out, w->data,
w->watcher_size); w->watcher_size);
// watchers don't give a verdict /* watchers don't give a verdict */
return 0; return 0;
} }
...@@ -113,7 +117,7 @@ static inline int ebt_dev_check(char *entry, const struct net_device *device) ...@@ -113,7 +117,7 @@ static inline int ebt_dev_check(char *entry, const struct net_device *device)
} }
#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg)) #define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
// process standard matches /* process standard matches */
static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h, static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
const struct net_device *in, const struct net_device *out) const struct net_device *in, const struct net_device *out)
{ {
...@@ -156,7 +160,7 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h, ...@@ -156,7 +160,7 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
return 0; return 0;
} }
// Do some firewalling /* Do some firewalling */
unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
const struct net_device *in, const struct net_device *out, const struct net_device *in, const struct net_device *out,
struct ebt_table *table) struct ebt_table *table)
...@@ -182,7 +186,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, ...@@ -182,7 +186,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
nentries = private->hook_entry[hook]->nentries; nentries = private->hook_entry[hook]->nentries;
point = (struct ebt_entry *)(private->hook_entry[hook]->data); point = (struct ebt_entry *)(private->hook_entry[hook]->data);
counter_base = cb_base + private->hook_entry[hook]->counter_offset; counter_base = cb_base + private->hook_entry[hook]->counter_offset;
// base for chain jumps /* base for chain jumps */
base = private->entries; base = private->entries;
i = 0; i = 0;
while (i < nentries) { while (i < nentries) {
...@@ -192,18 +196,18 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, ...@@ -192,18 +196,18 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0) if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0)
goto letscontinue; goto letscontinue;
// increase counter /* increase counter */
(*(counter_base + i)).pcnt++; (*(counter_base + i)).pcnt++;
(*(counter_base + i)).bcnt+=(**pskb).len; (*(counter_base + i)).bcnt+=(**pskb).len;
// these should only watch: not modify, nor tell us /* these should only watch: not modify, nor tell us
// what to do with the packet what to do with the packet */
EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, in, EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, in,
out); out);
t = (struct ebt_entry_target *) t = (struct ebt_entry_target *)
(((char *)point) + point->target_offset); (((char *)point) + point->target_offset);
// standard target /* standard target */
if (!t->u.target->target) if (!t->u.target->target)
verdict = ((struct ebt_standard_target *)t)->verdict; verdict = ((struct ebt_standard_target *)t)->verdict;
else else
...@@ -222,12 +226,12 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, ...@@ -222,12 +226,12 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
#ifdef CONFIG_NETFILTER_DEBUG #ifdef CONFIG_NETFILTER_DEBUG
if (sp == 0) { if (sp == 0) {
BUGPRINT("RETURN on base chain"); BUGPRINT("RETURN on base chain");
// act like this is EBT_CONTINUE /* act like this is EBT_CONTINUE */
goto letscontinue; goto letscontinue;
} }
#endif #endif
sp--; sp--;
// put all the local variables right /* put all the local variables right */
i = cs[sp].n; i = cs[sp].n;
chaininfo = cs[sp].chaininfo; chaininfo = cs[sp].chaininfo;
nentries = chaininfo->nentries; nentries = chaininfo->nentries;
...@@ -245,7 +249,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, ...@@ -245,7 +249,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
return NF_DROP; return NF_DROP;
} }
#endif #endif
// jump to a udc /* jump to a udc */
cs[sp].n = i + 1; cs[sp].n = i + 1;
cs[sp].chaininfo = chaininfo; cs[sp].chaininfo = chaininfo;
cs[sp].e = (struct ebt_entry *) cs[sp].e = (struct ebt_entry *)
...@@ -270,7 +274,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, ...@@ -270,7 +274,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
i++; i++;
} }
// I actually like this :) /* I actually like this :) */
if (chaininfo->policy == EBT_RETURN) if (chaininfo->policy == EBT_RETURN)
goto letsreturn; goto letsreturn;
if (chaininfo->policy == EBT_ACCEPT) { if (chaininfo->policy == EBT_ACCEPT) {
...@@ -281,7 +285,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, ...@@ -281,7 +285,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
return NF_DROP; return NF_DROP;
} }
// If it succeeds, returns element and locks mutex /* If it succeeds, returns element and locks mutex */
static inline void * static inline void *
find_inlist_lock_noload(struct list_head *head, const char *name, int *error, find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
struct semaphore *mutex) struct semaphore *mutex)
...@@ -359,14 +363,15 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e, ...@@ -359,14 +363,15 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
if (!match) if (!match)
return ret; return ret;
m->u.match = match; m->u.match = match;
if (match->me) if (!try_module_get(match->me)) {
__MOD_INC_USE_COUNT(match->me); up(&ebt_mutex);
return -EINVAL;
}
up(&ebt_mutex); up(&ebt_mutex);
if (match->check && if (match->check &&
match->check(name, hookmask, e, m->data, m->match_size) != 0) { match->check(name, hookmask, e, m->data, m->match_size) != 0) {
BUGPRINT("match->check failed\n"); BUGPRINT("match->check failed\n");
if (match->me) module_put(match->me);
__MOD_DEC_USE_COUNT(match->me);
return -EINVAL; return -EINVAL;
} }
(*cnt)++; (*cnt)++;
...@@ -387,22 +392,25 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, ...@@ -387,22 +392,25 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
if (!watcher) if (!watcher)
return ret; return ret;
w->u.watcher = watcher; w->u.watcher = watcher;
if (watcher->me) if (!try_module_get(watcher->me)) {
__MOD_INC_USE_COUNT(watcher->me); up(&ebt_mutex);
return -EINVAL;
}
up(&ebt_mutex); up(&ebt_mutex);
if (watcher->check && if (watcher->check &&
watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) { watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) {
BUGPRINT("watcher->check failed\n"); BUGPRINT("watcher->check failed\n");
if (watcher->me) module_put(watcher->me);
__MOD_DEC_USE_COUNT(watcher->me);
return -EINVAL; return -EINVAL;
} }
(*cnt)++; (*cnt)++;
return 0; return 0;
} }
// this one is very careful, as it is the first function /*
// to parse the userspace data * this one is very careful, as it is the first function
* to parse the userspace data
*/
static inline int static inline int
ebt_check_entry_size_and_hooks(struct ebt_entry *e, ebt_check_entry_size_and_hooks(struct ebt_entry *e,
struct ebt_table_info *newinfo, char *base, char *limit, struct ebt_table_info *newinfo, char *base, char *limit,
...@@ -418,24 +426,24 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, ...@@ -418,24 +426,24 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
(char *)e - newinfo->entries) (char *)e - newinfo->entries)
break; break;
} }
// beginning of a new chain /* beginning of a new chain
// if i == NF_BR_NUMHOOKS it must be a user defined chain if i == NF_BR_NUMHOOKS it must be a user defined chain */
if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) { if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) != 0) { if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) != 0) {
// we make userspace set this right, /* we make userspace set this right,
// so there is no misunderstanding so there is no misunderstanding */
BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set " BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
"in distinguisher\n"); "in distinguisher\n");
return -EINVAL; return -EINVAL;
} }
// this checks if the previous chain has as many entries /* this checks if the previous chain has as many entries
// as it said it has as it said it has */
if (*n != *cnt) { if (*n != *cnt) {
BUGPRINT("nentries does not equal the nr of entries " BUGPRINT("nentries does not equal the nr of entries "
"in the chain\n"); "in the chain\n");
return -EINVAL; return -EINVAL;
} }
// before we look at the struct, be sure it is not too big /* before we look at the struct, be sure it is not too big */
if ((char *)hook_entries[i] + sizeof(struct ebt_entries) if ((char *)hook_entries[i] + sizeof(struct ebt_entries)
> limit) { > limit) {
BUGPRINT("entries_size too small\n"); BUGPRINT("entries_size too small\n");
...@@ -443,14 +451,14 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, ...@@ -443,14 +451,14 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
} }
if (((struct ebt_entries *)e)->policy != EBT_DROP && if (((struct ebt_entries *)e)->policy != EBT_DROP &&
((struct ebt_entries *)e)->policy != EBT_ACCEPT) { ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
// only RETURN from udc /* only RETURN from udc */
if (i != NF_BR_NUMHOOKS || if (i != NF_BR_NUMHOOKS ||
((struct ebt_entries *)e)->policy != EBT_RETURN) { ((struct ebt_entries *)e)->policy != EBT_RETURN) {
BUGPRINT("bad policy\n"); BUGPRINT("bad policy\n");
return -EINVAL; return -EINVAL;
} }
} }
if (i == NF_BR_NUMHOOKS) // it's a user defined chain if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
(*udc_cnt)++; (*udc_cnt)++;
else else
newinfo->hook_entry[i] = (struct ebt_entries *)e; newinfo->hook_entry[i] = (struct ebt_entries *)e;
...@@ -462,14 +470,14 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e, ...@@ -462,14 +470,14 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
*cnt = 0; *cnt = 0;
return 0; return 0;
} }
// a plain old entry, heh /* a plain old entry, heh */
if (sizeof(struct ebt_entry) > e->watchers_offset || if (sizeof(struct ebt_entry) > e->watchers_offset ||
e->watchers_offset > e->target_offset || e->watchers_offset > e->target_offset ||
e->target_offset >= e->next_offset) { e->target_offset >= e->next_offset) {
BUGPRINT("entry offsets not in right order\n"); BUGPRINT("entry offsets not in right order\n");
return -EINVAL; return -EINVAL;
} }
// this is not checked anywhere else /* this is not checked anywhere else */
if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) { if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
BUGPRINT("target size too small\n"); BUGPRINT("target size too small\n");
return -EINVAL; return -EINVAL;
...@@ -487,8 +495,10 @@ struct ebt_cl_stack ...@@ -487,8 +495,10 @@ struct ebt_cl_stack
unsigned int hookmask; unsigned int hookmask;
}; };
// we need these positions to check that the jumps to a different part of the /*
// entries is a jump to the beginning of a new chain. * we need these positions to check that the jumps to a different part of the
* entries is a jump to the beginning of a new chain.
*/
static inline int static inline int
ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo, ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks, struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks,
...@@ -496,7 +506,7 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo, ...@@ -496,7 +506,7 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
{ {
int i; int i;
// we're only interested in chain starts /* we're only interested in chain starts */
if (e->bitmask & EBT_ENTRY_OR_ENTRIES) if (e->bitmask & EBT_ENTRY_OR_ENTRIES)
return 0; return 0;
for (i = 0; i < NF_BR_NUMHOOKS; i++) { for (i = 0; i < NF_BR_NUMHOOKS; i++) {
...@@ -505,12 +515,12 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo, ...@@ -505,12 +515,12 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
if (newinfo->hook_entry[i] == (struct ebt_entries *)e) if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
break; break;
} }
// only care about udc /* only care about udc */
if (i != NF_BR_NUMHOOKS) if (i != NF_BR_NUMHOOKS)
return 0; return 0;
udc[*n].cs.chaininfo = (struct ebt_entries *)e; udc[*n].cs.chaininfo = (struct ebt_entries *)e;
// these initialisations are depended on later in check_chainloops() /* these initialisations are depended on later in check_chainloops() */
udc[*n].cs.n = 0; udc[*n].cs.n = 0;
udc[*n].hookmask = 0; udc[*n].hookmask = 0;
...@@ -525,8 +535,7 @@ ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i) ...@@ -525,8 +535,7 @@ ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
return 1; return 1;
if (m->u.match->destroy) if (m->u.match->destroy)
m->u.match->destroy(m->data, m->match_size); m->u.match->destroy(m->data, m->match_size);
if (m->u.match->me) module_put(m->u.match->me);
__MOD_DEC_USE_COUNT(m->u.match->me);
return 0; return 0;
} }
...@@ -538,8 +547,7 @@ ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i) ...@@ -538,8 +547,7 @@ ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
return 1; return 1;
if (w->u.watcher->destroy) if (w->u.watcher->destroy)
w->u.watcher->destroy(w->data, w->watcher_size); w->u.watcher->destroy(w->data, w->watcher_size);
if (w->u.watcher->me) module_put(w->u.watcher->me);
__MOD_DEC_USE_COUNT(w->u.watcher->me);
return 0; return 0;
} }
...@@ -551,7 +559,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt) ...@@ -551,7 +559,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0) if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
return 0; return 0;
// we're done /* we're done */
if (cnt && (*cnt)-- == 0) if (cnt && (*cnt)-- == 0)
return 1; return 1;
EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL); EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
...@@ -559,8 +567,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt) ...@@ -559,8 +567,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
if (t->u.target->destroy) if (t->u.target->destroy)
t->u.target->destroy(t->data, t->target_size); t->u.target->destroy(t->data, t->target_size);
if (t->u.target->me) module_put(t->u.target->me);
__MOD_DEC_USE_COUNT(t->u.target->me);
return 0; return 0;
} }
...@@ -575,7 +582,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, ...@@ -575,7 +582,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
unsigned int i, j, hook = 0, hookmask = 0; unsigned int i, j, hook = 0, hookmask = 0;
int ret; int ret;
// Don't mess with the struct ebt_entries /* don't mess with the struct ebt_entries */
if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0) if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
return 0; return 0;
...@@ -591,7 +598,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, ...@@ -591,7 +598,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
BUGPRINT("NOPROTO & 802_3 not allowed\n"); BUGPRINT("NOPROTO & 802_3 not allowed\n");
return -EINVAL; return -EINVAL;
} }
// what hook do we belong to? /* what hook do we belong to? */
for (i = 0; i < NF_BR_NUMHOOKS; i++) { for (i = 0; i < NF_BR_NUMHOOKS; i++) {
if ((valid_hooks & (1 << i)) == 0) if ((valid_hooks & (1 << i)) == 0)
continue; continue;
...@@ -600,8 +607,8 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, ...@@ -600,8 +607,8 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
else else
break; break;
} }
// (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
// a base chain a base chain */
if (i < NF_BR_NUMHOOKS) if (i < NF_BR_NUMHOOKS)
hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS); hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
else { else {
...@@ -625,8 +632,10 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, ...@@ -625,8 +632,10 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
target = find_target_lock(t->u.name, &ret, &ebt_mutex); target = find_target_lock(t->u.name, &ret, &ebt_mutex);
if (!target) if (!target)
goto cleanup_watchers; goto cleanup_watchers;
if (target->me) if (!try_module_get(target->me)) {
__MOD_INC_USE_COUNT(target->me); up(&ebt_mutex);
goto cleanup_watchers;
}
up(&ebt_mutex); up(&ebt_mutex);
t->u.target = target; t->u.target = target;
...@@ -647,8 +656,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, ...@@ -647,8 +656,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
sizeof(struct ebt_entry_target) > e->next_offset) || sizeof(struct ebt_entry_target) > e->next_offset) ||
(t->u.target->check && (t->u.target->check &&
t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){ t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
if (t->u.target->me) module_put(t->u.target->me);
__MOD_DEC_USE_COUNT(t->u.target->me);
ret = -EFAULT; ret = -EFAULT;
goto cleanup_watchers; goto cleanup_watchers;
} }
...@@ -661,10 +669,12 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, ...@@ -661,10 +669,12 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
return ret; return ret;
} }
// checks for loops and sets the hook mask for udc /*
// the hook mask for udc tells us from which base chains the udc can be * checks for loops and sets the hook mask for udc
// accessed. This mask is a parameter to the check() functions of the extensions * the hook mask for udc tells us from which base chains the udc can be
int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s, * accessed. This mask is a parameter to the check() functions of the extensions
*/
static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
unsigned int udc_cnt, unsigned int hooknr, char *base) unsigned int udc_cnt, unsigned int hooknr, char *base)
{ {
int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict; int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
...@@ -672,9 +682,9 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s, ...@@ -672,9 +682,9 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
struct ebt_entry_target *t; struct ebt_entry_target *t;
while (pos < nentries || chain_nr != -1) { while (pos < nentries || chain_nr != -1) {
// end of udc, go back one 'recursion' step /* end of udc, go back one 'recursion' step */
if (pos == nentries) { if (pos == nentries) {
// put back values of the time when this chain was called /* put back values of the time when this chain was called */
e = cl_s[chain_nr].cs.e; e = cl_s[chain_nr].cs.e;
if (cl_s[chain_nr].from != -1) if (cl_s[chain_nr].from != -1)
nentries = nentries =
...@@ -682,7 +692,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s, ...@@ -682,7 +692,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
else else
nentries = chain->nentries; nentries = chain->nentries;
pos = cl_s[chain_nr].cs.n; pos = cl_s[chain_nr].cs.n;
// make sure we won't see a loop that isn't one /* make sure we won't see a loop that isn't one */
cl_s[chain_nr].cs.n = 0; cl_s[chain_nr].cs.n = 0;
chain_nr = cl_s[chain_nr].from; chain_nr = cl_s[chain_nr].from;
if (pos == nentries) if (pos == nentries)
...@@ -698,13 +708,13 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s, ...@@ -698,13 +708,13 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
return -1; return -1;
} }
verdict = ((struct ebt_standard_target *)t)->verdict; verdict = ((struct ebt_standard_target *)t)->verdict;
if (verdict >= 0) { // jump to another chain if (verdict >= 0) { /* jump to another chain */
struct ebt_entries *hlp2 = struct ebt_entries *hlp2 =
(struct ebt_entries *)(base + verdict); (struct ebt_entries *)(base + verdict);
for (i = 0; i < udc_cnt; i++) for (i = 0; i < udc_cnt; i++)
if (hlp2 == cl_s[i].cs.chaininfo) if (hlp2 == cl_s[i].cs.chaininfo)
break; break;
// bad destination or loop /* bad destination or loop */
if (i == udc_cnt) { if (i == udc_cnt) {
BUGPRINT("bad destination\n"); BUGPRINT("bad destination\n");
return -1; return -1;
...@@ -713,7 +723,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s, ...@@ -713,7 +723,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
BUGPRINT("loop\n"); BUGPRINT("loop\n");
return -1; return -1;
} }
// this can't be 0, so the above test is correct /* this can't be 0, so the above test is correct */
cl_s[i].cs.n = pos + 1; cl_s[i].cs.n = pos + 1;
pos = 0; pos = 0;
cl_s[i].cs.e = ((void *)e + e->next_offset); cl_s[i].cs.e = ((void *)e + e->next_offset);
...@@ -721,7 +731,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s, ...@@ -721,7 +731,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
nentries = hlp2->nentries; nentries = hlp2->nentries;
cl_s[i].from = chain_nr; cl_s[i].from = chain_nr;
chain_nr = i; chain_nr = i;
// this udc is accessible from the base chain for hooknr /* this udc is accessible from the base chain for hooknr */
cl_s[i].hookmask |= (1 << hooknr); cl_s[i].hookmask |= (1 << hooknr);
continue; continue;
} }
...@@ -732,13 +742,13 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s, ...@@ -732,13 +742,13 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
return 0; return 0;
} }
// do the parsing of the table/chains/entries/matches/watchers/targets, heh /* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
static int translate_table(struct ebt_replace *repl, static int translate_table(struct ebt_replace *repl,
struct ebt_table_info *newinfo) struct ebt_table_info *newinfo)
{ {
unsigned int i, j, k, udc_cnt; unsigned int i, j, k, udc_cnt;
int ret; int ret;
struct ebt_cl_stack *cl_s = NULL; // used in the checking for chain loops struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
i = 0; i = 0;
while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i))) while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i)))
...@@ -751,8 +761,8 @@ static int translate_table(struct ebt_replace *repl, ...@@ -751,8 +761,8 @@ static int translate_table(struct ebt_replace *repl,
BUGPRINT("Chains don't start at beginning\n"); BUGPRINT("Chains don't start at beginning\n");
return -EINVAL; return -EINVAL;
} }
// make sure chains are ordered after each other in same order /* make sure chains are ordered after each other in same order
// as their corresponding hooks as their corresponding hooks */
for (j = i + 1; j < NF_BR_NUMHOOKS; j++) { for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
if (!(repl->valid_hooks & (1 << j))) if (!(repl->valid_hooks & (1 << j)))
continue; continue;
...@@ -769,12 +779,12 @@ static int translate_table(struct ebt_replace *repl, ...@@ -769,12 +779,12 @@ static int translate_table(struct ebt_replace *repl,
newinfo->entries_size = repl->entries_size; newinfo->entries_size = repl->entries_size;
newinfo->nentries = repl->nentries; newinfo->nentries = repl->nentries;
// do some early checkings and initialize some things /* do some early checkings and initialize some things */
i = 0; // holds the expected nr. of entries for the chain i = 0; /* holds the expected nr. of entries for the chain */
j = 0; // holds the up to now counted entries for the chain j = 0; /* holds the up to now counted entries for the chain */
k = 0; // holds the total nr. of entries, should equal k = 0; /* holds the total nr. of entries, should equal
// newinfo->nentries afterwards newinfo->nentries afterwards */
udc_cnt = 0; // will hold the nr. of user defined chains (udc) udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
ebt_check_entry_size_and_hooks, newinfo, repl->entries, ebt_check_entry_size_and_hooks, newinfo, repl->entries,
repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k, repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k,
...@@ -793,7 +803,7 @@ static int translate_table(struct ebt_replace *repl, ...@@ -793,7 +803,7 @@ static int translate_table(struct ebt_replace *repl,
return -EINVAL; return -EINVAL;
} }
// check if all valid hooks have a chain /* check if all valid hooks have a chain */
for (i = 0; i < NF_BR_NUMHOOKS; i++) { for (i = 0; i < NF_BR_NUMHOOKS; i++) {
if (newinfo->hook_entry[i] == NULL && if (newinfo->hook_entry[i] == NULL &&
(repl->valid_hooks & (1 << i))) { (repl->valid_hooks & (1 << i))) {
...@@ -802,11 +812,11 @@ static int translate_table(struct ebt_replace *repl, ...@@ -802,11 +812,11 @@ static int translate_table(struct ebt_replace *repl,
} }
} }
// Get the location of the udc, put them in an array /* get the location of the udc, put them in an array
// While we're at it, allocate the chainstack while we're at it, allocate the chainstack */
if (udc_cnt) { if (udc_cnt) {
// this will get free'd in do_replace()/ebt_register_table() /* this will get free'd in do_replace()/ebt_register_table()
// if an error occurs if an error occurs */
newinfo->chainstack = (struct ebt_chainstack **) newinfo->chainstack = (struct ebt_chainstack **)
vmalloc(NR_CPUS * sizeof(struct ebt_chainstack)); vmalloc(NR_CPUS * sizeof(struct ebt_chainstack));
if (!newinfo->chainstack) if (!newinfo->chainstack)
...@@ -827,11 +837,11 @@ static int translate_table(struct ebt_replace *repl, ...@@ -827,11 +837,11 @@ static int translate_table(struct ebt_replace *repl,
vmalloc(udc_cnt * sizeof(struct ebt_cl_stack)); vmalloc(udc_cnt * sizeof(struct ebt_cl_stack));
if (!cl_s) if (!cl_s)
return -ENOMEM; return -ENOMEM;
i = 0; // the i'th udc i = 0; /* the i'th udc */
EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
ebt_get_udc_positions, newinfo, repl->hook_entry, &i, ebt_get_udc_positions, newinfo, repl->hook_entry, &i,
repl->valid_hooks, cl_s); repl->valid_hooks, cl_s);
// sanity check /* sanity check */
if (i != udc_cnt) { if (i != udc_cnt) {
BUGPRINT("i != udc_cnt\n"); BUGPRINT("i != udc_cnt\n");
vfree(cl_s); vfree(cl_s);
...@@ -839,7 +849,7 @@ static int translate_table(struct ebt_replace *repl, ...@@ -839,7 +849,7 @@ static int translate_table(struct ebt_replace *repl,
} }
} }
// Check for loops /* Check for loops */
for (i = 0; i < NF_BR_NUMHOOKS; i++) for (i = 0; i < NF_BR_NUMHOOKS; i++)
if (repl->valid_hooks & (1 << i)) if (repl->valid_hooks & (1 << i))
if (check_chainloops(newinfo->hook_entry[i], if (check_chainloops(newinfo->hook_entry[i],
...@@ -849,17 +859,17 @@ static int translate_table(struct ebt_replace *repl, ...@@ -849,17 +859,17 @@ static int translate_table(struct ebt_replace *repl,
return -EINVAL; return -EINVAL;
} }
// we now know the following (along with E=mc): /* we now know the following (along with E=mc):
// - the nr of entries in each chain is right - the nr of entries in each chain is right
// - the size of the allocated space is right - the size of the allocated space is right
// - all valid hooks have a corresponding chain - all valid hooks have a corresponding chain
// - there are no loops - there are no loops
// - wrong data can still be on the level of a single entry - wrong data can still be on the level of a single entry
// - could be there are jumps to places that are not the - could be there are jumps to places that are not the
// beginning of a chain. This can only occur in chains that beginning of a chain. This can only occur in chains that
// are not accessible from any base chains, so we don't care. are not accessible from any base chains, so we don't care. */
// used to know what we need to clean up if something goes wrong /* used to know what we need to clean up if something goes wrong */
i = 0; i = 0;
ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
ebt_check_entry, newinfo, repl->name, &i, repl->valid_hooks, ebt_check_entry, newinfo, repl->name, &i, repl->valid_hooks,
...@@ -873,17 +883,17 @@ static int translate_table(struct ebt_replace *repl, ...@@ -873,17 +883,17 @@ static int translate_table(struct ebt_replace *repl,
return ret; return ret;
} }
// called under write_lock /* called under write_lock */
static void get_counters(struct ebt_counter *oldcounters, static void get_counters(struct ebt_counter *oldcounters,
struct ebt_counter *counters, unsigned int nentries) struct ebt_counter *counters, unsigned int nentries)
{ {
int i, cpu; int i, cpu;
struct ebt_counter *counter_base; struct ebt_counter *counter_base;
// counters of cpu 0 /* counters of cpu 0 */
memcpy(counters, oldcounters, memcpy(counters, oldcounters,
sizeof(struct ebt_counter) * nentries); sizeof(struct ebt_counter) * nentries);
// add other counters to those of cpu 0 /* add other counters to those of cpu 0 */
for (cpu = 1; cpu < NR_CPUS; cpu++) { for (cpu = 1; cpu < NR_CPUS; cpu++) {
counter_base = COUNTER_BASE(oldcounters, nentries, cpu); counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
for (i = 0; i < nentries; i++) { for (i = 0; i < nentries; i++) {
...@@ -893,7 +903,7 @@ static void get_counters(struct ebt_counter *oldcounters, ...@@ -893,7 +903,7 @@ static void get_counters(struct ebt_counter *oldcounters,
} }
} }
// replace the table /* replace the table */
static int do_replace(void *user, unsigned int len) static int do_replace(void *user, unsigned int len)
{ {
int ret, i, countersize; int ret, i, countersize;
...@@ -901,7 +911,7 @@ static int do_replace(void *user, unsigned int len) ...@@ -901,7 +911,7 @@ static int do_replace(void *user, unsigned int len)
struct ebt_replace tmp; struct ebt_replace tmp;
struct ebt_table *t; struct ebt_table *t;
struct ebt_counter *counterstmp = NULL; struct ebt_counter *counterstmp = NULL;
// used to be able to unlock earlier /* used to be able to unlock earlier */
struct ebt_table_info *table; struct ebt_table_info *table;
if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
...@@ -937,8 +947,8 @@ static int do_replace(void *user, unsigned int len) ...@@ -937,8 +947,8 @@ static int do_replace(void *user, unsigned int len)
goto free_entries; goto free_entries;
} }
// the user wants counters back /* the user wants counters back
// the check on the size is done later, when we have the lock the check on the size is done later, when we have the lock */
if (tmp.num_counters) { if (tmp.num_counters) {
counterstmp = (struct ebt_counter *) counterstmp = (struct ebt_counter *)
vmalloc(tmp.num_counters * sizeof(struct ebt_counter)); vmalloc(tmp.num_counters * sizeof(struct ebt_counter));
...@@ -950,7 +960,7 @@ static int do_replace(void *user, unsigned int len) ...@@ -950,7 +960,7 @@ static int do_replace(void *user, unsigned int len)
else else
counterstmp = NULL; counterstmp = NULL;
// this can get initialized by translate_table() /* this can get initialized by translate_table() */
newinfo->chainstack = NULL; newinfo->chainstack = NULL;
ret = translate_table(&tmp, newinfo); ret = translate_table(&tmp, newinfo);
...@@ -961,7 +971,7 @@ static int do_replace(void *user, unsigned int len) ...@@ -961,7 +971,7 @@ static int do_replace(void *user, unsigned int len)
if (!t) if (!t)
goto free_iterate; goto free_iterate;
// the table doesn't like it /* the table doesn't like it */
if (t->check && (ret = t->check(newinfo, tmp.valid_hooks))) if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
goto free_unlock; goto free_unlock;
...@@ -971,9 +981,9 @@ static int do_replace(void *user, unsigned int len) ...@@ -971,9 +981,9 @@ static int do_replace(void *user, unsigned int len)
goto free_unlock; goto free_unlock;
} }
// we have the mutex lock, so no danger in reading this pointer /* we have the mutex lock, so no danger in reading this pointer */
table = t->private; table = t->private;
// we need an atomic snapshot of the counters /* we need an atomic snapshot of the counters */
write_lock_bh(&t->lock); write_lock_bh(&t->lock);
if (tmp.num_counters) if (tmp.num_counters)
get_counters(t->private->counters, counterstmp, get_counters(t->private->counters, counterstmp,
...@@ -982,10 +992,10 @@ static int do_replace(void *user, unsigned int len) ...@@ -982,10 +992,10 @@ static int do_replace(void *user, unsigned int len)
t->private = newinfo; t->private = newinfo;
write_unlock_bh(&t->lock); write_unlock_bh(&t->lock);
up(&ebt_mutex); up(&ebt_mutex);
// So, a user can change the chains while having messed up her counter /* so, a user can change the chains while having messed up her counter
// allocation. Only reason why this is done is because this way the lock allocation. Only reason why this is done is because this way the lock
// is held only once, while this doesn't bring the kernel into a is held only once, while this doesn't bring the kernel into a
// dangerous state. dangerous state. */
if (tmp.num_counters && if (tmp.num_counters &&
copy_to_user(tmp.counters, counterstmp, copy_to_user(tmp.counters, counterstmp,
tmp.num_counters * sizeof(struct ebt_counter))) { tmp.num_counters * sizeof(struct ebt_counter))) {
...@@ -995,7 +1005,7 @@ static int do_replace(void *user, unsigned int len) ...@@ -995,7 +1005,7 @@ static int do_replace(void *user, unsigned int len)
else else
ret = 0; ret = 0;
// decrease module count and free resources /* decrease module count and free resources */
EBT_ENTRY_ITERATE(table->entries, table->entries_size, EBT_ENTRY_ITERATE(table->entries, table->entries_size,
ebt_cleanup_entry, NULL); ebt_cleanup_entry, NULL);
...@@ -1019,7 +1029,7 @@ static int do_replace(void *user, unsigned int len) ...@@ -1019,7 +1029,7 @@ static int do_replace(void *user, unsigned int len)
free_counterstmp: free_counterstmp:
if (counterstmp) if (counterstmp)
vfree(counterstmp); vfree(counterstmp);
// can be initialized in translate_table() /* can be initialized in translate_table() */
if (newinfo->chainstack) { if (newinfo->chainstack) {
for (i = 0; i < NR_CPUS; i++) for (i = 0; i < NR_CPUS; i++)
vfree(newinfo->chainstack[i]); vfree(newinfo->chainstack[i]);
...@@ -1046,7 +1056,6 @@ int ebt_register_target(struct ebt_target *target) ...@@ -1046,7 +1056,6 @@ int ebt_register_target(struct ebt_target *target)
return -EEXIST; return -EEXIST;
} }
up(&ebt_mutex); up(&ebt_mutex);
MOD_INC_USE_COUNT;
return 0; return 0;
} }
...@@ -1056,7 +1065,6 @@ void ebt_unregister_target(struct ebt_target *target) ...@@ -1056,7 +1065,6 @@ void ebt_unregister_target(struct ebt_target *target)
down(&ebt_mutex); down(&ebt_mutex);
LIST_DELETE(&ebt_targets, target); LIST_DELETE(&ebt_targets, target);
up(&ebt_mutex); up(&ebt_mutex);
MOD_DEC_USE_COUNT;
} }
int ebt_register_match(struct ebt_match *match) int ebt_register_match(struct ebt_match *match)
...@@ -1071,7 +1079,6 @@ int ebt_register_match(struct ebt_match *match) ...@@ -1071,7 +1079,6 @@ int ebt_register_match(struct ebt_match *match)
return -EEXIST; return -EEXIST;
} }
up(&ebt_mutex); up(&ebt_mutex);
MOD_INC_USE_COUNT;
return 0; return 0;
} }
...@@ -1081,7 +1088,6 @@ void ebt_unregister_match(struct ebt_match *match) ...@@ -1081,7 +1088,6 @@ void ebt_unregister_match(struct ebt_match *match)
down(&ebt_mutex); down(&ebt_mutex);
LIST_DELETE(&ebt_matches, match); LIST_DELETE(&ebt_matches, match);
up(&ebt_mutex); up(&ebt_mutex);
MOD_DEC_USE_COUNT;
} }
int ebt_register_watcher(struct ebt_watcher *watcher) int ebt_register_watcher(struct ebt_watcher *watcher)
...@@ -1096,7 +1102,6 @@ int ebt_register_watcher(struct ebt_watcher *watcher) ...@@ -1096,7 +1102,6 @@ int ebt_register_watcher(struct ebt_watcher *watcher)
return -EEXIST; return -EEXIST;
} }
up(&ebt_mutex); up(&ebt_mutex);
MOD_INC_USE_COUNT;
return 0; return 0;
} }
...@@ -1106,7 +1111,6 @@ void ebt_unregister_watcher(struct ebt_watcher *watcher) ...@@ -1106,7 +1111,6 @@ void ebt_unregister_watcher(struct ebt_watcher *watcher)
down(&ebt_mutex); down(&ebt_mutex);
LIST_DELETE(&ebt_watchers, watcher); LIST_DELETE(&ebt_watchers, watcher);
up(&ebt_mutex); up(&ebt_mutex);
MOD_DEC_USE_COUNT;
} }
int ebt_register_table(struct ebt_table *table) int ebt_register_table(struct ebt_table *table)
...@@ -1138,7 +1142,7 @@ int ebt_register_table(struct ebt_table *table) ...@@ -1138,7 +1142,7 @@ int ebt_register_table(struct ebt_table *table)
if (countersize) if (countersize)
memset(newinfo->counters, 0, countersize); memset(newinfo->counters, 0, countersize);
// fill in newinfo and parse the entries /* fill in newinfo and parse the entries */
newinfo->chainstack = NULL; newinfo->chainstack = NULL;
ret = translate_table(table->table, newinfo); ret = translate_table(table->table, newinfo);
if (ret != 0) { if (ret != 0) {
...@@ -1165,7 +1169,6 @@ int ebt_register_table(struct ebt_table *table) ...@@ -1165,7 +1169,6 @@ int ebt_register_table(struct ebt_table *table)
list_prepend(&ebt_tables, table); list_prepend(&ebt_tables, table);
up(&ebt_mutex); up(&ebt_mutex);
MOD_INC_USE_COUNT;
return 0; return 0;
free_unlock: free_unlock:
up(&ebt_mutex); up(&ebt_mutex);
...@@ -1202,10 +1205,9 @@ void ebt_unregister_table(struct ebt_table *table) ...@@ -1202,10 +1205,9 @@ void ebt_unregister_table(struct ebt_table *table)
vfree(table->private->chainstack); vfree(table->private->chainstack);
} }
vfree(table->private); vfree(table->private);
MOD_DEC_USE_COUNT;
} }
// userspace just supplied us with counters /* userspace just supplied us with counters */
static int update_counters(void *user, unsigned int len) static int update_counters(void *user, unsigned int len)
{ {
int i, ret; int i, ret;
...@@ -1244,10 +1246,10 @@ static int update_counters(void *user, unsigned int len) ...@@ -1244,10 +1246,10 @@ static int update_counters(void *user, unsigned int len)
goto unlock_mutex; goto unlock_mutex;
} }
// we want an atomic add of the counters /* we want an atomic add of the counters */
write_lock_bh(&t->lock); write_lock_bh(&t->lock);
// we add to the counters of the first cpu /* we add to the counters of the first cpu */
for (i = 0; i < hlp.num_counters; i++) { for (i = 0; i < hlp.num_counters; i++) {
t->private->counters[i].pcnt += tmp[i].pcnt; t->private->counters[i].pcnt += tmp[i].pcnt;
t->private->counters[i].bcnt += tmp[i].bcnt; t->private->counters[i].bcnt += tmp[i].bcnt;
...@@ -1303,7 +1305,7 @@ static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase) ...@@ -1303,7 +1305,7 @@ static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
return 0; return 0;
} }
// called with ebt_mutex down /* called with ebt_mutex down */
static int copy_everything_to_user(struct ebt_table *t, void *user, static int copy_everything_to_user(struct ebt_table *t, void *user,
int *len, int cmd) int *len, int cmd)
{ {
...@@ -1345,7 +1347,7 @@ static int copy_everything_to_user(struct ebt_table *t, void *user, ...@@ -1345,7 +1347,7 @@ static int copy_everything_to_user(struct ebt_table *t, void *user,
return -EINVAL; return -EINVAL;
} }
// userspace might not need the counters /* userspace might not need the counters */
if (tmp.num_counters) { if (tmp.num_counters) {
if (tmp.num_counters != nentries) { if (tmp.num_counters != nentries) {
BUGPRINT("Num_counters wrong\n"); BUGPRINT("Num_counters wrong\n");
...@@ -1374,7 +1376,7 @@ static int copy_everything_to_user(struct ebt_table *t, void *user, ...@@ -1374,7 +1376,7 @@ static int copy_everything_to_user(struct ebt_table *t, void *user,
BUGPRINT("Couldn't copy entries to userspace\n"); BUGPRINT("Couldn't copy entries to userspace\n");
return -EFAULT; return -EFAULT;
} }
// set the match/watcher/target names right /* set the match/watcher/target names right */
return EBT_ENTRY_ITERATE(entries, entries_size, return EBT_ENTRY_ITERATE(entries, entries_size,
ebt_make_names, entries, tmp.entries); ebt_make_names, entries, tmp.entries);
} }
...@@ -1465,14 +1467,14 @@ static int __init init(void) ...@@ -1465,14 +1467,14 @@ static int __init init(void)
if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
return ret; return ret;
printk("Ebtables v2.0 registered"); printk(KERN_NOTICE "Ebtables v2.0 registered\n");
return 0; return 0;
} }
static void __exit fini(void) static void __exit fini(void)
{ {
nf_unregister_sockopt(&ebt_sockopts); nf_unregister_sockopt(&ebt_sockopts);
printk("Ebtables v2.0 unregistered"); printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
} }
EXPORT_SYMBOL(ebt_register_table); EXPORT_SYMBOL(ebt_register_table);
......
...@@ -2672,11 +2672,13 @@ int __init ip_rt_init(void) ...@@ -2672,11 +2672,13 @@ int __init ip_rt_init(void)
ip_rt_gc_interval; ip_rt_gc_interval;
add_timer(&rt_periodic_timer); add_timer(&rt_periodic_timer);
#ifdef CONFIG_PROC_FS
if (rt_cache_proc_init()) if (rt_cache_proc_init())
goto out_enomem; goto out_enomem;
proc_net_create ("rt_cache_stat", 0, rt_cache_stat_get_info); proc_net_create ("rt_cache_stat", 0, rt_cache_stat_get_info);
#ifdef CONFIG_NET_CLS_ROUTE #ifdef CONFIG_NET_CLS_ROUTE
create_proc_read_entry("net/rt_acct", 0, 0, ip_rt_acct_read, NULL); create_proc_read_entry("net/rt_acct", 0, 0, ip_rt_acct_read, NULL);
#endif
#endif #endif
xfrm_init(); xfrm_init();
out: out:
......
...@@ -2412,7 +2412,8 @@ static void tcp_seq_stop(struct seq_file *seq, void *v) ...@@ -2412,7 +2412,8 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
read_unlock_bh(&tp->syn_wait_lock); read_unlock_bh(&tp->syn_wait_lock);
} }
case TCP_SEQ_STATE_LISTENING: case TCP_SEQ_STATE_LISTENING:
tcp_listen_unlock(); if (v != (void *)1)
tcp_listen_unlock();
break; break;
case TCP_SEQ_STATE_TIME_WAIT: case TCP_SEQ_STATE_TIME_WAIT:
case TCP_SEQ_STATE_ESTABLISHED: case TCP_SEQ_STATE_ESTABLISHED:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment