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_assoc_timeout(struct net_device *dev, const u8 *addr) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); int i; bool done = false; wdev_lock(wdev); nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); if (wdev->sme_state == CFG80211_SME_CONNECTING) __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { if (wdev->auth_bsses[i] && memcmp(wdev->auth_bsses[i]->pub.bssid, addr, ETH_ALEN) == 0) { cfg80211_unhold_bss(wdev->auth_bsses[i]); cfg80211_put_bss(&wdev->auth_bsses[i]->pub); wdev->auth_bsses[i] = NULL; done = true; break; } } WARN_ON(!done); wdev_unlock(wdev); }
void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss, const u8 *buf, size_t len, int uapsd_queues) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; u8 *ie = mgmt->u.assoc_resp.variable; int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); u16 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); trace_cfg80211_send_rx_assoc(dev, bss); /* * This is a bit of a hack, we don't notify userspace of * a (re-)association reply if we tried to send a reassoc * and got a reject -- we only try again with an assoc * frame instead of reassoc. */ if (cfg80211_sme_rx_assoc_resp(wdev, status_code)) { cfg80211_unhold_bss(bss_from_pub(bss)); cfg80211_put_bss(wiphy, bss); return; } nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL, uapsd_queues); /* update current_bss etc., consumes the bss reference */ __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, status_code, status_code == WLAN_STATUS_SUCCESS, bss); }
void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, const u8 *buf, size_t len) { u16 status_code; 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; u8 *ie = mgmt->u.assoc_resp.variable; int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); trace_cfg80211_send_rx_assoc(dev, bss); wdev_lock(wdev); status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); /* * This is a bit of a hack, we don't notify userspace of * a (re-)association reply if we tried to send a reassoc * and got a reject -- we only try again with an assoc * frame instead of reassoc. */ if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && cfg80211_sme_failed_reassoc(wdev)) { cfg80211_put_bss(wiphy, bss); goto out; } nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); if (status_code != WLAN_STATUS_SUCCESS && wdev->conn) { cfg80211_sme_failed_assoc(wdev); /* * do not call connect_result() now because the * sme will schedule work that does it later. */ cfg80211_put_bss(wiphy, bss); goto out; } if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) { /* * This is for the userspace SME, the CONNECTING * state will be changed to CONNECTED by * __cfg80211_connect_result() below. */ wdev->sme_state = CFG80211_SME_CONNECTING; } /* this consumes the bss reference */ __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, status_code, status_code == WLAN_STATUS_SUCCESS, bss); out: wdev_unlock(wdev); }
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); wdev_lock(wdev); nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); if (wdev->sme_state == CFG80211_SME_CONNECTING) __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); wdev_unlock(wdev); }
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); } }
void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss, const u8 *buf, size_t len, int uapsd_queues) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; struct cfg80211_connect_resp_params cr; memset(&cr, 0, sizeof(cr)); cr.status = (int)le16_to_cpu(mgmt->u.assoc_resp.status_code); cr.bssid = mgmt->bssid; cr.bss = bss; cr.resp_ie = mgmt->u.assoc_resp.variable; cr.resp_ie_len = len - offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); cr.timeout_reason = NL80211_TIMEOUT_UNSPECIFIED; trace_cfg80211_send_rx_assoc(dev, bss); /* * This is a bit of a hack, we don't notify userspace of * a (re-)association reply if we tried to send a reassoc * and got a reject -- we only try again with an assoc * frame instead of reassoc. */ if (cfg80211_sme_rx_assoc_resp(wdev, cr.status)) { cfg80211_unhold_bss(bss_from_pub(bss)); cfg80211_put_bss(wiphy, bss); return; } nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL, uapsd_queues); /* update current_bss etc., consumes the bss reference */ __cfg80211_connect_result(dev, &cr, cr.status == WLAN_STATUS_SUCCESS); }
void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) { u16 status_code; 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; u8 *ie = mgmt->u.assoc_resp.variable; int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); struct cfg80211_internal_bss *bss = NULL; wdev_lock(wdev); status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); /* * This is a bit of a hack, we don't notify userspace of * a (re-)association reply if we tried to send a reassoc * and got a reject -- we only try again with an assoc * frame instead of reassoc. */ if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && cfg80211_sme_failed_reassoc(wdev)) goto out; nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); if (status_code == WLAN_STATUS_SUCCESS) { for (i = 0; i < MAX_AUTH_BSSES; i++) { if (!wdev->auth_bsses[i]) continue; if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid, ETH_ALEN) == 0) { bss = wdev->auth_bsses[i]; wdev->auth_bsses[i] = NULL; /* additional reference to drop hold */ cfg80211_ref_bss(bss); break; } } /* * We might be coming here because the driver reported * a successful association at the same time as the * user requested a deauth. In that case, we will have * removed the BSS from the auth_bsses list due to the * deauth request when the assoc response makes it. If * the two code paths acquire the lock the other way * around, that's just the standard situation of a * deauth being requested while connected. */ if (!bss) goto out; } else if (wdev->conn) { cfg80211_sme_failed_assoc(wdev); /* * do not call connect_result() now because the * sme will schedule work that does it later. */ goto out; } if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) { /* * This is for the userspace SME, the CONNECTING * state will be changed to CONNECTED by * __cfg80211_connect_result() below. */ wdev->sme_state = CFG80211_SME_CONNECTING; } /* this consumes one bss reference (unless bss is NULL) */ __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, status_code, status_code == WLAN_STATUS_SUCCESS, bss ? &bss->pub : NULL); /* drop hold now, and also reference acquired above */ if (bss) { cfg80211_unhold_bss(bss); cfg80211_put_bss(&bss->pub); } out: wdev_unlock(wdev); }