diff options
author | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2010-03-18 12:26:23 -0400 |
---|---|---|
committer | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2011-06-30 08:18:09 -0400 |
commit | 060e41794e3f09f0b28f79b8d6c7ac1a9641d672 (patch) | |
tree | 20aeda68993b5ee07459e339222c7d3b8f88d88b | |
parent | 6e10c469f0997a5ebaffa955d8716c59ba102a1f (diff) |
ieee802154: support specifying hw address for created devices
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
-rw-r--r-- | net/ieee802154/nl-phy.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index 02548b292b53..c64a38d57aa3 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/if_arp.h> | ||
27 | #include <net/netlink.h> | 28 | #include <net/netlink.h> |
28 | #include <net/genetlink.h> | 29 | #include <net/genetlink.h> |
29 | #include <net/wpan-phy.h> | 30 | #include <net/wpan-phy.h> |
@@ -213,12 +214,37 @@ static int ieee802154_add_iface(struct sk_buff *skb, | |||
213 | goto nla_put_failure; | 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 | dev = phy->add_iface(phy, devname); | 224 | dev = phy->add_iface(phy, devname); |
217 | if (IS_ERR(dev)) { | 225 | if (IS_ERR(dev)) { |
218 | rc = PTR_ERR(dev); | 226 | rc = PTR_ERR(dev); |
219 | goto nla_put_failure; | 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 | NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)); | 248 | NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)); |
223 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | 249 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); |
224 | 250 | ||
@@ -228,6 +254,11 @@ static int ieee802154_add_iface(struct sk_buff *skb, | |||
228 | 254 | ||
229 | return ieee802154_nl_reply(msg, info); | 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 | nla_put_failure: | 262 | nla_put_failure: |
232 | nlmsg_free(msg); | 263 | nlmsg_free(msg); |
233 | out_dev: | 264 | out_dev: |