File Index
Files and directories
Sign in
FILE

mlme.c

File preview with syntax highlighting.

linux-6.19.14/net/wireless/mlme.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * cfg80211 MLME SAP interface
   4 *
   5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
   6 * Copyright (c) 2015		Intel Deutschland GmbH
   7 * Copyright (C) 2019-2020, 2022-2025 Intel Corporation
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/etherdevice.h>
  13#include <linux/netdevice.h>
  14#include <linux/nl80211.h>
  15#include <linux/slab.h>
  16#include <linux/wireless.h>
  17#include <net/cfg80211.h>
  18#include <net/iw_handler.h>
  19#include "core.h"
  20#include "nl80211.h"
  21#include "rdev-ops.h"
  22
  23
  24void cfg80211_rx_assoc_resp(struct net_device *dev,
  25			    const struct cfg80211_rx_assoc_resp_data *data)
  26{
  27	struct wireless_dev *wdev = dev->ieee80211_ptr;
  28	struct wiphy *wiphy = wdev->wiphy;
  29	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
  30	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)data->buf;
  31	struct cfg80211_connect_resp_params cr = {
  32		.timeout_reason = NL80211_TIMEOUT_UNSPECIFIED,
  33		.req_ie = data->req_ies,
  34		.req_ie_len = data->req_ies_len,
  35		.resp_ie = mgmt->u.assoc_resp.variable,
  36		.resp_ie_len = data->len -
  37			       offsetof(struct ieee80211_mgmt,
  38					u.assoc_resp.variable),
  39		.status = le16_to_cpu(mgmt->u.assoc_resp.status_code),
  40		.ap_mld_addr = data->ap_mld_addr,
  41	};
  42	unsigned int link_id;
  43
  44	for (link_id = 0; link_id < ARRAY_SIZE(data->links); link_id++) {
  45		cr.links[link_id].status = data->links[link_id].status;
  46		cr.links[link_id].bss = data->links[link_id].bss;
  47
  48		WARN_ON_ONCE(cr.links[link_id].status != WLAN_STATUS_SUCCESS &&
  49			     (!cr.ap_mld_addr || !cr.links[link_id].bss));
  50
  51		if (!cr.links[link_id].bss)
  52			continue;
  53		cr.links[link_id].bssid = data->links[link_id].bss->bssid;
  54		cr.links[link_id].addr = data->links[link_id].addr;
  55		/* need to have local link addresses for MLO connections */
  56		WARN_ON(cr.ap_mld_addr &&
  57			!is_valid_ether_addr(cr.links[link_id].addr));
  58
  59		BUG_ON(!cr.links[link_id].bss->channel);
  60
  61		if (cr.links[link_id].bss->channel->band == NL80211_BAND_S1GHZ) {
  62			WARN_ON(link_id);
  63			cr.resp_ie = (u8 *)&mgmt->u.s1g_assoc_resp.variable;
  64			cr.resp_ie_len = data->len -
  65					 offsetof(struct ieee80211_mgmt,
  66						  u.s1g_assoc_resp.variable);
  67		}
  68
  69		if (cr.ap_mld_addr)
  70			cr.valid_links |= BIT(link_id);
  71	}
  72
  73	trace_cfg80211_send_rx_assoc(dev, data);
  74
  75	/*
  76	 * This is a bit of a hack, we don't notify userspace of
  77	 * a (re-)association reply if we tried to send a reassoc
  78	 * and got a reject -- we only try again with an assoc
  79	 * frame instead of reassoc.
  80	 */
  81	if (cfg80211_sme_rx_assoc_resp(wdev, cr.status)) {
  82		for (link_id = 0; link_id < ARRAY_SIZE(data->links); link_id++) {
  83			struct cfg80211_bss *bss = data->links[link_id].bss;
  84
  85			if (!bss)
  86				continue;
  87
  88			cfg80211_unhold_bss(bss_from_pub(bss));
  89			cfg80211_put_bss(wiphy, bss);
  90		}
  91		return;
  92	}
  93
  94	nl80211_send_rx_assoc(rdev, dev, data);
  95	/* update current_bss etc., consumes the bss reference */
  96	__cfg80211_connect_result(dev, &cr, cr.status == WLAN_STATUS_SUCCESS);
  97}
  98EXPORT_SYMBOL(cfg80211_rx_assoc_resp);
  99
 100static void cfg80211_process_auth(struct wireless_dev *wdev,
 101				  const u8 *buf, size_t len)
 102{
 103	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 104
 105	nl80211_send_rx_auth(rdev, wdev->netdev, buf, len, GFP_KERNEL);
 106	cfg80211_sme_rx_auth(wdev, buf, len);
 107}
 108
 109static void cfg80211_process_deauth(struct wireless_dev *wdev,
 110				    const u8 *buf, size_t len,
 111				    bool reconnect)
 112{
 113	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 114	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
 115	const u8 *bssid = mgmt->bssid;
 116	u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
 117	bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);
 118
 119	nl80211_send_deauth(rdev, wdev->netdev, buf, len, reconnect, GFP_KERNEL);
 120
 121	if (!wdev->connected || !ether_addr_equal(wdev->u.client.connected_addr, bssid))
 122		return;
 123
 124	__cfg80211_disconnected(wdev->netdev, NULL, 0, reason_code, from_ap);
 125	cfg80211_sme_deauth(wdev);
 126}
 127
 128static void cfg80211_process_disassoc(struct wireless_dev *wdev,
 129				      const u8 *buf, size_t len,
 130				      bool reconnect)
 131{
 132	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 133	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
 134	const u8 *bssid = mgmt->bssid;
 135	u16 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
 136	bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);
 137
 138	nl80211_send_disassoc(rdev, wdev->netdev, buf, len, reconnect,
 139			      GFP_KERNEL);
 140
 141	if (WARN_ON(!wdev->connected ||
 142		    !ether_addr_equal(wdev->u.client.connected_addr, bssid)))
 143		return;
 144
 145	__cfg80211_disconnected(wdev->netdev, NULL, 0, reason_code, from_ap);
 146	cfg80211_sme_disassoc(wdev);
 147}
 148
 149void cfg80211_rx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len)
 150{
 151	struct wireless_dev *wdev = dev->ieee80211_ptr;
 152	struct ieee80211_mgmt *mgmt = (void *)buf;
 153
 154	lockdep_assert_wiphy(wdev->wiphy);
 155
 156	trace_cfg80211_rx_mlme_mgmt(dev, buf, len);
 157
 158	if (WARN_ON(len < 2))
 159		return;
 160
 161	if (ieee80211_is_auth(mgmt->frame_control))
 162		cfg80211_process_auth(wdev, buf, len);
 163	else if (ieee80211_is_deauth(mgmt->frame_control))
 164		cfg80211_process_deauth(wdev, buf, len, false);
 165	else if (ieee80211_is_disassoc(mgmt->frame_control))
 166		cfg80211_process_disassoc(wdev, buf, len, false);
 167}
 168EXPORT_SYMBOL(cfg80211_rx_mlme_mgmt);
 169
 170void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr)
 171{
 172	struct wireless_dev *wdev = dev->ieee80211_ptr;
 173	struct wiphy *wiphy = wdev->wiphy;
 174	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
 175
 176	trace_cfg80211_send_auth_timeout(dev, addr);
 177
 178	nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
 179	cfg80211_sme_auth_timeout(wdev);
 180}
 181EXPORT_SYMBOL(cfg80211_auth_timeout);
 182
 183void cfg80211_assoc_failure(struct net_device *dev,
 184			    struct cfg80211_assoc_failure *data)
 185{
 186	struct wireless_dev *wdev = dev->ieee80211_ptr;
 187	struct wiphy *wiphy = wdev->wiphy;
 188	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
 189	const u8 *addr = data->ap_mld_addr ?: data->bss[0]->bssid;
 190	int i;
 191
 192	trace_cfg80211_send_assoc_failure(dev, data);
 193
 194	if (data->timeout) {
 195		nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
 196		cfg80211_sme_assoc_timeout(wdev);
 197	} else {
 198		cfg80211_sme_abandon_assoc(wdev);
 199	}
 200
 201	for (i = 0; i < ARRAY_SIZE(data->bss); i++) {
 202		struct cfg80211_bss *bss = data->bss[i];
 203
 204		if (!bss)
 205			continue;
 206
 207		cfg80211_unhold_bss(bss_from_pub(bss));
 208		cfg80211_put_bss(wiphy, bss);
 209	}
 210}
 211EXPORT_SYMBOL(cfg80211_assoc_failure);
 212
 213void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len,
 214			   bool reconnect)
 215{
 216	struct wireless_dev *wdev = dev->ieee80211_ptr;
 217	struct ieee80211_mgmt *mgmt = (void *)buf;
 218
 219	lockdep_assert_wiphy(wdev->wiphy);
 220
 221	trace_cfg80211_tx_mlme_mgmt(dev, buf, len, reconnect);
 222
 223	if (WARN_ON(len < 2))
 224		return;
 225
 226	if (ieee80211_is_deauth(mgmt->frame_control))
 227		cfg80211_process_deauth(wdev, buf, len, reconnect);
 228	else
 229		cfg80211_process_disassoc(wdev, buf, len, reconnect);
 230}
 231EXPORT_SYMBOL(cfg80211_tx_mlme_mgmt);
 232
 233void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
 234				  enum nl80211_key_type key_type, int key_id,
 235				  const u8 *tsc, gfp_t gfp)
 236{
 237	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
 238	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
 239#ifdef CONFIG_CFG80211_WEXT
 240	union iwreq_data wrqu;
 241	char *buf = kmalloc(128, gfp);
 242
 243	if (buf) {
 244		memset(&wrqu, 0, sizeof(wrqu));
 245		wrqu.data.length =
 246			sprintf(buf, "MLME-MICHAELMICFAILURE."
 247				"indication(keyid=%d %scast addr=%pM)",
 248				key_id, key_type == NL80211_KEYTYPE_GROUP
 249				? "broad" : "uni", addr);
 250		wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
 251		kfree(buf);
 252	}
 253#endif
 254
 255	trace_cfg80211_michael_mic_failure(dev, addr, key_type, key_id, tsc);
 256	nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
 257}
 258EXPORT_SYMBOL(cfg80211_michael_mic_failure);
 259
 260/* some MLME handling for userspace SME */
 261int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
 262		       struct net_device *dev,
 263		       struct cfg80211_auth_request *req)
 264{
 265	struct wireless_dev *wdev = dev->ieee80211_ptr;
 266
 267	lockdep_assert_wiphy(wdev->wiphy);
 268
 269	if (!req->bss)
 270		return -ENOENT;
 271
 272	if (req->link_id >= 0 &&
 273	    !(wdev->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO))
 274		return -EINVAL;
 275
 276	if (req->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
 277		if (!req->key || !req->key_len ||
 278		    req->key_idx < 0 || req->key_idx > 3)
 279			return -EINVAL;
 280	}
 281
 282	if (wdev->connected &&
 283	    ether_addr_equal(req->bss->bssid, wdev->u.client.connected_addr))
 284		return -EALREADY;
 285
 286	if (ether_addr_equal(req->bss->bssid, dev->dev_addr) ||
 287	    (req->link_id >= 0 &&
 288	     ether_addr_equal(req->ap_mld_addr, dev->dev_addr)))
 289		return -EINVAL;
 290
 291	return rdev_auth(rdev, dev, req);
 292}
 293
 294/*  Do a logical ht_capa &= ht_capa_mask.  */
 295void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
 296			       const struct ieee80211_ht_cap *ht_capa_mask)
 297{
 298	int i;
 299	u8 *p1, *p2;
 300	if (!ht_capa_mask) {
 301		memset(ht_capa, 0, sizeof(*ht_capa));
 302		return;
 303	}
 304
 305	p1 = (u8*)(ht_capa);
 306	p2 = (u8*)(ht_capa_mask);
 307	for (i = 0; i < sizeof(*ht_capa); i++)
 308		p1[i] &= p2[i];
 309}
 310
 311/*  Do a logical vht_capa &= vht_capa_mask.  */
 312void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
 313				const struct ieee80211_vht_cap *vht_capa_mask)
 314{
 315	int i;
 316	u8 *p1, *p2;
 317	if (!vht_capa_mask) {
 318		memset(vht_capa, 0, sizeof(*vht_capa));
 319		return;
 320	}
 321
 322	p1 = (u8*)(vht_capa);
 323	p2 = (u8*)(vht_capa_mask);
 324	for (i = 0; i < sizeof(*vht_capa); i++)
 325		p1[i] &= p2[i];
 326}
 327
 328static int
 329cfg80211_mlme_check_mlo_compat(const struct ieee80211_multi_link_elem *mle_a,
 330			       const struct ieee80211_multi_link_elem *mle_b,
 331			       struct netlink_ext_ack *extack)
 332{
 333	const struct ieee80211_mle_basic_common_info *common_a, *common_b;
 334
 335	common_a = (const void *)mle_a->variable;
 336	common_b = (const void *)mle_b->variable;
 337
 338	if (memcmp(common_a->mld_mac_addr, common_b->mld_mac_addr, ETH_ALEN)) {
 339		NL_SET_ERR_MSG(extack, "AP MLD address mismatch");
 340		return -EINVAL;
 341	}
 342
 343	if (ieee80211_mle_get_eml_cap((const u8 *)mle_a) !=
 344	    ieee80211_mle_get_eml_cap((const u8 *)mle_b)) {
 345		NL_SET_ERR_MSG(extack, "link EML capabilities mismatch");
 346		return -EINVAL;
 347	}
 348
 349	if (ieee80211_mle_get_mld_capa_op((const u8 *)mle_a) !=
 350	    ieee80211_mle_get_mld_capa_op((const u8 *)mle_b)) {
 351		NL_SET_ERR_MSG(extack, "link MLD capabilities/ops mismatch");
 352		return -EINVAL;
 353	}
 354
 355	/*
 356	 * Only verify the values in Extended MLD Capabilities that are
 357	 * not reserved when transmitted by an AP (and expected to remain the
 358	 * same over time).
 359	 * The Recommended Max Simultaneous Links subfield in particular is
 360	 * reserved when included in a unicast Probe Response frame and may
 361	 * also change when the AP adds/removes links. The BTM MLD
 362	 * Recommendation For Multiple APs Support subfield is reserved when
 363	 * transmitted by an AP. All other bits are currently reserved.
 364	 * See IEEE P802.11be/D7.0, Table 9-417o.
 365	 */
 366	if ((ieee80211_mle_get_ext_mld_capa_op((const u8 *)mle_a) &
 367	     (IEEE80211_EHT_ML_EXT_MLD_CAPA_OP_PARAM_UPDATE |
 368	      IEEE80211_EHT_ML_EXT_MLD_CAPA_NSTR_UPDATE |
 369	      IEEE80211_EHT_ML_EXT_MLD_CAPA_EMLSR_ENA_ON_ONE_LINK)) !=
 370	    (ieee80211_mle_get_ext_mld_capa_op((const u8 *)mle_b) &
 371	     (IEEE80211_EHT_ML_EXT_MLD_CAPA_OP_PARAM_UPDATE |
 372	      IEEE80211_EHT_ML_EXT_MLD_CAPA_NSTR_UPDATE |
 373	      IEEE80211_EHT_ML_EXT_MLD_CAPA_EMLSR_ENA_ON_ONE_LINK))) {
 374		NL_SET_ERR_MSG(extack,
 375			       "extended link MLD capabilities/ops mismatch");
 376		return -EINVAL;
 377	}
 378
 379	return 0;
 380}
 381
 382static int cfg80211_mlme_check_mlo(struct net_device *dev,
 383				   struct cfg80211_assoc_request *req,
 384				   struct netlink_ext_ack *extack)
 385{
 386	const struct ieee80211_multi_link_elem *mles[ARRAY_SIZE(req->links)] = {};
 387	int i;
 388
 389	if (req->link_id < 0)
 390		return 0;
 391
 392	if (!req->links[req->link_id].bss) {
 393		NL_SET_ERR_MSG(extack, "no BSS for assoc link");
 394		return -EINVAL;
 395	}
 396
 397	rcu_read_lock();
 398	for (i = 0; i < ARRAY_SIZE(req->links); i++) {
 399		const struct cfg80211_bss_ies *ies;
 400		const struct element *ml;
 401
 402		if (!req->links[i].bss)
 403			continue;
 404
 405		if (ether_addr_equal(req->links[i].bss->bssid, dev->dev_addr)) {
 406			NL_SET_ERR_MSG(extack, "BSSID must not be our address");
 407			req->links[i].error = -EINVAL;
 408			goto error;
 409		}
 410
 411		ies = rcu_dereference(req->links[i].bss->ies);
 412		ml = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_MULTI_LINK,
 413					    ies->data, ies->len);
 414		if (!ml) {
 415			NL_SET_ERR_MSG(extack, "MLO BSS w/o ML element");
 416			req->links[i].error = -EINVAL;
 417			goto error;
 418		}
 419
 420		if (!ieee80211_mle_type_ok(ml->data + 1,
 421					   IEEE80211_ML_CONTROL_TYPE_BASIC,
 422					   ml->datalen - 1)) {
 423			NL_SET_ERR_MSG(extack, "BSS with invalid ML element");
 424			req->links[i].error = -EINVAL;
 425			goto error;
 426		}
 427
 428		mles[i] = (const void *)(ml->data + 1);
 429
 430		if (ieee80211_mle_get_link_id((const u8 *)mles[i]) != i) {
 431			NL_SET_ERR_MSG(extack, "link ID mismatch");
 432			req->links[i].error = -EINVAL;
 433			goto error;
 434		}
 435	}
 436
 437	if (WARN_ON(!mles[req->link_id]))
 438		goto error;
 439
 440	for (i = 0; i < ARRAY_SIZE(req->links); i++) {
 441		if (i == req->link_id || !req->links[i].bss)
 442			continue;
 443
 444		if (WARN_ON(!mles[i]))
 445			goto error;
 446
 447		if (cfg80211_mlme_check_mlo_compat(mles[req->link_id], mles[i],
 448						   extack)) {
 449			req->links[i].error = -EINVAL;
 450			goto error;
 451		}
 452	}
 453
 454	rcu_read_unlock();
 455	return 0;
 456error:
 457	rcu_read_unlock();
 458	return -EINVAL;
 459}
 460
 461/* Note: caller must cfg80211_put_bss() regardless of result */
 462int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 463			struct net_device *dev,
 464			struct cfg80211_assoc_request *req,
 465			struct netlink_ext_ack *extack)
 466{
 467	struct wireless_dev *wdev = dev->ieee80211_ptr;
 468	int err;
 469
 470	lockdep_assert_wiphy(wdev->wiphy);
 471
 472	err = cfg80211_mlme_check_mlo(dev, req, extack);
 473	if (err)
 474		return err;
 475
 476	if (wdev->connected &&
 477	    (!req->prev_bssid ||
 478	     !ether_addr_equal(wdev->u.client.connected_addr, req->prev_bssid)))
 479		return -EALREADY;
 480
 481	if ((req->bss && ether_addr_equal(req->bss->bssid, dev->dev_addr)) ||
 482	    (req->link_id >= 0 &&
 483	     ether_addr_equal(req->ap_mld_addr, dev->dev_addr)))
 484		return -EINVAL;
 485
 486	cfg80211_oper_and_ht_capa(&req->ht_capa_mask,
 487				  rdev->wiphy.ht_capa_mod_mask);
 488	cfg80211_oper_and_vht_capa(&req->vht_capa_mask,
 489				   rdev->wiphy.vht_capa_mod_mask);
 490
 491	err = rdev_assoc(rdev, dev, req);
 492	if (!err) {
 493		int link_id;
 494
 495		if (req->bss) {
 496			cfg80211_ref_bss(&rdev->wiphy, req->bss);
 497			cfg80211_hold_bss(bss_from_pub(req->bss));
 498		}
 499
 500		for (link_id = 0; link_id < ARRAY_SIZE(req->links); link_id++) {
 501			if (!req->links[link_id].bss)
 502				continue;
 503			cfg80211_ref_bss(&rdev->wiphy, req->links[link_id].bss);
 504			cfg80211_hold_bss(bss_from_pub(req->links[link_id].bss));
 505		}
 506	}
 507	return err;
 508}
 509
 510int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
 511			 struct net_device *dev, const u8 *bssid,
 512			 const u8 *ie, int ie_len, u16 reason,
 513			 bool local_state_change)
 514{
 515	struct wireless_dev *wdev = dev->ieee80211_ptr;
 516	struct cfg80211_deauth_request req = {
 517		.bssid = bssid,
 518		.reason_code = reason,
 519		.ie = ie,
 520		.ie_len = ie_len,
 521		.local_state_change = local_state_change,
 522	};
 523
 524	lockdep_assert_wiphy(wdev->wiphy);
 525
 526	if (local_state_change &&
 527	    (!wdev->connected ||
 528	     !ether_addr_equal(wdev->u.client.connected_addr, bssid)))
 529		return 0;
 530
 531	if (ether_addr_equal(wdev->disconnect_bssid, bssid) ||
 532	    (wdev->connected &&
 533	     ether_addr_equal(wdev->u.client.connected_addr, bssid)))
 534		wdev->conn_owner_nlportid = 0;
 535
 536	return rdev_deauth(rdev, dev, &req);
 537}
 538
 539int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
 540			   struct net_device *dev, const u8 *ap_addr,
 541			   const u8 *ie, int ie_len, u16 reason,
 542			   bool local_state_change)
 543{
 544	struct wireless_dev *wdev = dev->ieee80211_ptr;
 545	struct cfg80211_disassoc_request req = {
 546		.reason_code = reason,
 547		.local_state_change = local_state_change,
 548		.ie = ie,
 549		.ie_len = ie_len,
 550		.ap_addr = ap_addr,
 551	};
 552	int err;
 553
 554	lockdep_assert_wiphy(wdev->wiphy);
 555
 556	if (!wdev->connected)
 557		return -ENOTCONN;
 558
 559	if (memcmp(wdev->u.client.connected_addr, ap_addr, ETH_ALEN))
 560		return -ENOTCONN;
 561
 562	err = rdev_disassoc(rdev, dev, &req);
 563	if (err)
 564		return err;
 565
 566	/* driver should have reported the disassoc */
 567	WARN_ON(wdev->connected);
 568	return 0;
 569}
 570
 571void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
 572			struct net_device *dev)
 573{
 574	struct wireless_dev *wdev = dev->ieee80211_ptr;
 575	u8 bssid[ETH_ALEN];
 576
 577	lockdep_assert_wiphy(wdev->wiphy);
 578
 579	if (!rdev->ops->deauth)
 580		return;
 581
 582	if (!wdev->connected)
 583		return;
 584
 585	memcpy(bssid, wdev->u.client.connected_addr, ETH_ALEN);
 586	cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0,
 587			     WLAN_REASON_DEAUTH_LEAVING, false);
 588}
 589
 590struct cfg80211_mgmt_registration {
 591	struct list_head list;
 592	struct wireless_dev *wdev;
 593
 594	u32 nlportid;
 595
 596	int match_len;
 597
 598	__le16 frame_type;
 599
 600	bool multicast_rx;
 601
 602	u8 match[];
 603};
 604
 605static void cfg80211_mgmt_registrations_update(struct wireless_dev *wdev)
 606{
 607	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 608	struct wireless_dev *tmp;
 609	struct cfg80211_mgmt_registration *reg;
 610	struct mgmt_frame_regs upd = {};
 611
 612	lockdep_assert_held(&rdev->wiphy.mtx);
 613
 614	spin_lock_bh(&rdev->mgmt_registrations_lock);
 615	if (!wdev->mgmt_registrations_need_update) {
 616		spin_unlock_bh(&rdev->mgmt_registrations_lock);
 617		return;
 618	}
 619
 620	rcu_read_lock();
 621	list_for_each_entry_rcu(tmp, &rdev->wiphy.wdev_list, list) {
 622		list_for_each_entry(reg, &tmp->mgmt_registrations, list) {
 623			u32 mask = BIT(le16_to_cpu(reg->frame_type) >> 4);
 624			u32 mcast_mask = 0;
 625
 626			if (reg->multicast_rx)
 627				mcast_mask = mask;
 628
 629			upd.global_stypes |= mask;
 630			upd.global_mcast_stypes |= mcast_mask;
 631
 632			if (tmp == wdev) {
 633				upd.interface_stypes |= mask;
 634				upd.interface_mcast_stypes |= mcast_mask;
 635			}
 636		}
 637	}
 638	rcu_read_unlock();
 639
 640	wdev->mgmt_registrations_need_update = 0;
 641	spin_unlock_bh(&rdev->mgmt_registrations_lock);
 642
 643	rdev_update_mgmt_frame_registrations(rdev, wdev, &upd);
 644}
 645
 646void cfg80211_mgmt_registrations_update_wk(struct work_struct *wk)
 647{
 648	struct cfg80211_registered_device *rdev;
 649	struct wireless_dev *wdev;
 650
 651	rdev = container_of(wk, struct cfg80211_registered_device,
 652			    mgmt_registrations_update_wk);
 653
 654	guard(wiphy)(&rdev->wiphy);
 655
 656	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
 657		cfg80211_mgmt_registrations_update(wdev);
 658}
 659
 660int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
 661				u16 frame_type, const u8 *match_data,
 662				int match_len, bool multicast_rx,
 663				struct netlink_ext_ack *extack)
 664{
 665	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 666	struct cfg80211_mgmt_registration *reg, *nreg;
 667	int err = 0;
 668	u16 mgmt_type;
 669	bool update_multicast = false;
 670
 671	if (!wdev->wiphy->mgmt_stypes)
 672		return -EOPNOTSUPP;
 673
 674	if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) {
 675		NL_SET_ERR_MSG(extack, "frame type not management");
 676		return -EINVAL;
 677	}
 678
 679	if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) {
 680		NL_SET_ERR_MSG(extack, "Invalid frame type");
 681		return -EINVAL;
 682	}
 683
 684	mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
 685	if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type))) {
 686		NL_SET_ERR_MSG(extack,
 687			       "Registration to specific type not supported");
 688		return -EINVAL;
 689	}
 690
 691	/*
 692	 * To support Pre Association Security Negotiation (PASN), registration
 693	 * for authentication frames should be supported. However, as some
 694	 * versions of the user space daemons wrongly register to all types of
 695	 * authentication frames (which might result in unexpected behavior)
 696	 * allow such registration if the request is for a specific
 697	 * authentication algorithm number.
 698	 */
 699	if (wdev->iftype == NL80211_IFTYPE_STATION &&
 700	    (frame_type & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_AUTH &&
 701	    !(match_data && match_len >= 2)) {
 702		NL_SET_ERR_MSG(extack,
 703			       "Authentication algorithm number required");
 704		return -EINVAL;
 705	}
 706
 707	nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
 708	if (!nreg)
 709		return -ENOMEM;
 710
 711	spin_lock_bh(&rdev->mgmt_registrations_lock);
 712
 713	list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
 714		int mlen = min(match_len, reg->match_len);
 715
 716		if (frame_type != le16_to_cpu(reg->frame_type))
 717			continue;
 718
 719		if (memcmp(reg->match, match_data, mlen) == 0) {
 720			if (reg->multicast_rx != multicast_rx) {
 721				update_multicast = true;
 722				reg->multicast_rx = multicast_rx;
 723				break;
 724			}
 725			NL_SET_ERR_MSG(extack, "Match already configured");
 726			err = -EALREADY;
 727			break;
 728		}
 729	}
 730
 731	if (err)
 732		goto out;
 733
 734	if (update_multicast) {
 735		kfree(nreg);
 736	} else {
 737		memcpy(nreg->match, match_data, match_len);
 738		nreg->match_len = match_len;
 739		nreg->nlportid = snd_portid;
 740		nreg->frame_type = cpu_to_le16(frame_type);
 741		nreg->wdev = wdev;
 742		nreg->multicast_rx = multicast_rx;
 743		list_add(&nreg->list, &wdev->mgmt_registrations);
 744	}
 745	wdev->mgmt_registrations_need_update = 1;
 746	spin_unlock_bh(&rdev->mgmt_registrations_lock);
 747
 748	cfg80211_mgmt_registrations_update(wdev);
 749
 750	return 0;
 751
 752 out:
 753	kfree(nreg);
 754	spin_unlock_bh(&rdev->mgmt_registrations_lock);
 755
 756	return err;
 757}
 758
 759void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
 760{
 761	struct wiphy *wiphy = wdev->wiphy;
 762	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
 763	struct cfg80211_mgmt_registration *reg, *tmp;
 764
 765	spin_lock_bh(&rdev->mgmt_registrations_lock);
 766
 767	list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
 768		if (reg->nlportid != nlportid)
 769			continue;
 770
 771		list_del(&reg->list);
 772		kfree(reg);
 773
 774		wdev->mgmt_registrations_need_update = 1;
 775		schedule_work(&rdev->mgmt_registrations_update_wk);
 776	}
 777
 778	spin_unlock_bh(&rdev->mgmt_registrations_lock);
 779
 780	if (nlportid && rdev->crit_proto_nlportid == nlportid) {
 781		rdev->crit_proto_nlportid = 0;
 782		rdev_crit_proto_stop(rdev, wdev);
 783	}
 784
 785	if (nlportid == wdev->ap_unexpected_nlportid)
 786		wdev->ap_unexpected_nlportid = 0;
 787}
 788
 789void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
 790{
 791	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 792	struct cfg80211_mgmt_registration *reg, *tmp;
 793
 794	spin_lock_bh(&rdev->mgmt_registrations_lock);
 795	list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
 796		list_del(&reg->list);
 797		kfree(reg);
 798	}
 799	wdev->mgmt_registrations_need_update = 1;
 800	spin_unlock_bh(&rdev->mgmt_registrations_lock);
 801
 802	cfg80211_mgmt_registrations_update(wdev);
 803}
 804
 805static bool cfg80211_allowed_address(struct wireless_dev *wdev, const u8 *addr)
 806{
 807	int i;
 808
 809	for_each_valid_link(wdev, i) {
 810		if (ether_addr_equal(addr, wdev->links[i].addr))
 811			return true;
 812	}
 813
 814	return ether_addr_equal(addr, wdev_address(wdev));
 815}
 816
 817static bool cfg80211_allowed_random_address(struct wireless_dev *wdev,
 818					    const struct ieee80211_mgmt *mgmt)
 819{
 820	if (ieee80211_is_auth(mgmt->frame_control) ||
 821	    ieee80211_is_deauth(mgmt->frame_control)) {
 822		/* Allow random TA to be used with authentication and
 823		 * deauthentication frames if the driver has indicated support.
 824		 */
 825		if (wiphy_ext_feature_isset(
 826			    wdev->wiphy,
 827			    NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA))
 828			return true;
 829	} else if (ieee80211_is_action(mgmt->frame_control) &&
 830		   mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
 831		/* Allow random TA to be used with Public Action frames if the
 832		 * driver has indicated support.
 833		 */
 834		if (!wdev->connected &&
 835		    wiphy_ext_feature_isset(
 836			    wdev->wiphy,
 837			    NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA))
 838			return true;
 839
 840		if (wdev->connected &&
 841		    wiphy_ext_feature_isset(
 842			    wdev->wiphy,
 843			    NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED))
 844			return true;
 845	}
 846
 847	return false;
 848}
 849
 850int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
 851			  struct wireless_dev *wdev,
 852			  struct cfg80211_mgmt_tx_params *params, u64 *cookie)
 853{
 854	const struct ieee80211_mgmt *mgmt;
 855	u16 stype;
 856
 857	lockdep_assert_wiphy(&rdev->wiphy);
 858
 859	if (!wdev->wiphy->mgmt_stypes)
 860		return -EOPNOTSUPP;
 861
 862	if (!rdev->ops->mgmt_tx)
 863		return -EOPNOTSUPP;
 864
 865	if (params->len < 24 + 1)
 866		return -EINVAL;
 867
 868	mgmt = (const struct ieee80211_mgmt *)params->buf;
 869
 870	if (!ieee80211_is_mgmt(mgmt->frame_control) ||
 871	    ieee80211_has_order(mgmt->frame_control))
 872		return -EINVAL;
 873
 874	stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
 875	if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].tx & BIT(stype >> 4)))
 876		return -EINVAL;
 877
 878	if (ieee80211_is_action(mgmt->frame_control) &&
 879	    mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
 880		int err = 0;
 881
 882		switch (wdev->iftype) {
 883		case NL80211_IFTYPE_ADHOC:
 884			/*
 885			 * check for IBSS DA must be done by driver as
 886			 * cfg80211 doesn't track the stations
 887			 */
 888			if (!wdev->u.ibss.current_bss ||
 889			    !ether_addr_equal(wdev->u.ibss.current_bss->pub.bssid,
 890					      mgmt->bssid)) {
 891				err = -ENOTCONN;
 892				break;
 893			}
 894			break;
 895		case NL80211_IFTYPE_STATION:
 896		case NL80211_IFTYPE_P2P_CLIENT:
 897			if (!wdev->connected) {
 898				err = -ENOTCONN;
 899				break;
 900			}
 901
 902			/* FIXME: MLD may address this differently */
 903
 904			if (!ether_addr_equal(wdev->u.client.connected_addr,
 905					      mgmt->bssid)) {
 906				err = -ENOTCONN;
 907				break;
 908			}
 909
 910			/* for station, check that DA is the AP */
 911			if (!ether_addr_equal(wdev->u.client.connected_addr,
 912					      mgmt->da)) {
 913				err = -ENOTCONN;
 914				break;
 915			}
 916			break;
 917		case NL80211_IFTYPE_AP:
 918		case NL80211_IFTYPE_P2P_GO:
 919		case NL80211_IFTYPE_AP_VLAN:
 920			if (!ether_addr_equal(mgmt->bssid, wdev_address(wdev)) &&
 921			    (params->link_id < 0 ||
 922			     !ether_addr_equal(mgmt->bssid,
 923					       wdev->links[params->link_id].addr)))
 924				err = -EINVAL;
 925			break;
 926		case NL80211_IFTYPE_MESH_POINT:
 927			if (!ether_addr_equal(mgmt->sa, mgmt->bssid)) {
 928				err = -EINVAL;
 929				break;
 930			}
 931			/*
 932			 * check for mesh DA must be done by driver as
 933			 * cfg80211 doesn't track the stations
 934			 */
 935			break;
 936		case NL80211_IFTYPE_P2P_DEVICE:
 937			/*
 938			 * fall through, P2P device only supports
 939			 * public action frames
 940			 */
 941		case NL80211_IFTYPE_NAN:
 942		default:
 943			err = -EOPNOTSUPP;
 944			break;
 945		}
 946
 947		if (err)
 948			return err;
 949	}
 950
 951	if (!cfg80211_allowed_address(wdev, mgmt->sa) &&
 952	    !cfg80211_allowed_random_address(wdev, mgmt))
 953		return -EINVAL;
 954
 955	/* Transmit the management frame as requested by user space */
 956	return rdev_mgmt_tx(rdev, wdev, params, cookie);
 957}
 958
 959bool cfg80211_rx_mgmt_ext(struct wireless_dev *wdev,
 960			  struct cfg80211_rx_info *info)
 961{
 962	struct wiphy *wiphy = wdev->wiphy;
 963	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
 964	struct cfg80211_mgmt_registration *reg;
 965	const struct ieee80211_txrx_stypes *stypes =
 966		&wiphy->mgmt_stypes[wdev->iftype];
 967	struct ieee80211_mgmt *mgmt = (void *)info->buf;
 968	const u8 *data;
 969	int data_len;
 970	bool result = false;
 971	__le16 ftype = mgmt->frame_control &
 972		cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
 973	u16 stype;
 974
 975	trace_cfg80211_rx_mgmt(wdev, info);
 976	stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4;
 977
 978	if (!(stypes->rx & BIT(stype))) {
 979		trace_cfg80211_return_bool(false);
 980		return false;
 981	}
 982
 983	data = info->buf + ieee80211_hdrlen(mgmt->frame_control);
 984	data_len = info->len - ieee80211_hdrlen(mgmt->frame_control);
 985
 986	spin_lock_bh(&rdev->mgmt_registrations_lock);
 987
 988	list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
 989		if (reg->frame_type != ftype)
 990			continue;
 991
 992		if (reg->match_len > data_len)
 993			continue;
 994
 995		if (memcmp(reg->match, data, reg->match_len))
 996			continue;
 997
 998		/* found match! */
 999
1000		/* Indicate the received Action frame to user space */
1001		if (nl80211_send_mgmt(rdev, wdev, reg->nlportid, info,
1002				      GFP_ATOMIC))
1003			continue;
1004
1005		result = true;
1006		break;
1007	}
1008
1009	spin_unlock_bh(&rdev->mgmt_registrations_lock);
1010
1011	trace_cfg80211_return_bool(result);
1012	return result;
1013}
1014EXPORT_SYMBOL(cfg80211_rx_mgmt_ext);
1015
1016void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev)
1017{
1018	cancel_delayed_work(&rdev->dfs_update_channels_wk);
1019	queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk, 0);
1020}
1021
1022void cfg80211_dfs_channels_update_work(struct work_struct *work)
1023{
1024	struct delayed_work *delayed_work = to_delayed_work(work);
1025	struct cfg80211_registered_device *rdev;
1026	struct cfg80211_chan_def chandef;
1027	struct ieee80211_supported_band *sband;
1028	struct ieee80211_channel *c;
1029	struct wiphy *wiphy;
1030	bool check_again = false;
1031	unsigned long timeout, next_time = 0;
1032	unsigned long time_dfs_update;
1033	enum nl80211_radar_event radar_event;
1034	int bandid, i;
1035
1036	rdev = container_of(delayed_work, struct cfg80211_registered_device,
1037			    dfs_update_channels_wk);
1038	wiphy = &rdev->wiphy;
1039
1040	rtnl_lock();
1041	for (bandid = 0; bandid < NUM_NL80211_BANDS; bandid++) {
1042		sband = wiphy->bands[bandid];
1043		if (!sband)
1044			continue;
1045
1046		for (i = 0; i < sband->n_channels; i++) {
1047			c = &sband->channels[i];
1048
1049			if (!(c->flags & IEEE80211_CHAN_RADAR))
1050				continue;
1051
1052			if (c->dfs_state != NL80211_DFS_UNAVAILABLE &&
1053			    c->dfs_state != NL80211_DFS_AVAILABLE)
1054				continue;
1055
1056			if (c->dfs_state == NL80211_DFS_UNAVAILABLE) {
1057				time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS;
1058				radar_event = NL80211_RADAR_NOP_FINISHED;
1059			} else {
1060				if (regulatory_pre_cac_allowed(wiphy) ||
1061				    cfg80211_any_wiphy_oper_chan(wiphy, c))
1062					continue;
1063
1064				time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS;
1065				radar_event = NL80211_RADAR_PRE_CAC_EXPIRED;
1066			}
1067
1068			timeout = c->dfs_state_entered +
1069				  msecs_to_jiffies(time_dfs_update);
1070
1071			if (time_after_eq(jiffies, timeout)) {
1072				c->dfs_state = NL80211_DFS_USABLE;
1073				c->dfs_state_entered = jiffies;
1074
1075				cfg80211_chandef_create(&chandef, c,
1076							NL80211_CHAN_NO_HT);
1077
1078				nl80211_radar_notify(rdev, &chandef,
1079						     radar_event, NULL,
1080						     GFP_ATOMIC);
1081
1082				regulatory_propagate_dfs_state(wiphy, &chandef,
1083							       c->dfs_state,
1084							       radar_event);
1085				continue;
1086			}
1087
1088			if (!check_again)
1089				next_time = timeout - jiffies;
1090			else
1091				next_time = min(next_time, timeout - jiffies);
1092			check_again = true;
1093		}
1094	}
1095	rtnl_unlock();
1096
1097	/* reschedule if there are other channels waiting to be cleared again */
1098	if (check_again)
1099		queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk,
1100				   next_time);
1101}
1102
1103
1104void __cfg80211_radar_event(struct wiphy *wiphy,
1105			    struct cfg80211_chan_def *chandef,
1106			    bool offchan, gfp_t gfp)
1107{
1108	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1109
1110	trace_cfg80211_radar_event(wiphy, chandef, offchan);
1111
1112	/* only set the chandef supplied channel to unavailable, in
1113	 * case the radar is detected on only one of multiple channels
1114	 * spanned by the chandef.
1115	 */
1116	cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE);
1117
1118	if (offchan)
1119		queue_work(cfg80211_wq, &rdev->background_cac_abort_wk);
1120
1121	cfg80211_sched_dfs_chan_update(rdev);
1122
1123	nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp);
1124
1125	memcpy(&rdev->radar_chandef, chandef, sizeof(struct cfg80211_chan_def));
1126	queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
1127}
1128EXPORT_SYMBOL(__cfg80211_radar_event);
1129
1130void cfg80211_cac_event(struct net_device *netdev,
1131			const struct cfg80211_chan_def *chandef,
1132			enum nl80211_radar_event event, gfp_t gfp,
1133			unsigned int link_id)
1134{
1135	struct wireless_dev *wdev = netdev->ieee80211_ptr;
1136	struct wiphy *wiphy = wdev->wiphy;
1137	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1138	unsigned long timeout;
1139
1140	if (WARN_ON(wdev->valid_links &&
1141		    !(wdev->valid_links & BIT(link_id))))
1142		return;
1143
1144	trace_cfg80211_cac_event(netdev, event, link_id);
1145
1146	if (WARN_ON(!wdev->links[link_id].cac_started &&
1147		    event != NL80211_RADAR_CAC_STARTED))
1148		return;
1149
1150	switch (event) {
1151	case NL80211_RADAR_CAC_FINISHED:
1152		timeout = wdev->links[link_id].cac_start_time +
1153			  msecs_to_jiffies(wdev->links[link_id].cac_time_ms);
1154		WARN_ON(!time_after_eq(jiffies, timeout));
1155		cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
1156		memcpy(&rdev->cac_done_chandef, chandef,
1157		       sizeof(struct cfg80211_chan_def));
1158		queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
1159		cfg80211_sched_dfs_chan_update(rdev);
1160		fallthrough;
1161	case NL80211_RADAR_CAC_ABORTED:
1162		wdev->links[link_id].cac_started = false;
1163		break;
1164	case NL80211_RADAR_CAC_STARTED:
1165		wdev->links[link_id].cac_started = true;
1166		break;
1167	default:
1168		WARN_ON(1);
1169		return;
1170	}
1171
1172	nl80211_radar_notify(rdev, chandef, event, netdev, gfp);
1173}
1174EXPORT_SYMBOL(cfg80211_cac_event);
1175
1176static void
1177__cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
1178				struct wireless_dev *wdev,
1179				const struct cfg80211_chan_def *chandef,
1180				enum nl80211_radar_event event)
1181{
1182	struct wiphy *wiphy = &rdev->wiphy;
1183	struct net_device *netdev;
1184
1185	lockdep_assert_wiphy(&rdev->wiphy);
1186
1187	if (!cfg80211_chandef_valid(chandef))
1188		return;
1189
1190	if (!rdev->background_radar_wdev)
1191		return;
1192
1193	switch (event) {
1194	case NL80211_RADAR_CAC_FINISHED:
1195		cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
1196		memcpy(&rdev->cac_done_chandef, chandef, sizeof(*chandef));
1197		queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
1198		cfg80211_sched_dfs_chan_update(rdev);
1199		wdev = rdev->background_radar_wdev;
1200		break;
1201	case NL80211_RADAR_CAC_ABORTED:
1202		if (!cancel_delayed_work(&rdev->background_cac_done_wk))
1203			return;
1204		wdev = rdev->background_radar_wdev;
1205		break;
1206	case NL80211_RADAR_CAC_STARTED:
1207		break;
1208	default:
1209		return;
1210	}
1211
1212	netdev = wdev ? wdev->netdev : NULL;
1213	nl80211_radar_notify(rdev, chandef, event, netdev, GFP_KERNEL);
1214}
1215
1216static void
1217cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
1218			      const struct cfg80211_chan_def *chandef,
1219			      enum nl80211_radar_event event)
1220{
1221	guard(wiphy)(&rdev->wiphy);
1222
1223	__cfg80211_background_cac_event(rdev, rdev->background_radar_wdev,
1224					chandef, event);
1225}
1226
1227void cfg80211_background_cac_done_wk(struct work_struct *work)
1228{
1229	struct delayed_work *delayed_work = to_delayed_work(work);
1230	struct cfg80211_registered_device *rdev;
1231
1232	rdev = container_of(delayed_work, struct cfg80211_registered_device,
1233			    background_cac_done_wk);
1234	cfg80211_background_cac_event(rdev, &rdev->background_radar_chandef,
1235				      NL80211_RADAR_CAC_FINISHED);
1236}
1237
1238void cfg80211_background_cac_abort_wk(struct work_struct *work)
1239{
1240	struct cfg80211_registered_device *rdev;
1241
1242	rdev = container_of(work, struct cfg80211_registered_device,
1243			    background_cac_abort_wk);
1244	cfg80211_background_cac_event(rdev, &rdev->background_radar_chandef,
1245				      NL80211_RADAR_CAC_ABORTED);
1246}
1247
1248void cfg80211_background_cac_abort(struct wiphy *wiphy)
1249{
1250	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1251
1252	queue_work(cfg80211_wq, &rdev->background_cac_abort_wk);
1253}
1254EXPORT_SYMBOL(cfg80211_background_cac_abort);
1255
1256int
1257cfg80211_start_background_radar_detection(struct cfg80211_registered_device *rdev,
1258					  struct wireless_dev *wdev,
1259					  struct cfg80211_chan_def *chandef)
1260{
1261	unsigned int cac_time_ms;
1262	int err;
1263
1264	lockdep_assert_wiphy(&rdev->wiphy);
1265
1266	if (!wiphy_ext_feature_isset(&rdev->wiphy,
1267				     NL80211_EXT_FEATURE_RADAR_BACKGROUND))
1268		return -EOPNOTSUPP;
1269
1270	/* Offchannel chain already locked by another wdev */
1271	if (rdev->background_radar_wdev && rdev->background_radar_wdev != wdev)
1272		return -EBUSY;
1273
1274	/* CAC already in progress on the offchannel chain */
1275	if (rdev->background_radar_wdev == wdev &&
1276	    delayed_work_pending(&rdev->background_cac_done_wk))
1277		return -EBUSY;
1278
1279	err = rdev_set_radar_background(rdev, chandef);
1280	if (err)
1281		return err;
1282
1283	cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, chandef);
1284	if (!cac_time_ms)
1285		cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
1286
1287	rdev->background_radar_chandef = *chandef;
1288	rdev->background_radar_wdev = wdev; /* Get offchain ownership */
1289
1290	__cfg80211_background_cac_event(rdev, wdev, chandef,
1291					NL80211_RADAR_CAC_STARTED);
1292	queue_delayed_work(cfg80211_wq, &rdev->background_cac_done_wk,
1293			   msecs_to_jiffies(cac_time_ms));
1294
1295	return 0;
1296}
1297
1298void cfg80211_stop_radar_detection(struct wireless_dev *wdev)
1299{
1300	struct wiphy *wiphy = wdev->wiphy;
1301	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1302	int link_id;
1303
1304	for_each_valid_link(wdev, link_id) {
1305		struct cfg80211_chan_def chandef;
1306
1307		if (!wdev->links[link_id].cac_started)
1308			continue;
1309
1310		chandef = *wdev_chandef(wdev, link_id);
1311		rdev_end_cac(rdev, wdev->netdev, link_id);
1312		nl80211_radar_notify(rdev, &chandef, NL80211_RADAR_CAC_ABORTED,
1313				     wdev->netdev, GFP_KERNEL);
1314	}
1315}
1316
1317void cfg80211_stop_background_radar_detection(struct wireless_dev *wdev)
1318{
1319	struct wiphy *wiphy = wdev->wiphy;
1320	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1321
1322	lockdep_assert_wiphy(wiphy);
1323
1324	if (wdev != rdev->background_radar_wdev)
1325		return;
1326
1327	rdev_set_radar_background(rdev, NULL);
1328	rdev->background_radar_wdev = NULL; /* Release offchain ownership */
1329
1330	__cfg80211_background_cac_event(rdev, wdev,
1331					&rdev->background_radar_chandef,
1332					NL80211_RADAR_CAC_ABORTED);
1333}
1334
1335int cfg80211_assoc_ml_reconf(struct cfg80211_registered_device *rdev,
1336			     struct net_device *dev,
1337			     struct cfg80211_ml_reconf_req *req)
1338{
1339	struct wireless_dev *wdev = dev->ieee80211_ptr;
1340	int err;
1341
1342	lockdep_assert_wiphy(wdev->wiphy);
1343
1344	err = rdev_assoc_ml_reconf(rdev, dev, req);
1345	if (!err) {
1346		int link_id;
1347
1348		for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS;
1349		     link_id++) {
1350			if (!req->add_links[link_id].bss)
1351				continue;
1352
1353			cfg80211_ref_bss(&rdev->wiphy, req->add_links[link_id].bss);
1354			cfg80211_hold_bss(bss_from_pub(req->add_links[link_id].bss));
1355		}
1356	}
1357
1358	return err;
1359}
1360
1361void cfg80211_mlo_reconf_add_done(struct net_device *dev,
1362				  struct cfg80211_mlo_reconf_done_data *data)
1363{
1364	struct wireless_dev *wdev = dev->ieee80211_ptr;
1365	struct wiphy *wiphy = wdev->wiphy;
1366	int link_id;
1367
1368	lockdep_assert_wiphy(wiphy);
1369
1370	trace_cfg80211_mlo_reconf_add_done(dev, data->added_links,
1371					   data->buf, data->len,
1372					   data->driver_initiated);
1373
1374	if (WARN_ON(!wdev->valid_links))
1375		return;
1376
1377	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
1378		    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
1379		return;
1380
1381	/* validate that a BSS is given for each added link */
1382	for (link_id = 0; link_id < ARRAY_SIZE(data->links); link_id++) {
1383		struct cfg80211_bss *bss = data->links[link_id].bss;
1384
1385		if (!(data->added_links & BIT(link_id)))
1386			continue;
1387
1388		if (WARN_ON(!bss))
1389			return;
1390	}
1391
1392	for (link_id = 0; link_id < ARRAY_SIZE(data->links); link_id++) {
1393		struct cfg80211_bss *bss = data->links[link_id].bss;
1394
1395		if (!bss)
1396			continue;
1397
1398		if (data->added_links & BIT(link_id)) {
1399			wdev->links[link_id].client.current_bss =
1400				bss_from_pub(bss);
1401
1402			if (data->driver_initiated)
1403				cfg80211_hold_bss(bss_from_pub(bss));
1404
1405			memcpy(wdev->links[link_id].addr,
1406			       data->links[link_id].addr,
1407			       ETH_ALEN);
1408		} else {
1409			if (!data->driver_initiated)
1410				cfg80211_unhold_bss(bss_from_pub(bss));
1411
1412			cfg80211_put_bss(wiphy, bss);
1413		}
1414	}
1415
1416	wdev->valid_links |= data->added_links;
1417	nl80211_mlo_reconf_add_done(dev, data);
1418}
1419EXPORT_SYMBOL(cfg80211_mlo_reconf_add_done);
~/ Read-only file preview.