aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-04-15 16:21:34 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-15 16:21:34 -0400
commit5c01d5669356e13f0fb468944c1dd4c6a7e978ad (patch)
treefa43345288d7b25fac92b3b35360a177c4947313 /net/wireless
parentfea069152614cdeefba4b2bf80afcddb9c217fc8 (diff)
parenta5e944f1d955f3819503348426763e21e0413ba6 (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/ath/ath5k/phy.c drivers/net/wireless/wl12xx/wl1271_main.c
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.h15
-rw-r--r--net/wireless/mlme.c39
-rw-r--r--net/wireless/nl80211.c22
-rw-r--r--net/wireless/reg.c6
-rw-r--r--net/wireless/sme.c15
-rw-r--r--net/wireless/util.c24
6 files changed, 86 insertions, 35 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h
index d52da913145a..b2234b436ead 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -293,13 +293,15 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
293 const u8 *bssid, 293 const u8 *bssid,
294 const u8 *ssid, int ssid_len, 294 const u8 *ssid, int ssid_len,
295 const u8 *ie, int ie_len, 295 const u8 *ie, int ie_len,
296 const u8 *key, int key_len, int key_idx); 296 const u8 *key, int key_len, int key_idx,
297 bool local_state_change);
297int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 298int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
298 struct net_device *dev, struct ieee80211_channel *chan, 299 struct net_device *dev, struct ieee80211_channel *chan,
299 enum nl80211_auth_type auth_type, const u8 *bssid, 300 enum nl80211_auth_type auth_type, const u8 *bssid,
300 const u8 *ssid, int ssid_len, 301 const u8 *ssid, int ssid_len,
301 const u8 *ie, int ie_len, 302 const u8 *ie, int ie_len,
302 const u8 *key, int key_len, int key_idx); 303 const u8 *key, int key_len, int key_idx,
304 bool local_state_change);
303int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 305int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
304 struct net_device *dev, 306 struct net_device *dev,
305 struct ieee80211_channel *chan, 307 struct ieee80211_channel *chan,
@@ -315,13 +317,16 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
315 struct cfg80211_crypto_settings *crypt); 317 struct cfg80211_crypto_settings *crypt);
316int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 318int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
317 struct net_device *dev, const u8 *bssid, 319 struct net_device *dev, const u8 *bssid,
318 const u8 *ie, int ie_len, u16 reason); 320 const u8 *ie, int ie_len, u16 reason,
321 bool local_state_change);
319int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 322int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
320 struct net_device *dev, const u8 *bssid, 323 struct net_device *dev, const u8 *bssid,
321 const u8 *ie, int ie_len, u16 reason); 324 const u8 *ie, int ie_len, u16 reason,
325 bool local_state_change);
322int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, 326int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
323 struct net_device *dev, const u8 *bssid, 327 struct net_device *dev, const u8 *bssid,
324 const u8 *ie, int ie_len, u16 reason); 328 const u8 *ie, int ie_len, u16 reason,
329 bool local_state_change);
325void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, 330void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
326 struct net_device *dev); 331 struct net_device *dev);
327void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 332void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 4bb734a95f57..48ead6f0426d 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -378,7 +378,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
378 const u8 *bssid, 378 const u8 *bssid,
379 const u8 *ssid, int ssid_len, 379 const u8 *ssid, int ssid_len,
380 const u8 *ie, int ie_len, 380 const u8 *ie, int ie_len,
381 const u8 *key, int key_len, int key_idx) 381 const u8 *key, int key_len, int key_idx,
382 bool local_state_change)
382{ 383{
383 struct wireless_dev *wdev = dev->ieee80211_ptr; 384 struct wireless_dev *wdev = dev->ieee80211_ptr;
384 struct cfg80211_auth_request req; 385 struct cfg80211_auth_request req;
@@ -408,6 +409,7 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
408 409
409 memset(&req, 0, sizeof(req)); 410 memset(&req, 0, sizeof(req));
410 411
412 req.local_state_change = local_state_change;
411 req.ie = ie; 413 req.ie = ie;
412 req.ie_len = ie_len; 414 req.ie_len = ie_len;
413 req.auth_type = auth_type; 415 req.auth_type = auth_type;
@@ -434,12 +436,18 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
434 goto out; 436 goto out;
435 } 437 }
436 438
437 wdev->authtry_bsses[slot] = bss; 439 if (local_state_change)
440 wdev->auth_bsses[slot] = bss;
441 else
442 wdev->authtry_bsses[slot] = bss;
438 cfg80211_hold_bss(bss); 443 cfg80211_hold_bss(bss);
439 444
440 err = rdev->ops->auth(&rdev->wiphy, dev, &req); 445 err = rdev->ops->auth(&rdev->wiphy, dev, &req);
441 if (err) { 446 if (err) {
442 wdev->authtry_bsses[slot] = NULL; 447 if (local_state_change)
448 wdev->auth_bsses[slot] = NULL;
449 else
450 wdev->authtry_bsses[slot] = NULL;
443 cfg80211_unhold_bss(bss); 451 cfg80211_unhold_bss(bss);
444 } 452 }
445 453
@@ -454,14 +462,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
454 enum nl80211_auth_type auth_type, const u8 *bssid, 462 enum nl80211_auth_type auth_type, const u8 *bssid,
455 const u8 *ssid, int ssid_len, 463 const u8 *ssid, int ssid_len,
456 const u8 *ie, int ie_len, 464 const u8 *ie, int ie_len,
457 const u8 *key, int key_len, int key_idx) 465 const u8 *key, int key_len, int key_idx,
466 bool local_state_change)
458{ 467{
459 int err; 468 int err;
460 469
461 wdev_lock(dev->ieee80211_ptr); 470 wdev_lock(dev->ieee80211_ptr);
462 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 471 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
463 ssid, ssid_len, ie, ie_len, 472 ssid, ssid_len, ie, ie_len,
464 key, key_len, key_idx); 473 key, key_len, key_idx, local_state_change);
465 wdev_unlock(dev->ieee80211_ptr); 474 wdev_unlock(dev->ieee80211_ptr);
466 475
467 return err; 476 return err;
@@ -555,7 +564,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
555 564
556int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 565int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
557 struct net_device *dev, const u8 *bssid, 566 struct net_device *dev, const u8 *bssid,
558 const u8 *ie, int ie_len, u16 reason) 567 const u8 *ie, int ie_len, u16 reason,
568 bool local_state_change)
559{ 569{
560 struct wireless_dev *wdev = dev->ieee80211_ptr; 570 struct wireless_dev *wdev = dev->ieee80211_ptr;
561 struct cfg80211_deauth_request req; 571 struct cfg80211_deauth_request req;
@@ -565,6 +575,7 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
565 575
566 memset(&req, 0, sizeof(req)); 576 memset(&req, 0, sizeof(req));
567 req.reason_code = reason; 577 req.reason_code = reason;
578 req.local_state_change = local_state_change;
568 req.ie = ie; 579 req.ie = ie;
569 req.ie_len = ie_len; 580 req.ie_len = ie_len;
570 if (wdev->current_bss && 581 if (wdev->current_bss &&
@@ -591,13 +602,15 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
591 602
592int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 603int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
593 struct net_device *dev, const u8 *bssid, 604 struct net_device *dev, const u8 *bssid,
594 const u8 *ie, int ie_len, u16 reason) 605 const u8 *ie, int ie_len, u16 reason,
606 bool local_state_change)
595{ 607{
596 struct wireless_dev *wdev = dev->ieee80211_ptr; 608 struct wireless_dev *wdev = dev->ieee80211_ptr;
597 int err; 609 int err;
598 610
599 wdev_lock(wdev); 611 wdev_lock(wdev);
600 err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason); 612 err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason,
613 local_state_change);
601 wdev_unlock(wdev); 614 wdev_unlock(wdev);
602 615
603 return err; 616 return err;
@@ -605,7 +618,8 @@ int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
605 618
606static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, 619static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
607 struct net_device *dev, const u8 *bssid, 620 struct net_device *dev, const u8 *bssid,
608 const u8 *ie, int ie_len, u16 reason) 621 const u8 *ie, int ie_len, u16 reason,
622 bool local_state_change)
609{ 623{
610 struct wireless_dev *wdev = dev->ieee80211_ptr; 624 struct wireless_dev *wdev = dev->ieee80211_ptr;
611 struct cfg80211_disassoc_request req; 625 struct cfg80211_disassoc_request req;
@@ -620,6 +634,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
620 634
621 memset(&req, 0, sizeof(req)); 635 memset(&req, 0, sizeof(req));
622 req.reason_code = reason; 636 req.reason_code = reason;
637 req.local_state_change = local_state_change;
623 req.ie = ie; 638 req.ie = ie;
624 req.ie_len = ie_len; 639 req.ie_len = ie_len;
625 if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) 640 if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0)
@@ -632,13 +647,15 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
632 647
633int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, 648int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
634 struct net_device *dev, const u8 *bssid, 649 struct net_device *dev, const u8 *bssid,
635 const u8 *ie, int ie_len, u16 reason) 650 const u8 *ie, int ie_len, u16 reason,
651 bool local_state_change)
636{ 652{
637 struct wireless_dev *wdev = dev->ieee80211_ptr; 653 struct wireless_dev *wdev = dev->ieee80211_ptr;
638 int err; 654 int err;
639 655
640 wdev_lock(wdev); 656 wdev_lock(wdev);
641 err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason); 657 err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason,
658 local_state_change);
642 wdev_unlock(wdev); 659 wdev_unlock(wdev);
643 660
644 return err; 661 return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 596bf189549a..356a84a5daee 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -151,6 +151,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
151 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, 151 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
152 [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, 152 [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 },
153 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, 153 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
154 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
154}; 155};
155 156
156/* policy for the attributes */ 157/* policy for the attributes */
@@ -2097,7 +2098,8 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
2097 goto out_rtnl; 2098 goto out_rtnl;
2098 2099
2099 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 2100 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2100 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { 2101 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
2102 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
2101 err = -EINVAL; 2103 err = -EINVAL;
2102 goto out; 2104 goto out;
2103 } 2105 }
@@ -3393,6 +3395,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3393 int err, ssid_len, ie_len = 0; 3395 int err, ssid_len, ie_len = 0;
3394 enum nl80211_auth_type auth_type; 3396 enum nl80211_auth_type auth_type;
3395 struct key_parse key; 3397 struct key_parse key;
3398 bool local_state_change;
3396 3399
3397 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3400 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3398 return -EINVAL; 3401 return -EINVAL;
@@ -3471,9 +3474,12 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3471 goto out; 3474 goto out;
3472 } 3475 }
3473 3476
3477 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3478
3474 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 3479 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
3475 ssid, ssid_len, ie, ie_len, 3480 ssid, ssid_len, ie, ie_len,
3476 key.p.key, key.p.key_len, key.idx); 3481 key.p.key, key.p.key_len, key.idx,
3482 local_state_change);
3477 3483
3478out: 3484out:
3479 cfg80211_unlock_rdev(rdev); 3485 cfg80211_unlock_rdev(rdev);
@@ -3650,6 +3656,7 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3650 const u8 *ie = NULL, *bssid; 3656 const u8 *ie = NULL, *bssid;
3651 int err, ie_len = 0; 3657 int err, ie_len = 0;
3652 u16 reason_code; 3658 u16 reason_code;
3659 bool local_state_change;
3653 3660
3654 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3661 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3655 return -EINVAL; 3662 return -EINVAL;
@@ -3695,7 +3702,10 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3695 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 3702 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
3696 } 3703 }
3697 3704
3698 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code); 3705 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3706
3707 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
3708 local_state_change);
3699 3709
3700out: 3710out:
3701 cfg80211_unlock_rdev(rdev); 3711 cfg80211_unlock_rdev(rdev);
@@ -3712,6 +3722,7 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
3712 const u8 *ie = NULL, *bssid; 3722 const u8 *ie = NULL, *bssid;
3713 int err, ie_len = 0; 3723 int err, ie_len = 0;
3714 u16 reason_code; 3724 u16 reason_code;
3725 bool local_state_change;
3715 3726
3716 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3727 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3717 return -EINVAL; 3728 return -EINVAL;
@@ -3757,7 +3768,10 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
3757 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 3768 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
3758 } 3769 }
3759 3770
3760 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code); 3771 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3772
3773 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
3774 local_state_change);
3761 3775
3762out: 3776out:
3763 cfg80211_unlock_rdev(rdev); 3777 cfg80211_unlock_rdev(rdev);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 422da20d1e5b..8f0d97dd3109 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2356,10 +2356,10 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
2356 rdev->country_ie_alpha2[1]); 2356 rdev->country_ie_alpha2[1]);
2357 } else 2357 } else
2358 printk(KERN_INFO "cfg80211: Current regulatory " 2358 printk(KERN_INFO "cfg80211: Current regulatory "
2359 "domain intersected: \n"); 2359 "domain intersected:\n");
2360 } else 2360 } else
2361 printk(KERN_INFO "cfg80211: Current regulatory " 2361 printk(KERN_INFO "cfg80211: Current regulatory "
2362 "domain intersected: \n"); 2362 "domain intersected:\n");
2363 } else if (is_world_regdom(rd->alpha2)) 2363 } else if (is_world_regdom(rd->alpha2))
2364 printk(KERN_INFO "cfg80211: World regulatory " 2364 printk(KERN_INFO "cfg80211: World regulatory "
2365 "domain updated:\n"); 2365 "domain updated:\n");
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index f4dfd5f5f2ea..c2735775ec19 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -171,7 +171,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
171 params->ssid, params->ssid_len, 171 params->ssid, params->ssid_len,
172 NULL, 0, 172 NULL, 0,
173 params->key, params->key_len, 173 params->key, params->key_len,
174 params->key_idx); 174 params->key_idx, false);
175 case CFG80211_CONN_ASSOCIATE_NEXT: 175 case CFG80211_CONN_ASSOCIATE_NEXT:
176 BUG_ON(!rdev->ops->assoc); 176 BUG_ON(!rdev->ops->assoc);
177 wdev->conn->state = CFG80211_CONN_ASSOCIATING; 177 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
@@ -186,12 +186,13 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
186 if (err) 186 if (err)
187 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, 187 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
188 NULL, 0, 188 NULL, 0,
189 WLAN_REASON_DEAUTH_LEAVING); 189 WLAN_REASON_DEAUTH_LEAVING,
190 false);
190 return err; 191 return err;
191 case CFG80211_CONN_DEAUTH_ASSOC_FAIL: 192 case CFG80211_CONN_DEAUTH_ASSOC_FAIL:
192 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, 193 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
193 NULL, 0, 194 NULL, 0,
194 WLAN_REASON_DEAUTH_LEAVING); 195 WLAN_REASON_DEAUTH_LEAVING, false);
195 /* return an error so that we call __cfg80211_connect_result() */ 196 /* return an error so that we call __cfg80211_connect_result() */
196 return -EINVAL; 197 return -EINVAL;
197 default: 198 default:
@@ -676,7 +677,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
676 continue; 677 continue;
677 bssid = wdev->auth_bsses[i]->pub.bssid; 678 bssid = wdev->auth_bsses[i]->pub.bssid;
678 ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, 679 ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0,
679 WLAN_REASON_DEAUTH_LEAVING); 680 WLAN_REASON_DEAUTH_LEAVING,
681 false);
680 WARN(ret, "deauth failed: %d\n", ret); 682 WARN(ret, "deauth failed: %d\n", ret);
681 } 683 }
682 } 684 }
@@ -935,7 +937,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
935 /* wdev->conn->params.bssid must be set if > SCANNING */ 937 /* wdev->conn->params.bssid must be set if > SCANNING */
936 err = __cfg80211_mlme_deauth(rdev, dev, 938 err = __cfg80211_mlme_deauth(rdev, dev,
937 wdev->conn->params.bssid, 939 wdev->conn->params.bssid,
938 NULL, 0, reason); 940 NULL, 0, reason, false);
939 if (err) 941 if (err)
940 return err; 942 return err;
941 } else { 943 } else {
@@ -991,7 +993,8 @@ void cfg80211_sme_disassoc(struct net_device *dev, int idx)
991 993
992 memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); 994 memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN);
993 if (__cfg80211_mlme_deauth(rdev, dev, bssid, 995 if (__cfg80211_mlme_deauth(rdev, dev, bssid,
994 NULL, 0, WLAN_REASON_DEAUTH_LEAVING)) { 996 NULL, 0, WLAN_REASON_DEAUTH_LEAVING,
997 false)) {
995 /* whatever -- assume gone anyway */ 998 /* whatever -- assume gone anyway */
996 cfg80211_unhold_bss(wdev->auth_bsses[idx]); 999 cfg80211_unhold_bss(wdev->auth_bsses[idx]);
997 cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); 1000 cfg80211_put_bss(&wdev->auth_bsses[idx]->pub);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index d3574a4eb3ba..3416373a9c0c 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -331,11 +331,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
331 if (iftype == NL80211_IFTYPE_MESH_POINT) { 331 if (iftype == NL80211_IFTYPE_MESH_POINT) {
332 struct ieee80211s_hdr *meshdr = 332 struct ieee80211s_hdr *meshdr =
333 (struct ieee80211s_hdr *) (skb->data + hdrlen); 333 (struct ieee80211s_hdr *) (skb->data + hdrlen);
334 hdrlen += ieee80211_get_mesh_hdrlen(meshdr); 334 /* make sure meshdr->flags is on the linear part */
335 if (!pskb_may_pull(skb, hdrlen + 1))
336 return -1;
335 if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { 337 if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
336 memcpy(dst, meshdr->eaddr1, ETH_ALEN); 338 skb_copy_bits(skb, hdrlen +
337 memcpy(src, meshdr->eaddr2, ETH_ALEN); 339 offsetof(struct ieee80211s_hdr, eaddr1),
340 dst, ETH_ALEN);
341 skb_copy_bits(skb, hdrlen +
342 offsetof(struct ieee80211s_hdr, eaddr2),
343 src, ETH_ALEN);
338 } 344 }
345 hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
339 } 346 }
340 break; 347 break;
341 case cpu_to_le16(IEEE80211_FCTL_FROMDS): 348 case cpu_to_le16(IEEE80211_FCTL_FROMDS):
@@ -347,9 +354,14 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
347 if (iftype == NL80211_IFTYPE_MESH_POINT) { 354 if (iftype == NL80211_IFTYPE_MESH_POINT) {
348 struct ieee80211s_hdr *meshdr = 355 struct ieee80211s_hdr *meshdr =
349 (struct ieee80211s_hdr *) (skb->data + hdrlen); 356 (struct ieee80211s_hdr *) (skb->data + hdrlen);
350 hdrlen += ieee80211_get_mesh_hdrlen(meshdr); 357 /* make sure meshdr->flags is on the linear part */
358 if (!pskb_may_pull(skb, hdrlen + 1))
359 return -1;
351 if (meshdr->flags & MESH_FLAGS_AE_A4) 360 if (meshdr->flags & MESH_FLAGS_AE_A4)
352 memcpy(src, meshdr->eaddr1, ETH_ALEN); 361 skb_copy_bits(skb, hdrlen +
362 offsetof(struct ieee80211s_hdr, eaddr1),
363 src, ETH_ALEN);
364 hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
353 } 365 }
354 break; 366 break;
355 case cpu_to_le16(0): 367 case cpu_to_le16(0):
@@ -358,7 +370,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
358 break; 370 break;
359 } 371 }
360 372
361 if (unlikely(skb->len - hdrlen < 8)) 373 if (!pskb_may_pull(skb, hdrlen + 8))
362 return -1; 374 return -1;
363 375
364 payload = skb->data + hdrlen; 376 payload = skb->data + hdrlen;