[PATCH 2/3] Transparent FST: hostapd integration
Anton Nayshtut
Anton.Nayshtut
Mon Feb 17 06:43:20 PST 2014
From: Anton Nayshtut <Anton.Nayshtut at wilocity.com>
This patch integrates the FST into the hostapd.
Signed-off-by: Anton Nayshtut <Anton.Nayshtut at wilocity.com>
Signed-off-by: Erez Kirshenbaum <Erez.Kirshenbaum at wilocity.com>
---
hostapd/config_file.c | 17 +++++++++++++
hostapd/defconfig | 3 +++
hostapd/hostapd.conf | 20 +++++++++++++++
hostapd/main.c | 25 ++++++++++++++++++-
src/ap/ap_config.h | 5 ++++
src/ap/ap_drv_ops.c | 15 +++++++++++
src/ap/beacon.c | 28 ++++++++++++++++++++-
src/ap/drv_callbacks.c | 27 ++++++++++++++++++++
src/ap/hostapd.c | 56 +++++++++++++++++++++++++++++++++++++++++-
src/ap/hostapd.h | 4 +++
src/ap/ieee802_11.c | 28 ++++++++++++++++++++-
src/ap/sta_info.c | 15 +++++++++++
src/ap/sta_info.h | 3 +++
src/ap/utils.c | 12 ++++++++-
src/common/ieee802_11_common.c | 34 +++++++++++++++++++++++++
src/common/ieee802_11_common.h | 15 +++++++++++
src/drivers/driver_nl80211.c | 11 +++++++++
17 files changed, 313 insertions(+), 5 deletions(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 19d6ad3..2f3fc14 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2907,6 +2907,23 @@ static int hostapd_config_fill(struct hostapd_config *conf,
"sae_groups value '%s'", line, pos);
return 1;
}
+#ifdef CONFIG_FST
+ } else if (os_strcmp(buf, "fst_bond") == 0) {
+ size_t len = os_strlen(pos);
+ if (!len || len > IFNAMSIZ) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid "
+ "fst_bond value '%s'", line, pos);
+ errors++;
+ } else if (conf->fst_bond[0]) {
+ wpa_printf(MSG_ERROR, "Line %d: Duplicate "
+ "fst_bond value '%s'", line, pos);
+ errors++;
+ } else
+ os_strlcpy(conf->fst_bond, pos,
+ sizeof(conf->fst_bond));
+ } else if (os_strcmp(buf, "fst_default") == 0) {
+ conf->fst_default = atoi(pos);
+#endif
} else {
wpa_printf(MSG_ERROR, "Line %d: unknown configuration "
"item '%s'", line, buf);
diff --git a/hostapd/defconfig b/hostapd/defconfig
index 8c8f0ea..3132fe6 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -286,6 +286,9 @@ CONFIG_IPV6=y
# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
#CONFIG_SQLITE=y
+# Enable Fast Session Transfer (FST)
+# CONFIG_FST=y
+
# Testing options
# This can be used to enable some testing options (see also the example
# configuration file) that are really useful only for testing clients that
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index c503ce2..8504130 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1666,3 +1666,23 @@ own_ip_addr=127.0.0.1
#bss=wlan0_1
#bssid=00:13:10:95:fe:0b
# ...
+
+##### Fast Session Transfer (FST) support #####################################
+#
+# 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
diff --git a/hostapd/main.c b/hostapd/main.c
index 3026929..e69c77d 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -27,7 +27,9 @@
#include "config_file.h"
#include "eap_register.h"
#include "ctrl_iface.h"
-
+#ifdef CONFIG_FST
+#include "fst/fst.h"
+#endif
struct hapd_global {
void **drv_priv;
@@ -654,6 +656,13 @@ int main(int argc, char *argv[])
return -1;
}
+#ifdef CONFIG_FST
+ if (fst_global_init()) {
+ wpa_printf(MSG_ERROR, "Failed to initilize global FST context");
+ goto out;
+ }
+#endif
+
/* Allocate and parse configuration for full interface files */
for (i = 0; i < interfaces.count; i++) {
interfaces.iface[i] = hostapd_interface_init(&interfaces,
@@ -716,6 +725,13 @@ int main(int argc, char *argv[])
goto out;
}
+#ifdef CONFIG_FST
+ if (fst_global_start()) {
+ wpa_printf(MSG_ERROR, "Failed to start FST");
+ goto out;
+ }
+#endif
+
hostapd_global_ctrl_iface_init(&interfaces);
if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
@@ -727,6 +743,9 @@ int main(int argc, char *argv[])
out:
hostapd_global_ctrl_iface_deinit(&interfaces);
+#ifdef CONFIG_FST
+ fst_global_stop();
+#endif
/* Deinitialize all interfaces */
for (i = 0; i < interfaces.count; i++)
hostapd_interface_deinit_free(interfaces.iface[i]);
@@ -741,6 +760,10 @@ int main(int argc, char *argv[])
os_free(bss_config);
+#ifdef CONFIG_FST
+ fst_global_deinit();
+#endif
+
os_program_deinit();
return ret;
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 4631ca9..d9fc525 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -543,6 +543,11 @@ struct hostapd_config {
u8 vht_oper_centr_freq_seg0_idx;
u8 vht_oper_centr_freq_seg1_idx;
+#ifdef CONFIG_FST
+ char fst_bond[IFNAMSIZ + 1];
+ int fst_default;
+#endif
+
#ifdef CONFIG_TESTING_OPTIONS
double ignore_probe_probability;
double ignore_auth_probability;
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index e998fc6..de25cfc 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -172,6 +172,21 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
}
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_FST
+ if (hapd->iface->fst_ies) {
+ size_t add = wpabuf_len(hapd->iface->fst_ies);
+ if (wpabuf_resize(&beacon, add) < 0)
+ goto fail;
+ wpabuf_put_buf(beacon, hapd->iface->fst_ies);
+ if (wpabuf_resize(&proberesp, add) < 0)
+ goto fail;
+ wpabuf_put_buf(proberesp, hapd->iface->fst_ies);
+ if (wpabuf_resize(&assocresp, add) < 0)
+ goto fail;
+ wpabuf_put_buf(assocresp, hapd->iface->fst_ies);
+ }
+#endif
+
if (hapd->conf->vendor_elements) {
size_t add = wpabuf_len(hapd->conf->vendor_elements);
if (wpabuf_resize(&beacon, add) == 0)
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index b1ebf6e..b130d7b 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -27,7 +27,9 @@
#include "ap_drv_ops.h"
#include "beacon.h"
#include "hs20.h"
-
+#ifdef CONFIG_FST
+#include "fst/fst.h"
+#endif
#ifdef NEED_AP_MLME
@@ -279,6 +281,10 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
if (hapd->p2p_probe_resp_ie)
buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
#endif /* CONFIG_P2P */
+#ifdef CONFIG_FST
+ if (hapd->iface->fst_ies)
+ buflen += wpabuf_len(hapd->iface->fst_ies);
+#endif
if (hapd->conf->vendor_elements)
buflen += wpabuf_len(hapd->conf->vendor_elements);
resp = os_zalloc(buflen);
@@ -376,6 +382,14 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
pos = hostapd_eid_hs20_indication(hapd, pos);
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_FST
+ if (hapd->iface->fst_ies) {
+ os_memcpy(pos, wpabuf_head(hapd->iface->fst_ies),
+ wpabuf_len(hapd->iface->fst_ies));
+ pos += wpabuf_len(hapd->iface->fst_ies);
+ }
+#endif
+
if (hapd->conf->vendor_elements) {
os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
wpabuf_len(hapd->conf->vendor_elements));
@@ -669,6 +683,11 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
if (hapd->p2p_beacon_ie)
tail_len += wpabuf_len(hapd->p2p_beacon_ie);
#endif /* CONFIG_P2P */
+#ifdef CONFIG_FST
+ if (hapd->iface->fst_ies) {
+ tail_len += wpabuf_len(hapd->iface->fst_ies);
+ }
+#endif
if (hapd->conf->vendor_elements)
tail_len += wpabuf_len(hapd->conf->vendor_elements);
tailpos = tail = os_malloc(tail_len);
@@ -780,6 +799,13 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
P2P_MANAGE)
tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
#endif /* CONFIG_P2P_MANAGER */
+#ifdef CONFIG_FST
+ if (hapd->iface->fst_ies) {
+ os_memcpy(tailpos, wpabuf_head(hapd->iface->fst_ies),
+ wpabuf_len(hapd->iface->fst_ies));
+ tailpos += wpabuf_len(hapd->iface->fst_ies);
+ }
+#endif
#ifdef CONFIG_HS20
tailpos = hostapd_eid_hs20_indication(hapd, tailpos);
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 9af9646..c546e82 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -31,6 +31,9 @@
#include "hw_features.h"
#include "dfs.h"
+#ifdef CONFIG_FST
+#include "fst/fst.h"
+#endif
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *req_ies, size_t req_ies_len, int reassoc)
@@ -131,6 +134,14 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
sta->hs20_ie = NULL;
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_FST
+ wpabuf_free(sta->mb_ies);
+ if (hapd->iface->fst) {
+ sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
+ } else
+ sta->mb_ies = NULL;
+#endif
+
if (hapd->conf->wpa) {
if (ie == NULL || ielen == 0) {
#ifdef CONFIG_WPS
@@ -301,6 +312,15 @@ skip_wpa_check:
sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
+ if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
+ sta->auth_alg == WLAN_AUTH_FT) {
+ /*
+ * Open, static WEP, or FT protocol; no separate authorization
+ * step.
+ */
+ ap_sta_set_authorized(hapd, sta, 1);
+ }
+
if (reassoc && (sta->auth_alg == WLAN_AUTH_FT))
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
else
@@ -602,6 +622,13 @@ static void hostapd_action_rx(struct hostapd_data *hapd,
ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len);
}
#endif /* CONFIG_WNM */
+#ifdef CONFIG_FST
+ if (mgmt->u.action.category == WLAN_ACTION_FST && hapd->iface->fst) {
+ fst_rx_action(hapd->iface->fst, mgmt, drv_mgmt->frame_len);
+ return;
+ }
+#endif
+
}
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index f9edf3b..477dccf 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -34,6 +34,9 @@
#include "gas_serv.h"
#include "dfs.h"
+#ifdef CONFIG_FST
+#include "fst/fst.h"
+#endif
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
@@ -533,7 +536,6 @@ static int hostapd_das_nas_mismatch(struct hostapd_data *hapd,
return 0;
}
-
static struct sta_info * hostapd_das_find_sta(struct hostapd_data *hapd,
struct radius_das_attrs *attr)
{
@@ -1072,6 +1074,37 @@ static int setup_interface2(struct hostapd_iface *iface)
return hostapd_setup_interface_complete(iface, 0);
}
+#ifdef CONFIG_FST
+static const u8 * fst_hostapd_get_bssid_cb(void *ctx)
+{
+ struct hostapd_data *hapd = ctx;
+ return hapd->own_addr;
+}
+
+static void fst_hostapd_get_channel_info_cb(void *ctx,
+ enum hostapd_hw_mode *hw_mode, u8 *channel)
+{
+ struct hostapd_data *hapd = ctx;
+ *hw_mode = ieee80211_freq_to_chan(hapd->iface->freq, channel);
+}
+
+
+static void fst_hostapd_set_ies_cb(void *ctx, struct wpabuf *fst_ies)
+{
+ struct hostapd_data *hapd = ctx;
+ if (hapd->iface->fst_ies != fst_ies) {
+ hapd->iface->fst_ies = fst_ies;
+ ieee802_11_set_beacon(hapd);
+ }
+}
+
+static int fst_hostapd_send_action_cb(void *ctx, const u8 *da, struct wpabuf *buf)
+{
+ struct hostapd_data *hapd = ctx;
+ return hostapd_drv_send_action(hapd, hapd->iface->freq, 0,
+ da, wpabuf_head(buf), wpabuf_len(buf));
+}
+#endif
/**
* hostapd_setup_interface_complete - Complete interface setup
@@ -1095,6 +1128,27 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
return -1;
}
+#ifdef CONFIG_FST
+ if (hapd->iconf->fst_bond[0]) {
+ struct fst_wpa_obj iface_obj = {
+ .ctx = hapd,
+ .get_bssid = fst_hostapd_get_bssid_cb,
+ .get_channel_info = fst_hostapd_get_channel_info_cb,
+ .set_ies = fst_hostapd_set_ies_cb,
+ .send_action = fst_hostapd_send_action_cb,
+ };
+ iface->fst = fst_attach(hapd->iconf->fst_bond,
+ hapd->iconf->fst_default, &iface_obj, hapd->conf->iface);
+ if (!iface->fst) {
+ wpa_printf(MSG_ERROR, "Could not attach to FST %s",
+ hapd->iconf->fst_bond);
+ return -1;
+ }
+ wpa_printf(MSG_DEBUG, "FST attached to %s (default=%d)",
+ hapd->iconf->fst_bond, hapd->iconf->fst_default);
+ }
+#endif
+
wpa_printf(MSG_DEBUG, "Completing interface initialization");
if (iface->conf->channel) {
#ifdef NEED_AP_MLME
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 489ab16..866b96f 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -272,6 +272,10 @@ struct hostapd_iface {
unsigned int wait_channel_update:1;
unsigned int cac_started:1;
+#ifdef CONFIG_FST
+ struct fst_iface *fst;
+ struct wpabuf *fst_ies;
+#endif
int num_ap; /* number of entries in ap_list */
struct ap_info *ap_list; /* AP info list head */
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 9251ac3..7c6cebc 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -38,7 +38,9 @@
#include "ap_drv_ops.h"
#include "wnm_ap.h"
#include "ieee802_11.h"
-
+#ifdef CONFIG_FST
+#include "fst/fst.h"
+#endif
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
{
@@ -1084,6 +1086,16 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
sta->hs20_ie = NULL;
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_FST
+ wpabuf_free(sta->mb_ies);
+ if (hapd->iface->fst) {
+ sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
+ }
+ else {
+ sta->mb_ies = NULL;
+ }
+#endif
+
return WLAN_STATUS_SUCCESS;
}
@@ -1215,6 +1227,14 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
p = hostapd_eid_p2p_manage(hapd, p);
#endif /* CONFIG_P2P_MANAGER */
+#ifdef CONFIG_FST
+ if (hapd->iface->fst_ies) {
+ os_memcpy(p, wpabuf_head(hapd->iface->fst_ies),
+ wpabuf_len(hapd->iface->fst_ies));
+ p += wpabuf_len(hapd->iface->fst_ies);
+ }
+#endif
+
send_len += p - reply->u.assoc_resp.variable;
if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0)
@@ -1607,6 +1627,12 @@ static int handle_action(struct hostapd_data *hapd,
ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
return 1;
#endif /* CONFIG_WNM */
+#ifdef CONFIG_FST
+ case WLAN_ACTION_FST:
+ if (hapd->iface->fst)
+ fst_rx_action(hapd->iface->fst, mgmt, len);
+ return 1;
+#endif /* CONFIG_FST */
case WLAN_ACTION_PUBLIC:
case WLAN_ACTION_PROTECTED_DUAL:
if (hapd->public_action_cb) {
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 24e764d..cd70436 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -31,6 +31,9 @@
#include "ap_drv_ops.h"
#include "gas_serv.h"
#include "sta_info.h"
+#ifdef CONFIG_FST
+#include "fst/fst.h"
+#endif
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
struct sta_info *sta);
@@ -259,6 +262,9 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
wpabuf_free(sta->wps_ie);
wpabuf_free(sta->p2p_ie);
wpabuf_free(sta->hs20_ie);
+#ifdef CONFIG_FST
+ wpabuf_free(sta->mb_ies);
+#endif
os_free(sta->ht_capabilities);
os_free(sta->vht_capabilities);
@@ -962,6 +968,15 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
sta->flags &= ~WLAN_STA_AUTHORIZED;
}
+#ifdef CONFIG_FST
+ if (hapd->iface->fst) {
+ if (authorized)
+ fst_notify_peer_connected(hapd->iface->fst, sta->addr, sta->mb_ies);
+ else
+ fst_notify_peer_disconnected(hapd->iface->fst, sta->addr);
+ }
+#endif
+
if (hapd->sta_authorized_cb)
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
sta->addr, authorized, dev_addr);
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 240b926..66db800 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -125,6 +125,9 @@ struct sta_info {
struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
struct wpabuf *hs20_ie; /* HS 2.0 IE from (Re)Association Request */
+#ifdef CONFIG_FST
+ struct wpabuf *mb_ies; /* MB IEs from (Re)Association Request */
+#endif
struct os_reltime connected_time;
diff --git a/src/ap/utils.c b/src/ap/utils.c
index 931968c..b97bebb 100644
--- a/src/ap/utils.c
+++ b/src/ap/utils.c
@@ -12,7 +12,9 @@
#include "common/ieee802_11_defs.h"
#include "sta_info.h"
#include "hostapd.h"
-
+#ifdef CONFIG_FST
+#include "fst/fst.h"
+#endif
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
int (*cb)(void *ctx, const u8 *sa,
@@ -55,6 +57,14 @@ static int prune_associations(struct hostapd_iface *iface, void *ctx)
ohapd = iface->bss[j];
if (ohapd == data->hapd)
continue;
+#ifdef CONFIG_FST
+ /* Don't prune STAs belong to same FST */
+ if (ohapd->iface->fst &&
+ data->hapd->iface->fst &&
+ fst_are_ifaces_aggregated(ohapd->iface->fst,
+ data->hapd->iface->fst))
+ continue;
+#endif
osta = ap_get_sta(ohapd, data->addr);
if (!osta)
continue;
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 50bdc01..10afc17 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -285,6 +285,18 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->ssid_list = pos;
elems->ssid_list_len = elen;
break;
+ case WLAN_EID_MULTI_BAND:
+ if (elems->mb_ies.nof_ies < MAX_NOF_MB_IES_SUPPORTED) {
+ elems->mb_ies.ies[elems->mb_ies.nof_ies].ie = pos;
+ elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
+ ++elems->mb_ies.nof_ies;
+ }
+ else {
+ wpa_printf(MSG_WARNING, "IEEE 802.11 element parse "
+ "ignored MB IE (id=%d elen=%d)",
+ id, elen);
+ }
+ break;
default:
unknown++;
if (!show_errors)
@@ -541,3 +553,25 @@ int supp_rates_11b_only(struct ieee802_11_elems *elems)
return num_11b > 0 && num_others == 0;
}
+
+struct wpabuf *mb_ies_by_info(struct mb_ies_info *info)
+{
+ struct wpabuf *mb_ies = NULL;
+ WPA_ASSERT(info != NULL);
+ if (info->nof_ies) {
+ u8 i;
+ size_t mb_ies_size = 0;
+ for (i = 0; i < info->nof_ies; i++) {
+ mb_ies_size += info->ies[i].ie_len + 2;
+ }
+ mb_ies = wpabuf_alloc(mb_ies_size);
+ if (mb_ies) {
+ for (i = 0; i < info->nof_ies; i++) {
+ wpabuf_put_data(mb_ies,
+ info->ies[i].ie - 2,
+ info->ies[i].ie_len + 2);
+ }
+ }
+ }
+ return mb_ies;
+}
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 4fb2e84..62fcb1c 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -9,6 +9,18 @@
#ifndef IEEE802_11_COMMON_H
#define IEEE802_11_COMMON_H
+#define MAX_NOF_MB_IES_SUPPORTED 5
+
+struct mb_ies_info
+{
+ struct
+ {
+ const u8 *ie;
+ u8 ie_len;
+ } ies[MAX_NOF_MB_IES_SUPPORTED];
+ u8 nof_ies;
+};
+
/* Parsed Information Elements */
struct ieee802_11_elems {
const u8 *ssid;
@@ -69,6 +81,8 @@ struct ieee802_11_elems {
u8 hs20_len;
u8 ext_capab_len;
u8 ssid_list_len;
+
+ struct mb_ies_info mb_ies;
};
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
@@ -95,5 +109,6 @@ int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel);
int supp_rates_11b_only(struct ieee802_11_elems *elems);
+struct wpabuf *mb_ies_by_info(struct mb_ies_info *info);
#endif /* IEEE802_11_COMMON_H */
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 32a371d..7d9ff25 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3827,6 +3827,11 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
drv->use_monitor = !info.poll_command_supported || !info.data_tx_status;
if (drv->device_ap_sme && drv->use_monitor) {
+#ifdef CONFIG_FST
+ wpa_printf(MSG_DEBUG, "nl80211: Disable use_monitor "
+ "with device_ap_sme due to FST");
+ drv->use_monitor = 0;
+#else
/*
* Non-mac80211 drivers may not support monitor interface.
* Make sure we do not get stuck with incorrect capability here
@@ -3838,6 +3843,7 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
"support detected");
drv->use_monitor = 0;
}
+#endif
}
/*
@@ -4358,6 +4364,11 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
ret = -1;
}
#endif /* CONFIG_TDLS */
+#ifdef CONFIG_FST
+ /* FST Action frames */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x12", 1) < 0)
+ ret = -1;
+#endif /* CONFIG_FST */
/* FT Action frames */
if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
--
1.8.3.1
More information about the Hostap
mailing list