diff options
author | David S. Miller <davem@davemloft.net> | 2010-12-23 13:13:30 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-23 13:13:30 -0500 |
commit | a130883d9528eefb66285728ba6a232d8fff9465 (patch) | |
tree | 304b63e59d910be2ee2798404fe4a940bdfdd2af /net/wireless | |
parent | d9f4fbaf7053af43e6c72909c2aff18654717aed (diff) | |
parent | 65a6538a56d4c7ae8465f2a8420ddc65877b6779 (diff) |
Merge branch 'for-davem' of ssh://master.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.c | 22 | ||||
-rw-r--r-- | net/wireless/core.h | 5 | ||||
-rw-r--r-- | net/wireless/mesh.c | 24 | ||||
-rw-r--r-- | net/wireless/mlme.c | 22 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 276 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 6 | ||||
-rw-r--r-- | net/wireless/reg.c | 3 | ||||
-rw-r--r-- | net/wireless/scan.c | 11 | ||||
-rw-r--r-- | net/wireless/util.c | 3 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 8 |
10 files changed, 309 insertions, 71 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index 79772fcc37bc..e9a5f8ca4c27 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -789,13 +789,23 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
789 | cfg80211_mgd_wext_connect(rdev, wdev); | 789 | cfg80211_mgd_wext_connect(rdev, wdev); |
790 | break; | 790 | break; |
791 | #endif | 791 | #endif |
792 | #ifdef CONFIG_MAC80211_MESH | ||
792 | case NL80211_IFTYPE_MESH_POINT: | 793 | case NL80211_IFTYPE_MESH_POINT: |
793 | /* backward compat code ... */ | 794 | { |
794 | if (wdev->mesh_id_up_len) | 795 | /* backward compat code... */ |
795 | __cfg80211_join_mesh(rdev, dev, wdev->ssid, | 796 | struct mesh_setup setup; |
796 | wdev->mesh_id_up_len, | 797 | memcpy(&setup, &default_mesh_setup, |
797 | &default_mesh_config); | 798 | sizeof(setup)); |
798 | break; | 799 | /* back compat only needed for mesh_id */ |
800 | setup.mesh_id = wdev->ssid; | ||
801 | setup.mesh_id_len = wdev->mesh_id_up_len; | ||
802 | if (wdev->mesh_id_up_len) | ||
803 | __cfg80211_join_mesh(rdev, dev, | ||
804 | &setup, | ||
805 | &default_mesh_config); | ||
806 | break; | ||
807 | } | ||
808 | #endif | ||
799 | default: | 809 | default: |
800 | break; | 810 | break; |
801 | } | 811 | } |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 743203bb61ac..26a0a084e16b 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -287,13 +287,14 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | |||
287 | 287 | ||
288 | /* mesh */ | 288 | /* mesh */ |
289 | extern const struct mesh_config default_mesh_config; | 289 | extern const struct mesh_config default_mesh_config; |
290 | extern const struct mesh_setup default_mesh_setup; | ||
290 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 291 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
291 | struct net_device *dev, | 292 | struct net_device *dev, |
292 | const u8 *mesh_id, u8 mesh_id_len, | 293 | const struct mesh_setup *setup, |
293 | const struct mesh_config *conf); | 294 | const struct mesh_config *conf); |
294 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 295 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
295 | struct net_device *dev, | 296 | struct net_device *dev, |
296 | const u8 *mesh_id, u8 mesh_id_len, | 297 | const struct mesh_setup *setup, |
297 | const struct mesh_config *conf); | 298 | const struct mesh_config *conf); |
298 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | 299 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, |
299 | struct net_device *dev); | 300 | struct net_device *dev); |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index e0b9747fe50a..73e39c171ffb 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -50,17 +50,19 @@ const struct mesh_config default_mesh_config = { | |||
50 | .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT, | 50 | .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT, |
51 | }; | 51 | }; |
52 | 52 | ||
53 | const struct mesh_setup default_mesh_setup = { | ||
54 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, | ||
55 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, | ||
56 | .vendor_ie = NULL, | ||
57 | .vendor_ie_len = 0, | ||
58 | }; | ||
53 | 59 | ||
54 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 60 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
55 | struct net_device *dev, | 61 | struct net_device *dev, |
56 | const u8 *mesh_id, u8 mesh_id_len, | 62 | const struct mesh_setup *setup, |
57 | const struct mesh_config *conf) | 63 | const struct mesh_config *conf) |
58 | { | 64 | { |
59 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 65 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
60 | struct mesh_setup setup = { | ||
61 | .mesh_id = mesh_id, | ||
62 | .mesh_id_len = mesh_id_len, | ||
63 | }; | ||
64 | int err; | 66 | int err; |
65 | 67 | ||
66 | BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN); | 68 | BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN); |
@@ -73,16 +75,16 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
73 | if (wdev->mesh_id_len) | 75 | if (wdev->mesh_id_len) |
74 | return -EALREADY; | 76 | return -EALREADY; |
75 | 77 | ||
76 | if (!mesh_id_len) | 78 | if (!setup->mesh_id_len) |
77 | return -EINVAL; | 79 | return -EINVAL; |
78 | 80 | ||
79 | if (!rdev->ops->join_mesh) | 81 | if (!rdev->ops->join_mesh) |
80 | return -EOPNOTSUPP; | 82 | return -EOPNOTSUPP; |
81 | 83 | ||
82 | err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, &setup); | 84 | err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup); |
83 | if (!err) { | 85 | if (!err) { |
84 | memcpy(wdev->ssid, mesh_id, mesh_id_len); | 86 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); |
85 | wdev->mesh_id_len = mesh_id_len; | 87 | wdev->mesh_id_len = setup->mesh_id_len; |
86 | } | 88 | } |
87 | 89 | ||
88 | return err; | 90 | return err; |
@@ -90,14 +92,14 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
90 | 92 | ||
91 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 93 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
92 | struct net_device *dev, | 94 | struct net_device *dev, |
93 | const u8 *mesh_id, u8 mesh_id_len, | 95 | const struct mesh_setup *setup, |
94 | const struct mesh_config *conf) | 96 | const struct mesh_config *conf) |
95 | { | 97 | { |
96 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 98 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
97 | int err; | 99 | int err; |
98 | 100 | ||
99 | wdev_lock(wdev); | 101 | wdev_lock(wdev); |
100 | err = __cfg80211_join_mesh(rdev, dev, mesh_id, mesh_id_len, conf); | 102 | err = __cfg80211_join_mesh(rdev, dev, setup, conf); |
101 | wdev_unlock(wdev); | 103 | wdev_unlock(wdev); |
102 | 104 | ||
103 | return err; | 105 | return err; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index d7680f2a4c5b..aa5df8865ff7 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -263,6 +263,28 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) | |||
263 | } | 263 | } |
264 | EXPORT_SYMBOL(cfg80211_send_disassoc); | 264 | EXPORT_SYMBOL(cfg80211_send_disassoc); |
265 | 265 | ||
266 | void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf, | ||
267 | size_t len) | ||
268 | { | ||
269 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
270 | struct wiphy *wiphy = wdev->wiphy; | ||
271 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
272 | |||
273 | nl80211_send_unprot_deauth(rdev, dev, buf, len, GFP_ATOMIC); | ||
274 | } | ||
275 | EXPORT_SYMBOL(cfg80211_send_unprot_deauth); | ||
276 | |||
277 | void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, | ||
278 | size_t len) | ||
279 | { | ||
280 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
281 | struct wiphy *wiphy = wdev->wiphy; | ||
282 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
283 | |||
284 | nl80211_send_unprot_disassoc(rdev, dev, buf, len, GFP_ATOMIC); | ||
285 | } | ||
286 | EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); | ||
287 | |||
266 | static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) | 288 | static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) |
267 | { | 289 | { |
268 | int i; | 290 | int i; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c3f80e565365..9b62710891a2 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -123,7 +123,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
123 | .len = NL80211_MAX_SUPP_RATES }, | 123 | .len = NL80211_MAX_SUPP_RATES }, |
124 | [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 }, | 124 | [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 }, |
125 | 125 | ||
126 | [NL80211_ATTR_MESH_PARAMS] = { .type = NLA_NESTED }, | 126 | [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED }, |
127 | 127 | ||
128 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, | 128 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, |
129 | .len = NL80211_HT_CAPABILITY_LEN }, | 129 | .len = NL80211_HT_CAPABILITY_LEN }, |
@@ -171,6 +171,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
171 | [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 }, | 171 | [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 }, |
172 | [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, | 172 | [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, |
173 | [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, | 173 | [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, |
174 | [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, | ||
174 | }; | 175 | }; |
175 | 176 | ||
176 | /* policy for the key attributes */ | 177 | /* policy for the key attributes */ |
@@ -182,6 +183,14 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { | |||
182 | [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, | 183 | [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, |
183 | [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, | 184 | [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, |
184 | [NL80211_KEY_TYPE] = { .type = NLA_U32 }, | 185 | [NL80211_KEY_TYPE] = { .type = NLA_U32 }, |
186 | [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, | ||
187 | }; | ||
188 | |||
189 | /* policy for the key default flags */ | ||
190 | static const struct nla_policy | ||
191 | nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = { | ||
192 | [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG }, | ||
193 | [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG }, | ||
185 | }; | 194 | }; |
186 | 195 | ||
187 | /* ifidx get helper */ | 196 | /* ifidx get helper */ |
@@ -314,6 +323,7 @@ struct key_parse { | |||
314 | int idx; | 323 | int idx; |
315 | int type; | 324 | int type; |
316 | bool def, defmgmt; | 325 | bool def, defmgmt; |
326 | bool def_uni, def_multi; | ||
317 | }; | 327 | }; |
318 | 328 | ||
319 | static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | 329 | static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) |
@@ -327,6 +337,13 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | |||
327 | k->def = !!tb[NL80211_KEY_DEFAULT]; | 337 | k->def = !!tb[NL80211_KEY_DEFAULT]; |
328 | k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT]; | 338 | k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT]; |
329 | 339 | ||
340 | if (k->def) { | ||
341 | k->def_uni = true; | ||
342 | k->def_multi = true; | ||
343 | } | ||
344 | if (k->defmgmt) | ||
345 | k->def_multi = true; | ||
346 | |||
330 | if (tb[NL80211_KEY_IDX]) | 347 | if (tb[NL80211_KEY_IDX]) |
331 | k->idx = nla_get_u8(tb[NL80211_KEY_IDX]); | 348 | k->idx = nla_get_u8(tb[NL80211_KEY_IDX]); |
332 | 349 | ||
@@ -349,6 +366,19 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | |||
349 | return -EINVAL; | 366 | return -EINVAL; |
350 | } | 367 | } |
351 | 368 | ||
369 | if (tb[NL80211_KEY_DEFAULT_TYPES]) { | ||
370 | struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; | ||
371 | int err = nla_parse_nested(kdt, | ||
372 | NUM_NL80211_KEY_DEFAULT_TYPES - 1, | ||
373 | tb[NL80211_KEY_DEFAULT_TYPES], | ||
374 | nl80211_key_default_policy); | ||
375 | if (err) | ||
376 | return err; | ||
377 | |||
378 | k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST]; | ||
379 | k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST]; | ||
380 | } | ||
381 | |||
352 | return 0; | 382 | return 0; |
353 | } | 383 | } |
354 | 384 | ||
@@ -373,12 +403,32 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k) | |||
373 | k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; | 403 | k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; |
374 | k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; | 404 | k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; |
375 | 405 | ||
406 | if (k->def) { | ||
407 | k->def_uni = true; | ||
408 | k->def_multi = true; | ||
409 | } | ||
410 | if (k->defmgmt) | ||
411 | k->def_multi = true; | ||
412 | |||
376 | if (info->attrs[NL80211_ATTR_KEY_TYPE]) { | 413 | if (info->attrs[NL80211_ATTR_KEY_TYPE]) { |
377 | k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); | 414 | k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); |
378 | if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) | 415 | if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) |
379 | return -EINVAL; | 416 | return -EINVAL; |
380 | } | 417 | } |
381 | 418 | ||
419 | if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) { | ||
420 | struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; | ||
421 | int err = nla_parse_nested( | ||
422 | kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1, | ||
423 | info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES], | ||
424 | nl80211_key_default_policy); | ||
425 | if (err) | ||
426 | return err; | ||
427 | |||
428 | k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST]; | ||
429 | k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST]; | ||
430 | } | ||
431 | |||
382 | return 0; | 432 | return 0; |
383 | } | 433 | } |
384 | 434 | ||
@@ -401,6 +451,11 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k) | |||
401 | if (k->def && k->defmgmt) | 451 | if (k->def && k->defmgmt) |
402 | return -EINVAL; | 452 | return -EINVAL; |
403 | 453 | ||
454 | if (k->defmgmt) { | ||
455 | if (k->def_uni || !k->def_multi) | ||
456 | return -EINVAL; | ||
457 | } | ||
458 | |||
404 | if (k->idx != -1) { | 459 | if (k->idx != -1) { |
405 | if (k->defmgmt) { | 460 | if (k->defmgmt) { |
406 | if (k->idx < 4 || k->idx > 5) | 461 | if (k->idx < 4 || k->idx > 5) |
@@ -450,6 +505,8 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, | |||
450 | goto error; | 505 | goto error; |
451 | def = 1; | 506 | def = 1; |
452 | result->def = parse.idx; | 507 | result->def = parse.idx; |
508 | if (!parse.def_uni || !parse.def_multi) | ||
509 | goto error; | ||
453 | } else if (parse.defmgmt) | 510 | } else if (parse.defmgmt) |
454 | goto error; | 511 | goto error; |
455 | err = cfg80211_validate_key_settings(rdev, &parse.p, | 512 | err = cfg80211_validate_key_settings(rdev, &parse.p, |
@@ -548,7 +605,13 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
548 | if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) | 605 | if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) |
549 | NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE); | 606 | NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE); |
550 | 607 | ||
551 | if (dev->ops->get_antenna) { | 608 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, |
609 | dev->wiphy.available_antennas_tx); | ||
610 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, | ||
611 | dev->wiphy.available_antennas_rx); | ||
612 | |||
613 | if ((dev->wiphy.available_antennas_tx || | ||
614 | dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) { | ||
552 | u32 tx_ant = 0, rx_ant = 0; | 615 | u32 tx_ant = 0, rx_ant = 0; |
553 | int res; | 616 | int res; |
554 | res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant); | 617 | res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant); |
@@ -662,7 +725,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
662 | CMD(add_beacon, NEW_BEACON); | 725 | CMD(add_beacon, NEW_BEACON); |
663 | CMD(add_station, NEW_STATION); | 726 | CMD(add_station, NEW_STATION); |
664 | CMD(add_mpath, NEW_MPATH); | 727 | CMD(add_mpath, NEW_MPATH); |
665 | CMD(update_mesh_params, SET_MESH_PARAMS); | 728 | CMD(update_mesh_config, SET_MESH_CONFIG); |
666 | CMD(change_bss, SET_BSS); | 729 | CMD(change_bss, SET_BSS); |
667 | CMD(auth, AUTHENTICATE); | 730 | CMD(auth, AUTHENTICATE); |
668 | CMD(assoc, ASSOCIATE); | 731 | CMD(assoc, ASSOCIATE); |
@@ -698,6 +761,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
698 | 761 | ||
699 | nla_nest_end(msg, nl_cmds); | 762 | nla_nest_end(msg, nl_cmds); |
700 | 763 | ||
764 | if (dev->ops->remain_on_channel) | ||
765 | NLA_PUT_U32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, | ||
766 | dev->wiphy.max_remain_on_channel_duration); | ||
767 | |||
701 | /* for now at least assume all drivers have it */ | 768 | /* for now at least assume all drivers have it */ |
702 | if (dev->ops->mgmt_tx) | 769 | if (dev->ops->mgmt_tx) |
703 | NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); | 770 | NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); |
@@ -1046,7 +1113,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1046 | if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && | 1113 | if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && |
1047 | info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) { | 1114 | info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) { |
1048 | u32 tx_ant, rx_ant; | 1115 | u32 tx_ant, rx_ant; |
1049 | if (!rdev->ops->set_antenna) { | 1116 | if ((!rdev->wiphy.available_antennas_tx && |
1117 | !rdev->wiphy.available_antennas_rx) || | ||
1118 | !rdev->ops->set_antenna) { | ||
1050 | result = -EOPNOTSUPP; | 1119 | result = -EOPNOTSUPP; |
1051 | goto bad_res; | 1120 | goto bad_res; |
1052 | } | 1121 | } |
@@ -1054,6 +1123,17 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1054 | tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]); | 1123 | tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]); |
1055 | rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]); | 1124 | rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]); |
1056 | 1125 | ||
1126 | /* reject antenna configurations which don't match the | ||
1127 | * available antenna masks, except for the "all" mask */ | ||
1128 | if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) || | ||
1129 | (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) { | ||
1130 | result = -EINVAL; | ||
1131 | goto bad_res; | ||
1132 | } | ||
1133 | |||
1134 | tx_ant = tx_ant & rdev->wiphy.available_antennas_tx; | ||
1135 | rx_ant = rx_ant & rdev->wiphy.available_antennas_rx; | ||
1136 | |||
1057 | result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant); | 1137 | result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant); |
1058 | if (result) | 1138 | if (result) |
1059 | goto bad_res; | 1139 | goto bad_res; |
@@ -1575,8 +1655,6 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1575 | struct key_parse key; | 1655 | struct key_parse key; |
1576 | int err; | 1656 | int err; |
1577 | struct net_device *dev = info->user_ptr[1]; | 1657 | struct net_device *dev = info->user_ptr[1]; |
1578 | int (*func)(struct wiphy *wiphy, struct net_device *netdev, | ||
1579 | u8 key_index); | ||
1580 | 1658 | ||
1581 | err = nl80211_parse_key(info, &key); | 1659 | err = nl80211_parse_key(info, &key); |
1582 | if (err) | 1660 | if (err) |
@@ -1589,27 +1667,61 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1589 | if (!key.def && !key.defmgmt) | 1667 | if (!key.def && !key.defmgmt) |
1590 | return -EINVAL; | 1668 | return -EINVAL; |
1591 | 1669 | ||
1592 | if (key.def) | 1670 | wdev_lock(dev->ieee80211_ptr); |
1593 | func = rdev->ops->set_default_key; | ||
1594 | else | ||
1595 | func = rdev->ops->set_default_mgmt_key; | ||
1596 | 1671 | ||
1597 | if (!func) | 1672 | if (key.def) { |
1598 | return -EOPNOTSUPP; | 1673 | if (!rdev->ops->set_default_key) { |
1674 | err = -EOPNOTSUPP; | ||
1675 | goto out; | ||
1676 | } | ||
1599 | 1677 | ||
1600 | wdev_lock(dev->ieee80211_ptr); | 1678 | err = nl80211_key_allowed(dev->ieee80211_ptr); |
1601 | err = nl80211_key_allowed(dev->ieee80211_ptr); | 1679 | if (err) |
1602 | if (!err) | 1680 | goto out; |
1603 | err = func(&rdev->wiphy, dev, key.idx); | 1681 | |
1682 | if (!(rdev->wiphy.flags & | ||
1683 | WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS)) { | ||
1684 | if (!key.def_uni || !key.def_multi) { | ||
1685 | err = -EOPNOTSUPP; | ||
1686 | goto out; | ||
1687 | } | ||
1688 | } | ||
1689 | |||
1690 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx, | ||
1691 | key.def_uni, key.def_multi); | ||
1692 | |||
1693 | if (err) | ||
1694 | goto out; | ||
1604 | 1695 | ||
1605 | #ifdef CONFIG_CFG80211_WEXT | 1696 | #ifdef CONFIG_CFG80211_WEXT |
1606 | if (!err) { | 1697 | dev->ieee80211_ptr->wext.default_key = key.idx; |
1607 | if (func == rdev->ops->set_default_key) | ||
1608 | dev->ieee80211_ptr->wext.default_key = key.idx; | ||
1609 | else | ||
1610 | dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; | ||
1611 | } | ||
1612 | #endif | 1698 | #endif |
1699 | } else { | ||
1700 | if (key.def_uni || !key.def_multi) { | ||
1701 | err = -EINVAL; | ||
1702 | goto out; | ||
1703 | } | ||
1704 | |||
1705 | if (!rdev->ops->set_default_mgmt_key) { | ||
1706 | err = -EOPNOTSUPP; | ||
1707 | goto out; | ||
1708 | } | ||
1709 | |||
1710 | err = nl80211_key_allowed(dev->ieee80211_ptr); | ||
1711 | if (err) | ||
1712 | goto out; | ||
1713 | |||
1714 | err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, | ||
1715 | dev, key.idx); | ||
1716 | if (err) | ||
1717 | goto out; | ||
1718 | |||
1719 | #ifdef CONFIG_CFG80211_WEXT | ||
1720 | dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; | ||
1721 | #endif | ||
1722 | } | ||
1723 | |||
1724 | out: | ||
1613 | wdev_unlock(dev->ieee80211_ptr); | 1725 | wdev_unlock(dev->ieee80211_ptr); |
1614 | 1726 | ||
1615 | return err; | 1727 | return err; |
@@ -2569,7 +2681,7 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
2569 | return r; | 2681 | return r; |
2570 | } | 2682 | } |
2571 | 2683 | ||
2572 | static int nl80211_get_mesh_params(struct sk_buff *skb, | 2684 | static int nl80211_get_mesh_config(struct sk_buff *skb, |
2573 | struct genl_info *info) | 2685 | struct genl_info *info) |
2574 | { | 2686 | { |
2575 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 2687 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
@@ -2584,7 +2696,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, | |||
2584 | if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) | 2696 | if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) |
2585 | return -EOPNOTSUPP; | 2697 | return -EOPNOTSUPP; |
2586 | 2698 | ||
2587 | if (!rdev->ops->get_mesh_params) | 2699 | if (!rdev->ops->get_mesh_config) |
2588 | return -EOPNOTSUPP; | 2700 | return -EOPNOTSUPP; |
2589 | 2701 | ||
2590 | wdev_lock(wdev); | 2702 | wdev_lock(wdev); |
@@ -2592,7 +2704,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, | |||
2592 | if (!wdev->mesh_id_len) | 2704 | if (!wdev->mesh_id_len) |
2593 | memcpy(&cur_params, &default_mesh_config, sizeof(cur_params)); | 2705 | memcpy(&cur_params, &default_mesh_config, sizeof(cur_params)); |
2594 | else | 2706 | else |
2595 | err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, | 2707 | err = rdev->ops->get_mesh_config(&rdev->wiphy, dev, |
2596 | &cur_params); | 2708 | &cur_params); |
2597 | wdev_unlock(wdev); | 2709 | wdev_unlock(wdev); |
2598 | 2710 | ||
@@ -2604,10 +2716,10 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, | |||
2604 | if (!msg) | 2716 | if (!msg) |
2605 | return -ENOMEM; | 2717 | return -ENOMEM; |
2606 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 2718 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
2607 | NL80211_CMD_GET_MESH_PARAMS); | 2719 | NL80211_CMD_GET_MESH_CONFIG); |
2608 | if (!hdr) | 2720 | if (!hdr) |
2609 | goto nla_put_failure; | 2721 | goto nla_put_failure; |
2610 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_PARAMS); | 2722 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG); |
2611 | if (!pinfoattr) | 2723 | if (!pinfoattr) |
2612 | goto nla_put_failure; | 2724 | goto nla_put_failure; |
2613 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 2725 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
@@ -2669,7 +2781,15 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A | |||
2669 | [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, | 2781 | [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, |
2670 | }; | 2782 | }; |
2671 | 2783 | ||
2672 | static int nl80211_parse_mesh_params(struct genl_info *info, | 2784 | static const struct nla_policy |
2785 | nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = { | ||
2786 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, | ||
2787 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, | ||
2788 | [NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE] = { .type = NLA_BINARY, | ||
2789 | .len = IEEE80211_MAX_DATA_LEN }, | ||
2790 | }; | ||
2791 | |||
2792 | static int nl80211_parse_mesh_config(struct genl_info *info, | ||
2673 | struct mesh_config *cfg, | 2793 | struct mesh_config *cfg, |
2674 | u32 *mask_out) | 2794 | u32 *mask_out) |
2675 | { | 2795 | { |
@@ -2685,10 +2805,10 @@ do {\ | |||
2685 | } while (0);\ | 2805 | } while (0);\ |
2686 | 2806 | ||
2687 | 2807 | ||
2688 | if (!info->attrs[NL80211_ATTR_MESH_PARAMS]) | 2808 | if (!info->attrs[NL80211_ATTR_MESH_CONFIG]) |
2689 | return -EINVAL; | 2809 | return -EINVAL; |
2690 | if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX, | 2810 | if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX, |
2691 | info->attrs[NL80211_ATTR_MESH_PARAMS], | 2811 | info->attrs[NL80211_ATTR_MESH_CONFIG], |
2692 | nl80211_meshconf_params_policy)) | 2812 | nl80211_meshconf_params_policy)) |
2693 | return -EINVAL; | 2813 | return -EINVAL; |
2694 | 2814 | ||
@@ -2735,15 +2855,51 @@ do {\ | |||
2735 | dot11MeshHWMPRootMode, mask, | 2855 | dot11MeshHWMPRootMode, mask, |
2736 | NL80211_MESHCONF_HWMP_ROOTMODE, | 2856 | NL80211_MESHCONF_HWMP_ROOTMODE, |
2737 | nla_get_u8); | 2857 | nla_get_u8); |
2738 | |||
2739 | if (mask_out) | 2858 | if (mask_out) |
2740 | *mask_out = mask; | 2859 | *mask_out = mask; |
2860 | |||
2741 | return 0; | 2861 | return 0; |
2742 | 2862 | ||
2743 | #undef FILL_IN_MESH_PARAM_IF_SET | 2863 | #undef FILL_IN_MESH_PARAM_IF_SET |
2744 | } | 2864 | } |
2745 | 2865 | ||
2746 | static int nl80211_update_mesh_params(struct sk_buff *skb, | 2866 | static int nl80211_parse_mesh_setup(struct genl_info *info, |
2867 | struct mesh_setup *setup) | ||
2868 | { | ||
2869 | struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1]; | ||
2870 | |||
2871 | if (!info->attrs[NL80211_ATTR_MESH_SETUP]) | ||
2872 | return -EINVAL; | ||
2873 | if (nla_parse_nested(tb, NL80211_MESH_SETUP_ATTR_MAX, | ||
2874 | info->attrs[NL80211_ATTR_MESH_SETUP], | ||
2875 | nl80211_mesh_setup_params_policy)) | ||
2876 | return -EINVAL; | ||
2877 | |||
2878 | if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL]) | ||
2879 | setup->path_sel_proto = | ||
2880 | (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ? | ||
2881 | IEEE80211_PATH_PROTOCOL_VENDOR : | ||
2882 | IEEE80211_PATH_PROTOCOL_HWMP; | ||
2883 | |||
2884 | if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC]) | ||
2885 | setup->path_metric = | ||
2886 | (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ? | ||
2887 | IEEE80211_PATH_METRIC_VENDOR : | ||
2888 | IEEE80211_PATH_METRIC_AIRTIME; | ||
2889 | |||
2890 | if (tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]) { | ||
2891 | struct nlattr *ieattr = | ||
2892 | tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]; | ||
2893 | if (!is_valid_ie_attr(ieattr)) | ||
2894 | return -EINVAL; | ||
2895 | setup->vendor_ie = nla_data(ieattr); | ||
2896 | setup->vendor_ie_len = nla_len(ieattr); | ||
2897 | } | ||
2898 | |||
2899 | return 0; | ||
2900 | } | ||
2901 | |||
2902 | static int nl80211_update_mesh_config(struct sk_buff *skb, | ||
2747 | struct genl_info *info) | 2903 | struct genl_info *info) |
2748 | { | 2904 | { |
2749 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 2905 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
@@ -2756,10 +2912,10 @@ static int nl80211_update_mesh_params(struct sk_buff *skb, | |||
2756 | if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) | 2912 | if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) |
2757 | return -EOPNOTSUPP; | 2913 | return -EOPNOTSUPP; |
2758 | 2914 | ||
2759 | if (!rdev->ops->update_mesh_params) | 2915 | if (!rdev->ops->update_mesh_config) |
2760 | return -EOPNOTSUPP; | 2916 | return -EOPNOTSUPP; |
2761 | 2917 | ||
2762 | err = nl80211_parse_mesh_params(info, &cfg, &mask); | 2918 | err = nl80211_parse_mesh_config(info, &cfg, &mask); |
2763 | if (err) | 2919 | if (err) |
2764 | return err; | 2920 | return err; |
2765 | 2921 | ||
@@ -2768,7 +2924,7 @@ static int nl80211_update_mesh_params(struct sk_buff *skb, | |||
2768 | err = -ENOLINK; | 2924 | err = -ENOLINK; |
2769 | 2925 | ||
2770 | if (!err) | 2926 | if (!err) |
2771 | err = rdev->ops->update_mesh_params(&rdev->wiphy, dev, | 2927 | err = rdev->ops->update_mesh_config(&rdev->wiphy, dev, |
2772 | mask, &cfg); | 2928 | mask, &cfg); |
2773 | 2929 | ||
2774 | wdev_unlock(wdev); | 2930 | wdev_unlock(wdev); |
@@ -4128,7 +4284,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
4128 | * We should be on that channel for at least one jiffie, | 4284 | * We should be on that channel for at least one jiffie, |
4129 | * and more than 5 seconds seems excessive. | 4285 | * and more than 5 seconds seems excessive. |
4130 | */ | 4286 | */ |
4131 | if (!duration || !msecs_to_jiffies(duration) || duration > 5000) | 4287 | if (!duration || !msecs_to_jiffies(duration) || |
4288 | duration > rdev->wiphy.max_remain_on_channel_duration) | ||
4132 | return -EINVAL; | 4289 | return -EINVAL; |
4133 | 4290 | ||
4134 | if (!rdev->ops->remain_on_channel) | 4291 | if (!rdev->ops->remain_on_channel) |
@@ -4296,6 +4453,7 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4296 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && | 4453 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && |
4297 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 4454 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
4298 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | 4455 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
4456 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && | ||
4299 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 4457 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
4300 | return -EOPNOTSUPP; | 4458 | return -EOPNOTSUPP; |
4301 | 4459 | ||
@@ -4336,6 +4494,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4336 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && | 4494 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && |
4337 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 4495 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
4338 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | 4496 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
4497 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && | ||
4339 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 4498 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
4340 | return -EOPNOTSUPP; | 4499 | return -EOPNOTSUPP; |
4341 | 4500 | ||
@@ -4562,14 +4721,16 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
4562 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 4721 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4563 | struct net_device *dev = info->user_ptr[1]; | 4722 | struct net_device *dev = info->user_ptr[1]; |
4564 | struct mesh_config cfg; | 4723 | struct mesh_config cfg; |
4724 | struct mesh_setup setup; | ||
4565 | int err; | 4725 | int err; |
4566 | 4726 | ||
4567 | /* start with default */ | 4727 | /* start with default */ |
4568 | memcpy(&cfg, &default_mesh_config, sizeof(cfg)); | 4728 | memcpy(&cfg, &default_mesh_config, sizeof(cfg)); |
4729 | memcpy(&setup, &default_mesh_setup, sizeof(setup)); | ||
4569 | 4730 | ||
4570 | if (info->attrs[NL80211_ATTR_MESH_PARAMS]) { | 4731 | if (info->attrs[NL80211_ATTR_MESH_CONFIG]) { |
4571 | /* and parse parameters if given */ | 4732 | /* and parse parameters if given */ |
4572 | err = nl80211_parse_mesh_params(info, &cfg, NULL); | 4733 | err = nl80211_parse_mesh_config(info, &cfg, NULL); |
4573 | if (err) | 4734 | if (err) |
4574 | return err; | 4735 | return err; |
4575 | } | 4736 | } |
@@ -4578,10 +4739,17 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
4578 | !nla_len(info->attrs[NL80211_ATTR_MESH_ID])) | 4739 | !nla_len(info->attrs[NL80211_ATTR_MESH_ID])) |
4579 | return -EINVAL; | 4740 | return -EINVAL; |
4580 | 4741 | ||
4581 | return cfg80211_join_mesh(rdev, dev, | 4742 | setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); |
4582 | nla_data(info->attrs[NL80211_ATTR_MESH_ID]), | 4743 | setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); |
4583 | nla_len(info->attrs[NL80211_ATTR_MESH_ID]), | 4744 | |
4584 | &cfg); | 4745 | if (info->attrs[NL80211_ATTR_MESH_SETUP]) { |
4746 | /* parse additional setup parameters if given */ | ||
4747 | err = nl80211_parse_mesh_setup(info, &setup); | ||
4748 | if (err) | ||
4749 | return err; | ||
4750 | } | ||
4751 | |||
4752 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); | ||
4585 | } | 4753 | } |
4586 | 4754 | ||
4587 | static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) | 4755 | static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) |
@@ -4847,16 +5015,16 @@ static struct genl_ops nl80211_ops[] = { | |||
4847 | .flags = GENL_ADMIN_PERM, | 5015 | .flags = GENL_ADMIN_PERM, |
4848 | }, | 5016 | }, |
4849 | { | 5017 | { |
4850 | .cmd = NL80211_CMD_GET_MESH_PARAMS, | 5018 | .cmd = NL80211_CMD_GET_MESH_CONFIG, |
4851 | .doit = nl80211_get_mesh_params, | 5019 | .doit = nl80211_get_mesh_config, |
4852 | .policy = nl80211_policy, | 5020 | .policy = nl80211_policy, |
4853 | /* can be retrieved by unprivileged users */ | 5021 | /* can be retrieved by unprivileged users */ |
4854 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 5022 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
4855 | NL80211_FLAG_NEED_RTNL, | 5023 | NL80211_FLAG_NEED_RTNL, |
4856 | }, | 5024 | }, |
4857 | { | 5025 | { |
4858 | .cmd = NL80211_CMD_SET_MESH_PARAMS, | 5026 | .cmd = NL80211_CMD_SET_MESH_CONFIG, |
4859 | .doit = nl80211_update_mesh_params, | 5027 | .doit = nl80211_update_mesh_config, |
4860 | .policy = nl80211_policy, | 5028 | .policy = nl80211_policy, |
4861 | .flags = GENL_ADMIN_PERM, | 5029 | .flags = GENL_ADMIN_PERM, |
4862 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5030 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
@@ -5368,6 +5536,22 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, | |||
5368 | NL80211_CMD_DISASSOCIATE, gfp); | 5536 | NL80211_CMD_DISASSOCIATE, gfp); |
5369 | } | 5537 | } |
5370 | 5538 | ||
5539 | void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev, | ||
5540 | struct net_device *netdev, const u8 *buf, | ||
5541 | size_t len, gfp_t gfp) | ||
5542 | { | ||
5543 | nl80211_send_mlme_event(rdev, netdev, buf, len, | ||
5544 | NL80211_CMD_UNPROT_DEAUTHENTICATE, gfp); | ||
5545 | } | ||
5546 | |||
5547 | void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev, | ||
5548 | struct net_device *netdev, const u8 *buf, | ||
5549 | size_t len, gfp_t gfp) | ||
5550 | { | ||
5551 | nl80211_send_mlme_event(rdev, netdev, buf, len, | ||
5552 | NL80211_CMD_UNPROT_DISASSOCIATE, gfp); | ||
5553 | } | ||
5554 | |||
5371 | static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, | 5555 | static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, |
5372 | struct net_device *netdev, int cmd, | 5556 | struct net_device *netdev, int cmd, |
5373 | const u8 *addr, gfp_t gfp) | 5557 | const u8 *addr, gfp_t gfp) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 16c2f7190768..e3f7fa886966 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -25,6 +25,12 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev, | |||
25 | void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, | 25 | void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, |
26 | struct net_device *netdev, | 26 | struct net_device *netdev, |
27 | const u8 *buf, size_t len, gfp_t gfp); | 27 | const u8 *buf, size_t len, gfp_t gfp); |
28 | void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev, | ||
29 | struct net_device *netdev, | ||
30 | const u8 *buf, size_t len, gfp_t gfp); | ||
31 | void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev, | ||
32 | struct net_device *netdev, | ||
33 | const u8 *buf, size_t len, gfp_t gfp); | ||
28 | void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, | 34 | void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, |
29 | struct net_device *netdev, | 35 | struct net_device *netdev, |
30 | const u8 *addr, gfp_t gfp); | 36 | const u8 *addr, gfp_t gfp); |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 5ed615f94e0c..99d41831d76e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -661,7 +661,8 @@ static int freq_reg_info_regd(struct wiphy *wiphy, | |||
661 | * Follow the driver's regulatory domain, if present, unless a country | 661 | * Follow the driver's regulatory domain, if present, unless a country |
662 | * IE has been processed or a user wants to help complaince further | 662 | * IE has been processed or a user wants to help complaince further |
663 | */ | 663 | */ |
664 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | 664 | if (!custom_regd && |
665 | last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
665 | last_request->initiator != NL80211_REGDOM_SET_BY_USER && | 666 | last_request->initiator != NL80211_REGDOM_SET_BY_USER && |
666 | wiphy->regd) | 667 | wiphy->regd) |
667 | regd = wiphy->regd; | 668 | regd = wiphy->regd; |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 503ebb86ba18..ea427f418f64 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -464,6 +464,9 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
464 | if (res->pub.beacon_ies) { | 464 | if (res->pub.beacon_ies) { |
465 | size_t used = dev->wiphy.bss_priv_size + sizeof(*res); | 465 | size_t used = dev->wiphy.bss_priv_size + sizeof(*res); |
466 | size_t ielen = res->pub.len_beacon_ies; | 466 | size_t ielen = res->pub.len_beacon_ies; |
467 | bool information_elements_is_beacon_ies = | ||
468 | (found->pub.information_elements == | ||
469 | found->pub.beacon_ies); | ||
467 | 470 | ||
468 | if (found->pub.beacon_ies && | 471 | if (found->pub.beacon_ies && |
469 | !found->beacon_ies_allocated && | 472 | !found->beacon_ies_allocated && |
@@ -487,6 +490,14 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
487 | found->pub.len_beacon_ies = ielen; | 490 | found->pub.len_beacon_ies = ielen; |
488 | } | 491 | } |
489 | } | 492 | } |
493 | |||
494 | /* Override IEs if they were from a beacon before */ | ||
495 | if (information_elements_is_beacon_ies) { | ||
496 | found->pub.information_elements = | ||
497 | found->pub.beacon_ies; | ||
498 | found->pub.len_information_elements = | ||
499 | found->pub.len_beacon_ies; | ||
500 | } | ||
490 | } | 501 | } |
491 | 502 | ||
492 | kref_put(&res->ref, bss_release); | 503 | kref_put(&res->ref, bss_release); |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 4de624ca4c63..7620ae2fcf18 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -689,7 +689,8 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev) | |||
689 | continue; | 689 | continue; |
690 | } | 690 | } |
691 | if (wdev->connect_keys->def == i) | 691 | if (wdev->connect_keys->def == i) |
692 | if (rdev->ops->set_default_key(wdev->wiphy, dev, i)) { | 692 | if (rdev->ops->set_default_key(wdev->wiphy, dev, |
693 | i, true, true)) { | ||
693 | netdev_err(dev, "failed to set defkey %d\n", i); | 694 | netdev_err(dev, "failed to set defkey %d\n", i); |
694 | continue; | 695 | continue; |
695 | } | 696 | } |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 12222ee6ebf2..3e5dbd4e4cd5 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -548,8 +548,8 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
548 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); | 548 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); |
549 | rejoin = true; | 549 | rejoin = true; |
550 | } | 550 | } |
551 | err = rdev->ops->set_default_key(&rdev->wiphy, | 551 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, |
552 | dev, idx); | 552 | idx, true, true); |
553 | } | 553 | } |
554 | if (!err) { | 554 | if (!err) { |
555 | wdev->wext.default_key = idx; | 555 | wdev->wext.default_key = idx; |
@@ -627,8 +627,8 @@ int cfg80211_wext_siwencode(struct net_device *dev, | |||
627 | err = 0; | 627 | err = 0; |
628 | wdev_lock(wdev); | 628 | wdev_lock(wdev); |
629 | if (wdev->current_bss) | 629 | if (wdev->current_bss) |
630 | err = rdev->ops->set_default_key(&rdev->wiphy, | 630 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, |
631 | dev, idx); | 631 | idx, true, true); |
632 | if (!err) | 632 | if (!err) |
633 | wdev->wext.default_key = idx; | 633 | wdev->wext.default_key = idx; |
634 | wdev_unlock(wdev); | 634 | wdev_unlock(wdev); |