diff mbox series

[v8,1/4] nl80211: add basic multiple bssid support

Message ID 20210309035437.6131-2-alokad@codeaurora.org (mailing list archive)
State Superseded
Delegated to: Johannes Berg
Headers show
Series Multiple BSSID support | expand

Commit Message

Aloka Dixit March 9, 2021, 3:54 a.m. UTC
From: John Crispin <john@phrozen.org>

This patch adds support for passing the multiple bssid config to the
kernel when an AP gets started. If the BSS is non-transmitting we need
to pass

* the ifidx of the transmitting parent
* the BSS index in the set
* the BSS count of the set
* flag indicating if we want to do EMA
* the multiple bssid elements as an array inside the beacon data

This allows use to generate multiple bssid beacons as well as EMA ones.

Signed-off-by: John Crispin <john@phrozen.org>
Co-developed-by: Aloka Dixit <alokad@codeaurora.org>
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
---
v8: Addition of NL80211_EXT_FEATURE_MULTIPLE_BSSID_AP,
NL80211_EXT_FEATURE_EMA_AP, along with wiphy parameters
max_num_vaps and max_profile_periodicity to be used by drivers

 include/net/cfg80211.h       |  47 ++++++
 include/uapi/linux/nl80211.h |  84 +++++++++++
 net/wireless/nl80211.c       | 277 ++++++++++++++++++++++++++++++-----
 3 files changed, 369 insertions(+), 39 deletions(-)

Comments

Dan Carpenter March 9, 2021, 6:40 a.m. UTC | #1
Hi Aloka,

url:    https://github.com/0day-ci/linux/commits/Aloka-Dixit/Multiple-BSSID-support/20210309-115621
base:   38b5133ad607ecdcc8d24906d1ac9cc8df41acd5
config: x86_64-randconfig-m001-20210309 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

New smatch warnings:
net/wireless/nl80211.c:5704 nl80211_start_ap() error: 'params.acl' dereferencing possible ERR_PTR()

vim +5704 net/wireless/nl80211.c

