wlan: Avoid duplicate macaddress configuration
Propogation from qcacld-3.0 to prima
Currently if the MAC is changed dynamically for any interface,
driver is allowing to configure a MAC which is already in use by
some other interface and it will allow different interfaces to
come up on same MAC address.
To address this issue add a check to configfure only different
MAC address.
Change-Id: Iece3bb063be30d5d983f4bec710d6d16b22bd2f9
CRs-Fixed: 2629343
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 29daf50..1728d3f 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -668,9 +668,10 @@
static int __hdd_hostapd_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *psta_mac_addr = addr;
- hdd_adapter_t *pAdapter;
+ hdd_adapter_t *pAdapter, *adapter_temp;
hdd_context_t *pHddCtx;
- int ret = 0;
+ int ret = 0, i;
+ v_MACADDR_t mac_addr;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
@@ -683,10 +684,49 @@
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
- {
return ret;
+
+
+ memcpy(&mac_addr, psta_mac_addr->sa_data, sizeof(mac_addr));
+ if(vos_is_macaddr_zero(&mac_addr)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "Zero Mac address");
+ return -EINVAL;
}
+
+ if (vos_is_macaddr_broadcast(&mac_addr)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"MAC is Broadcast");
+ return -EINVAL;
+ }
+
+ if (vos_is_macaddr_multicast(&mac_addr)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "Multicast Mac address");
+ return -EINVAL;
+ }
+
+
+ adapter_temp = hdd_get_adapter_by_macaddr(pHddCtx, mac_addr.bytes);
+ if (adapter_temp) {
+ if (!strcmp(adapter_temp->dev->name, dev->name))
+ return 0;
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: WLAN Mac Addr: "
+ MAC_ADDRESS_STR, __func__,
+ MAC_ADDR_ARRAY(mac_addr.bytes));
+ return -EINVAL;
+ }
+
+ for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++) {
+ if (!vos_mem_compare(&pAdapter->macAddressCurrent.bytes,
+ &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], VOS_MAC_ADDR_SIZE)) {
+ memcpy(&pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], mac_addr.bytes,
+ VOS_MAC_ADDR_SIZE);
+ break;
+ }
+ }
+
+ memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
+
EXIT();
return 0;
}
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index ccbd87c..3a3603d 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -8901,10 +8901,11 @@
static int __hdd_set_mac_address(struct net_device *dev, void *addr)
{
hdd_adapter_t *pAdapter;
+ hdd_adapter_t *adapter_temp;
hdd_context_t *pHddCtx;
struct sockaddr *psta_mac_addr = addr;
- eHalStatus halStatus = eHAL_STATUS_SUCCESS;
- int ret = 0;
+ int ret = 0, i;
+ v_MACADDR_t mac_addr;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
@@ -8917,15 +8918,47 @@
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
- {
return ret;
+
+ memcpy(&mac_addr, psta_mac_addr->sa_data, sizeof(mac_addr));
+ if(vos_is_macaddr_zero(&mac_addr)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "Zero Mac address");
+ return -EINVAL;
}
+ if (vos_is_macaddr_broadcast(&mac_addr)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,"MAC is Broadcast");
+ return -EINVAL;
+ }
+
+ if (vos_is_macaddr_multicast(&mac_addr)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "Multicast Mac address");
+ return -EINVAL;
+ }
+ adapter_temp = hdd_get_adapter_by_macaddr(pHddCtx, mac_addr.bytes);
+ if (adapter_temp) {
+ if (!strcmp(adapter_temp->dev->name, dev->name))
+ return 0;
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: WLAN Mac Addr: "
+ MAC_ADDRESS_STR, __func__,
+ MAC_ADDR_ARRAY(mac_addr.bytes));
+ return -EINVAL;
+ }
+
+ for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++) {
+ if (!vos_mem_compare(&pAdapter->macAddressCurrent.bytes,
+ &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], VOS_MAC_ADDR_SIZE)) {
+ memcpy(&pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], mac_addr.bytes,
+ VOS_MAC_ADDR_SIZE);
+ break;
+ }
+ }
memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
EXIT();
- return halStatus;
+ return 0;
}
/**---------------------------------------------------------------------------