#endif /* NO_CONFIG_WRITE */
+static int wpa_config_parse_mac_value(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ u8 mac_value[ETH_ALEN];
+
+ if (hwaddr_aton(value, mac_value) == 0) {
+ if (os_memcmp(mac_value, ssid->mac_value, ETH_ALEN) == 0)
+ return 1;
+ os_memcpy(ssid->mac_value, mac_value, ETH_ALEN);
+ return 0;
+ }
+
+ wpa_printf(MSG_ERROR, "Line %d: Invalid MAC address '%s'",
+ line, value);
+ return -1;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_mac_value(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ const size_t size = 3 * ETH_ALEN;
+ char *value;
+ int res;
+
+ if (ssid->mac_addr != 3)
+ return NULL;
+
+ value = os_malloc(size);
+ if (!value)
+ return NULL;
+ res = os_snprintf(value, size, MACSTR, MAC2STR(ssid->mac_value));
+ if (os_snprintf_error(size, res)) {
+ os_free(value);
+ return NULL;
+ }
+ value[size - 1] = '\0';
+ return value;
+}
+#endif /* NO_CONFIG_WRITE */
+
+
/* Helper macros for network block parser */
#ifdef OFFSET
{ INT(update_identifier) },
{ STR_RANGE(roaming_consortium_selection, 0, MAX_ROAMING_CONS_OI_LEN) },
#endif /* CONFIG_HS20 */
- { INT_RANGE(mac_addr, 0, 2) },
+ { INT_RANGE(mac_addr, 0, 3) },
+ { FUNC_KEY(mac_value) },
{ INT_RANGE(pbss, 0, 2) },
{ INT_RANGE(wps_disabled, 0, 1) },
{ INT_RANGE(fils_dh_group, 0, 65535) },
* 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)
+ * 3 = use dedicated/pregenerated MAC address (see mac_value)
*
* Internally, special value -1 is used to indicate that the parameter
* was not specified in the configuration (i.e., default behavior is
*/
int mac_addr;
+ /**
+ * mac_value - Specific MAC address to be used
+ *
+ * When mac_addr policy is equal to 3 this is the value of the MAC
+ * address that should be used.
+ */
+ u8 mac_value[ETH_ALEN];
+
/**
* no_auto_peer - Do not automatically peer with compatible mesh peers
*
#ifdef CONFIG_INTERWORKING
"roaming_consortium", "required_roaming_consortium",
#endif /* CONFIG_INTERWORKING */
- NULL
+ "mac_value", NULL
};
static dbus_bool_t should_quote_opt(const char *key)
struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
DBusMessageIter iter_dict;
char *value = NULL;
+ bool mac_addr3_set = false;
+ bool mac_value_set = false;
if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
return FALSE;
else if (os_strcmp(entry.key, "priority") == 0)
wpa_config_update_prio_list(wpa_s->conf);
+ /*
+ * MAC address policy "3" needs to come with mac_value in
+ * the message so make sure that it is present (checked after
+ * the loop - here we just note what has been supplied).
+ */
+ if (os_strcmp(entry.key, "mac_addr") == 0 &&
+ atoi(value) == 3)
+ mac_addr3_set = true;
+ if (os_strcmp(entry.key, "mac_value") == 0)
+ mac_value_set = true;
+
skip_update:
os_free(value);
value = NULL;
wpa_dbus_dict_entry_clear(&entry);
}
+ if (mac_addr3_set && !mac_value_set) {
+ wpa_printf(MSG_INFO, "dbus: Invalid mac_addr policy config");
+ dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
+ "Invalid mac_addr policy config");
+ return FALSE;
+ }
+
return TRUE;
error:
}
-int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
+int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style,
+ struct wpa_ssid *ssid)
{
struct os_reltime now;
u8 addr[ETH_ALEN];
os_get_reltime(&now);
if (wpa_s->last_mac_addr_style == style &&
+ /* Pregenerated addresses do not expire */
+ wpa_s->last_mac_addr_style != 3 &&
wpa_s->last_mac_addr_change.sec != 0 &&
!os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
wpa_s->conf->rand_addr_lifetime)) {
if (random_mac_addr_keep_oui(addr) < 0)
return -1;
break;
+ case 3:
+ if (!ssid) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Invalid 'ssid' for address policy 3");
+ return -1;
+ }
+ os_memcpy(addr, ssid->mac_value, ETH_ALEN);
+ break;
default:
return -1;
}
!wpa_s->conf->preassoc_mac_addr)
return 0;
- return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
+ return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
+ NULL);
}
#endif /* CONFIG_SAE */
if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
- if (wpas_update_random_addr(wpa_s, rand_style) < 0)
+ if (wpas_update_random_addr(wpa_s, rand_style, ssid) < 0)
return;
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
} else if (rand_style == 0 && wpa_s->mac_addr_changed) {
void wpas_request_connection(struct wpa_supplicant *wpa_s);
void wpas_request_disconnection(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 style);
+int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style,
+ struct wpa_ssid *ssid);
int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s);
void add_freq(int *freqs, int *num_freqs, int freq);