]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
FT: Add support for IEEE 802.11r with driver-based SME
authorDeepthi Gowri <deepthi@codeaurora.org>
Tue, 12 Mar 2013 18:08:53 +0000 (20:08 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 12 Mar 2013 18:08:53 +0000 (20:08 +0200)
Add NL80211_CMD_UPDATE_FT_IES to support update of FT IEs to the
WLAN driver. Add NL80211_CMD_FT_EVENT to send FT event from the
WLAN driver. This will carry the target AP's MAC address along
with the relevant Information Elements. This event is used to
report received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).

Signed-off-by: Deepthi Gowri <deepthi@codeaurora.org>
src/common/ieee802_11_defs.h
src/drivers/driver_nl80211.c
src/rsn_supp/wpa_ft.c
wpa_supplicant/events.c

index 652476ff97a7712178461cd84a3046aaa4099409..f782c86583ba98bd153b6521edf67cebb00a1ac5 100644 (file)
@@ -1005,6 +1005,8 @@ enum wifi_display_subelem {
 /* AKM suite selectors */
 #define WLAN_AKM_SUITE_8021X           0x000FAC01
 #define WLAN_AKM_SUITE_PSK             0x000FAC02
+#define WLAN_AKM_SUITE_FT_8021X                0x000FAC03
+#define WLAN_AKM_SUITE_FT_PSK          0x000FAC04
 #define WLAN_AKM_SUITE_CCKM            0x00409600
 
 
index 4635d05e9ac8fde2438af55ca51d0b16653429c8..100434db66dc6cc65997aca2a3bb3f1c05b1af30 100644 (file)
@@ -1633,6 +1633,34 @@ static void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data *drv,
 }
 
 
+static void mlme_event_ft_event(struct wpa_driver_nl80211_data *drv,
+                               struct nlattr *tb[])
+{
+       union wpa_event_data data;
+
+       os_memset(&data, 0, sizeof(data));
+
+       if (tb[NL80211_ATTR_IE]) {
+               data.ft_ies.ies = nla_data(tb[NL80211_ATTR_IE]);
+               data.ft_ies.ies_len = nla_len(tb[NL80211_ATTR_IE]);
+       }
+
+       if (tb[NL80211_ATTR_IE_RIC]) {
+               data.ft_ies.ric_ies = nla_data(tb[NL80211_ATTR_IE_RIC]);
+               data.ft_ies.ric_ies_len = nla_len(tb[NL80211_ATTR_IE_RIC]);
+       }
+
+       if (tb[NL80211_ATTR_MAC])
+               os_memcpy(data.ft_ies.target_ap,
+                         nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
+
+       wpa_printf(MSG_DEBUG, "nl80211: FT event target_ap " MACSTR,
+                  MAC2STR(data.ft_ies.target_ap));
+
+       wpa_supplicant_event(drv->ctx, EVENT_FT_RESPONSE, &data);
+}
+
+
 static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
                            struct nlattr *tb[])
 {
@@ -2330,6 +2358,9 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
        case NL80211_CMD_CONN_FAILED:
                nl80211_connect_failed_event(drv, tb);
                break;
+       case NL80211_CMD_FT_EVENT:
+               mlme_event_ft_event(drv, tb);
+               break;
        default:
                wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
                           "(cmd=%d)", cmd);
@@ -7142,6 +7173,8 @@ skip_auth_type:
 
        if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
            params->key_mgmt_suite == KEY_MGMT_PSK ||
+           params->key_mgmt_suite == KEY_MGMT_FT_802_1X ||
+           params->key_mgmt_suite == KEY_MGMT_FT_PSK ||
            params->key_mgmt_suite == KEY_MGMT_CCKM) {
                int mgmt = WLAN_AKM_SUITE_PSK;
 
@@ -7152,6 +7185,12 @@ skip_auth_type:
                case KEY_MGMT_802_1X:
                        mgmt = WLAN_AKM_SUITE_8021X;
                        break;
+               case KEY_MGMT_FT_802_1X:
+                       mgmt = WLAN_AKM_SUITE_FT_8021X;
+                       break;
+               case KEY_MGMT_FT_PSK:
+                       mgmt = WLAN_AKM_SUITE_FT_PSK;
+                       break;
                case KEY_MGMT_PSK:
                default:
                        mgmt = WLAN_AKM_SUITE_PSK;
@@ -9628,6 +9667,39 @@ static int driver_nl80211_probe_req_report(void *priv, int report)
 }
 
 
