---
include/net/cfg80211.h | 1 +
include/uapi/linux/nl80211.h | 1 +
net/wireless/core.h | 1 +
net/wireless/nl80211.c | 11 +++++++++++
net/wireless/sme.c | 7 +++++++
net/wireless/util.c | 11 +++++++++++
6 files changed, 32 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 5253e7f667bd..25eacbebfa29 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2553,6 +2553,7 @@ struct cfg80211_connect_params {
size_t fils_erp_rrk_len;
bool want_1x;
struct ieee80211_edmg edmg;
+ const u8 *mac_to_use;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 0ceb945a08fb..1bb4ce58da67 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2834,6 +2834,7 @@ enum nl80211_attrs {
NL80211_ATTR_WIPHY_EDMG_CHANNELS,
NL80211_ATTR_WIPHY_EDMG_BW_CONFIG,
+ NL80211_ATTR_MAC_TO_USE,
/* add attributes here, update the policy in nl80211.c */
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 77556c58d9ac..29e6ab2cf343 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -454,6 +454,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
struct vif_params *params);
void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
void cfg80211_process_wdev_events(struct wireless_dev *wdev);
+int cfg80211_set_mac_to_use(struct net_device *dev, const u8 *mac);
bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,
u32 center_freq_khz, u32 bw_khz);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4565d7385884..0202a762b5c8 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -591,6 +591,8 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
.len = SAE_PASSWORD_MAX_LEN },
[NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
[NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
+ [NL80211_ATTR_MAC_TO_USE] = { .type = NLA_EXACT_LEN_WARN,
+ .len = ETH_ALEN },
};
/* policy for the key attributes */
@@ -10045,6 +10047,15 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
}
+ if (info->attrs[NL80211_ATTR_MAC_TO_USE]) {
+ if (!wiphy_ext_feature_isset(wiphy,
+ NL80211_EXT_FEATURE_LIVE_ADDRESS_CHANGE))
+ return -EOPNOTSUPP;
+
+ connect.mac_to_use =
+ nla_data(info->attrs[NL80211_ATTR_MAC_TO_USE]);
+ }
+
wdev_lock(dev->ieee80211_ptr);
err = cfg80211_connect(rdev, dev, &connect, connkeys,
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 7a6c38ddc65a..f164af33655f 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -1242,11 +1242,18 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
wdev->conn_bss_type = connect->pbss ? IEEE80211_BSS_TYPE_PBSS :
IEEE80211_BSS_TYPE_ESS;
+ if (connect->mac_to_use) {
+ err = cfg80211_set_mac_to_use(dev, connect->mac_to_use);
+ if (err)
+ goto fail;
+ }
+
if (!rdev->ops->connect)
err = cfg80211_sme_connect(wdev, connect, prev_bssid);
else
err = rdev_connect(rdev, dev, connect);
+fail:
if (err) {
wdev->connect_keys = NULL;
/*
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 92cb2cbb179b..06700431cba0 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -2148,3 +2148,14 @@ bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype,
return false;
}
EXPORT_SYMBOL(cfg80211_iftype_allowed);
+
+int cfg80211_set_mac_to_use(struct net_device *dev, const u8 *mac)
+{
+ struct sockaddr sa;
+
+ sa.sa_family = dev->type;
+ memcpy(sa.sa_data, mac, ETH_ALEN);
+
+ return dev_set_mac_address(dev, &sa, NULL);
+}
+EXPORT_SYMBOL(cfg80211_set_mac_to_use);
--
2.17.1