|
|
@@ -0,0 +1,493 @@
|
|
|
+From: John Crispin <[email protected]>
|
|
|
+Date: Wed, 15 Sep 2021 19:54:34 -0700
|
|
|
+Subject: [PATCH] nl80211: MBSSID and EMA support in AP mode
|
|
|
+
|
|
|
+Add new attributes to configure support for multiple BSSID
|
|
|
+and advanced multi-BSSID advertisements (EMA) in AP mode.
|
|
|
+
|
|
|
+- NL80211_ATTR_MBSSID_CONFIG used for per interface configuration.
|
|
|
+- NL80211_ATTR_MBSSID_ELEMS used to MBSSID elements for beacons.
|
|
|
+
|
|
|
+Memory for the elements is allocated dynamically. This change frees
|
|
|
+the memory in existing functions which call nl80211_parse_beacon(),
|
|
|
+a comment is added to indicate the new references to do the same.
|
|
|
+
|
|
|
+Signed-off-by: John Crispin <[email protected]>
|
|
|
+Co-developed-by: Aloka Dixit <[email protected]>
|
|
|
+Signed-off-by: Aloka Dixit <[email protected]>
|
|
|
+Link: https://lore.kernel.org/r/[email protected]
|
|
|
+[don't leave ERR_PTR hanging around]
|
|
|
+Signed-off-by: Johannes Berg <[email protected]>
|
|
|
+---
|
|
|
+
|
|
|
+--- a/include/net/cfg80211.h
|
|
|
++++ b/include/net/cfg80211.h
|
|
|
+@@ -1046,6 +1046,36 @@ struct cfg80211_crypto_settings {
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
++ * struct cfg80211_mbssid_config - AP settings for multi bssid
|
|
|
++ *
|
|
|
++ * @tx_wdev: pointer to the transmitted interface in the MBSSID set
|
|
|
++ * @index: index of this AP in the multi bssid group.
|
|
|
++ * @ema: set to true if the beacons should be sent out in EMA mode.
|
|
|
++ */
|
|
|
++struct cfg80211_mbssid_config {
|
|
|
++ struct wireless_dev *tx_wdev;
|
|
|
++ u8 index;
|
|
|
++ bool ema;
|
|
|
++};
|
|
|
++
|
|
|
++/**
|
|
|
++ * struct cfg80211_mbssid_elems - Multiple BSSID elements
|
|
|
++ *
|
|
|
++ * @cnt: Number of elements in array %elems.
|
|
|
++ *
|
|
|
++ * @elem: Array of multiple BSSID element(s) to be added into Beacon frames.
|
|
|
++ * @elem.data: Data for multiple BSSID elements.
|
|
|
++ * @elem.len: Length of data.
|
|
|
++ */
|
|
|
++struct cfg80211_mbssid_elems {
|
|
|
++ u8 cnt;
|
|
|
++ struct {
|
|
|
++ const u8 *data;
|
|
|
++ size_t len;
|
|
|
++ } elem[];
|
|
|
++};
|
|
|
++
|
|
|
++/**
|
|
|
+ * struct cfg80211_beacon_data - beacon data
|
|
|
+ * @head: head portion of beacon (before TIM IE)
|
|
|
+ * or %NULL if not changed
|
|
|
+@@ -1063,6 +1093,7 @@ struct cfg80211_crypto_settings {
|
|
|
+ * @assocresp_ies_len: length of assocresp_ies in octets
|
|
|
+ * @probe_resp_len: length of probe response template (@probe_resp)
|
|
|
+ * @probe_resp: probe response template (AP mode only)
|
|
|
++ * @mbssid_ies: multiple BSSID elements
|
|
|
+ * @ftm_responder: enable FTM responder functionality; -1 for no change
|
|
|
+ * (which also implies no change in LCI/civic location data)
|
|
|
+ * @lci: Measurement Report element content, starting with Measurement Token
|
|
|
+@@ -1080,6 +1111,7 @@ struct cfg80211_beacon_data {
|
|
|
+ const u8 *probe_resp;
|
|
|
+ const u8 *lci;
|
|
|
+ const u8 *civicloc;
|
|
|
++ struct cfg80211_mbssid_elems *mbssid_ies;
|
|
|
+ s8 ftm_responder;
|
|
|
+
|
|
|
+ size_t head_len, tail_len;
|
|
|
+@@ -1194,6 +1226,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
|
|
|
++ * @mbssid_config: AP settings for multiple bssid
|
|
|
+ */
|
|
|
+ struct cfg80211_ap_settings {
|
|
|
+ struct cfg80211_chan_def chandef;
|
|
|
+@@ -1226,6 +1259,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_mbssid_config mbssid_config;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+@@ -4986,6 +5020,13 @@ struct wiphy_iftype_akm_suites {
|
|
|
+ * %NL80211_TID_CONFIG_ATTR_RETRY_LONG attributes
|
|
|
+ * @sar_capa: SAR control capabilities
|
|
|
+ * @rfkill: a pointer to the rfkill structure
|
|
|
++ *
|
|
|
++ * @mbssid_max_interfaces: maximum number of interfaces supported by the driver
|
|
|
++ * in a multiple BSSID set. This field must be set to a non-zero value
|
|
|
++ * by the driver to advertise MBSSID support.
|
|
|
++ * @mbssid_max_ema_profile_periodicity: maximum profile periodicity supported by
|
|
|
++ * the driver. Setting this field to a non-zero value indicates that the
|
|
|
++ * driver supports enhanced multi-BSSID advertisements (EMA AP).
|
|
|
+ */
|
|
|
+ struct wiphy {
|
|
|
+ struct mutex mtx;
|
|
|
+@@ -5133,6 +5174,9 @@ struct wiphy {
|
|
|
+
|
|
|
+ struct rfkill *rfkill;
|
|
|
+
|
|
|
++ u8 mbssid_max_interfaces;
|
|
|
++ u8 ema_max_profile_periodicity;
|
|
|
++
|
|
|
+ char priv[] __aligned(NETDEV_ALIGN);
|
|
|
+ };
|
|
|
+
|
|
|
+--- a/include/uapi/linux/nl80211.h
|
|
|
++++ b/include/uapi/linux/nl80211.h
|
|
|
+@@ -337,7 +337,10 @@
|
|
|
+ * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes
|
|
|
+ * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from
|
|
|
+ * userspace to request deletion of a virtual interface, then requires
|
|
|
+- * attribute %NL80211_ATTR_IFINDEX.
|
|
|
++ * attribute %NL80211_ATTR_IFINDEX. If multiple BSSID advertisements are
|
|
|
++ * enabled using %NL80211_ATTR_MBSSID_CONFIG, %NL80211_ATTR_MBSSID_ELEMS,
|
|
|
++ * and if this command is used for the transmitting interface, then all
|
|
|
++ * the non-transmitting interfaces are deleted as well.
|
|
|
+ *
|
|
|
+ * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified
|
|
|
+ * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC.
|
|
|
+@@ -2593,6 +2596,18 @@ enum nl80211_commands {
|
|
|
+ * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE
|
|
|
+ * information for the time while performing a color switch.
|
|
|
+ *
|
|
|
++ * @NL80211_ATTR_MBSSID_CONFIG: Nested attribute for multiple BSSID
|
|
|
++ * advertisements (MBSSID) parameters in AP mode.
|
|
|
++ * Kernel uses this attribute to indicate the driver's support for MBSSID
|
|
|
++ * and enhanced multi-BSSID advertisements (EMA AP) to the userspace.
|
|
|
++ * Userspace should use this attribute to configure per interface MBSSID
|
|
|
++ * parameters.
|
|
|
++ * See &enum nl80211_mbssid_config_attributes for details.
|
|
|
++ *
|
|
|
++ * @NL80211_ATTR_MBSSID_ELEMS: Nested parameter to pass multiple BSSID elements.
|
|
|
++ * Mandatory parameter for the transmitting interface to enable MBSSID.
|
|
|
++ * Optional for the non-transmitting interfaces.
|
|
|
++ *
|
|
|
+ * @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
|
|
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
|
|
|
+ * @__NL80211_ATTR_AFTER_LAST: internal use
|
|
|
+@@ -3096,6 +3111,9 @@ enum nl80211_attrs {
|
|
|
+ NL80211_ATTR_COLOR_CHANGE_COLOR,
|
|
|
+ NL80211_ATTR_COLOR_CHANGE_ELEMS,
|
|
|
+
|
|
|
++ NL80211_ATTR_MBSSID_CONFIG,
|
|
|
++ NL80211_ATTR_MBSSID_ELEMS,
|
|
|
++
|
|
|
+ /* add attributes here, update the policy in nl80211.c */
|
|
|
+
|
|
|
+ __NL80211_ATTR_AFTER_LAST,
|
|
|
+@@ -7349,4 +7367,60 @@ enum nl80211_sar_specs_attrs {
|
|
|
+ NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1,
|
|
|
+ };
|
|
|
+
|
|
|
++/**
|
|
|
++ * enum nl80211_mbssid_config_attributes - multiple BSSID (MBSSID) and enhanced
|
|
|
++ * multi-BSSID advertisements (EMA) in AP mode.
|
|
|
++ * Kernel uses some of these attributes to advertise driver's support for
|
|
|
++ * MBSSID and EMA.
|
|
|
++ * Remaining attributes should be used by the userspace to configure the
|
|
|
++ * features.
|
|
|
++ *
|
|
|
++ * @__NL80211_MBSSID_CONFIG_ATTR_INVALID: Invalid
|
|
|
++ *
|
|
|
++ * @NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES: Used by the kernel to advertise
|
|
|
++ * the maximum number of MBSSID interfaces supported by the driver.
|
|
|
++ * Driver should indicate MBSSID support by setting
|
|
|
++ * wiphy->mbssid_max_interfaces to a value more than or equal to 2.
|
|
|
++ *
|
|
|
++ * @NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY: Used by the kernel
|
|
|
++ * to advertise the maximum profile periodicity supported by the driver
|
|
|
++ * if EMA is enabled. Driver should indicate EMA support to the userspace
|
|
|
++ * by setting wiphy->mbssid_max_ema_profile_periodicity to
|
|
|
++ * a non-zero value.
|
|
|
++ *
|
|
|
++ * @NL80211_MBSSID_CONFIG_ATTR_INDEX: Mandatory parameter to pass the index of
|
|
|
++ * this BSS (u8) in the multiple BSSID set.
|
|
|
++ * Value must be set to 0 for the transmitting interface and non-zero for
|
|
|
++ * all non-transmitting interfaces. The userspace will be responsible
|
|
|
++ * for using unique indices for the interfaces.
|
|
|
++ * Range: 0 to wiphy->mbssid_max_interfaces-1.
|
|
|
++ *
|
|
|
++ * @NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX: Mandatory parameter for
|
|
|
++ * a non-transmitted profile which provides the interface index (u32) of
|
|
|
++ * the transmitted profile. The value must match one of the interface
|
|
|
++ * indices advertised by the kernel. Optional if the interface being set up
|
|
|
++ * is the transmitting one, however, if provided then the value must match
|
|
|
++ * the interface index of the same.
|
|
|
++ *
|
|
|
++ * @NL80211_MBSSID_CONFIG_ATTR_EMA: Flag used to enable EMA AP feature.
|
|
|
++ * Setting this flag is permitted only if the driver advertises EMA support
|
|
|
++ * by setting wiphy->mbssid_max_ema_profile_periodicity to non-zero.
|
|
|
++ *
|
|
|
++ * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal
|
|
|
++ * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute
|
|
|
++ */
|
|
|
++enum nl80211_mbssid_config_attributes {
|
|
|
++ __NL80211_MBSSID_CONFIG_ATTR_INVALID,
|
|
|
++
|
|
|
++ NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES,
|
|
|
++ NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY,
|
|
|
++ NL80211_MBSSID_CONFIG_ATTR_INDEX,
|
|
|
++ NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
|
|
|
++ NL80211_MBSSID_CONFIG_ATTR_EMA,
|
|
|
++
|
|
|
++ /* keep last */
|
|
|
++ __NL80211_MBSSID_CONFIG_ATTR_LAST,
|
|
|
++ NL80211_MBSSID_CONFIG_ATTR_MAX = __NL80211_MBSSID_CONFIG_ATTR_LAST - 1,
|
|
|
++};
|
|
|
++
|
|
|
+ #endif /* __LINUX_NL80211_H */
|
|
|
+--- a/net/wireless/nl80211.c
|
|
|
++++ b/net/wireless/nl80211.c
|
|
|
+@@ -439,6 +439,16 @@ sar_policy[NL80211_SAR_ATTR_MAX + 1] = {
|
|
|
+ [NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy),
|
|
|
+ };
|
|
|
+
|
|
|
++static const struct nla_policy
|
|
|
++nl80211_mbssid_config_policy[NL80211_MBSSID_CONFIG_ATTR_MAX + 1] = {
|
|
|
++ [NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES] = NLA_POLICY_MIN(NLA_U8, 2),
|
|
|
++ [NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY] =
|
|
|
++ NLA_POLICY_MIN(NLA_U8, 1),
|
|
|
++ [NL80211_MBSSID_CONFIG_ATTR_INDEX] = { .type = NLA_U8 },
|
|
|
++ [NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX] = { .type = NLA_U32 },
|
|
|
++ [NL80211_MBSSID_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 },
|
|
|
+@@ -780,6 +790,9 @@ static const struct nla_policy nl80211_p
|
|
|
+ [NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 },
|
|
|
+ [NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 },
|
|
|
+ [NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy),
|
|
|
++ [NL80211_ATTR_MBSSID_CONFIG] =
|
|
|
++ NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
|
|
|
++ [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
|
|
|
+ };
|
|
|
+
|
|
|
+ /* policy for the key attributes */
|
|
|
+@@ -2228,6 +2241,35 @@ fail:
|
|
|
+ return -ENOBUFS;
|
|
|
+ }
|
|
|
+
|
|
|
++static int nl80211_put_mbssid_support(struct wiphy *wiphy, struct sk_buff *msg)
|
|
|
++{
|
|
|
++ struct nlattr *config;
|
|
|
++
|
|
|
++ if (!wiphy->mbssid_max_interfaces)
|
|
|
++ return 0;
|
|
|
++
|
|
|
++ config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
|
|
|
++ if (!config)
|
|
|
++ return -ENOBUFS;
|
|
|
++
|
|
|
++ if (nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES,
|
|
|
++ wiphy->mbssid_max_interfaces))
|
|
|
++ goto fail;
|
|
|
++
|
|
|
++ if (wiphy->ema_max_profile_periodicity &&
|
|
|
++ nla_put_u8(msg,
|
|
|
++ NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY,
|
|
|
++ wiphy->ema_max_profile_periodicity))
|
|
|
++ goto fail;
|
|
|
++
|
|
|
++ nla_nest_end(msg, config);
|
|
|
++ return 0;
|
|
|
++
|
|
|
++fail:
|
|
|
++ nla_nest_cancel(msg, config);
|
|
|
++ return -ENOBUFS;
|
|
|
++}
|
|
|
++
|
|
|
+ struct nl80211_dump_wiphy_state {
|
|
|
+ s64 filter_wiphy;
|
|
|
+ long start;
|
|
|
+@@ -2813,6 +2855,9 @@ static int nl80211_send_wiphy(struct cfg
|
|
|
+ if (nl80211_put_sar_specs(rdev, msg))
|
|
|
+ goto nla_put_failure;
|
|
|
+
|
|
|
++ if (nl80211_put_mbssid_support(&rdev->wiphy, msg))
|
|
|
++ goto nla_put_failure;
|
|
|
++
|
|
|
+ /* done */
|
|
|
+ state->split_start = 0;
|
|
|
+ break;
|
|
|
+@@ -5002,6 +5047,96 @@ static int validate_beacon_tx_rate(struc
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
++static int nl80211_parse_mbssid_config(struct wiphy *wiphy,
|
|
|
++ struct net_device *dev,
|
|
|
++ struct nlattr *attrs,
|
|
|
++ struct cfg80211_mbssid_config *config,
|
|
|
++ u8 num_elems)
|
|
|
++{
|
|
|
++ struct nlattr *tb[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
|
|
|
++
|
|
|
++ if (!wiphy->mbssid_max_interfaces)
|
|
|
++ return -EOPNOTSUPP;
|
|
|
++
|
|
|
++ if (nla_parse_nested(tb, NL80211_MBSSID_CONFIG_ATTR_MAX, attrs, NULL,
|
|
|
++ NULL) ||
|
|
|
++ !tb[NL80211_MBSSID_CONFIG_ATTR_INDEX])
|
|
|
++ return -EINVAL;
|
|
|
++
|
|
|
++ config->ema = nla_get_flag(tb[NL80211_MBSSID_CONFIG_ATTR_EMA]);
|
|
|
++ if (config->ema) {
|
|
|
++ if (!wiphy->ema_max_profile_periodicity)
|
|
|
++ return -EOPNOTSUPP;
|
|
|
++
|
|
|
++ if (num_elems > wiphy->ema_max_profile_periodicity)
|
|
|
++ return -EINVAL;
|
|
|
++ }
|
|
|
++
|
|
|
++ config->index = nla_get_u8(tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]);
|
|
|
++ if (config->index >= wiphy->mbssid_max_interfaces ||
|
|
|
++ (!config->index && !num_elems))
|
|
|
++ return -EINVAL;
|
|
|
++
|
|
|
++ if (tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]) {
|
|
|
++ u32 tx_ifindex =
|
|
|
++ nla_get_u32(tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]);
|
|
|
++
|
|
|
++ if ((!config->index && tx_ifindex != dev->ifindex) ||
|
|
|
++ (config->index && tx_ifindex == dev->ifindex))
|
|
|
++ return -EINVAL;
|
|
|
++
|
|
|
++ if (tx_ifindex != dev->ifindex) {
|
|
|
++ struct net_device *tx_netdev =
|
|
|
++ dev_get_by_index(wiphy_net(wiphy), tx_ifindex);
|
|
|
++
|
|
|
++ if (!tx_netdev || !tx_netdev->ieee80211_ptr ||
|
|
|
++ tx_netdev->ieee80211_ptr->wiphy != wiphy ||
|
|
|
++ tx_netdev->ieee80211_ptr->iftype !=
|
|
|
++ NL80211_IFTYPE_AP) {
|
|
|
++ dev_put(tx_netdev);
|
|
|
++ return -EINVAL;
|
|
|
++ }
|
|
|
++
|
|
|
++ config->tx_wdev = tx_netdev->ieee80211_ptr;
|
|
|
++ } else {
|
|
|
++ config->tx_wdev = dev->ieee80211_ptr;
|
|
|
++ }
|
|
|
++ } else if (!config->index) {
|
|
|
++ config->tx_wdev = dev->ieee80211_ptr;
|
|
|
++ } else {
|
|
|
++ return -EINVAL;
|
|
|
++ }
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++static struct cfg80211_mbssid_elems *
|
|
|
++nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
|
|
|
++{
|
|
|
++ struct nlattr *nl_elems;
|
|
|
++ struct cfg80211_mbssid_elems *elems;
|
|
|
++ int rem_elems;
|
|
|
++ u8 i = 0, num_elems = 0;
|
|
|
++
|
|
|
++ if (!wiphy->mbssid_max_interfaces)
|
|
|
++ return ERR_PTR(-EINVAL);
|
|
|
++
|
|
|
++ nla_for_each_nested(nl_elems, attrs, rem_elems)
|
|
|
++ num_elems++;
|
|
|
++
|
|
|
++ elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL);
|
|
|
++ if (!elems)
|
|
|
++ return ERR_PTR(-ENOMEM);
|
|
|
++
|
|
|
++ nla_for_each_nested(nl_elems, attrs, rem_elems) {
|
|
|
++ elems->elem[i].data = nla_data(nl_elems);
|
|
|
++ elems->elem[i].len = nla_len(nl_elems);
|
|
|
++ i++;
|
|
|
++ }
|
|
|
++ elems->cnt = num_elems;
|
|
|
++ return elems;
|
|
|
++}
|
|
|
++
|
|
|
+ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
|
|
|
+ struct nlattr *attrs[],
|
|
|
+ struct cfg80211_beacon_data *bcn)
|
|
|
+@@ -5082,6 +5217,17 @@ static int nl80211_parse_beacon(struct c
|
|
|
+ bcn->ftm_responder = -1;
|
|
|
+ }
|
|
|
+
|
|
|
++ if (attrs[NL80211_ATTR_MBSSID_ELEMS]) {
|
|
|
++ struct cfg80211_mbssid_elems *mbssid =
|
|
|
++ nl80211_parse_mbssid_elems(&rdev->wiphy,
|
|
|
++ attrs[NL80211_ATTR_MBSSID_ELEMS]);
|
|
|
++
|
|
|
++ if (IS_ERR(mbssid))
|
|
|
++ return PTR_ERR(mbssid);
|
|
|
++
|
|
|
++ bcn->mbssid_ies = mbssid;
|
|
|
++ }
|
|
|
++
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -5538,6 +5684,17 @@ static int nl80211_start_ap(struct sk_bu
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
++ if (info->attrs[NL80211_ATTR_MBSSID_CONFIG]) {
|
|
|
++ err = nl80211_parse_mbssid_config(&rdev->wiphy, dev,
|
|
|
++ info->attrs[NL80211_ATTR_MBSSID_CONFIG],
|
|
|
++ ¶ms.mbssid_config,
|
|
|
++ params.beacon.mbssid_ies ?
|
|
|
++ params.beacon.mbssid_ies->cnt :
|
|
|
++ 0);
|
|
|
++ if (err)
|
|
|
++ goto out;
|
|
|
++ }
|
|
|
++
|
|
|
+ nl80211_calculate_ap_params(¶ms);
|
|
|
+
|
|
|
+ if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
|
|
|
+@@ -5559,6 +5716,11 @@ static int nl80211_start_ap(struct sk_bu
|
|
|
+
|
|
|
+ out:
|
|
|
+ kfree(params.acl);
|
|
|
++ kfree(params.beacon.mbssid_ies);
|
|
|
++ if (params.mbssid_config.tx_wdev &&
|
|
|
++ params.mbssid_config.tx_wdev->netdev &&
|
|
|
++ params.mbssid_config.tx_wdev->netdev != dev)
|
|
|
++ dev_put(params.mbssid_config.tx_wdev->netdev);
|
|
|
+
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+@@ -5583,12 +5745,14 @@ static int nl80211_set_beacon(struct sk_
|
|
|
+
|
|
|
+ err = nl80211_parse_beacon(rdev, info->attrs, ¶ms);
|
|
|
+ if (err)
|
|
|
+- return err;
|
|
|
++ goto out;
|
|
|
+
|
|
|
+ wdev_lock(wdev);
|
|
|
+ err = rdev_change_beacon(rdev, dev, ¶ms);
|
|
|
+ wdev_unlock(wdev);
|
|
|
+
|
|
|
++out:
|
|
|
++ kfree(params.mbssid_ies);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -9265,12 +9429,14 @@ static int nl80211_channel_switch(struct
|
|
|
+
|
|
|
+ err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.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],
|
|
|
+@@ -9389,6 +9555,8 @@ skip_beacons:
|
|
|
+ wdev_unlock(wdev);
|
|
|
+
|
|
|
+ free:
|
|
|
++ kfree(params.beacon_after.mbssid_ies);
|
|
|
++ kfree(params.beacon_csa.mbssid_ies);
|
|
|
+ kfree(csa_attrs);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+@@ -14924,6 +15092,8 @@ static int nl80211_color_change(struct s
|
|
|
+ wdev_unlock(wdev);
|
|
|
+
|
|
|
+ out:
|
|
|
++ kfree(params.beacon_next.mbssid_ies);
|
|
|
++ kfree(params.beacon_color_change.mbssid_ies);
|
|
|
+ kfree(tb);
|
|
|
+ return err;
|
|
|
+ }
|