(兩百一十六)Android Q WiFi p2p mac地址生成邏輯梳理

1.流程梳理

WifiP2pServiceImpl

                    case ENABLE_P2P:
                        if (!mIsWifiEnabled) {
                            Log.e(TAG, "Ignore P2P enable since wifi is " + mIsWifiEnabled);
                            break;
                        }
                        mInterfaceName = mWifiNative.setupInterface((String ifaceName) -> {
                            sendMessage(DISABLE_P2P);
                        }, getHandler());
                        if (mInterfaceName == null) {
                            Log.e(TAG, "Failed to setup interface for P2P");
                            break;
                        }
                        setupInterfaceFeatures(mInterfaceName);
                        try {
                            mNwService.setInterfaceUp(mInterfaceName);
                        } catch (RemoteException re) {
                            loge("Unable to change interface settings: " + re);
                        } catch (IllegalStateException ie) {
                            loge("Unable to change interface settings: " + ie);
                        }
                        registerForWifiMonitorEvents();
                        transitionTo(mInactiveState);
                        break;

創建p2p0,然後設置隨機p2p mac,之後up interface

主要看下設置隨機p2p mac這一步

            private void setupInterfaceFeatures(String interfaceName) {
                if (mContext.getResources().getBoolean(
                        R.bool.config_wifi_p2p_mac_randomization_supported)) {
                    Log.i(TAG, "Supported feature: P2P MAC randomization");
                    mWifiNative.setMacRandomization(true);
                } else {
                    mWifiNative.setMacRandomization(false);
                }
            }

WifiP2pNative

    /**
     * Enable/Disable MAC randomization.
     *
     * @param enable true to enable, false to disable.
     * @return true, if operation was successful.
     */
    public boolean setMacRandomization(boolean enable) {
        return mSupplicantP2pIfaceHal.setMacRandomization(enable);
    }

SupplicantP2pIfaceHal

    /**
     * Enable/Disable P2P MAC randomization.
     *
     * @param enable true to enable, false to disable.
     * @return true, if operation was successful.
     */
    public boolean setMacRandomization(boolean enable) {
        synchronized (mLock) {
            if (!checkSupplicantP2pIfaceAndLogFailureV1_2("setMacRandomization")) return false;

            android.hardware.wifi.supplicant.V1_2.ISupplicantP2pIface ifaceV12 =
                    getP2pIfaceMockableV1_2();
            SupplicantResult<Void> result = new SupplicantResult(
                    "setMacRandomization(" + enable + ")");
            try {
                result.setResult(ifaceV12.setMacRandomization(enable));
            } catch (RemoteException e) {
                Log.e(TAG, "ISupplicantP2pIface exception: " + e);
                supplicantServiceDiedHandler();
            }

            return result.isSuccess();
        }
    }

通過hidl調用到supplicant的api,p2p_iface.cpp

jiatai@jiatai:~/expand/aosp/Q_source_android-10.0.0_r6/external/wpa_supplicant_8$ grep "setMacRandomization" ./ -nri
./wpa_supplicant/hidl/1.2/p2p_iface.h:194:	Return<void> setMacRandomization(
./wpa_supplicant/hidl/1.2/p2p_iface.h:195:	    bool enable, setMacRandomization_cb _hidl_cb) override;
./wpa_supplicant/hidl/1.2/p2p_iface.h:304:	SupplicantStatus setMacRandomizationInternal(bool enable);
./wpa_supplicant/hidl/1.2/p2p_iface.cpp:853:Return<void> P2pIface::setMacRandomization(bool enable, setMacRandomization_cb _hidl_cb)
./wpa_supplicant/hidl/1.2/p2p_iface.cpp:857:	    &P2pIface::setMacRandomizationInternal, _hidl_cb, enable);
./wpa_supplicant/hidl/1.2/p2p_iface.cpp:1747:SupplicantStatus P2pIface::setMacRandomizationInternal(bool enable)
Return<void> P2pIface::setMacRandomization(bool enable, setMacRandomization_cb _hidl_cb)
{
	return validateAndCall(
	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
	    &P2pIface::setMacRandomizationInternal, _hidl_cb, enable);
}


SupplicantStatus P2pIface::setMacRandomizationInternal(bool enable)
{
	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
	bool currentEnabledState = !!wpa_s->conf->p2p_device_random_mac_addr;
	u8 *addr = NULL;

	// A dedicated p2p device is not managed by supplicant,
	// supplicant could not change its MAC address.
	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) {
		wpa_printf(MSG_ERROR,
			"Dedicated P2P device don't support MAC randomization");
		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, "NotSupported"};
	}

	// The same state, no change is needed.
	if (currentEnabledState == enable) {
		wpa_printf(MSG_DEBUG, "The random MAC is %s already.",
		    (enable) ? "enabled" : "disabled");
		return {SupplicantStatusCode::SUCCESS, ""};
	}

	if (enable) {
		wpa_s->conf->p2p_device_random_mac_addr = 1;
		wpa_s->conf->p2p_interface_random_mac_addr = 1;

		// restore config if it failed to set up MAC address.
		if (wpas_p2p_mac_setup(wpa_s) < 0) {
			wpa_s->conf->p2p_device_random_mac_addr = 0;
			wpa_s->conf->p2p_interface_random_mac_addr = 0;
			return {SupplicantStatusCode::FAILURE_UNKNOWN,
			    "Failed to set up MAC address."};
		}
	} else {
		// disable random MAC will use original MAC address
		// regardless of any saved persistent groups.
		if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
			wpa_printf(MSG_ERROR, "Failed to restore MAC address");
			return {SupplicantStatusCode::FAILURE_UNKNOWN,
			    "Failed to restore MAC address."};
		}

		if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
			wpa_printf(MSG_INFO, "Could not update MAC address information");
			return {SupplicantStatusCode::FAILURE_UNKNOWN,
			    "Failed to update MAC address."};
		}
		wpa_s->conf->p2p_device_random_mac_addr = 0;
		wpa_s->conf->p2p_interface_random_mac_addr = 0;
	}

	// update internal data to send out correct device address in action frame.
	os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
	os_memcpy(wpa_s->global->p2p->cfg->dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);

	return {SupplicantStatusCode::SUCCESS, ""};
}

