diff options
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 31 |
2 files changed, 23 insertions, 9 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 630a438180fd..989591787aee 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -284,6 +284,7 @@ struct ieee80211_if_managed { | |||
284 | 284 | ||
285 | struct mutex mtx; | 285 | struct mutex mtx; |
286 | struct ieee80211_bss *associated; | 286 | struct ieee80211_bss *associated; |
287 | struct ieee80211_mgd_work *old_associate_work; | ||
287 | struct list_head work_list; | 288 | struct list_head work_list; |
288 | 289 | ||
289 | u8 bssid[ETH_ALEN]; | 290 | u8 bssid[ETH_ALEN]; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6d5a1ee0445f..c374d2d73fa4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -880,10 +880,11 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | |||
880 | } | 880 | } |
881 | 881 | ||
882 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | 882 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, |
883 | struct ieee80211_bss *bss, | 883 | struct ieee80211_mgd_work *wk, |
884 | u32 bss_info_changed) | 884 | u32 bss_info_changed) |
885 | { | 885 | { |
886 | struct ieee80211_local *local = sdata->local; | 886 | struct ieee80211_local *local = sdata->local; |
887 | struct ieee80211_bss *bss = wk->bss; | ||
887 | 888 | ||
888 | bss_info_changed |= BSS_CHANGED_ASSOC; | 889 | bss_info_changed |= BSS_CHANGED_ASSOC; |
889 | /* set timing information */ | 890 | /* set timing information */ |
@@ -896,6 +897,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
896 | bss->cbss.capability, bss->has_erp_value, bss->erp_value); | 897 | bss->cbss.capability, bss->has_erp_value, bss->erp_value); |
897 | 898 | ||
898 | sdata->u.mgd.associated = bss; | 899 | sdata->u.mgd.associated = bss; |
900 | sdata->u.mgd.old_associate_work = wk; | ||
899 | memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); | 901 | memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); |
900 | 902 | ||
901 | /* just to be sure */ | 903 | /* just to be sure */ |
@@ -1010,7 +1012,8 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | |||
1010 | return RX_MGMT_NONE; | 1012 | return RX_MGMT_NONE; |
1011 | } | 1013 | } |
1012 | 1014 | ||
1013 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | 1015 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
1016 | bool deauth) | ||
1014 | { | 1017 | { |
1015 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1018 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1016 | struct ieee80211_local *local = sdata->local; | 1019 | struct ieee80211_local *local = sdata->local; |
@@ -1028,6 +1031,16 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | |||
1028 | ifmgd->associated = NULL; | 1031 | ifmgd->associated = NULL; |
1029 | memset(ifmgd->bssid, 0, ETH_ALEN); | 1032 | memset(ifmgd->bssid, 0, ETH_ALEN); |
1030 | 1033 | ||
1034 | if (deauth) { | ||
1035 | kfree(ifmgd->old_associate_work); | ||
1036 | ifmgd->old_associate_work = NULL; | ||
1037 | } else { | ||
1038 | struct ieee80211_mgd_work *wk = ifmgd->old_associate_work; | ||
1039 | |||
1040 | wk->state = IEEE80211_MGD_STATE_IDLE; | ||
1041 | list_add(&wk->list, &ifmgd->work_list); | ||
1042 | } | ||
1043 | |||
1031 | /* | 1044 | /* |
1032 | * we need to commit the associated = NULL change because the | 1045 | * we need to commit the associated = NULL change because the |
1033 | * scan code uses that to determine whether this iface should | 1046 | * scan code uses that to determine whether this iface should |
@@ -1345,7 +1358,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1345 | sdata->dev->name, bssid, reason_code); | 1358 | sdata->dev->name, bssid, reason_code); |
1346 | 1359 | ||
1347 | if (!wk) { | 1360 | if (!wk) { |
1348 | ieee80211_set_disassoc(sdata); | 1361 | ieee80211_set_disassoc(sdata, true); |
1349 | } else { | 1362 | } else { |
1350 | list_del(&wk->list); | 1363 | list_del(&wk->list); |
1351 | kfree(wk); | 1364 | kfree(wk); |
@@ -1378,7 +1391,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1378 | printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", | 1391 | printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", |
1379 | sdata->dev->name, reason_code); | 1392 | sdata->dev->name, reason_code); |
1380 | 1393 | ||
1381 | ieee80211_set_disassoc(sdata); | 1394 | ieee80211_set_disassoc(sdata, false); |
1382 | return RX_MGMT_CFG80211_DISASSOC; | 1395 | return RX_MGMT_CFG80211_DISASSOC; |
1383 | } | 1396 | } |
1384 | 1397 | ||
@@ -1581,7 +1594,8 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1581 | * ieee80211_set_associated() will tell the driver */ | 1594 | * ieee80211_set_associated() will tell the driver */ |
1582 | bss_conf->aid = aid; | 1595 | bss_conf->aid = aid; |
1583 | bss_conf->assoc_capability = capab_info; | 1596 | bss_conf->assoc_capability = capab_info; |
1584 | ieee80211_set_associated(sdata, wk->bss, changed); | 1597 | /* this will take ownership of wk */ |
1598 | ieee80211_set_associated(sdata, wk, changed); | ||
1585 | 1599 | ||
1586 | /* | 1600 | /* |
1587 | * Start timer to probe the connection to the AP now. | 1601 | * Start timer to probe the connection to the AP now. |
@@ -1590,7 +1604,6 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1590 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); | 1604 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); |
1591 | mod_beacon_timer(sdata); | 1605 | mod_beacon_timer(sdata); |
1592 | 1606 | ||
1593 | kfree(wk); | ||
1594 | return RX_MGMT_CFG80211_ASSOC; | 1607 | return RX_MGMT_CFG80211_ASSOC; |
1595 | } | 1608 | } |
1596 | 1609 | ||
@@ -2096,7 +2109,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2096 | printk(KERN_DEBUG "No probe response from AP %pM" | 2109 | printk(KERN_DEBUG "No probe response from AP %pM" |
2097 | " after %dms, disconnecting.\n", | 2110 | " after %dms, disconnecting.\n", |
2098 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 2111 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
2099 | ieee80211_set_disassoc(sdata); | 2112 | ieee80211_set_disassoc(sdata, true); |
2100 | mutex_unlock(&ifmgd->mtx); | 2113 | mutex_unlock(&ifmgd->mtx); |
2101 | /* | 2114 | /* |
2102 | * must be outside lock due to cfg80211, | 2115 | * must be outside lock due to cfg80211, |
@@ -2500,7 +2513,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2500 | 2513 | ||
2501 | if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { | 2514 | if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { |
2502 | bssid = req->bss->bssid; | 2515 | bssid = req->bss->bssid; |
2503 | ieee80211_set_disassoc(sdata); | 2516 | ieee80211_set_disassoc(sdata, true); |
2504 | } else list_for_each_entry(wk, &ifmgd->work_list, list) { | 2517 | } else list_for_each_entry(wk, &ifmgd->work_list, list) { |
2505 | if (&wk->bss->cbss == req->bss) { | 2518 | if (&wk->bss->cbss == req->bss) { |
2506 | bssid = req->bss->bssid; | 2519 | bssid = req->bss->bssid; |
@@ -2552,7 +2565,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2552 | return -ENOLINK; | 2565 | return -ENOLINK; |
2553 | } | 2566 | } |
2554 | 2567 | ||
2555 | ieee80211_set_disassoc(sdata); | 2568 | ieee80211_set_disassoc(sdata, false); |
2556 | 2569 | ||
2557 | mutex_unlock(&ifmgd->mtx); | 2570 | mutex_unlock(&ifmgd->mtx); |
2558 | 2571 | ||