Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * SME code for cfg80211
0004  * both driver SME event handling and the SME implementation
0005  * (for nl80211's connect() and wext)
0006  *
0007  * Copyright 2009   Johannes Berg <johannes@sipsolutions.net>
0008  * Copyright (C) 2009, 2020, 2022 Intel Corporation. All rights reserved.
0009  * Copyright 2017   Intel Deutschland GmbH
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  * Software SME in cfg80211, using auth/assoc/deauth calls to the
0027  * driver. This is for implementing nl80211's connect/disconnect
0028  * and wireless extensions (if configured.)
0029  */
0030 
0031 struct cfg80211_conn {
0032     struct cfg80211_connect_params params;
0033     /* these are sub-states of the _CONNECTING sme_state */
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         /* didn't find it during scan ... */
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         /* free directly, disconnected event already sent */
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 /* Returned bss is reference counted and must be cleaned up appropriately. */
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         /* select automatically between only open, shared, leap */
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             /* huh? */
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          * Some stupid APs don't accept reassoc, so we
0411          * need to fall back to trying regular assoc;
0412          * return true so no event is sent to userspace.
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             /* not listing IEs expected to be created by driver */
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         /* leave a whole for extended capabilities IE */
0525         memcpy(buf + offs + rdev->wiphy.extended_capabilities_len + 2,
0526                ies + offs, ies_len - offs);
0527     } else {
0528         offs = 0;
0529     }
0530 
0531     /* place extended capabilities IE (with only driver capabilities) */
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      * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
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         /* start with open system ... should mostly work */
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     /* see if we have the bss already */
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     /* we're good if we have a matching bss struct */
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         /* otherwise we'll need to scan for the AP first */
0615         err = cfg80211_conn_scan(wdev);
0616 
0617         /*
0618          * If we can't scan right now, then we need to scan again
0619          * after the current scan finished, since the parameters
0620          * changed (unless we find a good AP anyway).
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     /* wdev->conn->params.bssid must be set if > SCANNING */
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  * code shared for in-device and software SME
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      * All devices must be idle as otherwise if you are actively
0672      * scanning some new beacon hints could be learned and would
0673      * count as new regulatory hints.
0674      * Also if there is any other active beaconing interface we
0675      * need not issue a disconnect hint and reset any info such
0676      * as chan dfs state, etc.
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  * API calls for drivers implementing connect/disconnect and
0717  * SME event handling
0718  */
0719 
0720 /* This method must consume bss one way or another */
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             /* The same BSS is already updated so use it
0896              * instead, as it has latest info.
0897              */
0898             *bss = found;
0899         } else {
0900             /* Update with BSS provided by driver, it will
0901              * be freshly added and ref cnted, we can free
0902              * the old one.
0903              *
0904              * signal_valid can be false, as we are not
0905              * expecting the BSS to be found.
0906              *
0907              * keep the old timestamp to avoid confusion
0908              */
0909             cfg80211_bss_update(rdev, ibss, false,
0910                         ibss->ts);
0911         }
0912 
0913         cfg80211_put_bss(wdev->wiphy, tmp);
0914     }
0915 }
0916 
0917 /* Consumes bss object(s) one way or another */
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, &params->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 /* Consumes bss object one way or another */
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 /* Consumes info->links.bss object(s) one way or another */
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      * Use the wdev event list so that if there are pending
1273      * connected/roamed events, they will be reported first.
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     /* stop critical protocol if supported */
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      * Delete all the keys ... pairwise keys can't really
1315      * exist any more anyway, but default keys might.
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  * API calls for nl80211/wext compatibility code
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      * If we have an ssid_len, we're trying to connect or are
1386      * already connected, so reject a new SSID unless it's the
1387      * same (which is the case for re-association.)
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      * If connected, reject (re-)association unless prev_bssid
1396      * matches the current BSSID.
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      * Reject if we're in the process of connecting with WEP,
1408      * this case isn't very interesting and trying to handle
1409      * it would make the code much more complex.
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         /* If given a WEP key we may need it for shared key auth */
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              * If ciphers are not set (e.g. when going through
1434              * iwconfig), we have to set them appropriately here.
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          * This could be reassoc getting refused, don't clear
1468          * ssid_len in that case.
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      * Clear ssid_len unless we actually were fully connected,
1500      * in which case cfg80211_disconnected() will take care of
1501      * this later.
1502      */
1503     if (!wdev->connected)
1504         wdev->u.client.ssid_len = 0;
1505 
1506     return err;
1507 }
1508 
1509 /*
1510  * Used to clean up after the connection / connection attempt owner socket
1511  * disconnects
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              * Use disconnect_bssid if still connecting and
1537              * ops->disconnect not implemented.  Otherwise we can
1538              * use cfg80211_disconnect.
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 }