Extend random MAC address support to allow OUI to be kept
authorJouni Malinen <j@w1.fi>
Mon, 29 Sep 2014 20:24:19 +0000 (23:24 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 29 Sep 2014 21:40:23 +0000 (00:40 +0300)
mac_addr=2 and preassoc_mac_addr=2 parameters can now be used to
configure random MAC address to be generated by maintaining the OUI part
of the permanent MAC address (but with locally administered bit set to
1). Other than that, these values result in similar behavior with
mac_addr=1 and preassoc_mac_addr=1, respectively.

Signed-off-by: Jouni Malinen <j@w1.fi>
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/config_ssid.h
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant.conf
wpa_supplicant/wpa_supplicant_i.h

index f3a4917..b7f259b 100644 (file)
@@ -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
index 75257c5..3fd4192 100644 (file)
@@ -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;
 };
index b5dbf6e..f50b2d4 100644 (file)
@@ -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
index 92af112..3f60d2b 100644 (file)
@@ -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]) {
index f2eaaa8..89da0da 100644 (file)
@@ -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.
index 2b6ef79..f941923 100644 (file)
@@ -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);
 
 /**