FST: Integration into wpa_supplicant

This commit integrates the FST into the wpa_supplicant.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Anton Nayshtut 2014-11-16 17:28:53 +02:00 committed by Jouni Malinen
parent 55de4d4ba3
commit b36a3a65aa
7 changed files with 238 additions and 0 deletions

View file

@ -2000,6 +2000,19 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
if (wpa_found || rsn_found) if (wpa_found || rsn_found)
wpa_s->ap_ies_from_associnfo = 1; 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;
wpa_printf(MSG_DEBUG, "Looking for MB IE");
if (!mb_ies_info_by_ies(&mb_ies, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len))
wpa_s->received_mb_ies = mb_ies_by_info(&mb_ies);
}
#endif /* CONFIG_FST */
if (wpa_s->assoc_freq && data->assoc_info.freq && if (wpa_s->assoc_freq && data->assoc_info.freq &&
wpa_s->assoc_freq != data->assoc_info.freq) { wpa_s->assoc_freq != data->assoc_info.freq) {
wpa_printf(MSG_DEBUG, "Operating frequency changed from " wpa_printf(MSG_DEBUG, "Operating frequency changed from "

View file

@ -12,6 +12,7 @@
#endif /* __linux__ */ #endif /* __linux__ */
#include "common.h" #include "common.h"
#include "fst/fst.h"
#include "wpa_supplicant_i.h" #include "wpa_supplicant_i.h"
#include "driver_i.h" #include "driver_i.h"
#include "p2p_supplicant.h" #include "p2p_supplicant.h"
@ -309,6 +310,17 @@ int main(int argc, char *argv[])
"wpa_supplicant"); "wpa_supplicant");
} }
if (fst_global_init()) {
wpa_printf(MSG_ERROR, "Failed to initialize FST");
exitcode = -1;
goto out;
}
#if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
if (!fst_global_add_ctrl(fst_ctrl_cli))
wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
#endif
for (i = 0; exitcode == 0 && i < iface_count; i++) { for (i = 0; exitcode == 0 && i < iface_count; i++) {
struct wpa_supplicant *wpa_s; struct wpa_supplicant *wpa_s;
@ -334,6 +346,8 @@ int main(int argc, char *argv[])
wpa_supplicant_deinit(global); wpa_supplicant_deinit(global);
fst_global_deinit();
out: out:
wpa_supplicant_fd_workaround(0); wpa_supplicant_fd_workaround(0);
os_free(ifaces); os_free(ifaces);

View file

@ -17,6 +17,7 @@
#include "dbus/dbus_old.h" #include "dbus/dbus_old.h"
#include "dbus/dbus_new.h" #include "dbus/dbus_new.h"
#include "rsn_supp/wpa.h" #include "rsn_supp/wpa.h"
#include "fst/fst.h"
#include "driver_i.h" #include "driver_i.h"
#include "scan.h" #include "scan.h"
#include "p2p_supplicant.h" #include "p2p_supplicant.h"
@ -88,6 +89,16 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s,
/* notify the new DBus API */ /* notify the new DBus API */
wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATE); 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);
else if (old_state >= WPA_ASSOCIATED &&
new_state < WPA_ASSOCIATED)
fst_notify_peer_disconnected(wpa_s->fst, wpa_s->bssid);
}
#endif /* CONFIG_FST */
if (new_state == WPA_COMPLETED) if (new_state == WPA_COMPLETED)
wpas_p2p_notif_connected(wpa_s); wpas_p2p_notif_connected(wpa_s);
else if (old_state >= WPA_ASSOCIATED && new_state < WPA_ASSOCIATED) else if (old_state >= WPA_ASSOCIATED && new_state < WPA_ASSOCIATED)

View file

@ -485,6 +485,12 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
wpas_hs20_add_indication(extra_ie, -1); wpas_hs20_add_indication(extra_ie, -1);
#endif /* CONFIG_HS20 */ #endif /* CONFIG_HS20 */
#ifdef CONFIG_FST
if (wpa_s->fst_ies &&
wpabuf_resize(&extra_ie, wpabuf_len(wpa_s->fst_ies)) == 0)
wpabuf_put_buf(extra_ie, wpa_s->fst_ies);
#endif /* CONFIG_FST */
return extra_ie; return extra_ie;
} }

View file

