Commit 060e41794e3f09f0b28f79b8d6c7ac1a9641d672

Authored by Dmitry Eremin-Solenikov
1 parent 6e10c469f0

ieee802154: support specifying hw address for created devices

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>

Showing 1 changed file with 31 additions and 0 deletions Side-by-side Diff

net/ieee802154/nl-phy.c
... ... @@ -24,6 +24,7 @@
24 24  
25 25 #include <linux/kernel.h>
26 26 #include <linux/slab.h>
  27 +#include <linux/if_arp.h>
27 28 #include <net/netlink.h>
28 29 #include <net/genetlink.h>
29 30 #include <net/wpan-phy.h>
30 31  
... ... @@ -213,12 +214,37 @@
213 214 goto nla_put_failure;
214 215 }
215 216  
  217 + if (info->attrs[IEEE802154_ATTR_HW_ADDR] &&
  218 + nla_len(info->attrs[IEEE802154_ATTR_HW_ADDR]) !=
  219 + IEEE802154_ADDR_LEN) {
  220 + rc = -EINVAL;
  221 + goto nla_put_failure;
  222 + }
  223 +
216 224 dev = phy->add_iface(phy, devname);
217 225 if (IS_ERR(dev)) {
218 226 rc = PTR_ERR(dev);
219 227 goto nla_put_failure;
220 228 }
221 229  
  230 + if (info->attrs[IEEE802154_ATTR_HW_ADDR]) {
  231 + struct sockaddr addr;
  232 +
  233 + addr.sa_family = ARPHRD_IEEE802154;
  234 + nla_memcpy(&addr.sa_data, info->attrs[IEEE802154_ATTR_HW_ADDR],
  235 + IEEE802154_ADDR_LEN);
  236 +
  237 + /*
  238 + * strangely enough, some callbacks (inetdev_event) from
  239 + * dev_set_mac_address require RTNL_LOCK
  240 + */
  241 + rtnl_lock();
  242 + rc = dev_set_mac_address(dev, &addr);
  243 + rtnl_unlock();
  244 + if (rc)
  245 + goto dev_unregister;
  246 + }
  247 +
222 248 NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy));
223 249 NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
224 250  
... ... @@ -228,6 +254,11 @@
228 254  
229 255 return ieee802154_nl_reply(msg, info);
230 256  
  257 +dev_unregister:
  258 + rtnl_lock(); /* del_iface must be called with RTNL lock */
  259 + phy->del_iface(phy, dev);
  260 + dev_put(dev);
  261 + rtnl_unlock();
231 262 nla_put_failure:
232 263 nlmsg_free(msg);
233 264 out_dev: