FT: Copy FT Capability and Policy to MDIE from target AP
authorJouni Malinen <jouni.malinen@atheros.com>
Fri, 9 Apr 2010 13:26:20 +0000 (16:26 +0300)
committerJouni Malinen <j@w1.fi>
Fri, 9 Apr 2010 13:26:20 +0000 (16:26 +0300)
This sets the FT Capability and Policy field in the MDIE to the values
received from the target AP (if available). This fixes the MDIE contents
during FT Protocol, but the correct value may not yet be used in initial
mobility domain association.

src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_ft.c
wpa_supplicant/ctrl_iface.c
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant.c

index 905bb4a..f7b1fb7 100644 (file)
@@ -459,7 +459,7 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
 #ifdef CONFIG_IEEE80211R
        if (wpa_key_mgmt_ft(sm->key_mgmt)) {
                /* Prepare for the next transition */
-               wpa_ft_prepare_auth_request(sm);
+               wpa_ft_prepare_auth_request(sm, NULL);
        }
 #endif /* CONFIG_IEEE80211R */
 }
@@ -1936,7 +1936,7 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
                wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
 
                /* Prepare for the next transition */
-               wpa_ft_prepare_auth_request(sm);
+               wpa_ft_prepare_auth_request(sm, NULL);
 
                clear_ptk = 0;
        }
index 5ff6906..0d4405b 100644 (file)
@@ -281,14 +281,15 @@ static inline int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
 int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,
                         const u8 *r0kh_id, size_t r0kh_id_len,
                         const u8 *r1kh_id);
-int wpa_ft_prepare_auth_request(struct wpa_sm *sm);
+int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie);
 int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
                            int ft_action, const u8 *target_ap,
                            const u8 *ric_ies, size_t ric_ies_len);
 int wpa_ft_is_completed(struct wpa_sm *sm);
 int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
                                 size_t ies_len, const u8 *src_addr);
-int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap);
+int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
+                        const u8 *mdie);
 
 #else /* CONFIG_IEEE80211R */
 
@@ -299,7 +300,8 @@ wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,
        return 0;
 }
 
-static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm)
+static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm,
+                                             const u8 *mdie)
 {
        return 0;
 }
index eb68e26..7c89e9b 100644 (file)
@@ -115,6 +115,7 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,
  * @target_ap: Target AP address
  * @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL
  * @ric_ies_len: Length of ric_ies buffer in octets
+ * @ap_mdie: Mobility Domain IE from the target AP
  * Returns: Pointer to buffer with IEs or %NULL on failure
  *
  * Caller is responsible for freeing the returned buffer with os_free();
@@ -122,7 +123,8 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,
 static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
                               const u8 *anonce, const u8 *pmk_name,
                               const u8 *kck, const u8 *target_ap,
-                              const u8 *ric_ies, size_t ric_ies_len)
+                              const u8 *ric_ies, size_t ric_ies_len,
+                              const u8 *ap_mdie)
 {
        size_t buf_len;
        u8 *buf, *pos, *ftie_len, *ftie_pos;
@@ -227,7 +229,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
        pos += sizeof(*mdie);
        os_memcpy(mdie->mobility_domain, sm->mobility_domain,
                  MOBILITY_DOMAIN_ID_LEN);
-       mdie->ft_capab = 0; /* FIX: copy from the target AP's MDIE */
+       mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] : 0;
 
        /* FTIE[SNonce, [R1KH-ID,] R0KH-ID ] */
        ftie_pos = pos;
@@ -497,9 +499,10 @@ static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
 /**
  * wpa_ft_prepare_auth_request - Generate over-the-air auth request
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
+ * @mdie: Target AP MDIE
  * Returns: 0 on success, -1 on failure
  */
-int wpa_ft_prepare_auth_request(struct wpa_sm *sm)
+int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie)
 {
        u8 *ft_ies;
        size_t ft_ies_len;
@@ -511,7 +514,7 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm)
        }
 
        ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
-                                   NULL, sm->bssid, NULL, 0);
+                                   NULL, sm->bssid, NULL, 0, mdie);
        if (ft_ies) {
                wpa_sm_update_ft_ies(sm, sm->mobility_domain,
                                     ft_ies, ft_ies_len);
@@ -628,7 +631,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
 
        ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce,
                                    sm->pmk_r1_name, sm->ptk.kck, bssid,
-                                   ric_ies, ric_ies_len);
+                                   ric_ies, ric_ies_len,
+                                   parse.mdie ? parse.mdie - 2 : NULL);
        if (ft_ies) {
                wpa_sm_update_ft_ies(sm, sm->mobility_domain,
                                     ft_ies, ft_ies_len);
@@ -936,9 +940,12 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
 /**
  * wpa_ft_start_over_ds - Generate over-the-DS auth request
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
+ * @target_ap: Target AP Address
+ * @mdie: Mobility Domain IE from the target AP
  * Returns: 0 on success, -1 on failure
  */
-int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap)
+int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
+                        const u8 *mdie)
 {
        u8 *ft_ies;
        size_t ft_ies_len;
@@ -953,7 +960,7 @@ int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap)
        }
 
        ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
-                                   NULL, target_ap, NULL, 0);
+                                   NULL, target_ap, NULL, 0, mdie);
        if (ft_ies) {
                sm->over_the_ds_in_progress = 1;
                os_memcpy(sm->target_ap, target_ap, ETH_ALEN);
index c7d3427..969cc8a 100644 (file)
@@ -136,6 +136,8 @@ static int wpa_supplicant_ctrl_iface_ft_ds(
        struct wpa_supplicant *wpa_s, char *addr)
 {
        u8 target_ap[ETH_ALEN];
+       struct wpa_bss *bss;
+       const u8 *mdie;
 
        if (hwaddr_aton(addr, target_ap)) {
                wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
@@ -145,7 +147,13 @@ static int wpa_supplicant_ctrl_iface_ft_ds(
 
        wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
 
-       return wpa_ft_start_over_ds(wpa_s->wpa, target_ap);
+       bss = wpa_bss_get_bssid(wpa_s, target_ap);
+       if (bss)
+               mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
+       else
+               mdie = NULL;
+
+       return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
 }
 #endif /* CONFIG_IEEE80211R */
 
index f04295a..8148375 100644 (file)
@@ -163,7 +163,7 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
        wpa_sm_set_ft_params(wpa_s->wpa, md, NULL, 0, NULL);
        if (md) {
                /* Prepare for the next transition */
-               wpa_ft_prepare_auth_request(wpa_s->wpa);
+               wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
        }
 
        if (md && ssid->key_mgmt & (WPA_KEY_MGMT_FT_PSK |
index 6748735..c5387bf 100644 (file)
@@ -1040,7 +1040,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                wpa_sm_set_ft_params(wpa_s->wpa, md, NULL, 0, NULL);
                if (md) {
                        /* Prepare for the next transition */
-                       wpa_ft_prepare_auth_request(wpa_s->wpa);
+                       wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
                }
 #endif /* CONFIG_IEEE80211R */
 #ifdef CONFIG_WPS