@ -438,6 +438,21 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
} }
#endif /* CONFIG_HS20 */ #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 /* CONFIG_FST */
ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab, ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
sizeof(ext_capab)); sizeof(ext_capab));
if (ext_capab_len > 0) { if (ext_capab_len > 0) {

View file

@ -35,6 +35,7 @@
#include "common/ieee802_11_defs.h" #include "common/ieee802_11_defs.h"
#include "common/hw_features_common.h" #include "common/hw_features_common.h"
#include "p2p/p2p.h" #include "p2p/p2p.h"
#include "fst/fst.h"
#include "blacklist.h" #include "blacklist.h"
#include "wpas_glue.h" #include "wpas_glue.h"
#include "wps_supplicant.h" #include "wps_supplicant.h"
@ -2188,6 +2189,18 @@ 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 /* CONFIG_FST */
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL); wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
use_crypt = 1; use_crypt = 1;
cipher_pairwise = wpa_s->pairwise_cipher; cipher_pairwise = wpa_s->pairwise_cipher;
@ -3700,6 +3713,123 @@ int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
} }
#ifdef CONFIG_FST
static const u8 * wpas_fst_get_bssid_cb(void *ctx)
{
struct wpa_supplicant *wpa_s = ctx;
return (is_zero_ether_addr(wpa_s->bssid) ||
wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
}
static void wpas_fst_get_channel_info_cb(void *ctx,
enum hostapd_hw_mode *hw_mode,
u8 *channel)
{
struct wpa_supplicant *wpa_s = ctx;
if (wpa_s->current_bss) {
*hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
channel);
} else if (wpa_s->hw.num_modes) {
*hw_mode = wpa_s->hw.modes[0].mode;
} else {
WPA_ASSERT(0);
*hw_mode = 0;
}
}
static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
{
struct wpa_supplicant *wpa_s = ctx;
*modes = wpa_s->hw.modes;
return wpa_s->hw.num_modes;
}
static void wpas_fst_set_ies_cb(void *ctx, struct wpabuf *fst_ies)
{
struct wpa_supplicant *wpa_s = ctx;
wpa_s->fst_ies = fst_ies;
}
static int wpas_fst_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);
}
static struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
{
struct wpa_supplicant *wpa_s = ctx;
WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
return wpa_s->received_mb_ies;
}
static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
const u8 *buf, size_t size)
{
struct wpa_supplicant *wpa_s = ctx;
struct mb_ies_info info;
WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
if (!mb_ies_info_by_ies(&info, buf, size)) {
wpabuf_free(wpa_s->received_mb_ies);
wpa_s->received_mb_ies = mb_ies_by_info(&info);
}
}
const u8 * wpas_fst_get_peer_first(void *ctx, struct fst_get_peer_ctx **get_ctx,
Boolean mb_only)
{
struct wpa_supplicant *wpa_s = ctx;
*get_ctx = NULL;
if (!is_zero_ether_addr(wpa_s->bssid))
return (wpa_s->received_mb_ies || !mb_only) ?
wpa_s->bssid : NULL;
return NULL;
}
const u8 * wpas_fst_get_peer_next(void *ctx, struct fst_get_peer_ctx **get_ctx,
Boolean mb_only)
{
return NULL;
}
void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
struct fst_wpa_obj *iface_obj)
{
iface_obj->ctx = wpa_s;
iface_obj->get_bssid = wpas_fst_get_bssid_cb;
iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
iface_obj->set_ies = wpas_fst_set_ies_cb;
iface_obj->send_action = wpas_fst_send_action_cb;
iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
iface_obj->get_peer_first = wpas_fst_get_peer_first;
iface_obj->get_peer_next = wpas_fst_get_peer_next;
}
#endif /* CONFIG_FST */
static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s, static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
const struct wpa_driver_capa *capa) const struct wpa_driver_capa *capa)
{ {
@ -4238,6 +4368,28 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
return -1; return -1;
} }
#ifdef CONFIG_FST
if (wpa_s->conf->fst_group_id) {
struct fst_iface_cfg cfg;
struct fst_wpa_obj iface_obj;
fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
sizeof(cfg.group_id));
cfg.priority = wpa_s->conf->fst_priority;
cfg.llt = wpa_s->conf->fst_llt;
wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
&iface_obj, &cfg);
if (!wpa_s->fst) {
wpa_msg(wpa_s, MSG_ERROR,
"FST: Cannot attach iface %s to group %s",
wpa_s->ifname, cfg.group_id);
return -1;
}
}
#endif /* CONFIG_FST */
if (wpas_wps_init(wpa_s)) if (wpas_wps_init(wpa_s))
return -1; return -1;
@ -4346,6 +4498,17 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
wpas_ctrl_radio_work_flush(wpa_s); wpas_ctrl_radio_work_flush(wpa_s);
radio_remove_interface(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 /* CONFIG_FST */
if (wpa_s->drv_priv) if (wpa_s->drv_priv)
wpa_drv_deinit(wpa_s); wpa_drv_deinit(wpa_s);

View file

@ -977,6 +977,12 @@ struct wpa_supplicant {
u8 last_tspecs_count; u8 last_tspecs_count;
struct rrm_data rrm; struct rrm_data rrm;
#ifdef CONFIG_FST
struct fst_iface *fst;
struct wpabuf *fst_ies;
struct wpabuf *received_mb_ies;
#endif /* CONFIG_FST */
}; };
@ -1149,4 +1155,14 @@ int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
int *freq_array, unsigned int len); int *freq_array, unsigned int len);
void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx); void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx);
#ifdef CONFIG_FST
struct fst_wpa_obj;
void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
struct fst_wpa_obj *iface_obj);
#endif /* CONFIG_FST */
#endif /* WPA_SUPPLICANT_I_H */ #endif /* WPA_SUPPLICANT_I_H */