| --- 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" |