8860020e0be1f0 Johannes Berg             2012-02-13  5448  static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
8860020e0be1f0 Johannes Berg             2012-02-13  5449  {
8860020e0be1f0 Johannes Berg             2012-02-13  5450  	struct cfg80211_registered_device *rdev = info->user_ptr[0];
8860020e0be1f0 Johannes Berg             2012-02-13  5451  	struct net_device *dev = info->user_ptr[1];
8860020e0be1f0 Johannes Berg             2012-02-13  5452  	struct wireless_dev *wdev = dev->ieee80211_ptr;
8860020e0be1f0 Johannes Berg             2012-02-13  5453  	struct cfg80211_ap_settings params;
8860020e0be1f0 Johannes Berg             2012-02-13  5454  	int err;
8860020e0be1f0 Johannes Berg             2012-02-13  5455  
074ac8df9f93f2 Johannes Berg             2010-09-16  5456  	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4c476991062a0a Johannes Berg             2010-10-04  5457  	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4c476991062a0a Johannes Berg             2010-10-04  5458  		return -EOPNOTSUPP;
eec60b037a8755 Jouni Malinen             2009-03-20  5459  
8860020e0be1f0 Johannes Berg             2012-02-13  5460  	if (!rdev->ops->start_ap)
8860020e0be1f0 Johannes Berg             2012-02-13  5461  		return -EOPNOTSUPP;
8860020e0be1f0 Johannes Berg             2012-02-13  5462  
8860020e0be1f0 Johannes Berg             2012-02-13  5463  	if (wdev->beacon_interval)
8860020e0be1f0 Johannes Berg             2012-02-13  5464  		return -EALREADY;
8860020e0be1f0 Johannes Berg             2012-02-13  5465  
56d1893d94bc06 Johannes Berg             2011-05-09  5466  	memset(&params, 0, sizeof(params));
56d1893d94bc06 Johannes Berg             2011-05-09  5467  
8860020e0be1f0 Johannes Berg             2012-02-13  5468  	/* these are required for START_AP */
ed1b6cc7f80f83 Johannes Berg             2007-12-19  5469  	if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
ed1b6cc7f80f83 Johannes Berg             2007-12-19  5470  	    !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
4c476991062a0a Johannes Berg             2010-10-04  5471  	    !info->attrs[NL80211_ATTR_BEACON_HEAD])
4c476991062a0a Johannes Berg             2010-10-04  5472  		return -EINVAL;
ed1b6cc7f80f83 Johannes Berg             2007-12-19  5473  
81e54d08d9d845 Pradeep Kumar Chitrapu    2018-09-20  5474  	err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon);
8860020e0be1f0 Johannes Berg             2012-02-13  5475  	if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5476  		goto out;
8860020e0be1f0 Johannes Berg             2012-02-13  5477  
8860020e0be1f0 Johannes Berg             2012-02-13  5478  	params.beacon_interval =
56d1893d94bc06 Johannes Berg             2011-05-09  5479  		nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
56d1893d94bc06 Johannes Berg             2011-05-09  5480  	params.dtim_period =
56d1893d94bc06 Johannes Berg             2011-05-09  5481  		nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
56d1893d94bc06 Johannes Berg             2011-05-09  5482  
0c317a02ca982c Purushottam Kushwaha      2016-10-12  5483  	err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
0c317a02ca982c Purushottam Kushwaha      2016-10-12  5484  					   params.beacon_interval);
56d1893d94bc06 Johannes Berg             2011-05-09  5485  	if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5486  		goto out;
56d1893d94bc06 Johannes Berg             2011-05-09  5487  
32e9de846be885 Jouni Malinen             2011-08-10  5488  	/*
8860020e0be1f0 Johannes Berg             2012-02-13  5489  	 * In theory, some of these attributes should be required here
8860020e0be1f0 Johannes Berg             2012-02-13  5490  	 * but since they were not used when the command was originally
8860020e0be1f0 Johannes Berg             2012-02-13  5491  	 * added, keep them optional for old user space programs to let
8860020e0be1f0 Johannes Berg             2012-02-13  5492  	 * them continue to work with drivers that do not need the
8860020e0be1f0 Johannes Berg             2012-02-13  5493  	 * additional information -- drivers must check!
32e9de846be885 Jouni Malinen             2011-08-10  5494  	 */
32e9de846be885 Jouni Malinen             2011-08-10  5495  	if (info->attrs[NL80211_ATTR_SSID]) {
32e9de846be885 Jouni Malinen             2011-08-10  5496  		params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
32e9de846be885 Jouni Malinen             2011-08-10  5497  		params.ssid_len =
32e9de846be885 Jouni Malinen             2011-08-10  5498  			nla_len(info->attrs[NL80211_ATTR_SSID]);
1a41c96851bfa3 John Crispin              2021-03-08  5499  		if (params.ssid_len == 0) {
1a41c96851bfa3 John Crispin              2021-03-08  5500  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5501  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5502  		}
32e9de846be885 Jouni Malinen             2011-08-10  5503  	}
32e9de846be885 Jouni Malinen             2011-08-10  5504  
ab0d76f6823cc3 Johannes Berg             2018-10-02  5505  	if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
32e9de846be885 Jouni Malinen             2011-08-10  5506  		params.hidden_ssid = nla_get_u32(
32e9de846be885 Jouni Malinen             2011-08-10  5507  			info->attrs[NL80211_ATTR_HIDDEN_SSID]);
32e9de846be885 Jouni Malinen             2011-08-10  5508  
5fb628e9105eef Jouni Malinen             2011-08-10  5509  	params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
5fb628e9105eef Jouni Malinen             2011-08-10  5510  
5fb628e9105eef Jouni Malinen             2011-08-10  5511  	if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
5fb628e9105eef Jouni Malinen             2011-08-10  5512  		params.auth_type = nla_get_u32(
5fb628e9105eef Jouni Malinen             2011-08-10  5513  			info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e720676 Jouni Malinen             2012-09-30  5514  		if (!nl80211_valid_auth_type(rdev, params.auth_type,
1a41c96851bfa3 John Crispin              2021-03-08  5515  					     NL80211_CMD_START_AP)) {
1a41c96851bfa3 John Crispin              2021-03-08  5516  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5517  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5518  		}
5fb628e9105eef Jouni Malinen             2011-08-10  5519  	} else
5fb628e9105eef Jouni Malinen             2011-08-10  5520  		params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
5fb628e9105eef Jouni Malinen             2011-08-10  5521  
5fb628e9105eef Jouni Malinen             2011-08-10  5522  	err = nl80211_crypto_settings(rdev, info, &params.crypto,
5fb628e9105eef Jouni Malinen             2011-08-10  5523  				      NL80211_MAX_NR_CIPHER_SUITES);
5fb628e9105eef Jouni Malinen             2011-08-10  5524  	if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5525  		goto out;
5fb628e9105eef Jouni Malinen             2011-08-10  5526  
1b658f118b11de Vasanthakumar Thiagarajan 2012-03-02  5527  	if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
1a41c96851bfa3 John Crispin              2021-03-08  5528  		if (!(rdev->wiphy.features &
1a41c96851bfa3 John Crispin              2021-03-08  5529  		      NL80211_FEATURE_INACTIVITY_TIMER)) {
1a41c96851bfa3 John Crispin              2021-03-08  5530  			err = -EOPNOTSUPP;
1a41c96851bfa3 John Crispin              2021-03-08  5531  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5532  		}
1b658f118b11de Vasanthakumar Thiagarajan 2012-03-02  5533  		params.inactivity_timeout = nla_get_u16(
1b658f118b11de Vasanthakumar Thiagarajan 2012-03-02  5534  			info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
1b658f118b11de Vasanthakumar Thiagarajan 2012-03-02  5535  	}
1b658f118b11de Vasanthakumar Thiagarajan 2012-03-02  5536  
53cabad70ecf0c Johannes Berg             2012-11-14  5537  	if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
1a41c96851bfa3 John Crispin              2021-03-08  5538  		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
1a41c96851bfa3 John Crispin              2021-03-08  5539  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5540  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5541  		}
53cabad70ecf0c Johannes Berg             2012-11-14  5542  		params.p2p_ctwindow =
53cabad70ecf0c Johannes Berg             2012-11-14  5543  			nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
53cabad70ecf0c Johannes Berg             2012-11-14  5544  		if (params.p2p_ctwindow != 0 &&
1a41c96851bfa3 John Crispin              2021-03-08  5545  		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) {
1a41c96851bfa3 John Crispin              2021-03-08  5546  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5547  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5548  		}
53cabad70ecf0c Johannes Berg             2012-11-14  5549  	}
53cabad70ecf0c Johannes Berg             2012-11-14  5550  
53cabad70ecf0c Johannes Berg             2012-11-14  5551  	if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
53cabad70ecf0c Johannes Berg             2012-11-14  5552  		u8 tmp;
53cabad70ecf0c Johannes Berg             2012-11-14  5553  
1a41c96851bfa3 John Crispin              2021-03-08  5554  		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
1a41c96851bfa3 John Crispin              2021-03-08  5555  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5556  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5557  		}
53cabad70ecf0c Johannes Berg             2012-11-14  5558  		tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
53cabad70ecf0c Johannes Berg             2012-11-14  5559  		params.p2p_opp_ps = tmp;
53cabad70ecf0c Johannes Berg             2012-11-14  5560  		if (params.p2p_opp_ps != 0 &&
1a41c96851bfa3 John Crispin              2021-03-08  5561  		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) {
1a41c96851bfa3 John Crispin              2021-03-08  5562  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5563  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5564  		}
53cabad70ecf0c Johannes Berg             2012-11-14  5565  	}
53cabad70ecf0c Johannes Berg             2012-11-14  5566  
aa430da41019c1 Johannes Berg             2012-05-16  5567  	if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
683b6d3b31a519 Johannes Berg             2012-11-08  5568  		err = nl80211_parse_chandef(rdev, info, &params.chandef);
683b6d3b31a519 Johannes Berg             2012-11-08  5569  		if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5570  			goto out;
683b6d3b31a519 Johannes Berg             2012-11-08  5571  	} else if (wdev->preset_chandef.chan) {
683b6d3b31a519 Johannes Berg             2012-11-08  5572  		params.chandef = wdev->preset_chandef;
1a41c96851bfa3 John Crispin              2021-03-08  5573  	} else if (!nl80211_get_ap_channel(rdev, &params)) {
1a41c96851bfa3 John Crispin              2021-03-08  5574  		err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5575  		goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5576  	}
aa430da41019c1 Johannes Berg             2012-05-16  5577  
923b352f19d9ea Arik Nemtsov              2015-07-08  5578  	if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
1a41c96851bfa3 John Crispin              2021-03-08  5579  					   wdev->iftype)) {
1a41c96851bfa3 John Crispin              2021-03-08  5580  		err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5581  		goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5582  	}
aa430da41019c1 Johannes Berg             2012-05-16  5583  
a7c7fbff6a408d Purushottam Kushwaha      2016-09-14  5584  	if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488623730 Tamizh Chelvam            2020-05-13  5585  		err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
9a5f6488623730 Tamizh Chelvam            2020-05-13  5586  						    NL80211_ATTR_TX_RATES,
eb89a6a6b7a1af Miles Hu                  2020-08-04  5587  						    &params.beacon_rate,
857b34c4fb104c Rajkumar Manoharan        2020-10-16  5588  						    dev, false);
a7c7fbff6a408d Purushottam Kushwaha      2016-09-14  5589  		if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5590  			goto out;
a7c7fbff6a408d Purushottam Kushwaha      2016-09-14  5591  
8564e38206de2f Johannes Berg             2016-09-19  5592  		err = validate_beacon_tx_rate(rdev, params.chandef.chan->band,
8564e38206de2f Johannes Berg             2016-09-19  5593  					      &params.beacon_rate);
a7c7fbff6a408d Purushottam Kushwaha      2016-09-14  5594  		if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5595  			goto out;
a7c7fbff6a408d Purushottam Kushwaha      2016-09-14  5596  	}
a7c7fbff6a408d Purushottam Kushwaha      2016-09-14  5597  
18998c381b19bf Eliad Peller              2014-09-10  5598  	if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
18998c381b19bf Eliad Peller              2014-09-10  5599  		params.smps_mode =
18998c381b19bf Eliad Peller              2014-09-10  5600  			nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
18998c381b19bf Eliad Peller              2014-09-10  5601  		switch (params.smps_mode) {
18998c381b19bf Eliad Peller              2014-09-10  5602  		case NL80211_SMPS_OFF:
18998c381b19bf Eliad Peller              2014-09-10  5603  			break;
18998c381b19bf Eliad Peller              2014-09-10  5604  		case NL80211_SMPS_STATIC:
18998c381b19bf Eliad Peller              2014-09-10  5605  			if (!(rdev->wiphy.features &
1a41c96851bfa3 John Crispin              2021-03-08  5606  			      NL80211_FEATURE_STATIC_SMPS)) {
1a41c96851bfa3 John Crispin              2021-03-08  5607  				err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5608  				goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5609  			}
18998c381b19bf Eliad Peller              2014-09-10  5610  			break;
18998c381b19bf Eliad Peller              2014-09-10  5611  		case NL80211_SMPS_DYNAMIC:
18998c381b19bf Eliad Peller              2014-09-10  5612  			if (!(rdev->wiphy.features &
1a41c96851bfa3 John Crispin              2021-03-08  5613  			      NL80211_FEATURE_DYNAMIC_SMPS)) {
1a41c96851bfa3 John Crispin              2021-03-08  5614  				err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5615  				goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5616  			}
18998c381b19bf Eliad Peller              2014-09-10  5617  			break;
18998c381b19bf Eliad Peller              2014-09-10  5618  		default:
1a41c96851bfa3 John Crispin              2021-03-08  5619  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5620  			goto out;
18998c381b19bf Eliad Peller              2014-09-10  5621  		}
18998c381b19bf Eliad Peller              2014-09-10  5622  	} else {
18998c381b19bf Eliad Peller              2014-09-10  5623  		params.smps_mode = NL80211_SMPS_OFF;
18998c381b19bf Eliad Peller              2014-09-10  5624  	}
18998c381b19bf Eliad Peller              2014-09-10  5625  
6e8ef842223b90 Purushottam Kushwaha      2016-07-05  5626  	params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
1a41c96851bfa3 John Crispin              2021-03-08  5627  	if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
1a41c96851bfa3 John Crispin              2021-03-08  5628  		err = -EOPNOTSUPP;
1a41c96851bfa3 John Crispin              2021-03-08  5629  		goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5630  	}
6e8ef842223b90 Purushottam Kushwaha      2016-07-05  5631  
4baf6bea37247e Ola Olsson                2015-10-29  5632  	if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
4baf6bea37247e Ola Olsson                2015-10-29  5633  		params.acl = parse_acl_data(&rdev->wiphy, info);
1a41c96851bfa3 John Crispin              2021-03-08  5634  		if (IS_ERR(params.acl)) {
1a41c96851bfa3 John Crispin              2021-03-08  5635  			err = PTR_ERR(params.acl);

params.acl is an error pointer.

1a41c96851bfa3 John Crispin              2021-03-08  5636  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5637  		}
4baf6bea37247e Ola Olsson                2015-10-29  5638  	}
4baf6bea37247e Ola Olsson                2015-10-29  5639  
a0de1ca383c77a John Crispin              2019-05-28  5640  	params.twt_responder =
a0de1ca383c77a John Crispin              2019-05-28  5641  		    nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
a0de1ca383c77a John Crispin              2019-05-28  5642  
796e90f42b7e52 John Crispin              2019-07-30  5643  	if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
796e90f42b7e52 John Crispin              2019-07-30  5644  		err = nl80211_parse_he_obss_pd(
796e90f42b7e52 John Crispin              2019-07-30  5645  					info->attrs[NL80211_ATTR_HE_OBSS_PD],
796e90f42b7e52 John Crispin              2019-07-30  5646  					&params.he_obss_pd);
bc7a39b4272b96 Luca Coelho               2020-06-26  5647  		if (err)
9951ebfcdf2b97 Johannes Berg             2020-02-21  5648  			goto out;
796e90f42b7e52 John Crispin              2019-07-30  5649  	}
796e90f42b7e52 John Crispin              2019-07-30  5650  
5c5e52d1bb9625 John Crispin              2019-12-17  5651  	if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
5c5e52d1bb9625 John Crispin              2019-12-17  5652  		err = nl80211_parse_he_bss_color(
5c5e52d1bb9625 John Crispin              2019-12-17  5653  					info->attrs[NL80211_ATTR_HE_BSS_COLOR],
5c5e52d1bb9625 John Crispin              2019-12-17  5654  					&params.he_bss_color);
5c5e52d1bb9625 John Crispin              2019-12-17  5655  		if (err)
60a0121f8fa64b Luca Coelho               2020-06-26  5656  			goto out;
5c5e52d1bb9625 John Crispin              2019-12-17  5657  	}
5c5e52d1bb9625 John Crispin              2019-12-17  5658  
291c49ded2fda1 Aloka Dixit               2020-09-11  5659  	if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
291c49ded2fda1 Aloka Dixit               2020-09-11  5660  		err = nl80211_parse_fils_discovery(rdev,
291c49ded2fda1 Aloka Dixit               2020-09-11  5661  						   info->attrs[NL80211_ATTR_FILS_DISCOVERY],
291c49ded2fda1 Aloka Dixit               2020-09-11  5662  						   &params);
291c49ded2fda1 Aloka Dixit               2020-09-11  5663  		if (err)
291c49ded2fda1 Aloka Dixit               2020-09-11  5664  			goto out;
291c49ded2fda1 Aloka Dixit               2020-09-11  5665  	}
291c49ded2fda1 Aloka Dixit               2020-09-11  5666  
7443dcd1f1718a Aloka Dixit               2020-09-11  5667  	if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
7443dcd1f1718a Aloka Dixit               2020-09-11  5668  		err = nl80211_parse_unsol_bcast_probe_resp(
7443dcd1f1718a Aloka Dixit               2020-09-11  5669  			rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
7443dcd1f1718a Aloka Dixit               2020-09-11  5670  			&params);
7443dcd1f1718a Aloka Dixit               2020-09-11  5671  		if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5672  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5673  	}
1a41c96851bfa3 John Crispin              2021-03-08  5674  
1a41c96851bfa3 John Crispin              2021-03-08  5675  	if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_CONFIG]) {
1a41c96851bfa3 John Crispin              2021-03-08  5676  		err = nl80211_parse_multiple_bssid_config(
1a41c96851bfa3 John Crispin              2021-03-08  5677  			&rdev->wiphy,
1a41c96851bfa3 John Crispin              2021-03-08  5678  			info->attrs[NL80211_ATTR_MULTIPLE_BSSID_CONFIG],
1a41c96851bfa3 John Crispin              2021-03-08  5679  			&params);
1a41c96851bfa3 John Crispin              2021-03-08  5680  		if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5681  			goto out;
7443dcd1f1718a Aloka Dixit               2020-09-11  5682  	}
7443dcd1f1718a Aloka Dixit               2020-09-11  5683  
66cd794e3c30b8 Johannes Berg             2017-02-07  5684  	nl80211_calculate_ap_params(&params);
66cd794e3c30b8 Johannes Berg             2017-02-07  5685  
fe4943702c850f Srinivas Dasari           2019-01-23  5686  	if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
fe4943702c850f Srinivas Dasari           2019-01-23  5687  		params.flags |= AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
fe4943702c850f Srinivas Dasari           2019-01-23  5688  
c56589ed1d25ae Simon Wunderlich          2013-11-21  5689  	wdev_lock(wdev);
e35e4d28b687d4 Hila Gonen                2012-06-27  5690  	err = rdev_start_ap(rdev, dev, &params);
46c1dd0c7fac54 Felix Fietkau             2012-06-19  5691  	if (!err) {
683b6d3b31a519 Johannes Berg             2012-11-08  5692  		wdev->preset_chandef = params.chandef;
8860020e0be1f0 Johannes Berg             2012-02-13  5693  		wdev->beacon_interval = params.beacon_interval;
9e0e29615a2077 Michal Kazior             2014-01-29  5694  		wdev->chandef = params.chandef;
06e191e22eb99c Antonio Quartulli         2012-11-07  5695  		wdev->ssid_len = params.ssid_len;
06e191e22eb99c Antonio Quartulli         2012-11-07  5696  		memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
466a306142c002 Denis Kenzior             2018-03-26  5697  
466a306142c002 Denis Kenzior             2018-03-26  5698  		if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
466a306142c002 Denis Kenzior             2018-03-26  5699  			wdev->conn_owner_nlportid = info->snd_portid;
46c1dd0c7fac54 Felix Fietkau             2012-06-19  5700  	}
c56589ed1d25ae Simon Wunderlich          2013-11-21  5701  	wdev_unlock(wdev);
77765eaf5cfb6b Vasanthakumar Thiagarajan 2013-01-18  5702  
9951ebfcdf2b97 Johannes Berg             2020-02-21  5703  out:
77765eaf5cfb6b Vasanthakumar Thiagarajan 2013-01-18 @5704  	kfree(params.acl);
                                                                      ^^^^^^^^^^