+static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md,
+                                           const u8 *ies, size_t ies_len)
+{
+       int ret;
+       struct nl_msg *msg;
+       struct i802_bss *bss = priv;
+       struct wpa_driver_nl80211_data *drv = bss->drv;
+       u16 mdid = WPA_GET_LE16(md);
+
+       msg = nlmsg_alloc();
+       if (!msg)
+               return -ENOMEM;
+
+       wpa_printf(MSG_DEBUG, "nl80211: Updating FT IEs");
+       nl80211_cmd(drv, msg, 0, NL80211_CMD_UPDATE_FT_IES);
+       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+       NLA_PUT(msg, NL80211_ATTR_IE, ies_len, ies);
+       NLA_PUT_U16(msg, NL80211_ATTR_MDID, mdid);
+
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+       if (ret) {
+               wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed "
+                          "err=%d (%s)", ret, strerror(-ret));
+       }
+
+       return ret;
+
+nla_put_failure:
+       nlmsg_free(msg);
+       return -ENOBUFS;
+}
+
+
 const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .name = "nl80211",
        .desc = "Linux nl80211/cfg80211",
@@ -9703,4 +9775,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .send_tdls_mgmt = nl80211_send_tdls_mgmt,
        .tdls_oper = nl80211_tdls_oper,
 #endif /* CONFIG_TDLS */
+       .update_ft_ies = wpa_driver_nl80211_update_ft_ies,
 };
index 2df060ca87eb74900c2f5ed735a7f62de385c185..4b08a624d7701ce16ed94affc2a7177067d8e32a 100644 (file)
@@ -788,9 +788,12 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
        if (parse.ric) {
                wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response",
                            parse.ric, parse.ric_len);
-               /* TODO: parse response and inform driver about results */
+               /* TODO: parse response and inform driver about results when
+                * using wpa_supplicant SME */
        }
 
+       wpa_printf(MSG_DEBUG, "FT: Completed successfully");
+
        return 0;
 }
 
index 6c8ab6ca25ba99b929f0184ad37859b0b5c7f6ab..186db8aa281a43d0cb2fb88543164b21142552bc 100644 (file)
@@ -1438,6 +1438,7 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
 {
        int l, len, found = 0, wpa_found, rsn_found;
        const u8 *p;
+       u8 bssid[ETH_ALEN];
 
        wpa_dbg(wpa_s, MSG_DEBUG, "Association info event");
        if (data->assoc_info.req_ies)
@@ -1492,7 +1493,6 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
 #ifdef CONFIG_IEEE80211R
 #ifdef CONFIG_SME
        if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) {
-               u8 bssid[ETH_ALEN];
                if (wpa_drv_get_bssid(wpa_s, bssid) < 0 ||
                    wpa_ft_validate_reassoc_resp(wpa_s->wpa,
                                                 data->assoc_info.resp_ies,
@@ -1550,6 +1550,23 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
        }
 #endif /* CONFIG_SME */
 
+       /* Process FT when SME is in the driver */
+       if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+           wpa_ft_is_completed(wpa_s->wpa)) {
+               if (wpa_drv_get_bssid(wpa_s, bssid) < 0 ||
+                   wpa_ft_validate_reassoc_resp(wpa_s->wpa,
+                                                data->assoc_info.resp_ies,
+                                                data->assoc_info.resp_ies_len,
+                                                bssid) < 0) {
+                       wpa_dbg(wpa_s, MSG_DEBUG, "FT: Validation of "
+                               "Reassociation Response failed");
+                       wpa_supplicant_deauthenticate(
+                               wpa_s, WLAN_REASON_INVALID_IE);
+                       return -1;
+               }
+               wpa_dbg(wpa_s, MSG_DEBUG, "FT: Reassociation Response done");
+       }
+
        wpa_sm_set_ft_params(wpa_s->wpa, data->assoc_info.resp_ies,
                             data->assoc_info.resp_ies_len);
 #endif /* CONFIG_IEEE80211R */