[PATCH 3/3] Transparent FST: wpa_supplicant integration
Anton Nayshtut
Anton.Nayshtut
Mon Feb 17 06:43:21 PST 2014
From: Anton Nayshtut <Anton.Nayshtut at wilocity.com>
This patch integrates the FST into the wpa_supplicant.
Signed-off-by: Anton Nayshtut <Anton.Nayshtut at wilocity.com>
Signed-off-by: Erez Kirshenbaum <Erez.Kirshenbaum at wilocity.com>
---
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
};
--
1.8.3.1
More information about the Hostap
mailing list