summaryrefslogtreecommitdiff
path: root/net/bridge
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-31 20:43:41 +0400
committerIngo Molnar <mingo@elte.hu>2008-07-31 20:43:41 +0400
commit85e9ca333d03fbd56b9e123c8456f0d98e20faad (patch)
tree7bb15ada5f536950efa23ad60ea9eea60380ca1c /net/bridge
parenta300bec952127d9a15e666b391bb35c9aecb3002 (diff)
parent6e86841d05f371b5b9b86ce76c02aaee83352298 (diff)
downloadlinux-85e9ca333d03fbd56b9e123c8456f0d98e20faad.tar.xz
Merge branch 'linus' into timers/hpet
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/Kconfig1
-rw-r--r--net/bridge/br.c18
-rw-r--r--net/bridge/br_device.c14
-rw-r--r--net/bridge/br_fdb.c3
-rw-r--r--net/bridge/br_forward.c6
-rw-r--r--net/bridge/br_if.c22
-rw-r--r--net/bridge/br_input.c25
-rw-r--r--net/bridge/br_ioctl.c2
-rw-r--r--net/bridge/br_notify.c4
-rw-r--r--net/bridge/br_private.h10
-rw-r--r--net/bridge/br_private_stp.h2
-rw-r--r--net/bridge/br_stp.c3
-rw-r--r--net/bridge/br_stp_bpdu.c16
-rw-r--r--net/bridge/br_stp_if.c6
-rw-r--r--net/bridge/br_stp_timer.c2
-rw-r--r--net/bridge/netfilter/Kconfig11
-rw-r--r--net/bridge/netfilter/Makefile1
-rw-r--r--net/bridge/netfilter/ebt_ip6.c144
-rw-r--r--net/bridge/netfilter/ebt_log.c66
-rw-r--r--net/bridge/netfilter/ebtable_filter.c18
-rw-r--r--net/bridge/netfilter/ebtable_nat.c18
21 files changed, 270 insertions, 122 deletions
diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig
index 12265aff7099..e143ca678881 100644
--- a/net/bridge/Kconfig
+++ b/net/bridge/Kconfig
@@ -5,6 +5,7 @@
config BRIDGE
tristate "802.1d Ethernet Bridging"
select LLC
+ select STP
---help---
If you say Y here, then your Linux box will be able to act as an
Ethernet bridge, which means that the different Ethernet segments it
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 8f3c58e5f7a5..573acdf6f9ff 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -5,8 +5,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br.c,v 1.47 2001/12/24 00:56:41 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -20,21 +18,24 @@
#include <linux/init.h>
#include <linux/llc.h>
#include <net/llc.h>
+#include <net/stp.h>
#include "br_private.h"
int (*br_should_route_hook)(struct sk_buff *skb);
-static struct llc_sap *br_stp_sap;
+static const struct stp_proto br_stp_proto = {
+ .rcv = br_stp_rcv,
+};
static int __init br_init(void)
{
int err;
- br_stp_sap = llc_sap_open(LLC_SAP_BSPAN, br_stp_rcv);
- if (!br_stp_sap) {
+ err = stp_proto_register(&br_stp_proto);
+ if (err < 0) {
printk(KERN_ERR "bridge: can't register sap for STP\n");
- return -EADDRINUSE;
+ return err;
}
err = br_fdb_init();
@@ -67,13 +68,13 @@ err_out2:
err_out1:
br_fdb_fini();
err_out:
- llc_sap_put(br_stp_sap);
+ stp_proto_unregister(&br_stp_proto);
return err;
}
static void __exit br_deinit(void)
{
- rcu_assign_pointer(br_stp_sap->rcv_func, NULL);
+ stp_proto_unregister(&br_stp_proto);
br_netlink_fini();
unregister_netdevice_notifier(&br_device_notifier);
@@ -84,7 +85,6 @@ static void __exit br_deinit(void)
synchronize_net();
br_netfilter_fini();
- llc_sap_put(br_stp_sap);
br_fdb_get_hook = NULL;
br_fdb_put_hook = NULL;
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index bf7787395fe0..d9449df7cad5 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -5,8 +5,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_device.c,v 1.6 2001/12/24 00:59:55 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -21,12 +19,6 @@
#include <asm/uaccess.h>
#include "br_private.h"
-static struct net_device_stats *br_dev_get_stats(struct net_device *dev)
-{
- struct net_bridge *br = netdev_priv(dev);
- return &br->statistics;
-}
-
/* net device transmit always called with no BH (preempt_disabled) */
int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{
@@ -34,8 +26,8 @@ int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
const unsigned char *dest = skb->data;
struct net_bridge_fdb_entry *dst;
- br->statistics.tx_packets++;
- br->statistics.tx_bytes += skb->len;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
skb_reset_mac_header(skb);
skb_pull(skb, ETH_HLEN);
@@ -95,6 +87,7 @@ static int br_set_mac_address(struct net_device *dev, void *p)
spin_lock_bh(&br->lock);
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
br_stp_change_bridge_id(br, addr->sa_data);
+ br->flags |= BR_SET_MAC_ADDR;
spin_unlock_bh(&br->lock);
return 0;
@@ -161,7 +154,6 @@ void br_dev_setup(struct net_device *dev)
ether_setup(dev);
dev->do_ioctl = br_dev_ioctl;
- dev->get_stats = br_dev_get_stats;
dev->hard_start_xmit = br_dev_xmit;
dev->open = br_dev_open;
dev->set_multicast_list = br_dev_set_multicast_list;
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 72c5976a5ce3..a48f5efdb6bf 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -5,8 +5,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_fdb.c,v 1.6 2002/01/17 00:57:07 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -15,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/rculist.h>
#include <linux/spinlock.h>
#include <linux/times.h>
#include <linux/netdevice.h>
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index bdd7c35c3c7b..bdd9ccea17ce 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -5,8 +5,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_forward.c,v 1.4 2001/08/14 22:05:57 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -91,7 +89,7 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
/* called with rcu_read_lock */
void br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
{
- if (should_deliver(to, skb)) {
+ if (!skb_warn_if_lro(skb) && should_deliver(to, skb)) {
__br_forward(to, skb);
return;
}
@@ -115,7 +113,7 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb,
struct sk_buff *skb2;
if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
- br->statistics.tx_dropped++;
+ br->dev->stats.tx_dropped++;
kfree_skb(skb);
return;
}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index c2397f503b0f..a072ea5ca6f5 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -5,8 +5,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_if.c,v 1.7 2001/12/24 00:59:55 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -375,6 +373,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
if (IS_ERR(p))
return PTR_ERR(p);
+ err = dev_set_promiscuity(dev, 1);
+ if (err)
+ goto put_back;
+
err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj),
SYSFS_BRIDGE_PORT_ATTR);
if (err)
@@ -389,7 +391,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
goto err2;
rcu_assign_pointer(dev->br_port, p);
- dev_set_promiscuity(dev, 1);
+ dev_disable_lro(dev);
list_add_rcu(&p->list, &br->port_list);
@@ -413,12 +415,12 @@ err2:
br_fdb_delete_by_port(br, p, 1);
err1:
kobject_del(&p->kobj);
- goto put_back;
err0:
kobject_put(&p->kobj);
-
+ dev_set_promiscuity(dev, -1);
put_back:
dev_put(dev);
+ kfree(p);
return err;
}
@@ -442,12 +444,16 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
void __exit br_cleanup_bridges(void)
{
- struct net_device *dev, *nxt;
+ struct net_device *dev;
rtnl_lock();
- for_each_netdev_safe(&init_net, dev, nxt)
- if (dev->priv_flags & IFF_EBRIDGE)
+restart:
+ for_each_netdev(&init_net, dev) {
+ if (dev->priv_flags & IFF_EBRIDGE) {
del_br(dev->priv);
+ goto restart;
+ }
+ }
rtnl_unlock();
}
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 255c00f60ce7..30b88777c3df 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -5,8 +5,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_input.c,v 1.10 2001/12/24 04:50:20 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -24,13 +22,13 @@ const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
{
- struct net_device *indev;
+ struct net_device *indev, *brdev = br->dev;
- br->statistics.rx_packets++;
- br->statistics.rx_bytes += skb->len;
+ brdev->stats.rx_packets++;
+ brdev->stats.rx_bytes += skb->len;
indev = skb->dev;
- skb->dev = br->dev;
+ skb->dev = brdev;
NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
netif_receive_skb);
@@ -64,7 +62,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
dst = NULL;
if (is_multicast_ether_addr(dest)) {
- br->statistics.multicast++;
+ br->dev->stats.multicast++;
skb2 = skb;
} else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) {
skb2 = skb;
@@ -136,14 +134,11 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
if (skb->protocol == htons(ETH_P_PAUSE))
goto drop;
- /* Process STP BPDU's through normal netif_receive_skb() path */
- if (p->br->stp_enabled != BR_NO_STP) {
- if (NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
- NULL, br_handle_local_finish))
- return NULL;
- else
- return skb;
- }
+ if (NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
+ NULL, br_handle_local_finish))
+ return NULL; /* frame consumed by filter */
+ else
+ return skb; /* continue processing */
}
switch (p->state) {
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 0655a5f07f58..eeee218eed80 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -5,8 +5,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_ioctl.c,v 1.4 2000/11/08 05:16:40 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index 00644a544e3c..76340bdd052e 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -5,8 +5,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_notify.c,v 1.2 2000/02/21 15:51:34 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -37,7 +35,7 @@ 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 (dev_net(dev) != &init_net)
+ if (!net_eq(dev_net(dev), &init_net))
return NOTIFY_DONE;
/* not a port of a bridge */
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index c11b554fd109..815ed38925b2 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -4,8 +4,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_private.h,v 1.7 2001/12/24 00:59:55 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -90,11 +88,12 @@ struct net_bridge
spinlock_t lock;
struct list_head port_list;
struct net_device *dev;
- struct net_device_stats statistics;
spinlock_t hash_lock;
struct hlist_head hash[BR_HASH_SIZE];
struct list_head age_list;
unsigned long feature_mask;
+ unsigned long flags;
+#define BR_SET_MAC_ADDR 0x00000001
/* STP */
bridge_id designated_root;
@@ -227,8 +226,9 @@ extern void br_stp_set_path_cost(struct net_bridge_port *p,
extern ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id);
/* br_stp_bpdu.c */
-extern int br_stp_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt, struct net_device *orig_dev);
+struct stp_proto;
+extern void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
+ struct net_device *dev);
/* br_stp_timer.c */
extern void br_stp_timer_init(struct net_bridge *br);
diff --git a/net/bridge/br_private_stp.h b/net/bridge/br_private_stp.h
index e29f01ac1adf..8b650f7fbfa0 100644
--- a/net/bridge/br_private_stp.h
+++ b/net/bridge/br_private_stp.h
@@ -4,8 +4,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_private_stp.h,v 1.3 2001/02/05 06:03:47 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index e38034aa56f5..921bbe5cb94a 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -5,14 +5,13 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_stp.c,v 1.4 2000/06/19 10:13:35 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/kernel.h>
+#include <linux/rculist.h>
#include "br_private.h"
#include "br_private_stp.h"
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index ddeb6e5d45d6..8b200f96f722 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -5,8 +5,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_stp_bpdu.c,v 1.3 2001/11/10 02:35:25 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -20,6 +18,7 @@
#include <net/net_namespace.h>
#include <net/llc.h>
#include <net/llc_pdu.h>
+#include <net/stp.h>
#include <asm/unaligned.h>
#include "br_private.h"
@@ -133,26 +132,20 @@ void br_send_tcn_bpdu(struct net_bridge_port *p)
*
* NO locks, but rcu_read_lock (preempt_disabled)
*/
-int br_stp_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt, struct net_device *orig_dev)
+void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
+ struct net_device *dev)
{
- const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
const unsigned char *dest = eth_hdr(skb)->h_dest;
struct net_bridge_port *p = rcu_dereference(dev->br_port);
struct net_bridge *br;
const unsigned char *buf;
- if (dev_net(dev) != &init_net)
+ if (!net_eq(dev_net(dev), &init_net))
goto err;
if (!p)
goto err;
- if (pdu->ssap != LLC_SAP_BSPAN
- || pdu->dsap != LLC_SAP_BSPAN
- || pdu->ctrl_1 != LLC_PDU_TYPE_U)
- goto err;
-
if (!pskb_may_pull(skb, 4))
goto err;
@@ -226,5 +219,4 @@ int br_stp_rcv(struct sk_buff *skb, struct net_device *dev,
spin_unlock(&br->lock);
err:
kfree_skb(skb);
- return 0;
}
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 1a430eccec9b..9a52ac5b4525 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -5,8 +5,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_stp_if.c,v 1.4 2001/04/14 21:14:39 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -216,6 +214,10 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br)
const unsigned char *addr = br_mac_zero;
struct net_bridge_port *p;
+ /* user has chosen a value so keep it */
+ if (br->flags & BR_SET_MAC_ADDR)
+ return;
+
list_for_each_entry(p, &br->port_list, list) {
if (addr == br_mac_zero ||
memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0)
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index 77f5255e6915..772a140bfdf0 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -5,8 +5,6 @@
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_stp_timer.c,v 1.3 2000/05/05 02:17:17 davem Exp $
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig
index 7beeefa0f9c0..909479794999 100644
--- a/net/bridge/netfilter/Kconfig
+++ b/net/bridge/netfilter/Kconfig
@@ -83,6 +83,15 @@ config BRIDGE_EBT_IP
To compile it as a module, choose M here. If unsure, say N.
+config BRIDGE_EBT_IP6
+ tristate "ebt: IP6 filter support"
+ depends on BRIDGE_NF_EBTABLES && IPV6
+ help
+ This option adds the IP6 match, which allows basic IPV6 header field
+ filtering.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config BRIDGE_EBT_LIMIT
tristate "ebt: limit match support"
depends on BRIDGE_NF_EBTABLES
@@ -221,7 +230,7 @@ config BRIDGE_EBT_NFLOG
either the old LOG target, the old ULOG target or nfnetlink_log
as backend.
- This option adds the ulog watcher, that you can use in any rule
+ This option adds the nflog watcher, that you can use in any rule
in any ebtables table.
To compile it as a module, choose M here. If unsure, say N.
diff --git a/net/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile
index 83715d73a503..0718699540b0 100644
--- a/net/bridge/netfilter/Makefile
+++ b/net/bridge/netfilter/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_BRIDGE_EBT_802_3) += ebt_802_3.o
obj-$(CONFIG_BRIDGE_EBT_AMONG) += ebt_among.o
obj-$(CONFIG_BRIDGE_EBT_ARP) += ebt_arp.o
obj-$(CONFIG_BRIDGE_EBT_IP) += ebt_ip.o
+obj-$(CONFIG_BRIDGE_EBT_IP6) += ebt_ip6.o
obj-$(CONFIG_BRIDGE_EBT_LIMIT) += ebt_limit.o
obj-$(CONFIG_BRIDGE_EBT_MARK) += ebt_mark_m.o
obj-$(CONFIG_BRIDGE_EBT_PKTTYPE) += ebt_pkttype.o
diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c
new file mode 100644
index 000000000000..36efb3a75249
--- /dev/null
+++ b/net/bridge/netfilter/ebt_ip6.c
@@ -0,0 +1,144 @@
+/*
+ * ebt_ip6
+ *
+ * Authors:
+ * Manohar Castelino <manohar.r.castelino@intel.com>
+ * Kuo-Lang Tseng <kuo-lang.tseng@intel.com>
+ * Jan Engelhardt <jengelh@computergmbh.de>
+ *
+ * Summary:
+ * This is just a modification of the IPv4 code written by
+ * Bart De Schuymer <bdschuym@pandora.be>
+ * with the changes required to support IPv6
+ *
+ * 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>
+
+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)
+{
+ const struct ebt_ip6_info *info = (struct ebt_ip6_info *)data;
+ const struct ipv6hdr *ih6;
+ struct ipv6hdr _ip6h;
+ const struct tcpudphdr *pptr;
+ struct tcpudphdr _ports;
+ struct in6_addr tmp_addr;
+ int i;
+
+ ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h);
+ if (ih6 == NULL)
+ return EBT_NOMATCH;
+ if (info->bitmask & EBT_IP6_TCLASS &&
+ FWINV(info->tclass != ipv6_get_dsfield(ih6), EBT_IP6_TCLASS))
+ return EBT_NOMATCH;
+ 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;
+ 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;
+ 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;
+ if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO))
+ return EBT_NOMATCH;
+ if (!(info->bitmask & EBT_IP6_DPORT) &&
+ !(info->bitmask & EBT_IP6_SPORT))
+ return EBT_MATCH;
+ pptr = skb_header_pointer(skb, offset_ph, sizeof(_ports),
+ &_ports);
+ if (pptr == NULL)
+ return EBT_NOMATCH;
+ 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;
+ }
+ 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 EBT_MATCH;
+ }
+ return EBT_MATCH;
+}
+
+static int ebt_ip6_check(const char *tablename, unsigned int hookmask,
+ const struct ebt_entry *e, void *data, unsigned int datalen)
+{
+ struct ebt_ip6_info *info = (struct ebt_ip6_info *)data;
+
+ if (datalen != EBT_ALIGN(sizeof(struct ebt_ip6_info)))
+ return -EINVAL;
+ if (e->ethproto != htons(ETH_P_IPV6) || e->invflags & EBT_IPROTO)
+ return -EINVAL;
+ if (info->bitmask & ~EBT_IP6_MASK || info->invflags & ~EBT_IP6_MASK)
+ return -EINVAL;
+ if (info->bitmask & (EBT_IP6_DPORT | EBT_IP6_SPORT)) {
+ if (info->invflags & EBT_IP6_PROTO)
+ return -EINVAL;
+ if (info->protocol != IPPROTO_TCP &&
+ info->protocol != IPPROTO_UDP &&
+ info->protocol != IPPROTO_UDPLITE &&
+ info->protocol != IPPROTO_SCTP &&
+ info->protocol != IPPROTO_DCCP)
+ return -EINVAL;
+ }
+ if (info->bitmask & EBT_IP6_DPORT && info->dport[0] > info->dport[1])
+ return -EINVAL;
+ if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1])
+ return -EINVAL;
+ return 0;
+}
+
+static struct ebt_match filter_ip6 =
+{
+ .name = EBT_IP6_MATCH,
+ .match = ebt_filter_ip6,
+ .check = ebt_ip6_check,
+ .me = THIS_MODULE,
+};
+
+static int __init ebt_ip6_init(void)
+{
+ return ebt_register_match(&filter_ip6);
+}
+
+static void __exit ebt_ip6_fini(void)
+{
+ ebt_unregister_match(&filter_ip6);
+}
+
+module_init(ebt_ip6_init);
+module_exit(ebt_ip6_fini);
+MODULE_DESCRIPTION("Ebtables: IPv6 protocol packet match");
+MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 0b209e4aad0a..2f430d4ae911 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -18,6 +18,9 @@
#include <linux/if_arp.h>
#include <linux/spinlock.h>
#include <net/netfilter/nf_log.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
+#include <linux/in6.h>
static DEFINE_SPINLOCK(ebt_log_lock);
@@ -58,6 +61,27 @@ static void print_MAC(const unsigned char *p)
printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':');
}
+static void
+print_ports(const struct sk_buff *skb, uint8_t protocol, int offset)
+{
+ if (protocol == IPPROTO_TCP ||
+ protocol == IPPROTO_UDP ||
+ protocol == IPPROTO_UDPLITE ||
+ protocol == IPPROTO_SCTP ||
+ protocol == IPPROTO_DCCP) {
+ const struct tcpudphdr *pptr;
+ struct tcpudphdr _ports;
+
+ pptr = skb_header_pointer(skb, offset,
+ sizeof(_ports), &_ports);
+ if (pptr == NULL) {
+ printk(" INCOMPLETE TCP/UDP header");
+ return;
+ }
+ printk(" SPT=%u DPT=%u", ntohs(pptr->src), ntohs(pptr->dst));
+ }
+}
+
#define myNIPQUAD(a) a[0], a[1], a[2], a[3]
static void
ebt_log_packet(unsigned int pf, unsigned int hooknum,
@@ -95,25 +119,35 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum,
printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u, IP "
"tos=0x%02X, IP proto=%d", NIPQUAD(ih->saddr),
NIPQUAD(ih->daddr), ih->tos, ih->protocol);
- if (ih->protocol == IPPROTO_TCP ||
- ih->protocol == IPPROTO_UDP ||
- ih->protocol == IPPROTO_UDPLITE ||
- ih->protocol == IPPROTO_SCTP ||
- ih->protocol == IPPROTO_DCCP) {
- const struct tcpudphdr *pptr;
- struct tcpudphdr _ports;
-
- pptr = skb_header_pointer(skb, ih->ihl*4,
- sizeof(_ports), &_ports);
- if (pptr == NULL) {
- printk(" INCOMPLETE TCP/UDP header");
- goto out;
- }
- printk(" SPT=%u DPT=%u", ntohs(pptr->src),
- ntohs(pptr->dst));
+ print_ports(skb, ih->protocol, ih->ihl*4);
+ goto out;
+ }
+
+#if defined(CONFIG_BRIDGE_EBT_IP6) || defined(CONFIG_BRIDGE_EBT_IP6_MODULE)
+ if ((bitmask & EBT_LOG_IP6) && eth_hdr(skb)->h_proto ==
+ htons(ETH_P_IPV6)) {
+ const struct ipv6hdr *ih;
+ struct ipv6hdr _iph;
+ uint8_t nexthdr;
+ int offset_ph;
+
+ ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+ if (ih == NULL) {
+ printk(" INCOMPLETE IPv6 header");
+ goto out;
}
+ printk(" IPv6 SRC=%x:%x:%x:%x:%x:%x:%x:%x "
+ "IPv6 DST=%x:%x:%x:%x:%x:%x:%x:%x, IPv6 "
+ "priority=0x%01X, Next Header=%d", NIP6(ih->saddr),
+ NIP6(ih->daddr), ih->priority, ih->nexthdr);
+ nexthdr = ih->nexthdr;
+ offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr);
+ if (offset_ph == -1)
+ goto out;
+ print_ports(skb, nexthdr, offset_ph);
goto out;
}
+#endif
if ((bitmask & EBT_LOG_ARP) &&
((eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) ||
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index 690bc3ab186c..1a58af51a2e2 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 5b495fe2d0b6..f60c1e78e575 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);
}