From d6a5d8b6636b49b4ae54385661b434d1277c6d86 Mon Sep 17 00:00:00 2001 From: Bart De Schuymer Date: Wed, 31 Jul 2002 19:44:51 +0000 Subject: *** empty log message *** --- .../ebtables-v2.0_vs_2.4.18-rc1.001.diff | 1152 ++++++++++++++++++++ 1 file changed, 1152 insertions(+) create mode 100644 kernel/patches/incremental-patches/ebtables-v2.0_vs_2.4.18-rc1.001.diff (limited to 'kernel/patches/incremental-patches') diff --git a/kernel/patches/incremental-patches/ebtables-v2.0_vs_2.4.18-rc1.001.diff b/kernel/patches/incremental-patches/ebtables-v2.0_vs_2.4.18-rc1.001.diff new file mode 100644 index 0000000..6e03a05 --- /dev/null +++ b/kernel/patches/incremental-patches/ebtables-v2.0_vs_2.4.18-rc1.001.diff @@ -0,0 +1,1152 @@ +--- linux/net/core/dev.c Wed Jul 31 19:15:22 2002 ++++ ebt2.0-rc1/net/core/dev.c Wed Jul 31 19:04:30 2002 +@@ -1385,13 +1385,6 @@ + + #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) + int (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; +-#if defined(CONFIG_BRIDGE_EBT_BROUTE) || \ +- defined(CONFIG_BRIDGE_EBT_BROUTE_MODULE) +-unsigned int (*broute_decision) (unsigned int hook, struct sk_buff **pskb, +- const struct net_device *in, +- const struct net_device *out, +- int (*okfn)(struct sk_buff *)) = NULL; +-#endif + #endif + + static __inline__ int handle_bridge(struct sk_buff *skb, +--- linux/net/bridge/br.c Wed Jul 31 19:10:53 2002 ++++ ebt2.0-rc1/net/bridge/br.c Wed Jul 31 19:04:30 2002 +@@ -28,6 +28,14 @@ + #include "../atm/lec.h" + #endif + ++#if defined(CONFIG_BRIDGE_EBT_BROUTE) || \ ++ defined(CONFIG_BRIDGE_EBT_BROUTE_MODULE) ++unsigned int (*broute_decision) (unsigned int hook, struct sk_buff **pskb, ++ const struct net_device *in, ++ const struct net_device *out, ++ int (*okfn)(struct sk_buff *)) = NULL; ++#endif ++ + void br_dec_use_count() + { + MOD_DEC_USE_COUNT; +@@ -82,7 +90,12 @@ + #endif + } + ++#if defined(CONFIG_BRIDGE_EBT_BROUTE) || \ ++ defined(CONFIG_BRIDGE_EBT_BROUTE_MODULE) ++EXPORT_SYMBOL(broute_decision); ++#else + EXPORT_NO_SYMBOLS; ++#endif + + module_init(br_init) + module_exit(br_deinit) +--- linux/net/bridge/Makefile Wed Jul 31 19:10:53 2002 ++++ ebt2.0-rc1/net/bridge/Makefile Wed Jul 31 19:04:30 2002 +@@ -7,6 +7,12 @@ + # + # Note 2! The CFLAGS definition is now in the main makefile... + ++ifneq ($(CONFIG_BRIDGE_EBT_BROUTE),n) ++ifneq ($(CONFIG_BRIDGE_EBT_BROUTE),) ++export-objs := br.o ++endif ++endif ++ + O_TARGET := bridge.o + obj-y := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \ + br_ioctl.o br_notify.o br_stp.o br_stp_bpdu.o \ +--- linux/include/linux/netfilter_bridge.h Wed Jul 31 19:15:22 2002 ++++ ebt2.0-rc1/include/linux/netfilter_bridge.h Wed Jul 31 19:04:30 2002 +@@ -28,8 +28,7 @@ + NF_BR_PRI_FILTER_OTHER = 200, + NF_BR_PRI_NAT_DST_BRIDGED = -300, + NF_BR_PRI_NAT_DST_OTHER = 100, +- NF_BR_PRI_NAT_SRC_BRIDGED = -100, +- NF_BR_PRI_NAT_SRC_OTHER = 300, ++ NF_BR_PRI_NAT_SRC = 300, + NF_BR_PRI_LAST = INT_MAX, + }; + +--- linux/net/netsyms.c Wed Jul 31 19:15:22 2002 ++++ ebt2.0-rc1/net/netsyms.c Mon Feb 25 20:38:14 2002 +@@ -228,10 +228,6 @@ + + #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) + EXPORT_SYMBOL(br_handle_frame_hook); +-#if defined(CONFIG_BRIDGE_EBT_BROUTE) || \ +- defined(CONFIG_BRIDGE_EBT_BROUTE_MODULE) +-EXPORT_SYMBOL(broute_decision); +-#endif + #ifdef CONFIG_INET + EXPORT_SYMBOL(br_ioctl_hook); + #endif +--- linux/net/Makefile Wed Jul 31 19:15:22 2002 ++++ ebt2.0-rc1/net/Makefile Wed Jul 31 19:04:30 2002 +@@ -28,7 +28,7 @@ + endif + + ifneq ($(CONFIG_BRIDGE),n) +-ifneq ($CONFIG_BRIDGE),) ++ifneq ($(CONFIG_BRIDGE),) + subdir-$(CONFIG_BRIDGE) += bridge/netfilter + endif + endif +--- linux/net/bridge/netfilter/Makefile Wed Jul 31 19:15:22 2002 ++++ ebt2.0-rc1/net/bridge/netfilter/Makefile Wed Jul 31 19:04:30 2002 +@@ -9,7 +9,7 @@ + + O_TARGET := netfilter.o + +-export-objs = ebtables.o ++export-objs := ebtables.o + + obj-$(CONFIG_BRIDGE_EBT) += ebtables.o + obj-$(CONFIG_BRIDGE_EBT_T_FILTER) += ebtable_filter.o +@@ -19,8 +19,10 @@ + obj-$(CONFIG_BRIDGE_EBT_IPF) += ebt_ip.o + obj-$(CONFIG_BRIDGE_EBT_ARPF) += ebt_arp.o + obj-$(CONFIG_BRIDGE_EBT_VLANF) += ebt_vlan.o ++obj-$(CONFIG_BRIDGE_EBT_MARKF) += ebt_mark_m.o + obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o + obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o + obj-$(CONFIG_BRIDGE_EBT_DNAT) += ebt_dnat.o + obj-$(CONFIG_BRIDGE_EBT_REDIRECT) += ebt_redirect.o ++obj-$(CONFIG_BRIDGE_EBT_MARK_T) += ebt_mark.o + include $(TOPDIR)/Rules.make +--- linux/net/bridge/netfilter/Config.in Wed Jul 31 19:15:22 2002 ++++ ebt2.0-rc1/net/bridge/netfilter/Config.in Wed Jul 31 19:04:30 2002 +@@ -9,8 +9,10 @@ + dep_tristate ' ebt: IP filter support' CONFIG_BRIDGE_EBT_IPF $CONFIG_BRIDGE_EBT + dep_tristate ' ebt: ARP filter support' CONFIG_BRIDGE_EBT_ARPF $CONFIG_BRIDGE_EBT + dep_tristate ' ebt: 802.1Q VLAN filter support (EXPERIMENTAL)' CONFIG_BRIDGE_EBT_VLANF $CONFIG_BRIDGE_EBT ++dep_tristate ' ebt: mark filter support' CONFIG_BRIDGE_EBT_MARKF $CONFIG_BRIDGE_EBT + dep_tristate ' ebt: snat target support' CONFIG_BRIDGE_EBT_SNAT $CONFIG_BRIDGE_EBT + dep_tristate ' ebt: dnat target support' CONFIG_BRIDGE_EBT_DNAT $CONFIG_BRIDGE_EBT + dep_tristate ' ebt: redirect target support' CONFIG_BRIDGE_EBT_REDIRECT $CONFIG_BRIDGE_EBT ++dep_tristate ' ebt: mark target support' CONFIG_BRIDGE_EBT_MARK_T $CONFIG_BRIDGE_EBT + dep_tristate ' Bridge: ethernet database' CONFIG_BRIDGE_DB $CONFIG_BRIDGE + +--- linux/net/bridge/netfilter/ebtable_nat.c Wed Jul 31 19:15:22 2002 ++++ ebt2.0-rc1/net/bridge/netfilter/ebtable_nat.c Wed Jul 31 19:04:30 2002 +@@ -42,16 +42,6 @@ + RW_LOCK_UNLOCKED, check, NULL + }; + +-// used for snat to know if the frame comes from FORWARD or LOCAL_OUT. +-// needed because of the bridge-nf patch (that allows use of iptables +-// on bridged traffic) +-// if the packet is routed, we want the ebtables stuff on POSTROUTING +-// to be executed _after_ the iptables stuff. when it's bridged, it's +-// the way around +-static struct net_device __fake_net_device = { +- hard_header_len: ETH_HLEN +-}; +- + static unsigned int + ebt_nat_dst (unsigned int hook, struct sk_buff **pskb, + const struct net_device *in, const struct net_device *out, +@@ -60,50 +50,11 @@ + return ebt_do_table(hook, pskb, in, out, &frame_nat); + } + +-// let snat know this frame is routed +-static unsigned int ebt_clear_physin (unsigned int hook, struct sk_buff **pskb, +- const struct net_device *in, const struct net_device *out, +- int (*okfn)(struct sk_buff *)) +-{ +- (*pskb)->physindev = NULL; +- return NF_ACCEPT; +-} +- +-// let snat know this frame is bridged +-static unsigned int ebt_set_physin (unsigned int hook, struct sk_buff **pskb, +- const struct net_device *in, const struct net_device *out, +- int (*okfn)(struct sk_buff *)) +-{ +- (*pskb)->physindev = &__fake_net_device; +- return NF_ACCEPT; +-} +- + static unsigned int ebt_nat_src (unsigned int hook, struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) + { +- // this is a routed packet +- if ((*pskb)->physindev == NULL) +- return NF_ACCEPT; +- if ((*pskb)->physindev != &__fake_net_device) +- printk("ebtables (br_nat_src): physindev hack " +- "doesn't work - BUG\n"); +- +- return ebt_do_table(hook, pskb, in, out, &frame_nat); +-} +- +-static unsigned int ebt_nat_src_route (unsigned int hook, struct sk_buff **pskb, +- const struct net_device *in, const struct net_device *out, +- int (*okfn)(struct sk_buff *)) +-{ +- // this is a bridged packet +- if ((*pskb)->physindev == &__fake_net_device) +- return NF_ACCEPT; +- if ((*pskb)->physindev) +- printk("ebtables (br_nat_src_route): physindev hack " +- "doesn't work - BUG\n"); +- + return ebt_do_table(hook, pskb, in, out, &frame_nat); + } + +@@ -111,15 +62,9 @@ + { { NULL, NULL }, ebt_nat_dst, PF_BRIDGE, NF_BR_LOCAL_OUT, + NF_BR_PRI_NAT_DST_OTHER}, + { { NULL, NULL }, ebt_nat_src, PF_BRIDGE, NF_BR_POST_ROUTING, +- NF_BR_PRI_NAT_SRC_BRIDGED}, +- { { NULL, NULL }, ebt_nat_src_route, PF_BRIDGE, NF_BR_POST_ROUTING, +- NF_BR_PRI_NAT_SRC_OTHER}, ++ NF_BR_PRI_NAT_SRC}, + { { NULL, NULL }, ebt_nat_dst, PF_BRIDGE, NF_BR_PRE_ROUTING, + NF_BR_PRI_NAT_DST_BRIDGED}, +- { { NULL, NULL }, ebt_clear_physin, PF_BRIDGE, NF_BR_LOCAL_OUT, +- NF_BR_PRI_FILTER_OTHER + 1}, +- { { NULL, NULL }, ebt_set_physin, PF_BRIDGE, NF_BR_FORWARD, +- NF_BR_PRI_FILTER_OTHER + 1} + }; + + static int __init init(void) +--- linux/net/bridge/netfilter/ebt_redirect.c Wed Jul 31 19:15:22 2002 ++++ ebt2.0-rc1/net/bridge/netfilter/ebt_redirect.c Wed Jul 31 19:04:30 2002 +@@ -38,6 +38,10 @@ + { + struct ebt_redirect_info *infostuff = (struct ebt_redirect_info *) data; + ++ if ((hookmask & (1 << NF_BR_NUMHOOKS)) && ++ infostuff->target == EBT_RETURN) ++ return -EINVAL; ++ hookmask &= ~(1 << NF_BR_NUMHOOKS); + if ( (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING)) && + (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) ) + return -EINVAL; +--- /dev/null Thu Aug 24 11:00:32 2000 ++++ ebt2.0-rc1/net/bridge/netfilter/ebt_mark.c Wed Jul 31 19:04:30 2002 +@@ -0,0 +1,73 @@ ++/* ++ * ebt_mark_t ++ * ++ * Authors: ++ * Bart De Schuymer ++ * ++ * July, 2002 ++ * ++ */ ++ ++// The mark target can be used in any chain ++// I believe adding a mangle table just for marking is total overkill ++// Marking a frame doesn't really change anything in the frame anyway ++// The target member of the struct ebt_vlan_info provides the same ++// functionality as a separate table ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "../br_private.h" ++ ++static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr, ++ const struct net_device *in, const struct net_device *out, ++ const void *data, unsigned int datalen) ++{ ++ struct ebt_mark_t_info *infostuff = (struct ebt_mark_t_info *) data; ++ ++ if ((*pskb)->nfmark != infostuff->mark) { ++ (*pskb)->nfmark = infostuff->mark; ++ (*pskb)->nfcache |= NFC_ALTERED; ++ } ++ return infostuff->target; ++} ++ ++static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, ++ const struct ebt_entry *e, void *data, unsigned int datalen) ++{ ++ struct ebt_mark_t_info *infostuff = (struct ebt_mark_t_info *) data; ++ ++ if ((hookmask & (1 << NF_BR_NUMHOOKS)) && ++ infostuff->target == EBT_RETURN) ++ return -EINVAL; ++ hookmask &= ~(1 << NF_BR_NUMHOOKS); ++ if (datalen != sizeof(struct ebt_mark_t_info)) ++ return -EINVAL; ++ if (infostuff->target < -NUM_STANDARD_TARGETS || infostuff->target >= 0) ++ return -EINVAL; ++ return 0; ++} ++ ++static struct ebt_target mark_target = ++{ ++ {NULL, NULL}, EBT_MARK_TARGET, ebt_target_mark, ++ ebt_target_mark_check, NULL, THIS_MODULE ++}; ++ ++static int __init init(void) ++{ ++ return ebt_register_target(&mark_target); ++} ++ ++static void __exit fini(void) ++{ ++ ebt_unregister_target(&mark_target); ++} ++ ++module_init(init); ++module_exit(fini); ++EXPORT_NO_SYMBOLS; ++MODULE_LICENSE("GPL"); +--- /dev/null Thu Aug 24 11:00:32 2000 ++++ ebt2.0-rc1/net/bridge/netfilter/ebt_mark_m.c Wed Jul 31 19:04:30 2002 +@@ -0,0 +1,62 @@ ++/* ++ * ebt_mark_m ++ * ++ * Authors: ++ * Bart De Schuymer ++ * ++ * July, 2002 ++ * ++ */ ++ ++#include ++#include ++#include ++ ++static int ebt_filter_mark(const struct sk_buff *skb, ++ const struct net_device *in, const struct net_device *out, const void *data, ++ unsigned int datalen, const struct ebt_counter *c) ++{ ++ struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data; ++ ++ if (info->bitmask & EBT_MARK_OR) ++ return !(!!(skb->nfmark & info->mask) ^ info->invert); ++ return !(((skb->nfmark & info->mask) == info->mark) ^ info->invert); ++} ++ ++static int ebt_mark_check(const char *tablename, unsigned int hookmask, ++ const struct ebt_entry *e, void *data, unsigned int datalen) ++{ ++ struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data; ++ ++ if (info->bitmask & ~EBT_MARK_MASK) ++ return -EINVAL; ++ if ((info->bitmask & EBT_MARK_OR) && (info->bitmask & EBT_MARK_AND)) ++ return -EINVAL; ++ if (!info->bitmask) ++ return -EINVAL; ++ if (datalen != sizeof(struct ebt_mark_m_info)) { ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static struct ebt_match filter_mark = ++{ ++ {NULL, NULL}, EBT_MARK_MATCH, ebt_filter_mark, ebt_mark_check, NULL, ++ THIS_MODULE ++}; ++ ++static int __init init(void) ++{ ++ return ebt_register_match(&filter_mark); ++} ++ ++static void __exit fini(void) ++{ ++ ebt_unregister_match(&filter_mark); ++} ++ ++module_init(init); ++module_exit(fini); ++EXPORT_NO_SYMBOLS; ++MODULE_LICENSE("GPL"); +--- linux/net/bridge/netfilter/ebt_snat.c Wed Jul 31 19:15:22 2002 ++++ ebt2.0-rc1/net/bridge/netfilter/ebt_snat.c Wed Jul 31 19:04:30 2002 +@@ -31,6 +31,10 @@ + { + struct ebt_nat_info *infostuff = (struct ebt_nat_info *) data; + ++ if ((hookmask & (1 << NF_BR_NUMHOOKS)) && ++ infostuff->target == EBT_RETURN) ++ return -EINVAL; ++ hookmask &= ~(1 << NF_BR_NUMHOOKS); + if (strcmp(tablename, "nat")) + return -EINVAL; + if (datalen != sizeof(struct ebt_nat_info)) +--- linux/net/bridge/netfilter/ebt_dnat.c Wed Jul 31 19:15:22 2002 ++++ ebt2.0-rc1/net/bridge/netfilter/ebt_dnat.c Wed Jul 31 19:04:30 2002 +@@ -31,6 +31,10 @@ + { + struct ebt_nat_info *infostuff = (struct ebt_nat_info *) data; + ++ if ((hookmask & (1 << NF_BR_NUMHOOKS)) && ++ infostuff->target == EBT_RETURN) ++ return -EINVAL; ++ hookmask &= ~(1 << NF_BR_NUMHOOKS); + if ( (strcmp(tablename, "nat") || + (hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))) && + (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) ) +--- linux/net/bridge/netfilter/ebtables.c Wed Jul 31 19:15:22 2002 ++++ ebt2.0-rc1/net/bridge/netfilter/ebtables.c Wed Jul 31 19:04:30 2002 +@@ -4,7 +4,7 @@ + * Author: + * Bart De Schuymer + * +- * ebtables.c,v 2.0, April, 2002 ++ * ebtables.c,v 2.0, July, 2002 + * + * This code is stongly inspired on the iptables code which is + * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling +@@ -50,6 +50,21 @@ + ": out of memory: "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 ++// 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 ++#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_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \ ++ COUNTER_OFFSET(n) * cpu)) ++ ++ ++ + static void print_string(char *str); + + static DECLARE_MUTEX(ebt_mutex); +@@ -62,10 +77,8 @@ + { {NULL, NULL}, EBT_STANDARD_TARGET, NULL, NULL, NULL, NULL}; + + static inline int ebt_do_watcher (struct ebt_entry_watcher *w, +- const struct sk_buff *skb, +- const struct net_device *in, +- const struct net_device *out, +- const struct ebt_counter *c) ++ const struct sk_buff *skb, const struct net_device *in, ++ const struct net_device *out, const struct ebt_counter *c) + { + w->u.watcher->watcher(skb, in, out, w->data, + w->watcher_size, c); +@@ -74,10 +87,8 @@ + } + + static inline int ebt_do_match (struct ebt_entry_match *m, +- const struct sk_buff *skb, +- const struct net_device *in, +- const struct net_device *out, +- const struct ebt_counter *c) ++ const struct sk_buff *skb, const struct net_device *in, ++ const struct net_device *out, const struct ebt_counter *c) + { + return m->u.match->match(skb, in, out, m->data, + m->match_size, c); +@@ -89,7 +100,51 @@ + return 0; + if (!device) + return 1; +- return strncmp(entry, device->name, IFNAMSIZ); ++ return !!strncmp(entry, device->name, IFNAMSIZ); ++} ++ ++#define FWINV(bool,invflg) ((bool) ^ !!(p->invflags & invflg)) ++// process standard matches ++static inline int ebt_basic_match(struct ebt_entry *p, struct ethhdr *h, ++ const struct net_device *in, const struct net_device *out) ++{ ++ int verdict, i; ++ ++ if (p->bitmask & EBT_802_3) { ++ if (FWINV(ntohs(h->h_proto) >= 1536, EBT_IPROTO)) ++ return 1; ++ } else if (!(p->bitmask & EBT_NOPROTO) && ++ FWINV(p->ethproto != h->h_proto, EBT_IPROTO)) ++ return 1; ++ ++ if (FWINV(ebt_dev_check(p->in, in), EBT_IIN)) ++ return 1; ++ if (FWINV(ebt_dev_check(p->out, out), EBT_IOUT)) ++ return 1; ++ if ((!in || !in->br_port) ? 0 : FWINV(ebt_dev_check( ++ p->logical_in, &in->br_port->br->dev), EBT_ILOGICALIN)) ++ return 1; ++ if ((!out || !out->br_port) ? 0 : FWINV(ebt_dev_check( ++ (p->logical_out), &out->br_port->br->dev), EBT_ILOGICALOUT)) ++ return 1; ++ ++ if (p->bitmask & EBT_SOURCEMAC) { ++ verdict = 0; ++ for (i = 0; i < 6; i++) ++ verdict |= (h->h_source[i] ^ p->sourcemac[i]) & ++ p->sourcemsk[i]; ++ if (FWINV(verdict != 0, EBT_ISOURCE) ) ++ return 1; ++ } ++ if (p->bitmask & EBT_DESTMAC) { ++ verdict = 0; ++ for (i = 0; i < 6; i++) ++ verdict |= (h->h_dest[i] ^ p->destmac[i]) & ++ p->destmsk[i]; ++ if (FWINV(verdict != 0, EBT_IDEST) ) ++ return 1; ++ } ++ return 0; + } + + // Do some firewalling +@@ -97,9 +152,9 @@ + const struct net_device *in, const struct net_device *out, + struct ebt_table *table) + { +- int i, j, nentries; ++ int i, nentries; + struct ebt_entry *point; +- struct ebt_counter *counter_base; ++ struct ebt_counter *counter_base, *cb_base; + struct ebt_entry_target *t; + int verdict, sp = 0; + struct ebt_chainstack *cs; +@@ -108,6 +163,8 @@ + struct ebt_table_info *private = table->private; + + read_lock_bh(&table->lock); ++ cb_base = COUNTER_BASE(private->counters, private->nentries, \ ++ cpu_number_map(smp_processor_id())); + if (private->chainstack) + cs = private->chainstack[cpu_number_map(smp_processor_id())]; + else +@@ -115,117 +172,83 @@ + 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 + private->hook_entry[hook]->counter_offset; +- #define FWINV(bool,invflg) ((bool) ^ !!(point->invflags & invflg)) + // base for chain jumps + base = (char *)chaininfo; + i = 0; +- while (i < nentries) { +- if ( ( point->bitmask & EBT_NOPROTO || +- FWINV(point->ethproto == ((**pskb).mac.ethernet)->h_proto, +- EBT_IPROTO) +- || FWINV(ntohs(((**pskb).mac.ethernet)->h_proto) < 1536 && +- (point->bitmask & EBT_802_3), EBT_IPROTO) ) +- && FWINV(!ebt_dev_check((char *)(point->in), in), EBT_IIN) +- && FWINV(!ebt_dev_check((char *)(point->out), out), EBT_IOUT) +- && ((!in || !in->br_port) ? 1 : FWINV(!ebt_dev_check((char *) +- (point->logical_in), &in->br_port->br->dev), EBT_ILOGICALIN)) +- && ((!out || !out->br_port) ? 1 : +- FWINV(!ebt_dev_check((char *) +- (point->logical_out), &out->br_port->br->dev), EBT_ILOGICALOUT)) +- +- ) { +- if (point->bitmask & EBT_SOURCEMAC) { +- verdict = 0; +- for (j = 0; j < 6; j++) +- verdict |= (((**pskb).mac.ethernet)-> +- h_source[j] ^ point->sourcemac[j]) & +- point->sourcemsk[j]; +- if (FWINV(!!verdict, EBT_ISOURCE) ) +- goto letscontinue; +- } ++ while (i < nentries) { ++ if (ebt_basic_match(point, (**pskb).mac.ethernet, in, out)) ++ goto letscontinue; + +- if (point->bitmask & EBT_DESTMAC) { +- verdict = 0; +- for (j = 0; j < 6; j++) +- verdict |= (((**pskb).mac.ethernet)-> +- h_dest[j] ^ point->destmac[j]) & +- point->destmsk[j]; +- if (FWINV(!!verdict, EBT_IDEST) ) +- goto letscontinue; +- } ++ if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, ++ out, counter_base + i) != 0) ++ goto letscontinue; + +- if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, +- out, counter_base + i) != 0) +- goto letscontinue; ++ // increase counter ++ (*(counter_base + i)).pcnt++; + +- // increase counter +- (*(counter_base + i)).pcnt++; ++ // these should only watch: not modify, nor tell us ++ // what to do with the packet ++ EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, in, ++ out, counter_base + i); + +- // these should only watch: not modify, nor tell us +- // what to do with the packet +- EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, in, +- out, counter_base + i); +- +- t = (struct ebt_entry_target *) +- (((char *)point) + point->target_offset); +- // standard target +- if (!t->u.target->target) +- verdict = +- ((struct ebt_standard_target *)t)->verdict; +- else +- verdict = t->u.target->target(pskb, hook, +- in, out, t->data, t->target_size); +- if (verdict == EBT_ACCEPT) { +- read_unlock_bh(&table->lock); +- return NF_ACCEPT; +- } +- if (verdict == EBT_DROP) { +- read_unlock_bh(&table->lock); +- return NF_DROP; +- } +- if (verdict == EBT_RETURN) { ++ t = (struct ebt_entry_target *) ++ (((char *)point) + point->target_offset); ++ // standard target ++ if (!t->u.target->target) ++ verdict = ((struct ebt_standard_target *)t)->verdict; ++ else ++ verdict = t->u.target->target(pskb, hook, ++ in, out, t->data, t->target_size); ++ if (verdict == EBT_ACCEPT) { ++ read_unlock_bh(&table->lock); ++ return NF_ACCEPT; ++ } ++ if (verdict == EBT_DROP) { ++ read_unlock_bh(&table->lock); ++ return NF_DROP; ++ } ++ if (verdict == EBT_RETURN) { + letsreturn: +- if (sp == 0) +- // act like this is EBT_CONTINUE +- goto letscontinue; +- sp--; +- // put all the local variables right +- i = cs[sp].n; +- chaininfo = cs[sp].chaininfo; +- nentries = chaininfo->nentries; +- point = cs[sp].e; +- counter_base = cb_base + +- chaininfo->counter_offset; +- continue; +- } +- if (verdict == EBT_CONTINUE) ++ if (sp == 0) { ++ BUGPRINT("RETURN on base chain"); ++ // act like this is EBT_CONTINUE + goto letscontinue; +- if (verdict < 0) { +- BUGPRINT("bogus standard verdict\n"); +- read_unlock_bh(&table->lock); +- return NF_DROP; +- } +- // jump to a udc +- cs[sp].n = i + 1; +- cs[sp].chaininfo = chaininfo; +- cs[sp].e = (struct ebt_entry *) +- (((char *)point) + point->next_offset); +- i = 0; +- chaininfo = (struct ebt_entries *) (base + verdict); +- if (chaininfo->distinguisher) { +- BUGPRINT("jump to non-chain\n"); +- read_unlock_bh(&table->lock); +- return NF_DROP; + } ++ sp--; ++ // put all the local variables right ++ i = cs[sp].n; ++ chaininfo = cs[sp].chaininfo; + nentries = chaininfo->nentries; +- point = (struct ebt_entry *)chaininfo->data; +- counter_base = cb_base + chaininfo->counter_offset; +- sp++; ++ point = cs[sp].e; ++ counter_base = cb_base + ++ chaininfo->counter_offset; + continue; + } ++ if (verdict == EBT_CONTINUE) ++ goto letscontinue; ++ if (verdict < 0) { ++ BUGPRINT("bogus standard verdict\n"); ++ read_unlock_bh(&table->lock); ++ return NF_DROP; ++ } ++ // jump to a udc ++ cs[sp].n = i + 1; ++ cs[sp].chaininfo = chaininfo; ++ cs[sp].e = (struct ebt_entry *) ++ (((char *)point) + point->next_offset); ++ i = 0; ++ chaininfo = (struct ebt_entries *) (base + verdict); ++ if (chaininfo->distinguisher) { ++ BUGPRINT("jump to non-chain\n"); ++ read_unlock_bh(&table->lock); ++ return NF_DROP; ++ } ++ nentries = chaininfo->nentries; ++ point = (struct ebt_entry *)chaininfo->data; ++ counter_base = cb_base + chaininfo->counter_offset; ++ sp++; ++ continue; + letscontinue: + point = (struct ebt_entry *) + (((char *)point) + point->next_offset); +@@ -284,7 +307,6 @@ + request_module(modulename); + ret = find_inlist_lock_noload(head, name, error, mutex); + } +- + return ret; + } + #endif +@@ -320,9 +342,12 @@ + struct ebt_match *match; + int ret; + ++ if (((char *)m) + m->match_size + sizeof(struct ebt_entry_match) > ++ ((char *)e) + e->watchers_offset) ++ return -EINVAL; + m->u.name[EBT_FUNCTION_MAXNAMELEN - 1] = '\0'; + match = find_match_lock(m->u.name, &ret, &ebt_mutex); +- if (!match) ++ if (!match) + return ret; + m->u.match = match; + if (match->me) +@@ -346,9 +371,12 @@ + struct ebt_watcher *watcher; + int ret; + ++ if (((char *)w) + w->watcher_size + sizeof(struct ebt_entry_watcher) > ++ ((char *)e) + e->target_offset) ++ return -EINVAL; + w->u.name[EBT_FUNCTION_MAXNAMELEN - 1] = '\0'; + watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex); +- if (!watcher) ++ if (!watcher) + return ret; + w->u.watcher = watcher; + if (watcher->me) +@@ -547,14 +575,16 @@ + else + break; + } ++ // (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on ++ // a base chain + if (i < NF_BR_NUMHOOKS) +- hookmask = (1 << hook); ++ hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS); + else { + for (i = 0; i < udc_cnt; i++) + if ((char *)(cl_s[i].cs.chaininfo) > (char *)e) + break; + if (i == 0) +- hookmask = (1 << hook); ++ hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS); + else + hookmask = cl_s[i - 1].hookmask; + } +@@ -589,9 +619,10 @@ + ret = -EFAULT; + goto cleanup_watchers; + } +- } else if (t->u.target->check && +- t->u.target->check(name, hookmask, e, t->data, +- t->target_size) != 0) { ++ } else if ((e->target_offset + t->target_size + ++ sizeof(struct ebt_entry_target) > e->next_offset) || ++ (t->u.target->check && ++ t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){ + if (t->u.target->me) + __MOD_DEC_USE_COUNT(t->u.target->me); + ret = -EFAULT; +@@ -611,7 +642,7 @@ + { + struct ebt_entry_target *t; + +- if (e->bitmask == 0) ++ if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0) + return 0; + // we're done + if (cnt && (*cnt)-- == 0) +@@ -643,7 +674,8 @@ + // put back values of the time when this chain was called + e = cl_s[chain_nr].cs.e; + if (cl_s[chain_nr].from != -1) +- nentries = cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries; ++ nentries = ++ cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries; + else + nentries = chain->nentries; + pos = cl_s[chain_nr].cs.n; +@@ -679,6 +711,7 @@ + BUGPRINT("loop\n"); + return -1; + } ++ // this can't be 0, so the above test is correct + cl_s[i].cs.n = pos + 1; + pos = 0; + cl_s[i].cs.e = ((void *)e + e->next_offset); +@@ -784,7 +817,7 @@ + vfree(newinfo->chainstack[--i]); + vfree(newinfo->chainstack); + newinfo->chainstack = NULL; +- break; ++ return -ENOMEM; + } + } + +@@ -824,7 +857,6 @@ + // beginning of a chain. This can only occur in chains that + // are not accessible from any base chains, so we don't care. + +- // we just don't trust anything + repl->name[EBT_TABLE_MAXNAMELEN - 1] = '\0'; + // used to know what we need to clean up if something goes wrong + i = 0; +@@ -841,27 +873,27 @@ + } + + // called under write_lock +-static inline void get_counters(struct ebt_counter *oldcounters, ++static void get_counters(struct ebt_counter *oldcounters, + struct ebt_counter *counters, unsigned int nentries) + { +- int i, cpu, counter_base; ++ int i, cpu; ++ struct ebt_counter *counter_base; + + // counters of cpu 0 + 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 * nentries; ++ counter_base = COUNTER_BASE(oldcounters, nentries, cpu); + for (i = 0; i < nentries; i++) +- counters[i].pcnt += +- oldcounters[counter_base + i].pcnt; ++ counters[i].pcnt += counter_base[i].pcnt; + } + } + + // replace the table + static int do_replace(void *user, unsigned int len) + { +- int ret, i; ++ int ret, i, countersize; + struct ebt_table_info *newinfo; + struct ebt_replace tmp; + struct ebt_table *t; +@@ -869,7 +901,7 @@ + // used to be able to unlock earlier + struct ebt_table_info *table; + +- if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) ++ if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) + return -EFAULT; + + if (len != sizeof(tmp) + tmp.entries_size) { +@@ -881,28 +913,19 @@ + BUGPRINT("Entries_size never zero\n"); + return -EINVAL; + } ++ countersize = COUNTER_OFFSET(tmp.nentries) * smp_num_cpus; + newinfo = (struct ebt_table_info *) +- vmalloc(sizeof(struct ebt_table_info)); ++ vmalloc(sizeof(struct ebt_table_info) + countersize); + if (!newinfo) + return -ENOMEM; + +- if (tmp.nentries) { +- newinfo->counters = (struct ebt_counter *)vmalloc( +- sizeof(struct ebt_counter) * tmp.nentries * smp_num_cpus); +- if (!newinfo->counters) { +- ret = -ENOMEM; +- goto free_newinfo; +- } +- memset(newinfo->counters, 0, +- sizeof(struct ebt_counter) * tmp.nentries * smp_num_cpus); +- } +- else +- newinfo->counters = NULL; ++ if (countersize) ++ memset(newinfo->counters, 0, countersize); + + newinfo->entries = (char *)vmalloc(tmp.entries_size); + if (!newinfo->entries) { + ret = -ENOMEM; +- goto free_counters; ++ goto free_newinfo; + } + if (copy_from_user( + newinfo->entries, tmp.entries, tmp.entries_size) != 0) { +@@ -933,7 +956,7 @@ + + t = find_table_lock(tmp.name, &ret, &ebt_mutex); + if (!t) +- goto free_unlock; ++ goto free_iterate; + + // the table doesn't like it + if (t->check && (ret = t->check(newinfo, tmp.valid_hooks))) +@@ -974,8 +997,6 @@ + ebt_cleanup_entry, NULL); + + vfree(table->entries); +- if (table->counters) +- vfree(table->counters); + if (table->chainstack) { + for (i = 0; i < smp_num_cpus; i++) + vfree(table->chainstack[i]); +@@ -989,6 +1010,7 @@ + + free_unlock: + up(&ebt_mutex); ++free_iterate: + EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, + ebt_cleanup_entry, NULL); + free_counterstmp: +@@ -1003,9 +1025,6 @@ + free_entries: + if (newinfo->entries) + vfree(newinfo->entries); +-free_counters: +- if (newinfo->counters) +- vfree(newinfo->counters); + free_newinfo: + if (newinfo) + vfree(newinfo); +@@ -1090,7 +1109,7 @@ + int ebt_register_table(struct ebt_table *table) + { + struct ebt_table_info *newinfo; +- int ret, i; ++ int ret, i, countersize; + + if (!table || !table->table ||!table->table->entries || + table->table->entries_size == 0 || +@@ -1099,8 +1118,9 @@ + return -EINVAL; + } + ++ countersize = COUNTER_OFFSET(table->table->nentries) * smp_num_cpus; + newinfo = (struct ebt_table_info *) +- vmalloc(sizeof(struct ebt_table_info)); ++ vmalloc(sizeof(struct ebt_table_info) + countersize); + ret = -ENOMEM; + if (!newinfo) + return -ENOMEM; +@@ -1112,24 +1132,15 @@ + memcpy(newinfo->entries, table->table->entries, + table->table->entries_size); + +- if (table->table->nentries) { +- newinfo->counters = (struct ebt_counter *) +- vmalloc(table->table->nentries * +- sizeof(struct ebt_counter) * smp_num_cpus); +- if (!newinfo->counters) +- goto free_entries; +- memset(newinfo->counters, 0, table->table->nentries * +- sizeof(struct ebt_counter) * smp_num_cpus); +- } +- else +- newinfo->counters = NULL; ++ if (countersize) ++ memset(newinfo->counters, 0, countersize); + + // fill in newinfo and parse the entries + newinfo->chainstack = NULL; + ret = translate_table(table->table, newinfo); + if (ret != 0) { + BUGPRINT("Translate_table failed\n"); +- goto free_counters; ++ goto free_chainstack; + } + + if (table->check && table->check(newinfo, table->valid_hooks)) { +@@ -1141,7 +1152,7 @@ + table->lock = RW_LOCK_UNLOCKED; + ret = down_interruptible(&ebt_mutex); + if (ret != 0) +- goto free_counters; ++ goto free_chainstack; + + if (list_named_find(&ebt_tables, table->name)) { + ret = -EEXIST; +@@ -1155,15 +1166,12 @@ + return 0; + free_unlock: + up(&ebt_mutex); +-free_counters: +- if (newinfo->counters) +- vfree(newinfo->counters); ++free_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: + vfree(newinfo); +@@ -1183,8 +1191,6 @@ + up(&ebt_mutex); + EBT_ENTRY_ITERATE(table->private->entries, + table->private->entries_size, ebt_cleanup_entry, NULL); +- if (table->private->counters) +- vfree(table->private->counters); + if (table->private->entries) + vfree(table->private->entries); + if (table->private->chainstack) { +@@ -1219,7 +1225,6 @@ + } + + hlp.name[EBT_TABLE_MAXNAMELEN - 1] = '\0'; +- + t = find_table_lock(hlp.name, &ret, &ebt_mutex); + if (!t) + goto free_tmp; +@@ -1344,7 +1349,7 @@ + counterstmp = (struct ebt_counter *) + vmalloc(nentries * sizeof(struct ebt_counter)); + if (!counterstmp) { +- BUGPRINT("Couldn't copy counters, out of memory\n"); ++ MEMPRINT("Couldn't copy counters, out of memory\n"); + return -ENOMEM; + } + write_lock_bh(&t->lock); +--- linux/include/linux/netfilter_bridge/ebtables.h Wed Jul 31 19:15:22 2002 ++++ ebt2.0-rc1/include/linux/netfilter_bridge/ebtables.h Wed Jul 31 19:04:30 2002 +@@ -12,9 +12,9 @@ + + #ifndef __LINUX_BRIDGE_EFF_H + #define __LINUX_BRIDGE_EFF_H +-#include // IFNAMSIZ ++#include + #include +-#include // ETH_ALEN ++#include + + #define EBT_TABLE_MAXNAMELEN 32 + #define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN +@@ -46,10 +46,10 @@ + }; + + struct ebt_entries { +- // this field is always set to zero (including userspace). ++ // this field is always set to zero + // See EBT_ENTRY_OR_ENTRIES. + // Must be same size as ebt_entry.bitmask +- __u32 distinguisher; ++ unsigned int distinguisher; + // the chain name + char name[EBT_CHAIN_MAXNAMELEN]; + // counter offset for this chain +@@ -133,27 +133,27 @@ + // one entry + struct ebt_entry { + // this needs to be the first field +- __u32 bitmask; +- __u32 invflags; ++ unsigned int bitmask; ++ unsigned int invflags; + __u16 ethproto; + // the physical in-dev +- __u8 in[IFNAMSIZ]; ++ char in[IFNAMSIZ]; + // the logical in-dev +- __u8 logical_in[IFNAMSIZ]; ++ char logical_in[IFNAMSIZ]; + // the physical out-dev +- __u8 out[IFNAMSIZ]; ++ char out[IFNAMSIZ]; + // the logical out-dev +- __u8 logical_out[IFNAMSIZ]; +- __u8 sourcemac[ETH_ALEN]; +- __u8 sourcemsk[ETH_ALEN]; +- __u8 destmac[ETH_ALEN]; +- __u8 destmsk[ETH_ALEN]; ++ char logical_out[IFNAMSIZ]; ++ unsigned char sourcemac[ETH_ALEN]; ++ unsigned char sourcemsk[ETH_ALEN]; ++ unsigned char destmac[ETH_ALEN]; ++ unsigned char destmsk[ETH_ALEN]; + // sizeof ebt_entry + matches +- __u16 watchers_offset; ++ unsigned int watchers_offset; + // sizeof ebt_entry + matches + watchers +- __u16 target_offset; ++ unsigned int target_offset; + // sizeof ebt_entry + matches + watchers + target +- __u16 next_offset; ++ unsigned int next_offset; + unsigned char elems[0]; + }; + +@@ -238,10 +238,10 @@ + unsigned int nentries; + // pointers to the start of the chains + 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; + char *entries; ++ struct ebt_counter counters[0] __attribute__((aligned(SMP_CACHE_BYTES))); + }; + + struct ebt_table +--- /dev/null Thu Aug 24 11:00:32 2000 ++++ ebt2.0-rc1/include/linux/netfilter_bridge/ebt_mark_t.h Wed Jul 31 19:04:30 2002 +@@ -0,0 +1,12 @@ ++#ifndef __LINUX_BRIDGE_EBT_MARK_T_H ++#define __LINUX_BRIDGE_EBT_MARK_T_H ++ ++struct ebt_mark_t_info ++{ ++ unsigned long mark; ++ // EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN ++ int target; ++}; ++#define EBT_MARK_TARGET "mark" ++ ++#endif +--- /dev/null Thu Aug 24 11:00:32 2000 ++++ ebt2.0-rc1/include/linux/netfilter_bridge/ebt_mark_m.h Wed Jul 31 19:04:30 2002 +@@ -0,0 +1,15 @@ ++#ifndef __LINUX_BRIDGE_EBT_MARK_M_H ++#define __LINUX_BRIDGE_EBT_MARK_M_H ++ ++#define EBT_MARK_AND 0x01 ++#define EBT_MARK_OR 0x02 ++#define EBT_MARK_MASK (EBT_MARK_AND | EBT_MARK_OR) ++struct ebt_mark_m_info ++{ ++ unsigned long mark, mask; ++ __u8 invert; ++ __u8 bitmask; ++}; ++#define EBT_MARK_MATCH "mark_m" ++ ++#endif -- cgit v1.2.3