aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant
diff options
context:
space:
mode:
authorJason Mobarak <x@jason.mobarak.name>2014-09-01 04:23:36 (GMT)
committerJouni Malinen <j@w1.fi>2014-11-16 17:43:11 (GMT)
commit5cfb672ddef7c4e6a7bd424345c8f962a6f94dfc (patch)
tree74a187931616eedb4a53fd83e4b3b9e44704dda1 /wpa_supplicant
parentc596f3f083d1638b72758f9106770b264ca40f84 (diff)
downloadhostap-5cfb672ddef7c4e6a7bd424345c8f962a6f94dfc.zip
hostap-5cfb672ddef7c4e6a7bd424345c8f962a6f94dfc.tar.gz
hostap-5cfb672ddef7c4e6a7bd424345c8f962a6f94dfc.tar.bz2
mesh: Enable mesh HT mode
Add a new option "mesh_ht_mode" that specifies the HT mode for the mesh, with this option on, mesh beacons, actions frames, and probe responses with include the appropriate HT information elements. [original implementation by Chun-Yeow Yeoh <yeohchunyeow@gmail.com>] [some fixes by Masashi Honma <masashi.honma@gmail.com>] Signed-off-by: Ashok Nagarajan <ashok.dragon@gmail.com> Signed-off-by: Javier Cardona <javier@cozybit.com> Signed-off-by: Jason Mobarak <x@jason.mobarak.name>
Diffstat (limited to 'wpa_supplicant')
-rw-r--r--wpa_supplicant/ap.c42
-rw-r--r--wpa_supplicant/ap.h5
-rw-r--r--wpa_supplicant/config.c66
-rw-r--r--wpa_supplicant/config_file.c1
-rw-r--r--wpa_supplicant/config_ssid.h10
-rw-r--r--wpa_supplicant/mesh.c6
-rw-r--r--wpa_supplicant/mesh_mpm.c21
7 files changed, 132 insertions, 19 deletions
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 02ea609..f3acbc1 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -75,24 +75,10 @@ no_vht:
#endif /* CONFIG_IEEE80211N */
-static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid,
- struct hostapd_config *conf)
+void wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ struct hostapd_config *conf)
{
- struct hostapd_bss_config *bss = conf->bss[0];
-
- conf->driver = wpa_s->driver;
-
- os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));
-
- conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
- &conf->channel);
- if (conf->hw_mode == NUM_HOSTAPD_MODES) {
- wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
- ssid->frequency);
- return -1;
- }
-
/* TODO: enable HT40 if driver supports it;
* drop to 11b if driver does not support 11g */
@@ -155,6 +141,28 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
}
}
#endif /* CONFIG_IEEE80211N */
+}
+
+
+static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ struct hostapd_config *conf)
+{
+ struct hostapd_bss_config *bss = conf->bss[0];
+
+ conf->driver = wpa_s->driver;
+
+ os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));
+
+ conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
+ &conf->channel);
+ if (conf->hw_mode == NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
+ ssid->frequency);
+ return -1;
+ }
+
+ wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
#ifdef CONFIG_P2P
if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G &&
diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h
index 8aa5ffa..4d80c7a 100644
--- a/wpa_supplicant/ap.h
+++ b/wpa_supplicant/ap.h
@@ -75,4 +75,9 @@ int wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id,
const struct wpabuf *pw, const u8 *pubkey_hash);
+struct hostapd_config;
+void wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ struct hostapd_config *conf);
+
#endif /* AP_H */
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 637cdf1..9e261ba 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1588,6 +1588,66 @@ static char * wpa_config_write_psk_list(const struct parse_data *data,
#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_MESH
+
+static int wpa_config_parse_mesh_ht_mode(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ int htval = 0;
+
+ if (os_strcmp(value, "NOHT") == 0)
+ htval = CHAN_NO_HT;
+ else if (os_strcmp(value, "HT20") == 0)
+ htval = CHAN_HT20;
+ else if (os_strcmp(value, "HT40-") == 0)
+ htval = CHAN_HT40MINUS;
+ else if (os_strcmp(value, "HT40+") == 0)
+ htval = CHAN_HT40PLUS;
+ else {
+ wpa_printf(MSG_ERROR,
+ "Line %d: no ht_mode configured.", line);
+ return -1;
+ }
+
+ wpa_printf(MSG_MSGDUMP, "mesh_ht_mode: 0x%x", htval);
+ ssid->mesh_ht_mode = htval;
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_mesh_ht_mode(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ char *val;
+
+ switch (ssid->mesh_ht_mode) {
+ default:
+ val = NULL;
+ break;
+ case CHAN_NO_HT:
+ val = "NOHT";
+ break;
+ case CHAN_HT20:
+ val = "HT20";
+ break;
+ case CHAN_HT40MINUS:
+ val = "HT40-";
+ break;
+ case CHAN_HT40PLUS:
+ val = "HT40+";
+ break;
+ }
+ return val ? os_strdup(val) : NULL;
+}
+
+#endif /* NO_CONFIG_WRITE */
+
+#endif /* CONFIG_MESH */
+
+
/* Helper macros for network block parser */
#ifdef OFFSET
@@ -1757,6 +1817,9 @@ static const struct parse_data ssid_fields[] = {
{ INT_RANGE(peerkey, 0, 1) },
{ INT_RANGE(mixed_cell, 0, 1) },
{ INT_RANGE(frequency, 0, 65000) },
+#ifdef CONFIG_MESH
+ { FUNC(mesh_ht_mode) },
+#endif /* CONFIG_MESH */
{ INT(wpa_ptk_rekey) },
{ STR(bgscan) },
{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
@@ -2235,6 +2298,9 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
ssid->eap.sim_num = DEFAULT_USER_SELECTED_SIM;
#endif /* IEEE8021X_EAPOL */
+#ifdef CONFIG_MESH
+ ssid->mesh_ht_mode = DEFAULT_MESH_HT_MODE;
+#endif /* CONFIG_MESH */
#ifdef CONFIG_HT_OVERRIDES
ssid->disable_ht = DEFAULT_DISABLE_HT;
ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index d58707e..852140f 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -743,6 +743,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
INT(update_identifier);
#endif /* CONFIG_HS20 */
write_int(f, "mac_addr", ssid->mac_addr, -1);
+ STR(mesh_ht_mode);
#undef STR
#undef INT
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index a4910d0..85d976c 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -27,6 +27,7 @@
#define DEFAULT_FRAGMENT_SIZE 1398
#define DEFAULT_BG_SCAN_PERIOD -1
+#define DEFAULT_MESH_HT_MODE CHAN_UNDEFINED /* undefined */
#define DEFAULT_DISABLE_HT 0
#define DEFAULT_DISABLE_HT40 0
#define DEFAULT_DISABLE_SGI 0
@@ -403,6 +404,15 @@ struct wpa_ssid {
*/
int frequency;
+ /**
+ * mesh_ht_mode - definition of HT mode in mesh mode
+ *
+ * Use the given HT mode for mesh networks. The driver will
+ * adapt to other stations if neccesary, but advertise the
+ * configured HT mode (HT20/HT40-/HT40+/NOHT).
+ */
+ int mesh_ht_mode;
+
int ht40;
int vht;
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 6439d64..4a6924b 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -21,6 +21,7 @@
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "notify.h"
+#include "ap.h"
#include "mesh_mpm.h"
#include "mesh_rsn.h"
#include "mesh.h"
@@ -241,6 +242,8 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
goto out_free;
}
+ wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
+
return 0;
out_free:
wpa_supplicant_mesh_deinit(wpa_s);
@@ -295,6 +298,9 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
params.meshid = ssid->ssid;
params.meshid_len = ssid->ssid_len;
params.freq = ssid->frequency;
+#ifdef CONFIG_IEEE80211N
+ params.ht_mode = ssid->mesh_ht_mode;
+#endif /* CONFIG_IEEE80211N */
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index e440d4f..322c96c 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -213,6 +213,9 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
struct hostapd_data *bss = ifmsh->bss[0];
struct mesh_conf *conf = ifmsh->mconf;
u8 supp_rates[2 + 2 + 32];
+#ifdef CONFIG_IEEE80211N
+ u8 ht_capa_oper[2 + 26 + 2 + 22];
+#endif /* CONFIG_IEEE80211N */
u8 *pos, *cat;
u8 ie_len, add_plid = 0;
int ret;
@@ -243,6 +246,7 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
/* capability info */
wpabuf_put_le16(buf, ampe ? IEEE80211_CAP_PRIVACY : 0);
+ /* aid */
if (type == PLINK_CONFIRM)
wpabuf_put_le16(buf, sta->peer_lid);
@@ -309,7 +313,14 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
mesh_rsn_get_pmkid(wpa_s->mesh_rsn, sta,
wpabuf_put(buf, PMKID_LEN));
- /* TODO HT IEs */
+#ifdef CONFIG_IEEE80211N
+ if (type != PLINK_CLOSE &&
+ wpa_s->current_ssid->mesh_ht_mode != CHAN_NO_HT) {
+ pos = hostapd_eid_ht_capabilities(bss, ht_capa_oper);
+ pos = hostapd_eid_ht_operation(bss, pos);
+ wpabuf_put_data(buf, ht_capa_oper, pos - ht_capa_oper);
+ }
+#endif /* CONFIG_IEEE80211N */
if (ampe && mesh_rsn_protect_frame(wpa_s->mesh_rsn, sta, cat, buf)) {
wpa_msg(wpa_s, MSG_INFO,
@@ -520,6 +531,12 @@ void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
mesh_mpm_init_link(wpa_s, sta);
+#ifdef CONFIG_IEEE80211N
+ copy_sta_ht_capab(data, sta, elems->ht_capabilities,
+ elems->ht_capabilities_len);
+ update_ht_state(data, sta);
+#endif /* CONFIG_IEEE80211N */
+
/* insert into driver */
os_memset(&params, 0, sizeof(params));
params.supp_rates = sta->supported_rates;
@@ -528,7 +545,7 @@ void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
params.plink_state = sta->plink_state;
params.aid = sta->peer_lid;
params.listen_interval = 100;
- /* TODO: HT capabilities */
+ params.ht_capabilities = sta->ht_capabilities;
params.flags |= WPA_STA_WMM;
params.flags_mask |= WPA_STA_AUTHENTICATED;
if (conf->security == MESH_CONF_SEC_NONE) {