void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; int i; bool found = false, was_current = false; ASSERT_WDEV_LOCK(wdev); if (wdev->current_bss && memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; found = true; was_current = true; } else for (i = 0; i < MAX_AUTH_BSSES; i++) { if (wdev->auth_bsses[i] && memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { cfg80211_unhold_bss(wdev->auth_bsses[i]); cfg80211_put_bss(&wdev->auth_bsses[i]->pub); wdev->auth_bsses[i] = NULL; found = true; break; } if (wdev->authtry_bsses[i] && memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0 && memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) == 0) { cfg80211_unhold_bss(wdev->authtry_bsses[i]); cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); wdev->authtry_bsses[i] = NULL; found = true; break; } } if (!found) return; nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) { u16 reason_code; bool from_ap; reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0; __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); } }
void __cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; u16 reason_code; bool from_ap; trace___cfg80211_send_disassoc(dev); ASSERT_WDEV_LOCK(wdev); nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); if (wdev->sme_state != CFG80211_SME_CONNECTED) return; if (wdev->current_bss && ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { cfg80211_sme_disassoc(dev, wdev->current_bss); cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(wiphy, &wdev->current_bss->pub); wdev->current_bss = NULL; } else WARN_ON(1); reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr); __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); }
static void cfg80211_process_disassoc(struct wireless_dev *wdev, const u8 *buf, size_t len) { struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; u16 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr); nl80211_send_disassoc(rdev, wdev->netdev, buf, len, GFP_KERNEL); if (WARN_ON(!wdev->current_bss || !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) return; __cfg80211_disconnected(wdev->netdev, NULL, 0, reason_code, from_ap); cfg80211_sme_disassoc(wdev); }
void __cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; int i; u16 reason_code; bool from_ap; bool done = false; ASSERT_WDEV_LOCK(wdev); nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); if (wdev->sme_state != CFG80211_SME_CONNECTED) return; if (wdev->current_bss && memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { for (i = 0; i < MAX_AUTH_BSSES; i++) { if (wdev->authtry_bsses[i] || wdev->auth_bsses[i]) continue; wdev->auth_bsses[i] = wdev->current_bss; wdev->current_bss = NULL; done = true; cfg80211_sme_disassoc(dev, i); break; } WARN_ON(!done); } else WARN_ON(1); reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0; __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); }
void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; bool was_current = false; trace___cfg80211_send_deauth(dev); ASSERT_WDEV_LOCK(wdev); if (wdev->current_bss && ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(wiphy, &wdev->current_bss->pub); wdev->current_bss = NULL; was_current = true; } nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) { u16 reason_code; bool from_ap; reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr); __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); } }