Dereferencing potential error pointer.  Freeing resources that weren't
allocated is one of the classic bugs with "out:" labels that free
everything.

1a41c96851bfa3 John Crispin              2021-03-08  5705  	kfree(params.beacon.multiple_bssid);
8860020e0be1f0 Johannes Berg             2012-02-13  5706  	return err;
ed1b6cc7f80f83 Johannes Berg             2007-12-19  5707  }

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 911fae42b0c0..565a1356095f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -485,6 +485,21 @@  struct ieee80211_supported_band {
 	const struct ieee80211_sband_iftype_data *iftype_data;
 };
 
+/**
+ * struct cfg80211_multiple_bssid - AP settings for multi bssid
+ *
+ * @index: the index of this AP in the multi bssid group.
+ * @count: the total number of multi bssid peer APs.
+ * @parent: non-transmitted BSSs transmitted parents index
+ * @ema: Shall the beacons be sent out in EMA mode.
+ */
+struct cfg80211_multiple_bssid {
+	u8 index;
+	u8 count;
+	u32 parent;
+	bool ema;
+};
+
 /**
  * ieee80211_get_sband_iftype_data - return sband data for a given iftype
  * @sband: the sband to search for the STA on
@@ -1032,6 +1047,23 @@  struct cfg80211_crypto_settings {
 	enum nl80211_sae_pwe_mechanism sae_pwe;
 };
 
+/**
+ * struct cfg80211_multiple_bssid_data - Multiple BSSID elements
+ *
+ * @cnt: Number of elements in array %elems.
+ *
+ * @elems: Array of multiple BSSID element(s) to be added into Beacon frames.
+ * @elems.data: Data for multiple BSSID elements.
+ * @elems.len: Length of data.
+ */
+struct cfg80211_multiple_bssid_data {
+	u8 cnt;
+	struct {
+		u8 *data;
+		size_t len;
+	} elems[];
+};
+
 /**
  * struct cfg80211_beacon_data - beacon data
  * @head: head portion of beacon (before TIM IE)
@@ -1058,6 +1090,7 @@  struct cfg80211_crypto_settings {
  *	Token (measurement type 11)
  * @lci_len: LCI data length
  * @civicloc_len: Civic location data length
+ * @multiple_bssid: multiple_bssid elements
  */
 struct cfg80211_beacon_data {
 	const u8 *head, *tail;
@@ -1076,6 +1109,8 @@  struct cfg80211_beacon_data {
 	size_t probe_resp_len;
 	size_t lci_len;
 	size_t civicloc_len;
+
+	struct cfg80211_multiple_bssid_data *multiple_bssid;
 };
 
 struct mac_address {
@@ -1181,6 +1216,7 @@  enum cfg80211_ap_settings_flags {
  * @he_oper: HE operation IE (or %NULL if HE isn't enabled)
  * @fils_discovery: FILS discovery transmission parameters
  * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters
+ * @multiple_bssid: AP settings for multiple bssid.
  */
 struct cfg80211_ap_settings {
 	struct cfg80211_chan_def chandef;
@@ -1213,6 +1249,7 @@  struct cfg80211_ap_settings {
 	struct cfg80211_he_bss_color he_bss_color;
 	struct cfg80211_fils_discovery fils_discovery;
 	struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
+	struct cfg80211_multiple_bssid multiple_bssid;
 };
 
 /**
@@ -4941,6 +4978,11 @@  struct wiphy_iftype_akm_suites {
  *	configuration through the %NL80211_TID_CONFIG_ATTR_RETRY_SHORT and
  *	%NL80211_TID_CONFIG_ATTR_RETRY_LONG attributes
  * @sar_capa: SAR control capabilities
+ *
+ * @multiple_bssid: Describes device's multiple BSSID config support
+ * @multiple_bssid.max_num_vaps: Maximum number of VAPS supported by the driver
+ * @multiple_bssid.max_num_elems: Maximum number of multiple BSSID elements
+ *	supported by the driver
  */
 struct wiphy {
 	struct mutex mtx;
@@ -5083,6 +5125,11 @@  struct wiphy {
 
 	const struct cfg80211_sar_capa *sar_capa;
 
+	struct {
+		u8 max_num_vaps;
+		u8 max_profile_periodicity;
+	} multiple_bssid;
+
 	char priv[] __aligned(NETDEV_ALIGN);
 };
 
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index ac78da99fccd..c40e6789d142 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2557,6 +2557,19 @@  enum nl80211_commands {
  *	disassoc events to indicate that an immediate reconnect to the AP
  *	is desired.
  *
+ * @NL80211_ATTR_MULTIPLE_BSSID_CONFIG: Optional parameter to configure
+ *	multiple BSSID and enhanced multi-BSSID advertisements.
+ *	This attribute is also used to advertise the maximum number of VAPs
+ *	supported by the driver to the application. It is a nested attribute,
+ *	see &enum nl80211_multiple_bssid_config_attributes.
+ *
+ * @NL80211_ATTR_MULTIPLE_BSSID_ELEMS: Optional parameter for multiple BSSID
+ *	elements data. This attribute is also used to advertise the maximum
+ *	profile periodicity supported by the driver to the application, if
+ *	enhanced multi-BSS advertisements (EMA) feature is enabled.
+ *	It is a nested attribute, see
+ *	&enum nl80211_multiple_bssid_elems_attributes.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3054,6 +3067,9 @@  enum nl80211_attrs {
 
 	NL80211_ATTR_DISABLE_HE,
 
+	NL80211_ATTR_MULTIPLE_BSSID_CONFIG,
+	NL80211_ATTR_MULTIPLE_BSSID_ELEMS,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -5937,6 +5953,11 @@  enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_BEACON_RATE_HE: Driver supports beacon rate
  *	configuration (AP/mesh) with HE rates.
  *
+ * @NL80211_EXT_FEATURE_MULTIPLE_BSSID: Driver/device supports multiple BSSID
+ *	advertisements.
+ * @NL80211_EXT_FEATURE_EMA_AP: Driver/device supports enhanced multiple BSSID
+ *	advertisements (EMA).
+ *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
@@ -5998,6 +6019,8 @@  enum nl80211_ext_feature_index {
 	NL80211_EXT_FEATURE_FILS_DISCOVERY,
 	NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP,
 	NL80211_EXT_FEATURE_BEACON_RATE_HE,
+	NL80211_EXT_FEATURE_MULTIPLE_BSSID_AP,
+	NL80211_EXT_FEATURE_EMA_AP,
 
 	/* add new features before the definition below */
 	NUM_NL80211_EXT_FEATURES,
@@ -7277,4 +7300,65 @@  enum nl80211_sar_specs_attrs {
 	NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1,
 };
 
+/**
+ * enum nl80211_multiple_bssid_config_attributes - Attributes to configure
+ *	multiple BSSID and enhanced multi-BSSID advertisements.
+ *
+ * @__NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INVALID: Invalid
+ *
+ * @NL80211_MULTIPLE_BSSID_CONFIG_ATTR_PARENT: For a non-transmitted BSSID, this
+ *	attribute provides the interface index (u32) of the transmitted profile
+ *	in the multiple BSSID set.
+ *
+ * @NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INDEX: The index of this BSS (u8) inside
+ *	multiple BSSID set.
+ *
+ * @NL80211_MULTIPLE_BSSID_CONFIG_ATTR_COUNT: Total number of BSSs (u8) in the
+ *	multiple BSSID set.
+ *
+ * @NL80211_MULTIPLE_BSSID_CONFIG_ATTR_EMA: Flag to indicate if enhanced multi-BSSID
+ *	advertisements (EMA) feature is enabled.
+ *	If set to 1, elements provided through attribute
+ *	%NL80211_ATTR_MULTIPLE_BSSID_ELEMS are split into multiple beacons.
+ *	Otherwise, all elements will be included in every beacon.
+ *
+ * @__NL80211_MULTIPLE_BSSID_CONFIG_ATTR_LAST: Internal
+ * @NL80211_MULTIPLE_BSSID_CONFIG_ATTR_MAX: highest attribute
+ */
+enum nl80211_multiple_bssid_config_attributes {
+	__NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INVALID,
+
+	NL80211_MULTIPLE_BSSID_CONFIG_ATTR_PARENT,
+	NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INDEX,
+	NL80211_MULTIPLE_BSSID_CONFIG_ATTR_COUNT,
+	NL80211_MULTIPLE_BSSID_CONFIG_ATTR_EMA,
+
+	/* keep last */
+	__NL80211_MULTIPLE_BSSID_CONFIG_ATTR_LAST,
+	NL80211_MULTIPLE_BSSID_CONFIG_ATTR_MAX =
+		__NL80211_MULTIPLE_BSSID_CONFIG_ATTR_LAST - 1,
+};
+
+/**
+ * enum nl80211_multiple_bssid_elems_attributes - Attributes used to pass
+ *	multiple BSSID elements data.
+ *
+ * @__NL80211_MULTIPLE_BSSID_ELEMS_ATTR_INVALID: Invalid
+ *
+ * @NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT: Number of multiple BSSID
+ *	elements (u8).
+ *
+ * @NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA: Array of multiple BSSID elements.
+ */
+enum nl80211_multiple_bssid_elems_attributes {
+	__NL80211_MULTIPLE_BSSID_ELEMS_ATTR_INVALID,
+
+	NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT,
+	NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA,
+
+	__NL80211_MULTIPLE_BSSID_ELEMS_ATTR_LAST,
+	NL80211_MULTIPLE_BSSID_ELEMS_ATTR_MAX =
+		__NL80211_MULTIPLE_BSSID_ELEMS_ATTR_LAST - 1,
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 521d36bb0803..06f7e314b161 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -431,6 +431,20 @@  sar_policy[NL80211_SAR_ATTR_MAX + 1] = {
 	[NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy),
 };
 
+static const struct nla_policy
+nl80211_multiple_bssid_elems_policy[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_MAX + 1] = {
+	[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT] = { .type = NLA_U8 },
+	[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA] = { .type = NLA_NESTED },
+};
+
+static const struct nla_policy
+nl80211_multiple_bssid_policy[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_MAX + 1] = {
+	[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_PARENT] = { .type = NLA_U32 },
+	[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INDEX] = { .type = NLA_U8 },
+	[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_COUNT] = { .type = NLA_U8 },
+	[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_EMA] = { .type = NLA_FLAG },
+};
+
 static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 	[0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
 	[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
@@ -753,6 +767,10 @@  static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 	[NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
 	[NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
 	[NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
+	[NL80211_ATTR_MULTIPLE_BSSID_CONFIG] =
+			NLA_POLICY_NESTED(nl80211_multiple_bssid_policy),
+	[NL80211_ATTR_MULTIPLE_BSSID_ELEMS] =
+			NLA_POLICY_NESTED(nl80211_multiple_bssid_elems_policy),
 };
 
 /* policy for the key attributes */
@@ -2192,6 +2210,49 @@  nl80211_put_sar_specs(struct cfg80211_registered_device *rdev,
 	return -ENOBUFS;
 }
 
+static int
+nl80211_put_multiple_bssid_support(struct wiphy *wiphy, struct sk_buff *msg)
+{
+	struct nlattr *config = NULL, *elems = NULL;
+
+	if (!wiphy_ext_feature_isset(wiphy,
+				     NL80211_EXT_FEATURE_MULTIPLE_BSSID_AP))
+		return 0;
+
+	if (wiphy->multiple_bssid.max_num_vaps) {
+		config = nla_nest_start(msg,
+					NL80211_ATTR_MULTIPLE_BSSID_CONFIG);
+		if (!config)
+			return -ENOSPC;
+
+		if (nla_put_u8(msg, NL80211_MULTIPLE_BSSID_CONFIG_ATTR_COUNT,
+			       wiphy->multiple_bssid.max_num_vaps))
+			goto fail_config;
+
+		nla_nest_end(msg, config);
+	}
+
+	if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_EMA_AP) &&
+	    wiphy->multiple_bssid.max_profile_periodicity) {
+		elems = nla_nest_start(msg, NL80211_ATTR_MULTIPLE_BSSID_ELEMS);
+		if (!elems)
+			goto fail_config;
+
+		if (nla_put_u8(msg, NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT,
+			       wiphy->multiple_bssid.max_profile_periodicity))
+			goto fail_elems;
+
+		nla_nest_end(msg, elems);
+	}
+	return 0;
+
+fail_elems:
+	nla_nest_cancel(msg, elems);
+fail_config:
+	nla_nest_cancel(msg, config);
+	return -ENOBUFS;
+}
+
 struct nl80211_dump_wiphy_state {
 	s64 filter_wiphy;
 	long start;
@@ -2774,6 +2835,9 @@  static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
 		if (nl80211_put_sar_specs(rdev, msg))
 			goto nla_put_failure;
 
+		if (nl80211_put_multiple_bssid_support(&rdev->wiphy, msg))
+			goto nla_put_failure;
+
 		/* done */
 		state->split_start = 0;
 		break;
@@ -4952,6 +5016,90 @@  static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
 	return 0;
 }
 
+static int
+nl80211_parse_multiple_bssid_config(struct wiphy *wiphy,
+				    struct nlattr *attrs,
+				    struct cfg80211_ap_settings *params)
+{
+	struct nlattr *tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_MAX + 1];
+	int ret;
+	struct cfg80211_multiple_bssid *config = &params->multiple_bssid;
+
+	if (!wiphy_ext_feature_isset(wiphy,
+				     NL80211_EXT_FEATURE_MULTIPLE_BSSID_AP))
+		return -EINVAL;
+
+	ret = nla_parse_nested(tb, NL80211_MULTIPLE_BSSID_CONFIG_ATTR_MAX, attrs, NULL,
+			       NULL);
+	if (ret)
+		return ret;
+
+	config->ema = nla_get_flag(tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_EMA]);
+	if (config->ema &&
+	    (!wiphy_ext_feature_isset(wiphy,
+				      NL80211_EXT_FEATURE_EMA_AP) ||
+	     (wiphy->multiple_bssid.max_profile_periodicity &&
+	      params->beacon.multiple_bssid->cnt >
+	      wiphy->multiple_bssid.max_profile_periodicity)))
+		return -EINVAL;
+
+	if (!tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_COUNT])
+		return -EINVAL;
+
+	config->count = nla_get_u8(tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_COUNT]);
+	if (config->count < 1 ||
+	    (wiphy->multiple_bssid.max_num_vaps &&
+	     config->count > wiphy->multiple_bssid.max_num_vaps))
+		return -EINVAL;
+
+	if (tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_PARENT])
+		config->parent = nla_get_u32(tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_PARENT]);
+
+	if (tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INDEX])
+		config->index = nla_get_u8(tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INDEX]);
+
+	return 0;
+}
+
+static struct cfg80211_multiple_bssid_data *
+nl80211_parse_multiple_bssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
+{
+	struct cfg80211_multiple_bssid_data *multiple_bssid;
+	struct nlattr *nl_ie;
+	struct nlattr *tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_MAX + 1];
+	int rem_ie;
+	u8 i = 0, err, num_elems;
+
+	if (!wiphy_ext_feature_isset(wiphy,
+				     NL80211_EXT_FEATURE_MULTIPLE_BSSID_AP))
+		return NULL;
+
+	err = nla_parse_nested(tb, NL80211_MULTIPLE_BSSID_ELEMS_ATTR_MAX,
+			       attrs, NULL, NULL);
+	if (err)
+		return NULL;
+
+	if (!tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT] ||
+	    !tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA])
+		return NULL;
+
+	num_elems = nla_get_u8(tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT]);
+	multiple_bssid = kzalloc(struct_size(multiple_bssid, elems, num_elems),
+				 GFP_KERNEL);
+	if (!multiple_bssid)
+		return NULL;
+
+	multiple_bssid->cnt = num_elems;
+	nla_for_each_nested(nl_ie, tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA],
+			    rem_ie) {
+		multiple_bssid->elems[i].data = nla_data(nl_ie);
+		multiple_bssid->elems[i].len = nla_len(nl_ie);
+		i++;
+	}
+
+	return multiple_bssid;
+}
+
 static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
 				struct nlattr *attrs[],
 				struct cfg80211_beacon_data *bcn)
