summaryrefslogtreecommitdiffstats
path: root/net/bridge/br_device.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2005-12-21 18:51:49 -0800
committerDavid S. Miller <davem@sunset.davemloft.net>2006-01-03 13:11:00 -0800
commit4505a3ef720845b5db3ddb440de13cd4800fd508 (patch)
tree2de3d2fb20d160dc1a04bdb0295882561e4244bc /net/bridge/br_device.c
parentfbe9cc4a87030d5cad5f944ffaef6af7efd119e4 (diff)
downloadlinux-4505a3ef720845b5db3ddb440de13cd4800fd508.tar.bz2
[BRIDGE]: allow setting hardware address of bridge pseudo-dev
Some people are using bridging to hide multiple machines from an ISP that restricts by MAC address. So in that case allow the bridge mac address to be set to any of the existing interfaces. I don't want to allow any arbitrary value and confuse STP. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_device.c')
-rw-r--r--net/bridge/br_device.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index f564ee99782d..f7a66abf5def 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -15,7 +15,8 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
-#include <linux/module.h>
+#include <linux/etherdevice.h>
+
#include <asm/uaccess.h>
#include "br_private.h"
@@ -82,6 +83,29 @@ static int br_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+/* Allow setting mac address of pseudo-bridge to be same as
+ * any of the bound interfaces
+ */
+static int br_set_mac_address(struct net_device *dev, void *p)
+{
+ struct net_bridge *br = netdev_priv(dev);
+ struct sockaddr *addr = p;
+ struct net_bridge_port *port;
+ int err = -EADDRNOTAVAIL;
+
+ spin_lock_bh(&br->lock);
+ list_for_each_entry(port, &br->port_list, list) {
+ if (!compare_ether_addr(port->dev->dev_addr, addr->sa_data)) {
+ br_stp_change_bridge_id(br, addr->sa_data);
+ err = 0;
+ break;
+ }
+ }
+ spin_unlock_bh(&br->lock);
+
+ return err;
+}
+
void br_dev_setup(struct net_device *dev)
{
memset(dev->dev_addr, 0, ETH_ALEN);
@@ -98,6 +122,6 @@ void br_dev_setup(struct net_device *dev)
SET_MODULE_OWNER(dev);
dev->stop = br_dev_stop;
dev->tx_queue_len = 0;
- dev->set_mac_address = NULL;
+ dev->set_mac_address = br_set_mac_address;
dev->priv_flags = IFF_EBRIDGE;
}