blob: 13f0100c5578419a719e03c9faadfb0fdcbc5b16 [file] [log] [blame]
--- linux/net/bridge/netfilter/ebtable_broute.c Tue Jul 16 18:49:14 2002
+++ ebt2.0pre11.001/net/bridge/netfilter/ebtable_broute.c Tue Jul 9 20:04:31 2002
@@ -21,7 +21,7 @@
// EBT_ACCEPT means the frame will be bridged
// EBT_DROP means the frame will be routed
static struct ebt_entries initial_chain =
- {0, "BROUTE", 0, EBT_ACCEPT, 0};
+ {0, "BROUTING", 0, EBT_ACCEPT, 0};
static struct ebt_replace initial_table =
{
--- linux/net/bridge/netfilter/ebt_redirect.c Tue Jul 16 18:49:14 2002
+++ ebt2.0pre11.001/net/bridge/netfilter/ebt_redirect.c Tue Jul 9 15:41:46 2002
@@ -22,9 +22,14 @@
{
struct ebt_redirect_info *infostuff = (struct ebt_redirect_info *) data;
- memcpy((**pskb).mac.ethernet->h_dest,
- in->br_port->br->dev.dev_addr, ETH_ALEN);
- (*pskb)->pkt_type = PACKET_HOST;
+ if (hooknr != NF_BR_BROUTING)
+ memcpy((**pskb).mac.ethernet->h_dest,
+ in->br_port->br->dev.dev_addr, ETH_ALEN);
+ else {
+ memcpy((**pskb).mac.ethernet->h_dest,
+ in->dev_addr, ETH_ALEN);
+ (*pskb)->pkt_type = PACKET_HOST;
+ }
return infostuff->target;
}
--- linux/net/bridge/netfilter/ebtables.c Tue Jul 16 18:49:15 2002
+++ ebt2.0pre11.001/net/bridge/netfilter/ebtables.c Sun Jul 14 20:13:16 2002
@@ -105,15 +105,19 @@
struct ebt_chainstack *cs;
struct ebt_entries *chaininfo;
char *base;
+ struct ebt_table_info *private = table->private;
read_lock_bh(&table->lock);
- cs = table->private->chainstack;
- chaininfo = table->private->hook_entry[hook];
- nentries = table->private->hook_entry[hook]->nentries;
- point = (struct ebt_entry *)(table->private->hook_entry[hook]->data);
+ if (private->chainstack)
+ cs = private->chainstack[cpu_number_map(smp_processor_id())];
+ else
+ cs = NULL;
+ chaininfo = private->hook_entry[hook];
+ nentries = private->hook_entry[hook]->nentries;
+ point = (struct ebt_entry *)(private->hook_entry[hook]->data);
#define cb_base table->private->counters + \
cpu_number_map(smp_processor_id()) * table->private->nentries
- counter_base = cb_base + table->private->hook_entry[hook]->counter_offset;
+ counter_base = cb_base + private->hook_entry[hook]->counter_offset;
#define FWINV(bool,invflg) ((bool) ^ !!(point->invflags & invflg))
// base for chain jumps
base = (char *)chaininfo;
@@ -768,10 +772,22 @@
if (udc_cnt) {
// this will get free'd in do_replace()/ebt_register_table()
// if an error occurs
- newinfo->chainstack = (struct ebt_chainstack *)
- vmalloc(udc_cnt * sizeof(struct ebt_chainstack));
+ newinfo->chainstack = (struct ebt_chainstack **)
+ vmalloc(smp_num_cpus * sizeof(struct ebt_chainstack));
if (!newinfo->chainstack)
return -ENOMEM;
+ for (i = 0; i < smp_num_cpus; i++) {
+ newinfo->chainstack[i] =
+ vmalloc(udc_cnt * sizeof(struct ebt_chainstack));
+ if (!newinfo->chainstack[i]) {
+ while (i)
+ vfree(newinfo->chainstack[--i]);
+ vfree(newinfo->chainstack);
+ newinfo->chainstack = NULL;
+ break;
+ }
+ }
+
cl_s = (struct ebt_cl_stack *)
vmalloc(udc_cnt * sizeof(struct ebt_cl_stack));
if (!cl_s)
@@ -825,27 +841,27 @@
}
// called under write_lock
-static inline void get_counters(struct ebt_table_info *info,
- struct ebt_counter *counters)
+static inline void get_counters(struct ebt_counter *oldcounters,
+ struct ebt_counter *counters, unsigned int nentries)
{
int i, cpu, counter_base;
// counters of cpu 0
- memcpy(counters, info->counters,
- sizeof(struct ebt_counter) * info->nentries);
+ memcpy(counters, oldcounters,
+ sizeof(struct ebt_counter) * nentries);
// add other counters to those of cpu 0
for (cpu = 1; cpu < smp_num_cpus; cpu++) {
- counter_base = cpu * info->nentries;
- for (i = 0; i < info->nentries; i++)
+ counter_base = cpu * nentries;
+ for (i = 0; i < nentries; i++)
counters[i].pcnt +=
- info->counters[counter_base + i].pcnt;
+ oldcounters[counter_base + i].pcnt;
}
}
// replace the table
static int do_replace(void *user, unsigned int len)
{
- int ret;
+ int ret, i;
struct ebt_table_info *newinfo;
struct ebt_replace tmp;
struct ebt_table *t;
@@ -934,7 +950,8 @@
// we need an atomic snapshot of the counters
write_lock_bh(&t->lock);
if (tmp.num_counters)
- get_counters(t->private, counterstmp);
+ get_counters(t->private->counters, counterstmp,
+ t->private->nentries);
t->private = newinfo;
write_unlock_bh(&t->lock);
@@ -959,8 +976,11 @@
vfree(table->entries);
if (table->counters)
vfree(table->counters);
- if (table->chainstack)
+ if (table->chainstack) {
+ for (i = 0; i < smp_num_cpus; i++)
+ vfree(table->chainstack[i]);
vfree(table->chainstack);
+ }
vfree(table);
if (counterstmp)
@@ -975,8 +995,11 @@
if (counterstmp)
vfree(counterstmp);
// can be initialized in translate_table()
- if (newinfo->chainstack)
+ if (newinfo->chainstack) {
+ for (i = 0; i < smp_num_cpus; i++)
+ vfree(newinfo->chainstack[i]);
vfree(newinfo->chainstack);
+ }
free_entries:
if (newinfo->entries)
vfree(newinfo->entries);
@@ -1067,7 +1090,7 @@
int ebt_register_table(struct ebt_table *table)
{
struct ebt_table_info *newinfo;
- int ret;
+ int ret, i;
if (!table || !table->table ||!table->table->entries ||
table->table->entries_size == 0 ||
@@ -1135,8 +1158,11 @@
free_counters:
if (newinfo->counters)
vfree(newinfo->counters);
- if (newinfo->chainstack)
+ if (newinfo->chainstack) {
+ for (i = 0; i < smp_num_cpus; i++)
+ vfree(newinfo->chainstack[i]);
vfree(newinfo->chainstack);
+ }
free_entries:
vfree(newinfo->entries);
free_newinfo:
@@ -1146,6 +1172,8 @@
void ebt_unregister_table(struct ebt_table *table)
{
+ int i;
+
if (!table) {
BUGPRINT("Request to unregister NULL table!!!\n");
return;
@@ -1159,8 +1187,11 @@
vfree(table->private->counters);
if (table->private->entries)
vfree(table->private->entries);
- if (table->private->chainstack)
+ if (table->private->chainstack) {
+ for (i = 0; i < smp_num_cpus; i++)
+ vfree(table->private->chainstack[i]);
vfree(table->private->chainstack);
+ }
vfree(table->private);
MOD_DEC_USE_COUNT;
}
@@ -1263,52 +1294,65 @@
}
// called with ebt_mutex down
-static int copy_everything_to_user(struct ebt_table *t, void *user, int *len)
+static int copy_everything_to_user(struct ebt_table *t, void *user,
+ int *len, int cmd)
{
struct ebt_replace tmp;
- struct ebt_table_info *info = t->private;
- struct ebt_counter *counterstmp;
- int i;
+ struct ebt_counter *counterstmp, *oldcounters;
+ unsigned int entries_size, nentries;
+ char *entries;
+
+ if (cmd == EBT_SO_GET_ENTRIES) {
+ entries_size = t->private->entries_size;
+ nentries = t->private->nentries;
+ entries = t->private->entries;
+ oldcounters = t->private->counters;
+ } else {
+ entries_size = t->table->entries_size;
+ nentries = t->table->nentries;
+ entries = t->table->entries;
+ oldcounters = t->table->counters;
+ }
if (copy_from_user(&tmp, user, sizeof(tmp))) {
BUGPRINT("Cfu didn't work\n");
return -EFAULT;
}
- if (*len != sizeof(struct ebt_replace) + info->entries_size +
- (tmp.num_counters? info->nentries * sizeof(struct ebt_counter): 0)) {
+ if (*len != sizeof(struct ebt_replace) + entries_size +
+ (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
BUGPRINT("Wrong size\n");
return -EINVAL;
}
- if (tmp.nentries != info->nentries) {
+ if (tmp.nentries != nentries) {
BUGPRINT("Nentries wrong\n");
return -EINVAL;
}
- if (tmp.entries_size != info->entries_size) {
+ if (tmp.entries_size != entries_size) {
BUGPRINT("Wrong size\n");
return -EINVAL;
}
// userspace might not need the counters
if (tmp.num_counters) {
- if (tmp.num_counters != info->nentries) {
+ if (tmp.num_counters != nentries) {
BUGPRINT("Num_counters wrong\n");
return -EINVAL;
}
counterstmp = (struct ebt_counter *)
- vmalloc(info->nentries * sizeof(struct ebt_counter));
+ vmalloc(nentries * sizeof(struct ebt_counter));
if (!counterstmp) {
BUGPRINT("Couldn't copy counters, out of memory\n");
return -ENOMEM;
}
write_lock_bh(&t->lock);
- get_counters(info, counterstmp);
+ get_counters(oldcounters, counterstmp, nentries);
write_unlock_bh(&t->lock);
if (copy_to_user(tmp.counters, counterstmp,
- info->nentries * sizeof(struct ebt_counter))) {
+ nentries * sizeof(struct ebt_counter))) {
BUGPRINT("Couldn't copy counters to userspace\n");
vfree(counterstmp);
return -EFAULT;
@@ -1316,23 +1360,17 @@
vfree(counterstmp);
}
- if (copy_to_user(tmp.entries, info->entries, info->entries_size)) {
+ if (copy_to_user(tmp.entries, entries, entries_size)) {
BUGPRINT("Couldn't copy entries to userspace\n");
return -EFAULT;
}
- // make userspace's life easier
- memcpy(tmp.hook_entry, info->hook_entry,
- NF_BR_NUMHOOKS * sizeof(struct ebt_entries *));
- for (i = 0; i < NF_BR_NUMHOOKS; i++)
- tmp.hook_entry[i] = (struct ebt_entries *)(((char *)
- (info->hook_entry[i])) - info->entries + tmp.entries);
if (copy_to_user(user, &tmp, sizeof(struct ebt_replace))) {
BUGPRINT("Couldn't copy ebt_replace to userspace\n");
return -EFAULT;
}
// set the match/watcher/target names right
- return EBT_ENTRY_ITERATE(info->entries, info->entries_size,
- ebt_make_names, info->entries, tmp.entries);
+ return EBT_ENTRY_ITERATE(entries, entries_size,
+ ebt_make_names, entries, tmp.entries);
}
static int do_ebt_set_ctl(struct sock *sk,
@@ -1368,15 +1406,21 @@
switch(cmd) {
case EBT_SO_GET_INFO:
+ case EBT_SO_GET_INIT_INFO:
if (*len != sizeof(struct ebt_replace)){
ret = -EINVAL;
up(&ebt_mutex);
break;
}
- tmp.nentries = t->private->nentries;
- tmp.entries_size = t->private->entries_size;
- // userspace needs this to check the chain names
- tmp.valid_hooks = t->valid_hooks;
+ if (cmd == EBT_SO_GET_INFO) {
+ tmp.nentries = t->private->nentries;
+ tmp.entries_size = t->private->entries_size;
+ tmp.valid_hooks = t->valid_hooks;
+ } else {
+ tmp.nentries = t->table->nentries;
+ tmp.entries_size = t->table->entries_size;
+ tmp.valid_hooks = t->table->valid_hooks;
+ }
up(&ebt_mutex);
if (copy_to_user(user, &tmp, *len) != 0){
BUGPRINT("c2u Didn't work\n");
@@ -1387,9 +1431,10 @@
break;
case EBT_SO_GET_ENTRIES:
- ret = copy_everything_to_user(t, user, len);
+ case EBT_SO_GET_INIT_ENTRIES:
+ ret = copy_everything_to_user(t, user, len, cmd);
up(&ebt_mutex);
- break;
+ break;
default:
up(&ebt_mutex);
--- linux/include/linux/netfilter_bridge/ebtables.h Tue Jul 16 18:49:15 2002
+++ ebt2.0pre11.001/include/linux/netfilter_bridge/ebtables.h Sun Jul 14 19:19:09 2002
@@ -29,7 +29,9 @@
#define EBT_SO_GET_INFO (EBT_BASE_CTL)
#define EBT_SO_GET_ENTRIES (EBT_SO_GET_INFO+1)
-#define EBT_SO_GET_MAX (EBT_SO_GET_ENTRIES+1)
+#define EBT_SO_GET_INIT_INFO (EBT_SO_GET_ENTRIES+1)
+#define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO+1)
+#define EBT_SO_GET_MAX (EBT_SO_GET_INIT_ENTRIES+1)
// verdicts >0 are "branches"
#define EBT_ACCEPT -1
@@ -55,9 +57,9 @@
// one standard (accept, drop, return) per hook
int policy;
// nr. of entries
- __u32 nentries;
+ unsigned int nentries;
// entry list
- __u8 data[0];
+ char data[0];
};
// used for the bitmask of struct ebt_entry
@@ -238,7 +240,7 @@
struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
struct ebt_counter *counters;
// room to maintain the stack used for jumping from and into udc
- struct ebt_chainstack *chainstack;
+ struct ebt_chainstack **chainstack;
char *entries;
};
--- linux/include/linux/netfilter_bridge/ebt_nat.h Tue Jul 16 18:49:15 2002
+++ ebt2.0pre11.001/include/linux/netfilter_bridge/ebt_nat.h Tue Jul 16 18:45:16 2002
@@ -4,7 +4,7 @@
struct ebt_nat_info
{
unsigned char mac[ETH_ALEN];
- // EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN
+ // EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN
int target;
};
#define EBT_SNAT_TARGET "snat"