aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-10-08 15:39:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-08 15:39:28 -0400
commite9a68707d736f4f73d7e209885d7b4c5c452b1dc (patch)
treed9f76964c77c1059483b08436ed060b702b8e25d /net/wireless
parentdd53df265b1ee7a1fbbc76bb62c3bec2383bbd44 (diff)
parent15a6321d1c0f8db561932cd99e1b9897981da71f (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts: Documentation/feature-removal-schedule.txt drivers/net/wireless/ipw2x00/ipw2200.c
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.c54
-rw-r--r--net/wireless/core.h2
-rw-r--r--net/wireless/ibss.c2
-rw-r--r--net/wireless/mlme.c54
-rw-r--r--net/wireless/nl80211.c2000
-rw-r--r--net/wireless/scan.c12
-rw-r--r--net/wireless/sme.c2
-rw-r--r--net/wireless/util.c12
-rw-r--r--net/wireless/wext-compat.c38
9 files changed, 805 insertions, 1371 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 9c21ebf9780e..1684ad91763c 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -178,26 +178,10 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
178 char *newname) 178 char *newname)
179{ 179{
180 struct cfg80211_registered_device *rdev2; 180 struct cfg80211_registered_device *rdev2;
181 int wiphy_idx, taken = -1, result, digits; 181 int result;
182 182
183 assert_cfg80211_lock(); 183 assert_cfg80211_lock();
184 184
185 /* prohibit calling the thing phy%d when %d is not its number */
186 sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
187 if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) {
188 /* count number of places needed to print wiphy_idx */
189 digits = 1;
190 while (wiphy_idx /= 10)
191 digits++;
192 /*
193 * deny the name if it is phy<idx> where <idx> is printed
194 * without leading zeroes. taken == strlen(newname) here
195 */
196 if (taken == strlen(PHY_NAME) + digits)
197 return -EINVAL;
198 }
199
200
201 /* Ignore nop renames */ 185 /* Ignore nop renames */
202 if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0) 186 if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0)
203 return 0; 187 return 0;
@@ -205,7 +189,7 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
205 /* Ensure another device does not already have this name. */ 189 /* Ensure another device does not already have this name. */
206 list_for_each_entry(rdev2, &cfg80211_rdev_list, list) 190 list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
207 if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0) 191 if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0)
208 return -EINVAL; 192 return -EEXIST;
209 193
210 result = device_rename(&rdev->wiphy.dev, newname); 194 result = device_rename(&rdev->wiphy.dev, newname);
211 if (result) 195 if (result)
@@ -320,9 +304,11 @@ static void cfg80211_event_work(struct work_struct *work)
320struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) 304struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
321{ 305{
322 static int wiphy_counter; 306 static int wiphy_counter;
323 307 int i;
324 struct cfg80211_registered_device *rdev; 308 struct cfg80211_registered_device *rdev, *rdev2;
325 int alloc_size; 309 int alloc_size;
310 char nname[IFNAMSIZ + 1];
311 bool found = false;
326 312
327 WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key)); 313 WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key));
328 WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc)); 314 WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc));
@@ -346,16 +332,36 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
346 332
347 if (unlikely(!wiphy_idx_valid(rdev->wiphy_idx))) { 333 if (unlikely(!wiphy_idx_valid(rdev->wiphy_idx))) {
348 wiphy_counter--; 334 wiphy_counter--;
335 goto too_many_devs;
336 }
337
338 /* 64k wiphy devices is enough for anyone! */
339 for (i = 0; i < 0xFFFF; i++) {
340 found = false;
341 snprintf(nname, sizeof(nname)-1, PHY_NAME "%d", i);
342 nname[sizeof(nname)-1] = 0;
343 list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
344 if (strcmp(nname, dev_name(&rdev2->wiphy.dev)) == 0) {
345 found = true;
346 break;
347 }
348
349 if (!found)
350 break;
351 }
352
353 if (unlikely(found)) {
354too_many_devs:
349 mutex_unlock(&cfg80211_mutex); 355 mutex_unlock(&cfg80211_mutex);
350 /* ugh, wrapped! */ 356 /* ugh, too many devices already! */
351 kfree(rdev); 357 kfree(rdev);
352 return NULL; 358 return NULL;
353 } 359 }
354 360
355 mutex_unlock(&cfg80211_mutex);
356
357 /* give it a proper name */ 361 /* give it a proper name */
358 dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); 362 dev_set_name(&rdev->wiphy.dev, "%s", nname);
363
364 mutex_unlock(&cfg80211_mutex);
359 365
360 mutex_init(&rdev->mtx); 366 mutex_init(&rdev->mtx);
361 mutex_init(&rdev->devlist_mtx); 367 mutex_init(&rdev->devlist_mtx);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 5d89310b3587..6583cca0e2ee 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -375,7 +375,7 @@ bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev);
375/* internal helpers */ 375/* internal helpers */
376int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, 376int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
377 struct key_params *params, int key_idx, 377 struct key_params *params, int key_idx,
378 const u8 *mac_addr); 378 bool pairwise, const u8 *mac_addr);
379void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, 379void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
380 size_t ie_len, u16 reason, bool from_ap); 380 size_t ie_len, u16 reason, bool from_ap);
381void cfg80211_sme_scan_done(struct net_device *dev); 381void cfg80211_sme_scan_done(struct net_device *dev);
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 8cb6e08373b9..f33fbb79437c 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -160,7 +160,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
160 */ 160 */
161 if (rdev->ops->del_key) 161 if (rdev->ops->del_key)
162 for (i = 0; i < 6; i++) 162 for (i = 0; i < 6; i++)
163 rdev->ops->del_key(wdev->wiphy, dev, i, NULL); 163 rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
164 164
165 if (wdev->current_bss) { 165 if (wdev->current_bss) {
166 cfg80211_unhold_bss(wdev->current_bss); 166 cfg80211_unhold_bss(wdev->current_bss);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 46f371160896..caf11a427507 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -876,21 +876,53 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
876 876
877 if (ieee80211_is_action(mgmt->frame_control) && 877 if (ieee80211_is_action(mgmt->frame_control) &&
878 mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { 878 mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
879 /* Verify that we are associated with the destination AP */ 879 int err = 0;
880
880 wdev_lock(wdev); 881 wdev_lock(wdev);
881 882
882 if (!wdev->current_bss || 883 switch (wdev->iftype) {
883 memcmp(wdev->current_bss->pub.bssid, mgmt->bssid, 884 case NL80211_IFTYPE_ADHOC:
884 ETH_ALEN) != 0 || 885 case NL80211_IFTYPE_STATION:
885 ((wdev->iftype == NL80211_IFTYPE_STATION || 886 case NL80211_IFTYPE_P2P_CLIENT:
886 wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) && 887 if (!wdev->current_bss) {
887 memcmp(wdev->current_bss->pub.bssid, mgmt->da, 888 err = -ENOTCONN;
888 ETH_ALEN) != 0)) { 889 break;
889 wdev_unlock(wdev); 890 }
890 return -ENOTCONN; 891
891 } 892 if (memcmp(wdev->current_bss->pub.bssid,
893 mgmt->bssid, ETH_ALEN)) {
894 err = -ENOTCONN;
895 break;
896 }
897
898 /*
899 * check for IBSS DA must be done by driver as
900 * cfg80211 doesn't track the stations
901 */
902 if (wdev->iftype == NL80211_IFTYPE_ADHOC)
903 break;
892 904
905 /* for station, check that DA is the AP */
906 if (memcmp(wdev->current_bss->pub.bssid,
907 mgmt->da, ETH_ALEN)) {
908 err = -ENOTCONN;
909 break;
910 }
911 break;
912 case NL80211_IFTYPE_AP:
913 case NL80211_IFTYPE_P2P_GO:
914 case NL80211_IFTYPE_AP_VLAN:
915 if (memcmp(mgmt->bssid, dev->dev_addr, ETH_ALEN))
916 err = -EINVAL;
917 break;
918 default:
919 err = -EOPNOTSUPP;
920 break;
921 }
893 wdev_unlock(wdev); 922 wdev_unlock(wdev);
923
924 if (err)
925 return err;
894 } 926 }
895 927
896 if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0) 928 if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9c84825803ce..882dc921103b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -23,6 +23,11 @@
23#include "nl80211.h" 23#include "nl80211.h"
24#include "reg.h" 24#include "reg.h"
25 25
26static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
27 struct genl_info *info);
28static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
29 struct genl_info *info);
30
26/* the netlink family */ 31/* the netlink family */
27static struct genl_family nl80211_fam = { 32static struct genl_family nl80211_fam = {
28 .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ 33 .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
@@ -31,6 +36,8 @@ static struct genl_family nl80211_fam = {
31 .version = 1, /* no particular meaning now */ 36 .version = 1, /* no particular meaning now */
32 .maxattr = NL80211_ATTR_MAX, 37 .maxattr = NL80211_ATTR_MAX,
33 .netnsok = true, 38 .netnsok = true,
39 .pre_doit = nl80211_pre_doit,
40 .post_doit = nl80211_post_doit,
34}; 41};
35 42
36/* internal helper: get rdev and dev */ 43/* internal helper: get rdev and dev */
@@ -86,6 +93,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
86 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, 93 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
87 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, 94 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
88 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, 95 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
96 [NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 },
89 97
90 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, 98 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
91 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, 99 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
@@ -161,7 +169,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
161 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, 169 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
162}; 170};
163 171
164/* policy for the attributes */ 172/* policy for the key attributes */
165static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { 173static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
166 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN }, 174 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
167 [NL80211_KEY_IDX] = { .type = NLA_U8 }, 175 [NL80211_KEY_IDX] = { .type = NLA_U8 },
@@ -169,6 +177,7 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
169 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, 177 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
170 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, 178 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
171 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, 179 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
180 [NL80211_KEY_TYPE] = { .type = NLA_U32 },
172}; 181};
173 182
174/* ifidx get helper */ 183/* ifidx get helper */
@@ -191,6 +200,47 @@ static int nl80211_get_ifidx(struct netlink_callback *cb)
191 return res; 200 return res;
192} 201}
193 202
203static int nl80211_prepare_netdev_dump(struct sk_buff *skb,
204 struct netlink_callback *cb,
205 struct cfg80211_registered_device **rdev,
206 struct net_device **dev)
207{
208 int ifidx = cb->args[0];
209 int err;
210
211 if (!ifidx)
212 ifidx = nl80211_get_ifidx(cb);
213 if (ifidx < 0)
214 return ifidx;
215
216 cb->args[0] = ifidx;
217
218 rtnl_lock();
219
220 *dev = __dev_get_by_index(sock_net(skb->sk), ifidx);
221 if (!*dev) {
222 err = -ENODEV;
223 goto out_rtnl;
224 }
225
226 *rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
227 if (IS_ERR(dev)) {
228 err = PTR_ERR(dev);
229 goto out_rtnl;
230 }
231
232 return 0;
233 out_rtnl:
234 rtnl_unlock();
235 return err;
236}
237
238static void nl80211_finish_netdev_dump(struct cfg80211_registered_device *rdev)
239{
240 cfg80211_unlock_rdev(rdev);
241 rtnl_unlock();
242}
243
194/* IE validation */ 244/* IE validation */
195static bool is_valid_ie_attr(const struct nlattr *attr) 245static bool is_valid_ie_attr(const struct nlattr *attr)
196{ 246{
@@ -258,6 +308,7 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
258struct key_parse { 308struct key_parse {
259 struct key_params p; 309 struct key_params p;
260 int idx; 310 int idx;
311 int type;
261 bool def, defmgmt; 312 bool def, defmgmt;
262}; 313};
263 314
@@ -288,6 +339,12 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
288 if (tb[NL80211_KEY_CIPHER]) 339 if (tb[NL80211_KEY_CIPHER])
289 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]); 340 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
290 341
342 if (tb[NL80211_KEY_TYPE]) {
343 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
344 if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
345 return -EINVAL;
346 }
347
291 return 0; 348 return 0;
292} 349}
293 350
@@ -312,6 +369,12 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
312 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; 369 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
313 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; 370 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
314 371
372 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
373 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
374 if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
375 return -EINVAL;
376 }
377
315 return 0; 378 return 0;
316} 379}
317 380
@@ -321,6 +384,7 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
321 384
322 memset(k, 0, sizeof(*k)); 385 memset(k, 0, sizeof(*k));
323 k->idx = -1; 386 k->idx = -1;
387 k->type = -1;
324 388
325 if (info->attrs[NL80211_ATTR_KEY]) 389 if (info->attrs[NL80211_ATTR_KEY])
326 err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k); 390 err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k);
@@ -385,7 +449,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
385 } else if (parse.defmgmt) 449 } else if (parse.defmgmt)
386 goto error; 450 goto error;
387 err = cfg80211_validate_key_settings(rdev, &parse.p, 451 err = cfg80211_validate_key_settings(rdev, &parse.p,
388 parse.idx, NULL); 452 parse.idx, false, NULL);
389 if (err) 453 if (err)
390 goto error; 454 goto error;
391 result->params[parse.idx].cipher = parse.p.cipher; 455 result->params[parse.idx].cipher = parse.p.cipher;
@@ -404,9 +468,6 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
404{ 468{
405 ASSERT_WDEV_LOCK(wdev); 469 ASSERT_WDEV_LOCK(wdev);
406 470
407 if (!netif_running(wdev->netdev))
408 return -ENETDOWN;
409
410 switch (wdev->iftype) { 471 switch (wdev->iftype) {
411 case NL80211_IFTYPE_AP: 472 case NL80211_IFTYPE_AP:
412 case NL80211_IFTYPE_AP_VLAN: 473 case NL80211_IFTYPE_AP_VLAN:
@@ -471,6 +532,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
471 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, 532 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
472 dev->wiphy.max_scan_ie_len); 533 dev->wiphy.max_scan_ie_len);
473 534
535 if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)
536 NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN);
537
474 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, 538 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,
475 sizeof(u32) * dev->wiphy.n_cipher_suites, 539 sizeof(u32) * dev->wiphy.n_cipher_suites,
476 dev->wiphy.cipher_suites); 540 dev->wiphy.cipher_suites);
@@ -603,6 +667,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
603 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); 667 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
604 } 668 }
605 CMD(set_channel, SET_CHANNEL); 669 CMD(set_channel, SET_CHANNEL);
670 CMD(set_wds_peer, SET_WDS_PEER);
606 671
607#undef CMD 672#undef CMD
608 673
@@ -703,28 +768,18 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
703static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) 768static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
704{ 769{
705 struct sk_buff *msg; 770 struct sk_buff *msg;
706 struct cfg80211_registered_device *dev; 771 struct cfg80211_registered_device *dev = info->user_ptr[0];
707
708 dev = cfg80211_get_dev_from_info(info);
709 if (IS_ERR(dev))
710 return PTR_ERR(dev);
711 772
712 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 773 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
713 if (!msg) 774 if (!msg)
714 goto out_err; 775 return -ENOMEM;
715
716 if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
717 goto out_free;
718 776
719 cfg80211_unlock_rdev(dev); 777 if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0) {
778 nlmsg_free(msg);
779 return -ENOBUFS;
780 }
720 781
721 return genlmsg_reply(msg, info); 782 return genlmsg_reply(msg, info);
722
723 out_free:
724 nlmsg_free(msg);
725 out_err:
726 cfg80211_unlock_rdev(dev);
727 return -ENOBUFS;
728} 783}
729 784
730static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { 785static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
@@ -813,24 +868,36 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
813 868
814static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info) 869static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
815{ 870{
816 struct cfg80211_registered_device *rdev; 871 struct cfg80211_registered_device *rdev = info->user_ptr[0];
817 struct net_device *netdev; 872 struct net_device *netdev = info->user_ptr[1];
818 int result;
819 873
820 rtnl_lock(); 874 return __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info);
875}
821 876
822 result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev); 877static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info)
823 if (result) 878{
824 goto unlock; 879 struct cfg80211_registered_device *rdev = info->user_ptr[0];
880 struct net_device *dev = info->user_ptr[1];
881 struct wireless_dev *wdev = dev->ieee80211_ptr;
882 const u8 *bssid;
825 883
826 result = __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info); 884 if (!info->attrs[NL80211_ATTR_MAC])
885 return -EINVAL;
827 886
828 unlock: 887 if (netif_running(dev))
829 rtnl_unlock(); 888 return -EBUSY;
830 889
831 return result; 890 if (!rdev->ops->set_wds_peer)
891 return -EOPNOTSUPP;
892
893 if (wdev->iftype != NL80211_IFTYPE_WDS)
894 return -EOPNOTSUPP;
895
896 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
897 return rdev->ops->set_wds_peer(wdev->wiphy, dev, bssid);
832} 898}
833 899
900
834static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) 901static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
835{ 902{
836 struct cfg80211_registered_device *rdev; 903 struct cfg80211_registered_device *rdev;
@@ -843,8 +910,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
843 u32 frag_threshold = 0, rts_threshold = 0; 910 u32 frag_threshold = 0, rts_threshold = 0;
844 u8 coverage_class = 0; 911 u8 coverage_class = 0;
845 912
846 rtnl_lock();
847
848 /* 913 /*
849 * Try to find the wiphy and netdev. Normally this 914 * Try to find the wiphy and netdev. Normally this
850 * function shouldn't need the netdev, but this is 915 * function shouldn't need the netdev, but this is
@@ -871,8 +936,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
871 rdev = __cfg80211_rdev_from_info(info); 936 rdev = __cfg80211_rdev_from_info(info);
872 if (IS_ERR(rdev)) { 937 if (IS_ERR(rdev)) {
873 mutex_unlock(&cfg80211_mutex); 938 mutex_unlock(&cfg80211_mutex);
874 result = PTR_ERR(rdev); 939 return PTR_ERR(rdev);
875 goto unlock;
876 } 940 }
877 wdev = NULL; 941 wdev = NULL;
878 netdev = NULL; 942 netdev = NULL;
@@ -1054,8 +1118,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
1054 mutex_unlock(&rdev->mtx); 1118 mutex_unlock(&rdev->mtx);
1055 if (netdev) 1119 if (netdev)
1056 dev_put(netdev); 1120 dev_put(netdev);
1057 unlock:
1058 rtnl_unlock();
1059 return result; 1121 return result;
1060} 1122}
1061 1123
@@ -1135,33 +1197,20 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
1135static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) 1197static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
1136{ 1198{
1137 struct sk_buff *msg; 1199 struct sk_buff *msg;
1138 struct cfg80211_registered_device *dev; 1200 struct cfg80211_registered_device *dev = info->user_ptr[0];
1139 struct net_device *netdev; 1201 struct net_device *netdev = info->user_ptr[1];
1140 int err;
1141
1142 err = get_rdev_dev_by_info_ifindex(info, &dev, &netdev);
1143 if (err)
1144 return err;
1145 1202
1146 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1203 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1147 if (!msg) 1204 if (!msg)
1148 goto out_err; 1205 return -ENOMEM;
1149 1206
1150 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, 1207 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0,
1151 dev, netdev) < 0) 1208 dev, netdev) < 0) {
1152 goto out_free; 1209 nlmsg_free(msg);
1153 1210 return -ENOBUFS;
1154 dev_put(netdev); 1211 }
1155 cfg80211_unlock_rdev(dev);
1156 1212
1157 return genlmsg_reply(msg, info); 1213 return genlmsg_reply(msg, info);
1158
1159 out_free:
1160 nlmsg_free(msg);
1161 out_err:
1162 dev_put(netdev);
1163 cfg80211_unlock_rdev(dev);
1164 return -ENOBUFS;
1165} 1214}
1166 1215
1167static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = { 1216static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
@@ -1221,39 +1270,29 @@ static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
1221 1270
1222static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) 1271static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1223{ 1272{
1224 struct cfg80211_registered_device *rdev; 1273 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1225 struct vif_params params; 1274 struct vif_params params;
1226 int err; 1275 int err;
1227 enum nl80211_iftype otype, ntype; 1276 enum nl80211_iftype otype, ntype;
1228 struct net_device *dev; 1277 struct net_device *dev = info->user_ptr[1];
1229 u32 _flags, *flags = NULL; 1278 u32 _flags, *flags = NULL;
1230 bool change = false; 1279 bool change = false;
1231 1280
1232 memset(&params, 0, sizeof(params)); 1281 memset(&params, 0, sizeof(params));
1233 1282
1234 rtnl_lock();
1235
1236 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1237 if (err)
1238 goto unlock_rtnl;
1239
1240 otype = ntype = dev->ieee80211_ptr->iftype; 1283 otype = ntype = dev->ieee80211_ptr->iftype;
1241 1284
1242 if (info->attrs[NL80211_ATTR_IFTYPE]) { 1285 if (info->attrs[NL80211_ATTR_IFTYPE]) {
1243 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); 1286 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
1244 if (otype != ntype) 1287 if (otype != ntype)
1245 change = true; 1288 change = true;
1246 if (ntype > NL80211_IFTYPE_MAX) { 1289 if (ntype > NL80211_IFTYPE_MAX)
1247 err = -EINVAL; 1290 return -EINVAL;
1248 goto unlock;
1249 }
1250 } 1291 }
1251 1292
1252 if (info->attrs[NL80211_ATTR_MESH_ID]) { 1293 if (info->attrs[NL80211_ATTR_MESH_ID]) {
1253 if (ntype != NL80211_IFTYPE_MESH_POINT) { 1294 if (ntype != NL80211_IFTYPE_MESH_POINT)
1254 err = -EINVAL; 1295 return -EINVAL;
1255 goto unlock;
1256 }
1257 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); 1296 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
1258 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); 1297 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
1259 change = true; 1298 change = true;
@@ -1264,20 +1303,18 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1264 change = true; 1303 change = true;
1265 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype); 1304 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
1266 if (err) 1305 if (err)
1267 goto unlock; 1306 return err;
1268 } else { 1307 } else {
1269 params.use_4addr = -1; 1308 params.use_4addr = -1;
1270 } 1309 }
1271 1310
1272 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { 1311 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
1273 if (ntype != NL80211_IFTYPE_MONITOR) { 1312 if (ntype != NL80211_IFTYPE_MONITOR)
1274 err = -EINVAL; 1313 return -EINVAL;
1275 goto unlock;
1276 }
1277 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], 1314 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
1278 &_flags); 1315 &_flags);
1279 if (err) 1316 if (err)
1280 goto unlock; 1317 return err;
1281 1318
1282 flags = &_flags; 1319 flags = &_flags;
1283 change = true; 1320 change = true;
@@ -1291,17 +1328,12 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1291 if (!err && params.use_4addr != -1) 1328 if (!err && params.use_4addr != -1)
1292 dev->ieee80211_ptr->use_4addr = params.use_4addr; 1329 dev->ieee80211_ptr->use_4addr = params.use_4addr;
1293 1330
1294 unlock:
1295 dev_put(dev);
1296 cfg80211_unlock_rdev(rdev);
1297 unlock_rtnl:
1298 rtnl_unlock();
1299 return err; 1331 return err;
1300} 1332}
1301 1333
1302static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) 1334static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1303{ 1335{
1304 struct cfg80211_registered_device *rdev; 1336 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1305 struct vif_params params; 1337 struct vif_params params;
1306 int err; 1338 int err;
1307 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; 1339 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
@@ -1318,19 +1350,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1318 return -EINVAL; 1350 return -EINVAL;
1319 } 1351 }
1320 1352
1321 rtnl_lock();
1322
1323 rdev = cfg80211_get_dev_from_info(info);
1324 if (IS_ERR(rdev)) {
1325 err = PTR_ERR(rdev);
1326 goto unlock_rtnl;
1327 }
1328
1329 if (!rdev->ops->add_virtual_intf || 1353 if (!rdev->ops->add_virtual_intf ||
1330 !(rdev->wiphy.interface_modes & (1 << type))) { 1354 !(rdev->wiphy.interface_modes & (1 << type)))
1331 err = -EOPNOTSUPP; 1355 return -EOPNOTSUPP;
1332 goto unlock;
1333 }
1334 1356
1335 if (type == NL80211_IFTYPE_MESH_POINT && 1357 if (type == NL80211_IFTYPE_MESH_POINT &&
1336 info->attrs[NL80211_ATTR_MESH_ID]) { 1358 info->attrs[NL80211_ATTR_MESH_ID]) {
@@ -1342,7 +1364,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1342 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); 1364 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1343 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type); 1365 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
1344 if (err) 1366 if (err)
1345 goto unlock; 1367 return err;
1346 } 1368 }
1347 1369
1348 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? 1370 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
@@ -1352,38 +1374,18 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1352 nla_data(info->attrs[NL80211_ATTR_IFNAME]), 1374 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
1353 type, err ? NULL : &flags, &params); 1375 type, err ? NULL : &flags, &params);
1354 1376
1355 unlock:
1356 cfg80211_unlock_rdev(rdev);
1357 unlock_rtnl:
1358 rtnl_unlock();
1359 return err; 1377 return err;
1360} 1378}
1361 1379
1362static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) 1380static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
1363{ 1381{
1364 struct cfg80211_registered_device *rdev; 1382 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1365 int err; 1383 struct net_device *dev = info->user_ptr[1];
1366 struct net_device *dev;
1367
1368 rtnl_lock();
1369
1370 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1371 if (err)
1372 goto unlock_rtnl;
1373 1384
1374 if (!rdev->ops->del_virtual_intf) { 1385 if (!rdev->ops->del_virtual_intf)
1375 err = -EOPNOTSUPP; 1386 return -EOPNOTSUPP;
1376 goto out;
1377 }
1378
1379 err = rdev->ops->del_virtual_intf(&rdev->wiphy, dev);
1380 1387
1381 out: 1388 return rdev->ops->del_virtual_intf(&rdev->wiphy, dev);
1382 cfg80211_unlock_rdev(rdev);
1383 dev_put(dev);
1384 unlock_rtnl:
1385 rtnl_unlock();
1386 return err;
1387} 1389}
1388 1390
1389struct get_key_cookie { 1391struct get_key_cookie {
@@ -1436,11 +1438,12 @@ static void get_key_callback(void *c, struct key_params *params)
1436 1438
1437static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) 1439static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1438{ 1440{
1439 struct cfg80211_registered_device *rdev; 1441 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1440 int err; 1442 int err;
1441 struct net_device *dev; 1443 struct net_device *dev = info->user_ptr[1];
1442 u8 key_idx = 0; 1444 u8 key_idx = 0;
1443 u8 *mac_addr = NULL; 1445 const u8 *mac_addr = NULL;
1446 bool pairwise;
1444 struct get_key_cookie cookie = { 1447 struct get_key_cookie cookie = {
1445 .error = 0, 1448 .error = 0,
1446 }; 1449 };
@@ -1456,30 +1459,28 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1456 if (info->attrs[NL80211_ATTR_MAC]) 1459 if (info->attrs[NL80211_ATTR_MAC])
1457 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1460 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1458 1461
1459 rtnl_lock(); 1462 pairwise = !!mac_addr;
1460 1463 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
1461 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); 1464 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
1462 if (err) 1465 if (kt >= NUM_NL80211_KEYTYPES)
1463 goto unlock_rtnl; 1466 return -EINVAL;
1464 1467 if (kt != NL80211_KEYTYPE_GROUP &&
1465 if (!rdev->ops->get_key) { 1468 kt != NL80211_KEYTYPE_PAIRWISE)
1466 err = -EOPNOTSUPP; 1469 return -EINVAL;
1467 goto out; 1470 pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
1468 } 1471 }
1469 1472
1473 if (!rdev->ops->get_key)
1474 return -EOPNOTSUPP;
1475
1470 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1476 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1471 if (!msg) { 1477 if (!msg)
1472 err = -ENOMEM; 1478 return -ENOMEM;
1473 goto out;
1474 }
1475 1479
1476 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 1480 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
1477 NL80211_CMD_NEW_KEY); 1481 NL80211_CMD_NEW_KEY);
1478 1482 if (IS_ERR(hdr))
1479 if (IS_ERR(hdr)) { 1483 return PTR_ERR(hdr);
1480 err = PTR_ERR(hdr);
1481 goto free_msg;
1482 }
1483 1484
1484 cookie.msg = msg; 1485 cookie.msg = msg;
1485 cookie.idx = key_idx; 1486 cookie.idx = key_idx;
@@ -1489,8 +1490,12 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1489 if (mac_addr) 1490 if (mac_addr)
1490 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); 1491 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
1491 1492
1492 err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, mac_addr, 1493 if (pairwise && mac_addr &&
1493 &cookie, get_key_callback); 1494 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
1495 return -ENOENT;
1496
1497 err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, pairwise,
1498 mac_addr, &cookie, get_key_callback);
1494 1499
1495 if (err) 1500 if (err)
1496 goto free_msg; 1501 goto free_msg;
@@ -1499,28 +1504,21 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1499 goto nla_put_failure; 1504 goto nla_put_failure;
1500 1505
1501 genlmsg_end(msg, hdr); 1506 genlmsg_end(msg, hdr);
1502 err = genlmsg_reply(msg, info); 1507 return genlmsg_reply(msg, info);
1503 goto out;
1504 1508
1505 nla_put_failure: 1509 nla_put_failure:
1506 err = -ENOBUFS; 1510 err = -ENOBUFS;
1507 free_msg: 1511 free_msg:
1508 nlmsg_free(msg); 1512 nlmsg_free(msg);
1509 out:
1510 cfg80211_unlock_rdev(rdev);
1511 dev_put(dev);
1512 unlock_rtnl:
1513 rtnl_unlock();
1514
1515 return err; 1513 return err;
1516} 1514}
1517 1515
1518static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) 1516static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1519{ 1517{
1520 struct cfg80211_registered_device *rdev; 1518 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1521 struct key_parse key; 1519 struct key_parse key;
1522 int err; 1520 int err;
1523 struct net_device *dev; 1521 struct net_device *dev = info->user_ptr[1];
1524 int (*func)(struct wiphy *wiphy, struct net_device *netdev, 1522 int (*func)(struct wiphy *wiphy, struct net_device *netdev,
1525 u8 key_index); 1523 u8 key_index);
1526 1524
@@ -1535,21 +1533,13 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1535 if (!key.def && !key.defmgmt) 1533 if (!key.def && !key.defmgmt)
1536 return -EINVAL; 1534 return -EINVAL;
1537 1535
1538 rtnl_lock();
1539
1540 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1541 if (err)
1542 goto unlock_rtnl;
1543
1544 if (key.def) 1536 if (key.def)
1545 func = rdev->ops->set_default_key; 1537 func = rdev->ops->set_default_key;
1546 else 1538 else
1547 func = rdev->ops->set_default_mgmt_key; 1539 func = rdev->ops->set_default_mgmt_key;
1548 1540
1549 if (!func) { 1541 if (!func)
1550 err = -EOPNOTSUPP; 1542 return -EOPNOTSUPP;
1551 goto out;
1552 }
1553 1543
1554 wdev_lock(dev->ieee80211_ptr); 1544 wdev_lock(dev->ieee80211_ptr);
1555 err = nl80211_key_allowed(dev->ieee80211_ptr); 1545 err = nl80211_key_allowed(dev->ieee80211_ptr);
@@ -1566,23 +1556,16 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1566#endif 1556#endif
1567 wdev_unlock(dev->ieee80211_ptr); 1557 wdev_unlock(dev->ieee80211_ptr);
1568 1558
1569 out:
1570 cfg80211_unlock_rdev(rdev);
1571 dev_put(dev);
1572
1573 unlock_rtnl:
1574 rtnl_unlock();
1575
1576 return err; 1559 return err;
1577} 1560}
1578 1561
1579static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) 1562static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1580{ 1563{
1581 struct cfg80211_registered_device *rdev; 1564 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1582 int err; 1565 int err;
1583 struct net_device *dev; 1566 struct net_device *dev = info->user_ptr[1];
1584 struct key_parse key; 1567 struct key_parse key;
1585 u8 *mac_addr = NULL; 1568 const u8 *mac_addr = NULL;
1586 1569
1587 err = nl80211_parse_key(info, &key); 1570 err = nl80211_parse_key(info, &key);
1588 if (err) 1571 if (err)
@@ -1594,43 +1577,42 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1594 if (info->attrs[NL80211_ATTR_MAC]) 1577 if (info->attrs[NL80211_ATTR_MAC])
1595 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1578 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1596 1579
1597 rtnl_lock(); 1580 if (key.type == -1) {
1581 if (mac_addr)
1582 key.type = NL80211_KEYTYPE_PAIRWISE;
1583 else
1584 key.type = NL80211_KEYTYPE_GROUP;
1585 }
1598 1586
1599 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); 1587 /* for now */
1600 if (err) 1588 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
1601 goto unlock_rtnl; 1589 key.type != NL80211_KEYTYPE_GROUP)
1590 return -EINVAL;
1602 1591
1603 if (!rdev->ops->add_key) { 1592 if (!rdev->ops->add_key)
1604 err = -EOPNOTSUPP; 1593 return -EOPNOTSUPP;
1605 goto out;
1606 }
1607 1594
1608 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr)) { 1595 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
1609 err = -EINVAL; 1596 key.type == NL80211_KEYTYPE_PAIRWISE,
1610 goto out; 1597 mac_addr))
1611 } 1598 return -EINVAL;
1612 1599
1613 wdev_lock(dev->ieee80211_ptr); 1600 wdev_lock(dev->ieee80211_ptr);
1614 err = nl80211_key_allowed(dev->ieee80211_ptr); 1601 err = nl80211_key_allowed(dev->ieee80211_ptr);
1615 if (!err) 1602 if (!err)
1616 err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx, 1603 err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx,
1604 key.type == NL80211_KEYTYPE_PAIRWISE,
1617 mac_addr, &key.p); 1605 mac_addr, &key.p);
1618 wdev_unlock(dev->ieee80211_ptr); 1606 wdev_unlock(dev->ieee80211_ptr);
1619 1607
1620 out:
1621 cfg80211_unlock_rdev(rdev);
1622 dev_put(dev);
1623 unlock_rtnl:
1624 rtnl_unlock();
1625
1626 return err; 1608 return err;
1627} 1609}
1628 1610
1629static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) 1611static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1630{ 1612{
1631 struct cfg80211_registered_device *rdev; 1613 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1632 int err; 1614 int err;
1633 struct net_device *dev; 1615 struct net_device *dev = info->user_ptr[1];
1634 u8 *mac_addr = NULL; 1616 u8 *mac_addr = NULL;
1635 struct key_parse key; 1617 struct key_parse key;
1636 1618
@@ -1641,21 +1623,32 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1641 if (info->attrs[NL80211_ATTR_MAC]) 1623 if (info->attrs[NL80211_ATTR_MAC])
1642 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1624 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1643 1625
1644 rtnl_lock(); 1626 if (key.type == -1) {
1627 if (mac_addr)
1628 key.type = NL80211_KEYTYPE_PAIRWISE;
1629 else
1630 key.type = NL80211_KEYTYPE_GROUP;
1631 }
1645 1632
1646 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); 1633 /* for now */
1647 if (err) 1634 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
1648 goto unlock_rtnl; 1635 key.type != NL80211_KEYTYPE_GROUP)
1636 return -EINVAL;
1649 1637
1650 if (!rdev->ops->del_key) { 1638 if (!rdev->ops->del_key)
1651 err = -EOPNOTSUPP; 1639 return -EOPNOTSUPP;
1652 goto out;
1653 }
1654 1640
1655 wdev_lock(dev->ieee80211_ptr); 1641 wdev_lock(dev->ieee80211_ptr);
1656 err = nl80211_key_allowed(dev->ieee80211_ptr); 1642 err = nl80211_key_allowed(dev->ieee80211_ptr);
1643
1644 if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr &&
1645 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
1646 err = -ENOENT;
1647
1657 if (!err) 1648 if (!err)
1658 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr); 1649 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx,
1650 key.type == NL80211_KEYTYPE_PAIRWISE,
1651 mac_addr);
1659 1652
1660#ifdef CONFIG_CFG80211_WEXT 1653#ifdef CONFIG_CFG80211_WEXT
1661 if (!err) { 1654 if (!err) {
@@ -1667,13 +1660,6 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1667#endif 1660#endif
1668 wdev_unlock(dev->ieee80211_ptr); 1661 wdev_unlock(dev->ieee80211_ptr);
1669 1662
1670 out:
1671 cfg80211_unlock_rdev(rdev);
1672 dev_put(dev);
1673
1674 unlock_rtnl:
1675 rtnl_unlock();
1676
1677 return err; 1663 return err;
1678} 1664}
1679 1665
@@ -1681,36 +1667,25 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1681{ 1667{
1682 int (*call)(struct wiphy *wiphy, struct net_device *dev, 1668 int (*call)(struct wiphy *wiphy, struct net_device *dev,
1683 struct beacon_parameters *info); 1669 struct beacon_parameters *info);
1684 struct cfg80211_registered_device *rdev; 1670 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1685 int err; 1671 struct net_device *dev = info->user_ptr[1];
1686 struct net_device *dev;
1687 struct beacon_parameters params; 1672 struct beacon_parameters params;
1688 int haveinfo = 0; 1673 int haveinfo = 0;
1689 1674
1690 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) 1675 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]))
1691 return -EINVAL; 1676 return -EINVAL;
1692 1677
1693 rtnl_lock();
1694
1695 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1696 if (err)
1697 goto unlock_rtnl;
1698
1699 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 1678 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
1700 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 1679 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
1701 err = -EOPNOTSUPP; 1680 return -EOPNOTSUPP;
1702 goto out;
1703 }
1704 1681
1705 switch (info->genlhdr->cmd) { 1682 switch (info->genlhdr->cmd) {
1706 case NL80211_CMD_NEW_BEACON: 1683 case NL80211_CMD_NEW_BEACON:
1707 /* these are required for NEW_BEACON */ 1684 /* these are required for NEW_BEACON */
1708 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || 1685 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
1709 !info->attrs[NL80211_ATTR_DTIM_PERIOD] || 1686 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
1710 !info->attrs[NL80211_ATTR_BEACON_HEAD]) { 1687 !info->attrs[NL80211_ATTR_BEACON_HEAD])
1711 err = -EINVAL; 1688 return -EINVAL;
1712 goto out;
1713 }
1714 1689
1715 call = rdev->ops->add_beacon; 1690 call = rdev->ops->add_beacon;
1716 break; 1691 break;
@@ -1719,14 +1694,11 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1719 break; 1694 break;
1720 default: 1695 default:
1721 WARN_ON(1); 1696 WARN_ON(1);
1722 err = -EOPNOTSUPP; 1697 return -EOPNOTSUPP;
1723 goto out;
1724 } 1698 }
1725 1699
1726 if (!call) { 1700 if (!call)
1727 err = -EOPNOTSUPP; 1701 return -EOPNOTSUPP;
1728 goto out;
1729 }
1730 1702
1731 memset(&params, 0, sizeof(params)); 1703 memset(&params, 0, sizeof(params));
1732 1704
@@ -1756,53 +1728,25 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1756 haveinfo = 1; 1728 haveinfo = 1;
1757 } 1729 }
1758 1730
1759 if (!haveinfo) { 1731 if (!haveinfo)
1760 err = -EINVAL; 1732 return -EINVAL;
1761 goto out;
1762 }
1763
1764 err = call(&rdev->wiphy, dev, &params);
1765
1766 out:
1767 cfg80211_unlock_rdev(rdev);
1768 dev_put(dev);
1769 unlock_rtnl:
1770 rtnl_unlock();
1771 1733
1772 return err; 1734 return call(&rdev->wiphy, dev, &params);
1773} 1735}
1774 1736
1775static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) 1737static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
1776{ 1738{
1777 struct cfg80211_registered_device *rdev; 1739 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1778 int err; 1740 struct net_device *dev = info->user_ptr[1];
1779 struct net_device *dev;
1780 1741
1781 rtnl_lock(); 1742 if (!rdev->ops->del_beacon)
1782 1743 return -EOPNOTSUPP;
1783 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
1784 if (err)
1785 goto unlock_rtnl;
1786
1787 if (!rdev->ops->del_beacon) {
1788 err = -EOPNOTSUPP;
1789 goto out;
1790 }
1791 1744
1792 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 1745 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
1793 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 1746 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
1794 err = -EOPNOTSUPP; 1747 return -EOPNOTSUPP;
1795 goto out;
1796 }
1797 err = rdev->ops->del_beacon(&rdev->wiphy, dev);
1798
1799 out:
1800 cfg80211_unlock_rdev(rdev);
1801 dev_put(dev);
1802 unlock_rtnl:
1803 rtnl_unlock();
1804 1748
1805 return err; 1749 return rdev->ops->del_beacon(&rdev->wiphy, dev);
1806} 1750}
1807 1751
1808static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { 1752static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
@@ -1923,6 +1867,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
1923 if (sinfo->filled & STATION_INFO_TX_PACKETS) 1867 if (sinfo->filled & STATION_INFO_TX_PACKETS)
1924 NLA_PUT_U32(msg, NL80211_STA_INFO_TX_PACKETS, 1868 NLA_PUT_U32(msg, NL80211_STA_INFO_TX_PACKETS,
1925 sinfo->tx_packets); 1869 sinfo->tx_packets);
1870 if (sinfo->filled & STATION_INFO_TX_RETRIES)
1871 NLA_PUT_U32(msg, NL80211_STA_INFO_TX_RETRIES,
1872 sinfo->tx_retries);
1873 if (sinfo->filled & STATION_INFO_TX_FAILED)
1874 NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED,
1875 sinfo->tx_failed);
1926 nla_nest_end(msg, sinfoattr); 1876 nla_nest_end(msg, sinfoattr);
1927 1877
1928 return genlmsg_end(msg, hdr); 1878 return genlmsg_end(msg, hdr);
@@ -1939,28 +1889,12 @@ static int nl80211_dump_station(struct sk_buff *skb,
1939 struct cfg80211_registered_device *dev; 1889 struct cfg80211_registered_device *dev;
1940 struct net_device *netdev; 1890 struct net_device *netdev;
1941 u8 mac_addr[ETH_ALEN]; 1891 u8 mac_addr[ETH_ALEN];
1942 int ifidx = cb->args[0];
1943 int sta_idx = cb->args[1]; 1892 int sta_idx = cb->args[1];
1944 int err; 1893 int err;
1945 1894
1946 if (!ifidx) 1895 err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
1947 ifidx = nl80211_get_ifidx(cb); 1896 if (err)
1948 if (ifidx < 0) 1897 return err;
1949 return ifidx;
1950
1951 rtnl_lock();
1952
1953 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
1954 if (!netdev) {
1955 err = -ENODEV;
1956 goto out_rtnl;
1957 }
1958
1959 dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
1960 if (IS_ERR(dev)) {
1961 err = PTR_ERR(dev);
1962 goto out_rtnl;
1963 }
1964 1898
1965 if (!dev->ops->dump_station) { 1899 if (!dev->ops->dump_station) {
1966 err = -EOPNOTSUPP; 1900 err = -EOPNOTSUPP;
@@ -1990,21 +1924,19 @@ static int nl80211_dump_station(struct sk_buff *skb,
1990 cb->args[1] = sta_idx; 1924 cb->args[1] = sta_idx;
1991 err = skb->len; 1925 err = skb->len;
1992 out_err: 1926 out_err:
1993 cfg80211_unlock_rdev(dev); 1927 nl80211_finish_netdev_dump(dev);
1994 out_rtnl:
1995 rtnl_unlock();
1996 1928
1997 return err; 1929 return err;
1998} 1930}
1999 1931
2000static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) 1932static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
2001{ 1933{
2002 struct cfg80211_registered_device *rdev; 1934 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2003 int err; 1935 struct net_device *dev = info->user_ptr[1];
2004 struct net_device *dev;
2005 struct station_info sinfo; 1936 struct station_info sinfo;
2006 struct sk_buff *msg; 1937 struct sk_buff *msg;
2007 u8 *mac_addr = NULL; 1938 u8 *mac_addr = NULL;
1939 int err;
2008 1940
2009 memset(&sinfo, 0, sizeof(sinfo)); 1941 memset(&sinfo, 0, sizeof(sinfo));
2010 1942
@@ -2013,41 +1945,24 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
2013 1945
2014 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1946 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2015 1947
2016 rtnl_lock(); 1948 if (!rdev->ops->get_station)
2017 1949 return -EOPNOTSUPP;
2018 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2019 if (err)
2020 goto out_rtnl;
2021
2022 if (!rdev->ops->get_station) {
2023 err = -EOPNOTSUPP;
2024 goto out;
2025 }
2026 1950
2027 err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo); 1951 err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo);
2028 if (err) 1952 if (err)
2029 goto out; 1953 return err;
2030 1954
2031 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1955 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2032 if (!msg) 1956 if (!msg)
2033 goto out; 1957 return -ENOMEM;
2034 1958
2035 if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0, 1959 if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
2036 dev, mac_addr, &sinfo) < 0) 1960 dev, mac_addr, &sinfo) < 0) {
2037 goto out_free; 1961 nlmsg_free(msg);
2038 1962 return -ENOBUFS;
2039 err = genlmsg_reply(msg, info); 1963 }
2040 goto out;
2041
2042 out_free:
2043 nlmsg_free(msg);
2044 out:
2045 cfg80211_unlock_rdev(rdev);
2046 dev_put(dev);
2047 out_rtnl:
2048 rtnl_unlock();
2049 1964
2050 return err; 1965 return genlmsg_reply(msg, info);
2051} 1966}
2052 1967
2053/* 1968/*
@@ -2077,9 +1992,9 @@ static int get_vlan(struct genl_info *info,
2077 1992
2078static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) 1993static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
2079{ 1994{
2080 struct cfg80211_registered_device *rdev; 1995 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2081 int err; 1996 int err;
2082 struct net_device *dev; 1997 struct net_device *dev = info->user_ptr[1];
2083 struct station_parameters params; 1998 struct station_parameters params;
2084 u8 *mac_addr = NULL; 1999 u8 *mac_addr = NULL;
2085 2000
@@ -2117,12 +2032,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
2117 params.plink_action = 2032 params.plink_action =
2118 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); 2033 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
2119 2034
2120 rtnl_lock();
2121
2122 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2123 if (err)
2124 goto out_rtnl;
2125
2126 err = get_vlan(info, rdev, &params.vlan); 2035 err = get_vlan(info, rdev, &params.vlan);
2127 if (err) 2036 if (err)
2128 goto out; 2037 goto out;
@@ -2184,19 +2093,15 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
2184 out: 2093 out:
2185 if (params.vlan) 2094 if (params.vlan)
2186 dev_put(params.vlan); 2095 dev_put(params.vlan);
2187 cfg80211_unlock_rdev(rdev);
2188 dev_put(dev);
2189 out_rtnl:
2190 rtnl_unlock();
2191 2096
2192 return err; 2097 return err;
2193} 2098}
2194 2099
2195static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) 2100static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
2196{ 2101{
2197 struct cfg80211_registered_device *rdev; 2102 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2198 int err; 2103 int err;
2199 struct net_device *dev; 2104 struct net_device *dev = info->user_ptr[1];
2200 struct station_parameters params; 2105 struct station_parameters params;
2201 u8 *mac_addr = NULL; 2106 u8 *mac_addr = NULL;
2202 2107
@@ -2233,18 +2138,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
2233 if (parse_station_flags(info, &params)) 2138 if (parse_station_flags(info, &params))
2234 return -EINVAL; 2139 return -EINVAL;
2235 2140
2236 rtnl_lock();
2237
2238 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2239 if (err)
2240 goto out_rtnl;
2241
2242 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 2141 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2243 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && 2142 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
2244 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 2143 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2245 err = -EINVAL; 2144 return -EINVAL;
2246 goto out;
2247 }
2248 2145
2249 err = get_vlan(info, rdev, &params.vlan); 2146 err = get_vlan(info, rdev, &params.vlan);
2250 if (err) 2147 if (err)
@@ -2258,62 +2155,33 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
2258 goto out; 2155 goto out;
2259 } 2156 }
2260 2157
2261 if (!netif_running(dev)) {
2262 err = -ENETDOWN;
2263 goto out;
2264 }
2265
2266 err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, &params); 2158 err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, &params);
2267 2159
2268 out: 2160 out:
2269 if (params.vlan) 2161 if (params.vlan)
2270 dev_put(params.vlan); 2162 dev_put(params.vlan);
2271 cfg80211_unlock_rdev(rdev);
2272 dev_put(dev);
2273 out_rtnl:
2274 rtnl_unlock();
2275
2276 return err; 2163 return err;
2277} 2164}
2278 2165
2279static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) 2166static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
2280{ 2167{
2281 struct cfg80211_registered_device *rdev; 2168 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2282 int err; 2169 struct net_device *dev = info->user_ptr[1];
2283 struct net_device *dev;
2284 u8 *mac_addr = NULL; 2170 u8 *mac_addr = NULL;
2285 2171
2286 if (info->attrs[NL80211_ATTR_MAC]) 2172 if (info->attrs[NL80211_ATTR_MAC])
2287 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 2173 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2288 2174
2289 rtnl_lock();
2290
2291 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2292 if (err)
2293 goto out_rtnl;
2294
2295 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 2175 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2296 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && 2176 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
2297 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && 2177 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
2298 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 2178 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2299 err = -EINVAL; 2179 return -EINVAL;
2300 goto out;
2301 }
2302
2303 if (!rdev->ops->del_station) {
2304 err = -EOPNOTSUPP;
2305 goto out;
2306 }
2307
2308 err = rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
2309 2180
2310 out: 2181 if (!rdev->ops->del_station)
2311 cfg80211_unlock_rdev(rdev); 2182 return -EOPNOTSUPP;
2312 dev_put(dev);
2313 out_rtnl:
2314 rtnl_unlock();
2315 2183
2316 return err; 2184 return rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
2317} 2185}
2318 2186
2319static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq, 2187static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
@@ -2376,28 +2244,12 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
2376 struct net_device *netdev; 2244 struct net_device *netdev;
2377 u8 dst[ETH_ALEN]; 2245 u8 dst[ETH_ALEN];
2378 u8 next_hop[ETH_ALEN]; 2246 u8 next_hop[ETH_ALEN];
2379 int ifidx = cb->args[0];
2380 int path_idx = cb->args[1]; 2247 int path_idx = cb->args[1];
2381 int err; 2248 int err;
2382 2249
2383 if (!ifidx) 2250 err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
2384 ifidx = nl80211_get_ifidx(cb); 2251 if (err)
2385 if (ifidx < 0) 2252 return err;
2386 return ifidx;
2387
2388 rtnl_lock();
2389
2390 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
2391 if (!netdev) {
2392 err = -ENODEV;
2393 goto out_rtnl;
2394 }
2395
2396 dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
2397 if (IS_ERR(dev)) {
2398 err = PTR_ERR(dev);
2399 goto out_rtnl;
2400 }
2401 2253
2402 if (!dev->ops->dump_mpath) { 2254 if (!dev->ops->dump_mpath) {
2403 err = -EOPNOTSUPP; 2255 err = -EOPNOTSUPP;
@@ -2431,18 +2283,15 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
2431 cb->args[1] = path_idx; 2283 cb->args[1] = path_idx;
2432 err = skb->len; 2284 err = skb->len;
2433 out_err: 2285 out_err:
2434 cfg80211_unlock_rdev(dev); 2286 nl80211_finish_netdev_dump(dev);
2435 out_rtnl:
2436 rtnl_unlock();
2437
2438 return err; 2287 return err;
2439} 2288}
2440 2289
2441static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) 2290static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
2442{ 2291{
2443 struct cfg80211_registered_device *rdev; 2292 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2444 int err; 2293 int err;
2445 struct net_device *dev; 2294 struct net_device *dev = info->user_ptr[1];
2446 struct mpath_info pinfo; 2295 struct mpath_info pinfo;
2447 struct sk_buff *msg; 2296 struct sk_buff *msg;
2448 u8 *dst = NULL; 2297 u8 *dst = NULL;
@@ -2455,53 +2304,33 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
2455 2304
2456 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 2305 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
2457 2306
2458 rtnl_lock(); 2307 if (!rdev->ops->get_mpath)
2459 2308 return -EOPNOTSUPP;
2460 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2461 if (err)
2462 goto out_rtnl;
2463
2464 if (!rdev->ops->get_mpath) {
2465 err = -EOPNOTSUPP;
2466 goto out;
2467 }
2468 2309
2469 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { 2310 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
2470 err = -EOPNOTSUPP; 2311 return -EOPNOTSUPP;
2471 goto out;
2472 }
2473 2312
2474 err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo); 2313 err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo);
2475 if (err) 2314 if (err)
2476 goto out; 2315 return err;
2477 2316
2478 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2317 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2479 if (!msg) 2318 if (!msg)
2480 goto out; 2319 return -ENOMEM;
2481 2320
2482 if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0, 2321 if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
2483 dev, dst, next_hop, &pinfo) < 0) 2322 dev, dst, next_hop, &pinfo) < 0) {
2484 goto out_free; 2323 nlmsg_free(msg);
2485 2324 return -ENOBUFS;
2486 err = genlmsg_reply(msg, info); 2325 }
2487 goto out;
2488
2489 out_free:
2490 nlmsg_free(msg);
2491 out:
2492 cfg80211_unlock_rdev(rdev);
2493 dev_put(dev);
2494 out_rtnl:
2495 rtnl_unlock();
2496 2326
2497 return err; 2327 return genlmsg_reply(msg, info);
2498} 2328}
2499 2329
2500static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) 2330static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
2501{ 2331{
2502 struct cfg80211_registered_device *rdev; 2332 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2503 int err; 2333 struct net_device *dev = info->user_ptr[1];
2504 struct net_device *dev;
2505 u8 *dst = NULL; 2334 u8 *dst = NULL;
2506 u8 *next_hop = NULL; 2335 u8 *next_hop = NULL;
2507 2336
@@ -2514,42 +2343,19 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
2514 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 2343 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
2515 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); 2344 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
2516 2345
2517 rtnl_lock(); 2346 if (!rdev->ops->change_mpath)
2518 2347 return -EOPNOTSUPP;
2519 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2520 if (err)
2521 goto out_rtnl;
2522
2523 if (!rdev->ops->change_mpath) {
2524 err = -EOPNOTSUPP;
2525 goto out;
2526 }
2527
2528 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
2529 err = -EOPNOTSUPP;
2530 goto out;
2531 }
2532
2533 if (!netif_running(dev)) {
2534 err = -ENETDOWN;
2535 goto out;
2536 }
2537
2538 err = rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
2539 2348
2540 out: 2349 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
2541 cfg80211_unlock_rdev(rdev); 2350 return -EOPNOTSUPP;
2542 dev_put(dev);
2543 out_rtnl:
2544 rtnl_unlock();
2545 2351
2546 return err; 2352 return rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
2547} 2353}
2354
2548static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) 2355static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
2549{ 2356{
2550 struct cfg80211_registered_device *rdev; 2357 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2551 int err; 2358 struct net_device *dev = info->user_ptr[1];
2552 struct net_device *dev;
2553 u8 *dst = NULL; 2359 u8 *dst = NULL;
2554 u8 *next_hop = NULL; 2360 u8 *next_hop = NULL;
2555 2361
@@ -2562,75 +2368,34 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
2562 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 2368 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
2563 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); 2369 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
2564 2370
2565 rtnl_lock(); 2371 if (!rdev->ops->add_mpath)
2566 2372 return -EOPNOTSUPP;
2567 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2568 if (err)
2569 goto out_rtnl;
2570
2571 if (!rdev->ops->add_mpath) {
2572 err = -EOPNOTSUPP;
2573 goto out;
2574 }
2575
2576 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
2577 err = -EOPNOTSUPP;
2578 goto out;
2579 }
2580
2581 if (!netif_running(dev)) {
2582 err = -ENETDOWN;
2583 goto out;
2584 }
2585
2586 err = rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
2587 2373
2588 out: 2374 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
2589 cfg80211_unlock_rdev(rdev); 2375 return -EOPNOTSUPP;
2590 dev_put(dev);
2591 out_rtnl:
2592 rtnl_unlock();
2593 2376
2594 return err; 2377 return rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
2595} 2378}
2596 2379
2597static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) 2380static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
2598{ 2381{
2599 struct cfg80211_registered_device *rdev; 2382 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2600 int err; 2383 struct net_device *dev = info->user_ptr[1];
2601 struct net_device *dev;
2602 u8 *dst = NULL; 2384 u8 *dst = NULL;
2603 2385
2604 if (info->attrs[NL80211_ATTR_MAC]) 2386 if (info->attrs[NL80211_ATTR_MAC])
2605 dst = nla_data(info->attrs[NL80211_ATTR_MAC]); 2387 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
2606 2388
2607 rtnl_lock(); 2389 if (!rdev->ops->del_mpath)
2608 2390 return -EOPNOTSUPP;
2609 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2610 if (err)
2611 goto out_rtnl;
2612
2613 if (!rdev->ops->del_mpath) {
2614 err = -EOPNOTSUPP;
2615 goto out;
2616 }
2617
2618 err = rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
2619
2620 out:
2621 cfg80211_unlock_rdev(rdev);
2622 dev_put(dev);
2623 out_rtnl:
2624 rtnl_unlock();
2625 2391
2626 return err; 2392 return rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
2627} 2393}
2628 2394
2629static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) 2395static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
2630{ 2396{
2631 struct cfg80211_registered_device *rdev; 2397 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2632 int err; 2398 struct net_device *dev = info->user_ptr[1];
2633 struct net_device *dev;
2634 struct bss_parameters params; 2399 struct bss_parameters params;
2635 2400
2636 memset(&params, 0, sizeof(params)); 2401 memset(&params, 0, sizeof(params));
@@ -2658,32 +2423,14 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
2658 if (info->attrs[NL80211_ATTR_AP_ISOLATE]) 2423 if (info->attrs[NL80211_ATTR_AP_ISOLATE])
2659 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]); 2424 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
2660 2425
2661 rtnl_lock(); 2426 if (!rdev->ops->change_bss)
2662 2427 return -EOPNOTSUPP;
2663 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2664 if (err)
2665 goto out_rtnl;
2666
2667 if (!rdev->ops->change_bss) {
2668 err = -EOPNOTSUPP;
2669 goto out;
2670 }
2671 2428
2672 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 2429 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2673 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 2430 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2674 err = -EOPNOTSUPP; 2431 return -EOPNOTSUPP;
2675 goto out;
2676 }
2677
2678 err = rdev->ops->change_bss(&rdev->wiphy, dev, &params);
2679
2680 out:
2681 cfg80211_unlock_rdev(rdev);
2682 dev_put(dev);
2683 out_rtnl:
2684 rtnl_unlock();
2685 2432
2686 return err; 2433 return rdev->ops->change_bss(&rdev->wiphy, dev, &params);
2687} 2434}
2688 2435
2689static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { 2436static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
@@ -2762,37 +2509,26 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
2762static int nl80211_get_mesh_params(struct sk_buff *skb, 2509static int nl80211_get_mesh_params(struct sk_buff *skb,
2763 struct genl_info *info) 2510 struct genl_info *info)
2764{ 2511{
2765 struct cfg80211_registered_device *rdev; 2512 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2766 struct mesh_config cur_params; 2513 struct mesh_config cur_params;
2767 int err; 2514 int err;
2768 struct net_device *dev; 2515 struct net_device *dev = info->user_ptr[1];
2769 void *hdr; 2516 void *hdr;
2770 struct nlattr *pinfoattr; 2517 struct nlattr *pinfoattr;
2771 struct sk_buff *msg; 2518 struct sk_buff *msg;
2772 2519
2773 rtnl_lock(); 2520 if (!rdev->ops->get_mesh_params)
2774 2521 return -EOPNOTSUPP;
2775 /* Look up our device */
2776 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2777 if (err)
2778 goto out_rtnl;
2779
2780 if (!rdev->ops->get_mesh_params) {
2781 err = -EOPNOTSUPP;
2782 goto out;
2783 }
2784 2522
2785 /* Get the mesh params */ 2523 /* Get the mesh params */
2786 err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params); 2524 err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params);
2787 if (err) 2525 if (err)
2788 goto out; 2526 return err;
2789 2527
2790 /* Draw up a netlink message to send back */ 2528 /* Draw up a netlink message to send back */
2791 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2529 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2792 if (!msg) { 2530 if (!msg)
2793 err = -ENOBUFS; 2531 return -ENOMEM;
2794 goto out;
2795 }
2796 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 2532 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
2797 NL80211_CMD_GET_MESH_PARAMS); 2533 NL80211_CMD_GET_MESH_PARAMS);
2798 if (!hdr) 2534 if (!hdr)
@@ -2831,21 +2567,12 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
2831 cur_params.dot11MeshHWMPRootMode); 2567 cur_params.dot11MeshHWMPRootMode);
2832 nla_nest_end(msg, pinfoattr); 2568 nla_nest_end(msg, pinfoattr);
2833 genlmsg_end(msg, hdr); 2569 genlmsg_end(msg, hdr);
2834 err = genlmsg_reply(msg, info); 2570 return genlmsg_reply(msg, info);
2835 goto out;
2836 2571
2837 nla_put_failure: 2572 nla_put_failure:
2838 genlmsg_cancel(msg, hdr); 2573 genlmsg_cancel(msg, hdr);
2839 nlmsg_free(msg); 2574 nlmsg_free(msg);
2840 err = -EMSGSIZE; 2575 return -ENOBUFS;
2841 out:
2842 /* Cleanup */
2843 cfg80211_unlock_rdev(rdev);
2844 dev_put(dev);
2845 out_rtnl:
2846 rtnl_unlock();
2847
2848 return err;
2849} 2576}
2850 2577
2851#define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \ 2578#define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \
@@ -2875,10 +2602,9 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
2875 2602
2876static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) 2603static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2877{ 2604{
2878 int err;
2879 u32 mask; 2605 u32 mask;
2880 struct cfg80211_registered_device *rdev; 2606 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2881 struct net_device *dev; 2607 struct net_device *dev = info->user_ptr[1];
2882 struct mesh_config cfg; 2608 struct mesh_config cfg;
2883 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1]; 2609 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
2884 struct nlattr *parent_attr; 2610 struct nlattr *parent_attr;
@@ -2890,16 +2616,8 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2890 parent_attr, nl80211_meshconf_params_policy)) 2616 parent_attr, nl80211_meshconf_params_policy))
2891 return -EINVAL; 2617 return -EINVAL;
2892 2618
2893 rtnl_lock(); 2619 if (!rdev->ops->set_mesh_params)
2894 2620 return -EOPNOTSUPP;
2895 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
2896 if (err)
2897 goto out_rtnl;
2898
2899 if (!rdev->ops->set_mesh_params) {
2900 err = -EOPNOTSUPP;
2901 goto out;
2902 }
2903 2621
2904 /* This makes sure that there aren't more than 32 mesh config 2622 /* This makes sure that there aren't more than 32 mesh config
2905 * parameters (otherwise our bitfield scheme would not work.) */ 2623 * parameters (otherwise our bitfield scheme would not work.) */
@@ -2945,16 +2663,7 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2945 nla_get_u8); 2663 nla_get_u8);
2946 2664
2947 /* Apply changes */ 2665 /* Apply changes */
2948 err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask); 2666 return rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask);
2949
2950 out:
2951 /* cleanup */
2952 cfg80211_unlock_rdev(rdev);
2953 dev_put(dev);
2954 out_rtnl:
2955 rtnl_unlock();
2956
2957 return err;
2958} 2667}
2959 2668
2960#undef FILL_IN_MESH_PARAM_IF_SET 2669#undef FILL_IN_MESH_PARAM_IF_SET
@@ -3137,8 +2846,8 @@ static int validate_scan_freqs(struct nlattr *freqs)
3137 2846
3138static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) 2847static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3139{ 2848{
3140 struct cfg80211_registered_device *rdev; 2849 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3141 struct net_device *dev; 2850 struct net_device *dev = info->user_ptr[1];
3142 struct cfg80211_scan_request *request; 2851 struct cfg80211_scan_request *request;
3143 struct cfg80211_ssid *ssid; 2852 struct cfg80211_ssid *ssid;
3144 struct ieee80211_channel *channel; 2853 struct ieee80211_channel *channel;
@@ -3151,36 +2860,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3151 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 2860 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3152 return -EINVAL; 2861 return -EINVAL;
3153 2862
3154 rtnl_lock();
3155
3156 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
3157 if (err)
3158 goto out_rtnl;
3159
3160 wiphy = &rdev->wiphy; 2863 wiphy = &rdev->wiphy;
3161 2864
3162 if (!rdev->ops->scan) { 2865 if (!rdev->ops->scan)
3163 err = -EOPNOTSUPP; 2866 return -EOPNOTSUPP;
3164 goto out;
3165 }
3166
3167 if (!netif_running(dev)) {
3168 err = -ENETDOWN;
3169 goto out;
3170 }
3171 2867
3172 if (rdev->scan_req) { 2868 if (rdev->scan_req)
3173 err = -EBUSY; 2869 return -EBUSY;
3174 goto out;
3175 }
3176 2870
3177 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { 2871 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
3178 n_channels = validate_scan_freqs( 2872 n_channels = validate_scan_freqs(
3179 info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); 2873 info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
3180 if (!n_channels) { 2874 if (!n_channels)
3181 err = -EINVAL; 2875 return -EINVAL;
3182 goto out;
3183 }
3184 } else { 2876 } else {
3185 n_channels = 0; 2877 n_channels = 0;
3186 2878
@@ -3193,29 +2885,23 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3193 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) 2885 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
3194 n_ssids++; 2886 n_ssids++;
3195 2887
3196 if (n_ssids > wiphy->max_scan_ssids) { 2888 if (n_ssids > wiphy->max_scan_ssids)
3197 err = -EINVAL; 2889 return -EINVAL;
3198 goto out;
3199 }
3200 2890
3201 if (info->attrs[NL80211_ATTR_IE]) 2891 if (info->attrs[NL80211_ATTR_IE])
3202 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 2892 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
3203 else 2893 else
3204 ie_len = 0; 2894 ie_len = 0;
3205 2895
3206 if (ie_len > wiphy->max_scan_ie_len) { 2896 if (ie_len > wiphy->max_scan_ie_len)
3207 err = -EINVAL; 2897 return -EINVAL;
3208 goto out;
3209 }
3210 2898
3211 request = kzalloc(sizeof(*request) 2899 request = kzalloc(sizeof(*request)
3212 + sizeof(*ssid) * n_ssids 2900 + sizeof(*ssid) * n_ssids
3213 + sizeof(channel) * n_channels 2901 + sizeof(channel) * n_channels
3214 + ie_len, GFP_KERNEL); 2902 + ie_len, GFP_KERNEL);
3215 if (!request) { 2903 if (!request)
3216 err = -ENOMEM; 2904 return -ENOMEM;
3217 goto out;
3218 }
3219 2905
3220 if (n_ssids) 2906 if (n_ssids)
3221 request->ssids = (void *)&request->channels[n_channels]; 2907 request->ssids = (void *)&request->channels[n_channels];
@@ -3303,18 +2989,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3303 if (!err) { 2989 if (!err) {
3304 nl80211_send_scan_start(rdev, dev); 2990 nl80211_send_scan_start(rdev, dev);
3305 dev_hold(dev); 2991 dev_hold(dev);
3306 } 2992 } else {
3307
3308 out_free: 2993 out_free:
3309 if (err) {
3310 rdev->scan_req = NULL; 2994 rdev->scan_req = NULL;
3311 kfree(request); 2995 kfree(request);
3312 } 2996 }
3313 out:
3314 cfg80211_unlock_rdev(rdev);
3315 dev_put(dev);
3316 out_rtnl:
3317 rtnl_unlock();
3318 2997
3319 return err; 2998 return err;
3320} 2999}
@@ -3411,25 +3090,12 @@ static int nl80211_dump_scan(struct sk_buff *skb,
3411 struct net_device *dev; 3090 struct net_device *dev;
3412 struct cfg80211_internal_bss *scan; 3091 struct cfg80211_internal_bss *scan;
3413 struct wireless_dev *wdev; 3092 struct wireless_dev *wdev;
3414 int ifidx = cb->args[0];
3415 int start = cb->args[1], idx = 0; 3093 int start = cb->args[1], idx = 0;
3416 int err; 3094 int err;
3417 3095
3418 if (!ifidx) 3096 err = nl80211_prepare_netdev_dump(skb, cb, &rdev, &dev);
3419 ifidx = nl80211_get_ifidx(cb); 3097 if (err)
3420 if (ifidx < 0) 3098 return err;
3421 return ifidx;
3422 cb->args[0] = ifidx;
3423
3424 dev = dev_get_by_index(sock_net(skb->sk), ifidx);
3425 if (!dev)
3426 return -ENODEV;
3427
3428 rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
3429 if (IS_ERR(rdev)) {
3430 err = PTR_ERR(rdev);
3431 goto out_put_netdev;
3432 }
3433 3099
3434 wdev = dev->ieee80211_ptr; 3100 wdev = dev->ieee80211_ptr;
3435 3101
@@ -3445,21 +3111,17 @@ static int nl80211_dump_scan(struct sk_buff *skb,
3445 cb->nlh->nlmsg_seq, NLM_F_MULTI, 3111 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3446 rdev, wdev, scan) < 0) { 3112 rdev, wdev, scan) < 0) {
3447 idx--; 3113 idx--;
3448 goto out; 3114 break;
3449 } 3115 }
3450 } 3116 }
3451 3117
3452 out:
3453 spin_unlock_bh(&rdev->bss_lock); 3118 spin_unlock_bh(&rdev->bss_lock);
3454 wdev_unlock(wdev); 3119 wdev_unlock(wdev);
3455 3120
3456 cb->args[1] = idx; 3121 cb->args[1] = idx;
3457 err = skb->len; 3122 nl80211_finish_netdev_dump(rdev);
3458 cfg80211_unlock_rdev(rdev);
3459 out_put_netdev:
3460 dev_put(dev);
3461 3123
3462 return err; 3124 return skb->len;
3463} 3125}
3464 3126
3465static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq, 3127static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq,
@@ -3489,6 +3151,8 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq,
3489 if (survey->filled & SURVEY_INFO_NOISE_DBM) 3151 if (survey->filled & SURVEY_INFO_NOISE_DBM)
3490 NLA_PUT_U8(msg, NL80211_SURVEY_INFO_NOISE, 3152 NLA_PUT_U8(msg, NL80211_SURVEY_INFO_NOISE,
3491 survey->noise); 3153 survey->noise);
3154 if (survey->filled & SURVEY_INFO_IN_USE)
3155 NLA_PUT_FLAG(msg, NL80211_SURVEY_INFO_IN_USE);
3492 3156
3493 nla_nest_end(msg, infoattr); 3157 nla_nest_end(msg, infoattr);
3494 3158
@@ -3505,29 +3169,12 @@ static int nl80211_dump_survey(struct sk_buff *skb,
3505 struct survey_info survey; 3169 struct survey_info survey;
3506 struct cfg80211_registered_device *dev; 3170 struct cfg80211_registered_device *dev;
3507 struct net_device *netdev; 3171 struct net_device *netdev;
3508 int ifidx = cb->args[0];
3509 int survey_idx = cb->args[1]; 3172 int survey_idx = cb->args[1];
3510 int res; 3173 int res;
3511 3174
3512 if (!ifidx) 3175 res = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
3513 ifidx = nl80211_get_ifidx(cb); 3176 if (res)
3514 if (ifidx < 0) 3177 return res;
3515 return ifidx;
3516 cb->args[0] = ifidx;
3517
3518 rtnl_lock();
3519
3520 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
3521 if (!netdev) {
3522 res = -ENODEV;
3523 goto out_rtnl;
3524 }
3525
3526 dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
3527 if (IS_ERR(dev)) {
3528 res = PTR_ERR(dev);
3529 goto out_rtnl;
3530 }
3531 3178
3532 if (!dev->ops->dump_survey) { 3179 if (!dev->ops->dump_survey) {
3533 res = -EOPNOTSUPP; 3180 res = -EOPNOTSUPP;
@@ -3555,10 +3202,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
3555 cb->args[1] = survey_idx; 3202 cb->args[1] = survey_idx;
3556 res = skb->len; 3203 res = skb->len;
3557 out_err: 3204 out_err:
3558 cfg80211_unlock_rdev(dev); 3205 nl80211_finish_netdev_dump(dev);
3559 out_rtnl:
3560 rtnl_unlock();
3561
3562 return res; 3206 return res;
3563} 3207}
3564 3208
@@ -3591,8 +3235,8 @@ static bool nl80211_valid_cipher_suite(u32 cipher)
3591 3235
3592static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) 3236static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3593{ 3237{
3594 struct cfg80211_registered_device *rdev; 3238 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3595 struct net_device *dev; 3239 struct net_device *dev = info->user_ptr[1];
3596 struct ieee80211_channel *chan; 3240 struct ieee80211_channel *chan;
3597 const u8 *bssid, *ssid, *ie = NULL; 3241 const u8 *bssid, *ssid, *ie = NULL;
3598 int err, ssid_len, ie_len = 0; 3242 int err, ssid_len, ie_len = 0;
@@ -3620,6 +3264,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3620 return err; 3264 return err;
3621 3265
3622 if (key.idx >= 0) { 3266 if (key.idx >= 0) {
3267 if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
3268 return -EINVAL;
3623 if (!key.p.key || !key.p.key_len) 3269 if (!key.p.key || !key.p.key_len)
3624 return -EINVAL; 3270 return -EINVAL;
3625 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 || 3271 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
@@ -3634,12 +3280,6 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3634 key.p.key = NULL; 3280 key.p.key = NULL;
3635 } 3281 }
3636 3282
3637 rtnl_lock();
3638
3639 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
3640 if (err)
3641 goto unlock_rtnl;
3642
3643 if (key.idx >= 0) { 3283 if (key.idx >= 0) {
3644 int i; 3284 int i;
3645 bool ok = false; 3285 bool ok = false;
@@ -3649,35 +3289,22 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3649 break; 3289 break;
3650 } 3290 }
3651 } 3291 }
3652 if (!ok) { 3292 if (!ok)
3653 err = -EINVAL; 3293 return -EINVAL;
3654 goto out;
3655 }
3656 } 3294 }
3657 3295
3658 if (!rdev->ops->auth) { 3296 if (!rdev->ops->auth)
3659 err = -EOPNOTSUPP; 3297 return -EOPNOTSUPP;
3660 goto out;
3661 }
3662 3298
3663 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3299 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
3664 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3300 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
3665 err = -EOPNOTSUPP; 3301 return -EOPNOTSUPP;
3666 goto out;
3667 }
3668
3669 if (!netif_running(dev)) {
3670 err = -ENETDOWN;
3671 goto out;
3672 }
3673 3302
3674 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); 3303 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
3675 chan = ieee80211_get_channel(&rdev->wiphy, 3304 chan = ieee80211_get_channel(&rdev->wiphy,
3676 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); 3305 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3677 if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) { 3306 if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED))
3678 err = -EINVAL; 3307 return -EINVAL;
3679 goto out;
3680 }
3681 3308
3682 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); 3309 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
3683 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); 3310 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
@@ -3688,24 +3315,15 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3688 } 3315 }
3689 3316
3690 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); 3317 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
3691 if (!nl80211_valid_auth_type(auth_type)) { 3318 if (!nl80211_valid_auth_type(auth_type))
3692 err = -EINVAL; 3319 return -EINVAL;
3693 goto out;
3694 }
3695 3320
3696 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; 3321 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3697 3322
3698 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 3323 return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
3699 ssid, ssid_len, ie, ie_len, 3324 ssid, ssid_len, ie, ie_len,
3700 key.p.key, key.p.key_len, key.idx, 3325 key.p.key, key.p.key_len, key.idx,
3701 local_state_change); 3326 local_state_change);
3702
3703out:
3704 cfg80211_unlock_rdev(rdev);
3705 dev_put(dev);
3706unlock_rtnl:
3707 rtnl_unlock();
3708 return err;
3709} 3327}
3710 3328
3711static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, 3329static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
@@ -3789,8 +3407,8 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
3789 3407
3790static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) 3408static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3791{ 3409{
3792 struct cfg80211_registered_device *rdev; 3410 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3793 struct net_device *dev; 3411 struct net_device *dev = info->user_ptr[1];
3794 struct cfg80211_crypto_settings crypto; 3412 struct cfg80211_crypto_settings crypto;
3795 struct ieee80211_channel *chan; 3413 struct ieee80211_channel *chan;
3796 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; 3414 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
@@ -3805,36 +3423,19 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3805 !info->attrs[NL80211_ATTR_WIPHY_FREQ]) 3423 !info->attrs[NL80211_ATTR_WIPHY_FREQ])
3806 return -EINVAL; 3424 return -EINVAL;
3807 3425
3808 rtnl_lock(); 3426 if (!rdev->ops->assoc)
3809 3427 return -EOPNOTSUPP;
3810 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
3811 if (err)
3812 goto unlock_rtnl;
3813
3814 if (!rdev->ops->assoc) {
3815 err = -EOPNOTSUPP;
3816 goto out;
3817 }
3818 3428
3819 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3429 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
3820 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3430 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
3821 err = -EOPNOTSUPP; 3431 return -EOPNOTSUPP;
3822 goto out;
3823 }
3824
3825 if (!netif_running(dev)) {
3826 err = -ENETDOWN;
3827 goto out;
3828 }
3829 3432
3830 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); 3433 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
3831 3434
3832 chan = ieee80211_get_channel(&rdev->wiphy, 3435 chan = ieee80211_get_channel(&rdev->wiphy,
3833 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); 3436 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3834 if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) { 3437 if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED))
3835 err = -EINVAL; 3438 return -EINVAL;
3836 goto out;
3837 }
3838 3439
3839 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); 3440 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
3840 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); 3441 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
@@ -3849,10 +3450,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3849 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); 3450 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
3850 if (mfp == NL80211_MFP_REQUIRED) 3451 if (mfp == NL80211_MFP_REQUIRED)
3851 use_mfp = true; 3452 use_mfp = true;
3852 else if (mfp != NL80211_MFP_NO) { 3453 else if (mfp != NL80211_MFP_NO)
3853 err = -EINVAL; 3454 return -EINVAL;
3854 goto out;
3855 }
3856 } 3455 }
3857 3456
3858 if (info->attrs[NL80211_ATTR_PREV_BSSID]) 3457 if (info->attrs[NL80211_ATTR_PREV_BSSID])
@@ -3864,20 +3463,15 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3864 ssid, ssid_len, ie, ie_len, use_mfp, 3463 ssid, ssid_len, ie, ie_len, use_mfp,
3865 &crypto); 3464 &crypto);
3866 3465
3867out:
3868 cfg80211_unlock_rdev(rdev);
3869 dev_put(dev);
3870unlock_rtnl:
3871 rtnl_unlock();
3872 return err; 3466 return err;
3873} 3467}
3874 3468
3875static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) 3469static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3876{ 3470{
3877 struct cfg80211_registered_device *rdev; 3471 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3878 struct net_device *dev; 3472 struct net_device *dev = info->user_ptr[1];
3879 const u8 *ie = NULL, *bssid; 3473 const u8 *ie = NULL, *bssid;
3880 int err, ie_len = 0; 3474 int ie_len = 0;
3881 u16 reason_code; 3475 u16 reason_code;
3882 bool local_state_change; 3476 bool local_state_change;
3883 3477
@@ -3890,35 +3484,19 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3890 if (!info->attrs[NL80211_ATTR_REASON_CODE]) 3484 if (!info->attrs[NL80211_ATTR_REASON_CODE])
3891 return -EINVAL; 3485 return -EINVAL;
3892 3486
3893 rtnl_lock(); 3487 if (!rdev->ops->deauth)
3894 3488 return -EOPNOTSUPP;
3895 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
3896 if (err)
3897 goto unlock_rtnl;
3898
3899 if (!rdev->ops->deauth) {
3900 err = -EOPNOTSUPP;
3901 goto out;
3902 }
3903 3489
3904 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3490 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
3905 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3491 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
3906 err = -EOPNOTSUPP; 3492 return -EOPNOTSUPP;
3907 goto out;
3908 }
3909
3910 if (!netif_running(dev)) {
3911 err = -ENETDOWN;
3912 goto out;
3913 }
3914 3493
3915 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); 3494 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
3916 3495
3917 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); 3496 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
3918 if (reason_code == 0) { 3497 if (reason_code == 0) {
3919 /* Reason Code 0 is reserved */ 3498 /* Reason Code 0 is reserved */
3920 err = -EINVAL; 3499 return -EINVAL;
3921 goto out;
3922 } 3500 }
3923 3501
3924 if (info->attrs[NL80211_ATTR_IE]) { 3502 if (info->attrs[NL80211_ATTR_IE]) {
@@ -3928,23 +3506,16 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3928 3506
3929 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; 3507 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3930 3508
3931 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, 3509 return cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
3932 local_state_change); 3510 local_state_change);
3933
3934out:
3935 cfg80211_unlock_rdev(rdev);
3936 dev_put(dev);
3937unlock_rtnl:
3938 rtnl_unlock();
3939 return err;
3940} 3511}
3941 3512
3942static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) 3513static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
3943{ 3514{
3944 struct cfg80211_registered_device *rdev; 3515 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3945 struct net_device *dev; 3516 struct net_device *dev = info->user_ptr[1];
3946 const u8 *ie = NULL, *bssid; 3517 const u8 *ie = NULL, *bssid;
3947 int err, ie_len = 0; 3518 int ie_len = 0;
3948 u16 reason_code; 3519 u16 reason_code;
3949 bool local_state_change; 3520 bool local_state_change;
3950 3521
@@ -3957,35 +3528,19 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
3957 if (!info->attrs[NL80211_ATTR_REASON_CODE]) 3528 if (!info->attrs[NL80211_ATTR_REASON_CODE])
3958 return -EINVAL; 3529 return -EINVAL;
3959 3530
3960 rtnl_lock(); 3531 if (!rdev->ops->disassoc)
3961 3532 return -EOPNOTSUPP;
3962 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
3963 if (err)
3964 goto unlock_rtnl;
3965
3966 if (!rdev->ops->disassoc) {
3967 err = -EOPNOTSUPP;
3968 goto out;
3969 }
3970 3533
3971 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3534 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
3972 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3535 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
3973 err = -EOPNOTSUPP; 3536 return -EOPNOTSUPP;
3974 goto out;
3975 }
3976
3977 if (!netif_running(dev)) {
3978 err = -ENETDOWN;
3979 goto out;
3980 }
3981 3537
3982 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); 3538 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
3983 3539
3984 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); 3540 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
3985 if (reason_code == 0) { 3541 if (reason_code == 0) {
3986 /* Reason Code 0 is reserved */ 3542 /* Reason Code 0 is reserved */
3987 err = -EINVAL; 3543 return -EINVAL;
3988 goto out;
3989 } 3544 }
3990 3545
3991 if (info->attrs[NL80211_ATTR_IE]) { 3546 if (info->attrs[NL80211_ATTR_IE]) {
@@ -3995,21 +3550,14 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
3995 3550
3996 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; 3551 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3997 3552
3998 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, 3553 return cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
3999 local_state_change); 3554 local_state_change);
4000
4001out:
4002 cfg80211_unlock_rdev(rdev);
4003 dev_put(dev);
4004unlock_rtnl:
4005 rtnl_unlock();
4006 return err;
4007} 3555}
4008 3556
4009static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) 3557static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4010{ 3558{
4011 struct cfg80211_registered_device *rdev; 3559 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4012 struct net_device *dev; 3560 struct net_device *dev = info->user_ptr[1];
4013 struct cfg80211_ibss_params ibss; 3561 struct cfg80211_ibss_params ibss;
4014 struct wiphy *wiphy; 3562 struct wiphy *wiphy;
4015 struct cfg80211_cached_keys *connkeys = NULL; 3563 struct cfg80211_cached_keys *connkeys = NULL;
@@ -4034,26 +3582,11 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4034 return -EINVAL; 3582 return -EINVAL;
4035 } 3583 }
4036 3584
4037 rtnl_lock(); 3585 if (!rdev->ops->join_ibss)
4038 3586 return -EOPNOTSUPP;
4039 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4040 if (err)
4041 goto unlock_rtnl;
4042
4043 if (!rdev->ops->join_ibss) {
4044 err = -EOPNOTSUPP;
4045 goto out;
4046 }
4047
4048 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
4049 err = -EOPNOTSUPP;
4050 goto out;
4051 }
4052 3587
4053 if (!netif_running(dev)) { 3588 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
4054 err = -ENETDOWN; 3589 return -EOPNOTSUPP;
4055 goto out;
4056 }
4057 3590
4058 wiphy = &rdev->wiphy; 3591 wiphy = &rdev->wiphy;
4059 3592
@@ -4071,24 +3604,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4071 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); 3604 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
4072 if (!ibss.channel || 3605 if (!ibss.channel ||
4073 ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || 3606 ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
4074 ibss.channel->flags & IEEE80211_CHAN_DISABLED) { 3607 ibss.channel->flags & IEEE80211_CHAN_DISABLED)
4075 err = -EINVAL; 3608 return -EINVAL;
4076 goto out;
4077 }
4078 3609
4079 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; 3610 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
4080 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; 3611 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
4081 3612
4082 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
4083 connkeys = nl80211_parse_connkeys(rdev,
4084 info->attrs[NL80211_ATTR_KEYS]);
4085 if (IS_ERR(connkeys)) {
4086 err = PTR_ERR(connkeys);
4087 connkeys = NULL;
4088 goto out;
4089 }
4090 }
4091
4092 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) { 3613 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
4093 u8 *rates = 3614 u8 *rates =
4094 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); 3615 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
@@ -4098,10 +3619,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4098 wiphy->bands[ibss.channel->band]; 3619 wiphy->bands[ibss.channel->band];
4099 int i, j; 3620 int i, j;
4100 3621
4101 if (n_rates == 0) { 3622 if (n_rates == 0)
4102 err = -EINVAL; 3623 return -EINVAL;
4103 goto out;
4104 }
4105 3624
4106 for (i = 0; i < n_rates; i++) { 3625 for (i = 0; i < n_rates; i++) {
4107 int rate = (rates[i] & 0x7f) * 5; 3626 int rate = (rates[i] & 0x7f) * 5;
@@ -4114,60 +3633,36 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4114 break; 3633 break;
4115 } 3634 }
4116 } 3635 }
4117 if (!found) { 3636 if (!found)
4118 err = -EINVAL; 3637 return -EINVAL;
4119 goto out;
4120 }
4121 } 3638 }
4122 } 3639 }
4123 3640
4124 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); 3641 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
3642 connkeys = nl80211_parse_connkeys(rdev,
3643 info->attrs[NL80211_ATTR_KEYS]);
3644 if (IS_ERR(connkeys))
3645 return PTR_ERR(connkeys);
3646 }
4125 3647
4126out: 3648 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
4127 cfg80211_unlock_rdev(rdev);
4128 dev_put(dev);
4129unlock_rtnl:
4130 if (err) 3649 if (err)
4131 kfree(connkeys); 3650 kfree(connkeys);
4132 rtnl_unlock();
4133 return err; 3651 return err;
4134} 3652}
4135 3653
4136static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info) 3654static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
4137{ 3655{
4138 struct cfg80211_registered_device *rdev; 3656 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4139 struct net_device *dev; 3657 struct net_device *dev = info->user_ptr[1];
4140 int err;
4141 3658
4142 rtnl_lock(); 3659 if (!rdev->ops->leave_ibss)
4143 3660 return -EOPNOTSUPP;
4144 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4145 if (err)
4146 goto unlock_rtnl;
4147
4148 if (!rdev->ops->leave_ibss) {
4149 err = -EOPNOTSUPP;
4150 goto out;
4151 }
4152
4153 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
4154 err = -EOPNOTSUPP;
4155 goto out;
4156 }
4157
4158 if (!netif_running(dev)) {
4159 err = -ENETDOWN;
4160 goto out;
4161 }
4162 3661
4163 err = cfg80211_leave_ibss(rdev, dev, false); 3662 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
3663 return -EOPNOTSUPP;
4164 3664
4165out: 3665 return cfg80211_leave_ibss(rdev, dev, false);
4166 cfg80211_unlock_rdev(rdev);
4167 dev_put(dev);
4168unlock_rtnl:
4169 rtnl_unlock();
4170 return err;
4171} 3666}
4172 3667
4173#ifdef CONFIG_NL80211_TESTMODE 3668#ifdef CONFIG_NL80211_TESTMODE
@@ -4177,20 +3672,12 @@ static struct genl_multicast_group nl80211_testmode_mcgrp = {
4177 3672
4178static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) 3673static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
4179{ 3674{
4180 struct cfg80211_registered_device *rdev; 3675 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4181 int err; 3676 int err;
4182 3677
4183 if (!info->attrs[NL80211_ATTR_TESTDATA]) 3678 if (!info->attrs[NL80211_ATTR_TESTDATA])
4184 return -EINVAL; 3679 return -EINVAL;
4185 3680
4186 rtnl_lock();
4187
4188 rdev = cfg80211_get_dev_from_info(info);
4189 if (IS_ERR(rdev)) {
4190 err = PTR_ERR(rdev);
4191 goto unlock_rtnl;
4192 }
4193
4194 err = -EOPNOTSUPP; 3681 err = -EOPNOTSUPP;
4195 if (rdev->ops->testmode_cmd) { 3682 if (rdev->ops->testmode_cmd) {
4196 rdev->testmode_info = info; 3683 rdev->testmode_info = info;
@@ -4200,10 +3687,6 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
4200 rdev->testmode_info = NULL; 3687 rdev->testmode_info = NULL;
4201 } 3688 }
4202 3689
4203 cfg80211_unlock_rdev(rdev);
4204
4205 unlock_rtnl:
4206 rtnl_unlock();
4207 return err; 3690 return err;
4208} 3691}
4209 3692
@@ -4294,8 +3777,8 @@ EXPORT_SYMBOL(cfg80211_testmode_event);
4294 3777
4295static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) 3778static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
4296{ 3779{
4297 struct cfg80211_registered_device *rdev; 3780 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4298 struct net_device *dev; 3781 struct net_device *dev = info->user_ptr[1];
4299 struct cfg80211_connect_params connect; 3782 struct cfg80211_connect_params connect;
4300 struct wiphy *wiphy; 3783 struct wiphy *wiphy;
4301 struct cfg80211_cached_keys *connkeys = NULL; 3784 struct cfg80211_cached_keys *connkeys = NULL;
@@ -4324,22 +3807,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
4324 NL80211_MAX_NR_CIPHER_SUITES); 3807 NL80211_MAX_NR_CIPHER_SUITES);
4325 if (err) 3808 if (err)
4326 return err; 3809 return err;
4327 rtnl_lock();
4328
4329 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4330 if (err)
4331 goto unlock_rtnl;
4332 3810
4333 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3811 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4334 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3812 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
4335 err = -EOPNOTSUPP; 3813 return -EOPNOTSUPP;
4336 goto out;
4337 }
4338
4339 if (!netif_running(dev)) {
4340 err = -ENETDOWN;
4341 goto out;
4342 }
4343 3814
4344 wiphy = &rdev->wiphy; 3815 wiphy = &rdev->wiphy;
4345 3816
@@ -4358,39 +3829,27 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
4358 ieee80211_get_channel(wiphy, 3829 ieee80211_get_channel(wiphy,
4359 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); 3830 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
4360 if (!connect.channel || 3831 if (!connect.channel ||
4361 connect.channel->flags & IEEE80211_CHAN_DISABLED) { 3832 connect.channel->flags & IEEE80211_CHAN_DISABLED)
4362 err = -EINVAL; 3833 return -EINVAL;
4363 goto out;
4364 }
4365 } 3834 }
4366 3835
4367 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) { 3836 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
4368 connkeys = nl80211_parse_connkeys(rdev, 3837 connkeys = nl80211_parse_connkeys(rdev,
4369 info->attrs[NL80211_ATTR_KEYS]); 3838 info->attrs[NL80211_ATTR_KEYS]);
4370 if (IS_ERR(connkeys)) { 3839 if (IS_ERR(connkeys))
4371 err = PTR_ERR(connkeys); 3840 return PTR_ERR(connkeys);
4372 connkeys = NULL;
4373 goto out;
4374 }
4375 } 3841 }
4376 3842
4377 err = cfg80211_connect(rdev, dev, &connect, connkeys); 3843 err = cfg80211_connect(rdev, dev, &connect, connkeys);
4378
4379out:
4380 cfg80211_unlock_rdev(rdev);
4381 dev_put(dev);
4382unlock_rtnl:
4383 if (err) 3844 if (err)
4384 kfree(connkeys); 3845 kfree(connkeys);
4385 rtnl_unlock();
4386 return err; 3846 return err;
4387} 3847}
4388 3848
4389static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) 3849static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
4390{ 3850{
4391 struct cfg80211_registered_device *rdev; 3851 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4392 struct net_device *dev; 3852 struct net_device *dev = info->user_ptr[1];
4393 int err;
4394 u16 reason; 3853 u16 reason;
4395 3854
4396 if (!info->attrs[NL80211_ATTR_REASON_CODE]) 3855 if (!info->attrs[NL80211_ATTR_REASON_CODE])
@@ -4401,36 +3860,16 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
4401 if (reason == 0) 3860 if (reason == 0)
4402 return -EINVAL; 3861 return -EINVAL;
4403 3862
4404 rtnl_lock();
4405
4406 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4407 if (err)
4408 goto unlock_rtnl;
4409
4410 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3863 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4411 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3864 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
4412 err = -EOPNOTSUPP; 3865 return -EOPNOTSUPP;
4413 goto out;
4414 }
4415
4416 if (!netif_running(dev)) {
4417 err = -ENETDOWN;
4418 goto out;
4419 }
4420
4421 err = cfg80211_disconnect(rdev, dev, reason, true);
4422 3866
4423out: 3867 return cfg80211_disconnect(rdev, dev, reason, true);
4424 cfg80211_unlock_rdev(rdev);
4425 dev_put(dev);
4426unlock_rtnl:
4427 rtnl_unlock();
4428 return err;
4429} 3868}
4430 3869
4431static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) 3870static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
4432{ 3871{
4433 struct cfg80211_registered_device *rdev; 3872 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4434 struct net *net; 3873 struct net *net;
4435 int err; 3874 int err;
4436 u32 pid; 3875 u32 pid;
@@ -4440,43 +3879,26 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
4440 3879
4441 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]); 3880 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);
4442 3881
4443 rtnl_lock();
4444
4445 rdev = cfg80211_get_dev_from_info(info);
4446 if (IS_ERR(rdev)) {
4447 err = PTR_ERR(rdev);
4448 goto out_rtnl;
4449 }
4450
4451 net = get_net_ns_by_pid(pid); 3882 net = get_net_ns_by_pid(pid);
4452 if (IS_ERR(net)) { 3883 if (IS_ERR(net))
4453 err = PTR_ERR(net); 3884 return PTR_ERR(net);
4454 goto out;
4455 }
4456 3885
4457 err = 0; 3886 err = 0;
4458 3887
4459 /* check if anything to do */ 3888 /* check if anything to do */
4460 if (net_eq(wiphy_net(&rdev->wiphy), net)) 3889 if (!net_eq(wiphy_net(&rdev->wiphy), net))
4461 goto out_put_net; 3890 err = cfg80211_switch_netns(rdev, net);
4462 3891
4463 err = cfg80211_switch_netns(rdev, net);
4464 out_put_net:
4465 put_net(net); 3892 put_net(net);
4466 out:
4467 cfg80211_unlock_rdev(rdev);
4468 out_rtnl:
4469 rtnl_unlock();
4470 return err; 3893 return err;
4471} 3894}
4472 3895
4473static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info) 3896static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
4474{ 3897{
4475 struct cfg80211_registered_device *rdev; 3898 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4476 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev, 3899 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
4477 struct cfg80211_pmksa *pmksa) = NULL; 3900 struct cfg80211_pmksa *pmksa) = NULL;
4478 int err; 3901 struct net_device *dev = info->user_ptr[1];
4479 struct net_device *dev;
4480 struct cfg80211_pmksa pmksa; 3902 struct cfg80211_pmksa pmksa;
4481 3903
4482 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa)); 3904 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
@@ -4487,20 +3909,12 @@ static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
4487 if (!info->attrs[NL80211_ATTR_PMKID]) 3909 if (!info->attrs[NL80211_ATTR_PMKID])
4488 return -EINVAL; 3910 return -EINVAL;
4489 3911
4490 rtnl_lock();
4491
4492 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4493 if (err)
4494 goto out_rtnl;
4495
4496 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]); 3912 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
4497 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); 3913 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
4498 3914
4499 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3915 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4500 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3916 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
4501 err = -EOPNOTSUPP; 3917 return -EOPNOTSUPP;
4502 goto out;
4503 }
4504 3918
4505 switch (info->genlhdr->cmd) { 3919 switch (info->genlhdr->cmd) {
4506 case NL80211_CMD_SET_PMKSA: 3920 case NL80211_CMD_SET_PMKSA:
@@ -4514,62 +3928,32 @@ static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
4514 break; 3928 break;
4515 } 3929 }
4516 3930
4517 if (!rdev_ops) { 3931 if (!rdev_ops)
4518 err = -EOPNOTSUPP; 3932 return -EOPNOTSUPP;
4519 goto out;
4520 }
4521
4522 err = rdev_ops(&rdev->wiphy, dev, &pmksa);
4523
4524 out:
4525 cfg80211_unlock_rdev(rdev);
4526 dev_put(dev);
4527 out_rtnl:
4528 rtnl_unlock();
4529 3933
4530 return err; 3934 return rdev_ops(&rdev->wiphy, dev, &pmksa);
4531} 3935}
4532 3936
4533static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info) 3937static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
4534{ 3938{
4535 struct cfg80211_registered_device *rdev; 3939 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4536 int err; 3940 struct net_device *dev = info->user_ptr[1];
4537 struct net_device *dev;
4538
4539 rtnl_lock();
4540
4541 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4542 if (err)
4543 goto out_rtnl;
4544 3941
4545 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 3942 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4546 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 3943 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
4547 err = -EOPNOTSUPP; 3944 return -EOPNOTSUPP;
4548 goto out;
4549 }
4550
4551 if (!rdev->ops->flush_pmksa) {
4552 err = -EOPNOTSUPP;
4553 goto out;
4554 }
4555
4556 err = rdev->ops->flush_pmksa(&rdev->wiphy, dev);
4557
4558 out:
4559 cfg80211_unlock_rdev(rdev);
4560 dev_put(dev);
4561 out_rtnl:
4562 rtnl_unlock();
4563 3945
4564 return err; 3946 if (!rdev->ops->flush_pmksa)
3947 return -EOPNOTSUPP;
4565 3948
3949 return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
4566} 3950}
4567 3951
4568static int nl80211_remain_on_channel(struct sk_buff *skb, 3952static int nl80211_remain_on_channel(struct sk_buff *skb,
4569 struct genl_info *info) 3953 struct genl_info *info)
4570{ 3954{
4571 struct cfg80211_registered_device *rdev; 3955 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4572 struct net_device *dev; 3956 struct net_device *dev = info->user_ptr[1];
4573 struct ieee80211_channel *chan; 3957 struct ieee80211_channel *chan;
4574 struct sk_buff *msg; 3958 struct sk_buff *msg;
4575 void *hdr; 3959 void *hdr;
@@ -4591,21 +3975,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
4591 if (!duration || !msecs_to_jiffies(duration) || duration > 5000) 3975 if (!duration || !msecs_to_jiffies(duration) || duration > 5000)
4592 return -EINVAL; 3976 return -EINVAL;
4593 3977
4594 rtnl_lock(); 3978 if (!rdev->ops->remain_on_channel)
4595 3979 return -EOPNOTSUPP;
4596 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4597 if (err)
4598 goto unlock_rtnl;
4599
4600 if (!rdev->ops->remain_on_channel) {
4601 err = -EOPNOTSUPP;
4602 goto out;
4603 }
4604
4605 if (!netif_running(dev)) {
4606 err = -ENETDOWN;
4607 goto out;
4608 }
4609 3980
4610 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { 3981 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
4611 channel_type = nla_get_u32( 3982 channel_type = nla_get_u32(
@@ -4613,24 +3984,18 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
4613 if (channel_type != NL80211_CHAN_NO_HT && 3984 if (channel_type != NL80211_CHAN_NO_HT &&
4614 channel_type != NL80211_CHAN_HT20 && 3985 channel_type != NL80211_CHAN_HT20 &&
4615 channel_type != NL80211_CHAN_HT40PLUS && 3986 channel_type != NL80211_CHAN_HT40PLUS &&
4616 channel_type != NL80211_CHAN_HT40MINUS) { 3987 channel_type != NL80211_CHAN_HT40MINUS)
4617 err = -EINVAL; 3988 return -EINVAL;
4618 goto out;
4619 }
4620 } 3989 }
4621 3990
4622 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); 3991 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
4623 chan = rdev_freq_to_chan(rdev, freq, channel_type); 3992 chan = rdev_freq_to_chan(rdev, freq, channel_type);
4624 if (chan == NULL) { 3993 if (chan == NULL)
4625 err = -EINVAL; 3994 return -EINVAL;
4626 goto out;
4627 }
4628 3995
4629 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3996 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4630 if (!msg) { 3997 if (!msg)
4631 err = -ENOMEM; 3998 return -ENOMEM;
4632 goto out;
4633 }
4634 3999
4635 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 4000 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
4636 NL80211_CMD_REMAIN_ON_CHANNEL); 4001 NL80211_CMD_REMAIN_ON_CHANNEL);
@@ -4649,58 +4014,32 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
4649 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); 4014 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
4650 4015
4651 genlmsg_end(msg, hdr); 4016 genlmsg_end(msg, hdr);
4652 err = genlmsg_reply(msg, info); 4017
4653 goto out; 4018 return genlmsg_reply(msg, info);
4654 4019
4655 nla_put_failure: 4020 nla_put_failure:
4656 err = -ENOBUFS; 4021 err = -ENOBUFS;
4657 free_msg: 4022 free_msg:
4658 nlmsg_free(msg); 4023 nlmsg_free(msg);
4659 out:
4660 cfg80211_unlock_rdev(rdev);
4661 dev_put(dev);
4662 unlock_rtnl:
4663 rtnl_unlock();
4664 return err; 4024 return err;
4665} 4025}
4666 4026
4667static int nl80211_cancel_remain_on_channel(struct sk_buff *skb, 4027static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
4668 struct genl_info *info) 4028 struct genl_info *info)
4669{ 4029{
4670 struct cfg80211_registered_device *rdev; 4030 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4671 struct net_device *dev; 4031 struct net_device *dev = info->user_ptr[1];
4672 u64 cookie; 4032 u64 cookie;
4673 int err;
4674 4033
4675 if (!info->attrs[NL80211_ATTR_COOKIE]) 4034 if (!info->attrs[NL80211_ATTR_COOKIE])
4676 return -EINVAL; 4035 return -EINVAL;
4677 4036
4678 rtnl_lock(); 4037 if (!rdev->ops->cancel_remain_on_channel)
4679 4038 return -EOPNOTSUPP;
4680 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4681 if (err)
4682 goto unlock_rtnl;
4683
4684 if (!rdev->ops->cancel_remain_on_channel) {
4685 err = -EOPNOTSUPP;
4686 goto out;
4687 }
4688
4689 if (!netif_running(dev)) {
4690 err = -ENETDOWN;
4691 goto out;
4692 }
4693 4039
4694 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]); 4040 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
4695 4041
4696 err = rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie); 4042 return rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie);
4697
4698 out:
4699 cfg80211_unlock_rdev(rdev);
4700 dev_put(dev);
4701 unlock_rtnl:
4702 rtnl_unlock();
4703 return err;
4704} 4043}
4705 4044
4706static u32 rateset_to_mask(struct ieee80211_supported_band *sband, 4045static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
@@ -4736,26 +4075,18 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
4736 struct genl_info *info) 4075 struct genl_info *info)
4737{ 4076{
4738 struct nlattr *tb[NL80211_TXRATE_MAX + 1]; 4077 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
4739 struct cfg80211_registered_device *rdev; 4078 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4740 struct cfg80211_bitrate_mask mask; 4079 struct cfg80211_bitrate_mask mask;
4741 int err, rem, i; 4080 int rem, i;
4742 struct net_device *dev; 4081 struct net_device *dev = info->user_ptr[1];
4743 struct nlattr *tx_rates; 4082 struct nlattr *tx_rates;
4744 struct ieee80211_supported_band *sband; 4083 struct ieee80211_supported_band *sband;
4745 4084
4746 if (info->attrs[NL80211_ATTR_TX_RATES] == NULL) 4085 if (info->attrs[NL80211_ATTR_TX_RATES] == NULL)
4747 return -EINVAL; 4086 return -EINVAL;
4748 4087
4749 rtnl_lock(); 4088 if (!rdev->ops->set_bitrate_mask)
4750 4089 return -EOPNOTSUPP;
4751 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4752 if (err)
4753 goto unlock_rtnl;
4754
4755 if (!rdev->ops->set_bitrate_mask) {
4756 err = -EOPNOTSUPP;
4757 goto unlock;
4758 }
4759 4090
4760 memset(&mask, 0, sizeof(mask)); 4091 memset(&mask, 0, sizeof(mask));
4761 /* Default to all rates enabled */ 4092 /* Default to all rates enabled */
@@ -4772,15 +4103,11 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
4772 nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) 4103 nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
4773 { 4104 {
4774 enum ieee80211_band band = nla_type(tx_rates); 4105 enum ieee80211_band band = nla_type(tx_rates);
4775 if (band < 0 || band >= IEEE80211_NUM_BANDS) { 4106 if (band < 0 || band >= IEEE80211_NUM_BANDS)
4776 err = -EINVAL; 4107 return -EINVAL;
4777 goto unlock;
4778 }
4779 sband = rdev->wiphy.bands[band]; 4108 sband = rdev->wiphy.bands[band];
4780 if (sband == NULL) { 4109 if (sband == NULL)
4781 err = -EINVAL; 4110 return -EINVAL;
4782 goto unlock;
4783 }
4784 nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), 4111 nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
4785 nla_len(tx_rates), nl80211_txattr_policy); 4112 nla_len(tx_rates), nl80211_txattr_policy);
4786 if (tb[NL80211_TXRATE_LEGACY]) { 4113 if (tb[NL80211_TXRATE_LEGACY]) {
@@ -4788,29 +4115,19 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
4788 sband, 4115 sband,
4789 nla_data(tb[NL80211_TXRATE_LEGACY]), 4116 nla_data(tb[NL80211_TXRATE_LEGACY]),
4790 nla_len(tb[NL80211_TXRATE_LEGACY])); 4117 nla_len(tb[NL80211_TXRATE_LEGACY]));
4791 if (mask.control[band].legacy == 0) { 4118 if (mask.control[band].legacy == 0)
4792 err = -EINVAL; 4119 return -EINVAL;
4793 goto unlock;
4794 }
4795 } 4120 }
4796 } 4121 }
4797 4122
4798 err = rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask); 4123 return rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask);
4799
4800 unlock:
4801 dev_put(dev);
4802 cfg80211_unlock_rdev(rdev);
4803 unlock_rtnl:
4804 rtnl_unlock();
4805 return err;
4806} 4124}
4807 4125
4808static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) 4126static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
4809{ 4127{
4810 struct cfg80211_registered_device *rdev; 4128 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4811 struct net_device *dev; 4129 struct net_device *dev = info->user_ptr[1];
4812 u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION; 4130 u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
4813 int err;
4814 4131
4815 if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) 4132 if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
4816 return -EINVAL; 4133 return -EINVAL;
@@ -4818,41 +4135,28 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
4818 if (info->attrs[NL80211_ATTR_FRAME_TYPE]) 4135 if (info->attrs[NL80211_ATTR_FRAME_TYPE])
4819 frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]); 4136 frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
4820 4137
4821 rtnl_lock();
4822
4823 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4824 if (err)
4825 goto unlock_rtnl;
4826
4827 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 4138 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4828 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && 4139 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
4829 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 4140 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
4830 err = -EOPNOTSUPP; 4141 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4831 goto out; 4142 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
4832 } 4143 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4144 return -EOPNOTSUPP;
4833 4145
4834 /* not much point in registering if we can't reply */ 4146 /* not much point in registering if we can't reply */
4835 if (!rdev->ops->mgmt_tx) { 4147 if (!rdev->ops->mgmt_tx)
4836 err = -EOPNOTSUPP; 4148 return -EOPNOTSUPP;
4837 goto out;
4838 }
4839 4149
4840 err = cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid, 4150 return cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid,
4841 frame_type, 4151 frame_type,
4842 nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), 4152 nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
4843 nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); 4153 nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
4844 out:
4845 cfg80211_unlock_rdev(rdev);
4846 dev_put(dev);
4847 unlock_rtnl:
4848 rtnl_unlock();
4849 return err;
4850} 4154}
4851 4155
4852static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) 4156static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
4853{ 4157{
4854 struct cfg80211_registered_device *rdev; 4158 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4855 struct net_device *dev; 4159 struct net_device *dev = info->user_ptr[1];
4856 struct ieee80211_channel *chan; 4160 struct ieee80211_channel *chan;
4857 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 4161 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
4858 bool channel_type_valid = false; 4162 bool channel_type_valid = false;
@@ -4866,28 +4170,16 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
4866 !info->attrs[NL80211_ATTR_WIPHY_FREQ]) 4170 !info->attrs[NL80211_ATTR_WIPHY_FREQ])
4867 return -EINVAL; 4171 return -EINVAL;
4868 4172
4869 rtnl_lock(); 4173 if (!rdev->ops->mgmt_tx)
4870 4174 return -EOPNOTSUPP;
4871 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4872 if (err)
4873 goto unlock_rtnl;
4874
4875 if (!rdev->ops->mgmt_tx) {
4876 err = -EOPNOTSUPP;
4877 goto out;
4878 }
4879 4175
4880 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && 4176 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4881 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && 4177 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
4882 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { 4178 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
4883 err = -EOPNOTSUPP; 4179 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4884 goto out; 4180 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
4885 } 4181 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4886 4182 return -EOPNOTSUPP;
4887 if (!netif_running(dev)) {
4888 err = -ENETDOWN;
4889 goto out;
4890 }
4891 4183
4892 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { 4184 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
4893 channel_type = nla_get_u32( 4185 channel_type = nla_get_u32(
@@ -4895,25 +4187,19 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
4895 if (channel_type != NL80211_CHAN_NO_HT && 4187 if (channel_type != NL80211_CHAN_NO_HT &&
4896 channel_type != NL80211_CHAN_HT20 && 4188 channel_type != NL80211_CHAN_HT20 &&
4897 channel_type != NL80211_CHAN_HT40PLUS && 4189 channel_type != NL80211_CHAN_HT40PLUS &&
4898 channel_type != NL80211_CHAN_HT40MINUS) { 4190 channel_type != NL80211_CHAN_HT40MINUS)
4899 err = -EINVAL; 4191 return -EINVAL;
4900 goto out;
4901 }
4902 channel_type_valid = true; 4192 channel_type_valid = true;
4903 } 4193 }
4904 4194
4905 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); 4195 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
4906 chan = rdev_freq_to_chan(rdev, freq, channel_type); 4196 chan = rdev_freq_to_chan(rdev, freq, channel_type);
4907 if (chan == NULL) { 4197 if (chan == NULL)
4908 err = -EINVAL; 4198 return -EINVAL;
4909 goto out;
4910 }
4911 4199
4912 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4200 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4913 if (!msg) { 4201 if (!msg)
4914 err = -ENOMEM; 4202 return -ENOMEM;
4915 goto out;
4916 }
4917 4203
4918 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 4204 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
4919 NL80211_CMD_FRAME); 4205 NL80211_CMD_FRAME);
@@ -4933,110 +4219,72 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
4933 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); 4219 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
4934 4220
4935 genlmsg_end(msg, hdr); 4221 genlmsg_end(msg, hdr);
4936 err = genlmsg_reply(msg, info); 4222 return genlmsg_reply(msg, info);
4937 goto out;
4938 4223
4939 nla_put_failure: 4224 nla_put_failure:
4940 err = -ENOBUFS; 4225 err = -ENOBUFS;
4941 free_msg: 4226 free_msg:
4942 nlmsg_free(msg); 4227 nlmsg_free(msg);
4943 out:
4944 cfg80211_unlock_rdev(rdev);
4945 dev_put(dev);
4946unlock_rtnl:
4947 rtnl_unlock();
4948 return err; 4228 return err;
4949} 4229}
4950 4230
4951static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info) 4231static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
4952{ 4232{
4953 struct cfg80211_registered_device *rdev; 4233 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4954 struct wireless_dev *wdev; 4234 struct wireless_dev *wdev;
4955 struct net_device *dev; 4235 struct net_device *dev = info->user_ptr[1];
4956 u8 ps_state; 4236 u8 ps_state;
4957 bool state; 4237 bool state;
4958 int err; 4238 int err;
4959 4239
4960 if (!info->attrs[NL80211_ATTR_PS_STATE]) { 4240 if (!info->attrs[NL80211_ATTR_PS_STATE])
4961 err = -EINVAL; 4241 return -EINVAL;
4962 goto out;
4963 }
4964 4242
4965 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]); 4243 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
4966 4244
4967 if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED) { 4245 if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED)
4968 err = -EINVAL; 4246 return -EINVAL;
4969 goto out;
4970 }
4971
4972 rtnl_lock();
4973
4974 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4975 if (err)
4976 goto unlock_rtnl;
4977 4247
4978 wdev = dev->ieee80211_ptr; 4248 wdev = dev->ieee80211_ptr;
4979 4249
4980 if (!rdev->ops->set_power_mgmt) { 4250 if (!rdev->ops->set_power_mgmt)
4981 err = -EOPNOTSUPP; 4251 return -EOPNOTSUPP;
4982 goto unlock_rdev;
4983 }
4984 4252
4985 state = (ps_state == NL80211_PS_ENABLED) ? true : false; 4253 state = (ps_state == NL80211_PS_ENABLED) ? true : false;
4986 4254
4987 if (state == wdev->ps) 4255 if (state == wdev->ps)
4988 goto unlock_rdev; 4256 return 0;
4989
4990 wdev->ps = state;
4991
4992 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, wdev->ps,
4993 wdev->ps_timeout))
4994 /* assume this means it's off */
4995 wdev->ps = false;
4996
4997unlock_rdev:
4998 cfg80211_unlock_rdev(rdev);
4999 dev_put(dev);
5000unlock_rtnl:
5001 rtnl_unlock();
5002 4257
5003out: 4258 err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, state,
4259 wdev->ps_timeout);
4260 if (!err)
4261 wdev->ps = state;
5004 return err; 4262 return err;
5005} 4263}
5006 4264
5007static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) 4265static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
5008{ 4266{
5009 struct cfg80211_registered_device *rdev; 4267 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5010 enum nl80211_ps_state ps_state; 4268 enum nl80211_ps_state ps_state;
5011 struct wireless_dev *wdev; 4269 struct wireless_dev *wdev;
5012 struct net_device *dev; 4270 struct net_device *dev = info->user_ptr[1];
5013 struct sk_buff *msg; 4271 struct sk_buff *msg;
5014 void *hdr; 4272 void *hdr;
5015 int err; 4273 int err;
5016 4274
5017 rtnl_lock();
5018
5019 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
5020 if (err)
5021 goto unlock_rtnl;
5022
5023 wdev = dev->ieee80211_ptr; 4275 wdev = dev->ieee80211_ptr;
5024 4276
5025 if (!rdev->ops->set_power_mgmt) { 4277 if (!rdev->ops->set_power_mgmt)
5026 err = -EOPNOTSUPP; 4278 return -EOPNOTSUPP;
5027 goto out;
5028 }
5029 4279
5030 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4280 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5031 if (!msg) { 4281 if (!msg)
5032 err = -ENOMEM; 4282 return -ENOMEM;
5033 goto out;
5034 }
5035 4283
5036 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 4284 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
5037 NL80211_CMD_GET_POWER_SAVE); 4285 NL80211_CMD_GET_POWER_SAVE);
5038 if (!hdr) { 4286 if (!hdr) {
5039 err = -ENOMEM; 4287 err = -ENOBUFS;
5040 goto free_msg; 4288 goto free_msg;
5041 } 4289 }
5042 4290
@@ -5048,22 +4296,12 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
5048 NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state); 4296 NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state);
5049 4297
5050 genlmsg_end(msg, hdr); 4298 genlmsg_end(msg, hdr);
5051 err = genlmsg_reply(msg, info); 4299 return genlmsg_reply(msg, info);
5052 goto out;
5053 4300
5054nla_put_failure: 4301 nla_put_failure:
5055 err = -ENOBUFS; 4302 err = -ENOBUFS;
5056 4303 free_msg:
5057free_msg:
5058 nlmsg_free(msg); 4304 nlmsg_free(msg);
5059
5060out:
5061 cfg80211_unlock_rdev(rdev);
5062 dev_put(dev);
5063
5064unlock_rtnl:
5065 rtnl_unlock();
5066
5067 return err; 4305 return err;
5068} 4306}
5069 4307
@@ -5077,42 +4315,24 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = {
5077static int nl80211_set_cqm_rssi(struct genl_info *info, 4315static int nl80211_set_cqm_rssi(struct genl_info *info,
5078 s32 threshold, u32 hysteresis) 4316 s32 threshold, u32 hysteresis)
5079{ 4317{
5080 struct cfg80211_registered_device *rdev; 4318 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5081 struct wireless_dev *wdev; 4319 struct wireless_dev *wdev;
5082 struct net_device *dev; 4320 struct net_device *dev = info->user_ptr[1];
5083 int err;
5084 4321
5085 if (threshold > 0) 4322 if (threshold > 0)
5086 return -EINVAL; 4323 return -EINVAL;
5087 4324
5088 rtnl_lock();
5089
5090 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
5091 if (err)
5092 goto unlock_rdev;
5093
5094 wdev = dev->ieee80211_ptr; 4325 wdev = dev->ieee80211_ptr;
5095 4326
5096 if (!rdev->ops->set_cqm_rssi_config) { 4327 if (!rdev->ops->set_cqm_rssi_config)
5097 err = -EOPNOTSUPP; 4328 return -EOPNOTSUPP;
5098 goto unlock_rdev;
5099 }
5100 4329
5101 if (wdev->iftype != NL80211_IFTYPE_STATION && 4330 if (wdev->iftype != NL80211_IFTYPE_STATION &&
5102 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) { 4331 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
5103 err = -EOPNOTSUPP; 4332 return -EOPNOTSUPP;
5104 goto unlock_rdev;
5105 }
5106
5107 err = rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev,
5108 threshold, hysteresis);
5109
5110unlock_rdev:
5111 cfg80211_unlock_rdev(rdev);
5112 dev_put(dev);
5113 rtnl_unlock();
5114 4333
5115 return err; 4334 return rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev,
4335 threshold, hysteresis);
5116} 4336}
5117 4337
5118static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) 4338static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
@@ -5146,6 +4366,65 @@ out:
5146 return err; 4366 return err;
5147} 4367}
5148 4368
4369#define NL80211_FLAG_NEED_WIPHY 0x01
4370#define NL80211_FLAG_NEED_NETDEV 0x02
4371#define NL80211_FLAG_NEED_RTNL 0x04
4372#define NL80211_FLAG_CHECK_NETDEV_UP 0x08
4373#define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\
4374 NL80211_FLAG_CHECK_NETDEV_UP)
4375
4376static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
4377 struct genl_info *info)
4378{
4379 struct cfg80211_registered_device *rdev;
4380 struct net_device *dev;
4381 int err;
4382 bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL;
4383
4384 if (rtnl)
4385 rtnl_lock();
4386
4387 if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
4388 rdev = cfg80211_get_dev_from_info(info);
4389 if (IS_ERR(rdev)) {
4390 if (rtnl)
4391 rtnl_unlock();
4392 return PTR_ERR(rdev);
4393 }
4394 info->user_ptr[0] = rdev;
4395 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
4396 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4397 if (err) {
4398 if (rtnl)
4399 rtnl_unlock();
4400 return err;
4401 }
4402 if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
4403 !netif_running(dev)) {
4404 cfg80211_unlock_rdev(rdev);
4405 dev_put(dev);
4406 if (rtnl)
4407 rtnl_unlock();
4408 return -ENETDOWN;
4409 }
4410 info->user_ptr[0] = rdev;
4411 info->user_ptr[1] = dev;
4412 }
4413
4414 return 0;
4415}
4416
4417static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
4418 struct genl_info *info)
4419{
4420 if (info->user_ptr[0])
4421 cfg80211_unlock_rdev(info->user_ptr[0]);
4422 if (info->user_ptr[1])
4423 dev_put(info->user_ptr[1]);
4424 if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
4425 rtnl_unlock();
4426}
4427
5149static struct genl_ops nl80211_ops[] = { 4428static struct genl_ops nl80211_ops[] = {
5150 { 4429 {
5151 .cmd = NL80211_CMD_GET_WIPHY, 4430 .cmd = NL80211_CMD_GET_WIPHY,
@@ -5153,12 +4432,14 @@ static struct genl_ops nl80211_ops[] = {
5153 .dumpit = nl80211_dump_wiphy, 4432 .dumpit = nl80211_dump_wiphy,
5154 .policy = nl80211_policy, 4433 .policy = nl80211_policy,
5155 /* can be retrieved by unprivileged users */ 4434 /* can be retrieved by unprivileged users */
4435 .internal_flags = NL80211_FLAG_NEED_WIPHY,
5156 }, 4436 },
5157 { 4437 {
5158 .cmd = NL80211_CMD_SET_WIPHY, 4438 .cmd = NL80211_CMD_SET_WIPHY,
5159 .doit = nl80211_set_wiphy, 4439 .doit = nl80211_set_wiphy,
5160 .policy = nl80211_policy, 4440 .policy = nl80211_policy,
5161 .flags = GENL_ADMIN_PERM, 4441 .flags = GENL_ADMIN_PERM,
4442 .internal_flags = NL80211_FLAG_NEED_RTNL,
5162 }, 4443 },
5163 { 4444 {
5164 .cmd = NL80211_CMD_GET_INTERFACE, 4445 .cmd = NL80211_CMD_GET_INTERFACE,
@@ -5166,90 +4447,119 @@ static struct genl_ops nl80211_ops[] = {
5166 .dumpit = nl80211_dump_interface, 4447 .dumpit = nl80211_dump_interface,
5167 .policy = nl80211_policy, 4448 .policy = nl80211_policy,
5168 /* can be retrieved by unprivileged users */ 4449 /* can be retrieved by unprivileged users */
4450 .internal_flags = NL80211_FLAG_NEED_NETDEV,
5169 }, 4451 },
5170 { 4452 {
5171 .cmd = NL80211_CMD_SET_INTERFACE, 4453 .cmd = NL80211_CMD_SET_INTERFACE,
5172 .doit = nl80211_set_interface, 4454 .doit = nl80211_set_interface,
5173 .policy = nl80211_policy, 4455 .policy = nl80211_policy,
5174 .flags = GENL_ADMIN_PERM, 4456 .flags = GENL_ADMIN_PERM,
4457 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4458 NL80211_FLAG_NEED_RTNL,
5175 }, 4459 },
5176 { 4460 {
5177 .cmd = NL80211_CMD_NEW_INTERFACE, 4461 .cmd = NL80211_CMD_NEW_INTERFACE,
5178 .doit = nl80211_new_interface, 4462 .doit = nl80211_new_interface,
5179 .policy = nl80211_policy, 4463 .policy = nl80211_policy,
5180 .flags = GENL_ADMIN_PERM, 4464 .flags = GENL_ADMIN_PERM,
4465 .internal_flags = NL80211_FLAG_NEED_WIPHY |
4466 NL80211_FLAG_NEED_RTNL,
5181 }, 4467 },
5182 { 4468 {
5183 .cmd = NL80211_CMD_DEL_INTERFACE, 4469 .cmd = NL80211_CMD_DEL_INTERFACE,
5184 .doit = nl80211_del_interface, 4470 .doit = nl80211_del_interface,
5185 .policy = nl80211_policy, 4471 .policy = nl80211_policy,
5186 .flags = GENL_ADMIN_PERM, 4472 .flags = GENL_ADMIN_PERM,
4473 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4474 NL80211_FLAG_NEED_RTNL,
5187 }, 4475 },
5188 { 4476 {
5189 .cmd = NL80211_CMD_GET_KEY, 4477 .cmd = NL80211_CMD_GET_KEY,
5190 .doit = nl80211_get_key, 4478 .doit = nl80211_get_key,
5191 .policy = nl80211_policy, 4479 .policy = nl80211_policy,
5192 .flags = GENL_ADMIN_PERM, 4480 .flags = GENL_ADMIN_PERM,
4481 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4482 NL80211_FLAG_NEED_RTNL,
5193 }, 4483 },
5194 { 4484 {
5195 .cmd = NL80211_CMD_SET_KEY, 4485 .cmd = NL80211_CMD_SET_KEY,
5196 .doit = nl80211_set_key, 4486 .doit = nl80211_set_key,
5197 .policy = nl80211_policy, 4487 .policy = nl80211_policy,
5198 .flags = GENL_ADMIN_PERM, 4488 .flags = GENL_ADMIN_PERM,
4489 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4490 NL80211_FLAG_NEED_RTNL,
5199 }, 4491 },
5200 { 4492 {
5201 .cmd = NL80211_CMD_NEW_KEY, 4493 .cmd = NL80211_CMD_NEW_KEY,
5202 .doit = nl80211_new_key, 4494 .doit = nl80211_new_key,
5203 .policy = nl80211_policy, 4495 .policy = nl80211_policy,
5204 .flags = GENL_ADMIN_PERM, 4496 .flags = GENL_ADMIN_PERM,
4497 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4498 NL80211_FLAG_NEED_RTNL,
5205 }, 4499 },
5206 { 4500 {
5207 .cmd = NL80211_CMD_DEL_KEY, 4501 .cmd = NL80211_CMD_DEL_KEY,
5208 .doit = nl80211_del_key, 4502 .doit = nl80211_del_key,
5209 .policy = nl80211_policy, 4503 .policy = nl80211_policy,
5210 .flags = GENL_ADMIN_PERM, 4504 .flags = GENL_ADMIN_PERM,
4505 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4506 NL80211_FLAG_NEED_RTNL,
5211 }, 4507 },
5212 { 4508 {
5213 .cmd = NL80211_CMD_SET_BEACON, 4509 .cmd = NL80211_CMD_SET_BEACON,
5214 .policy = nl80211_policy, 4510 .policy = nl80211_policy,
5215 .flags = GENL_ADMIN_PERM, 4511 .flags = GENL_ADMIN_PERM,
5216 .doit = nl80211_addset_beacon, 4512 .doit = nl80211_addset_beacon,
4513 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4514 NL80211_FLAG_NEED_RTNL,
5217 }, 4515 },
5218 { 4516 {
5219 .cmd = NL80211_CMD_NEW_BEACON, 4517 .cmd = NL80211_CMD_NEW_BEACON,
5220 .policy = nl80211_policy, 4518 .policy = nl80211_policy,
5221 .flags = GENL_ADMIN_PERM, 4519 .flags = GENL_ADMIN_PERM,
5222 .doit = nl80211_addset_beacon, 4520 .doit = nl80211_addset_beacon,
4521 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4522 NL80211_FLAG_NEED_RTNL,
5223 }, 4523 },
5224 { 4524 {
5225 .cmd = NL80211_CMD_DEL_BEACON, 4525 .cmd = NL80211_CMD_DEL_BEACON,
5226 .policy = nl80211_policy, 4526 .policy = nl80211_policy,
5227 .flags = GENL_ADMIN_PERM, 4527 .flags = GENL_ADMIN_PERM,
5228 .doit = nl80211_del_beacon, 4528 .doit = nl80211_del_beacon,
4529 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4530 NL80211_FLAG_NEED_RTNL,
5229 }, 4531 },
5230 { 4532 {
5231 .cmd = NL80211_CMD_GET_STATION, 4533 .cmd = NL80211_CMD_GET_STATION,
5232 .doit = nl80211_get_station, 4534 .doit = nl80211_get_station,
5233 .dumpit = nl80211_dump_station, 4535 .dumpit = nl80211_dump_station,
5234 .policy = nl80211_policy, 4536 .policy = nl80211_policy,
4537 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4538 NL80211_FLAG_NEED_RTNL,
5235 }, 4539 },
5236 { 4540 {
5237 .cmd = NL80211_CMD_SET_STATION, 4541 .cmd = NL80211_CMD_SET_STATION,
5238 .doit = nl80211_set_station, 4542 .doit = nl80211_set_station,
5239 .policy = nl80211_policy, 4543 .policy = nl80211_policy,
5240 .flags = GENL_ADMIN_PERM, 4544 .flags = GENL_ADMIN_PERM,
4545 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4546 NL80211_FLAG_NEED_RTNL,
5241 }, 4547 },
5242 { 4548 {
5243 .cmd = NL80211_CMD_NEW_STATION, 4549 .cmd = NL80211_CMD_NEW_STATION,
5244 .doit = nl80211_new_station, 4550 .doit = nl80211_new_station,
5245 .policy = nl80211_policy, 4551 .policy = nl80211_policy,
5246 .flags = GENL_ADMIN_PERM, 4552 .flags = GENL_ADMIN_PERM,
4553 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4554 NL80211_FLAG_NEED_RTNL,
5247 }, 4555 },
5248 { 4556 {
5249 .cmd = NL80211_CMD_DEL_STATION, 4557 .cmd = NL80211_CMD_DEL_STATION,
5250 .doit = nl80211_del_station, 4558 .doit = nl80211_del_station,
5251 .policy = nl80211_policy, 4559 .policy = nl80211_policy,
5252 .flags = GENL_ADMIN_PERM, 4560 .flags = GENL_ADMIN_PERM,
4561 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4562 NL80211_FLAG_NEED_RTNL,
5253 }, 4563 },
5254 { 4564 {
5255 .cmd = NL80211_CMD_GET_MPATH, 4565 .cmd = NL80211_CMD_GET_MPATH,
@@ -5257,30 +4567,40 @@ static struct genl_ops nl80211_ops[] = {
5257 .dumpit = nl80211_dump_mpath, 4567 .dumpit = nl80211_dump_mpath,
5258 .policy = nl80211_policy, 4568 .policy = nl80211_policy,
5259 .flags = GENL_ADMIN_PERM, 4569 .flags = GENL_ADMIN_PERM,
4570 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4571 NL80211_FLAG_NEED_RTNL,
5260 }, 4572 },
5261 { 4573 {
5262 .cmd = NL80211_CMD_SET_MPATH, 4574 .cmd = NL80211_CMD_SET_MPATH,
5263 .doit = nl80211_set_mpath, 4575 .doit = nl80211_set_mpath,
5264 .policy = nl80211_policy, 4576 .policy = nl80211_policy,
5265 .flags = GENL_ADMIN_PERM, 4577 .flags = GENL_ADMIN_PERM,
4578 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4579 NL80211_FLAG_NEED_RTNL,
5266 }, 4580 },
5267 { 4581 {
5268 .cmd = NL80211_CMD_NEW_MPATH, 4582 .cmd = NL80211_CMD_NEW_MPATH,
5269 .doit = nl80211_new_mpath, 4583 .doit = nl80211_new_mpath,
5270 .policy = nl80211_policy, 4584 .policy = nl80211_policy,
5271 .flags = GENL_ADMIN_PERM, 4585 .flags = GENL_ADMIN_PERM,
4586 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4587 NL80211_FLAG_NEED_RTNL,
5272 }, 4588 },
5273 { 4589 {
5274 .cmd = NL80211_CMD_DEL_MPATH, 4590 .cmd = NL80211_CMD_DEL_MPATH,
5275 .doit = nl80211_del_mpath, 4591 .doit = nl80211_del_mpath,
5276 .policy = nl80211_policy, 4592 .policy = nl80211_policy,
5277 .flags = GENL_ADMIN_PERM, 4593 .flags = GENL_ADMIN_PERM,
4594 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4595 NL80211_FLAG_NEED_RTNL,
5278 }, 4596 },
5279 { 4597 {
5280 .cmd = NL80211_CMD_SET_BSS, 4598 .cmd = NL80211_CMD_SET_BSS,
5281 .doit = nl80211_set_bss, 4599 .doit = nl80211_set_bss,
5282 .policy = nl80211_policy, 4600 .policy = nl80211_policy,
5283 .flags = GENL_ADMIN_PERM, 4601 .flags = GENL_ADMIN_PERM,
4602 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4603 NL80211_FLAG_NEED_RTNL,
5284 }, 4604 },
5285 { 4605 {
5286 .cmd = NL80211_CMD_GET_REG, 4606 .cmd = NL80211_CMD_GET_REG,
@@ -5305,18 +4625,24 @@ static struct genl_ops nl80211_ops[] = {
5305 .doit = nl80211_get_mesh_params, 4625 .doit = nl80211_get_mesh_params,
5306 .policy = nl80211_policy, 4626 .policy = nl80211_policy,
5307 /* can be retrieved by unprivileged users */ 4627 /* can be retrieved by unprivileged users */
4628 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4629 NL80211_FLAG_NEED_RTNL,
5308 }, 4630 },
5309 { 4631 {
5310 .cmd = NL80211_CMD_SET_MESH_PARAMS, 4632 .cmd = NL80211_CMD_SET_MESH_PARAMS,
5311 .doit = nl80211_set_mesh_params, 4633 .doit = nl80211_set_mesh_params,
5312 .policy = nl80211_policy, 4634 .policy = nl80211_policy,
5313 .flags = GENL_ADMIN_PERM, 4635 .flags = GENL_ADMIN_PERM,
4636 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4637 NL80211_FLAG_NEED_RTNL,
5314 }, 4638 },
5315 { 4639 {
5316 .cmd = NL80211_CMD_TRIGGER_SCAN, 4640 .cmd = NL80211_CMD_TRIGGER_SCAN,
5317 .doit = nl80211_trigger_scan, 4641 .doit = nl80211_trigger_scan,
5318 .policy = nl80211_policy, 4642 .policy = nl80211_policy,
5319 .flags = GENL_ADMIN_PERM, 4643 .flags = GENL_ADMIN_PERM,
4644 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4645 NL80211_FLAG_NEED_RTNL,
5320 }, 4646 },
5321 { 4647 {
5322 .cmd = NL80211_CMD_GET_SCAN, 4648 .cmd = NL80211_CMD_GET_SCAN,
@@ -5328,36 +4654,48 @@ static struct genl_ops nl80211_ops[] = {
5328 .doit = nl80211_authenticate, 4654 .doit = nl80211_authenticate,
5329 .policy = nl80211_policy, 4655 .policy = nl80211_policy,
5330 .flags = GENL_ADMIN_PERM, 4656 .flags = GENL_ADMIN_PERM,
4657 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4658 NL80211_FLAG_NEED_RTNL,
5331 }, 4659 },
5332 { 4660 {
5333 .cmd = NL80211_CMD_ASSOCIATE, 4661 .cmd = NL80211_CMD_ASSOCIATE,
5334 .doit = nl80211_associate, 4662 .doit = nl80211_associate,
5335 .policy = nl80211_policy, 4663 .policy = nl80211_policy,
5336 .flags = GENL_ADMIN_PERM, 4664 .flags = GENL_ADMIN_PERM,
4665 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4666 NL80211_FLAG_NEED_RTNL,
5337 }, 4667 },
5338 { 4668 {
5339 .cmd = NL80211_CMD_DEAUTHENTICATE, 4669 .cmd = NL80211_CMD_DEAUTHENTICATE,
5340 .doit = nl80211_deauthenticate, 4670 .doit = nl80211_deauthenticate,
5341 .policy = nl80211_policy, 4671 .policy = nl80211_policy,
5342 .flags = GENL_ADMIN_PERM, 4672 .flags = GENL_ADMIN_PERM,
4673 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4674 NL80211_FLAG_NEED_RTNL,
5343 }, 4675 },
5344 { 4676 {
5345 .cmd = NL80211_CMD_DISASSOCIATE, 4677 .cmd = NL80211_CMD_DISASSOCIATE,
5346 .doit = nl80211_disassociate, 4678 .doit = nl80211_disassociate,
5347 .policy = nl80211_policy, 4679 .policy = nl80211_policy,
5348 .flags = GENL_ADMIN_PERM, 4680 .flags = GENL_ADMIN_PERM,
4681 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4682 NL80211_FLAG_NEED_RTNL,
5349 }, 4683 },
5350 { 4684 {
5351 .cmd = NL80211_CMD_JOIN_IBSS, 4685 .cmd = NL80211_CMD_JOIN_IBSS,
5352 .doit = nl80211_join_ibss, 4686 .doit = nl80211_join_ibss,
5353 .policy = nl80211_policy, 4687 .policy = nl80211_policy,
5354 .flags = GENL_ADMIN_PERM, 4688 .flags = GENL_ADMIN_PERM,
4689 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4690 NL80211_FLAG_NEED_RTNL,
5355 }, 4691 },
5356 { 4692 {
5357 .cmd = NL80211_CMD_LEAVE_IBSS, 4693 .cmd = NL80211_CMD_LEAVE_IBSS,
5358 .doit = nl80211_leave_ibss, 4694 .doit = nl80211_leave_ibss,
5359 .policy = nl80211_policy, 4695 .policy = nl80211_policy,
5360 .flags = GENL_ADMIN_PERM, 4696 .flags = GENL_ADMIN_PERM,
4697 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4698 NL80211_FLAG_NEED_RTNL,
5361 }, 4699 },
5362#ifdef CONFIG_NL80211_TESTMODE 4700#ifdef CONFIG_NL80211_TESTMODE
5363 { 4701 {
@@ -5365,6 +4703,8 @@ static struct genl_ops nl80211_ops[] = {
5365 .doit = nl80211_testmode_do, 4703 .doit = nl80211_testmode_do,
5366 .policy = nl80211_policy, 4704 .policy = nl80211_policy,
5367 .flags = GENL_ADMIN_PERM, 4705 .flags = GENL_ADMIN_PERM,
4706 .internal_flags = NL80211_FLAG_NEED_WIPHY |
4707 NL80211_FLAG_NEED_RTNL,
5368 }, 4708 },
5369#endif 4709#endif
5370 { 4710 {
@@ -5372,18 +4712,24 @@ static struct genl_ops nl80211_ops[] = {
5372 .doit = nl80211_connect, 4712 .doit = nl80211_connect,
5373 .policy = nl80211_policy, 4713 .policy = nl80211_policy,
5374 .flags = GENL_ADMIN_PERM, 4714 .flags = GENL_ADMIN_PERM,
4715 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4716 NL80211_FLAG_NEED_RTNL,
5375 }, 4717 },
5376 { 4718 {
5377 .cmd = NL80211_CMD_DISCONNECT, 4719 .cmd = NL80211_CMD_DISCONNECT,
5378 .doit = nl80211_disconnect, 4720 .doit = nl80211_disconnect,
5379 .policy = nl80211_policy, 4721 .policy = nl80211_policy,
5380 .flags = GENL_ADMIN_PERM, 4722 .flags = GENL_ADMIN_PERM,
4723 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4724 NL80211_FLAG_NEED_RTNL,
5381 }, 4725 },
5382 { 4726 {
5383 .cmd = NL80211_CMD_SET_WIPHY_NETNS, 4727 .cmd = NL80211_CMD_SET_WIPHY_NETNS,
5384 .doit = nl80211_wiphy_netns, 4728 .doit = nl80211_wiphy_netns,
5385 .policy = nl80211_policy, 4729 .policy = nl80211_policy,
5386 .flags = GENL_ADMIN_PERM, 4730 .flags = GENL_ADMIN_PERM,
4731 .internal_flags = NL80211_FLAG_NEED_WIPHY |
4732 NL80211_FLAG_NEED_RTNL,
5387 }, 4733 },
5388 { 4734 {
5389 .cmd = NL80211_CMD_GET_SURVEY, 4735 .cmd = NL80211_CMD_GET_SURVEY,
@@ -5395,72 +4741,104 @@ static struct genl_ops nl80211_ops[] = {
5395 .doit = nl80211_setdel_pmksa, 4741 .doit = nl80211_setdel_pmksa,
5396 .policy = nl80211_policy, 4742 .policy = nl80211_policy,
5397 .flags = GENL_ADMIN_PERM, 4743 .flags = GENL_ADMIN_PERM,
4744 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4745 NL80211_FLAG_NEED_RTNL,
5398 }, 4746 },
5399 { 4747 {
5400 .cmd = NL80211_CMD_DEL_PMKSA, 4748 .cmd = NL80211_CMD_DEL_PMKSA,
5401 .doit = nl80211_setdel_pmksa, 4749 .doit = nl80211_setdel_pmksa,
5402 .policy = nl80211_policy, 4750 .policy = nl80211_policy,
5403 .flags = GENL_ADMIN_PERM, 4751 .flags = GENL_ADMIN_PERM,
4752 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4753 NL80211_FLAG_NEED_RTNL,
5404 }, 4754 },
5405 { 4755 {
5406 .cmd = NL80211_CMD_FLUSH_PMKSA, 4756 .cmd = NL80211_CMD_FLUSH_PMKSA,
5407 .doit = nl80211_flush_pmksa, 4757 .doit = nl80211_flush_pmksa,
5408 .policy = nl80211_policy, 4758 .policy = nl80211_policy,
5409 .flags = GENL_ADMIN_PERM, 4759 .flags = GENL_ADMIN_PERM,
4760 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4761 NL80211_FLAG_NEED_RTNL,
5410 }, 4762 },
5411 { 4763 {
5412 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL, 4764 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
5413 .doit = nl80211_remain_on_channel, 4765 .doit = nl80211_remain_on_channel,
5414 .policy = nl80211_policy, 4766 .policy = nl80211_policy,
5415 .flags = GENL_ADMIN_PERM, 4767 .flags = GENL_ADMIN_PERM,
4768 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4769 NL80211_FLAG_NEED_RTNL,
5416 }, 4770 },
5417 { 4771 {
5418 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, 4772 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
5419 .doit = nl80211_cancel_remain_on_channel, 4773 .doit = nl80211_cancel_remain_on_channel,
5420 .policy = nl80211_policy, 4774 .policy = nl80211_policy,
5421 .flags = GENL_ADMIN_PERM, 4775 .flags = GENL_ADMIN_PERM,
4776 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4777 NL80211_FLAG_NEED_RTNL,
5422 }, 4778 },
5423 { 4779 {
5424 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK, 4780 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
5425 .doit = nl80211_set_tx_bitrate_mask, 4781 .doit = nl80211_set_tx_bitrate_mask,
5426 .policy = nl80211_policy, 4782 .policy = nl80211_policy,
5427 .flags = GENL_ADMIN_PERM, 4783 .flags = GENL_ADMIN_PERM,
4784 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4785 NL80211_FLAG_NEED_RTNL,
5428 }, 4786 },
5429 { 4787 {
5430 .cmd = NL80211_CMD_REGISTER_FRAME, 4788 .cmd = NL80211_CMD_REGISTER_FRAME,
5431 .doit = nl80211_register_mgmt, 4789 .doit = nl80211_register_mgmt,
5432 .policy = nl80211_policy, 4790 .policy = nl80211_policy,
5433 .flags = GENL_ADMIN_PERM, 4791 .flags = GENL_ADMIN_PERM,
4792 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4793 NL80211_FLAG_NEED_RTNL,
5434 }, 4794 },
5435 { 4795 {
5436 .cmd = NL80211_CMD_FRAME, 4796 .cmd = NL80211_CMD_FRAME,
5437 .doit = nl80211_tx_mgmt, 4797 .doit = nl80211_tx_mgmt,
5438 .policy = nl80211_policy, 4798 .policy = nl80211_policy,
5439 .flags = GENL_ADMIN_PERM, 4799 .flags = GENL_ADMIN_PERM,
4800 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4801 NL80211_FLAG_NEED_RTNL,
5440 }, 4802 },
5441 { 4803 {
5442 .cmd = NL80211_CMD_SET_POWER_SAVE, 4804 .cmd = NL80211_CMD_SET_POWER_SAVE,
5443 .doit = nl80211_set_power_save, 4805 .doit = nl80211_set_power_save,
5444 .policy = nl80211_policy, 4806 .policy = nl80211_policy,
5445 .flags = GENL_ADMIN_PERM, 4807 .flags = GENL_ADMIN_PERM,
4808 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4809 NL80211_FLAG_NEED_RTNL,
5446 }, 4810 },
5447 { 4811 {
5448 .cmd = NL80211_CMD_GET_POWER_SAVE, 4812 .cmd = NL80211_CMD_GET_POWER_SAVE,
5449 .doit = nl80211_get_power_save, 4813 .doit = nl80211_get_power_save,
5450 .policy = nl80211_policy, 4814 .policy = nl80211_policy,
5451 /* can be retrieved by unprivileged users */ 4815 /* can be retrieved by unprivileged users */
4816 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4817 NL80211_FLAG_NEED_RTNL,
5452 }, 4818 },
5453 { 4819 {
5454 .cmd = NL80211_CMD_SET_CQM, 4820 .cmd = NL80211_CMD_SET_CQM,
5455 .doit = nl80211_set_cqm, 4821 .doit = nl80211_set_cqm,
5456 .policy = nl80211_policy, 4822 .policy = nl80211_policy,
5457 .flags = GENL_ADMIN_PERM, 4823 .flags = GENL_ADMIN_PERM,
4824 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4825 NL80211_FLAG_NEED_RTNL,
5458 }, 4826 },
5459 { 4827 {
5460 .cmd = NL80211_CMD_SET_CHANNEL, 4828 .cmd = NL80211_CMD_SET_CHANNEL,
5461 .doit = nl80211_set_channel, 4829 .doit = nl80211_set_channel,
5462 .policy = nl80211_policy, 4830 .policy = nl80211_policy,
5463 .flags = GENL_ADMIN_PERM, 4831 .flags = GENL_ADMIN_PERM,
4832 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4833 NL80211_FLAG_NEED_RTNL,
4834 },
4835 {
4836 .cmd = NL80211_CMD_SET_WDS_PEER,
4837 .doit = nl80211_set_wds_peer,
4838 .policy = nl80211_policy,
4839 .flags = GENL_ADMIN_PERM,
4840 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4841 NL80211_FLAG_NEED_RTNL,
5464 }, 4842 },
5465}; 4843};
5466 4844
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 5ca8c7180141..503ebb86ba18 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -650,14 +650,14 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
650 bss = container_of(pub, struct cfg80211_internal_bss, pub); 650 bss = container_of(pub, struct cfg80211_internal_bss, pub);
651 651
652 spin_lock_bh(&dev->bss_lock); 652 spin_lock_bh(&dev->bss_lock);
653 if (!list_empty(&bss->list)) {
654 list_del_init(&bss->list);
655 dev->bss_generation++;
656 rb_erase(&bss->rbn, &dev->bss_tree);
653 657
654 list_del(&bss->list); 658 kref_put(&bss->ref, bss_release);
655 dev->bss_generation++; 659 }
656 rb_erase(&bss->rbn, &dev->bss_tree);
657
658 spin_unlock_bh(&dev->bss_lock); 660 spin_unlock_bh(&dev->bss_lock);
659
660 kref_put(&bss->ref, bss_release);
661} 661}
662EXPORT_SYMBOL(cfg80211_unlink_bss); 662EXPORT_SYMBOL(cfg80211_unlink_bss);
663 663
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index f161b9844542..e17b0bee6bdc 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -698,7 +698,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
698 */ 698 */
699 if (rdev->ops->del_key) 699 if (rdev->ops->del_key)
700 for (i = 0; i < 6; i++) 700 for (i = 0; i < 6; i++)
701 rdev->ops->del_key(wdev->wiphy, dev, i, NULL); 701 rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
702 702
703#ifdef CONFIG_CFG80211_WEXT 703#ifdef CONFIG_CFG80211_WEXT
704 memset(&wrqu, 0, sizeof(wrqu)); 704 memset(&wrqu, 0, sizeof(wrqu));
diff --git a/net/wireless/util.c b/net/wireless/util.c
index fb5448f7d55a..76120aeda57d 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -144,19 +144,25 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
144 144
145int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, 145int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
146 struct key_params *params, int key_idx, 146 struct key_params *params, int key_idx,
147 const u8 *mac_addr) 147 bool pairwise, const u8 *mac_addr)
148{ 148{
149 int i; 149 int i;
150 150
151 if (key_idx > 5) 151 if (key_idx > 5)
152 return -EINVAL; 152 return -EINVAL;
153 153
154 if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
155 return -EINVAL;
156
157 if (pairwise && !mac_addr)
158 return -EINVAL;
159
154 /* 160 /*
155 * Disallow pairwise keys with non-zero index unless it's WEP 161 * Disallow pairwise keys with non-zero index unless it's WEP
156 * (because current deployments use pairwise WEP keys with 162 * (because current deployments use pairwise WEP keys with
157 * non-zero indizes but 802.11i clearly specifies to use zero) 163 * non-zero indizes but 802.11i clearly specifies to use zero)
158 */ 164 */
159 if (mac_addr && key_idx && 165 if (pairwise && key_idx &&
160 params->cipher != WLAN_CIPHER_SUITE_WEP40 && 166 params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
161 params->cipher != WLAN_CIPHER_SUITE_WEP104) 167 params->cipher != WLAN_CIPHER_SUITE_WEP104)
162 return -EINVAL; 168 return -EINVAL;
@@ -677,7 +683,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
677 for (i = 0; i < 6; i++) { 683 for (i = 0; i < 6; i++) {
678 if (!wdev->connect_keys->params[i].cipher) 684 if (!wdev->connect_keys->params[i].cipher)
679 continue; 685 continue;
680 if (rdev->ops->add_key(wdev->wiphy, dev, i, NULL, 686 if (rdev->ops->add_key(wdev->wiphy, dev, i, false, NULL,
681 &wdev->connect_keys->params[i])) { 687 &wdev->connect_keys->params[i])) {
682 printk(KERN_ERR "%s: failed to set key %d\n", 688 printk(KERN_ERR "%s: failed to set key %d\n",
683 dev->name, i); 689 dev->name, i);
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 7e5c3a45f811..6002265289c6 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -432,14 +432,17 @@ int cfg80211_wext_giwretry(struct net_device *dev,
432EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); 432EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
433 433
434static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, 434static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
435 struct net_device *dev, const u8 *addr, 435 struct net_device *dev, bool pairwise,
436 bool remove, bool tx_key, int idx, 436 const u8 *addr, bool remove, bool tx_key,
437 struct key_params *params) 437 int idx, struct key_params *params)
438{ 438{
439 struct wireless_dev *wdev = dev->ieee80211_ptr; 439 struct wireless_dev *wdev = dev->ieee80211_ptr;
440 int err, i; 440 int err, i;
441 bool rejoin = false; 441 bool rejoin = false;
442 442
443 if (pairwise && !addr)
444 return -EINVAL;
445
443 if (!wdev->wext.keys) { 446 if (!wdev->wext.keys) {
444 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), 447 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
445 GFP_KERNEL); 448 GFP_KERNEL);
@@ -478,7 +481,13 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
478 __cfg80211_leave_ibss(rdev, wdev->netdev, true); 481 __cfg80211_leave_ibss(rdev, wdev->netdev, true);
479 rejoin = true; 482 rejoin = true;
480 } 483 }
481 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); 484
485 if (!pairwise && addr &&
486 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
487 err = -ENOENT;
488 else
489 err = rdev->ops->del_key(&rdev->wiphy, dev, idx,
490 pairwise, addr);
482 } 491 }
483 wdev->wext.connect.privacy = false; 492 wdev->wext.connect.privacy = false;
484 /* 493 /*
@@ -507,12 +516,13 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
507 if (addr) 516 if (addr)
508 tx_key = false; 517 tx_key = false;
509 518
510 if (cfg80211_validate_key_settings(rdev, params, idx, addr)) 519 if (cfg80211_validate_key_settings(rdev, params, idx, pairwise, addr))
511 return -EINVAL; 520 return -EINVAL;
512 521
513 err = 0; 522 err = 0;
514 if (wdev->current_bss) 523 if (wdev->current_bss)
515 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); 524 err = rdev->ops->add_key(&rdev->wiphy, dev, idx,
525 pairwise, addr, params);
516 if (err) 526 if (err)
517 return err; 527 return err;
518 528
@@ -563,17 +573,17 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
563} 573}
564 574
565static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, 575static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
566 struct net_device *dev, const u8 *addr, 576 struct net_device *dev, bool pairwise,
567 bool remove, bool tx_key, int idx, 577 const u8 *addr, bool remove, bool tx_key,
568 struct key_params *params) 578 int idx, struct key_params *params)
569{ 579{
570 int err; 580 int err;
571 581
572 /* devlist mutex needed for possible IBSS re-join */ 582 /* devlist mutex needed for possible IBSS re-join */
573 mutex_lock(&rdev->devlist_mtx); 583 mutex_lock(&rdev->devlist_mtx);
574 wdev_lock(dev->ieee80211_ptr); 584 wdev_lock(dev->ieee80211_ptr);
575 err = __cfg80211_set_encryption(rdev, dev, addr, remove, 585 err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
576 tx_key, idx, params); 586 remove, tx_key, idx, params);
577 wdev_unlock(dev->ieee80211_ptr); 587 wdev_unlock(dev->ieee80211_ptr);
578 mutex_unlock(&rdev->devlist_mtx); 588 mutex_unlock(&rdev->devlist_mtx);
579 589
@@ -635,7 +645,7 @@ int cfg80211_wext_siwencode(struct net_device *dev,
635 else if (!remove) 645 else if (!remove)
636 return -EINVAL; 646 return -EINVAL;
637 647
638 return cfg80211_set_encryption(rdev, dev, NULL, remove, 648 return cfg80211_set_encryption(rdev, dev, false, NULL, remove,
639 wdev->wext.default_key == -1, 649 wdev->wext.default_key == -1,
640 idx, &params); 650 idx, &params);
641} 651}
@@ -725,7 +735,9 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
725 } 735 }
726 736
727 return cfg80211_set_encryption( 737 return cfg80211_set_encryption(
728 rdev, dev, addr, remove, 738 rdev, dev,
739 !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY),
740 addr, remove,
729 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, 741 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
730 idx, &params); 742 idx, &params);
731} 743}