Commit 060e41794e3f09f0b28f79b8d6c7ac1a9641d672
1 parent
6e10c469f0
Exists in
master
and in
4 other branches
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: |