@@ -5032,6 +5180,14 @@  static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
 		bcn->ftm_responder = -1;
 	}
 
+	if (attrs[NL80211_ATTR_MULTIPLE_BSSID_ELEMS]) {
+		bcn->multiple_bssid = nl80211_parse_multiple_bssid_elems(
+				&rdev->wiphy,
+				attrs[NL80211_ATTR_MULTIPLE_BSSID_ELEMS]);
+		if (!bcn->multiple_bssid)
+			return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -5317,7 +5473,7 @@  static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 
 	err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon);
 	if (err)
-		return err;
+		goto out;
 
 	params.beacon_interval =
 		nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
@@ -5327,7 +5483,7 @@  static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 	err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
 					   params.beacon_interval);
 	if (err)
-		return err;
+		goto out;
 
 	/*
 	 * In theory, some of these attributes should be required here
@@ -5340,8 +5496,10 @@  static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 		params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
 		params.ssid_len =
 			nla_len(info->attrs[NL80211_ATTR_SSID]);
-		if (params.ssid_len == 0)
-			return -EINVAL;
+		if (params.ssid_len == 0) {
+			err = -EINVAL;
+			goto out;
+		}
 	}
 
 	if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
@@ -5354,57 +5512,74 @@  static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 		params.auth_type = nla_get_u32(
 			info->attrs[NL80211_ATTR_AUTH_TYPE]);
 		if (!nl80211_valid_auth_type(rdev, params.auth_type,
-					     NL80211_CMD_START_AP))
-			return -EINVAL;
+					     NL80211_CMD_START_AP)) {
+			err = -EINVAL;
+			goto out;
+		}
 	} else
 		params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
 
 	err = nl80211_crypto_settings(rdev, info, &params.crypto,
 				      NL80211_MAX_NR_CIPHER_SUITES);
 	if (err)
-		return err;
+		goto out;
 
 	if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
-		if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER))
-			return -EOPNOTSUPP;
+		if (!(rdev->wiphy.features &
+		      NL80211_FEATURE_INACTIVITY_TIMER)) {
+			err = -EOPNOTSUPP;
+			goto out;
+		}
 		params.inactivity_timeout = nla_get_u16(
 			info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
 	}
 
 	if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
-		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
-			return -EINVAL;
+		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
+			err = -EINVAL;
+			goto out;
+		}
 		params.p2p_ctwindow =
 			nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
 		if (params.p2p_ctwindow != 0 &&
-		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
-			return -EINVAL;
+		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) {
+			err = -EINVAL;
+			goto out;
+		}
 	}
 
 	if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
 		u8 tmp;
 
-		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
-			return -EINVAL;
+		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
+			err = -EINVAL;
+			goto out;
+		}
 		tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
 		params.p2p_opp_ps = tmp;
 		if (params.p2p_opp_ps != 0 &&
-		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
-			return -EINVAL;
+		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) {
+			err = -EINVAL;
+			goto out;
+		}
 	}
 
 	if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
 		err = nl80211_parse_chandef(rdev, info, &params.chandef);
 		if (err)
-			return err;
+			goto out;
 	} else if (wdev->preset_chandef.chan) {
 		params.chandef = wdev->preset_chandef;
-	} else if (!nl80211_get_ap_channel(rdev, &params))
-		return -EINVAL;
+	} else if (!nl80211_get_ap_channel(rdev, &params)) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
-					   wdev->iftype))
-		return -EINVAL;
+					   wdev->iftype)) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	if (info->attrs[NL80211_ATTR_TX_RATES]) {
 		err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
@@ -5412,12 +5587,12 @@  static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 						    &params.beacon_rate,
 						    dev, false);
 		if (err)
-			return err;
+			goto out;
 
 		err = validate_beacon_tx_rate(rdev, params.chandef.chan->band,
 					      &params.beacon_rate);
 		if (err)
-			return err;
+			goto out;
 	}
 
 	if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
@@ -5428,29 +5603,38 @@  static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 			break;
 		case NL80211_SMPS_STATIC:
 			if (!(rdev->wiphy.features &
-			      NL80211_FEATURE_STATIC_SMPS))
-				return -EINVAL;
+			      NL80211_FEATURE_STATIC_SMPS)) {
+				err = -EINVAL;
+				goto out;
+			}
 			break;
 		case NL80211_SMPS_DYNAMIC:
 			if (!(rdev->wiphy.features &
-			      NL80211_FEATURE_DYNAMIC_SMPS))
-				return -EINVAL;
+			      NL80211_FEATURE_DYNAMIC_SMPS)) {
+				err = -EINVAL;
+				goto out;
+			}
 			break;
 		default:
-			return -EINVAL;
+			err = -EINVAL;
+			goto out;
 		}
 	} else {
 		params.smps_mode = NL80211_SMPS_OFF;
 	}
 
 	params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
-	if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ])
-		return -EOPNOTSUPP;
+	if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
 
 	if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
 		params.acl = parse_acl_data(&rdev->wiphy, info);
-		if (IS_ERR(params.acl))
-			return PTR_ERR(params.acl);
+		if (IS_ERR(params.acl)) {
+			err = PTR_ERR(params.acl);
+			goto out;
+		}
 	}
 
 	params.twt_responder =
@@ -5485,7 +5669,16 @@  static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 			rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
 			&params);
 		if (err)
-			return err;
+			goto out;
+	}
+
+	if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_CONFIG]) {
+		err = nl80211_parse_multiple_bssid_config(
+			&rdev->wiphy,
+			info->attrs[NL80211_ATTR_MULTIPLE_BSSID_CONFIG],
+			&params);
+		if (err)
+			goto out;
 	}
 
 	nl80211_calculate_ap_params(&params);
@@ -5509,7 +5702,7 @@  static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 
 out:
 	kfree(params.acl);
-
+	kfree(params.beacon.multiple_bssid);
 	return err;
 }
 
@@ -5533,12 +5726,14 @@  static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
 
 	err = nl80211_parse_beacon(rdev, info->attrs, &params);
 	if (err)
-		return err;
+		goto out;
 
 	wdev_lock(wdev);
 	err = rdev_change_beacon(rdev, dev, &params);
 	wdev_unlock(wdev);
 
+out:
+	kfree(params.multiple_bssid);
 	return err;
 }
 
@@ -9218,12 +9413,14 @@  static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
 
 	err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after);
 	if (err)
-		return err;
+		goto free;
 
 	csa_attrs = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*csa_attrs),
 			    GFP_KERNEL);
-	if (!csa_attrs)
-		return -ENOMEM;
+	if (!csa_attrs) {
+		err = -ENOMEM;
+		goto free;
+	}
 
 	err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
 					  info->attrs[NL80211_ATTR_CSA_IES],
@@ -9341,6 +9538,8 @@  static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
 	wdev_unlock(wdev);
 
 free:
+	kfree(params.beacon_after.multiple_bssid);
+	kfree(params.beacon_csa.multiple_bssid);
 	kfree(csa_attrs);
 	return err;
 }