可以看到如果打開隨機mac特性會自動生成隨機mac,否則應該是用的設備mac

1.1 隨機mac

p2p_supplicant.c

int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s)
{
	u8 addr[ETH_ALEN] = {0};

	if (wpa_s->conf->p2p_device_random_mac_addr == 0)
		return 0;

	if (wpa_s->conf->ssid == NULL) {
		if (random_mac_addr(addr) < 0) {
			wpa_msg(wpa_s, MSG_INFO,
				"Failed to generate random MAC address");
			return -EINVAL;
		}

		/* Store generated MAC address. */
		os_memcpy(wpa_s->conf->p2p_device_persistent_mac_addr, addr,
			  ETH_ALEN);
	} else {
		/* If there are existing saved groups, restore last MAC address.
		 * if there is no last used MAC address, the last one is
		 * factory MAC. */
		if (is_zero_ether_addr(
			    wpa_s->conf->p2p_device_persistent_mac_addr))
			return 0;
		os_memcpy(addr, wpa_s->conf->p2p_device_persistent_mac_addr,
			  ETH_ALEN);
		wpa_msg(wpa_s, MSG_DEBUG, "Restore last used MAC address.");
	}

	if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
		wpa_msg(wpa_s, MSG_INFO,
			"Failed to set random MAC address");
		return -EINVAL;
	}

	if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
		wpa_msg(wpa_s, MSG_INFO,
			"Could not update MAC address information");
		return -EINVAL;
	}

	wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
		MAC2STR(addr));

	return 0;
}

然後jiatai@jiatai:~/expand/aosp/Q_source_android-10.0.0_r6/external/wpa_supplicant_8$ gedit +978 ./src/utils/common.c

int random_mac_addr(u8 *addr)
{
	if (os_get_random(addr, ETH_ALEN) < 0)
		return -1;
	addr[0] &= 0xfe; /* unicast */
	addr[0] |= 0x02; /* locally administered */
	return 0;
}

生成隨機mac,單播位置0,和本地生成位置1

 

1.2 factory mac

gedit ./wpa_supplicant/driver_i.h

 gedit ./src/drivers/driver_nl80211.c

gedit ./src/drivers/linux_ioctl.c

static inline int wpa_drv_set_mac_addr(struct wpa_supplicant *wpa_s,
				       const u8 *addr)
{
	if (!wpa_s->driver->set_mac_addr)
		return -1;
	return wpa_s->driver->set_mac_addr(wpa_s->drv_priv, addr);
}
static int nl80211_set_mac_addr(void *priv, const u8 *addr)
{
	struct i802_bss *bss = priv;
	struct wpa_driver_nl80211_data *drv = bss->drv;
	int new_addr = addr != NULL;

	if (TEST_FAIL())
		return -1;

	if (!addr)
		addr = drv->perm_addr;

	if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) < 0)
		return -1;

	if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, addr) < 0)
	{
		wpa_printf(MSG_DEBUG,
			   "nl80211: failed to set_mac_addr for %s to " MACSTR,
			   bss->ifname, MAC2STR(addr));
		if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname,
					  1) < 0) {
			wpa_printf(MSG_DEBUG,
				   "nl80211: Could not restore interface UP after failed set_mac_addr");
		}
		return -1;
	}

	wpa_printf(MSG_DEBUG, "nl80211: set_mac_addr for %s to " MACSTR,
		   bss->ifname, MAC2STR(addr));
	drv->addr_changed = new_addr;
	os_memcpy(bss->addr, addr, ETH_ALEN);

	if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1) < 0)
	{
		wpa_printf(MSG_DEBUG,
			   "nl80211: Could not restore interface UP after set_mac_addr");
	}

	return 0;
}
int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr)
{
	struct ifreq ifr;

	os_memset(&ifr, 0, sizeof(ifr));
	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
	os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
	ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;

	if (ioctl(sock, SIOCSIFHWADDR, &ifr)) {
		wpa_printf(MSG_DEBUG, "Could not set interface %s hwaddr: %s",
			   ifname, strerror(errno));
		return -1;
	}

	return 0;
}

看樣子恢復成factory就是把addr設爲null傳下去就好了

 

2.總結

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章