Commit 41dad9af authored by Roland Dreier's avatar Roland Dreier Committed by Linus Torvalds

[NET]: Fix up RTM_SETLINK handling.

parent df53773c
...@@ -480,6 +480,7 @@ extern int register_netdevice(struct net_device *dev); ...@@ -480,6 +480,7 @@ extern int register_netdevice(struct net_device *dev);
extern int unregister_netdevice(struct net_device *dev); extern int unregister_netdevice(struct net_device *dev);
extern int register_netdevice_notifier(struct notifier_block *nb); extern int register_netdevice_notifier(struct notifier_block *nb);
extern int unregister_netdevice_notifier(struct notifier_block *nb); extern int unregister_netdevice_notifier(struct notifier_block *nb);
extern int call_netdevice_notifiers(unsigned long val, void *v);
extern int dev_new_index(void); extern int dev_new_index(void);
extern struct net_device *dev_get_by_index(int ifindex); extern struct net_device *dev_get_by_index(int ifindex);
extern struct net_device *__dev_get_by_index(int ifindex); extern struct net_device *__dev_get_by_index(int ifindex);
......
...@@ -877,6 +877,18 @@ int unregister_netdevice_notifier(struct notifier_block *nb) ...@@ -877,6 +877,18 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
return notifier_chain_unregister(&netdev_chain, nb); return notifier_chain_unregister(&netdev_chain, nb);
} }
/**
* call_netdevice_notifiers - call all network notifier blocks
*
* Call all network notifier blocks. Parameters and return value
* are as for notifier_call_chain().
*/
int call_netdevice_notifiers(unsigned long val, void *v)
{
return notifier_call_chain(&netdev_chain, val, v);
}
/* /*
* Support routine. Sends outgoing frames to any network * Support routine. Sends outgoing frames to any network
* taps currently in use. * taps currently in use.
......
...@@ -234,10 +234,20 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -234,10 +234,20 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = -EINVAL; err = -EINVAL;
if (ida[IFLA_ADDRESS - 1]) { if (ida[IFLA_ADDRESS - 1]) {
if (!dev->set_mac_address) {
err = -EOPNOTSUPP;
goto out;
}
if (!netif_device_present(dev)) {
err = -ENODEV;
goto out;
}
if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len)) if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len))
goto out; goto out;
memcpy(dev->dev_addr, RTA_DATA(ida[IFLA_ADDRESS - 1]),
dev->addr_len); err = dev->set_mac_address(dev, RTA_DATA(ida[IFLA_ADDRESS - 1]));
if (err)
goto out;
} }
if (ida[IFLA_BROADCAST - 1]) { if (ida[IFLA_BROADCAST - 1]) {
...@@ -250,6 +260,9 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -250,6 +260,9 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = 0; err = 0;
out: out:
if (!err)
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
dev_put(dev); dev_put(dev);
return err; return err;
} }
......
...@@ -508,6 +508,7 @@ EXPORT_SYMBOL(tr_type_trans); ...@@ -508,6 +508,7 @@ EXPORT_SYMBOL(tr_type_trans);
/* Device callback registration */ /* Device callback registration */
EXPORT_SYMBOL(register_netdevice_notifier); EXPORT_SYMBOL(register_netdevice_notifier);
EXPORT_SYMBOL(unregister_netdevice_notifier); EXPORT_SYMBOL(unregister_netdevice_notifier);
EXPORT_SYMBOL(call_netdevice_notifiers);
/* support for loadable net drivers */ /* support for loadable net drivers */
#ifdef CONFIG_NET #ifdef CONFIG_NET
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment