diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index f3a491710..b7f259b6c 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1754,7 +1754,7 @@ static const struct parse_data ssid_fields[] = { #ifdef CONFIG_HS20 { INT(update_identifier) }, #endif /* CONFIG_HS20 */ - { INT_RANGE(mac_addr, 0, 1) }, + { INT_RANGE(mac_addr, 0, 2) }, }; #undef OFFSET diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 75257c552..3fd4192c5 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -1058,6 +1058,7 @@ struct wpa_config { * * 0 = use permanent MAC address * 1 = use random MAC address for each ESS connection + * 2 = like 1, but maintain OUI (with local admin bit set) * * By default, permanent MAC address is used unless policy is changed by * the per-network mac_addr parameter. Global mac_addr=1 can be used to @@ -1075,6 +1076,7 @@ struct wpa_config { * * 0 = use permanent MAC address * 1 = use random MAC address + * 2 = like 1, but maintain OUI (with local admin bit set) */ int preassoc_mac_addr; }; diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index b5dbf6ee3..f50b2d41d 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -659,6 +659,7 @@ struct wpa_ssid { * * 0 = use permanent MAC address * 1 = use random MAC address for each ESS connection + * 2 = like 1, but maintain OUI (with local admin bit set) * * Internally, special value -1 is used to indicate that the parameter * was not specified in the configuration (i.e., default behavior is diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 92af1124f..3f60d2ba8 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1380,13 +1380,14 @@ void wpas_connect_work_done(struct wpa_supplicant *wpa_s) } -int wpas_update_random_addr(struct wpa_supplicant *wpa_s) +int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style) { struct os_reltime now; u8 addr[ETH_ALEN]; os_get_reltime(&now); - if (wpa_s->last_mac_addr_change.sec != 0 && + if (wpa_s->last_mac_addr_style == style && + wpa_s->last_mac_addr_change.sec != 0 && !os_reltime_expired(&now, &wpa_s->last_mac_addr_change, wpa_s->conf->rand_addr_lifetime)) { wpa_msg(wpa_s, MSG_DEBUG, @@ -1394,8 +1395,19 @@ int wpas_update_random_addr(struct wpa_supplicant *wpa_s) return 0; } - if (random_mac_addr(addr) < 0) + switch (style) { + case 1: + if (random_mac_addr(addr) < 0) + return -1; + break; + case 2: + os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN); + if (random_mac_addr_keep_oui(addr) < 0) + return -1; + break; + default: return -1; + } if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) { wpa_msg(wpa_s, MSG_INFO, @@ -1405,6 +1417,7 @@ int wpas_update_random_addr(struct wpa_supplicant *wpa_s) os_get_reltime(&wpa_s->last_mac_addr_change); wpa_s->mac_addr_changed = 1; + wpa_s->last_mac_addr_style = style; if (wpa_supplicant_update_mac_addr(wpa_s) < 0) { wpa_msg(wpa_s, MSG_INFO, @@ -1425,7 +1438,7 @@ int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s) !wpa_s->conf->preassoc_mac_addr) return 0; - return wpas_update_random_addr(wpa_s); + return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr); } @@ -1443,12 +1456,17 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid) { struct wpa_connect_work *cwork; + int rand_style; + + if (ssid->mac_addr == -1) + rand_style = wpa_s->conf->mac_addr; + else + rand_style = ssid->mac_addr; if (wpa_s->last_ssid == ssid) { wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS"); - } else if (ssid->mac_addr == 1 || - (ssid->mac_addr == -1 && wpa_s->conf->mac_addr == 1)) { - if (wpas_update_random_addr(wpa_s) < 0) + } else if (rand_style > 0) { + if (wpas_update_random_addr(wpa_s, rand_style) < 0) return; wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); } else if (wpa_s->mac_addr_changed) { @@ -2783,6 +2801,7 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s) wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR, MAC2STR(wpa_s->own_addr)); + os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN); wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); if (wpa_s->bridge_ifname[0]) { diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index f2eaaa891..89da0dafd 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -335,6 +335,7 @@ fast_reauth=1 # MAC address policy default # 0 = use permanent MAC address # 1 = use random MAC address for each ESS connection +# 2 = like 1, but maintain OUI (with local admin bit set) # # By default, permanent MAC address is used unless policy is changed by # the per-network mac_addr parameter. Global mac_addr=1 can be used to @@ -347,6 +348,7 @@ fast_reauth=1 # MAC address policy for pre-association operations (scanning, ANQP) # 0 = use permanent MAC address # 1 = use random MAC address +# 2 = like 1, but maintain OUI (with local admin bit set) #preassoc_mac_addr=0 # Interworking (IEEE 802.11u) @@ -982,6 +984,7 @@ fast_reauth=1 # MAC address policy # 0 = use permanent MAC address # 1 = use random MAC address for each ESS connection +# 2 = like 1, but maintain OUI (with local admin bit set) #mac_addr=0 # disable_ht: Whether HT (802.11n) should be disabled. diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 2b6ef79ad..f94192394 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -391,6 +391,7 @@ struct wpa_supplicant { struct l2_packet_data *l2; struct l2_packet_data *l2_br; unsigned char own_addr[ETH_ALEN]; + unsigned char perm_addr[ETH_ALEN]; char ifname[100]; #ifdef CONFIG_CTRL_IFACE_DBUS char *dbus_path; @@ -613,6 +614,7 @@ struct wpa_supplicant { unsigned int mac_addr_changed:1; struct os_reltime last_mac_addr_change; + int last_mac_addr_style; struct ibss_rsn *ibss_rsn; @@ -962,7 +964,7 @@ int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid, size_t ssid_len); void wpas_request_connection(struct wpa_supplicant *wpa_s); int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen); -int wpas_update_random_addr(struct wpa_supplicant *wpa_s); +int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style); int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s); /**