cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sme.c (36290B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * SME code for cfg80211
      4 * both driver SME event handling and the SME implementation
      5 * (for nl80211's connect() and wext)
      6 *
      7 * Copyright 2009	Johannes Berg <johannes@sipsolutions.net>
      8 * Copyright (C) 2009, 2020 Intel Corporation. All rights reserved.
      9 * Copyright 2017	Intel Deutschland GmbH
     10 */
     11
     12#include <linux/etherdevice.h>
     13#include <linux/if_arp.h>
     14#include <linux/slab.h>
     15#include <linux/workqueue.h>
     16#include <linux/wireless.h>
     17#include <linux/export.h>
     18#include <net/iw_handler.h>
     19#include <net/cfg80211.h>
     20#include <net/rtnetlink.h>
     21#include "nl80211.h"
     22#include "reg.h"
     23#include "rdev-ops.h"
     24
     25/*
     26 * Software SME in cfg80211, using auth/assoc/deauth calls to the
     27 * driver. This is for implementing nl80211's connect/disconnect
     28 * and wireless extensions (if configured.)
     29 */
     30
     31struct cfg80211_conn {
     32	struct cfg80211_connect_params params;
     33	/* these are sub-states of the _CONNECTING sme_state */
     34	enum {
     35		CFG80211_CONN_SCANNING,
     36		CFG80211_CONN_SCAN_AGAIN,
     37		CFG80211_CONN_AUTHENTICATE_NEXT,
     38		CFG80211_CONN_AUTHENTICATING,
     39		CFG80211_CONN_AUTH_FAILED_TIMEOUT,
     40		CFG80211_CONN_ASSOCIATE_NEXT,
     41		CFG80211_CONN_ASSOCIATING,
     42		CFG80211_CONN_ASSOC_FAILED,
     43		CFG80211_CONN_ASSOC_FAILED_TIMEOUT,
     44		CFG80211_CONN_DEAUTH,
     45		CFG80211_CONN_ABANDON,
     46		CFG80211_CONN_CONNECTED,
     47	} state;
     48	u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
     49	const u8 *ie;
     50	size_t ie_len;
     51	bool auto_auth, prev_bssid_valid;
     52};
     53
     54static void cfg80211_sme_free(struct wireless_dev *wdev)
     55{
     56	if (!wdev->conn)
     57		return;
     58
     59	kfree(wdev->conn->ie);
     60	kfree(wdev->conn);
     61	wdev->conn = NULL;
     62}
     63
     64static int cfg80211_conn_scan(struct wireless_dev *wdev)
     65{
     66	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
     67	struct cfg80211_scan_request *request;
     68	int n_channels, err;
     69
     70	ASSERT_WDEV_LOCK(wdev);
     71
     72	if (rdev->scan_req || rdev->scan_msg)
     73		return -EBUSY;
     74
     75	if (wdev->conn->params.channel)
     76		n_channels = 1;
     77	else
     78		n_channels = ieee80211_get_num_supported_channels(wdev->wiphy);
     79
     80	request = kzalloc(sizeof(*request) + sizeof(request->ssids[0]) +
     81			  sizeof(request->channels[0]) * n_channels,
     82			  GFP_KERNEL);
     83	if (!request)
     84		return -ENOMEM;
     85
     86	if (wdev->conn->params.channel) {
     87		enum nl80211_band band = wdev->conn->params.channel->band;
     88		struct ieee80211_supported_band *sband =
     89			wdev->wiphy->bands[band];
     90
     91		if (!sband) {
     92			kfree(request);
     93			return -EINVAL;
     94		}
     95		request->channels[0] = wdev->conn->params.channel;
     96		request->rates[band] = (1 << sband->n_bitrates) - 1;
     97	} else {
     98		int i = 0, j;
     99		enum nl80211_band band;
    100		struct ieee80211_supported_band *bands;
    101		struct ieee80211_channel *channel;
    102
    103		for (band = 0; band < NUM_NL80211_BANDS; band++) {
    104			bands = wdev->wiphy->bands[band];
    105			if (!bands)
    106				continue;
    107			for (j = 0; j < bands->n_channels; j++) {
    108				channel = &bands->channels[j];
    109				if (channel->flags & IEEE80211_CHAN_DISABLED)
    110					continue;
    111				request->channels[i++] = channel;
    112			}
    113			request->rates[band] = (1 << bands->n_bitrates) - 1;
    114		}
    115		n_channels = i;
    116	}
    117	request->n_channels = n_channels;
    118	request->ssids = (void *)&request->channels[n_channels];
    119	request->n_ssids = 1;
    120
    121	memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,
    122		wdev->conn->params.ssid_len);
    123	request->ssids[0].ssid_len = wdev->conn->params.ssid_len;
    124
    125	eth_broadcast_addr(request->bssid);
    126
    127	request->wdev = wdev;
    128	request->wiphy = &rdev->wiphy;
    129	request->scan_start = jiffies;
    130
    131	rdev->scan_req = request;
    132
    133	err = rdev_scan(rdev, request);
    134	if (!err) {
    135		wdev->conn->state = CFG80211_CONN_SCANNING;
    136		nl80211_send_scan_start(rdev, wdev);
    137		dev_hold(wdev->netdev);
    138	} else {
    139		rdev->scan_req = NULL;
    140		kfree(request);
    141	}
    142	return err;
    143}
    144
    145static int cfg80211_conn_do_work(struct wireless_dev *wdev,
    146				 enum nl80211_timeout_reason *treason)
    147{
    148	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    149	struct cfg80211_connect_params *params;
    150	struct cfg80211_assoc_request req = {};
    151	int err;
    152
    153	ASSERT_WDEV_LOCK(wdev);
    154
    155	if (!wdev->conn)
    156		return 0;
    157
    158	params = &wdev->conn->params;
    159
    160	switch (wdev->conn->state) {
    161	case CFG80211_CONN_SCANNING:
    162		/* didn't find it during scan ... */
    163		return -ENOENT;
    164	case CFG80211_CONN_SCAN_AGAIN:
    165		return cfg80211_conn_scan(wdev);
    166	case CFG80211_CONN_AUTHENTICATE_NEXT:
    167		if (WARN_ON(!rdev->ops->auth))
    168			return -EOPNOTSUPP;
    169		wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
    170		return cfg80211_mlme_auth(rdev, wdev->netdev,
    171					  params->channel, params->auth_type,
    172					  params->bssid,
    173					  params->ssid, params->ssid_len,
    174					  NULL, 0,
    175					  params->key, params->key_len,
    176					  params->key_idx, NULL, 0);
    177	case CFG80211_CONN_AUTH_FAILED_TIMEOUT:
    178		*treason = NL80211_TIMEOUT_AUTH;
    179		return -ENOTCONN;
    180	case CFG80211_CONN_ASSOCIATE_NEXT:
    181		if (WARN_ON(!rdev->ops->assoc))
    182			return -EOPNOTSUPP;
    183		wdev->conn->state = CFG80211_CONN_ASSOCIATING;
    184		if (wdev->conn->prev_bssid_valid)
    185			req.prev_bssid = wdev->conn->prev_bssid;
    186		req.ie = params->ie;
    187		req.ie_len = params->ie_len;
    188		req.use_mfp = params->mfp != NL80211_MFP_NO;
    189		req.crypto = params->crypto;
    190		req.flags = params->flags;
    191		req.ht_capa = params->ht_capa;
    192		req.ht_capa_mask = params->ht_capa_mask;
    193		req.vht_capa = params->vht_capa;
    194		req.vht_capa_mask = params->vht_capa_mask;
    195
    196		err = cfg80211_mlme_assoc(rdev, wdev->netdev, params->channel,
    197					  params->bssid, params->ssid,
    198					  params->ssid_len, &req);
    199		if (err)
    200			cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
    201					     NULL, 0,
    202					     WLAN_REASON_DEAUTH_LEAVING,
    203					     false);
    204		return err;
    205	case CFG80211_CONN_ASSOC_FAILED_TIMEOUT:
    206		*treason = NL80211_TIMEOUT_ASSOC;
    207		fallthrough;
    208	case CFG80211_CONN_ASSOC_FAILED:
    209		cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
    210				     NULL, 0,
    211				     WLAN_REASON_DEAUTH_LEAVING, false);
    212		return -ENOTCONN;
    213	case CFG80211_CONN_DEAUTH:
    214		cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
    215				     NULL, 0,
    216				     WLAN_REASON_DEAUTH_LEAVING, false);
    217		fallthrough;
    218	case CFG80211_CONN_ABANDON:
    219		/* free directly, disconnected event already sent */
    220		cfg80211_sme_free(wdev);
    221		return 0;
    222	default:
    223		return 0;
    224	}
    225}
    226
    227void cfg80211_conn_work(struct work_struct *work)
    228{
    229	struct cfg80211_registered_device *rdev =
    230		container_of(work, struct cfg80211_registered_device, conn_work);
    231	struct wireless_dev *wdev;
    232	u8 bssid_buf[ETH_ALEN], *bssid = NULL;
    233	enum nl80211_timeout_reason treason;
    234
    235	wiphy_lock(&rdev->wiphy);
    236
    237	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
    238		if (!wdev->netdev)
    239			continue;
    240
    241		wdev_lock(wdev);
    242		if (!netif_running(wdev->netdev)) {
    243			wdev_unlock(wdev);
    244			continue;
    245		}
    246		if (!wdev->conn ||
    247		    wdev->conn->state == CFG80211_CONN_CONNECTED) {
    248			wdev_unlock(wdev);
    249			continue;
    250		}
    251		if (wdev->conn->params.bssid) {
    252			memcpy(bssid_buf, wdev->conn->params.bssid, ETH_ALEN);
    253			bssid = bssid_buf;
    254		}
    255		treason = NL80211_TIMEOUT_UNSPECIFIED;
    256		if (cfg80211_conn_do_work(wdev, &treason)) {
    257			struct cfg80211_connect_resp_params cr;
    258
    259			memset(&cr, 0, sizeof(cr));
    260			cr.status = -1;
    261			cr.bssid = bssid;
    262			cr.timeout_reason = treason;
    263			__cfg80211_connect_result(wdev->netdev, &cr, false);
    264		}
    265		wdev_unlock(wdev);
    266	}
    267
    268	wiphy_unlock(&rdev->wiphy);
    269}
    270
    271/* Returned bss is reference counted and must be cleaned up appropriately. */
    272static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev)
    273{
    274	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    275	struct cfg80211_bss *bss;
    276
    277	ASSERT_WDEV_LOCK(wdev);
    278
    279	bss = cfg80211_get_bss(wdev->wiphy, wdev->conn->params.channel,
    280			       wdev->conn->params.bssid,
    281			       wdev->conn->params.ssid,
    282			       wdev->conn->params.ssid_len,
    283			       wdev->conn_bss_type,
    284			       IEEE80211_PRIVACY(wdev->conn->params.privacy));
    285	if (!bss)
    286		return NULL;
    287
    288	memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN);
    289	wdev->conn->params.bssid = wdev->conn->bssid;
    290	wdev->conn->params.channel = bss->channel;
    291	wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
    292	schedule_work(&rdev->conn_work);
    293
    294	return bss;
    295}
    296
    297static void __cfg80211_sme_scan_done(struct net_device *dev)
    298{
    299	struct wireless_dev *wdev = dev->ieee80211_ptr;
    300	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    301	struct cfg80211_bss *bss;
    302
    303	ASSERT_WDEV_LOCK(wdev);
    304
    305	if (!wdev->conn)
    306		return;
    307
    308	if (wdev->conn->state != CFG80211_CONN_SCANNING &&
    309	    wdev->conn->state != CFG80211_CONN_SCAN_AGAIN)
    310		return;
    311
    312	bss = cfg80211_get_conn_bss(wdev);
    313	if (bss)
    314		cfg80211_put_bss(&rdev->wiphy, bss);
    315	else
    316		schedule_work(&rdev->conn_work);
    317}
    318
    319void cfg80211_sme_scan_done(struct net_device *dev)
    320{
    321	struct wireless_dev *wdev = dev->ieee80211_ptr;
    322
    323	wdev_lock(wdev);
    324	__cfg80211_sme_scan_done(dev);
    325	wdev_unlock(wdev);
    326}
    327
    328void cfg80211_sme_rx_auth(struct wireless_dev *wdev, const u8 *buf, size_t len)
    329{
    330	struct wiphy *wiphy = wdev->wiphy;
    331	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
    332	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
    333	u16 status_code = le16_to_cpu(mgmt->u.auth.status_code);
    334
    335	ASSERT_WDEV_LOCK(wdev);
    336
    337	if (!wdev->conn || wdev->conn->state == CFG80211_CONN_CONNECTED)
    338		return;
    339
    340	if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
    341	    wdev->conn->auto_auth &&
    342	    wdev->conn->params.auth_type != NL80211_AUTHTYPE_NETWORK_EAP) {
    343		/* select automatically between only open, shared, leap */
    344		switch (wdev->conn->params.auth_type) {
    345		case NL80211_AUTHTYPE_OPEN_SYSTEM:
    346			if (wdev->connect_keys)
    347				wdev->conn->params.auth_type =
    348					NL80211_AUTHTYPE_SHARED_KEY;
    349			else
    350				wdev->conn->params.auth_type =
    351					NL80211_AUTHTYPE_NETWORK_EAP;
    352			break;
    353		case NL80211_AUTHTYPE_SHARED_KEY:
    354			wdev->conn->params.auth_type =
    355				NL80211_AUTHTYPE_NETWORK_EAP;
    356			break;
    357		default:
    358			/* huh? */
    359			wdev->conn->params.auth_type =
    360				NL80211_AUTHTYPE_OPEN_SYSTEM;
    361			break;
    362		}
    363		wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
    364		schedule_work(&rdev->conn_work);
    365	} else if (status_code != WLAN_STATUS_SUCCESS) {
    366		struct cfg80211_connect_resp_params cr;
    367
    368		memset(&cr, 0, sizeof(cr));
    369		cr.status = status_code;
    370		cr.bssid = mgmt->bssid;
    371		cr.timeout_reason = NL80211_TIMEOUT_UNSPECIFIED;
    372		__cfg80211_connect_result(wdev->netdev, &cr, false);
    373	} else if (wdev->conn->state == CFG80211_CONN_AUTHENTICATING) {
    374		wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
    375		schedule_work(&rdev->conn_work);
    376	}
    377}
    378
    379bool cfg80211_sme_rx_assoc_resp(struct wireless_dev *wdev, u16 status)
    380{
    381	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    382
    383	if (!wdev->conn)
    384		return false;
    385
    386	if (status == WLAN_STATUS_SUCCESS) {
    387		wdev->conn->state = CFG80211_CONN_CONNECTED;
    388		return false;
    389	}
    390
    391	if (wdev->conn->prev_bssid_valid) {
    392		/*
    393		 * Some stupid APs don't accept reassoc, so we
    394		 * need to fall back to trying regular assoc;
    395		 * return true so no event is sent to userspace.
    396		 */
    397		wdev->conn->prev_bssid_valid = false;
    398		wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
    399		schedule_work(&rdev->conn_work);
    400		return true;
    401	}
    402
    403	wdev->conn->state = CFG80211_CONN_ASSOC_FAILED;
    404	schedule_work(&rdev->conn_work);
    405	return false;
    406}
    407
    408void cfg80211_sme_deauth(struct wireless_dev *wdev)
    409{
    410	cfg80211_sme_free(wdev);
    411}
    412
    413void cfg80211_sme_auth_timeout(struct wireless_dev *wdev)
    414{
    415	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    416
    417	if (!wdev->conn)
    418		return;
    419
    420	wdev->conn->state = CFG80211_CONN_AUTH_FAILED_TIMEOUT;
    421	schedule_work(&rdev->conn_work);
    422}
    423
    424void cfg80211_sme_disassoc(struct wireless_dev *wdev)
    425{
    426	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    427
    428	if (!wdev->conn)
    429		return;
    430
    431	wdev->conn->state = CFG80211_CONN_DEAUTH;
    432	schedule_work(&rdev->conn_work);
    433}
    434
    435void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
    436{
    437	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    438
    439	if (!wdev->conn)
    440		return;
    441
    442	wdev->conn->state = CFG80211_CONN_ASSOC_FAILED_TIMEOUT;
    443	schedule_work(&rdev->conn_work);
    444}
    445
    446void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev)
    447{
    448	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    449
    450	if (!wdev->conn)
    451		return;
    452
    453	wdev->conn->state = CFG80211_CONN_ABANDON;
    454	schedule_work(&rdev->conn_work);
    455}
    456
    457static int cfg80211_sme_get_conn_ies(struct wireless_dev *wdev,
    458				     const u8 *ies, size_t ies_len,
    459				     const u8 **out_ies, size_t *out_ies_len)
    460{
    461	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    462	u8 *buf;
    463	size_t offs;
    464
    465	if (!rdev->wiphy.extended_capabilities_len ||
    466	    (ies && cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, ies, ies_len))) {
    467		*out_ies = kmemdup(ies, ies_len, GFP_KERNEL);
    468		if (!*out_ies)
    469			return -ENOMEM;
    470		*out_ies_len = ies_len;
    471		return 0;
    472	}
    473
    474	buf = kmalloc(ies_len + rdev->wiphy.extended_capabilities_len + 2,
    475		      GFP_KERNEL);
    476	if (!buf)
    477		return -ENOMEM;
    478
    479	if (ies_len) {
    480		static const u8 before_extcapa[] = {
    481			/* not listing IEs expected to be created by driver */
    482			WLAN_EID_RSN,
    483			WLAN_EID_QOS_CAPA,
    484			WLAN_EID_RRM_ENABLED_CAPABILITIES,
    485			WLAN_EID_MOBILITY_DOMAIN,
    486			WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
    487			WLAN_EID_BSS_COEX_2040,
    488		};
    489
    490		offs = ieee80211_ie_split(ies, ies_len, before_extcapa,
    491					  ARRAY_SIZE(before_extcapa), 0);
    492		memcpy(buf, ies, offs);
    493		/* leave a whole for extended capabilities IE */
    494		memcpy(buf + offs + rdev->wiphy.extended_capabilities_len + 2,
    495		       ies + offs, ies_len - offs);
    496	} else {
    497		offs = 0;
    498	}
    499
    500	/* place extended capabilities IE (with only driver capabilities) */
    501	buf[offs] = WLAN_EID_EXT_CAPABILITY;
    502	buf[offs + 1] = rdev->wiphy.extended_capabilities_len;
    503	memcpy(buf + offs + 2,
    504	       rdev->wiphy.extended_capabilities,
    505	       rdev->wiphy.extended_capabilities_len);
    506
    507	*out_ies = buf;
    508	*out_ies_len = ies_len + rdev->wiphy.extended_capabilities_len + 2;
    509
    510	return 0;
    511}
    512
    513static int cfg80211_sme_connect(struct wireless_dev *wdev,
    514				struct cfg80211_connect_params *connect,
    515				const u8 *prev_bssid)
    516{
    517	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    518	struct cfg80211_bss *bss;
    519	int err;
    520
    521	if (!rdev->ops->auth || !rdev->ops->assoc)
    522		return -EOPNOTSUPP;
    523
    524	if (wdev->current_bss) {
    525		cfg80211_unhold_bss(wdev->current_bss);
    526		cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
    527		wdev->current_bss = NULL;
    528
    529		cfg80211_sme_free(wdev);
    530	}
    531
    532	if (wdev->conn)
    533		return -EINPROGRESS;
    534
    535	wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL);
    536	if (!wdev->conn)
    537		return -ENOMEM;
    538
    539	/*
    540	 * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
    541	 */
    542	memcpy(&wdev->conn->params, connect, sizeof(*connect));
    543	if (connect->bssid) {
    544		wdev->conn->params.bssid = wdev->conn->bssid;
    545		memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
    546	}
    547
    548	if (cfg80211_sme_get_conn_ies(wdev, connect->ie, connect->ie_len,
    549				      &wdev->conn->ie,
    550				      &wdev->conn->params.ie_len)) {
    551		kfree(wdev->conn);
    552		wdev->conn = NULL;
    553		return -ENOMEM;
    554	}
    555	wdev->conn->params.ie = wdev->conn->ie;
    556
    557	if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
    558		wdev->conn->auto_auth = true;
    559		/* start with open system ... should mostly work */
    560		wdev->conn->params.auth_type =
    561			NL80211_AUTHTYPE_OPEN_SYSTEM;
    562	} else {
    563		wdev->conn->auto_auth = false;
    564	}
    565
    566	wdev->conn->params.ssid = wdev->ssid;
    567	wdev->conn->params.ssid_len = wdev->ssid_len;
    568
    569	/* see if we have the bss already */
    570	bss = cfg80211_get_conn_bss(wdev);
    571
    572	if (prev_bssid) {
    573		memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN);
    574		wdev->conn->prev_bssid_valid = true;
    575	}
    576
    577	/* we're good if we have a matching bss struct */
    578	if (bss) {
    579		enum nl80211_timeout_reason treason;
    580
    581		err = cfg80211_conn_do_work(wdev, &treason);
    582		cfg80211_put_bss(wdev->wiphy, bss);
    583	} else {
    584		/* otherwise we'll need to scan for the AP first */
    585		err = cfg80211_conn_scan(wdev);
    586
    587		/*
    588		 * If we can't scan right now, then we need to scan again
    589		 * after the current scan finished, since the parameters
    590		 * changed (unless we find a good AP anyway).
    591		 */
    592		if (err == -EBUSY) {
    593			err = 0;
    594			wdev->conn->state = CFG80211_CONN_SCAN_AGAIN;
    595		}
    596	}
    597
    598	if (err)
    599		cfg80211_sme_free(wdev);
    600
    601	return err;
    602}
    603
    604static int cfg80211_sme_disconnect(struct wireless_dev *wdev, u16 reason)
    605{
    606	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    607	int err;
    608
    609	if (!wdev->conn)
    610		return 0;
    611
    612	if (!rdev->ops->deauth)
    613		return -EOPNOTSUPP;
    614
    615	if (wdev->conn->state == CFG80211_CONN_SCANNING ||
    616	    wdev->conn->state == CFG80211_CONN_SCAN_AGAIN) {
    617		err = 0;
    618		goto out;
    619	}
    620
    621	/* wdev->conn->params.bssid must be set if > SCANNING */
    622	err = cfg80211_mlme_deauth(rdev, wdev->netdev,
    623				   wdev->conn->params.bssid,
    624				   NULL, 0, reason, false);
    625 out:
    626	cfg80211_sme_free(wdev);
    627	return err;
    628}
    629
    630/*
    631 * code shared for in-device and software SME
    632 */
    633
    634static bool cfg80211_is_all_idle(void)
    635{
    636	struct cfg80211_registered_device *rdev;
    637	struct wireless_dev *wdev;
    638	bool is_all_idle = true;
    639
    640	/*
    641	 * All devices must be idle as otherwise if you are actively
    642	 * scanning some new beacon hints could be learned and would
    643	 * count as new regulatory hints.
    644	 * Also if there is any other active beaconing interface we
    645	 * need not issue a disconnect hint and reset any info such
    646	 * as chan dfs state, etc.
    647	 */
    648	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
    649		list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
    650			wdev_lock(wdev);
    651			if (wdev->conn || wdev->current_bss ||
    652			    cfg80211_beaconing_iface_active(wdev))
    653				is_all_idle = false;
    654			wdev_unlock(wdev);
    655		}
    656	}
    657
    658	return is_all_idle;
    659}
    660
    661static void disconnect_work(struct work_struct *work)
    662{
    663	rtnl_lock();
    664	if (cfg80211_is_all_idle())
    665		regulatory_hint_disconnect();
    666	rtnl_unlock();
    667}
    668
    669DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
    670
    671
    672/*
    673 * API calls for drivers implementing connect/disconnect and
    674 * SME event handling
    675 */
    676
    677/* This method must consume bss one way or another */
    678void __cfg80211_connect_result(struct net_device *dev,
    679			       struct cfg80211_connect_resp_params *cr,
    680			       bool wextev)
    681{
    682	struct wireless_dev *wdev = dev->ieee80211_ptr;
    683	const struct element *country_elem;
    684	const u8 *country_data;
    685	u8 country_datalen;
    686#ifdef CONFIG_CFG80211_WEXT
    687	union iwreq_data wrqu;
    688#endif
    689
    690	ASSERT_WDEV_LOCK(wdev);
    691
    692	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
    693		    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) {
    694		cfg80211_put_bss(wdev->wiphy, cr->bss);
    695		return;
    696	}
    697
    698	wdev->unprot_beacon_reported = 0;
    699	nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev, cr,
    700				    GFP_KERNEL);
    701
    702#ifdef CONFIG_CFG80211_WEXT
    703	if (wextev) {
    704		if (cr->req_ie && cr->status == WLAN_STATUS_SUCCESS) {
    705			memset(&wrqu, 0, sizeof(wrqu));
    706			wrqu.data.length = cr->req_ie_len;
    707			wireless_send_event(dev, IWEVASSOCREQIE, &wrqu,
    708					    cr->req_ie);
    709		}
    710
    711		if (cr->resp_ie && cr->status == WLAN_STATUS_SUCCESS) {
    712			memset(&wrqu, 0, sizeof(wrqu));
    713			wrqu.data.length = cr->resp_ie_len;
    714			wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu,
    715					    cr->resp_ie);
    716		}
    717
    718		memset(&wrqu, 0, sizeof(wrqu));
    719		wrqu.ap_addr.sa_family = ARPHRD_ETHER;
    720		if (cr->bssid && cr->status == WLAN_STATUS_SUCCESS) {
    721			memcpy(wrqu.ap_addr.sa_data, cr->bssid, ETH_ALEN);
    722			memcpy(wdev->wext.prev_bssid, cr->bssid, ETH_ALEN);
    723			wdev->wext.prev_bssid_valid = true;
    724		}
    725		wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
    726	}
    727#endif
    728
    729	if (!cr->bss && (cr->status == WLAN_STATUS_SUCCESS)) {
    730		WARN_ON_ONCE(!wiphy_to_rdev(wdev->wiphy)->ops->connect);
    731		cr->bss = cfg80211_get_bss(wdev->wiphy, NULL, cr->bssid,
    732					   wdev->ssid, wdev->ssid_len,
    733					   wdev->conn_bss_type,
    734					   IEEE80211_PRIVACY_ANY);
    735		if (cr->bss)
    736			cfg80211_hold_bss(bss_from_pub(cr->bss));
    737	}
    738
    739	if (wdev->current_bss) {
    740		cfg80211_unhold_bss(wdev->current_bss);
    741		cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
    742		wdev->current_bss = NULL;
    743	}
    744
    745	if (cr->status != WLAN_STATUS_SUCCESS) {
    746		kfree_sensitive(wdev->connect_keys);
    747		wdev->connect_keys = NULL;
    748		wdev->ssid_len = 0;
    749		wdev->conn_owner_nlportid = 0;
    750		if (cr->bss) {
    751			cfg80211_unhold_bss(bss_from_pub(cr->bss));
    752			cfg80211_put_bss(wdev->wiphy, cr->bss);
    753		}
    754		cfg80211_sme_free(wdev);
    755		return;
    756	}
    757
    758	if (WARN_ON(!cr->bss))
    759		return;
    760
    761	wdev->current_bss = bss_from_pub(cr->bss);
    762
    763	if (!(wdev->wiphy->flags & WIPHY_FLAG_HAS_STATIC_WEP))
    764		cfg80211_upload_connect_keys(wdev);
    765
    766	rcu_read_lock();
    767	country_elem = ieee80211_bss_get_elem(cr->bss, WLAN_EID_COUNTRY);
    768	if (!country_elem) {
    769		rcu_read_unlock();
    770		return;
    771	}
    772
    773	country_datalen = country_elem->datalen;
    774	country_data = kmemdup(country_elem->data, country_datalen, GFP_ATOMIC);
    775	rcu_read_unlock();
    776
    777	if (!country_data)
    778		return;
    779
    780	regulatory_hint_country_ie(wdev->wiphy, cr->bss->channel->band,
    781				   country_data, country_datalen);
    782	kfree(country_data);
    783}
    784
    785/* Consumes bss object one way or another */
    786void cfg80211_connect_done(struct net_device *dev,
    787			   struct cfg80211_connect_resp_params *params,
    788			   gfp_t gfp)
    789{
    790	struct wireless_dev *wdev = dev->ieee80211_ptr;
    791	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    792	struct cfg80211_event *ev;
    793	unsigned long flags;
    794	u8 *next;
    795
    796	if (params->bss) {
    797		struct cfg80211_internal_bss *ibss = bss_from_pub(params->bss);
    798
    799		if (list_empty(&ibss->list)) {
    800			struct cfg80211_bss *found = NULL, *tmp = params->bss;
    801
    802			found = cfg80211_get_bss(wdev->wiphy, NULL,
    803						 params->bss->bssid,
    804						 wdev->ssid, wdev->ssid_len,
    805						 wdev->conn_bss_type,
    806						 IEEE80211_PRIVACY_ANY);
    807			if (found) {
    808				/* The same BSS is already updated so use it
    809				 * instead, as it has latest info.
    810				 */
    811				params->bss = found;
    812			} else {
    813				/* Update with BSS provided by driver, it will
    814				 * be freshly added and ref cnted, we can free
    815				 * the old one.
    816				 *
    817				 * signal_valid can be false, as we are not
    818				 * expecting the BSS to be found.
    819				 *
    820				 * keep the old timestamp to avoid confusion
    821				 */
    822				cfg80211_bss_update(rdev, ibss, false,
    823						    ibss->ts);
    824			}
    825
    826			cfg80211_put_bss(wdev->wiphy, tmp);
    827		}
    828	}
    829
    830	ev = kzalloc(sizeof(*ev) + (params->bssid ? ETH_ALEN : 0) +
    831		     params->req_ie_len + params->resp_ie_len +
    832		     params->fils.kek_len + params->fils.pmk_len +
    833		     (params->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
    834	if (!ev) {
    835		cfg80211_put_bss(wdev->wiphy, params->bss);
    836		return;
    837	}
    838
    839	ev->type = EVENT_CONNECT_RESULT;
    840	next = ((u8 *)ev) + sizeof(*ev);
    841	if (params->bssid) {
    842		ev->cr.bssid = next;
    843		memcpy((void *)ev->cr.bssid, params->bssid, ETH_ALEN);
    844		next += ETH_ALEN;
    845	}
    846	if (params->req_ie_len) {
    847		ev->cr.req_ie = next;
    848		ev->cr.req_ie_len = params->req_ie_len;
    849		memcpy((void *)ev->cr.req_ie, params->req_ie,
    850		       params->req_ie_len);
    851		next += params->req_ie_len;
    852	}
    853	if (params->resp_ie_len) {
    854		ev->cr.resp_ie = next;
    855		ev->cr.resp_ie_len = params->resp_ie_len;
    856		memcpy((void *)ev->cr.resp_ie, params->resp_ie,
    857		       params->resp_ie_len);
    858		next += params->resp_ie_len;
    859	}
    860	if (params->fils.kek_len) {
    861		ev->cr.fils.kek = next;
    862		ev->cr.fils.kek_len = params->fils.kek_len;
    863		memcpy((void *)ev->cr.fils.kek, params->fils.kek,
    864		       params->fils.kek_len);
    865		next += params->fils.kek_len;
    866	}
    867	if (params->fils.pmk_len) {
    868		ev->cr.fils.pmk = next;
    869		ev->cr.fils.pmk_len = params->fils.pmk_len;
    870		memcpy((void *)ev->cr.fils.pmk, params->fils.pmk,
    871		       params->fils.pmk_len);
    872		next += params->fils.pmk_len;
    873	}
    874	if (params->fils.pmkid) {
    875		ev->cr.fils.pmkid = next;
    876		memcpy((void *)ev->cr.fils.pmkid, params->fils.pmkid,
    877		       WLAN_PMKID_LEN);
    878		next += WLAN_PMKID_LEN;
    879	}
    880	ev->cr.fils.update_erp_next_seq_num = params->fils.update_erp_next_seq_num;
    881	if (params->fils.update_erp_next_seq_num)
    882		ev->cr.fils.erp_next_seq_num = params->fils.erp_next_seq_num;
    883	if (params->bss)
    884		cfg80211_hold_bss(bss_from_pub(params->bss));
    885	ev->cr.bss = params->bss;
    886	ev->cr.status = params->status;
    887	ev->cr.timeout_reason = params->timeout_reason;
    888
    889	spin_lock_irqsave(&wdev->event_lock, flags);
    890	list_add_tail(&ev->list, &wdev->event_list);
    891	spin_unlock_irqrestore(&wdev->event_lock, flags);
    892	queue_work(cfg80211_wq, &rdev->event_work);
    893}
    894EXPORT_SYMBOL(cfg80211_connect_done);
    895
    896/* Consumes bss object one way or another */
    897void __cfg80211_roamed(struct wireless_dev *wdev,
    898		       struct cfg80211_roam_info *info)
    899{
    900#ifdef CONFIG_CFG80211_WEXT
    901	union iwreq_data wrqu;
    902#endif
    903	ASSERT_WDEV_LOCK(wdev);
    904
    905	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
    906		    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
    907		goto out;
    908
    909	if (WARN_ON(!wdev->current_bss))
    910		goto out;
    911
    912	cfg80211_unhold_bss(wdev->current_bss);
    913	cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
    914	wdev->current_bss = NULL;
    915
    916	if (WARN_ON(!info->bss))
    917		return;
    918
    919	cfg80211_hold_bss(bss_from_pub(info->bss));
    920	wdev->current_bss = bss_from_pub(info->bss);
    921
    922	wdev->unprot_beacon_reported = 0;
    923	nl80211_send_roamed(wiphy_to_rdev(wdev->wiphy),
    924			    wdev->netdev, info, GFP_KERNEL);
    925
    926#ifdef CONFIG_CFG80211_WEXT
    927	if (info->req_ie) {
    928		memset(&wrqu, 0, sizeof(wrqu));
    929		wrqu.data.length = info->req_ie_len;
    930		wireless_send_event(wdev->netdev, IWEVASSOCREQIE,
    931				    &wrqu, info->req_ie);
    932	}
    933
    934	if (info->resp_ie) {
    935		memset(&wrqu, 0, sizeof(wrqu));
    936		wrqu.data.length = info->resp_ie_len;
    937		wireless_send_event(wdev->netdev, IWEVASSOCRESPIE,
    938				    &wrqu, info->resp_ie);
    939	}
    940
    941	memset(&wrqu, 0, sizeof(wrqu));
    942	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
    943	memcpy(wrqu.ap_addr.sa_data, info->bss->bssid, ETH_ALEN);
    944	memcpy(wdev->wext.prev_bssid, info->bss->bssid, ETH_ALEN);
    945	wdev->wext.prev_bssid_valid = true;
    946	wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL);
    947#endif
    948
    949	return;
    950out:
    951	cfg80211_put_bss(wdev->wiphy, info->bss);
    952}
    953
    954/* Consumes info->bss object one way or another */
    955void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info,
    956		     gfp_t gfp)
    957{
    958	struct wireless_dev *wdev = dev->ieee80211_ptr;
    959	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    960	struct cfg80211_event *ev;
    961	unsigned long flags;
    962	u8 *next;
    963
    964	if (!info->bss) {
    965		info->bss = cfg80211_get_bss(wdev->wiphy, info->channel,
    966					     info->bssid, wdev->ssid,
    967					     wdev->ssid_len,
    968					     wdev->conn_bss_type,
    969					     IEEE80211_PRIVACY_ANY);
    970	}
    971
    972	if (WARN_ON(!info->bss))
    973		return;
    974
    975	ev = kzalloc(sizeof(*ev) + info->req_ie_len + info->resp_ie_len +
    976		     info->fils.kek_len + info->fils.pmk_len +
    977		     (info->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
    978	if (!ev) {
    979		cfg80211_put_bss(wdev->wiphy, info->bss);
    980		return;
    981	}
    982
    983	ev->type = EVENT_ROAMED;
    984	next = ((u8 *)ev) + sizeof(*ev);
    985	if (info->req_ie_len) {
    986		ev->rm.req_ie = next;
    987		ev->rm.req_ie_len = info->req_ie_len;
    988		memcpy((void *)ev->rm.req_ie, info->req_ie, info->req_ie_len);
    989		next += info->req_ie_len;
    990	}
    991	if (info->resp_ie_len) {
    992		ev->rm.resp_ie = next;
    993		ev->rm.resp_ie_len = info->resp_ie_len;
    994		memcpy((void *)ev->rm.resp_ie, info->resp_ie,
    995		       info->resp_ie_len);
    996		next += info->resp_ie_len;
    997	}
    998	if (info->fils.kek_len) {
    999		ev->rm.fils.kek = next;
   1000		ev->rm.fils.kek_len = info->fils.kek_len;
   1001		memcpy((void *)ev->rm.fils.kek, info->fils.kek,
   1002		       info->fils.kek_len);
   1003		next += info->fils.kek_len;
   1004	}
   1005	if (info->fils.pmk_len) {
   1006		ev->rm.fils.pmk = next;
   1007		ev->rm.fils.pmk_len = info->fils.pmk_len;
   1008		memcpy((void *)ev->rm.fils.pmk, info->fils.pmk,
   1009		       info->fils.pmk_len);
   1010		next += info->fils.pmk_len;
   1011	}
   1012	if (info->fils.pmkid) {
   1013		ev->rm.fils.pmkid = next;
   1014		memcpy((void *)ev->rm.fils.pmkid, info->fils.pmkid,
   1015		       WLAN_PMKID_LEN);
   1016		next += WLAN_PMKID_LEN;
   1017	}
   1018	ev->rm.fils.update_erp_next_seq_num = info->fils.update_erp_next_seq_num;
   1019	if (info->fils.update_erp_next_seq_num)
   1020		ev->rm.fils.erp_next_seq_num = info->fils.erp_next_seq_num;
   1021	ev->rm.bss = info->bss;
   1022
   1023	spin_lock_irqsave(&wdev->event_lock, flags);
   1024	list_add_tail(&ev->list, &wdev->event_list);
   1025	spin_unlock_irqrestore(&wdev->event_lock, flags);
   1026	queue_work(cfg80211_wq, &rdev->event_work);
   1027}
   1028EXPORT_SYMBOL(cfg80211_roamed);
   1029
   1030void __cfg80211_port_authorized(struct wireless_dev *wdev, const u8 *bssid)
   1031{
   1032	ASSERT_WDEV_LOCK(wdev);
   1033
   1034	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
   1035		return;
   1036
   1037	if (WARN_ON(!wdev->current_bss) ||
   1038	    WARN_ON(!ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
   1039		return;
   1040
   1041	nl80211_send_port_authorized(wiphy_to_rdev(wdev->wiphy), wdev->netdev,
   1042				     bssid);
   1043}
   1044
   1045void cfg80211_port_authorized(struct net_device *dev, const u8 *bssid,
   1046			      gfp_t gfp)
   1047{
   1048	struct wireless_dev *wdev = dev->ieee80211_ptr;
   1049	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
   1050	struct cfg80211_event *ev;
   1051	unsigned long flags;
   1052
   1053	if (WARN_ON(!bssid))
   1054		return;
   1055
   1056	ev = kzalloc(sizeof(*ev), gfp);
   1057	if (!ev)
   1058		return;
   1059
   1060	ev->type = EVENT_PORT_AUTHORIZED;
   1061	memcpy(ev->pa.bssid, bssid, ETH_ALEN);
   1062
   1063	/*
   1064	 * Use the wdev event list so that if there are pending
   1065	 * connected/roamed events, they will be reported first.
   1066	 */
   1067	spin_lock_irqsave(&wdev->event_lock, flags);
   1068	list_add_tail(&ev->list, &wdev->event_list);
   1069	spin_unlock_irqrestore(&wdev->event_lock, flags);
   1070	queue_work(cfg80211_wq, &rdev->event_work);
   1071}
   1072EXPORT_SYMBOL(cfg80211_port_authorized);
   1073
   1074void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
   1075			     size_t ie_len, u16 reason, bool from_ap)
   1076{
   1077	struct wireless_dev *wdev = dev->ieee80211_ptr;
   1078	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
   1079	int i;
   1080#ifdef CONFIG_CFG80211_WEXT
   1081	union iwreq_data wrqu;
   1082#endif
   1083
   1084	ASSERT_WDEV_LOCK(wdev);
   1085
   1086	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
   1087		    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
   1088		return;
   1089
   1090	if (wdev->current_bss) {
   1091		cfg80211_unhold_bss(wdev->current_bss);
   1092		cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
   1093	}
   1094
   1095	wdev->current_bss = NULL;
   1096	wdev->ssid_len = 0;
   1097	wdev->conn_owner_nlportid = 0;
   1098	kfree_sensitive(wdev->connect_keys);
   1099	wdev->connect_keys = NULL;
   1100
   1101	nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
   1102
   1103	/* stop critical protocol if supported */
   1104	if (rdev->ops->crit_proto_stop && rdev->crit_proto_nlportid) {
   1105		rdev->crit_proto_nlportid = 0;
   1106		rdev_crit_proto_stop(rdev, wdev);
   1107	}
   1108
   1109	/*
   1110	 * Delete all the keys ... pairwise keys can't really
   1111	 * exist any more anyway, but default keys might.
   1112	 */
   1113	if (rdev->ops->del_key) {
   1114		int max_key_idx = 5;
   1115
   1116		if (wiphy_ext_feature_isset(
   1117			    wdev->wiphy,
   1118			    NL80211_EXT_FEATURE_BEACON_PROTECTION) ||
   1119		    wiphy_ext_feature_isset(
   1120			    wdev->wiphy,
   1121			    NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
   1122			max_key_idx = 7;
   1123		for (i = 0; i <= max_key_idx; i++)
   1124			rdev_del_key(rdev, dev, i, false, NULL);
   1125	}
   1126
   1127	rdev_set_qos_map(rdev, dev, NULL);
   1128
   1129#ifdef CONFIG_CFG80211_WEXT
   1130	memset(&wrqu, 0, sizeof(wrqu));
   1131	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
   1132	wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
   1133	wdev->wext.connect.ssid_len = 0;
   1134#endif
   1135
   1136	schedule_work(&cfg80211_disconnect_work);
   1137}
   1138
   1139void cfg80211_disconnected(struct net_device *dev, u16 reason,
   1140			   const u8 *ie, size_t ie_len,
   1141			   bool locally_generated, gfp_t gfp)
   1142{
   1143	struct wireless_dev *wdev = dev->ieee80211_ptr;
   1144	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
   1145	struct cfg80211_event *ev;
   1146	unsigned long flags;
   1147
   1148	ev = kzalloc(sizeof(*ev) + ie_len, gfp);
   1149	if (!ev)
   1150		return;
   1151
   1152	ev->type = EVENT_DISCONNECTED;
   1153	ev->dc.ie = ((u8 *)ev) + sizeof(*ev);
   1154	ev->dc.ie_len = ie_len;
   1155	memcpy((void *)ev->dc.ie, ie, ie_len);
   1156	ev->dc.reason = reason;
   1157	ev->dc.locally_generated = locally_generated;
   1158
   1159	spin_lock_irqsave(&wdev->event_lock, flags);
   1160	list_add_tail(&ev->list, &wdev->event_list);
   1161	spin_unlock_irqrestore(&wdev->event_lock, flags);
   1162	queue_work(cfg80211_wq, &rdev->event_work);
   1163}
   1164EXPORT_SYMBOL(cfg80211_disconnected);
   1165
   1166/*
   1167 * API calls for nl80211/wext compatibility code
   1168 */
   1169int cfg80211_connect(struct cfg80211_registered_device *rdev,
   1170		     struct net_device *dev,
   1171		     struct cfg80211_connect_params *connect,
   1172		     struct cfg80211_cached_keys *connkeys,
   1173		     const u8 *prev_bssid)
   1174{
   1175	struct wireless_dev *wdev = dev->ieee80211_ptr;
   1176	int err;
   1177
   1178	ASSERT_WDEV_LOCK(wdev);
   1179
   1180	/*
   1181	 * If we have an ssid_len, we're trying to connect or are
   1182	 * already connected, so reject a new SSID unless it's the
   1183	 * same (which is the case for re-association.)
   1184	 */
   1185	if (wdev->ssid_len &&
   1186	    (wdev->ssid_len != connect->ssid_len ||
   1187	     memcmp(wdev->ssid, connect->ssid, wdev->ssid_len)))
   1188		return -EALREADY;
   1189
   1190	/*
   1191	 * If connected, reject (re-)association unless prev_bssid
   1192	 * matches the current BSSID.
   1193	 */
   1194	if (wdev->current_bss) {
   1195		if (!prev_bssid)
   1196			return -EALREADY;
   1197		if (!ether_addr_equal(prev_bssid, wdev->current_bss->pub.bssid))
   1198			return -ENOTCONN;
   1199	}
   1200
   1201	/*
   1202	 * Reject if we're in the process of connecting with WEP,
   1203	 * this case isn't very interesting and trying to handle
   1204	 * it would make the code much more complex.
   1205	 */
   1206	if (wdev->connect_keys)
   1207		return -EINPROGRESS;
   1208
   1209	cfg80211_oper_and_ht_capa(&connect->ht_capa_mask,
   1210				  rdev->wiphy.ht_capa_mod_mask);
   1211	cfg80211_oper_and_vht_capa(&connect->vht_capa_mask,
   1212				   rdev->wiphy.vht_capa_mod_mask);
   1213
   1214	if (connkeys && connkeys->def >= 0) {
   1215		int idx;
   1216		u32 cipher;
   1217
   1218		idx = connkeys->def;
   1219		cipher = connkeys->params[idx].cipher;
   1220		/* If given a WEP key we may need it for shared key auth */
   1221		if (cipher == WLAN_CIPHER_SUITE_WEP40 ||
   1222		    cipher == WLAN_CIPHER_SUITE_WEP104) {
   1223			connect->key_idx = idx;
   1224			connect->key = connkeys->params[idx].key;
   1225			connect->key_len = connkeys->params[idx].key_len;
   1226
   1227			/*
   1228			 * If ciphers are not set (e.g. when going through
   1229			 * iwconfig), we have to set them appropriately here.
   1230			 */
   1231			if (connect->crypto.cipher_group == 0)
   1232				connect->crypto.cipher_group = cipher;
   1233
   1234			if (connect->crypto.n_ciphers_pairwise == 0) {
   1235				connect->crypto.n_ciphers_pairwise = 1;
   1236				connect->crypto.ciphers_pairwise[0] = cipher;
   1237			}
   1238		}
   1239
   1240		connect->crypto.wep_keys = connkeys->params;
   1241		connect->crypto.wep_tx_key = connkeys->def;
   1242	} else {
   1243		if (WARN_ON(connkeys))
   1244			return -EINVAL;
   1245	}
   1246
   1247	wdev->connect_keys = connkeys;
   1248	memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
   1249	wdev->ssid_len = connect->ssid_len;
   1250
   1251	wdev->conn_bss_type = connect->pbss ? IEEE80211_BSS_TYPE_PBSS :
   1252					      IEEE80211_BSS_TYPE_ESS;
   1253
   1254	if (!rdev->ops->connect)
   1255		err = cfg80211_sme_connect(wdev, connect, prev_bssid);
   1256	else
   1257		err = rdev_connect(rdev, dev, connect);
   1258
   1259	if (err) {
   1260		wdev->connect_keys = NULL;
   1261		/*
   1262		 * This could be reassoc getting refused, don't clear
   1263		 * ssid_len in that case.
   1264		 */
   1265		if (!wdev->current_bss)
   1266			wdev->ssid_len = 0;
   1267		return err;
   1268	}
   1269
   1270	return 0;
   1271}
   1272
   1273int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
   1274			struct net_device *dev, u16 reason, bool wextev)
   1275{
   1276	struct wireless_dev *wdev = dev->ieee80211_ptr;
   1277	int err = 0;
   1278
   1279	ASSERT_WDEV_LOCK(wdev);
   1280
   1281	kfree_sensitive(wdev->connect_keys);
   1282	wdev->connect_keys = NULL;
   1283
   1284	wdev->conn_owner_nlportid = 0;
   1285
   1286	if (wdev->conn)
   1287		err = cfg80211_sme_disconnect(wdev, reason);
   1288	else if (!rdev->ops->disconnect)
   1289		cfg80211_mlme_down(rdev, dev);
   1290	else if (wdev->ssid_len)
   1291		err = rdev_disconnect(rdev, dev, reason);
   1292
   1293	/*
   1294	 * Clear ssid_len unless we actually were fully connected,
   1295	 * in which case cfg80211_disconnected() will take care of
   1296	 * this later.
   1297	 */
   1298	if (!wdev->current_bss)
   1299		wdev->ssid_len = 0;
   1300
   1301	return err;
   1302}
   1303
   1304/*
   1305 * Used to clean up after the connection / connection attempt owner socket
   1306 * disconnects
   1307 */
   1308void cfg80211_autodisconnect_wk(struct work_struct *work)
   1309{
   1310	struct wireless_dev *wdev =
   1311		container_of(work, struct wireless_dev, disconnect_wk);
   1312	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
   1313
   1314	wdev_lock(wdev);
   1315
   1316	if (wdev->conn_owner_nlportid) {
   1317		switch (wdev->iftype) {
   1318		case NL80211_IFTYPE_ADHOC:
   1319			__cfg80211_leave_ibss(rdev, wdev->netdev, false);
   1320			break;
   1321		case NL80211_IFTYPE_AP:
   1322		case NL80211_IFTYPE_P2P_GO:
   1323			__cfg80211_stop_ap(rdev, wdev->netdev, false);
   1324			break;
   1325		case NL80211_IFTYPE_MESH_POINT:
   1326			__cfg80211_leave_mesh(rdev, wdev->netdev);
   1327			break;
   1328		case NL80211_IFTYPE_STATION:
   1329		case NL80211_IFTYPE_P2P_CLIENT:
   1330			/*
   1331			 * Use disconnect_bssid if still connecting and
   1332			 * ops->disconnect not implemented.  Otherwise we can
   1333			 * use cfg80211_disconnect.
   1334			 */
   1335			if (rdev->ops->disconnect || wdev->current_bss)
   1336				cfg80211_disconnect(rdev, wdev->netdev,
   1337						    WLAN_REASON_DEAUTH_LEAVING,
   1338						    true);
   1339			else
   1340				cfg80211_mlme_deauth(rdev, wdev->netdev,
   1341						     wdev->disconnect_bssid,
   1342						     NULL, 0,
   1343						     WLAN_REASON_DEAUTH_LEAVING,
   1344						     false);
   1345			break;
   1346		default:
   1347			break;
   1348		}
   1349	}
   1350
   1351	wdev_unlock(wdev);
   1352}