#ifdef CONFIG_HS20
{ INT(update_identifier) },
#endif /* CONFIG_HS20 */
+ { INT_RANGE(mac_addr, 0, 1) },
};
#undef OFFSET
#ifdef CONFIG_IEEE80211W
ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
#endif /* CONFIG_IEEE80211W */
+ ssid->mac_addr = -1;
}
config->wmm_ac_params[2] = ac_vi;
config->wmm_ac_params[3] = ac_vo;
config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY;
+ config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
if (ctrl_interface)
config->ctrl_interface = os_strdup(ctrl_interface);
{ STR(osu_dir), 0 },
{ STR(wowlan_triggers), 0 },
{ INT(p2p_search_delay), 0},
+ { INT(mac_addr), 0 },
+ { INT(rand_addr_lifetime), 0 },
+ { INT(preassoc_mac_addr), 0 },
};
#undef FUNC
#define DEFAULT_ACCESS_NETWORK_TYPE 15
#define DEFAULT_SCAN_CUR_FREQ 0
#define DEFAULT_P2P_SEARCH_DELAY 500
+#define DEFAULT_RAND_ADDR_LIFETIME 60
#include "config_ssid.h"
#include "wps/wps.h"
* resources.
*/
unsigned int p2p_search_delay;
+
+ /**
+ * mac_addr - MAC address policy default
+ *
+ * 0 = use permanent MAC address
+ * 1 = use random MAC address for each ESS connection
+ *
+ * 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
+ * change this default behavior.
+ */
+ int mac_addr;
+
+ /**
+ * rand_addr_lifetime - Lifetime of random MAC address in seconds
+ */
+ unsigned int rand_addr_lifetime;
+
+ /**
+ * preassoc_mac_addr - Pre-association MAC address policy
+ *
+ * 0 = use permanent MAC address
+ * 1 = use random MAC address
+ */
+ int preassoc_mac_addr;
};
#ifdef CONFIG_HS20
INT(update_identifier);
#endif /* CONFIG_HS20 */
+ write_int(f, "mac_addr", ssid->mac_addr, -1);
#undef STR
#undef INT
if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY)
fprintf(f, "p2p_search_delay=%u\n",
config->p2p_search_delay);
+
+ if (config->mac_addr)
+ fprintf(f, "mac_addr=%d\n", config->mac_addr);
+
+ if (config->rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME)
+ fprintf(f, "rand_addr_lifetime=%u\n",
+ config->rand_addr_lifetime);
+
+ if (config->preassoc_mac_addr)
+ fprintf(f, "preassoc_mac_addr=%d\n", config->preassoc_mac_addr);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
#endif /* CONFIG_HS20 */
unsigned int wps_run;
+
+ /**
+ * mac_addr - MAC address policy
+ *
+ * 0 = use permanent MAC address
+ * 1 = use random MAC address for each ESS connection
+ *
+ * Internally, special value -1 is used to indicate that the parameter
+ * was not specified in the configuration (i.e., default behavior is
+ * followed).
+ */
+ int mac_addr;
};
#endif /* CONFIG_SSID_H */
struct wpa_ssid *remove_ssid = ssid;
id = ssid->id;
ssid = ssid->next;
+ if (wpa_s->last_ssid == remove_ssid)
+ wpa_s->last_ssid = NULL;
wpas_notify_network_removed(wpa_s, remove_ssid);
wpa_config_remove_network(wpa_s->conf, id);
}
return -1;
}
+ if (wpa_s->last_ssid == ssid)
+ wpa_s->last_ssid = NULL;
+
if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
#ifdef CONFIG_SME
wpa_s->sme.prev_bssid_set = 0;
{
struct gas_query_pending *query = work->ctx;
struct gas_query *gas = query->gas;
+ struct wpa_supplicant *wpa_s = gas->wpa_s;
if (deinit) {
if (work->started) {
return;
}
+ if (wpas_update_random_addr_disassoc(wpa_s) < 0) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Failed to assign random MAC address for GAS");
+ gas_query_free(query, 1);
+ radio_work_done(work);
+ return;
+ }
+
gas->work = work;
if (gas_query_tx(gas, query, query->req) < 0) {
return;
}
+ if (wpas_update_random_addr_disassoc(wpa_s) < 0) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Failed to assign random MAC address for a scan");
+ radio_work_done(work);
+ return;
+ }
+
wpa_supplicant_notify_scanning(wpa_s, 1);
if (wpa_s->clear_driver_scan_cache)
}
+int wpas_update_random_addr(struct wpa_supplicant *wpa_s)
+{
+ struct os_reltime now;
+ u8 addr[ETH_ALEN];
+
+ os_get_reltime(&now);
+ if (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,
+ "Previously selected random MAC address has not yet expired");
+ return 0;
+ }
+
+ if (random_mac_addr(addr) < 0)
+ return -1;
+
+ if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Failed to set random MAC address");
+ return -1;
+ }
+
+ os_get_reltime(&wpa_s->last_mac_addr_change);
+ wpa_s->mac_addr_changed = 1;
+
+ if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Could not update MAC address information");
+ return -1;
+ }
+
+ wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
+ MAC2STR(addr));
+
+ return 0;
+}
+
+
+int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
+ !wpa_s->conf->preassoc_mac_addr)
+ return 0;
+
+ return wpas_update_random_addr(wpa_s);
+}
+
+
static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
/**
{
struct wpa_connect_work *cwork;
+ 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)
+ return;
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
+ } else if (wpa_s->mac_addr_changed) {
+ if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Could not restore permanent MAC address");
+ return;
+ }
+ wpa_s->mac_addr_changed = 0;
+ if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Could not update MAC address information");
+ return;
+ }
+ wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
+ }
+ wpa_s->last_ssid = ssid;
+
#ifdef CONFIG_IBSS_RSN
ibss_rsn_deinit(wpa_s->ibss_rsn);
wpa_s->ibss_rsn = NULL;
return -1;
}
+ wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
+
return 0;
}
# 1: Scan current operating frequency if another VIF on the same radio
# is already associated.
+# MAC address policy default
+# 0 = use permanent MAC address
+# 1 = use random MAC address for each ESS connection
+#
+# 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
+# change this default behavior.
+#mac_addr=0
+
+# Lifetime of random MAC address in seconds (default: 60)
+#rand_addr_lifetime=60
+
+# MAC address policy for pre-association operations (scanning, ANQP)
+# 0 = use permanent MAC address
+# 1 = use random MAC address
+#preassoc_mac_addr=0
+
# Interworking (IEEE 802.11u)
# Enable Interworking
# Beacon interval (default: 100 TU)
#beacon_int=100
+# MAC address policy
+# 0 = use permanent MAC address
+# 1 = use random MAC address for each ESS connection
+#mac_addr=0
+
# disable_ht: Whether HT (802.11n) should be disabled.
# 0 = HT enabled (if AP supports it)
# 1 = HT disabled
int disconnected; /* all connections disabled; i.e., do no reassociate
* before this has been cleared */
struct wpa_ssid *current_ssid;
+ struct wpa_ssid *last_ssid;
struct wpa_bss *current_bss;
int ap_ies_from_associnfo;
unsigned int assoc_freq;
unsigned int last_eapol_matches_bssid:1;
unsigned int eap_expected_failure:1;
unsigned int reattach:1; /* reassociation to the same BSS requested */
+ unsigned int mac_addr_changed:1;
+
+ struct os_reltime last_mac_addr_change;
struct ibss_rsn *ibss_rsn;
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_disassoc(struct wpa_supplicant *wpa_s);
/**
* wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response