blob: 6e03a05619d5b6801e1bae2539b3cef7a622615b [file] [log] [blame]
--- 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 <bart.de.schuymer@pandora.be>
+ *
+ * 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 <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_mark_t.h>
+#include <linux/netfilter_bridge.h>
+#include <linux/skbuff.h>
+#include <linux/module.h>
+#include <net/sock.h>
+#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 <bart.de.schuymer@pandora.be>
+ *
+ * July, 2002
+ *
+ */
+
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_mark_m.h>
+#include <linux/module.h>
+
+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 <bart.de.schuymer@pandora.be>
*
- * 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 <linux/if.h> // IFNAMSIZ
+#include <linux/if.h>
#include <linux/netfilter_bridge.h>
-#include <linux/if_ether.h> // ETH_ALEN
+#include <linux/if_ether.h>
#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