diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index b30376031..cb2c8d631 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -938,6 +938,14 @@ ssid_list_set: } #endif /* CONFIG_P2P */ + if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) { + params.mac_addr_rand = 1; + if (wpa_s->mac_addr_scan) { + params.mac_addr = wpa_s->mac_addr_scan; + params.mac_addr_mask = wpa_s->mac_addr_scan + ETH_ALEN; + } + } + scan_params = ¶ms; scan: @@ -1281,6 +1289,15 @@ scan: wpa_setband_scan_freqs(wpa_s, scan_params); + if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCHED_SCAN) { + params.mac_addr_rand = 1; + if (wpa_s->mac_addr_sched_scan) { + params.mac_addr = wpa_s->mac_addr_sched_scan; + params.mac_addr_mask = wpa_s->mac_addr_sched_scan + + ETH_ALEN; + } + } + ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params, wpa_s->sched_scan_interval); wpabuf_free(extra_ie); @@ -1926,6 +1943,23 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src) params->only_new_results = src->only_new_results; params->low_priority = src->low_priority; + if (src->mac_addr_rand) { + params->mac_addr_rand = src->mac_addr_rand; + + if (src->mac_addr && src->mac_addr_mask) { + u8 *mac_addr; + + mac_addr = os_malloc(2 * ETH_ALEN); + if (!mac_addr) + goto failed; + + os_memcpy(mac_addr, src->mac_addr, ETH_ALEN); + os_memcpy(mac_addr + ETH_ALEN, src->mac_addr_mask, + ETH_ALEN); + params->mac_addr = mac_addr; + params->mac_addr_mask = mac_addr + ETH_ALEN; + } + } return params; failed: @@ -1946,6 +1980,13 @@ void wpa_scan_free_params(struct wpa_driver_scan_params *params) os_free((u8 *) params->extra_ies); os_free(params->freqs); os_free(params->filter_ssids); + + /* + * Note: params->mac_addr_mask points to same memory allocation and + * must not be freed separately. + */ + os_free((u8 *) params->mac_addr); + os_free(params); } @@ -2050,6 +2091,14 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s) params.freqs = wpa_s->manual_sched_scan_freqs; } + if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_PNO) { + params.mac_addr_rand = 1; + if (wpa_s->mac_addr_pno) { + params.mac_addr = wpa_s->mac_addr_pno; + params.mac_addr_mask = wpa_s->mac_addr_pno + ETH_ALEN; + } + } + ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms, interval); os_free(params.filter_ssids); if (ret == 0) @@ -2077,3 +2126,61 @@ int wpas_stop_pno(struct wpa_supplicant *wpa_s) return ret; } + + +void wpas_mac_addr_rand_scan_clear(struct wpa_supplicant *wpa_s, + unsigned int type) +{ + type &= MAC_ADDR_RAND_ALL; + wpa_s->mac_addr_rand_enable &= ~type; + + if (type & MAC_ADDR_RAND_SCAN) { + os_free(wpa_s->mac_addr_scan); + wpa_s->mac_addr_scan = NULL; + } + + if (type & MAC_ADDR_RAND_SCHED_SCAN) { + os_free(wpa_s->mac_addr_sched_scan); + wpa_s->mac_addr_sched_scan = NULL; + } + + if (type & MAC_ADDR_RAND_PNO) { + os_free(wpa_s->mac_addr_pno); + wpa_s->mac_addr_pno = NULL; + } +} + + +int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s, + unsigned int type, const u8 *addr, + const u8 *mask) +{ + u8 *tmp = NULL; + + wpas_mac_addr_rand_scan_clear(wpa_s, type); + + if (addr) { + tmp = os_malloc(2 * ETH_ALEN); + if (!tmp) + return -1; + os_memcpy(tmp, addr, ETH_ALEN); + os_memcpy(tmp + ETH_ALEN, mask, ETH_ALEN); + } + + if (type == MAC_ADDR_RAND_SCAN) { + wpa_s->mac_addr_scan = tmp; + } else if (type == MAC_ADDR_RAND_SCHED_SCAN) { + wpa_s->mac_addr_sched_scan = tmp; + } else if (type == MAC_ADDR_RAND_PNO) { + wpa_s->mac_addr_pno = tmp; + } else { + wpa_printf(MSG_INFO, + "scan: Invalid MAC randomization type=0x%x", + type); + os_free(tmp); + return -1; + } + + wpa_s->mac_addr_rand_enable |= type; + return 0; +} diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h index 946d2b35e..7650f5a25 100644 --- a/wpa_supplicant/scan.h +++ b/wpa_supplicant/scan.h @@ -49,4 +49,10 @@ void wpa_scan_free_params(struct wpa_driver_scan_params *params); int wpas_start_pno(struct wpa_supplicant *wpa_s); int wpas_stop_pno(struct wpa_supplicant *wpa_s); +void wpas_mac_addr_rand_scan_clear(struct wpa_supplicant *wpa_s, + unsigned int type); +int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s, + unsigned int type, const u8 *addr, + const u8 *mask); + #endif /* SCAN_H */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 32676cde9..e5dc43f7f 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -488,6 +488,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) os_free(wpa_s->manual_sched_scan_freqs); wpa_s->manual_sched_scan_freqs = NULL; + wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL); + gas_query_deinit(wpa_s->gas); wpa_s->gas = NULL; @@ -3869,6 +3871,13 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, wpa_s->num_multichan_concurrent = capa.num_multichan_concurrent; wpa_s->wmm_ac_supported = capa.wmm_ac_supported; + + if (capa.mac_addr_rand_scan_supported) + wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN; + if (wpa_s->sched_scan_supported && + capa.mac_addr_rand_sched_scan_supported) + wpa_s->mac_addr_rand_supported |= + (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO); } if (wpa_s->max_remain_on_chan == 0) wpa_s->max_remain_on_chan = 1000; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 9d24b9427..c541ccb4e 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -897,6 +897,20 @@ struct wpa_supplicant { unsigned int wmm_ac_supported:1; unsigned int ext_work_in_progress:1; +#define MAC_ADDR_RAND_SCAN BIT(0) +#define MAC_ADDR_RAND_SCHED_SCAN BIT(1) +#define MAC_ADDR_RAND_PNO BIT(2) +#define MAC_ADDR_RAND_ALL (MAC_ADDR_RAND_SCAN | \ + MAC_ADDR_RAND_SCHED_SCAN | \ + MAC_ADDR_RAND_PNO) + unsigned int mac_addr_rand_supported; + unsigned int mac_addr_rand_enable; + + /* MAC Address followed by mask (2 * ETH_ALEN) */ + u8 *mac_addr_scan; + u8 *mac_addr_sched_scan; + u8 *mac_addr_pno; + #ifdef CONFIG_WNM u8 wnm_dialog_token; u8 wnm_reply;