0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/etherdevice.h>
0013 #include <linux/if_arp.h>
0014 #include <linux/slab.h>
0015 #include <linux/workqueue.h>
0016 #include <linux/wireless.h>
0017 #include <linux/export.h>
0018 #include <net/iw_handler.h>
0019 #include <net/cfg80211.h>
0020 #include <net/rtnetlink.h>
0021 #include "nl80211.h"
0022 #include "reg.h"
0023 #include "rdev-ops.h"
0024
0025
0026
0027
0028
0029
0030
0031 struct cfg80211_conn {
0032 struct cfg80211_connect_params params;
0033
0034 enum {
0035 CFG80211_CONN_SCANNING,
0036 CFG80211_CONN_SCAN_AGAIN,
0037 CFG80211_CONN_AUTHENTICATE_NEXT,
0038 CFG80211_CONN_AUTHENTICATING,
0039 CFG80211_CONN_AUTH_FAILED_TIMEOUT,
0040 CFG80211_CONN_ASSOCIATE_NEXT,
0041 CFG80211_CONN_ASSOCIATING,
0042 CFG80211_CONN_ASSOC_FAILED,
0043 CFG80211_CONN_ASSOC_FAILED_TIMEOUT,
0044 CFG80211_CONN_DEAUTH,
0045 CFG80211_CONN_ABANDON,
0046 CFG80211_CONN_CONNECTED,
0047 } state;
0048 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
0049 const u8 *ie;
0050 size_t ie_len;
0051 bool auto_auth, prev_bssid_valid;
0052 };
0053
0054 static void cfg80211_sme_free(struct wireless_dev *wdev)
0055 {
0056 if (!wdev->conn)
0057 return;
0058
0059 kfree(wdev->conn->ie);
0060 kfree(wdev->conn);
0061 wdev->conn = NULL;
0062 }
0063
0064 static int cfg80211_conn_scan(struct wireless_dev *wdev)
0065 {
0066 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0067 struct cfg80211_scan_request *request;
0068 int n_channels, err;
0069
0070 ASSERT_WDEV_LOCK(wdev);
0071
0072 if (rdev->scan_req || rdev->scan_msg)
0073 return -EBUSY;
0074
0075 if (wdev->conn->params.channel)
0076 n_channels = 1;
0077 else
0078 n_channels = ieee80211_get_num_supported_channels(wdev->wiphy);
0079
0080 request = kzalloc(sizeof(*request) + sizeof(request->ssids[0]) +
0081 sizeof(request->channels[0]) * n_channels,
0082 GFP_KERNEL);
0083 if (!request)
0084 return -ENOMEM;
0085
0086 if (wdev->conn->params.channel) {
0087 enum nl80211_band band = wdev->conn->params.channel->band;
0088 struct ieee80211_supported_band *sband =
0089 wdev->wiphy->bands[band];
0090
0091 if (!sband) {
0092 kfree(request);
0093 return -EINVAL;
0094 }
0095 request->channels[0] = wdev->conn->params.channel;
0096 request->rates[band] = (1 << sband->n_bitrates) - 1;
0097 } else {
0098 int i = 0, j;
0099 enum nl80211_band band;
0100 struct ieee80211_supported_band *bands;
0101 struct ieee80211_channel *channel;
0102
0103 for (band = 0; band < NUM_NL80211_BANDS; band++) {
0104 bands = wdev->wiphy->bands[band];
0105 if (!bands)
0106 continue;
0107 for (j = 0; j < bands->n_channels; j++) {
0108 channel = &bands->channels[j];
0109 if (channel->flags & IEEE80211_CHAN_DISABLED)
0110 continue;
0111 request->channels[i++] = channel;
0112 }
0113 request->rates[band] = (1 << bands->n_bitrates) - 1;
0114 }
0115 n_channels = i;
0116 }
0117 request->n_channels = n_channels;
0118 request->ssids = (void *)&request->channels[n_channels];
0119 request->n_ssids = 1;
0120
0121 memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,
0122 wdev->conn->params.ssid_len);
0123 request->ssids[0].ssid_len = wdev->conn->params.ssid_len;
0124
0125 eth_broadcast_addr(request->bssid);
0126
0127 request->wdev = wdev;
0128 request->wiphy = &rdev->wiphy;
0129 request->scan_start = jiffies;
0130
0131 rdev->scan_req = request;
0132
0133 err = rdev_scan(rdev, request);
0134 if (!err) {
0135 wdev->conn->state = CFG80211_CONN_SCANNING;
0136 nl80211_send_scan_start(rdev, wdev);
0137 dev_hold(wdev->netdev);
0138 } else {
0139 rdev->scan_req = NULL;
0140 kfree(request);
0141 }
0142 return err;
0143 }
0144
0145 static int cfg80211_conn_do_work(struct wireless_dev *wdev,
0146 enum nl80211_timeout_reason *treason)
0147 {
0148 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0149 struct cfg80211_connect_params *params;
0150 struct cfg80211_auth_request auth_req = {};
0151 struct cfg80211_assoc_request req = {};
0152 int err;
0153
0154 ASSERT_WDEV_LOCK(wdev);
0155
0156 if (!wdev->conn)
0157 return 0;
0158
0159 params = &wdev->conn->params;
0160
0161 switch (wdev->conn->state) {
0162 case CFG80211_CONN_SCANNING:
0163
0164 return -ENOENT;
0165 case CFG80211_CONN_SCAN_AGAIN:
0166 return cfg80211_conn_scan(wdev);
0167 case CFG80211_CONN_AUTHENTICATE_NEXT:
0168 if (WARN_ON(!rdev->ops->auth))
0169 return -EOPNOTSUPP;
0170 wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
0171 auth_req.key = params->key;
0172 auth_req.key_len = params->key_len;
0173 auth_req.key_idx = params->key_idx;
0174 auth_req.auth_type = params->auth_type;
0175 auth_req.bss = cfg80211_get_bss(&rdev->wiphy, params->channel,
0176 params->bssid,
0177 params->ssid, params->ssid_len,
0178 IEEE80211_BSS_TYPE_ESS,
0179 IEEE80211_PRIVACY_ANY);
0180 auth_req.link_id = -1;
0181 err = cfg80211_mlme_auth(rdev, wdev->netdev, &auth_req);
0182 cfg80211_put_bss(&rdev->wiphy, auth_req.bss);
0183 return err;
0184 case CFG80211_CONN_AUTH_FAILED_TIMEOUT:
0185 *treason = NL80211_TIMEOUT_AUTH;
0186 return -ENOTCONN;
0187 case CFG80211_CONN_ASSOCIATE_NEXT:
0188 if (WARN_ON(!rdev->ops->assoc))
0189 return -EOPNOTSUPP;
0190 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
0191 if (wdev->conn->prev_bssid_valid)
0192 req.prev_bssid = wdev->conn->prev_bssid;
0193 req.ie = params->ie;
0194 req.ie_len = params->ie_len;
0195 req.use_mfp = params->mfp != NL80211_MFP_NO;
0196 req.crypto = params->crypto;
0197 req.flags = params->flags;
0198 req.ht_capa = params->ht_capa;
0199 req.ht_capa_mask = params->ht_capa_mask;
0200 req.vht_capa = params->vht_capa;
0201 req.vht_capa_mask = params->vht_capa_mask;
0202 req.link_id = -1;
0203
0204 req.bss = cfg80211_get_bss(&rdev->wiphy, params->channel,
0205 params->bssid,
0206 params->ssid, params->ssid_len,
0207 IEEE80211_BSS_TYPE_ESS,
0208 IEEE80211_PRIVACY_ANY);
0209 if (!req.bss) {
0210 err = -ENOENT;
0211 } else {
0212 err = cfg80211_mlme_assoc(rdev, wdev->netdev, &req);
0213 cfg80211_put_bss(&rdev->wiphy, req.bss);
0214 }
0215
0216 if (err)
0217 cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
0218 NULL, 0,
0219 WLAN_REASON_DEAUTH_LEAVING,
0220 false);
0221 return err;
0222 case CFG80211_CONN_ASSOC_FAILED_TIMEOUT:
0223 *treason = NL80211_TIMEOUT_ASSOC;
0224 fallthrough;
0225 case CFG80211_CONN_ASSOC_FAILED:
0226 cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
0227 NULL, 0,
0228 WLAN_REASON_DEAUTH_LEAVING, false);
0229 return -ENOTCONN;
0230 case CFG80211_CONN_DEAUTH:
0231 cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
0232 NULL, 0,
0233 WLAN_REASON_DEAUTH_LEAVING, false);
0234 fallthrough;
0235 case CFG80211_CONN_ABANDON:
0236
0237 cfg80211_sme_free(wdev);
0238 return 0;
0239 default:
0240 return 0;
0241 }
0242 }
0243
0244 void cfg80211_conn_work(struct work_struct *work)
0245 {
0246 struct cfg80211_registered_device *rdev =
0247 container_of(work, struct cfg80211_registered_device, conn_work);
0248 struct wireless_dev *wdev;
0249 u8 bssid_buf[ETH_ALEN], *bssid = NULL;
0250 enum nl80211_timeout_reason treason;
0251
0252 wiphy_lock(&rdev->wiphy);
0253
0254 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
0255 if (!wdev->netdev)
0256 continue;
0257
0258 wdev_lock(wdev);
0259 if (!netif_running(wdev->netdev)) {
0260 wdev_unlock(wdev);
0261 continue;
0262 }
0263 if (!wdev->conn ||
0264 wdev->conn->state == CFG80211_CONN_CONNECTED) {
0265 wdev_unlock(wdev);
0266 continue;
0267 }
0268 if (wdev->conn->params.bssid) {
0269 memcpy(bssid_buf, wdev->conn->params.bssid, ETH_ALEN);
0270 bssid = bssid_buf;
0271 }
0272 treason = NL80211_TIMEOUT_UNSPECIFIED;
0273 if (cfg80211_conn_do_work(wdev, &treason)) {
0274 struct cfg80211_connect_resp_params cr;
0275
0276 memset(&cr, 0, sizeof(cr));
0277 cr.status = -1;
0278 cr.links[0].bssid = bssid;
0279 cr.timeout_reason = treason;
0280 __cfg80211_connect_result(wdev->netdev, &cr, false);
0281 }
0282 wdev_unlock(wdev);
0283 }
0284
0285 wiphy_unlock(&rdev->wiphy);
0286 }
0287
0288
0289 static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev)
0290 {
0291 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0292 struct cfg80211_bss *bss;
0293
0294 ASSERT_WDEV_LOCK(wdev);
0295
0296 bss = cfg80211_get_bss(wdev->wiphy, wdev->conn->params.channel,
0297 wdev->conn->params.bssid,
0298 wdev->conn->params.ssid,
0299 wdev->conn->params.ssid_len,
0300 wdev->conn_bss_type,
0301 IEEE80211_PRIVACY(wdev->conn->params.privacy));
0302 if (!bss)
0303 return NULL;
0304
0305 memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN);
0306 wdev->conn->params.bssid = wdev->conn->bssid;
0307 wdev->conn->params.channel = bss->channel;
0308 wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
0309 schedule_work(&rdev->conn_work);
0310
0311 return bss;
0312 }
0313
0314 static void __cfg80211_sme_scan_done(struct net_device *dev)
0315 {
0316 struct wireless_dev *wdev = dev->ieee80211_ptr;
0317 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0318 struct cfg80211_bss *bss;
0319
0320 ASSERT_WDEV_LOCK(wdev);
0321
0322 if (!wdev->conn)
0323 return;
0324
0325 if (wdev->conn->state != CFG80211_CONN_SCANNING &&
0326 wdev->conn->state != CFG80211_CONN_SCAN_AGAIN)
0327 return;
0328
0329 bss = cfg80211_get_conn_bss(wdev);
0330 if (bss)
0331 cfg80211_put_bss(&rdev->wiphy, bss);
0332 else
0333 schedule_work(&rdev->conn_work);
0334 }
0335
0336 void cfg80211_sme_scan_done(struct net_device *dev)
0337 {
0338 struct wireless_dev *wdev = dev->ieee80211_ptr;
0339
0340 wdev_lock(wdev);
0341 __cfg80211_sme_scan_done(dev);
0342 wdev_unlock(wdev);
0343 }
0344
0345 void cfg80211_sme_rx_auth(struct wireless_dev *wdev, const u8 *buf, size_t len)
0346 {
0347 struct wiphy *wiphy = wdev->wiphy;
0348 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
0349 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
0350 u16 status_code = le16_to_cpu(mgmt->u.auth.status_code);
0351
0352 ASSERT_WDEV_LOCK(wdev);
0353
0354 if (!wdev->conn || wdev->conn->state == CFG80211_CONN_CONNECTED)
0355 return;
0356
0357 if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
0358 wdev->conn->auto_auth &&
0359 wdev->conn->params.auth_type != NL80211_AUTHTYPE_NETWORK_EAP) {
0360
0361 switch (wdev->conn->params.auth_type) {
0362 case NL80211_AUTHTYPE_OPEN_SYSTEM:
0363 if (wdev->connect_keys)
0364 wdev->conn->params.auth_type =
0365 NL80211_AUTHTYPE_SHARED_KEY;
0366 else
0367 wdev->conn->params.auth_type =
0368 NL80211_AUTHTYPE_NETWORK_EAP;
0369 break;
0370 case NL80211_AUTHTYPE_SHARED_KEY:
0371 wdev->conn->params.auth_type =
0372 NL80211_AUTHTYPE_NETWORK_EAP;
0373 break;
0374 default:
0375
0376 wdev->conn->params.auth_type =
0377 NL80211_AUTHTYPE_OPEN_SYSTEM;
0378 break;
0379 }
0380 wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
0381 schedule_work(&rdev->conn_work);
0382 } else if (status_code != WLAN_STATUS_SUCCESS) {
0383 struct cfg80211_connect_resp_params cr;
0384
0385 memset(&cr, 0, sizeof(cr));
0386 cr.status = status_code;
0387 cr.links[0].bssid = mgmt->bssid;
0388 cr.timeout_reason = NL80211_TIMEOUT_UNSPECIFIED;
0389 __cfg80211_connect_result(wdev->netdev, &cr, false);
0390 } else if (wdev->conn->state == CFG80211_CONN_AUTHENTICATING) {
0391 wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
0392 schedule_work(&rdev->conn_work);
0393 }
0394 }
0395
0396 bool cfg80211_sme_rx_assoc_resp(struct wireless_dev *wdev, u16 status)
0397 {
0398 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0399
0400 if (!wdev->conn)
0401 return false;
0402
0403 if (status == WLAN_STATUS_SUCCESS) {
0404 wdev->conn->state = CFG80211_CONN_CONNECTED;
0405 return false;
0406 }
0407
0408 if (wdev->conn->prev_bssid_valid) {
0409
0410
0411
0412
0413
0414 wdev->conn->prev_bssid_valid = false;
0415 wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
0416 schedule_work(&rdev->conn_work);
0417 return true;
0418 }
0419
0420 wdev->conn->state = CFG80211_CONN_ASSOC_FAILED;
0421 schedule_work(&rdev->conn_work);
0422 return false;
0423 }
0424
0425 void cfg80211_sme_deauth(struct wireless_dev *wdev)
0426 {
0427 cfg80211_sme_free(wdev);
0428 }
0429
0430 void cfg80211_sme_auth_timeout(struct wireless_dev *wdev)
0431 {
0432 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0433
0434 if (!wdev->conn)
0435 return;
0436
0437 wdev->conn->state = CFG80211_CONN_AUTH_FAILED_TIMEOUT;
0438 schedule_work(&rdev->conn_work);
0439 }
0440
0441 void cfg80211_sme_disassoc(struct wireless_dev *wdev)
0442 {
0443 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0444
0445 if (!wdev->conn)
0446 return;
0447
0448 wdev->conn->state = CFG80211_CONN_DEAUTH;
0449 schedule_work(&rdev->conn_work);
0450 }
0451
0452 void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
0453 {
0454 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0455
0456 if (!wdev->conn)
0457 return;
0458
0459 wdev->conn->state = CFG80211_CONN_ASSOC_FAILED_TIMEOUT;
0460 schedule_work(&rdev->conn_work);
0461 }
0462
0463 void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev)
0464 {
0465 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0466
0467 if (!wdev->conn)
0468 return;
0469
0470 wdev->conn->state = CFG80211_CONN_ABANDON;
0471 schedule_work(&rdev->conn_work);
0472 }
0473
0474 static void cfg80211_wdev_release_bsses(struct wireless_dev *wdev)
0475 {
0476 unsigned int link;
0477
0478 for_each_valid_link(wdev, link) {
0479 if (!wdev->links[link].client.current_bss)
0480 continue;
0481 cfg80211_unhold_bss(wdev->links[link].client.current_bss);
0482 cfg80211_put_bss(wdev->wiphy,
0483 &wdev->links[link].client.current_bss->pub);
0484 wdev->links[link].client.current_bss = NULL;
0485 }
0486 }
0487
0488 static int cfg80211_sme_get_conn_ies(struct wireless_dev *wdev,
0489 const u8 *ies, size_t ies_len,
0490 const u8 **out_ies, size_t *out_ies_len)
0491 {
0492 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0493 u8 *buf;
0494 size_t offs;
0495
0496 if (!rdev->wiphy.extended_capabilities_len ||
0497 (ies && cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, ies, ies_len))) {
0498 *out_ies = kmemdup(ies, ies_len, GFP_KERNEL);
0499 if (!*out_ies)
0500 return -ENOMEM;
0501 *out_ies_len = ies_len;
0502 return 0;
0503 }
0504
0505 buf = kmalloc(ies_len + rdev->wiphy.extended_capabilities_len + 2,
0506 GFP_KERNEL);
0507 if (!buf)
0508 return -ENOMEM;
0509
0510 if (ies_len) {
0511 static const u8 before_extcapa[] = {
0512
0513 WLAN_EID_RSN,
0514 WLAN_EID_QOS_CAPA,
0515 WLAN_EID_RRM_ENABLED_CAPABILITIES,
0516 WLAN_EID_MOBILITY_DOMAIN,
0517 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
0518 WLAN_EID_BSS_COEX_2040,
0519 };
0520
0521 offs = ieee80211_ie_split(ies, ies_len, before_extcapa,
0522 ARRAY_SIZE(before_extcapa), 0);
0523 memcpy(buf, ies, offs);
0524
0525 memcpy(buf + offs + rdev->wiphy.extended_capabilities_len + 2,
0526 ies + offs, ies_len - offs);
0527 } else {
0528 offs = 0;
0529 }
0530
0531
0532 buf[offs] = WLAN_EID_EXT_CAPABILITY;
0533 buf[offs + 1] = rdev->wiphy.extended_capabilities_len;
0534 memcpy(buf + offs + 2,
0535 rdev->wiphy.extended_capabilities,
0536 rdev->wiphy.extended_capabilities_len);
0537
0538 *out_ies = buf;
0539 *out_ies_len = ies_len + rdev->wiphy.extended_capabilities_len + 2;
0540
0541 return 0;
0542 }
0543
0544 static int cfg80211_sme_connect(struct wireless_dev *wdev,
0545 struct cfg80211_connect_params *connect,
0546 const u8 *prev_bssid)
0547 {
0548 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0549 struct cfg80211_bss *bss;
0550 int err;
0551
0552 if (!rdev->ops->auth || !rdev->ops->assoc)
0553 return -EOPNOTSUPP;
0554
0555 cfg80211_wdev_release_bsses(wdev);
0556
0557 if (wdev->connected) {
0558 cfg80211_sme_free(wdev);
0559 wdev->connected = false;
0560 }
0561
0562 if (wdev->conn)
0563 return -EINPROGRESS;
0564
0565 wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL);
0566 if (!wdev->conn)
0567 return -ENOMEM;
0568
0569
0570
0571
0572 memcpy(&wdev->conn->params, connect, sizeof(*connect));
0573 if (connect->bssid) {
0574 wdev->conn->params.bssid = wdev->conn->bssid;
0575 memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
0576 }
0577
0578 if (cfg80211_sme_get_conn_ies(wdev, connect->ie, connect->ie_len,
0579 &wdev->conn->ie,
0580 &wdev->conn->params.ie_len)) {
0581 kfree(wdev->conn);
0582 wdev->conn = NULL;
0583 return -ENOMEM;
0584 }
0585 wdev->conn->params.ie = wdev->conn->ie;
0586
0587 if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
0588 wdev->conn->auto_auth = true;
0589
0590 wdev->conn->params.auth_type =
0591 NL80211_AUTHTYPE_OPEN_SYSTEM;
0592 } else {
0593 wdev->conn->auto_auth = false;
0594 }
0595
0596 wdev->conn->params.ssid = wdev->u.client.ssid;
0597 wdev->conn->params.ssid_len = wdev->u.client.ssid_len;
0598
0599
0600 bss = cfg80211_get_conn_bss(wdev);
0601
0602 if (prev_bssid) {
0603 memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN);
0604 wdev->conn->prev_bssid_valid = true;
0605 }
0606
0607
0608 if (bss) {
0609 enum nl80211_timeout_reason treason;
0610
0611 err = cfg80211_conn_do_work(wdev, &treason);
0612 cfg80211_put_bss(wdev->wiphy, bss);
0613 } else {
0614
0615 err = cfg80211_conn_scan(wdev);
0616
0617
0618
0619
0620
0621
0622 if (err == -EBUSY) {
0623 err = 0;
0624 wdev->conn->state = CFG80211_CONN_SCAN_AGAIN;
0625 }
0626 }
0627
0628 if (err)
0629 cfg80211_sme_free(wdev);
0630
0631 return err;
0632 }
0633
0634 static int cfg80211_sme_disconnect(struct wireless_dev *wdev, u16 reason)
0635 {
0636 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0637 int err;
0638
0639 if (!wdev->conn)
0640 return 0;
0641
0642 if (!rdev->ops->deauth)
0643 return -EOPNOTSUPP;
0644
0645 if (wdev->conn->state == CFG80211_CONN_SCANNING ||
0646 wdev->conn->state == CFG80211_CONN_SCAN_AGAIN) {
0647 err = 0;
0648 goto out;
0649 }
0650
0651
0652 err = cfg80211_mlme_deauth(rdev, wdev->netdev,
0653 wdev->conn->params.bssid,
0654 NULL, 0, reason, false);
0655 out:
0656 cfg80211_sme_free(wdev);
0657 return err;
0658 }
0659
0660
0661
0662
0663
0664 static bool cfg80211_is_all_idle(void)
0665 {
0666 struct cfg80211_registered_device *rdev;
0667 struct wireless_dev *wdev;
0668 bool is_all_idle = true;
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
0679 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
0680 wdev_lock(wdev);
0681 if (wdev->conn || wdev->connected ||
0682 cfg80211_beaconing_iface_active(wdev))
0683 is_all_idle = false;
0684 wdev_unlock(wdev);
0685 }
0686 }
0687
0688 return is_all_idle;
0689 }
0690
0691 static void disconnect_work(struct work_struct *work)
0692 {
0693 rtnl_lock();
0694 if (cfg80211_is_all_idle())
0695 regulatory_hint_disconnect();
0696 rtnl_unlock();
0697 }
0698
0699 DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
0700
0701 static void
0702 cfg80211_connect_result_release_bsses(struct wireless_dev *wdev,
0703 struct cfg80211_connect_resp_params *cr)
0704 {
0705 unsigned int link;
0706
0707 for_each_valid_link(cr, link) {
0708 if (!cr->links[link].bss)
0709 continue;
0710 cfg80211_unhold_bss(bss_from_pub(cr->links[link].bss));
0711 cfg80211_put_bss(wdev->wiphy, cr->links[link].bss);
0712 }
0713 }
0714
0715
0716
0717
0718
0719
0720
0721 void __cfg80211_connect_result(struct net_device *dev,
0722 struct cfg80211_connect_resp_params *cr,
0723 bool wextev)
0724 {
0725 struct wireless_dev *wdev = dev->ieee80211_ptr;
0726 const struct element *country_elem = NULL;
0727 const u8 *country_data;
0728 u8 country_datalen;
0729 #ifdef CONFIG_CFG80211_WEXT
0730 union iwreq_data wrqu;
0731 #endif
0732 unsigned int link;
0733 const u8 *connected_addr;
0734 bool bss_not_found = false;
0735
0736 ASSERT_WDEV_LOCK(wdev);
0737
0738 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
0739 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
0740 goto out;
0741
0742 if (cr->valid_links) {
0743 if (WARN_ON(!cr->ap_mld_addr))
0744 goto out;
0745
0746 for_each_valid_link(cr, link) {
0747 if (WARN_ON(!cr->links[link].addr))
0748 goto out;
0749 }
0750 }
0751
0752 wdev->unprot_beacon_reported = 0;
0753 nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev, cr,
0754 GFP_KERNEL);
0755 connected_addr = cr->valid_links ? cr->ap_mld_addr : cr->links[0].bssid;
0756
0757 #ifdef CONFIG_CFG80211_WEXT
0758 if (wextev && !cr->valid_links) {
0759 if (cr->req_ie && cr->status == WLAN_STATUS_SUCCESS) {
0760 memset(&wrqu, 0, sizeof(wrqu));
0761 wrqu.data.length = cr->req_ie_len;
0762 wireless_send_event(dev, IWEVASSOCREQIE, &wrqu,
0763 cr->req_ie);
0764 }
0765
0766 if (cr->resp_ie && cr->status == WLAN_STATUS_SUCCESS) {
0767 memset(&wrqu, 0, sizeof(wrqu));
0768 wrqu.data.length = cr->resp_ie_len;
0769 wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu,
0770 cr->resp_ie);
0771 }
0772
0773 memset(&wrqu, 0, sizeof(wrqu));
0774 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
0775 if (connected_addr && cr->status == WLAN_STATUS_SUCCESS) {
0776 memcpy(wrqu.ap_addr.sa_data, connected_addr, ETH_ALEN);
0777 memcpy(wdev->wext.prev_bssid, connected_addr, ETH_ALEN);
0778 wdev->wext.prev_bssid_valid = true;
0779 }
0780 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
0781 }
0782 #endif
0783
0784 if (cr->status == WLAN_STATUS_SUCCESS) {
0785 if (!wiphy_to_rdev(wdev->wiphy)->ops->connect) {
0786 for_each_valid_link(cr, link) {
0787 if (WARN_ON_ONCE(!cr->links[link].bss))
0788 break;
0789 }
0790 }
0791
0792 for_each_valid_link(cr, link) {
0793 if (cr->links[link].bss)
0794 continue;
0795
0796 cr->links[link].bss =
0797 cfg80211_get_bss(wdev->wiphy, NULL,
0798 cr->links[link].bssid,
0799 wdev->u.client.ssid,
0800 wdev->u.client.ssid_len,
0801 wdev->conn_bss_type,
0802 IEEE80211_PRIVACY_ANY);
0803 if (!cr->links[link].bss) {
0804 bss_not_found = true;
0805 break;
0806 }
0807 cfg80211_hold_bss(bss_from_pub(cr->links[link].bss));
0808 }
0809 }
0810
0811 cfg80211_wdev_release_bsses(wdev);
0812
0813 if (cr->status != WLAN_STATUS_SUCCESS) {
0814 kfree_sensitive(wdev->connect_keys);
0815 wdev->connect_keys = NULL;
0816 wdev->u.client.ssid_len = 0;
0817 wdev->conn_owner_nlportid = 0;
0818 cfg80211_connect_result_release_bsses(wdev, cr);
0819 cfg80211_sme_free(wdev);
0820 return;
0821 }
0822
0823 if (WARN_ON(bss_not_found)) {
0824 cfg80211_connect_result_release_bsses(wdev, cr);
0825 return;
0826 }
0827
0828 memset(wdev->links, 0, sizeof(wdev->links));
0829 wdev->valid_links = cr->valid_links;
0830 for_each_valid_link(cr, link)
0831 wdev->links[link].client.current_bss =
0832 bss_from_pub(cr->links[link].bss);
0833 wdev->connected = true;
0834 ether_addr_copy(wdev->u.client.connected_addr, connected_addr);
0835 if (cr->valid_links) {
0836 for_each_valid_link(cr, link)
0837 memcpy(wdev->links[link].addr, cr->links[link].addr,
0838 ETH_ALEN);
0839 }
0840
0841 if (!(wdev->wiphy->flags & WIPHY_FLAG_HAS_STATIC_WEP))
0842 cfg80211_upload_connect_keys(wdev);
0843
0844 rcu_read_lock();
0845 for_each_valid_link(cr, link) {
0846 country_elem =
0847 ieee80211_bss_get_elem(cr->links[link].bss,
0848 WLAN_EID_COUNTRY);
0849 if (country_elem)
0850 break;
0851 }
0852 if (!country_elem) {
0853 rcu_read_unlock();
0854 return;
0855 }
0856
0857 country_datalen = country_elem->datalen;
0858 country_data = kmemdup(country_elem->data, country_datalen, GFP_ATOMIC);
0859 rcu_read_unlock();
0860
0861 if (!country_data)
0862 return;
0863
0864 regulatory_hint_country_ie(wdev->wiphy,
0865 cr->links[link].bss->channel->band,
0866 country_data, country_datalen);
0867 kfree(country_data);
0868
0869 return;
0870 out:
0871 for_each_valid_link(cr, link)
0872 cfg80211_put_bss(wdev->wiphy, cr->links[link].bss);
0873 }
0874
0875 static void cfg80211_update_link_bss(struct wireless_dev *wdev,
0876 struct cfg80211_bss **bss)
0877 {
0878 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0879 struct cfg80211_internal_bss *ibss;
0880
0881 if (!*bss)
0882 return;
0883
0884 ibss = bss_from_pub(*bss);
0885 if (list_empty(&ibss->list)) {
0886 struct cfg80211_bss *found = NULL, *tmp = *bss;
0887
0888 found = cfg80211_get_bss(wdev->wiphy, NULL,
0889 (*bss)->bssid,
0890 wdev->u.client.ssid,
0891 wdev->u.client.ssid_len,
0892 wdev->conn_bss_type,
0893 IEEE80211_PRIVACY_ANY);
0894 if (found) {
0895
0896
0897
0898 *bss = found;
0899 } else {
0900
0901
0902
0903
0904
0905
0906
0907
0908
0909 cfg80211_bss_update(rdev, ibss, false,
0910 ibss->ts);
0911 }
0912
0913 cfg80211_put_bss(wdev->wiphy, tmp);
0914 }
0915 }
0916
0917
0918 void cfg80211_connect_done(struct net_device *dev,
0919 struct cfg80211_connect_resp_params *params,
0920 gfp_t gfp)
0921 {
0922 struct wireless_dev *wdev = dev->ieee80211_ptr;
0923 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
0924 struct cfg80211_event *ev;
0925 unsigned long flags;
0926 u8 *next;
0927 size_t link_info_size = 0;
0928 unsigned int link;
0929
0930 for_each_valid_link(params, link) {
0931 cfg80211_update_link_bss(wdev, ¶ms->links[link].bss);
0932 link_info_size += params->links[link].bssid ? ETH_ALEN : 0;
0933 link_info_size += params->links[link].addr ? ETH_ALEN : 0;
0934 }
0935
0936 ev = kzalloc(sizeof(*ev) + (params->ap_mld_addr ? ETH_ALEN : 0) +
0937 params->req_ie_len + params->resp_ie_len +
0938 params->fils.kek_len + params->fils.pmk_len +
0939 (params->fils.pmkid ? WLAN_PMKID_LEN : 0) + link_info_size,
0940 gfp);
0941
0942 if (!ev) {
0943 for_each_valid_link(params, link)
0944 cfg80211_put_bss(wdev->wiphy,
0945 params->links[link].bss);
0946 return;
0947 }
0948
0949 ev->type = EVENT_CONNECT_RESULT;
0950 next = ((u8 *)ev) + sizeof(*ev);
0951 if (params->ap_mld_addr) {
0952 ev->cr.ap_mld_addr = next;
0953 memcpy((void *)ev->cr.ap_mld_addr, params->ap_mld_addr,
0954 ETH_ALEN);
0955 next += ETH_ALEN;
0956 }
0957 if (params->req_ie_len) {
0958 ev->cr.req_ie = next;
0959 ev->cr.req_ie_len = params->req_ie_len;
0960 memcpy((void *)ev->cr.req_ie, params->req_ie,
0961 params->req_ie_len);
0962 next += params->req_ie_len;
0963 }
0964 if (params->resp_ie_len) {
0965 ev->cr.resp_ie = next;
0966 ev->cr.resp_ie_len = params->resp_ie_len;
0967 memcpy((void *)ev->cr.resp_ie, params->resp_ie,
0968 params->resp_ie_len);
0969 next += params->resp_ie_len;
0970 }
0971 if (params->fils.kek_len) {
0972 ev->cr.fils.kek = next;
0973 ev->cr.fils.kek_len = params->fils.kek_len;
0974 memcpy((void *)ev->cr.fils.kek, params->fils.kek,
0975 params->fils.kek_len);
0976 next += params->fils.kek_len;
0977 }
0978 if (params->fils.pmk_len) {
0979 ev->cr.fils.pmk = next;
0980 ev->cr.fils.pmk_len = params->fils.pmk_len;
0981 memcpy((void *)ev->cr.fils.pmk, params->fils.pmk,
0982 params->fils.pmk_len);
0983 next += params->fils.pmk_len;
0984 }
0985 if (params->fils.pmkid) {
0986 ev->cr.fils.pmkid = next;
0987 memcpy((void *)ev->cr.fils.pmkid, params->fils.pmkid,
0988 WLAN_PMKID_LEN);
0989 next += WLAN_PMKID_LEN;
0990 }
0991 ev->cr.fils.update_erp_next_seq_num = params->fils.update_erp_next_seq_num;
0992 if (params->fils.update_erp_next_seq_num)
0993 ev->cr.fils.erp_next_seq_num = params->fils.erp_next_seq_num;
0994 ev->cr.valid_links = params->valid_links;
0995 for_each_valid_link(params, link) {
0996 if (params->links[link].bss)
0997 cfg80211_hold_bss(
0998 bss_from_pub(params->links[link].bss));
0999 ev->cr.links[link].bss = params->links[link].bss;
1000
1001 if (params->links[link].addr) {
1002 ev->cr.links[link].addr = next;
1003 memcpy((void *)ev->cr.links[link].addr,
1004 params->links[link].addr,
1005 ETH_ALEN);
1006 next += ETH_ALEN;
1007 }
1008 if (params->links[link].bssid) {
1009 ev->cr.links[link].bssid = next;
1010 memcpy((void *)ev->cr.links[link].bssid,
1011 params->links[link].bssid,
1012 ETH_ALEN);
1013 next += ETH_ALEN;
1014 }
1015 }
1016 ev->cr.status = params->status;
1017 ev->cr.timeout_reason = params->timeout_reason;
1018
1019 spin_lock_irqsave(&wdev->event_lock, flags);
1020 list_add_tail(&ev->list, &wdev->event_list);
1021 spin_unlock_irqrestore(&wdev->event_lock, flags);
1022 queue_work(cfg80211_wq, &rdev->event_work);
1023 }
1024 EXPORT_SYMBOL(cfg80211_connect_done);
1025
1026
1027 void __cfg80211_roamed(struct wireless_dev *wdev,
1028 struct cfg80211_roam_info *info)
1029 {
1030 #ifdef CONFIG_CFG80211_WEXT
1031 union iwreq_data wrqu;
1032 #endif
1033 unsigned int link;
1034 const u8 *connected_addr;
1035
1036 ASSERT_WDEV_LOCK(wdev);
1037
1038 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
1039 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
1040 goto out;
1041
1042 if (WARN_ON(!wdev->connected))
1043 goto out;
1044
1045 if (info->valid_links) {
1046 if (WARN_ON(!info->ap_mld_addr))
1047 goto out;
1048
1049 for_each_valid_link(info, link) {
1050 if (WARN_ON(!info->links[link].addr))
1051 goto out;
1052 }
1053 }
1054
1055 cfg80211_wdev_release_bsses(wdev);
1056
1057 for_each_valid_link(info, link) {
1058 if (WARN_ON(!info->links[link].bss))
1059 goto out;
1060 }
1061
1062 memset(wdev->links, 0, sizeof(wdev->links));
1063 wdev->valid_links = info->valid_links;
1064 for_each_valid_link(info, link) {
1065 cfg80211_hold_bss(bss_from_pub(info->links[link].bss));
1066 wdev->links[link].client.current_bss =
1067 bss_from_pub(info->links[link].bss);
1068 }
1069
1070 connected_addr = info->valid_links ?
1071 info->ap_mld_addr :
1072 info->links[0].bss->bssid;
1073 ether_addr_copy(wdev->u.client.connected_addr, connected_addr);
1074 if (info->valid_links) {
1075 for_each_valid_link(info, link)
1076 memcpy(wdev->links[link].addr, info->links[link].addr,
1077 ETH_ALEN);
1078 }
1079 wdev->unprot_beacon_reported = 0;
1080 nl80211_send_roamed(wiphy_to_rdev(wdev->wiphy),
1081 wdev->netdev, info, GFP_KERNEL);
1082
1083 #ifdef CONFIG_CFG80211_WEXT
1084 if (!info->valid_links) {
1085 if (info->req_ie) {
1086 memset(&wrqu, 0, sizeof(wrqu));
1087 wrqu.data.length = info->req_ie_len;
1088 wireless_send_event(wdev->netdev, IWEVASSOCREQIE,
1089 &wrqu, info->req_ie);
1090 }
1091
1092 if (info->resp_ie) {
1093 memset(&wrqu, 0, sizeof(wrqu));
1094 wrqu.data.length = info->resp_ie_len;
1095 wireless_send_event(wdev->netdev, IWEVASSOCRESPIE,
1096 &wrqu, info->resp_ie);
1097 }
1098
1099 memset(&wrqu, 0, sizeof(wrqu));
1100 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1101 memcpy(wrqu.ap_addr.sa_data, connected_addr, ETH_ALEN);
1102 memcpy(wdev->wext.prev_bssid, connected_addr, ETH_ALEN);
1103 wdev->wext.prev_bssid_valid = true;
1104 wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL);
1105 }
1106 #endif
1107
1108 return;
1109 out:
1110 for_each_valid_link(info, link)
1111 cfg80211_put_bss(wdev->wiphy, info->links[link].bss);
1112 }
1113
1114
1115 void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info,
1116 gfp_t gfp)
1117 {
1118 struct wireless_dev *wdev = dev->ieee80211_ptr;
1119 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
1120 struct cfg80211_event *ev;
1121 unsigned long flags;
1122 u8 *next;
1123 unsigned int link;
1124 size_t link_info_size = 0;
1125 bool bss_not_found = false;
1126
1127 for_each_valid_link(info, link) {
1128 link_info_size += info->links[link].addr ? ETH_ALEN : 0;
1129 link_info_size += info->links[link].bssid ? ETH_ALEN : 0;
1130
1131 if (info->links[link].bss)
1132 continue;
1133
1134 info->links[link].bss =
1135 cfg80211_get_bss(wdev->wiphy,
1136 info->links[link].channel,
1137 info->links[link].bssid,
1138 wdev->u.client.ssid,
1139 wdev->u.client.ssid_len,
1140 wdev->conn_bss_type,
1141 IEEE80211_PRIVACY_ANY);
1142
1143 if (!info->links[link].bss) {
1144 bss_not_found = true;
1145 break;
1146 }
1147 }
1148
1149 if (WARN_ON(bss_not_found))
1150 goto out;
1151
1152 ev = kzalloc(sizeof(*ev) + info->req_ie_len + info->resp_ie_len +
1153 info->fils.kek_len + info->fils.pmk_len +
1154 (info->fils.pmkid ? WLAN_PMKID_LEN : 0) +
1155 (info->ap_mld_addr ? ETH_ALEN : 0) + link_info_size, gfp);
1156 if (!ev)
1157 goto out;
1158
1159 ev->type = EVENT_ROAMED;
1160 next = ((u8 *)ev) + sizeof(*ev);
1161 if (info->req_ie_len) {
1162 ev->rm.req_ie = next;
1163 ev->rm.req_ie_len = info->req_ie_len;
1164 memcpy((void *)ev->rm.req_ie, info->req_ie, info->req_ie_len);
1165 next += info->req_ie_len;
1166 }
1167 if (info->resp_ie_len) {
1168 ev->rm.resp_ie = next;
1169 ev->rm.resp_ie_len = info->resp_ie_len;
1170 memcpy((void *)ev->rm.resp_ie, info->resp_ie,
1171 info->resp_ie_len);
1172 next += info->resp_ie_len;
1173 }
1174 if (info->fils.kek_len) {
1175 ev->rm.fils.kek = next;
1176 ev->rm.fils.kek_len = info->fils.kek_len;
1177 memcpy((void *)ev->rm.fils.kek, info->fils.kek,
1178 info->fils.kek_len);
1179 next += info->fils.kek_len;
1180 }
1181 if (info->fils.pmk_len) {
1182 ev->rm.fils.pmk = next;
1183 ev->rm.fils.pmk_len = info->fils.pmk_len;
1184 memcpy((void *)ev->rm.fils.pmk, info->fils.pmk,
1185 info->fils.pmk_len);
1186 next += info->fils.pmk_len;
1187 }
1188 if (info->fils.pmkid) {
1189 ev->rm.fils.pmkid = next;
1190 memcpy((void *)ev->rm.fils.pmkid, info->fils.pmkid,
1191 WLAN_PMKID_LEN);
1192 next += WLAN_PMKID_LEN;
1193 }
1194 ev->rm.fils.update_erp_next_seq_num = info->fils.update_erp_next_seq_num;
1195 if (info->fils.update_erp_next_seq_num)
1196 ev->rm.fils.erp_next_seq_num = info->fils.erp_next_seq_num;
1197 if (info->ap_mld_addr) {
1198 ev->rm.ap_mld_addr = next;
1199 memcpy((void *)ev->rm.ap_mld_addr, info->ap_mld_addr,
1200 ETH_ALEN);
1201 next += ETH_ALEN;
1202 }
1203 ev->rm.valid_links = info->valid_links;
1204 for_each_valid_link(info, link) {
1205 ev->rm.links[link].bss = info->links[link].bss;
1206
1207 if (info->links[link].addr) {
1208 ev->rm.links[link].addr = next;
1209 memcpy((void *)ev->rm.links[link].addr,
1210 info->links[link].addr,
1211 ETH_ALEN);
1212 next += ETH_ALEN;
1213 }
1214
1215 if (info->links[link].bssid) {
1216 ev->rm.links[link].bssid = next;
1217 memcpy((void *)ev->rm.links[link].bssid,
1218 info->links[link].bssid,
1219 ETH_ALEN);
1220 next += ETH_ALEN;
1221 }
1222 }
1223
1224 spin_lock_irqsave(&wdev->event_lock, flags);
1225 list_add_tail(&ev->list, &wdev->event_list);
1226 spin_unlock_irqrestore(&wdev->event_lock, flags);
1227 queue_work(cfg80211_wq, &rdev->event_work);
1228
1229 return;
1230 out:
1231 for_each_valid_link(info, link)
1232 cfg80211_put_bss(wdev->wiphy, info->links[link].bss);
1233
1234 }
1235 EXPORT_SYMBOL(cfg80211_roamed);
1236
1237 void __cfg80211_port_authorized(struct wireless_dev *wdev, const u8 *bssid)
1238 {
1239 ASSERT_WDEV_LOCK(wdev);
1240
1241 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
1242 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
1243 return;
1244
1245 if (WARN_ON(!wdev->connected) ||
1246 WARN_ON(!ether_addr_equal(wdev->u.client.connected_addr, bssid)))
1247 return;
1248
1249 nl80211_send_port_authorized(wiphy_to_rdev(wdev->wiphy), wdev->netdev,
1250 bssid);
1251 }
1252
1253 void cfg80211_port_authorized(struct net_device *dev, const u8 *bssid,
1254 gfp_t gfp)
1255 {
1256 struct wireless_dev *wdev = dev->ieee80211_ptr;
1257 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
1258 struct cfg80211_event *ev;
1259 unsigned long flags;
1260
1261 if (WARN_ON(!bssid))
1262 return;
1263
1264 ev = kzalloc(sizeof(*ev), gfp);
1265 if (!ev)
1266 return;
1267
1268 ev->type = EVENT_PORT_AUTHORIZED;
1269 memcpy(ev->pa.bssid, bssid, ETH_ALEN);
1270
1271
1272
1273
1274
1275 spin_lock_irqsave(&wdev->event_lock, flags);
1276 list_add_tail(&ev->list, &wdev->event_list);
1277 spin_unlock_irqrestore(&wdev->event_lock, flags);
1278 queue_work(cfg80211_wq, &rdev->event_work);
1279 }
1280 EXPORT_SYMBOL(cfg80211_port_authorized);
1281
1282 void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
1283 size_t ie_len, u16 reason, bool from_ap)
1284 {
1285 struct wireless_dev *wdev = dev->ieee80211_ptr;
1286 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
1287 int i;
1288 #ifdef CONFIG_CFG80211_WEXT
1289 union iwreq_data wrqu;
1290 #endif
1291
1292 ASSERT_WDEV_LOCK(wdev);
1293
1294 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
1295 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
1296 return;
1297
1298 cfg80211_wdev_release_bsses(wdev);
1299 wdev->connected = false;
1300 wdev->u.client.ssid_len = 0;
1301 wdev->conn_owner_nlportid = 0;
1302 kfree_sensitive(wdev->connect_keys);
1303 wdev->connect_keys = NULL;
1304
1305 nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
1306
1307
1308 if (rdev->ops->crit_proto_stop && rdev->crit_proto_nlportid) {
1309 rdev->crit_proto_nlportid = 0;
1310 rdev_crit_proto_stop(rdev, wdev);
1311 }
1312
1313
1314
1315
1316
1317 if (rdev->ops->del_key) {
1318 int max_key_idx = 5;
1319
1320 if (wiphy_ext_feature_isset(
1321 wdev->wiphy,
1322 NL80211_EXT_FEATURE_BEACON_PROTECTION) ||
1323 wiphy_ext_feature_isset(
1324 wdev->wiphy,
1325 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
1326 max_key_idx = 7;
1327 for (i = 0; i <= max_key_idx; i++)
1328 rdev_del_key(rdev, dev, i, false, NULL);
1329 }
1330
1331 rdev_set_qos_map(rdev, dev, NULL);
1332
1333 #ifdef CONFIG_CFG80211_WEXT
1334 memset(&wrqu, 0, sizeof(wrqu));
1335 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1336 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
1337 wdev->wext.connect.ssid_len = 0;
1338 #endif
1339
1340 schedule_work(&cfg80211_disconnect_work);
1341 }
1342
1343 void cfg80211_disconnected(struct net_device *dev, u16 reason,
1344 const u8 *ie, size_t ie_len,
1345 bool locally_generated, gfp_t gfp)
1346 {
1347 struct wireless_dev *wdev = dev->ieee80211_ptr;
1348 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
1349 struct cfg80211_event *ev;
1350 unsigned long flags;
1351
1352 ev = kzalloc(sizeof(*ev) + ie_len, gfp);
1353 if (!ev)
1354 return;
1355
1356 ev->type = EVENT_DISCONNECTED;
1357 ev->dc.ie = ((u8 *)ev) + sizeof(*ev);
1358 ev->dc.ie_len = ie_len;
1359 memcpy((void *)ev->dc.ie, ie, ie_len);
1360 ev->dc.reason = reason;
1361 ev->dc.locally_generated = locally_generated;
1362
1363 spin_lock_irqsave(&wdev->event_lock, flags);
1364 list_add_tail(&ev->list, &wdev->event_list);
1365 spin_unlock_irqrestore(&wdev->event_lock, flags);
1366 queue_work(cfg80211_wq, &rdev->event_work);
1367 }
1368 EXPORT_SYMBOL(cfg80211_disconnected);
1369
1370
1371
1372
1373 int cfg80211_connect(struct cfg80211_registered_device *rdev,
1374 struct net_device *dev,
1375 struct cfg80211_connect_params *connect,
1376 struct cfg80211_cached_keys *connkeys,
1377 const u8 *prev_bssid)
1378 {
1379 struct wireless_dev *wdev = dev->ieee80211_ptr;
1380 int err;
1381
1382 ASSERT_WDEV_LOCK(wdev);
1383
1384
1385
1386
1387
1388
1389 if (wdev->u.client.ssid_len &&
1390 (wdev->u.client.ssid_len != connect->ssid_len ||
1391 memcmp(wdev->u.client.ssid, connect->ssid, wdev->u.client.ssid_len)))
1392 return -EALREADY;
1393
1394
1395
1396
1397
1398 if (wdev->connected) {
1399 if (!prev_bssid)
1400 return -EALREADY;
1401 if (!ether_addr_equal(prev_bssid,
1402 wdev->u.client.connected_addr))
1403 return -ENOTCONN;
1404 }
1405
1406
1407
1408
1409
1410
1411 if (wdev->connect_keys)
1412 return -EINPROGRESS;
1413
1414 cfg80211_oper_and_ht_capa(&connect->ht_capa_mask,
1415 rdev->wiphy.ht_capa_mod_mask);
1416 cfg80211_oper_and_vht_capa(&connect->vht_capa_mask,
1417 rdev->wiphy.vht_capa_mod_mask);
1418
1419 if (connkeys && connkeys->def >= 0) {
1420 int idx;
1421 u32 cipher;
1422
1423 idx = connkeys->def;
1424 cipher = connkeys->params[idx].cipher;
1425
1426 if (cipher == WLAN_CIPHER_SUITE_WEP40 ||
1427 cipher == WLAN_CIPHER_SUITE_WEP104) {
1428 connect->key_idx = idx;
1429 connect->key = connkeys->params[idx].key;
1430 connect->key_len = connkeys->params[idx].key_len;
1431
1432
1433
1434
1435
1436 if (connect->crypto.cipher_group == 0)
1437 connect->crypto.cipher_group = cipher;
1438
1439 if (connect->crypto.n_ciphers_pairwise == 0) {
1440 connect->crypto.n_ciphers_pairwise = 1;
1441 connect->crypto.ciphers_pairwise[0] = cipher;
1442 }
1443 }
1444
1445 connect->crypto.wep_keys = connkeys->params;
1446 connect->crypto.wep_tx_key = connkeys->def;
1447 } else {
1448 if (WARN_ON(connkeys))
1449 return -EINVAL;
1450 }
1451
1452 wdev->connect_keys = connkeys;
1453 memcpy(wdev->u.client.ssid, connect->ssid, connect->ssid_len);
1454 wdev->u.client.ssid_len = connect->ssid_len;
1455
1456 wdev->conn_bss_type = connect->pbss ? IEEE80211_BSS_TYPE_PBSS :
1457 IEEE80211_BSS_TYPE_ESS;
1458
1459 if (!rdev->ops->connect)
1460 err = cfg80211_sme_connect(wdev, connect, prev_bssid);
1461 else
1462 err = rdev_connect(rdev, dev, connect);
1463
1464 if (err) {
1465 wdev->connect_keys = NULL;
1466
1467
1468
1469
1470 if (!wdev->connected)
1471 wdev->u.client.ssid_len = 0;
1472 return err;
1473 }
1474
1475 return 0;
1476 }
1477
1478 int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
1479 struct net_device *dev, u16 reason, bool wextev)
1480 {
1481 struct wireless_dev *wdev = dev->ieee80211_ptr;
1482 int err = 0;
1483
1484 ASSERT_WDEV_LOCK(wdev);
1485
1486 kfree_sensitive(wdev->connect_keys);
1487 wdev->connect_keys = NULL;
1488
1489 wdev->conn_owner_nlportid = 0;
1490
1491 if (wdev->conn)
1492 err = cfg80211_sme_disconnect(wdev, reason);
1493 else if (!rdev->ops->disconnect)
1494 cfg80211_mlme_down(rdev, dev);
1495 else if (wdev->u.client.ssid_len)
1496 err = rdev_disconnect(rdev, dev, reason);
1497
1498
1499
1500
1501
1502
1503 if (!wdev->connected)
1504 wdev->u.client.ssid_len = 0;
1505
1506 return err;
1507 }
1508
1509
1510
1511
1512
1513 void cfg80211_autodisconnect_wk(struct work_struct *work)
1514 {
1515 struct wireless_dev *wdev =
1516 container_of(work, struct wireless_dev, disconnect_wk);
1517 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
1518
1519 wdev_lock(wdev);
1520
1521 if (wdev->conn_owner_nlportid) {
1522 switch (wdev->iftype) {
1523 case NL80211_IFTYPE_ADHOC:
1524 __cfg80211_leave_ibss(rdev, wdev->netdev, false);
1525 break;
1526 case NL80211_IFTYPE_AP:
1527 case NL80211_IFTYPE_P2P_GO:
1528 __cfg80211_stop_ap(rdev, wdev->netdev, -1, false);
1529 break;
1530 case NL80211_IFTYPE_MESH_POINT:
1531 __cfg80211_leave_mesh(rdev, wdev->netdev);
1532 break;
1533 case NL80211_IFTYPE_STATION:
1534 case NL80211_IFTYPE_P2P_CLIENT:
1535
1536
1537
1538
1539
1540 if (rdev->ops->disconnect || wdev->connected)
1541 cfg80211_disconnect(rdev, wdev->netdev,
1542 WLAN_REASON_DEAUTH_LEAVING,
1543 true);
1544 else
1545 cfg80211_mlme_deauth(rdev, wdev->netdev,
1546 wdev->disconnect_bssid,
1547 NULL, 0,
1548 WLAN_REASON_DEAUTH_LEAVING,
1549 false);
1550 break;
1551 default:
1552 break;
1553 }
1554 }
1555
1556 wdev_unlock(wdev);
1557 }