From patchwork Mon Feb 17 14:43:21 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Nayshtut X-Patchwork-Id: 321013 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from maxx.maxx.shmoo.com (maxx.shmoo.com [205.134.188.171]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 2C7942C00B3 for ; Tue, 18 Feb 2014 01:44:46 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 2F3F49C091; Mon, 17 Feb 2014 09:44:33 -0500 (EST) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HYElVm74Kl9j; Mon, 17 Feb 2014 09:44:32 -0500 (EST) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 1AD2C9C11F; Mon, 17 Feb 2014 09:44:02 -0500 (EST) X-Original-To: mailman-post+HostAP@maxx.shmoo.com Delivered-To: mailman-post+HostAP@maxx.shmoo.com Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 2A9AE9C091 for ; Mon, 17 Feb 2014 09:44:00 -0500 (EST) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id aKNakaHslNvB for ; Mon, 17 Feb 2014 09:43:54 -0500 (EST) Received: from mxout5.netvision.net.il (mxout5.netvision.net.il [194.90.6.65]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 29C269C121 for ; Mon, 17 Feb 2014 09:43:42 -0500 (EST) Received: from lap-wlt-dell.swtex.com ([192.117.6.36]) by mxout5.netvision.net.il (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0N1500GT2A8M3PO0@mxout5.netvision.net.il> for HostAP@lists.shmoo.com; Mon, 17 Feb 2014 16:43:37 +0200 (IST) From: Anton Nayshtut To: HostAP@lists.shmoo.com Subject: [PATCH 3/3] Transparent FST: wpa_supplicant integration Date: Mon, 17 Feb 2014 16:43:21 +0200 Message-id: <1392648201-7416-4-git-send-email-Anton.Nayshtut@Wilocity.com> X-Mailer: git-send-email 1.8.3.1 In-reply-to: <1392648201-7416-1-git-send-email-Anton.Nayshtut@Wilocity.com> References: <1392648201-7416-1-git-send-email-Anton.Nayshtut@Wilocity.com> Cc: Erez Kirshenbaum X-BeenThere: hostap@lists.shmoo.com X-Mailman-Version: 2.1.11 Precedence: list List-Id: HostAP Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: hostap-bounces@lists.shmoo.com Errors-To: hostap-bounces@lists.shmoo.com From: Anton Nayshtut This patch integrates the FST into the wpa_supplicant. Signed-off-by: Anton Nayshtut Signed-off-by: Erez Kirshenbaum --- wpa_supplicant/config.c | 7 +++ wpa_supplicant/config.h | 5 +++ wpa_supplicant/defconfig | 3 ++ wpa_supplicant/events.c | 48 +++++++++++++++++++- wpa_supplicant/main.c | 16 +++++++ wpa_supplicant/notify.c | 13 ++++++ wpa_supplicant/scan.c | 7 +++ wpa_supplicant/sme.c | 14 ++++++ wpa_supplicant/wpa_supplicant.c | 91 ++++++++++++++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant.conf | 20 +++++++++ wpa_supplicant/wpa_supplicant_i.h | 6 +++ 11 files changed, 229 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 2dd7054..c26cf6f 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1998,6 +1998,9 @@ void wpa_config_free(struct wpa_config *config) os_free(config->ext_password_backend); os_free(config->sae_groups); wpabuf_free(config->ap_vendor_elements); +#ifdef CONFIG_FST + os_free(config->fst_bond); +#endif os_free(config); } @@ -3401,6 +3404,10 @@ static const struct global_parse_data global_fields[] = { { INT(scan_cur_freq), 0 }, { INT(sched_scan_interval), 0 }, { INT(tdls_external_control), 0}, +#ifdef CONFIG_FST + { STR(fst_bond), 0 }, + { INT_RANGE(fst_default, 0, 1), 0 }, +#endif }; #undef FUNC diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index e7bdaa5..4d58077 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -953,6 +953,11 @@ struct wpa_config { u8 ip_addr_mask[4]; u8 ip_addr_start[4]; u8 ip_addr_end[4]; + +#ifdef CONFIG_FST + char *fst_bond; + int fst_default; +#endif }; diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index 6684782..75af101 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -495,3 +495,6 @@ CONFIG_PEERKEY=y # # External password backend for testing purposes (developer use) #CONFIG_EXT_PASSWORD_TEST=y + +# Enable Fast Session Transfer (FST) +# CONFIG_FST=y diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 47434e4..4a8fc2c 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -42,7 +42,9 @@ #include "scan.h" #include "offchannel.h" #include "interworking.h" - +#ifdef CONFIG_FST +#include "fst/fst.h" +#endif #ifndef CONFIG_NO_SCAN_PROCESSING static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s, @@ -1780,6 +1782,43 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, if (wpa_found || rsn_found) wpa_s->ap_ies_from_associnfo = 1; +#ifdef CONFIG_FST + wpabuf_free(wpa_s->received_mb_ies); + wpa_s->received_mb_ies = NULL; + if (wpa_s->fst) { + struct mb_ies_info mb_ies; + + os_memset(&mb_ies, 0, sizeof(mb_ies)); + + wpa_printf(MSG_DEBUG, "Looking for MB IE..."); + + p = data->assoc_info.beacon_ies; + l = data->assoc_info.beacon_ies_len; + p = data->assoc_info.resp_ies; + l = data->assoc_info.resp_ies_len; + + while (p && l >= 2 && mb_ies.nof_ies < MAX_NOF_MB_IES_SUPPORTED) { + len = p[1] + 2; + if (len > l) { + wpa_hexdump(MSG_DEBUG, "Truncated IE in beacon_ies", + p, l); + break; + } + + if (p[0] == WLAN_EID_MULTI_BAND) { + wpa_printf(MSG_DEBUG, "MB IE of %u bytes found", len); + mb_ies.ies[mb_ies.nof_ies].ie = p + 2; + mb_ies.ies[mb_ies.nof_ies].ie_len = len - 2; + ++mb_ies.nof_ies; + } + + l -= len; + p += len; + } + wpa_s->received_mb_ies = mb_ies_by_info(&mb_ies); + } +#endif + if (wpa_s->assoc_freq && data->assoc_info.freq && wpa_s->assoc_freq != data->assoc_info.freq) { wpa_printf(MSG_DEBUG, "Operating frequency changed from " @@ -2767,6 +2806,13 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_INTERWORKING */ +#ifdef CONFIG_FST + if (mgmt->u.action.category == WLAN_ACTION_FST && wpa_s->fst) { + fst_rx_action(wpa_s->fst, mgmt, len); + return; + } +#endif + #ifdef CONFIG_P2P wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid, category, payload, plen, freq); diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c index d56935d..f015de0 100644 --- a/wpa_supplicant/main.c +++ b/wpa_supplicant/main.c @@ -16,6 +16,11 @@ #include "driver_i.h" #include "p2p_supplicant.h" +#ifdef CONFIG_FST +#include "fst/fst.h" +#endif + +extern struct wpa_driver_ops *wpa_drivers[]; static void usage(void) { @@ -325,9 +330,20 @@ int main(int argc, char *argv[]) #endif /* CONFIG_P2P */ } +#ifdef CONFIG_FST + if (exitcode == 0 && fst_global_start()) { + wpa_printf(MSG_ERROR, "Failed to start FST"); + exitcode = -1; + } +#endif + if (exitcode == 0) exitcode = wpa_supplicant_run(global); +#ifdef CONFIG_FST + fst_global_stop(); +#endif + wpa_supplicant_deinit(global); out: diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c index a82fbf3..d99b93b 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -22,6 +22,9 @@ #include "p2p_supplicant.h" #include "sme.h" #include "notify.h" +#ifdef CONFIG_FST +#include "fst/fst.h" +#endif int wpas_notify_supplicant_initialized(struct wpa_global *global) { @@ -79,6 +82,16 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s, /* notify the new DBus API */ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATE); +#ifdef CONFIG_FST + if (wpa_s->fst && !is_zero_ether_addr(wpa_s->bssid)) { + if (new_state == WPA_COMPLETED) + fst_notify_peer_connected(wpa_s->fst, + wpa_s->bssid, wpa_s->received_mb_ies); + else if (old_state >= WPA_ASSOCIATED && new_state < WPA_ASSOCIATED) + fst_notify_peer_disconnected(wpa_s->fst, wpa_s->bssid); + } +#endif + #ifdef CONFIG_P2P if (new_state == WPA_COMPLETED) wpas_p2p_notif_connected(wpa_s); diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 6c742d6..3f6ad67 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -428,6 +428,13 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) wpas_hs20_add_indication(extra_ie); #endif /* CONFIG_HS20 */ +#ifdef CONFIG_FST + if (wpa_s->fst_ies) { + if (wpabuf_resize(&extra_ie, wpabuf_len(wpa_s->fst_ies)) == 0) + wpabuf_put_buf(extra_ie, wpa_s->fst_ies); + } +#endif + return extra_ie; } diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index e712ac4..61765a2 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -370,6 +370,20 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_HS20 */ +#ifdef CONFIG_FST + if (wpa_s->fst_ies) { + int fst_ies_len = wpabuf_len(wpa_s->fst_ies); + if (wpa_s->sme.assoc_req_ie_len + fst_ies_len <= + sizeof(wpa_s->sme.assoc_req_ie)) { + os_memcpy(wpa_s->sme.assoc_req_ie + + wpa_s->sme.assoc_req_ie_len, + wpabuf_head(wpa_s->fst_ies), + fst_ies_len); + wpa_s->sme.assoc_req_ie_len += fst_ies_len; + } + } +#endif + ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab); if (ext_capab_len > 0) { u8 *pos = wpa_s->sme.assoc_req_ie; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index e942b62..3df2476 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -51,6 +51,9 @@ #include "offchannel.h" #include "hs20_supplicant.h" #include "wnm_sta.h" +#ifdef CONFIG_FST +#include "fst/fst.h" +#endif const char *wpa_supplicant_version = "wpa_supplicant v" VERSION_STR "\n" @@ -1613,6 +1616,19 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) } } +#ifdef CONFIG_FST + if (wpa_s->fst_ies) + { + int fst_ies_len = wpabuf_len(wpa_s->fst_ies); + if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) { + os_memcpy(wpa_ie + wpa_ie_len, + wpabuf_head(wpa_s->fst_ies), + fst_ies_len); + wpa_ie_len += fst_ies_len; + } + } +#endif + wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL); use_crypt = 1; cipher_pairwise = wpa_s->pairwise_cipher; @@ -2995,6 +3011,37 @@ int wpas_init_ext_pw(struct wpa_supplicant *wpa_s) return 0; } +#ifdef CONFIG_FST +static const u8 * fst_wpa_supplicant_get_bssid_cb(void *ctx) +{ + struct wpa_supplicant *wpa_s = ctx; + return is_zero_ether_addr(wpa_s->bssid) ? NULL : wpa_s->bssid; +} + +static void fst_wpa_supplicant_get_channel_info_cb(void *ctx, + enum hostapd_hw_mode *hw_mode, u8 *channel) +{ + struct wpa_supplicant *wpa_s = ctx; + *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq, channel); +} + +static void fst_wpa_supplicant_set_ies_cb(void *ctx, + struct wpabuf *fst_ies) +{ + struct wpa_supplicant *wpa_s = ctx; + wpa_s->fst_ies = fst_ies; +} + +static int fst_wpa_supplicant_send_action_cb(void *ctx, const u8 *da, + struct wpabuf *data) +{ + struct wpa_supplicant *wpa_s = ctx; + WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0); + return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(data), wpabuf_len(data), 0); +} +#endif static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s, const char *rn) @@ -3472,6 +3519,27 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, return -1; } +#ifdef CONFIG_FST + if (wpa_s->conf->fst_bond[0]) { + struct fst_wpa_obj iface_obj = { + .ctx = wpa_s, + .get_bssid = fst_wpa_supplicant_get_bssid_cb, + .get_channel_info = fst_wpa_supplicant_get_channel_info_cb, + .set_ies = fst_wpa_supplicant_set_ies_cb, + .send_action = fst_wpa_supplicant_send_action_cb, + }; + wpa_s->fst = fst_attach(wpa_s->conf->fst_bond, + wpa_s->conf->fst_default, &iface_obj, wpa_s->ifname); + if (!wpa_s->fst) { + wpa_msg(wpa_s, MSG_ERROR, "Could not find FST %s", + wpa_s->conf->fst_bond); + return -1; + } + wpa_msg(wpa_s, MSG_DEBUG, "FST set: %s", + wpa_s->conf->fst_bond); + } +#endif + if (wpas_wps_init(wpa_s)) return -1; @@ -3559,6 +3627,17 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s, wpas_ctrl_radio_work_flush(wpa_s); radio_remove_interface(wpa_s); +#ifdef CONFIG_FST + if (wpa_s->fst) { + fst_detach(wpa_s->fst); + wpa_s->fst = NULL; + } + if (wpa_s->received_mb_ies) { + wpabuf_free(wpa_s->received_mb_ies); + wpa_s->received_mb_ies = NULL; + } +#endif + if (wpa_s->drv_priv) wpa_drv_deinit(wpa_s); @@ -3824,6 +3903,14 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params) wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR); +#ifdef CONFIG_FST + if (fst_global_init()) { + wpa_printf(MSG_ERROR, "Failed to initialize FST"); + wpa_supplicant_deinit(global); + return NULL; + } +#endif + if (eloop_init()) { wpa_printf(MSG_ERROR, "Failed to initialize event loop"); wpa_supplicant_deinit(global); @@ -3943,6 +4030,10 @@ void wpa_supplicant_deinit(struct wpa_global *global) eloop_destroy(); +#ifdef CONFIG_FST + fst_global_deinit(); +#endif + if (global->params.pid_file) { os_daemonize_terminate(global->params.pid_file); os_free(global->params.pid_file); diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 9d3bf6d..874cf69 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -920,6 +920,26 @@ fast_reauth=1 # 2: MCS 0-9 # 3: not supported +# Fast Session Transfer (FST) +# +# The options in this section are only available when the build configuration +# option CONFIG_FST is set while compiling hostapd. They allow this interface +# to be a part of FST setup. +# +# FST is the transfer of a session from a channel to another channel, in the +# same or different frequency bands. +# +# For detals, see WGA Specification. +# +# Bonding to be used for FST operations +##fst_bond=bond0 +# +# Whether the interface is the FST default +# Each fst_bond must have one and only one fst_default interface defined. +# 0 = don't use this interface as FST default +# 1 = use this interface as FST default +#fst_default=1 + # Example blocks: # Simple case: WPA-PSK, PSK as an ASCII passphrase, allow all valid ciphers diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index bcdb4d0..d0eb599 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -811,6 +811,12 @@ struct wpa_supplicant { struct wpa_radio_work *connect_work; unsigned int ext_work_id; + +#ifdef CONFIG_FST + struct fst_iface *fst; + struct wpabuf *fst_ies; + struct wpabuf *received_mb_ies; +#endif };