aboutsummaryrefslogtreecommitdiff
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br.c22
-rw-r--r--net/bridge/br_device.c27
-rw-r--r--net/bridge/br_if.c18
-rw-r--r--net/bridge/br_ioctl.c28
-rw-r--r--net/bridge/br_netfilter.c67
-rw-r--r--net/bridge/br_netlink.c15
-rw-r--r--net/bridge/br_notify.c3
-rw-r--r--net/bridge/br_private.h12
-rw-r--r--net/bridge/br_stp.c25
-rw-r--r--net/bridge/br_stp_bpdu.c3
-rw-r--r--net/bridge/br_sysfs_br.c26
-rw-r--r--net/bridge/netfilter/Kconfig30
-rw-r--r--net/bridge/netfilter/ebt_802_3.c47
-rw-r--r--net/bridge/netfilter/ebt_among.c85
-rw-r--r--net/bridge/netfilter/ebt_arp.c73
-rw-r--r--net/bridge/netfilter/ebt_arpreply.c49
-rw-r--r--net/bridge/netfilter/ebt_dnat.c57
-rw-r--r--net/bridge/netfilter/ebt_ip.c72
-rw-r--r--net/bridge/netfilter/ebt_ip6.c76
-rw-r--r--net/bridge/netfilter/ebt_limit.c45
-rw-r--r--net/bridge/netfilter/ebt_log.c57
-rw-r--r--net/bridge/netfilter/ebt_mark.c41
-rw-r--r--net/bridge/netfilter/ebt_mark_m.c45
-rw-r--r--net/bridge/netfilter/ebt_nflog.c44
-rw-r--r--net/bridge/netfilter/ebt_pkttype.c41
-rw-r--r--net/bridge/netfilter/ebt_redirect.c63
-rw-r--r--net/bridge/netfilter/ebt_snat.c52
-rw-r--r--net/bridge/netfilter/ebt_stp.c78
-rw-r--r--net/bridge/netfilter/ebt_ulog.c58
-rw-r--r--net/bridge/netfilter/ebt_vlan.c61
-rw-r--r--net/bridge/netfilter/ebtable_filter.c18
-rw-r--r--net/bridge/netfilter/ebtable_nat.c18
-rw-r--r--net/bridge/netfilter/ebtables.c313
33 files changed, 814 insertions, 855 deletions
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 573acdf6f9f..4d2c1f1cb52 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -28,6 +28,10 @@ static const struct stp_proto br_stp_proto = {
.rcv = br_stp_rcv,
};
+static struct pernet_operations br_net_ops = {
+ .exit = br_net_exit,
+};
+
static int __init br_init(void)
{
int err;
@@ -42,18 +46,22 @@ static int __init br_init(void)
if (err)
goto err_out;
- err = br_netfilter_init();
+ err = register_pernet_subsys(&br_net_ops);
if (err)
goto err_out1;
- err = register_netdevice_notifier(&br_device_notifier);
+ err = br_netfilter_init();
if (err)
goto err_out2;
- err = br_netlink_init();
+ err = register_netdevice_notifier(&br_device_notifier);
if (err)
goto err_out3;
+ err = br_netlink_init();
+ if (err)
+ goto err_out4;
+
brioctl_set(br_ioctl_deviceless_stub);
br_handle_frame_hook = br_handle_frame;
@@ -61,10 +69,12 @@ static int __init br_init(void)
br_fdb_put_hook = br_fdb_put;
return 0;
-err_out3:
+err_out4:
unregister_netdevice_notifier(&br_device_notifier);
-err_out2:
+err_out3:
br_netfilter_fini();
+err_out2:
+ unregister_pernet_subsys(&br_net_ops);
err_out1:
br_fdb_fini();
err_out:
@@ -80,7 +90,7 @@ static void __exit br_deinit(void)
unregister_netdevice_notifier(&br_device_notifier);
brioctl_set(NULL);
- br_cleanup_bridges();
+ unregister_pernet_subsys(&br_net_ops);
synchronize_net();
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index d9449df7cad..22ba8632196 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -68,10 +68,17 @@ static int br_dev_stop(struct net_device *dev)
static int br_change_mtu(struct net_device *dev, int new_mtu)
{
- if (new_mtu < 68 || new_mtu > br_min_mtu(netdev_priv(dev)))
+ struct net_bridge *br = netdev_priv(dev);
+ if (new_mtu < 68 || new_mtu > br_min_mtu(br))
return -EINVAL;
dev->mtu = new_mtu;
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+ /* remember the MTU in the rtable for PMTU */
+ br->fake_rtable.u.dst.metrics[RTAX_MTU - 1] = new_mtu;
+#endif
+
return 0;
}
@@ -141,11 +148,16 @@ static int br_set_tx_csum(struct net_device *dev, u32 data)
}
static struct ethtool_ops br_ethtool_ops = {
- .get_drvinfo = br_getinfo,
- .get_link = ethtool_op_get_link,
- .set_sg = br_set_sg,
- .set_tx_csum = br_set_tx_csum,
- .set_tso = br_set_tso,
+ .get_drvinfo = br_getinfo,
+ .get_link = ethtool_op_get_link,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = br_set_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = br_set_sg,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = br_set_tso,
+ .get_ufo = ethtool_op_get_ufo,
+ .get_flags = ethtool_op_get_flags,
};
void br_dev_setup(struct net_device *dev)
@@ -166,5 +178,6 @@ void br_dev_setup(struct net_device *dev)
dev->priv_flags = IFF_EBRIDGE;
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
- NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX;
+ NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX |
+ NETIF_F_NETNS_LOCAL;
}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index a072ea5ca6f..573e20f7dba 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -168,7 +168,7 @@ static void del_br(struct net_bridge *br)
unregister_netdevice(br->dev);
}
-static struct net_device *new_bridge_dev(const char *name)
+static struct net_device *new_bridge_dev(struct net *net, const char *name)
{
struct net_bridge *br;
struct net_device *dev;
@@ -178,6 +178,7 @@ static struct net_device *new_bridge_dev(const char *name)
if (!dev)
return NULL;
+ dev_net_set(dev, net);
br = netdev_priv(dev);
br->dev = dev;
@@ -202,6 +203,9 @@ static struct net_device *new_bridge_dev(const char *name)
br->topology_change = 0;
br->topology_change_detected = 0;
br->ageing_time = 300 * HZ;
+
+ br_netfilter_rtable_init(br);
+
INIT_LIST_HEAD(&br->age_list);
br_stp_timer_init(br);
@@ -259,12 +263,12 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
return p;
}
-int br_add_bridge(const char *name)
+int br_add_bridge(struct net *net, const char *name)
{
struct net_device *dev;
int ret;
- dev = new_bridge_dev(name);
+ dev = new_bridge_dev(net, name);
if (!dev)
return -ENOMEM;
@@ -291,13 +295,13 @@ out_free:
goto out;
}
-int br_del_bridge(const char *name)
+int br_del_bridge(struct net *net, const char *name)
{
struct net_device *dev;
int ret = 0;
rtnl_lock();
- dev = __dev_get_by_name(&init_net, name);
+ dev = __dev_get_by_name(net, name);
if (dev == NULL)
ret = -ENXIO; /* Could not find device */
@@ -442,13 +446,13 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
return 0;
}
-void __exit br_cleanup_bridges(void)
+void br_net_exit(struct net *net)
{
struct net_device *dev;
rtnl_lock();
restart:
- for_each_netdev(&init_net, dev) {
+ for_each_netdev(net, dev) {
if (dev->priv_flags & IFF_EBRIDGE) {
del_br(dev->priv);
goto restart;
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index eeee218eed8..6a6433daaf2 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -21,12 +21,12 @@
#include "br_private.h"
/* called with RTNL */
-static int get_bridge_ifindices(int *indices, int num)
+static int get_bridge_ifindices(struct net *net, int *indices, int num)
{
struct net_device *dev;
int i = 0;
- for_each_netdev(&init_net, dev) {
+ for_each_netdev(net, dev) {
if (i >= num)
break;
if (dev->priv_flags & IFF_EBRIDGE)
@@ -89,7 +89,7 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd)
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- dev = dev_get_by_index(&init_net, ifindex);
+ dev = dev_get_by_index(dev_net(br->dev), ifindex);
if (dev == NULL)
return -EINVAL;
@@ -188,15 +188,21 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return 0;
case BRCTL_SET_BRIDGE_HELLO_TIME:
+ {
+ unsigned long t = clock_t_to_jiffies(args[1]);
if (!capable(CAP_NET_ADMIN))
return -EPERM;
+ if (t < HZ)
+ return -EINVAL;
+
spin_lock_bh(&br->lock);
- br->bridge_hello_time = clock_t_to_jiffies(args[1]);
+ br->bridge_hello_time = t;
if (br_is_root_bridge(br))
br->hello_time = br->bridge_hello_time;
spin_unlock_bh(&br->lock);
return 0;
+ }
case BRCTL_SET_BRIDGE_MAX_AGE:
if (!capable(CAP_NET_ADMIN))
@@ -309,7 +315,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return -EOPNOTSUPP;
}
-static int old_deviceless(void __user *uarg)
+static int old_deviceless(struct net *net, void __user *uarg)
{
unsigned long args[3];
@@ -331,7 +337,7 @@ static int old_deviceless(void __user *uarg)
if (indices == NULL)
return -ENOMEM;
- args[2] = get_bridge_ifindices(indices, args[2]);
+ args[2] = get_bridge_ifindices(net, indices, args[2]);
ret = copy_to_user((void __user *)args[1], indices, args[2]*sizeof(int))
? -EFAULT : args[2];
@@ -354,9 +360,9 @@ static int old_deviceless(void __user *uarg)
buf[IFNAMSIZ-1] = 0;
if (args[0] == BRCTL_ADD_BRIDGE)
- return br_add_bridge(buf);
+ return br_add_bridge(net, buf);
- return br_del_bridge(buf);
+ return br_del_bridge(net, buf);
}
}
@@ -368,7 +374,7 @@ int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uar
switch (cmd) {
case SIOCGIFBR:
case SIOCSIFBR:
- return old_deviceless(uarg);
+ return old_deviceless(net, uarg);
case SIOCBRADDBR:
case SIOCBRDELBR:
@@ -383,9 +389,9 @@ int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uar
buf[IFNAMSIZ-1] = 0;
if (cmd == SIOCBRADDBR)
- return br_add_bridge(buf);
+ return br_add_bridge(net, buf);
- return br_del_bridge(buf);
+ return br_del_bridge(net, buf);
}
}
return -EOPNOTSUPP;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index bb90cd7bace..a4abed5b4c4 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -101,33 +101,30 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb)
pppoe_proto(skb) == htons(PPP_IPV6) && \
brnf_filter_pppoe_tagged)
-/* We need these fake structures to make netfilter happy --
- * lots of places assume that skb->dst != NULL, which isn't
- * all that unreasonable.
- *
+/*
+ * Initialize bogus route table used to keep netfilter happy.
* Currently, we fill in the PMTU entry because netfilter
* refragmentation needs it, and the rt_flags entry because
* ipt_REJECT needs it. Future netfilter modules might
- * require us to fill additional fields. */
-static struct net_device __fake_net_device = {
- .hard_header_len = ETH_HLEN,
-#ifdef CONFIG_NET_NS
- .nd_net = &init_net,
-#endif
-};
+ * require us to fill additional fields.
+ */
+void br_netfilter_rtable_init(struct net_bridge *br)
+{
+ struct rtable *rt = &br->fake_rtable;
-static struct rtable __fake_rtable = {
- .u = {
- .dst = {
- .__refcnt = ATOMIC_INIT(1),
- .dev = &__fake_net_device,
- .path = &__fake_rtable.u.dst,
- .metrics = {[RTAX_MTU - 1] = 1500},
- .flags = DST_NOXFRM,
- }
- },
- .rt_flags = 0,
-};
+ atomic_set(&rt->u.dst.__refcnt, 1);
+ rt->u.dst.dev = br->dev;
+ rt->u.dst.path = &rt->u.dst;
+ rt->u.dst.metrics[RTAX_MTU - 1] = 1500;
+ rt->u.dst.flags = DST_NOXFRM;
+}
+
+static inline struct rtable *bridge_parent_rtable(const struct net_device *dev)
+{
+ struct net_bridge_port *port = rcu_dereference(dev->br_port);
+
+ return port ? &port->br->fake_rtable : NULL;
+}
static inline struct net_device *bridge_parent(const struct net_device *dev)
{
@@ -226,8 +223,12 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
}
nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
- skb->rtable = &__fake_rtable;
- dst_hold(&__fake_rtable.u.dst);
+ skb->rtable = bridge_parent_rtable(nf_bridge->physindev);
+ if (!skb->rtable) {
+ kfree_skb(skb);
+ return 0;
+ }
+ dst_hold(&skb->rtable->u.dst);
skb->dev = nf_bridge->physindev;
nf_bridge_push_encap_header(skb);
@@ -391,8 +392,12 @@ bridged_dnat:
skb->pkt_type = PACKET_HOST;
}
} else {
- skb->rtable = &__fake_rtable;
- dst_hold(&__fake_rtable.u.dst);
+ skb->rtable = bridge_parent_rtable(nf_bridge->physindev);
+ if (!skb->rtable) {
+ kfree_skb(skb);
+ return 0;
+ }
+ dst_hold(&skb->rtable->u.dst);
}
skb->dev = nf_bridge->physindev;
@@ -611,8 +616,8 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff *skb,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- if (skb->rtable == &__fake_rtable) {
- dst_release(&__fake_rtable.u.dst);
+ if (skb->rtable && skb->rtable == bridge_parent_rtable(in)) {
+ dst_release(&skb->rtable->u.dst);
skb->rtable = NULL;
}
@@ -652,7 +657,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb,
{
struct nf_bridge_info *nf_bridge;
struct net_device *parent;
- int pf;
+ u_int8_t pf;
if (!skb->nf_bridge)
return NF_ACCEPT;
@@ -786,7 +791,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb,
{
struct nf_bridge_info *nf_bridge = skb->nf_bridge;
struct net_device *realoutdev = bridge_parent(skb->dev);
- int pf;
+ u_int8_t pf;
#ifdef CONFIG_NETFILTER_DEBUG
/* Be very paranoid. This probably won't happen anymore, but let's
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index f155e6ce8a2..ba7be195803 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -82,6 +82,7 @@ nla_put_failure:
*/
void br_ifinfo_notify(int event, struct net_bridge_port *port)
{
+ struct net *net = dev_net(port->dev);
struct sk_buff *skb;
int err = -ENOBUFS;
@@ -97,10 +98,10 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port)
kfree_skb(skb);
goto errout;
}
- err = rtnl_notify(skb, &init_net,0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
+ err = rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
errout:
if (err < 0)
- rtnl_set_sk_err(&init_net, RTNLGRP_LINK, err);
+ rtnl_set_sk_err(net, RTNLGRP_LINK, err);
}
/*
@@ -112,11 +113,8 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
struct net_device *dev;
int idx;
- if (net != &init_net)
- return 0;
-
idx = 0;
- for_each_netdev(&init_net, dev) {
+ for_each_netdev(net, dev) {
/* not a bridge port */
if (dev->br_port == NULL || idx < cb->args[0])
goto skip;
@@ -147,9 +145,6 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
struct net_bridge_port *p;
u8 new_state;
- if (net != &init_net)
- return -EINVAL;
-
if (nlmsg_len(nlh) < sizeof(*ifm))
return -EINVAL;
@@ -165,7 +160,7 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (new_state > BR_STATE_BLOCKING)
return -EINVAL;
- dev = __dev_get_by_index(&init_net, ifm->ifi_index);
+ dev = __dev_get_by_index(net, ifm->ifi_index);
if (!dev)
return -ENODEV;
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index 76340bdd052..763a3ec292e 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -35,9 +35,6 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
struct net_bridge_port *p = dev->br_port;
struct net_bridge *br;
- if (!net_eq(dev_net(dev), &init_net))
- return NOTIFY_DONE;
-
/* not a port of a bridge */
if (p == NULL)
return NOTIFY_DONE;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 815ed38925b..b6c3b71974d 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -15,6 +15,7 @@
#include <linux/netdevice.h>
#include <linux/if_bridge.h>
+#include <net/route.h>
#define BR_HASH_BITS 8
#define BR_HASH_SIZE (1 << BR_HASH_BITS)
@@ -92,6 +93,9 @@ struct net_bridge
struct hlist_head hash[BR_HASH_SIZE];
struct list_head age_list;
unsigned long feature_mask;
+#ifdef CONFIG_BRIDGE_NETFILTER
+ struct rtable fake_rtable;
+#endif
unsigned long flags;
#define BR_SET_MAC_ADDR 0x00000001
@@ -174,9 +178,9 @@ extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb);
/* br_if.c */
extern void br_port_carrier_check(struct net_bridge_port *p);
-extern int br_add_bridge(const char *name);
-extern int br_del_bridge(const char *name);
-extern void br_cleanup_bridges(void);
+extern int br_add_bridge(struct net *net, const char *name);
+extern int br_del_bridge(struct net *net, const char *name);
+extern void br_net_exit(struct net *net);
extern int br_add_if(struct net_bridge *br,
struct net_device *dev);
extern int br_del_if(struct net_bridge *br,
@@ -197,9 +201,11 @@ extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __us
#ifdef CONFIG_BRIDGE_NETFILTER
extern int br_netfilter_init(void);
extern void br_netfilter_fini(void);
+extern void br_netfilter_rtable_init(struct net_bridge *);
#else
#define br_netfilter_init() (0)
#define br_netfilter_fini() do { } while(0)
+#define br_netfilter_rtable_init(x)
#endif
/* br_stp.c */
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 921bbe5cb94..6e63ec3f1fc 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -368,14 +368,25 @@ static void br_make_blocking(struct net_bridge_port *p)
/* called under bridge lock */
static void br_make_forwarding(struct net_bridge_port *p)
{
- if (p->state == BR_STATE_BLOCKING) {
- if (p->br->stp_enabled == BR_KERNEL_STP)
- p->state = BR_STATE_LISTENING;
- else
- p->state = BR_STATE_LEARNING;
+ struct net_bridge *br = p->br;
- br_log_state(p);
- mod_timer(&p->forward_delay_timer, jiffies + p->br->forward_delay); }
+ if (p->state != BR_STATE_BLOCKING)
+ return;
+
+ if (br->forward_delay == 0) {
+ p->state = BR_STATE_FORWARDING;
+ br_topology_change_detection(br);
+ del_timer(&p->forward_delay_timer);
+ }
+ else if (p->br->stp_enabled == BR_KERNEL_STP)
+ p->state = BR_STATE_LISTENING;
+ else
+ p->state = BR_STATE_LEARNING;
+
+ br_log_state(p);
+
+ if (br->forward_delay != 0)
+ mod_timer(&p->forward_delay_timer, jiffies + br->forward_delay);
}
/* called under bridge lock */
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index 8b200f96f72..81ae40b3f65 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -140,9 +140,6 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
struct net_bridge *br;
const unsigned char *buf;
- if (!net_eq(dev_net(dev), &init_net))
- goto err;
-
if (!p)
goto err;
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 27d6a511c8c..158dee8b496 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -29,11 +29,12 @@
*/
static ssize_t store_bridge_parm(struct device *d,
const char *buf, size_t len,
- void (*set)(struct net_bridge *, unsigned long))
+ int (*set)(struct net_bridge *, unsigned long))
{
struct net_bridge *br = to_bridge(d);
char *endp;
unsigned long val;
+ int err;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
@@ -43,9 +44,9 @@ static ssize_t store_bridge_parm(struct device *d,
return -EINVAL;
spin_lock_bh(&br->lock);
- (*set)(br, val);
+ err = (*set)(br, val);
spin_unlock_bh(&br->lock);
- return len;
+ return err ? err : len;
}
@@ -56,12 +57,13 @@ static ssize_t show_forward_delay(struct device *d,
return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay));
}
-static void set_forward_delay(struct net_bridge *br, unsigned long val)
+static int set_forward_delay(struct net_bridge *br, unsigned long val)
{
unsigned long delay = clock_t_to_jiffies(val);
br->forward_delay = delay;
if (br_is_root_bridge(br))
br->bridge_forward_delay = delay;
+ return 0;
}
static ssize_t store_forward_delay(struct device *d,
@@ -80,12 +82,17 @@ static ssize_t show_hello_time(struct device *d, struct device_attribute *attr,
jiffies_to_clock_t(to_bridge(d)->hello_time));
}
-static void set_hello_time(struct net_bridge *br, unsigned long val)
+static int set_hello_time(struct net_bridge *br, unsigned long val)
{
unsigned long t = clock_t_to_jiffies(val);
+
+ if (t < HZ)
+ return -EINVAL;
+
br->hello_time = t;
if (br_is_root_bridge(br))
br->bridge_hello_time = t;
+ return 0;
}
static ssize_t store_hello_time(struct device *d,
@@ -104,12 +111,13 @@ static ssize_t show_max_age(struct device *d, struct device_attribute *attr,
jiffies_to_clock_t(to_bridge(d)->max_age));
}
-static void set_max_age(struct net_bridge *br, unsigned long val)
+static int set_max_age(struct net_bridge *br, unsigned long val)
{
unsigned long t = clock_t_to_jiffies(val);
br->max_age = t;
if (br_is_root_bridge(br))
br->bridge_max_age = t;
+ return 0;
}
static ssize_t store_max_age(struct device *d, struct device_attribute *attr,
@@ -126,9 +134,10 @@ static ssize_t show_ageing_time(struct device *d,
return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time));
}
-static void set_ageing_time(struct net_bridge *br, unsigned long val)
+static int set_ageing_time(struct net_bridge *br, unsigned long val)
{
br->ageing_time = clock_t_to_jiffies(val);
+ return 0;
}
static ssize_t store_ageing_time(struct device *d,
@@ -180,9 +189,10 @@ static ssize_t show_priority(struct device *d, struct device_attribute *attr,
(br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]);
}
-static void set_priority(struct net_bridge *br, unsigned long val)
+static int set_priority(struct net_bridge *br, unsigned long val)
{
br_stp_set_bridge_priority(br, (u16) val);
+ return 0;
}
static ssize_t store_priority(struct device *d, struct device_attribute *attr,
diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig
index 90947979499..366d3e9d51f 100644
--- a/net/bridge/netfilter/Kconfig
+++ b/net/bridge/netfilter/Kconfig
@@ -2,21 +2,21 @@
# Bridge netfilter configuration
#
-menu "Bridge: Netfilter Configuration"
- depends on BRIDGE && BRIDGE_NETFILTER
-
-config BRIDGE_NF_EBTABLES
+menuconfig BRIDGE_NF_EBTABLES
tristate "Ethernet Bridge tables (ebtables) support"
+ select NETFILTER_XTABLES
help
ebtables is a general, extensible frame/packet identification
framework. Say 'Y' or 'M' here if you want to do Ethernet
filtering/NAT/brouting on the Ethernet bridge.
+
+if BRIDGE_NF_EBTABLES
+
#
# tables
#
config BRIDGE_EBT_BROUTE
tristate "ebt: broute table support"
- depends on BRIDGE_NF_EBTABLES
help
The ebtables broute table is used to define rules that decide between
bridging and routing frames, giving Linux the functionality of a
@@ -27,7 +27,6 @@ config BRIDGE_EBT_BROUTE
config BRIDGE_EBT_T_FILTER
tristate "ebt: filter table support"
- depends on BRIDGE_NF_EBTABLES
help
The ebtables filter table is used to define frame filtering rules at
local input, forwarding and local output. See the man page for
@@ -37,7 +36,6 @@ config BRIDGE_EBT_T_FILTER
config BRIDGE_EBT_T_NAT
tristate "ebt: nat table support"
- depends on BRIDGE_NF_EBTABLES
help
The ebtables nat table is used to define rules that alter the MAC
source address (MAC SNAT) or the MAC destination address (MAC DNAT).
@@ -49,7 +47,6 @@ config BRIDGE_EBT_T_NAT
#
config BRIDGE_EBT_802_3
tristate "ebt: 802.3 filter support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds matching support for 802.3 Ethernet frames.
@@ -57,7 +54,6 @@ config BRIDGE_EBT_802_3
config BRIDGE_EBT_AMONG
tristate "ebt: among filter support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the among match, which allows matching the MAC source
and/or destination address on a list of addresses. Optionally,
@@ -67,7 +63,6 @@ config BRIDGE_EBT_AMONG
config BRIDGE_EBT_ARP
tristate "ebt: ARP filter support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the ARP match, which allows ARP and RARP header field
filtering.
@@ -76,7 +71,6 @@ config BRIDGE_EBT_ARP
config BRIDGE_EBT_IP
tristate "ebt: IP filter support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the IP match, which allows basic IP header field
filtering.
@@ -94,7 +88,6 @@ config BRIDGE_EBT_IP6
config BRIDGE_EBT_LIMIT
tristate "ebt: limit match support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the limit match, which allows you to control
the rate at which a rule can be matched. This match is the
@@ -105,7 +98,6 @@ config BRIDGE_EBT_LIMIT
config BRIDGE_EBT_MARK
tristate "ebt: mark filter support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the mark match, which allows matching frames based on
the 'nfmark' value in the frame. This can be set by the mark target.
@@ -116,7 +108,6 @@ config BRIDGE_EBT_MARK
config BRIDGE_EBT_PKTTYPE
tristate "ebt: packet type filter support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the packet type match, which allows matching on the
type of packet based on its Ethernet "class" (as determined by
@@ -127,7 +118,6 @@ config BRIDGE_EBT_PKTTYPE
config BRIDGE_EBT_STP
tristate "ebt: STP filter support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the Spanning Tree Protocol match, which
allows STP header field filtering.
@@ -136,7 +126,6 @@ config BRIDGE_EBT_STP
config BRIDGE_EBT_VLAN
tristate "ebt: 802.1Q VLAN filter support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the 802.1Q vlan match, which allows the filtering of
802.1Q vlan fields.
@@ -156,7 +145,6 @@ config BRIDGE_EBT_ARPREPLY
config BRIDGE_EBT_DNAT
tristate "ebt: dnat target support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the MAC DNAT target, which allows altering the MAC
destination address of frames.
@@ -165,7 +153,6 @@ config BRIDGE_EBT_DNAT
config BRIDGE_EBT_MARK_T
tristate "ebt: mark target support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the mark target, which allows marking frames by
setting the 'nfmark' value in the frame.
@@ -176,7 +163,6 @@ config BRIDGE_EBT_MARK_T
config BRIDGE_EBT_REDIRECT
tristate "ebt: redirect target support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the MAC redirect target, which allows altering the MAC
destination address of a frame to that of the device it arrived on.
@@ -185,7 +171,6 @@ config BRIDGE_EBT_REDIRECT
config BRIDGE_EBT_SNAT
tristate "ebt: snat target support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the MAC SNAT target, which allows altering the MAC
source address of frames.
@@ -196,7 +181,6 @@ config BRIDGE_EBT_SNAT
#
config BRIDGE_EBT_LOG
tristate "ebt: log support"
- depends on BRIDGE_NF_EBTABLES
help
This option adds the log watcher, that you can use in any rule
in any ebtables table. It records info about the frame header
@@ -206,7 +190,6 @@ config BRIDGE_EBT_LOG
config BRIDGE_EBT_ULOG
tristate "ebt: ulog support (OBSOLETE)"
- depends on BRIDGE_NF_EBTABLES
help
This option enables the old bridge-specific "ebt_ulog" implementation
which has been obsoleted by the new "nfnetlink_log" code (see
@@ -223,7 +206,6 @@ config BRIDGE_EBT_ULOG
config BRIDGE_EBT_NFLOG
tristate "ebt: nflog support"
- depends on BRIDGE_NF_EBTABLES
help
This option enables the nflog watcher, which allows to LOG
messages through the netfilter logging API, which can use
@@ -235,4 +217,4 @@ config BRIDGE_EBT_NFLOG
To compile it as a module, choose M here. If unsure, say N.
-endmenu
+endif # BRIDGE_NF_EBTABLES
diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c
index 98534025360..bd91dc58d49 100644
--- a/net/bridge/netfilter/ebt_802_3.c
+++ b/net/bridge/netfilter/ebt_802_3.c
@@ -7,64 +7,63 @@
* May 2003
*
*/
-
+#include <linux/module.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_802_3.h>
-#include <linux/module.h>
-static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const void *data, unsigned int datalen)
+static bool
+ebt_802_3_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ebt_802_3_info *info = data;
+ const struct ebt_802_3_info *info = par->matchinfo;
const struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb);
__be16 type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;
if (info->bitmask & EBT_802_3_SAP) {
if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP))
- return EBT_NOMATCH;
+ return false;
if (FWINV(info->sap != hdr->llc.ui.dsap, EBT_802_3_SAP))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_802_3_TYPE) {
if (!(hdr->llc.ui.dsap == CHECK_TYPE && hdr->llc.ui.ssap == CHECK_TYPE))
- return EBT_NOMATCH;
+ return false;
if (FWINV(info->type != type, EBT_802_3_TYPE))
- return EBT_NOMATCH;
+ return false;
}
- return EBT_MATCH;
+ return true;
}
-static struct ebt_match filter_802_3;
-static int ebt_802_3_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_802_3_mt_check(const struct xt_mtchk_param *par)
{
- const struct ebt_802_3_info *info = data;
+ const struct ebt_802_3_info *info = par->matchinfo;
- if (datalen < sizeof(struct ebt_802_3_info))
- return -EINVAL;
if (info->bitmask & ~EBT_802_3_MASK || info->invflags & ~EBT_802_3_MASK)
- return -EINVAL;
+ return false;
- return 0;
+ return true;
}
-static struct ebt_match filter_802_3 __read_mostly = {
- .name = EBT_802_3_MATCH,
- .match = ebt_filter_802_3,
- .check = ebt_802_3_check,
+static struct xt_match ebt_802_3_mt_reg __read_mostly = {
+ .name = "802_3",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .match = ebt_802_3_mt,
+ .checkentry = ebt_802_3_mt_check,
+ .matchsize = XT_ALIGN(sizeof(struct ebt_802_3_info)),
.me = THIS_MODULE,
};
static int __init ebt_802_3_init(void)
{
- return ebt_register_match(&filter_802_3);
+ return xt_register_match(&ebt_802_3_mt_reg);
}
static void __exit ebt_802_3_fini(void)
{
- ebt_unregister_match(&filter_802_3);
+ xt_unregister_match(&ebt_802_3_mt_reg);
}
module_init(ebt_802_3_init);
diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c
index 70b6dca5ea7..b595f091f35 100644
--- a/net/bridge/netfilter/ebt_among.c
+++ b/net/bridge/netfilter/ebt_among.c
@@ -7,15 +7,15 @@
* August, 2003
*
*/
-
-#include <linux/netfilter_bridge/ebtables.h>
-#include <linux/netfilter_bridge/ebt_among.h>
#include <linux/ip.h>
#include <linux/if_arp.h>
#include <linux/module.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_among.h>
-static int ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh,
- const char *mac, __be32 ip)
+static bool ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh,
+ const char *mac, __be32 ip)
{
/* You may be puzzled as to how this code works.
* Some tricks were used, refer to
@@ -33,23 +33,19 @@ static int ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh,
if (ip) {
for (i = start; i < limit; i++) {
p = &wh->pool[i];
- if (cmp[1] == p->cmp[1] && cmp[0] == p->cmp[0]) {
- if (p->ip == 0 || p->ip == ip) {
- return 1;
- }
- }
+ if (cmp[1] == p->cmp[1] && cmp[0] == p->cmp[0])
+ if (p->ip == 0 || p->ip == ip)
+ return true;
}
} else {
for (i = start; i < limit; i++) {
p = &wh->pool[i];
- if (cmp[1] == p->cmp[1] && cmp[0] == p->cmp[0]) {
- if (p->ip == 0) {
- return 1;
- }
- }
+ if (cmp[1] == p->cmp[1] && cmp[0] == p->cmp[0])
+ if (p->ip == 0)
+ return true;
}
}
- return 0;
+ return false;
}
static int ebt_mac_wormhash_check_integrity(const struct ebt_mac_wormhash
@@ -131,12 +127,10 @@ static int get_ip_src(const struct sk_buff *skb, __be32 *addr)
return 0;
}
-static int ebt_filter_among(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out, const void *data,
- unsigned int datalen)
+static bool
+ebt_among_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ebt_among_info *info = data;
+ const struct ebt_among_info *info = par->matchinfo;
const char *dmac, *smac;
const struct ebt_mac_wormhash *wh_dst, *wh_src;
__be32 dip = 0, sip = 0;
@@ -147,41 +141,41 @@ static int ebt_filter_among(const struct sk_buff *skb,
if (wh_src) {
smac = eth_hdr(skb)->h_source;
if (get_ip_src(skb, &sip))
- return EBT_NOMATCH;
+ return false;
if (!(info->bitmask & EBT_AMONG_SRC_NEG)) {
/* we match only if it contains */
if (!ebt_mac_wormhash_contains(wh_src, smac, sip))
- return EBT_NOMATCH;
+ return false;
} else {
/* we match only if it DOES NOT contain */
if (ebt_mac_wormhash_contains(wh_src, smac, sip))
- return EBT_NOMATCH;
+ return false;
}
}
if (wh_dst) {
dmac = eth_hdr(skb)->h_dest;
if (get_ip_dst(skb, &dip))
- return EBT_NOMATCH;
+ return false;
if (!(info->bitmask & EBT_AMONG_DST_NEG)) {
/* we match only if it contains */
if (!ebt_mac_wormhash_contains(wh_dst, dmac, dip))
- return EBT_NOMATCH;
+ return false;
} else {
/* we match only if it DOES NOT contain */
if (ebt_mac_wormhash_contains(wh_dst, dmac, dip))
- return EBT_NOMATCH;
+ return false;
}
}
- return EBT_MATCH;
+ return true;
}
-static int ebt_among_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data,
- unsigned int datalen)
+static bool ebt_among_mt_check(const struct xt_mtchk_param *par)
{
- const struct ebt_among_info *info = data;
+ const struct ebt_among_info *info = par->matchinfo;
+ const struct ebt_entry_match *em =
+ container_of(par->matchinfo, const struct ebt_entry_match, data);
int expected_length = sizeof(struct ebt_among_info);
const struct ebt_mac_wormhash *wh_dst, *wh_src;
int err;
@@ -191,42 +185,45 @@ static int ebt_among_check(const char *tablename, unsigned int hookmask,
expected_length += ebt_mac_wormhash_size(wh_dst);
expected_length += ebt_mac_wormhash_size(wh_src);
- if (datalen != EBT_ALIGN(expected_length)) {
+ if (em->match_size != EBT_ALIGN(expected_length)) {
printk(KERN_WARNING
"ebtables: among: wrong size: %d "
"against expected %d, rounded to %Zd\n",
- datalen, expected_length,
+ em->match_size, expected_length,
EBT_ALIGN(expected_length));
- return -EINVAL;
+ return false;
}
if (wh_dst && (err = ebt_mac_wormhash_check_integrity(wh_dst))) {
printk(KERN_WARNING
"ebtables: among: dst integrity fail: %x\n", -err);
- return -EINVAL;
+ return false;
}
if (wh_src && (err = ebt_mac_wormhash_check_integrity(wh_src))) {
printk(KERN_WARNING
"ebtables: among: src integrity fail: %x\n", -err);
- return -EINVAL;
+ return false;
}
- return 0;
+ return true;
}
-static struct ebt_match filter_among __read_mostly = {
- .name = EBT_AMONG_MATCH,
- .match = ebt_filter_among,
- .check = ebt_among_check,
+static struct xt_match ebt_among_mt_reg __read_mostly = {
+ .name = "among",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .match = ebt_among_mt,
+ .checkentry = ebt_among_mt_check,
+ .matchsize = -1, /* special case */
.me = THIS_MODULE,
};
static int __init ebt_among_init(void)
{
- return ebt_register_match(&filter_among);
+ return xt_register_match(&ebt_among_mt_reg);
}
static void __exit ebt_among_fini(void)
{
- ebt_unregister_match(&filter_among);
+ xt_unregister_match(&ebt_among_mt_reg);
}
module_init(ebt_among_init);
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
index 7c535be7566..b7ad60419f9 100644
--- a/net/bridge/netfilter/ebt_arp.c
+++ b/net/bridge/netfilter/ebt_arp.c
@@ -8,58 +8,58 @@
* April, 2002
*
*/
-
-#include <linux/netfilter_bridge/ebtables.h>
-#include <linux/netfilter_bridge/ebt_arp.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/module.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_arp.h>
-static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const void *data, unsigned int datalen)
+static bool
+ebt_arp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ebt_arp_info *info = data;
+ const struct ebt_arp_info *info = par->matchinfo;
const struct arphdr *ah;
struct arphdr _arph;
ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
if (ah == NULL)
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode !=
ah->ar_op, EBT_ARP_OPCODE))
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype !=
ah->ar_hrd, EBT_ARP_HTYPE))
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype !=
ah->ar_pro, EBT_ARP_PTYPE))
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_GRAT)) {
const __be32 *sap, *dap;
__be32 saddr, daddr;
if (ah->ar_pln != sizeof(__be32) || ah->ar_pro != htons(ETH_P_IP))
- return EBT_NOMATCH;
+ return false;
sap = skb_header_pointer(skb, sizeof(struct arphdr) +
ah->ar_hln, sizeof(saddr),
&saddr);
if (sap == NULL)
- return EBT_NOMATCH;
+ return false;
dap = skb_header_pointer(skb, sizeof(struct arphdr) +
2*ah->ar_hln+sizeof(saddr),
sizeof(daddr), &daddr);
if (dap == NULL)
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_ARP_SRC_IP &&
FWINV(info->saddr != (*sap & info->smsk), EBT_ARP_SRC_IP))
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_ARP_DST_IP &&
FWINV(info->daddr != (*dap & info->dmsk), EBT_ARP_DST_IP))
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_ARP_GRAT &&
FWINV(*dap != *sap, EBT_ARP_GRAT))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) {
@@ -68,18 +68,18 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
uint8_t verdict, i;
if (ah->ar_hln != ETH_ALEN || ah->ar_hrd != htons(ARPHRD_ETHER))
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_ARP_SRC_MAC) {
mp = skb_header_pointer(skb, sizeof(struct arphdr),
sizeof(_mac), &_mac);
if (mp == NULL)
- return EBT_NOMATCH;
+ return false;
verdict = 0;
for (i = 0; i < 6; i++)
verdict |= (mp[i] ^ info->smaddr[i]) &
info->smmsk[i];
if (FWINV(verdict != 0, EBT_ARP_SRC_MAC))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_ARP_DST_MAC) {
@@ -87,50 +87,51 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
ah->ar_hln + ah->ar_pln,
sizeof(_mac), &_mac);
if (mp == NULL)
- return EBT_NOMATCH;
+ return false;
verdict = 0;
for (i = 0; i < 6; i++)
verdict |= (mp[i] ^ info->dmaddr[i]) &
info->dmmsk[i];
if (FWINV(verdict != 0, EBT_ARP_DST_MAC))
- return EBT_NOMATCH;
+ return false;
}
}
- return EBT_MATCH;
+ return true;
}
-static int ebt_arp_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_arp_mt_check(const struct xt_mtchk_param *par)
{
- const struct ebt_arp_info *info = data;
+ const struct ebt_arp_info *info = par->matchinfo;
+ const struct ebt_entry *e = par->entryinfo;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_arp_info)))
- return -EINVAL;
if ((e->ethproto != htons(ETH_P_ARP) &&
e->ethproto != htons(ETH_P_RARP)) ||
e->invflags & EBT_IPROTO)
- return -EINVAL;
+ return false;
if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK)
- return -EINVAL;
- return 0;
+ return false;
+ return true;
}
-static struct ebt_match filter_arp __read_mostly = {
- .name = EBT_ARP_MATCH,
- .match = ebt_filter_arp,
- .check = ebt_arp_check,
+static struct xt_match ebt_arp_mt_reg __read_mostly = {
+ .name = "arp",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .match = ebt_arp_mt,
+ .checkentry = ebt_arp_mt_check,
+ .matchsize = XT_ALIGN(sizeof(struct ebt_arp_info)),
.me = THIS_MODULE,
};
static int __init ebt_arp_init(void)
{
- return ebt_register_match(&filter_arp);
+ return xt_register_match(&ebt_arp_mt_reg);
}
static void __exit ebt_arp_fini(void)
{
- ebt_unregister_match(&filter_arp);
+ xt_unregister_match(&ebt_arp_mt_reg);
}
module_init(ebt_arp_init);
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index 0c4279590fc..76584cd72e5 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -8,18 +8,17 @@
* August, 2003
*
*/
-
-#include <linux/netfilter_bridge/ebtables.h>
-#include <linux/netfilter_bridge/ebt_arpreply.h>
#include <linux/if_arp.h>
#include <net/arp.h>
#include <linux/module.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_arpreply.h>
-static int ebt_target_reply(struct sk_buff *skb, unsigned int hooknr,
- const struct net_device *in, const struct net_device *out,
- const void *data, unsigned int datalen)
+static unsigned int
+ebt_arpreply_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- struct ebt_arpreply_info *info = (void *)data;
+ const struct ebt_arpreply_info *info = par->targinfo;
const __be32 *siptr, *diptr;
__be32 _sip, _dip;
const struct arphdr *ap;
@@ -52,45 +51,45 @@ static int ebt_target_reply(struct sk_buff *skb, unsigned int hooknr,
if (diptr == NULL)
return EBT_DROP;
- arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)in,
+ arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)par->in,
*diptr, shp, info->mac, shp);
return info->target;
}
-static int ebt_target_reply_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_arpreply_tg_check(const struct xt_tgchk_param *par)
{
- const struct ebt_arpreply_info *info = data;
+ const struct ebt_arpreply_info *info = par->targinfo;
+ const struct ebt_entry *e = par->entryinfo;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_arpreply_info)))
- return -EINVAL;
if (BASE_CHAIN && info->target == EBT_RETURN)
- return -EINVAL;
+ return false;
if (e->ethproto != htons(ETH_P_ARP) ||
e->invflags & EBT_IPROTO)
- return -EINVAL;
- CLEAR_BASE_CHAIN_BIT;
- if (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING))
- return -EINVAL;
- return 0;
+ return false;
+ return true;
}
-static struct ebt_target reply_target __read_mostly = {
- .name = EBT_ARPREPLY_TARGET,
- .target = ebt_target_reply,
- .check = ebt_target_reply_check,
+static struct xt_target ebt_arpreply_tg_reg __read_mostly = {
+ .name = "arpreply",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .table = "nat",
+ .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING),
+ .target = ebt_arpreply_tg,
+ .checkentry = ebt_arpreply_tg_check,
+ .targetsize = XT_ALIGN(sizeof(struct ebt_arpreply_info)),
.me = THIS_MODULE,
};
static int __init ebt_arpreply_init(void)
{
- return ebt_register_target(&reply_target);
+ return xt_register_target(&ebt_arpreply_tg_reg);
}
static void __exit ebt_arpreply_fini(void)
{
- ebt_unregister_target(&reply_target);
+ xt_unregister_target(&ebt_arpreply_tg_reg);
}
module_init(ebt_arpreply_init);
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
index ca64c1cc1b4..6b49ea9e31f 100644
--- a/net/bridge/netfilter/ebt_dnat.c
+++ b/net/bridge/netfilter/ebt_dnat.c
@@ -7,18 +7,17 @@
* June, 2002
*
*/
-
+#include <linux/module.h>
+#include <net/sock.h>
#include <linux/netfilter.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_nat.h>
-#include <linux/module.h>
-#include <net/sock.h>
-static int ebt_target_dnat(struct sk_buff *skb, unsigned int hooknr,
- const struct net_device *in, const struct net_device *out,
- const void *data, unsigned int datalen)
+static unsigned int
+ebt_dnat_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct ebt_nat_info *info = data;
+ const struct ebt_nat_info *info = par->targinfo;
if (!skb_make_writable(skb, 0))
return EBT_DROP;
@@ -27,40 +26,46 @@ static int ebt_target_dnat(struct sk_buff *skb, unsigned int hooknr,
return info->target;
}
-static int ebt_target_dnat_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_dnat_tg_check(const struct xt_tgchk_param *par)
{
- const struct ebt_nat_info *info = data;
+ const struct ebt_nat_info *info = par->targinfo;
+ unsigned int hook_mask;
if (BASE_CHAIN && info->target == EBT_RETURN)
- return -EINVAL;
- CLEAR_BASE_CHAIN_BIT;
- if ( (strcmp(tablename, "nat") ||
- (hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))) &&
- (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) )
- return -EINVAL;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
- return -EINVAL;
+ return false;
+
+ hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS);
+ if ((strcmp(par->table, "nat") != 0 ||
+ (hook_mask & ~((1 << NF_BR_PRE_ROUTING) |
+ (1 << NF_BR_LOCAL_OUT)))) &&
+ (strcmp(par->table, "broute") != 0 ||
+ hook_mask & ~(1 << NF_BR_BROUTING)))
+ return false;
if (INVALID_TARGET)
- return -EINVAL;
- return 0;
+ return false;
+ return true;
}
-static struct ebt_target dnat __read_mostly = {
- .name = EBT_DNAT_TARGET,
- .target = ebt_target_dnat,
- .check = ebt_target_dnat_check,
+static struct xt_target ebt_dnat_tg_reg __read_mostly = {
+ .name = "dnat",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING) |
+ (1 << NF_BR_LOCAL_OUT) | (1 << NF_BR_BROUTING),
+ .target = ebt_dnat_tg,
+ .checkentry = ebt_dnat_tg_check,
+ .targetsize = XT_ALIGN(sizeof(struct ebt_nat_info)),
.me = THIS_MODULE,
};
static int __init ebt_dnat_init(void)
{
- return ebt_register_target(&dnat);
+ return xt_register_target(&ebt_dnat_tg_reg);
}
static void __exit ebt_dnat_fini(void)
{
- ebt_unregister_target(&dnat);
+ xt_unregister_target(&ebt_dnat_tg_reg);
}
module_init(ebt_dnat_init);
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
index 65caa00dcf2..d771bbfbcbe 100644
--- a/net/bridge/netfilter/ebt_ip.c
+++ b/net/bridge/netfilter/ebt_ip.c
@@ -11,24 +11,23 @@
* Innominate Security Technologies AG <mhopf@innominate.com>
* September, 2002
*/
-
-#include <linux/netfilter_bridge/ebtables.h>
-#include <linux/netfilter_bridge/ebt_ip.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <linux/in.h>
#include <linux/module.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_ip.h>
struct tcpudphdr {
__be16 src;
__be16 dst;
};
-static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const void *data,
- unsigned int datalen)
+static bool
+ebt_ip_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ebt_ip_info *info = data;
+ const struct ebt_ip_info *info = par->matchinfo;
const struct iphdr *ih;
struct iphdr _iph;
const struct tcpudphdr *pptr;
@@ -36,92 +35,93 @@ static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
if (ih == NULL)
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_IP_TOS &&
FWINV(info->tos != ih->tos, EBT_IP_TOS))
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_IP_SOURCE &&
FWINV((ih->saddr & info->smsk) !=
info->saddr, EBT_IP_SOURCE))
- return EBT_NOMATCH;
+ return false;
if ((info->bitmask & EBT_IP_DEST) &&
FWINV((ih->daddr & info->dmsk) !=
info->daddr, EBT_IP_DEST))
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_IP_PROTO) {
if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO))
- return EBT_NOMATCH;
+ return false;
if (!(info->bitmask & EBT_IP_DPORT) &&
!(info->bitmask & EBT_IP_SPORT))
- return EBT_MATCH;
+ return true;
if (ntohs(ih->frag_off) & IP_OFFSET)
- return EBT_NOMATCH;
+ return false;
pptr = skb_header_pointer(skb, ih->ihl*4,
sizeof(_ports), &_ports);
if (pptr == NULL)
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_IP_DPORT) {
u32 dst = ntohs(pptr->dst);
if (FWINV(dst < info->dport[0] ||
dst > info->dport[1],
EBT_IP_DPORT))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_IP_SPORT) {
u32 src = ntohs(pptr->src);
if (FWINV(src < info->sport[0] ||
src > info->sport[1],
EBT_IP_SPORT))
- return EBT_NOMATCH;
+ return false;
}
}
- return EBT_MATCH;
+ return true;
}
-static int ebt_ip_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_ip_mt_check(const struct xt_mtchk_param *par)
{
- const struct ebt_ip_info *info = data;
+ const struct ebt_ip_info *info = par->matchinfo;
+ const struct ebt_entry *e = par->entryinfo;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_ip_info)))
- return -EINVAL;
if (e->ethproto != htons(ETH_P_IP) ||
e->invflags & EBT_IPROTO)
- return -EINVAL;
+ return false;
if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
- return -EINVAL;
+ return false;
if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) {
if (info->invflags & EBT_IP_PROTO)
- return -EINVAL;
+ return false;
if (info->protocol != IPPROTO_TCP &&
info->protocol != IPPROTO_UDP &&
info->protocol != IPPROTO_UDPLITE &&
info->protocol != IPPROTO_SCTP &&
info->protocol != IPPROTO_DCCP)
- return -EINVAL;
+ return false;
}
if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1])
- return -EINVAL;
+ return false;
if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1])
- return -EINVAL;
- return 0;
+ return false;
+ return true;
}
-static struct ebt_match filter_ip __read_mostly = {
- .name = EBT_IP_MATCH,
- .match = ebt_filter_ip,
- .check = ebt_ip_check,
+static struct xt_match ebt_ip_mt_reg __read_mostly = {
+ .name = "ip",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .match = ebt_ip_mt,
+ .checkentry = ebt_ip_mt_check,
+ .matchsize = XT_ALIGN(sizeof(struct ebt_ip_info)),
.me = THIS_MODULE,
};
static int __init ebt_ip_init(void)
{
- return ebt_register_match(&filter_ip);
+ return xt_register_match(&ebt_ip_mt_reg);
}
static void __exit ebt_ip_fini(void)
{
- ebt_unregister_match(&filter_ip);
+ xt_unregister_match(&ebt_ip_mt_reg);
}
module_init(ebt_ip_init);
diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c
index 36efb3a7524..784a6573876 100644
--- a/net/bridge/netfilter/ebt_ip6.c
+++ b/net/bridge/netfilter/ebt_ip6.c
@@ -13,26 +13,24 @@
*
* Jan, 2008
*/
-
-#include <linux/netfilter_bridge/ebtables.h>
-#include <linux/netfilter_bridge/ebt_ip6.h>
#include <linux/ipv6.h>
#include <net/ipv6.h>
#include <linux/in.h>
#include <linux/module.h>
#include <net/dsfield.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_ip6.h>
struct tcpudphdr {
__be16 src;
__be16 dst;
};
-static int ebt_filter_ip6(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out, const void *data,
- unsigned int datalen)
+static bool
+ebt_ip6_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ebt_ip6_info *info = (struct ebt_ip6_info *)data;
+ const struct ebt_ip6_info *info = par->matchinfo;
const struct ipv6hdr *ih6;
struct ipv6hdr _ip6h;
const struct tcpudphdr *pptr;
@@ -42,100 +40,100 @@ static int ebt_filter_ip6(const struct sk_buff *skb,
ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h);
if (ih6 == NULL)
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_IP6_TCLASS &&
FWINV(info->tclass != ipv6_get_dsfield(ih6), EBT_IP6_TCLASS))
- return EBT_NOMATCH;
+ return false;
for (i = 0; i < 4; i++)
tmp_addr.in6_u.u6_addr32[i] = ih6->saddr.in6_u.u6_addr32[i] &
info->smsk.in6_u.u6_addr32[i];
if (info->bitmask & EBT_IP6_SOURCE &&
FWINV((ipv6_addr_cmp(&tmp_addr, &info->saddr) != 0),
EBT_IP6_SOURCE))
- return EBT_NOMATCH;
+ return false;
for (i = 0; i < 4; i++)
tmp_addr.in6_u.u6_addr32[i] = ih6->daddr.in6_u.u6_addr32[i] &
info->dmsk.in6_u.u6_addr32[i];
if (info->bitmask & EBT_IP6_DEST &&
FWINV((ipv6_addr_cmp(&tmp_addr, &info->daddr) != 0), EBT_IP6_DEST))
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_IP6_PROTO) {
uint8_t nexthdr = ih6->nexthdr;
int offset_ph;
offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr);
if (offset_ph == -1)
- return EBT_NOMATCH;
+ return false;
if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO))
- return EBT_NOMATCH;
+ return false;
if (!(info->bitmask & EBT_IP6_DPORT) &&
!(info->bitmask & EBT_IP6_SPORT))
- return EBT_MATCH;
+ return true;
pptr = skb_header_pointer(skb, offset_ph, sizeof(_ports),
&_ports);
if (pptr == NULL)
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_IP6_DPORT) {
u32 dst = ntohs(pptr->dst);
if (FWINV(dst < info->dport[0] ||
dst > info->dport[1], EBT_IP6_DPORT))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_IP6_SPORT) {
u32 src = ntohs(pptr->src);
if (FWINV(src < info->sport[0] ||
src > info->sport[1], EBT_IP6_SPORT))
- return EBT_NOMATCH;
+ return false;
}
- return EBT_MATCH;
+ return true;
}
- return EBT_MATCH;
+ return true;
}
-static int ebt_ip6_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_ip6_mt_check(const struct xt_mtchk_param *par)
{
- struct ebt_ip6_info *info = (struct ebt_ip6_info *)data;
+ const struct ebt_entry *e = par->entryinfo;
+ struct ebt_ip6_info *info = par->matchinfo;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_ip6_info)))
- return -EINVAL;
if (e->ethproto != htons(ETH_P_IPV6) || e->invflags & EBT_IPROTO)
- return -EINVAL;
+ return false;
if (info->bitmask & ~EBT_IP6_MASK || info->invflags & ~EBT_IP6_MASK)
- return -EINVAL;
+ return false;
if (info->bitmask & (EBT_IP6_DPORT | EBT_IP6_SPORT)) {
if (info->invflags & EBT_IP6_PROTO)
- return -EINVAL;
+ return false;
if (info->protocol != IPPROTO_TCP &&
info->protocol != IPPROTO_UDP &&
info->protocol != IPPROTO_UDPLITE &&
info->protocol != IPPROTO_SCTP &&
info->protocol != IPPROTO_DCCP)
- return -EINVAL;
+ return false;
}
if (info->bitmask & EBT_IP6_DPORT && info->dport[0] > info->dport[1])
- return -EINVAL;
+ return false;
if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1])
- return -EINVAL;
- return 0;
+ return false;
+ return true;
}
-static struct ebt_match filter_ip6 =
-{
- .name = EBT_IP6_MATCH,
- .match = ebt_filter_ip6,
- .check = ebt_ip6_check,
+static struct xt_match ebt_ip6_mt_reg __read_mostly = {
+ .name = "ip6",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .match = ebt_ip6_mt,
+ .checkentry = ebt_ip6_mt_check,
+ .matchsize = XT_ALIGN(sizeof(struct ebt_ip6_info)),
.me = THIS_MODULE,
};
static int __init ebt_ip6_init(void)
{
- return ebt_register_match(&filter_ip6);
+ return xt_register_match(&ebt_ip6_mt_reg);
}
static void __exit ebt_ip6_fini(void)
{
- ebt_unregister_match(&filter_ip6);
+ xt_unregister_match(&ebt_ip6_mt_reg);
}
module_init(ebt_ip6_init);
diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c
index 8cbdc01c253..f7bd9192ff0 100644
--- a/net/bridge/netfilter/ebt_limit.c
+++ b/net/bridge/netfilter/ebt_limit.c
@@ -10,13 +10,12 @@
* September, 2003
*
*/
-
-#include <linux/netfilter_bridge/ebtables.h>
-#include <linux/netfilter_bridge/ebt_limit.h>
#include <linux/module.h>
-
#include <linux/netdevice.h>
#include <linux/spinlock.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_limit.h>
static DEFINE_SPINLOCK(limit_lock);
@@ -31,11 +30,10 @@ static DEFINE_SPINLOCK(limit_lock);
#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
-static int ebt_limit_match(const struct sk_buff *skb,
- const struct net_device *in, const struct net_device *out,
- const void *data, unsigned int datalen)
+static bool
+ebt_limit_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- struct ebt_limit_info *info = (struct ebt_limit_info *)data;
+ struct ebt_limit_info *info = (void *)par->matchinfo;
unsigned long now = jiffies;
spin_lock_bh(&limit_lock);
@@ -47,11 +45,11 @@ static int ebt_limit_match(const struct sk_buff *skb,
/* We're not limited. */
info->credit -= info->cost;
spin_unlock_bh(&limit_lock);
- return EBT_MATCH;
+ return true;
}
spin_unlock_bh(&limit_lock);
- return EBT_NOMATCH;
+ return false;
}
/* Precision saver. */
@@ -66,20 +64,16 @@ user2credits(u_int32_t user)
return (user * HZ * CREDITS_PER_JIFFY) / EBT_LIMIT_SCALE;
}
-static int ebt_limit_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_limit_mt_check(const struct xt_mtchk_param *par)
{
- struct ebt_limit_info *info = data;
-
- if (datalen != EBT_ALIGN(sizeof(struct ebt_limit_info)))
- return -EINVAL;
+ struct ebt_limit_info *info = par->matchinfo;
/* Check for overflow. */
if (info->burst == 0 ||
user2credits(info->avg * info->burst) < user2credits(info->avg)) {
printk("Overflow in ebt_limit, try lower: %u/%u\n",
info->avg, info->burst);
- return -EINVAL;
+ return false;
}
/* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */
@@ -87,24 +81,27 @@ static int ebt_limit_check(const char *tablename, unsigned int hookmask,
info->credit = user2credits(info->avg * info->burst);
info->credit_cap = user2credits(info->avg * info->burst);
info->cost = user2credits(info->avg);
- return 0;
+ return true;
}
-static struct ebt_match ebt_limit_reg __read_mostly = {
- .name = EBT_LIMIT_MATCH,
- .match = ebt_limit_match,
- .check = ebt_limit_check,
+static struct xt_match ebt_limit_mt_reg __read_mostly = {
+ .name = "limit",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .match = ebt_limit_mt,
+ .checkentry = ebt_limit_mt_check,
+ .matchsize = XT_ALIGN(sizeof(struct ebt_limit_info)),
.me = THIS_MODULE,
};
static int __init ebt_limit_init(void)
{
- return ebt_register_match(&ebt_limit_reg);
+ return xt_register_match(&ebt_limit_mt_reg);
}
static void __exit ebt_limit_fini(void)
{
- ebt_unregister_match(&ebt_limit_reg);
+ xt_unregister_match(&ebt_limit_mt_reg);
}
module_init(ebt_limit_init);
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 2f430d4ae91..3d33c608906 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -8,10 +8,6 @@
* April, 2002
*
*/
-
-#include <linux/netfilter_bridge/ebtables.h>
-#include <linux/netfilter_bridge/ebt_log.h>
-#include <linux/netfilter.h>
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/in.h>
@@ -21,22 +17,23 @@
#include <linux/ipv6.h>
#include <net/ipv6.h>
#include <linux/in6.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_log.h>
+#include <linux/netfilter.h>
static DEFINE_SPINLOCK(ebt_log_lock);
-static int ebt_log_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_log_tg_check(const struct xt_tgchk_param *par)
{
- struct ebt_log_info *info = data;
+ struct ebt_log_info *info = par->targinfo;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_log_info)))
- return -EINVAL;
if (info->bitmask & ~EBT_LOG_MASK)
- return -EINVAL;
+ return false;
if (info->loglevel >= 8)
- return -EINVAL;
+ return false;
info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0';
- return 0;
+ return true;
}
struct tcpudphdr
@@ -84,7 +81,7 @@ print_ports(const struct sk_buff *skb, uint8_t protocol, int offset)
#define myNIPQUAD(a) a[0], a[1], a[2], a[3]
static void
-ebt_log_packet(unsigned int pf, unsigned int hooknum,
+ebt_log_packet(u_int8_t pf, unsigned int hooknum,
const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct nf_loginfo *loginfo,
const char *prefix)
@@ -194,11 +191,10 @@ out:
}
-static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
- const struct net_device *in, const struct net_device *out,
- const void *data, unsigned int datalen)
+static unsigned int
+ebt_log_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct ebt_log_info *info = data;
+ const struct ebt_log_info *info = par->targinfo;
struct nf_loginfo li;
li.type = NF_LOG_TYPE_LOG;
@@ -206,18 +202,21 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
li.u.log.logflags = info->bitmask;
if (info->bitmask & EBT_LOG_NFLOG)
- nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
- "%s", info->prefix);
+ nf_log_packet(NFPROTO_BRIDGE, par->hooknum, skb, par->in,
+ par->out, &li, "%s", info->prefix);
else
- ebt_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
- info->prefix);
+ ebt_log_packet(NFPROTO_BRIDGE, par->hooknum, skb, par->in,
+ par->out, &li, info->prefix);
+ return EBT_CONTINUE;
}
-static struct ebt_watcher log =
-{
- .name = EBT_LOG_WATCHER,
- .watcher = ebt_log,
- .check = ebt_log_check,
+static struct xt_target ebt_log_tg_reg __read_mostly = {
+ .name = "log",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .target = ebt_log_tg,
+ .checkentry = ebt_log_tg_check,
+ .targetsize = XT_ALIGN(sizeof(struct ebt_log_info)),
.me = THIS_MODULE,
};
@@ -231,17 +230,17 @@ static int __init ebt_log_init(void)
{
int ret;
- ret = ebt_register_watcher(&log);
+ ret = xt_register_target(&ebt_log_tg_reg);
if (ret < 0)
return ret;
- nf_log_register(PF_BRIDGE, &ebt_log_logger);
+ nf_log_register(NFPROTO_BRIDGE, &ebt_log_logger);
return 0;
}
static void __exit ebt_log_fini(void)
{
nf_log_unregister(&ebt_log_logger);
- ebt_unregister_watcher(&log);
+ xt_unregister_target(&ebt_log_tg_reg);
}
module_init(ebt_log_init);
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index 36723f47db0..2fee7e8e2e9 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -13,15 +13,15 @@
* Marking a frame doesn't really change anything in the frame anyway.
*/
+#include <linux/module.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_mark_t.h>
-#include <linux/module.h>
-static int ebt_target_mark(struct sk_buff *skb, unsigned int hooknr,
- const struct net_device *in, const struct net_device *out,
- const void *data, unsigned int datalen)
+static unsigned int
+ebt_mark_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct ebt_mark_t_info *info = data;
+ const struct ebt_mark_t_info *info = par->targinfo;
int action = info->target & -16;
if (action == MARK_SET_VALUE)
@@ -36,42 +36,41 @@ static int ebt_target_mark(struct sk_buff *skb, unsigned int hooknr,
return info->target | ~EBT_VERDICT_BITS;
}
-static int ebt_target_mark_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_mark_tg_check(const struct xt_tgchk_param *par)
{
- const struct ebt_mark_t_info *info = data;
+ const struct ebt_mark_t_info *info = par->targinfo;
int tmp;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info)))
- return -EINVAL;
tmp = info->target | ~EBT_VERDICT_BITS;
if (BASE_CHAIN && tmp == EBT_RETURN)
- return -EINVAL;
- CLEAR_BASE_CHAIN_BIT;
+ return false;
if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
- return -EINVAL;
+ return false;
tmp = info->target & ~EBT_VERDICT_BITS;
if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE)
- return -EINVAL;
- return 0;
+ return false;
+ return true;
}
-static struct ebt_target mark_target __read_mostly = {
- .name = EBT_MARK_TARGET,
- .target = ebt_target_mark,
- .check = ebt_target_mark_check,
+static struct xt_target ebt_mark_tg_reg __read_mostly = {
+ .name = "mark",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .target = ebt_mark_tg,
+ .checkentry = ebt_mark_tg_check,
+ .targetsize = XT_ALIGN(sizeof(struct ebt_mark_t_info)),
.me = THIS_MODULE,
};
static int __init ebt_mark_init(void)
{
- return ebt_register_target(&mark_target);
+ return xt_register_target(&ebt_mark_tg_reg);
}
static void __exit ebt_mark_fini(void)
{
- ebt_unregister_target(&mark_target);
+ xt_unregister_target(&ebt_mark_tg_reg);
}
module_init(ebt_mark_init);
diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c
index 9b0a4543861..ea570f214b1 100644
--- a/net/bridge/netfilter/ebt_mark_m.c
+++ b/net/bridge/netfilter/ebt_mark_m.c
@@ -7,53 +7,52 @@
* July, 2002
*
*/
-
+#include <linux/module.h>
+#include <linux/netfilter/x_tables.h>
#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)
+static bool
+ebt_mark_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ebt_mark_m_info *info = data;
+ const struct ebt_mark_m_info *info = par->matchinfo;
if (info->bitmask & EBT_MARK_OR)
- return !(!!(skb->mark & info->mask) ^ info->invert);
- return !(((skb->mark & info->mask) == info->mark) ^ info->invert);
+ return !!(skb->mark & info->mask) ^ info->invert;
+ return ((skb->mark & 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)
+static bool ebt_mark_mt_check(const struct xt_mtchk_param *par)
{
- const struct ebt_mark_m_info *info = data;
+ const struct ebt_mark_m_info *info = par->matchinfo;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_m_info)))
- return -EINVAL;
if (info->bitmask & ~EBT_MARK_MASK)
- return -EINVAL;
+ return false;
if ((info->bitmask & EBT_MARK_OR) && (info->bitmask & EBT_MARK_AND))
- return -EINVAL;
+ return false;
if (!info->bitmask)
- return -EINVAL;
- return 0;
+ return false;
+ return true;
}
-static struct ebt_match filter_mark __read_mostly = {
- .name = EBT_MARK_MATCH,
- .match = ebt_filter_mark,
- .check = ebt_mark_check,
+static struct xt_match ebt_mark_mt_reg __read_mostly = {
+ .name = "mark_m",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .match = ebt_mark_mt,
+ .checkentry = ebt_mark_mt_check,
+ .matchsize = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
.me = THIS_MODULE,
};
static int __init ebt_mark_m_init(void)
{
- return ebt_register_match(&filter_mark);
+ return xt_register_match(&ebt_mark_mt_reg);
}
static void __exit ebt_mark_m_fini(void)
{
- ebt_unregister_match(&filter_mark);
+ xt_unregister_match(&ebt_mark_mt_reg);
}
module_init(ebt_mark_m_init);
diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c
index 8e799aa9e56..2a63d996dd4 100644
--- a/net/bridge/netfilter/ebt_nflog.c
+++ b/net/bridge/netfilter/ebt_nflog.c
@@ -14,17 +14,15 @@
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_nflog.h>
#include <net/netfilter/nf_log.h>
-static void ebt_nflog(const struct sk_buff *skb,
- unsigned int hooknr,
- const struct net_device *in,
- const struct net_device *out,
- const void *data, unsigned int datalen)
+static unsigned int
+ebt_nflog_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- struct ebt_nflog_info *info = (struct ebt_nflog_info *)data;
+ const struct ebt_nflog_info *info = par->targinfo;
struct nf_loginfo li;
li.type = NF_LOG_TYPE_ULOG;
@@ -32,39 +30,39 @@ static void ebt_nflog(const struct sk_buff *skb,
li.u.ulog.group = info->group;
li.u.ulog.qthreshold = info->threshold;
- nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, "%s", info->prefix);
+ nf_log_packet(PF_BRIDGE, par->hooknum, skb, par->in, par->out,
+ &li, "%s", info->prefix);
+ return EBT_CONTINUE;
}
-static int ebt_nflog_check(const char *tablename,
- unsigned int hookmask,
- const struct ebt_entry *e,
- void *data, unsigned int datalen)
+static bool ebt_nflog_tg_check(const struct xt_tgchk_param *par)
{
- struct ebt_nflog_info *info = (struct ebt_nflog_info *)data;
+ struct ebt_nflog_info *info = par->targinfo;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_nflog_info)))
- return -EINVAL;
if (info->flags & ~EBT_NFLOG_MASK)
- return -EINVAL;
+ return false;
info->prefix[EBT_NFLOG_PREFIX_SIZE - 1] = '\0';
- return 0;
+ return true;
}
-static struct ebt_watcher nflog __read_mostly = {
- .name = EBT_NFLOG_WATCHER,
- .watcher = ebt_nflog,
- .check = ebt_nflog_check,
- .me = THIS_MODULE,
+static struct xt_target ebt_nflog_tg_reg __read_mostly = {
+ .name = "nflog",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .target = ebt_nflog_tg,
+ .checkentry = ebt_nflog_tg_check,
+ .targetsize = XT_ALIGN(sizeof(struct ebt_nflog_info)),
+ .me = THIS_MODULE,
};
static int __init ebt_nflog_init(void)
{
- return ebt_register_watcher(&nflog);
+ return xt_register_target(&ebt_nflog_tg_reg);
}
static void __exit ebt_nflog_fini(void)
{
- ebt_unregister_watcher(&nflog);
+ xt_unregister_target(&ebt_nflog_tg_reg);
}
module_init(ebt_nflog_init);
diff --git a/net/bridge/netfilter/ebt_pkttype.c b/net/bridge/netfilter/ebt_pkttype.c
index 676db32df3d..883e96e2a54 100644
--- a/net/bridge/netfilter/ebt_pkttype.c
+++ b/net/bridge/netfilter/ebt_pkttype.c
@@ -7,50 +7,47 @@
* April, 2003
*
*/
-
+#include <linux/module.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_pkttype.h>
-#include <linux/module.h>
-static int ebt_filter_pkttype(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *data,
- unsigned int datalen)
+static bool
+ebt_pkttype_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ebt_pkttype_info *info = data;
+ const struct ebt_pkttype_info *info = par->matchinfo;
- return (skb->pkt_type != info->pkt_type) ^ info->invert;
+ return (skb->pkt_type == info->pkt_type) ^ info->invert;
}
-static int ebt_pkttype_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_pkttype_mt_check(const struct xt_mtchk_param *par)
{
- const struct ebt_pkttype_info *info = data;
+ const struct ebt_pkttype_info *info = par->matchinfo;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_pkttype_info)))
- return -EINVAL;
if (info->invert != 0 && info->invert != 1)
- return -EINVAL;
+ return false;
/* Allow any pkt_type value */
- return 0;
+ return true;
}
-static struct ebt_match filter_pkttype __read_mostly = {
- .name = EBT_PKTTYPE_MATCH,
- .match = ebt_filter_pkttype,
- .check = ebt_pkttype_check,
+static struct xt_match ebt_pkttype_mt_reg __read_mostly = {
+ .name = "pkttype",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .match = ebt_pkttype_mt,
+ .checkentry = ebt_pkttype_mt_check,
+ .matchsize = XT_ALIGN(sizeof(struct ebt_pkttype_info)),
.me = THIS_MODULE,
};
static int __init ebt_pkttype_init(void)
{
- return ebt_register_match(&filter_pkttype);
+ return xt_register_match(&ebt_pkttype_mt_reg);
}
static void __exit ebt_pkttype_fini(void)
{
- ebt_unregister_match(&filter_pkttype);
+ xt_unregister_match(&ebt_pkttype_mt_reg);
}
module_init(ebt_pkttype_init);
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index b8afe850cf1..c8a49f7a57b 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -7,65 +7,70 @@
* April, 2002
*
*/
-
-#include <linux/netfilter.h>
-#include <linux/netfilter_bridge/ebtables.h>
-#include <linux/netfilter_bridge/ebt_redirect.h>
#include <linux/module.h>
#include <net/sock.h>
#include "../br_private.h"
+#include <linux/netfilter.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_redirect.h>
-static int ebt_target_redirect(struct sk_buff *skb, unsigned int hooknr,
- const struct net_device *in, const struct net_device *out,
- const void *data, unsigned int datalen)
+static unsigned int
+ebt_redirect_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct ebt_redirect_info *info = data;
+ const struct ebt_redirect_info *info = par->targinfo;
if (!skb_make_writable(skb, 0))
return EBT_DROP;
- if (hooknr != NF_BR_BROUTING)
+ if (par->hooknum != NF_BR_BROUTING)
memcpy(eth_hdr(skb)->h_dest,
- in->br_port->br->dev->dev_addr, ETH_ALEN);
+ par->in->br_port->br->dev->dev_addr, ETH_ALEN);
else
- memcpy(eth_hdr(skb)->h_dest, in->dev_addr, ETH_ALEN);
+ memcpy(eth_hdr(skb)->h_dest, par->in->dev_addr, ETH_ALEN);
skb->pkt_type = PACKET_HOST;
return info->target;
}
-static int ebt_target_redirect_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_redirect_tg_check(const struct xt_tgchk_param *par)
{
- const struct ebt_redirect_info *info = data;
+ const struct ebt_redirect_info *info = par->targinfo;
+ unsigned int hook_mask;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_redirect_info)))
- return -EINVAL;
if (BASE_CHAIN && info->target == EBT_RETURN)
- return -EINVAL;
- CLEAR_BASE_CHAIN_BIT;
- if ( (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING)) &&
- (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) )
- return -EINVAL;
+ return false;
+
+ hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS);
+ if ((strcmp(par->table, "nat") != 0 ||
+ hook_mask & ~(1 << NF_BR_PRE_ROUTING)) &&
+ (strcmp(par->table, "broute") != 0 ||
+ hook_mask & ~(1 << NF_BR_BROUTING)))
+ return false;
if (INVALID_TARGET)
- return -EINVAL;
- return 0;
+ return false;
+ return true;
}
-static struct ebt_target redirect_target __read_mostly = {
- .name = EBT_REDIRECT_TARGET,
- .target = ebt_target_redirect,
- .check = ebt_target_redirect_check,
+static struct xt_target ebt_redirect_tg_reg __read_mostly = {
+ .name = "redirect",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING) |
+ (1 << NF_BR_BROUTING),
+ .target = ebt_redirect_tg,
+ .checkentry = ebt_redirect_tg_check,
+ .targetsize = XT_ALIGN(sizeof(struct ebt_redirect_info)),
.me = THIS_MODULE,
};
static int __init ebt_redirect_init(void)
{
- return ebt_register_target(&redirect_target);
+ return xt_register_target(&ebt_redirect_tg_reg);
}
static void __exit ebt_redirect_fini(void)
{
- ebt_unregister_target(&redirect_target);
+ xt_unregister_target(&ebt_redirect_tg_reg);
}
module_init(ebt_redirect_init);
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index 5425333dda0..8d04d4c302b 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -7,20 +7,19 @@
* June, 2002
*
*/
-
-#include <linux/netfilter.h>
-#include <linux/netfilter_bridge/ebtables.h>
-#include <linux/netfilter_bridge/ebt_nat.h>
#include <linux/module.h>
#include <net/sock.h>
#include <linux/if_arp.h>
#include <net/arp.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_nat.h>
-static int ebt_target_snat(struct sk_buff *skb, unsigned int hooknr,
- const struct net_device *in, const struct net_device *out,
- const void *data, unsigned int datalen)
+static unsigned int
+ebt_snat_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct ebt_nat_info *info = data;
+ const struct ebt_nat_info *info = par->targinfo;
if (!skb_make_writable(skb, 0))
return EBT_DROP;
@@ -43,46 +42,43 @@ out:
return info->target | ~EBT_VERDICT_BITS;
}
-static int ebt_target_snat_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_snat_tg_check(const struct xt_tgchk_param *par)
{
- const struct ebt_nat_info *info = data;
+ const struct ebt_nat_info *info = par->targinfo;
int tmp;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
- return -EINVAL;
tmp = info->target | ~EBT_VERDICT_BITS;
if (BASE_CHAIN && tmp == EBT_RETURN)
- return -EINVAL;
- CLEAR_BASE_CHAIN_BIT;
- if (strcmp(tablename, "nat"))
- return -EINVAL;
- if (hookmask & ~(1 << NF_BR_POST_ROUTING))
- return -EINVAL;
+ return false;
if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
- return -EINVAL;
+ return false;
tmp = info->target | EBT_VERDICT_BITS;
if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT)
- return -EINVAL;
- return 0;
+ return false;
+ return true;
}
-static struct ebt_target snat __read_mostly = {
- .name = EBT_SNAT_TARGET,
- .target = ebt_target_snat,
- .check = ebt_target_snat_check,
+static struct xt_target ebt_snat_tg_reg __read_mostly = {
+ .name = "snat",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .table = "nat",
+ .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_POST_ROUTING),
+ .target = ebt_snat_tg,
+ .checkentry = ebt_snat_tg_check,
+ .targetsize = XT_ALIGN(sizeof(struct ebt_nat_info)),
.me = THIS_MODULE,
};
static int __init ebt_snat_init(void)
{
- return ebt_register_target(&snat);
+ return xt_register_target(&ebt_snat_tg_reg);
}
static void __exit ebt_snat_fini(void)
{
- ebt_unregister_target(&snat);
+ xt_unregister_target(&ebt_snat_tg_reg);
}
module_init(ebt_snat_init);
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c
index 40f36d37607..48527e62162 100644
--- a/net/bridge/netfilter/ebt_stp.c
+++ b/net/bridge/netfilter/ebt_stp.c
@@ -7,11 +7,11 @@
*
* July, 2003
*/
-
-#include <linux/netfilter_bridge/ebtables.h>
-#include <linux/netfilter_bridge/ebt_stp.h>
#include <linux/etherdevice.h>
#include <linux/module.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_stp.h>
#define BPDU_TYPE_CONFIG 0
#define BPDU_TYPE_TCN 0x80
@@ -40,7 +40,7 @@ struct stp_config_pdu {
#define NR16(p) (p[0] << 8 | p[1])
#define NR32(p) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3])
-static int ebt_filter_config(const struct ebt_stp_info *info,
+static bool ebt_filter_config(const struct ebt_stp_info *info,
const struct stp_config_pdu *stpc)
{
const struct ebt_stp_config_info *c;
@@ -51,12 +51,12 @@ static int ebt_filter_config(const struct ebt_stp_info *info,
c = &info->config;
if ((info->bitmask & EBT_STP_FLAGS) &&
FWINV(c->flags != stpc->flags, EBT_STP_FLAGS))
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_STP_ROOTPRIO) {
v16 = NR16(stpc->root);
if (FWINV(v16 < c->root_priol ||
v16 > c->root_priou, EBT_STP_ROOTPRIO))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_STP_ROOTADDR) {
verdict = 0;
@@ -64,19 +64,19 @@ static int ebt_filter_config(const struct ebt_stp_info *info,
verdict |= (stpc->root[2+i] ^ c->root_addr[i]) &
c->root_addrmsk[i];
if (FWINV(verdict != 0, EBT_STP_ROOTADDR))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_STP_ROOTCOST) {
v32 = NR32(stpc->root_cost);
if (FWINV(v32 < c->root_costl ||
v32 > c->root_costu, EBT_STP_ROOTCOST))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_STP_SENDERPRIO) {
v16 = NR16(stpc->sender);
if (FWINV(v16 < c->sender_priol ||
v16 > c->sender_priou, EBT_STP_SENDERPRIO))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_STP_SENDERADDR) {
verdict = 0;
@@ -84,60 +84,60 @@ static int ebt_filter_config(const struct ebt_stp_info *info,
verdict |= (stpc->sender[2+i] ^ c->sender_addr[i]) &
c->sender_addrmsk[i];
if (FWINV(verdict != 0, EBT_STP_SENDERADDR))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_STP_PORT) {
v16 = NR16(stpc->port);
if (FWINV(v16 < c->portl ||
v16 > c->portu, EBT_STP_PORT))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_STP_MSGAGE) {
v16 = NR16(stpc->msg_age);
if (FWINV(v16 < c->msg_agel ||
v16 > c->msg_ageu, EBT_STP_MSGAGE))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_STP_MAXAGE) {
v16 = NR16(stpc->max_age);
if (FWINV(v16 < c->max_agel ||
v16 > c->max_ageu, EBT_STP_MAXAGE))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_STP_HELLOTIME) {
v16 = NR16(stpc->hello_time);
if (FWINV(v16 < c->hello_timel ||
v16 > c->hello_timeu, EBT_STP_HELLOTIME))
- return EBT_NOMATCH;
+ return false;
}
if (info->bitmask & EBT_STP_FWDD) {
v16 = NR16(stpc->forward_delay);
if (FWINV(v16 < c->forward_delayl ||
v16 > c->forward_delayu, EBT_STP_FWDD))
- return EBT_NOMATCH;
+ return false;
}
- return EBT_MATCH;
+ return true;
}
-static int ebt_filter_stp(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const void *data, unsigned int datalen)
+static bool
+ebt_stp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ebt_stp_info *info = data;
+ const struct ebt_stp_info *info = par->matchinfo;
const struct stp_header *sp;
struct stp_header _stph;
const uint8_t header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
sp = skb_header_pointer(skb, 0, sizeof(_stph), &_stph);
if (sp == NULL)
- return EBT_NOMATCH;
+ return false;
/* The stp code only considers these */
if (memcmp(sp, header, sizeof(header)))
- return EBT_NOMATCH;
+ return false;
if (info->bitmask & EBT_STP_TYPE
&& FWINV(info->type != sp->type, EBT_STP_TYPE))
- return EBT_NOMATCH;
+ return false;
if (sp->type == BPDU_TYPE_CONFIG &&
info->bitmask & EBT_STP_CONFIG_MASK) {
@@ -147,48 +147,48 @@ static int ebt_filter_stp(const struct sk_buff *skb, const struct net_device *in
st = skb_header_pointer(skb, sizeof(_stph),
sizeof(_stpc), &_stpc);
if (st == NULL)
- return EBT_NOMATCH;
+ return false;
return ebt_filter_config(info, st);
}
- return EBT_MATCH;
+ return true;
}
-static int ebt_stp_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_stp_mt_check(const struct xt_mtchk_param *par)
{
- const struct ebt_stp_info *info = data;
- const unsigned int len = EBT_ALIGN(sizeof(struct ebt_stp_info));
+ const struct ebt_stp_info *info = par->matchinfo;
const uint8_t bridge_ula[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00};
const uint8_t msk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ const struct ebt_entry *e = par->entryinfo;
if (info->bitmask & ~EBT_STP_MASK || info->invflags & ~EBT_STP_MASK ||
!(info->bitmask & EBT_STP_MASK))
- return -EINVAL;
- if (datalen != len)
- return -EINVAL;
+ return false;
/* Make sure the match only receives stp frames */
if (compare_ether_addr(e->destmac, bridge_ula) ||
compare_ether_addr(e->destmsk, msk) || !(e->bitmask & EBT_DESTMAC))
- return -EINVAL;
+ return false;
- return 0;
+ return true;
}
-static struct ebt_match filter_stp __read_mostly = {
- .name = EBT_STP_MATCH,
- .match = ebt_filter_stp,
- .check = ebt_stp_check,
+static struct xt_match ebt_stp_mt_reg __read_mostly = {
+ .name = "stp",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .match = ebt_stp_mt,
+ .checkentry = ebt_stp_mt_check,
+ .matchsize = XT_ALIGN(sizeof(struct ebt_stp_info)),
.me = THIS_MODULE,
};
static int __init ebt_stp_init(void)
{
- return ebt_register_match(&filter_stp);
+ return xt_register_match(&ebt_stp_mt_reg);
}
static void __exit ebt_stp_fini(void)
{
- ebt_unregister_match(&filter_stp);
+ xt_unregister_match(&ebt_stp_mt_reg);
}
module_init(ebt_stp_init);
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 2d4c9ef909f..2c6d6823e70 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -36,6 +36,7 @@
#include <linux/timer.h>
#include <linux/netlink.h>
#include <linux/netdevice.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_ulog.h>
#include <net/netfilter/nf_log.h>
@@ -223,7 +224,7 @@ alloc_failure:
}
/* this function is registered with the netfilter core */
-static void ebt_log_packet(unsigned int pf, unsigned int hooknum,
+static void ebt_log_packet(u_int8_t pf, unsigned int hooknum,
const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct nf_loginfo *li,
const char *prefix)
@@ -245,24 +246,20 @@ static void ebt_log_packet(unsigned int pf, unsigned int hooknum,
ebt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
}
-static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr,
- const struct net_device *in, const struct net_device *out,
- const void *data, unsigned int datalen)
+static unsigned int
+ebt_ulog_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct ebt_ulog_info *uloginfo = data;
-
- ebt_ulog_packet(hooknr, skb, in, out, uloginfo, NULL);
+ ebt_ulog_packet(par->hooknum, skb, par->in, par->out,
+ par->targinfo, NULL);
+ return EBT_CONTINUE;
}
-
-static int ebt_ulog_check(const char *tablename, unsigned int hookmask,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_ulog_tg_check(const struct xt_tgchk_param *par)
{
- struct ebt_ulog_info *uloginfo = data;
+ struct ebt_ulog_info *uloginfo = par->targinfo;
- if (datalen != EBT_ALIGN(sizeof(struct ebt_ulog_info)) ||
- uloginfo->nlgroup > 31)
- return -EINVAL;
+ if (uloginfo->nlgroup > 31)
+ return false;
uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0';
@@ -272,27 +269,31 @@ static int ebt_ulog_check(const char *tablename, unsigned int hookmask,
return 0;
}
-static struct ebt_watcher ulog __read_mostly = {
- .name = EBT_ULOG_WATCHER,
- .watcher = ebt_ulog,
- .check = ebt_ulog_check,
+static struct xt_target ebt_ulog_tg_reg __read_mostly = {
+ .name = "ulog",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .target = ebt_ulog_tg,
+ .checkentry = ebt_ulog_tg_check,
+ .targetsize = XT_ALIGN(sizeof(struct ebt_ulog_info)),
.me = THIS_MODULE,
};
static const struct nf_logger ebt_ulog_logger = {
- .name = EBT_ULOG_WATCHER,
+ .name = "ulog",
.logfn = &ebt_log_packet,
.me = THIS_MODULE,
};
static int __init ebt_ulog_init(void)
{
- int i, ret = 0;
+ bool ret = true;
+ int i;
if (nlbufsiz >= 128*1024) {
printk(KERN_NOTICE "ebt_ulog: Netlink buffer has to be <= 128kB,"
" please try a smaller nlbufsiz parameter.\n");
- return -EINVAL;
+ return false;
}
/* initialize ulog_buffers */
@@ -304,13 +305,16 @@ static int __init ebt_ulog_init(void)
ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG,
EBT_ULOG_MAXNLGROUPS, NULL, NULL,
THIS_MODULE);
- if (!ebtulognl)
- ret = -ENOMEM;
- else if ((ret = ebt_register_watcher(&ulog)))
+ if (!ebtulognl) {
+ printk(KERN_WARNING KBUILD_MODNAME ": out of memory trying to "
+ "call netlink_kernel_create\n");
+ ret = false;
+ } else if (xt_register_target(&ebt_ulog_tg_reg) != 0) {
netlink_kernel_release(ebtulognl);
+ }
- if (ret == 0)
- nf_log_register(PF_BRIDGE, &ebt_ulog_logger);
+ if (ret)
+ nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger);
return ret;
}
@@ -321,7 +325,7 @@ static void __exit ebt_ulog_fini(void)
int i;
nf_log_unregister(&ebt_ulog_logger);
- ebt_unregister_watcher(&ulog);
+ xt_unregister_target(&ebt_ulog_tg_reg);
for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
ub = &ulog_buffers[i];
if (timer_pending(&ub->timer))
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index ab60b0dade8..3dddd489328 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -22,6 +22,7 @@
#include <linux/if_vlan.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_vlan.h>
@@ -37,15 +38,12 @@ MODULE_LICENSE("GPL");
#define DEBUG_MSG(args...) if (debug) printk (KERN_DEBUG "ebt_vlan: " args)
#define GET_BITMASK(_BIT_MASK_) info->bitmask & _BIT_MASK_
-#define EXIT_ON_MISMATCH(_MATCH_,_MASK_) {if (!((info->_MATCH_ == _MATCH_)^!!(info->invflags & _MASK_))) return EBT_NOMATCH;}
+#define EXIT_ON_MISMATCH(_MATCH_,_MASK_) {if (!((info->_MATCH_ == _MATCH_)^!!(info->invflags & _MASK_))) return false; }
-static int
-ebt_filter_vlan(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *data, unsigned int datalen)
+static bool
+ebt_vlan_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ebt_vlan_info *info = data;
+ const struct ebt_vlan_info *info = par->matchinfo;
const struct vlan_hdr *fp;
struct vlan_hdr _frame;
@@ -57,7 +55,7 @@ ebt_filter_vlan(const struct sk_buff *skb,
fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
if (fp == NULL)
- return EBT_NOMATCH;
+ return false;
/* Tag Control Information (TCI) consists of the following elements:
* - User_priority. The user_priority field is three bits in length,
@@ -83,30 +81,20 @@ ebt_filter_vlan(const struct sk_buff *skb,
if (GET_BITMASK(EBT_VLAN_ENCAP))
EXIT_ON_MISMATCH(encap, EBT_VLAN_ENCAP);
- return EBT_MATCH;
+ return true;
}
-static int
-ebt_check_vlan(const char *tablename,
- unsigned int hooknr,
- const struct ebt_entry *e, void *data, unsigned int datalen)
+static bool ebt_vlan_mt_check(const struct xt_mtchk_param *par)
{
- struct ebt_vlan_info *info = data;
-
- /* Parameters buffer overflow check */
- if (datalen != EBT_ALIGN(sizeof(struct ebt_vlan_info))) {
- DEBUG_MSG
- ("passed size %d is not eq to ebt_vlan_info (%Zd)\n",
- datalen, sizeof(struct ebt_vlan_info));
- return -EINVAL;
- }
+ struct ebt_vlan_info *info = par->matchinfo;
+ const struct ebt_entry *e = par->entryinfo;
/* Is it 802.1Q frame checked? */
if (e->ethproto != htons(ETH_P_8021Q)) {
DEBUG_MSG
("passed entry proto %2.4X is not 802.1Q (8100)\n",
(unsigned short) ntohs(e->ethproto));
- return -EINVAL;
+ return false;
}
/* Check for bitmask range
@@ -114,14 +102,14 @@ ebt_check_vlan(const char *tablename,
if (info->bitmask & ~EBT_VLAN_MASK) {
DEBUG_MSG("bitmask %2X is out of mask (%2X)\n",
info->bitmask, EBT_VLAN_MASK);
- return -EINVAL;
+ return false;
}
/* Check for inversion flags range */
if (info->invflags & ~EBT_VLAN_MASK) {
DEBUG_MSG("inversion flags %2X is out of mask (%2X)\n",
info->invflags, EBT_VLAN_MASK);
- return -EINVAL;
+ return false;
}
/* Reserved VLAN ID (VID) values
@@ -136,7 +124,7 @@ ebt_check_vlan(const char *tablename,
DEBUG_MSG
("id %d is out of range (1-4096)\n",
info->id);
- return -EINVAL;
+ return false;
}
/* Note: This is valid VLAN-tagged frame point.
* Any value of user_priority are acceptable,
@@ -151,7 +139,7 @@ ebt_check_vlan(const char *tablename,
if ((unsigned char) info->prio > 7) {
DEBUG_MSG("prio %d is out of range (0-7)\n",
info->prio);
- return -EINVAL;
+ return false;
}
}
/* Check for encapsulated proto range - it is possible to be
@@ -162,17 +150,20 @@ ebt_check_vlan(const char *tablename,
DEBUG_MSG
("encap frame length %d is less than minimal\n",
ntohs(info->encap));
- return -EINVAL;
+ return false;
}
}
- return 0;
+ return true;
}
-static struct ebt_match filter_vlan __read_mostly = {
- .name = EBT_VLAN_MATCH,
- .match = ebt_filter_vlan,
- .check = ebt_check_vlan,
+static struct xt_match ebt_vlan_mt_reg __read_mostly = {
+ .name = "vlan",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .match = ebt_vlan_mt,
+ .checkentry = ebt_vlan_mt_check,
+ .matchsize = XT_ALIGN(sizeof(struct ebt_vlan_info)),
.me = THIS_MODULE,
};
@@ -181,12 +172,12 @@ static int __init ebt_vlan_init(void)
DEBUG_MSG("ebtables 802.1Q extension module v"
MODULE_VERS "\n");
DEBUG_MSG("module debug=%d\n", !!debug);
- return ebt_register_match(&filter_vlan);
+ return xt_register_match(&ebt_vlan_mt_reg);
}
static void __exit ebt_vlan_fini(void)
{
- ebt_unregister_match(&filter_vlan);
+ xt_unregister_match(&ebt_vlan_mt_reg);
}
module_init(ebt_vlan_init);
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index 690bc3ab186..1a58af51a2e 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -93,28 +93,20 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
static int __init ebtable_filter_init(void)
{
- int i, j, ret;
+ int ret;
ret = ebt_register_table(&frame_filter);
if (ret < 0)
return ret;
- for (i = 0; i < ARRAY_SIZE(ebt_ops_filter); i++)
- if ((ret = nf_register_hook(&ebt_ops_filter[i])) < 0)
- goto cleanup;
- return ret;
-cleanup:
- for (j = 0; j < i; j++)
- nf_unregister_hook(&ebt_ops_filter[j]);
- ebt_unregister_table(&frame_filter);
+ ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
+ if (ret < 0)
+ ebt_unregister_table(&frame_filter);
return ret;
}
static void __exit ebtable_filter_fini(void)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ebt_ops_filter); i++)
- nf_unregister_hook(&ebt_ops_filter[i]);
+ nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
ebt_unregister_table(&frame_filter);
}
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 5b495fe2d0b..f60c1e78e57 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -100,28 +100,20 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
static int __init ebtable_nat_init(void)
{
- int i, ret, j;
+ int ret;
ret = ebt_register_table(&frame_nat);
if (ret < 0)
return ret;
- for (i = 0; i < ARRAY_SIZE(ebt_ops_nat); i++)
- if ((ret = nf_register_hook(&ebt_ops_nat[i])) < 0)
- goto cleanup;
- return ret;
-cleanup:
- for (j = 0; j < i; j++)
- nf_unregister_hook(&ebt_ops_nat[j]);
- ebt_unregister_table(&frame_nat);
+ ret = nf_register_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat));
+ if (ret < 0)
+ ebt_unregister_table(&frame_nat);
return ret;
}
static void __exit ebtable_nat_fini(void)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ebt_ops_nat); i++)
- nf_unregister_hook(&ebt_ops_nat[i]);
+ nf_unregister_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat));
ebt_unregister_table(&frame_nat);
}
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 32afff859e4..5bb88eb0aad 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -19,6 +19,7 @@
#include <linux/kmod.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
@@ -55,29 +56,31 @@
static DEFINE_MUTEX(ebt_mutex);
static LIST_HEAD(ebt_tables);
-static LIST_HEAD(ebt_targets);
-static LIST_HEAD(ebt_matches);
-static LIST_HEAD(ebt_watchers);
-static struct ebt_target ebt_standard_target =
-{ {NULL, NULL}, EBT_STANDARD_TARGET, NULL, NULL, NULL, NULL};
+static struct xt_target ebt_standard_target = {
+ .name = "standard",
+ .revision = 0,
+ .family = NFPROTO_BRIDGE,
+ .targetsize = sizeof(int),
+};
-static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
- const struct sk_buff *skb, unsigned int hooknr, const struct net_device *in,
- const struct net_device *out)
+static inline int
+ebt_do_watcher(const struct ebt_entry_watcher *w, struct sk_buff *skb,
+ struct xt_target_param *par)
{
- w->u.watcher->watcher(skb, hooknr, in, out, w->data,
- w->watcher_size);
+ par->target = w->u.watcher;
+ par->targinfo = w->data;
+ w->u.watcher->target(skb, par);
/* watchers don't give a verdict */
return 0;
}
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 sk_buff *skb, struct xt_match_param *par)
{
- return m->u.match->match(skb, in, out, m->data,
- m->match_size);
+ par->match = m->u.match;
+ par->matchinfo = m->data;
+ return m->u.match->match(skb, par);
}
static inline int ebt_dev_check(char *entry, const struct net_device *device)
@@ -153,6 +156,15 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
struct ebt_entries *chaininfo;
char *base;
struct ebt_table_info *private;
+ bool hotdrop = false;
+ struct xt_match_param mtpar;
+ struct xt_target_param tgpar;
+
+ mtpar.family = tgpar.family = NFPROTO_BRIDGE;
+ mtpar.in = tgpar.in = in;
+ mtpar.out = tgpar.out = out;
+ mtpar.hotdrop = &hotdrop;
+ tgpar.hooknum = hook;
read_lock_bh(&table->lock);
private = table->private;
@@ -173,8 +185,12 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
if (ebt_basic_match(point, eth_hdr(skb), in, out))
goto letscontinue;
- if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, in, out) != 0)
+ if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &mtpar) != 0)
goto letscontinue;
+ if (hotdrop) {
+ read_unlock_bh(&table->lock);
+ return NF_DROP;
+ }
/* increase counter */
(*(counter_base + i)).pcnt++;
@@ -182,17 +198,18 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
/* these should only watch: not modify, nor tell us
what to do with the packet */
- EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, hook, in,
- out);
+ EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, &tgpar);
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(skb, hook,
- in, out, t->data, t->target_size);
+ else {
+ tgpar.target = t->u.target;
+ tgpar.targinfo = t->data;
+ verdict = t->u.target->target(skb, &tgpar);
+ }
if (verdict == EBT_ACCEPT) {
read_unlock_bh(&table->lock);
return NF_ACCEPT;
@@ -312,80 +329,71 @@ find_table_lock(const char *name, int *error, struct mutex *mutex)
return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex);
}
-static inline struct ebt_match *
-find_match_lock(const char *name, int *error, struct mutex *mutex)
-{
- return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex);
-}
-
-static inline struct ebt_watcher *
-find_watcher_lock(const char *name, int *error, struct mutex *mutex)
-{
- return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex);
-}
-
-static inline struct ebt_target *
-find_target_lock(const char *name, int *error, struct mutex *mutex)
-{
- return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex);
-}
-
static inline int
-ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
- const char *name, unsigned int hookmask, unsigned int *cnt)
+ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par,
+ unsigned int *cnt)
{
- struct ebt_match *match;
+ const struct ebt_entry *e = par->entryinfo;
+ struct xt_match *match;
size_t left = ((char *)e + e->watchers_offset) - (char *)m;
int ret;
if (left < sizeof(struct ebt_entry_match) ||
left - sizeof(struct ebt_entry_match) < m->match_size)
return -EINVAL;
- match = find_match_lock(m->u.name, &ret, &ebt_mutex);
- if (!match)
- return ret;
- m->u.match = match;
- if (!try_module_get(match->me)) {
- mutex_unlock(&ebt_mutex);
+
+ match = try_then_request_module(xt_find_match(NFPROTO_BRIDGE,
+ m->u.name, 0), "ebt_%s", m->u.name);
+ if (IS_ERR(match))
+ return PTR_ERR(match);
+ if (match == NULL)
return -ENOENT;
- }
- mutex_unlock(&ebt_mutex);
- if (match->check &&
- match->check(name, hookmask, e, m->data, m->match_size) != 0) {
- BUGPRINT("match->check failed\n");
+ m->u.match = match;
+
+ par->match = match;
+ par->matchinfo = m->data;
+ ret = xt_check_match(par, m->match_size,
+ e->ethproto, e->invflags & EBT_IPROTO);
+ if (ret < 0) {
module_put(match->me);
- return -EINVAL;
+ return ret;
}
+
(*cnt)++;
return 0;
}
static inline int
-ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
- const char *name, unsigned int hookmask, unsigned int *cnt)
+ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par,
+ unsigned int *cnt)
{
- struct ebt_watcher *watcher;
+ const struct ebt_entry *e = par->entryinfo;
+ struct xt_target *watcher;
size_t left = ((char *)e + e->target_offset) - (char *)w;
int ret;
if (left < sizeof(struct ebt_entry_watcher) ||
left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
return -EINVAL;
- watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
- if (!watcher)
- return ret;
- w->u.watcher = watcher;
- if (!try_module_get(watcher->me)) {
- mutex_unlock(&ebt_mutex);
+
+ watcher = try_then_request_module(
+ xt_find_target(NFPROTO_BRIDGE, w->u.name, 0),
+ "ebt_%s", w->u.name);
+ if (IS_ERR(watcher))
+ return PTR_ERR(watcher);
+ if (watcher == NULL)
return -ENOENT;
- }
- mutex_unlock(&ebt_mutex);
- if (watcher->check &&
- watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) {
- BUGPRINT("watcher->check failed\n");
+ w->u.watcher = watcher;
+
+ par->target = watcher;
+ par->targinfo = w->data;
+ ret = xt_check_target(par, w->watcher_size,
+ e->ethproto, e->invflags & EBT_IPROTO);
+ if (ret < 0) {
module_put(watcher->me);
- return -EINVAL;
+ return ret;
}
+
(*cnt)++;
return 0;
}
@@ -558,30 +566,41 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
static inline int
ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
{
+ struct xt_mtdtor_param par;
+
if (i && (*i)-- == 0)
return 1;
- if (m->u.match->destroy)
- m->u.match->destroy(m->data, m->match_size);
- module_put(m->u.match->me);
+ par.match = m->u.match;
+ par.matchinfo = m->data;
+ par.family = NFPROTO_BRIDGE;
+ if (par.match->destroy != NULL)
+ par.match->destroy(&par);
+ module_put(par.match->me);
return 0;
}
static inline int
ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
{
+ struct xt_tgdtor_param par;
+
if (i && (*i)-- == 0)
return 1;
- if (w->u.watcher->destroy)
- w->u.watcher->destroy(w->data, w->watcher_size);
- module_put(w->u.watcher->me);
+ par.target = w->u.watcher;
+ par.targinfo = w->data;
+ par.family = NFPROTO_BRIDGE;
+ if (par.target->destroy != NULL)
+ par.target->destroy(&par);
+ module_put(par.target->me);
return 0;
}
static inline int
ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
{
+ struct xt_tgdtor_param par;
struct ebt_entry_target *t;
if (e->bitmask == 0)
@@ -592,10 +611,13 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);
t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
- if (t->u.target->destroy)
- t->u.target->destroy(t->data, t->target_size);
- module_put(t->u.target->me);
+ par.target = t->u.target;
+ par.targinfo = t->data;
+ par.family = NFPROTO_BRIDGE;
+ if (par.target->destroy != NULL)
+ par.target->destroy(&par);
+ module_put(par.target->me);
return 0;
}
@@ -605,10 +627,12 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
{
struct ebt_entry_target *t;
- struct ebt_target *target;
+ struct xt_target *target;
unsigned int i, j, hook = 0, hookmask = 0;
size_t gap;
int ret;
+ struct xt_mtchk_param mtpar;
+ struct xt_tgchk_param tgpar;
/* don't mess with the struct ebt_entries */
if (e->bitmask == 0)
@@ -649,24 +673,31 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
hookmask = cl_s[i - 1].hookmask;
}
i = 0;
- ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);
+
+ mtpar.table = tgpar.table = name;
+ mtpar.entryinfo = tgpar.entryinfo = e;
+ mtpar.hook_mask = tgpar.hook_mask = hookmask;
+ mtpar.family = tgpar.family = NFPROTO_BRIDGE;
+ ret = EBT_MATCH_ITERATE(e, ebt_check_match, &mtpar, &i);
if (ret != 0)
goto cleanup_matches;
j = 0;
- ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
+ ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, &tgpar, &j);
if (ret != 0)
goto cleanup_watchers;
t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
gap = e->next_offset - e->target_offset;
- target = find_target_lock(t->u.name, &ret, &ebt_mutex);
- if (!target)
+
+ target = try_then_request_module(
+ xt_find_target(NFPROTO_BRIDGE, t->u.name, 0),
+ "ebt_%s", t->u.name);
+ if (IS_ERR(target)) {
+ ret = PTR_ERR(target);
goto cleanup_watchers;
- if (!try_module_get(target->me)) {
- mutex_unlock(&ebt_mutex);
+ } else if (target == NULL) {
ret = -ENOENT;
goto cleanup_watchers;
}
- mutex_unlock(&ebt_mutex);
t->u.target = target;
if (t->u.target == &ebt_standard_target) {
@@ -681,13 +712,20 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
ret = -EFAULT;
goto cleanup_watchers;
}
- } else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
- (t->u.target->check &&
- t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
+ } else if (t->target_size > gap - sizeof(struct ebt_entry_target)) {
module_put(t->u.target->me);
ret = -EFAULT;
goto cleanup_watchers;
}
+
+ tgpar.target = target;
+ tgpar.targinfo = t->data;
+ ret = xt_check_target(&tgpar, t->target_size,
+ e->ethproto, e->invflags & EBT_IPROTO);
+ if (ret < 0) {
+ module_put(target->me);
+ goto cleanup_watchers;
+ }
(*cnt)++;
return 0;
cleanup_watchers:
@@ -1068,87 +1106,6 @@ free_newinfo:
return ret;
}
-int ebt_register_target(struct ebt_target *target)
-{
- struct ebt_target *t;
- int ret;
-
- ret = mutex_lock_interruptible(&ebt_mutex);
- if (ret != 0)
- return ret;
- list_for_each_entry(t, &ebt_targets, list) {
- if (strcmp(t->name, target->name) == 0) {
- mutex_unlock(&ebt_mutex);
- return -EEXIST;
- }
- }
- list_add(&target->list, &ebt_targets);
- mutex_unlock(&ebt_mutex);
-
- return 0;
-}
-
-void ebt_unregister_target(struct ebt_target *target)
-{
- mutex_lock(&ebt_mutex);
- list_del(&target->list);
- mutex_unlock(&ebt_mutex);
-}
-
-int ebt_register_match(struct ebt_match *match)
-{
- struct ebt_match *m;
- int ret;
-
- ret = mutex_lock_interruptible(&ebt_mutex);
- if (ret != 0)
- return ret;
- list_for_each_entry(m, &ebt_matches, list) {
- if (strcmp(m->name, match->name) == 0) {
- mutex_unlock(&ebt_mutex);
- return -EEXIST;
- }
- }
- list_add(&match->list, &ebt_matches);
- mutex_unlock(&ebt_mutex);
-
- return 0;
-}
-
-void ebt_unregister_match(struct ebt_match *match)
-{
- mutex_lock(&ebt_mutex);
- list_del(&match->list);
- mutex_unlock(&ebt_mutex);
-}
-
-int ebt_register_watcher(struct ebt_watcher *watcher)
-{
- struct ebt_watcher *w;
- int ret;
-
- ret = mutex_lock_interruptible(&ebt_mutex);
- if (ret != 0)
- return ret;
- list_for_each_entry(w, &ebt_watchers, list) {
- if (strcmp(w->name, watcher->name) == 0) {
- mutex_unlock(&ebt_mutex);
- return -EEXIST;
- }
- }
- list_add(&watcher->list, &ebt_watchers);
- mutex_unlock(&ebt_mutex);
-
- return 0;
-}
-
-void ebt_unregister_watcher(struct ebt_watcher *watcher)
-{
- mutex_lock(&ebt_mutex);
- list_del(&watcher->list);
- mutex_unlock(&ebt_mutex);
-}
-
int ebt_register_table(struct ebt_table *table)
{
struct ebt_table_info *newinfo;
@@ -1518,11 +1475,14 @@ static int __init ebtables_init(void)
{
int ret;
- mutex_lock(&ebt_mutex);
- list_add(&ebt_standard_target.list, &ebt_targets);
- mutex_unlock(&ebt_mutex);
- if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
+ ret = xt_register_target(&ebt_standard_target);
+ if (ret < 0)
+ return ret;
+ ret = nf_register_sockopt(&ebt_sockopts);
+ if (ret < 0) {
+ xt_unregister_target(&ebt_standard_target);
return ret;
+ }
printk(KERN_INFO "Ebtables v2.0 registered\n");
return 0;
@@ -1531,17 +1491,12 @@ static int __init ebtables_init(void)
static void __exit ebtables_fini(void)
{
nf_unregister_sockopt(&ebt_sockopts);
+ xt_unregister_target(&ebt_standard_target);
printk(KERN_INFO "Ebtables v2.0 unregistered\n");
}
EXPORT_SYMBOL(ebt_register_table);
EXPORT_SYMBOL(ebt_unregister_table);
-EXPORT_SYMBOL(ebt_register_match);
-EXPORT_SYMBOL(ebt_unregister_match);
-EXPORT_SYMBOL(ebt_register_watcher);
-EXPORT_SYMBOL(ebt_unregister_watcher);
-EXPORT_SYMBOL(ebt_register_target);
-EXPORT_SYMBOL(ebt_unregister_target);
EXPORT_SYMBOL(ebt_do_table);
module_init(ebtables_init);
module_exit(ebtables_fini);