aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bridge/br_device.c28
-rw-r--r--net/bridge/br_private.h1
-rw-r--r--net/bridge/br_stp_if.c3
3 files changed, 28 insertions, 4 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 @@
15 15
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/netdevice.h> 17#include <linux/netdevice.h>
18#include <linux/module.h> 18#include <linux/etherdevice.h>
19
19#include <asm/uaccess.h> 20#include <asm/uaccess.h>
20#include "br_private.h" 21#include "br_private.h"
21 22
@@ -82,6 +83,29 @@ static int br_change_mtu(struct net_device *dev, int new_mtu)
82 return 0; 83 return 0;
83} 84}
84 85
86/* Allow setting mac address of pseudo-bridge to be same as
87 * any of the bound interfaces
88 */
89static int br_set_mac_address(struct net_device *dev, void *p)
90{
91 struct net_bridge *br = netdev_priv(dev);
92 struct sockaddr *addr = p;
93 struct net_bridge_port *port;
94 int err = -EADDRNOTAVAIL;
95
96 spin_lock_bh(&br->lock);
97 list_for_each_entry(port, &br->port_list, list) {
98 if (!compare_ether_addr(port->dev->dev_addr, addr->sa_data)) {
99 br_stp_change_bridge_id(br, addr->sa_data);
100 err = 0;
101 break;
102 }
103 }
104 spin_unlock_bh(&br->lock);
105
106 return err;
107}
108
85void br_dev_setup(struct net_device *dev) 109void br_dev_setup(struct net_device *dev)
86{ 110{
87 memset(dev->dev_addr, 0, ETH_ALEN); 111 memset(dev->dev_addr, 0, ETH_ALEN);
@@ -98,6 +122,6 @@ void br_dev_setup(struct net_device *dev)
98 SET_MODULE_OWNER(dev); 122 SET_MODULE_OWNER(dev);
99 dev->stop = br_dev_stop; 123 dev->stop = br_dev_stop;
100 dev->tx_queue_len = 0; 124 dev->tx_queue_len = 0;
101 dev->set_mac_address = NULL; 125 dev->set_mac_address = br_set_mac_address;
102 dev->priv_flags = IFF_EBRIDGE; 126 dev->priv_flags = IFF_EBRIDGE;
103} 127}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index bdf95a74d8cd..2c249486476f 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -201,6 +201,7 @@ extern void br_stp_disable_bridge(struct net_bridge *br);
201extern void br_stp_enable_port(struct net_bridge_port *p); 201extern void br_stp_enable_port(struct net_bridge_port *p);
202extern void br_stp_disable_port(struct net_bridge_port *p); 202extern void br_stp_disable_port(struct net_bridge_port *p);
203extern void br_stp_recalculate_bridge_id(struct net_bridge *br); 203extern void br_stp_recalculate_bridge_id(struct net_bridge *br);
204extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a);
204extern void br_stp_set_bridge_priority(struct net_bridge *br, 205extern void br_stp_set_bridge_priority(struct net_bridge *br,
205 u16 newprio); 206 u16 newprio);
206extern void br_stp_set_port_priority(struct net_bridge_port *p, 207extern void br_stp_set_port_priority(struct net_bridge_port *p,
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index ac09b6a23523..2d2e969ae25d 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -120,8 +120,7 @@ void br_stp_disable_port(struct net_bridge_port *p)
120} 120}
121 121
122/* called under bridge lock */ 122/* called under bridge lock */
123static void br_stp_change_bridge_id(struct net_bridge *br, 123void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
124 const unsigned char *addr)
125{ 124{
126 unsigned char oldaddr[6]; 125 unsigned char oldaddr[6];
127 struct net_bridge_port *p; 126 struct net_bridge_port *p;