summaryrefslogtreecommitdiffstats
path: root/contrib/wpa/hostapd
diff options
context:
space:
mode:
authorrpaulo <rpaulo@FreeBSD.org>2015-10-18 21:38:25 +0000
committerrpaulo <rpaulo@FreeBSD.org>2015-10-18 21:38:25 +0000
commitc437e26a1d8c13d53c6b57c8f8a8a28525fb34b0 (patch)
tree2a6d777bac31b66dc039b0c8eed342049d131f0b /contrib/wpa/hostapd
parent7b5d098c90f0f2e5151f5a80014ba3932988a132 (diff)
parent7726170474c6c89d386ba77b425d186e993a03a0 (diff)
downloadFreeBSD-src-c437e26a1d8c13d53c6b57c8f8a8a28525fb34b0.zip
FreeBSD-src-c437e26a1d8c13d53c6b57c8f8a8a28525fb34b0.tar.gz
Update hostapd/wpa_supplicant to version 2.5.
Tested by several people on current@/wireless@. Relnotes: yes
Diffstat (limited to 'contrib/wpa/hostapd')
-rw-r--r--contrib/wpa/hostapd/ChangeLog36
-rw-r--r--contrib/wpa/hostapd/config_file.c164
-rw-r--r--contrib/wpa/hostapd/config_file.h2
-rw-r--r--contrib/wpa/hostapd/ctrl_iface.c814
-rw-r--r--contrib/wpa/hostapd/defconfig12
-rw-r--r--contrib/wpa/hostapd/hlr_auc_gw.c48
-rw-r--r--contrib/wpa/hostapd/hlr_auc_gw.milenage_db4
-rw-r--r--contrib/wpa/hostapd/hostapd.conf115
-rw-r--r--contrib/wpa/hostapd/hostapd_cli.c91
-rw-r--r--contrib/wpa/hostapd/main.c43
10 files changed, 1149 insertions, 180 deletions
diff --git a/contrib/wpa/hostapd/ChangeLog b/contrib/wpa/hostapd/ChangeLog
index e6f8c6a..af54e1e 100644
--- a/contrib/wpa/hostapd/ChangeLog
+++ b/contrib/wpa/hostapd/ChangeLog
@@ -1,5 +1,41 @@
ChangeLog for hostapd
+2015-09-27 - v2.5
+ * fixed WPS UPnP vulnerability with HTTP chunked transfer encoding
+ [http://w1.fi/security/2015-2/] (CVE-2015-4141)
+ * fixed WMM Action frame parser
+ [http://w1.fi/security/2015-3/] (CVE-2015-4142)
+ * fixed EAP-pwd server missing payload length validation
+ [http://w1.fi/security/2015-4/]
+ (CVE-2015-4143, CVE-2015-4144, CVE-2015-4145)
+ * fixed validation of WPS and P2P NFC NDEF record payload length
+ [http://w1.fi/security/2015-5/]
+ * nl80211:
+ - fixed vendor command handling to check OUI properly
+ * fixed hlr_auc_gw build with OpenSSL
+ * hlr_auc_gw: allow Milenage RES length to be reduced
+ * disable HT for a station that does not support WMM/QoS
+ * added support for hashed password (NtHash) in EAP-pwd server
+ * fixed and extended dynamic VLAN cases
+ * added EAP-EKE server support for deriving Session-Id
+ * set Acct-Session-Id to a random value to make it more likely to be
+ unique even if the device does not have a proper clock
+ * added more 2.4 GHz channels for 20/40 MHz HT co-ex scan
+ * modified SAE routines to be more robust and PWE generation to be
+ stronger against timing attacks
+ * added support for Brainpool Elliptic Curves with SAE
+ * increases maximum value accepted for cwmin/cwmax
+ * added support for CCMP-256 and GCMP-256 as group ciphers with FT
+ * added Fast Session Transfer (FST) module
+ * removed optional fields from RSNE when using FT with PMF
+ (workaround for interoperability issues with iOS 8.4)
+ * added EAP server support for TLS session resumption
+ * fixed key derivation for Suite B 192-bit AKM (this breaks
+ compatibility with the earlier version)
+ * added mechanism to track unconnected stations and do minimal band
+ steering
+ * number of small fixes
+
2015-03-15 - v2.4
* allow OpenSSL cipher configuration to be set for internal EAP server
(openssl_ciphers parameter)
diff --git a/contrib/wpa/hostapd/config_file.c b/contrib/wpa/hostapd/config_file.c
index 53143f7..82ac61d 100644
--- a/contrib/wpa/hostapd/config_file.c
+++ b/contrib/wpa/hostapd/config_file.c
@@ -222,9 +222,15 @@ static int hostapd_config_read_eap_user(const char *fname,
return 0;
if (os_strncmp(fname, "sqlite:", 7) == 0) {
+#ifdef CONFIG_SQLITE
os_free(conf->eap_user_sqlite);
conf->eap_user_sqlite = os_strdup(fname + 7);
return 0;
+#else /* CONFIG_SQLITE */
+ wpa_printf(MSG_ERROR,
+ "EAP user file in SQLite DB, but CONFIG_SQLITE was not enabled in the build.");
+ return -1;
+#endif /* CONFIG_SQLITE */
}
f = fopen(fname, "r");
@@ -775,6 +781,24 @@ static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
}
+static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
+{
+ char *pos;
+
+ /* for backwards compatibility, translate ' ' in conf str to ',' */
+ pos = val;
+ while (pos) {
+ pos = os_strchr(pos, ' ');
+ if (pos)
+ *pos++ = ',';
+ }
+ if (freq_range_list_parse(&conf->acs_ch_list, val))
+ return -1;
+
+ return 0;
+}
+
+
static int hostapd_parse_intlist(int **int_list, char *val)
{
int *list;
@@ -875,7 +899,9 @@ static int hostapd_config_read_int10(const char *value)
static int valid_cw(int cw)
{
return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 ||
- cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023);
+ cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 ||
+ cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 ||
+ cw == 32767);
}
@@ -886,11 +912,11 @@ enum {
IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */
};
-static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name,
- char *val)
+static int hostapd_config_tx_queue(struct hostapd_config *conf,
+ const char *name, const char *val)
{
int num;
- char *pos;
+ const char *pos;
struct hostapd_tx_queue_params *queue;
/* skip 'tx_queue_' prefix */
@@ -1134,13 +1160,23 @@ static int hostapd_config_vht_capab(struct hostapd_config *conf,
if (os_strstr(capab, "[BF-ANTENNA-2]") &&
(conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
conf->vht_capab |= (1 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
+ if (os_strstr(capab, "[BF-ANTENNA-3]") &&
+ (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
+ conf->vht_capab |= (2 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
+ if (os_strstr(capab, "[BF-ANTENNA-4]") &&
+ (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
+ conf->vht_capab |= (3 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") &&
(conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
conf->vht_capab |= (1 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
+ if (os_strstr(capab, "[SOUNDING-DIMENSION-3]") &&
+ (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
+ conf->vht_capab |= (2 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
+ if (os_strstr(capab, "[SOUNDING-DIMENSION-4]") &&
+ (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
+ conf->vht_capab |= (3 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
if (os_strstr(capab, "[MU-BEAMFORMER]"))
conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE;
- if (os_strstr(capab, "[MU-BEAMFORMEE]"))
- conf->vht_capab |= VHT_CAP_MU_BEAMFORMEE_CAPABLE;
if (os_strstr(capab, "[VHT-TXOP-PS]"))
conf->vht_capab |= VHT_CAP_VHT_TXOP_PS;
if (os_strstr(capab, "[HTC-VHT]"))
@@ -1699,7 +1735,7 @@ static int hs20_parse_osu_ssid(struct hostapd_bss_config *bss,
char *str;
str = wpa_config_parse_string(pos, &slen);
- if (str == NULL || slen < 1 || slen > HOSTAPD_MAX_SSID_LEN) {
+ if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, pos);
os_free(str);
return -1;
@@ -1900,7 +1936,7 @@ fail:
static int hostapd_config_fill(struct hostapd_config *conf,
struct hostapd_bss_config *bss,
- char *buf, char *pos, int line)
+ const char *buf, char *pos, int line)
{
if (os_strcmp(buf, "interface") == 0) {
os_strlcpy(conf->bss[0]->iface, pos,
@@ -1946,7 +1982,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line);
} else if (os_strcmp(buf, "ssid") == 0) {
bss->ssid.ssid_len = os_strlen(pos);
- if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN ||
+ if (bss->ssid.ssid_len > SSID_MAX_LEN ||
bss->ssid.ssid_len < 1) {
wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
line, pos);
@@ -1957,7 +1993,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "ssid2") == 0) {
size_t slen;
char *str = wpa_config_parse_string(pos, &slen);
- if (str == NULL || slen < 1 || slen > HOSTAPD_MAX_SSID_LEN) {
+ if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
line, pos);
os_free(str);
@@ -2043,6 +2079,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->private_key_passwd = os_strdup(pos);
} else if (os_strcmp(buf, "check_crl") == 0) {
bss->check_crl = atoi(pos);
+ } else if (os_strcmp(buf, "tls_session_lifetime") == 0) {
+ bss->tls_session_lifetime = atoi(pos);
} else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
os_free(bss->ocsp_stapling_response);
bss->ocsp_stapling_response = os_strdup(pos);
@@ -2515,13 +2553,17 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
else if (os_strcmp(pos, "ad") == 0)
conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
+ else if (os_strcmp(pos, "any") == 0)
+ conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY;
else {
wpa_printf(MSG_ERROR, "Line %d: unknown hw_mode '%s'",
line, pos);
return 1;
}
} else if (os_strcmp(buf, "wps_rf_bands") == 0) {
- if (os_strcmp(pos, "a") == 0)
+ if (os_strcmp(pos, "ad") == 0)
+ bss->wps_rf_bands = WPS_RF_60GHZ;
+ else if (os_strcmp(pos, "a") == 0)
bss->wps_rf_bands = WPS_RF_50GHZ;
else if (os_strcmp(pos, "g") == 0 ||
os_strcmp(pos, "b") == 0)
@@ -2542,12 +2584,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line);
return 1;
#else /* CONFIG_ACS */
+ conf->acs = 1;
conf->channel = 0;
#endif /* CONFIG_ACS */
- } else
+ } else {
conf->channel = atoi(pos);
+ conf->acs = conf->channel == 0;
+ }
} else if (os_strcmp(buf, "chanlist") == 0) {
- if (hostapd_parse_intlist(&conf->chanlist, pos)) {
+ if (hostapd_parse_chanlist(conf, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid channel list",
line);
return 1;
@@ -2810,7 +2855,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
os_free(bss->wps_pin_requests);
bss->wps_pin_requests = os_strdup(pos);
} else if (os_strcmp(buf, "device_name") == 0) {
- if (os_strlen(pos) > 32) {
+ if (os_strlen(pos) > WPS_DEV_NAME_MAX_LEN) {
wpa_printf(MSG_ERROR, "Line %d: Too long "
"device_name", line);
return 1;
@@ -3111,6 +3156,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->disable_dgaf = atoi(pos);
} else if (os_strcmp(buf, "proxy_arp") == 0) {
bss->proxy_arp = atoi(pos);
+ } else if (os_strcmp(buf, "na_mcast_to_ucast") == 0) {
+ bss->na_mcast_to_ucast = atoi(pos);
} else if (os_strcmp(buf, "osen") == 0) {
bss->osen = atoi(pos);
} else if (os_strcmp(buf, "anqp_domain_id") == 0) {
@@ -3223,6 +3270,24 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->bss_load_test_set = 1;
} else if (os_strcmp(buf, "radio_measurements") == 0) {
bss->radio_measurements = atoi(pos);
+ } else if (os_strcmp(buf, "own_ie_override") == 0) {
+ struct wpabuf *tmp;
+ size_t len = os_strlen(pos) / 2;
+
+ tmp = wpabuf_alloc(len);
+ if (!tmp)
+ return 1;
+
+ if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) {
+ wpabuf_free(tmp);
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid own_ie_override '%s'",
+ line, pos);
+ return 1;
+ }
+
+ wpabuf_free(bss->own_ie_override);
+ bss->own_ie_override = tmp;
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strcmp(buf, "vendor_elements") == 0) {
struct wpabuf *elems;
@@ -3276,6 +3341,74 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "wowlan_triggers") == 0) {
os_free(bss->wowlan_triggers);
bss->wowlan_triggers = os_strdup(pos);
+#ifdef CONFIG_FST
+ } else if (os_strcmp(buf, "fst_group_id") == 0) {
+ size_t len = os_strlen(pos);
+
+ if (!len || len >= sizeof(conf->fst_cfg.group_id)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid fst_group_id value '%s'",
+ line, pos);
+ return 1;
+ }
+
+ if (conf->fst_cfg.group_id[0]) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Duplicate fst_group value '%s'",
+ line, pos);
+ return 1;
+ }
+
+ os_strlcpy(conf->fst_cfg.group_id, pos,
+ sizeof(conf->fst_cfg.group_id));
+ } else if (os_strcmp(buf, "fst_priority") == 0) {
+ char *endp;
+ long int val;
+
+ if (!*pos) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: fst_priority value not supplied (expected 1..%u)",
+ line, FST_MAX_PRIO_VALUE);
+ return -1;
+ }
+
+ val = strtol(pos, &endp, 0);
+ if (*endp || val < 1 || val > FST_MAX_PRIO_VALUE) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid fst_priority %ld (%s) (expected 1..%u)",
+ line, val, pos, FST_MAX_PRIO_VALUE);
+ return 1;
+ }
+ conf->fst_cfg.priority = (u8) val;
+ } else if (os_strcmp(buf, "fst_llt") == 0) {
+ char *endp;
+ long int val;
+
+ if (!*pos) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: fst_llt value not supplied (expected 1..%u)",
+ line, FST_MAX_LLT_MS);
+ return -1;
+ }
+ val = strtol(pos, &endp, 0);
+ if (*endp || val < 1 || val > FST_MAX_LLT_MS) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid fst_llt %ld (%s) (expected 1..%u)",
+ line, val, pos, FST_MAX_LLT_MS);
+ return 1;
+ }
+ conf->fst_cfg.llt = (u32) val;
+#endif /* CONFIG_FST */
+ } else if (os_strcmp(buf, "track_sta_max_num") == 0) {
+ conf->track_sta_max_num = atoi(pos);
+ } else if (os_strcmp(buf, "track_sta_max_age") == 0) {
+ conf->track_sta_max_age = atoi(pos);
+ } else if (os_strcmp(buf, "no_probe_resp_if_seen_on") == 0) {
+ os_free(bss->no_probe_resp_if_seen_on);
+ bss->no_probe_resp_if_seen_on = os_strdup(pos);
+ } else if (os_strcmp(buf, "no_auth_if_seen_on") == 0) {
+ os_free(bss->no_auth_if_seen_on);
+ bss->no_auth_if_seen_on = os_strdup(pos);
} else {
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",
@@ -3378,7 +3511,8 @@ struct hostapd_config * hostapd_config_read(const char *fname)
int hostapd_set_iface(struct hostapd_config *conf,
- struct hostapd_bss_config *bss, char *field, char *value)
+ struct hostapd_bss_config *bss, const char *field,
+ char *value)
{
int errors;
size_t i;
diff --git a/contrib/wpa/hostapd/config_file.h b/contrib/wpa/hostapd/config_file.h
index fba57b8..c98bdb6 100644
--- a/contrib/wpa/hostapd/config_file.h
+++ b/contrib/wpa/hostapd/config_file.h
@@ -11,7 +11,7 @@
struct hostapd_config * hostapd_config_read(const char *fname);
int hostapd_set_iface(struct hostapd_config *conf,
- struct hostapd_bss_config *bss, char *field,
+ struct hostapd_bss_config *bss, const char *field,
char *value);
#endif /* CONFIG_FILE_H */
diff --git a/contrib/wpa/hostapd/ctrl_iface.c b/contrib/wpa/hostapd/ctrl_iface.c
index 86f1aa6..cb6fb17 100644
--- a/contrib/wpa/hostapd/ctrl_iface.c
+++ b/contrib/wpa/hostapd/ctrl_iface.c
@@ -25,6 +25,7 @@
#include "common/ieee802_11_defs.h"
#include "crypto/tls.h"
#include "drivers/driver.h"
+#include "eapol_auth/eapol_auth_sm.h"
#include "radius/radius_client.h"
#include "radius/radius_server.h"
#include "l2_packet/l2_packet.h"
@@ -43,10 +44,13 @@
#include "ap/beacon.h"
#include "wps/wps_defs.h"
#include "wps/wps.h"
+#include "fst/fst_ctrl_iface.h"
#include "config_file.h"
#include "ctrl_iface.h"
+#define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
+
struct wpa_ctrl_dst {
struct wpa_ctrl_dst *next;
struct sockaddr_un addr;
@@ -57,6 +61,7 @@ struct wpa_ctrl_dst {
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+ enum wpa_msg_type type,
const char *buf, size_t len);
@@ -1055,6 +1060,97 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
#endif /* CONFIG_WNM */
+static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd,
+ char *buf, size_t buflen)
+{
+ int ret = 0;
+ char *pos, *end;
+
+ pos = buf;
+ end = buf + buflen;
+
+ WPA_ASSERT(hapd->conf->wpa_key_mgmt);
+
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
+ ret = os_snprintf(pos, end - pos, "WPA-PSK ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
+ ret = os_snprintf(pos, end - pos, "WPA-EAP ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#ifdef CONFIG_IEEE80211R
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
+ ret = os_snprintf(pos, end - pos, "FT-PSK ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
+ ret = os_snprintf(pos, end - pos, "FT-EAP ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#ifdef CONFIG_SAE
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
+ ret = os_snprintf(pos, end - pos, "FT-SAE ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_SAE */
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IEEE80211W
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
+ ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
+ ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_SAE
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
+ ret = os_snprintf(pos, end - pos, "SAE ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_SAE */
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
+ ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+ if (hapd->conf->wpa_key_mgmt &
+ WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
+ ret = os_snprintf(pos, end - pos,
+ "WPA-EAP-SUITE-B-192 ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+
+ if (pos > buf && *(pos - 1) == ' ') {
+ *(pos - 1) = '\0';
+ pos--;
+ }
+
+ return pos - buf;
+}
+
+
static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
char *buf, size_t buflen)
{
@@ -1104,82 +1200,20 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
}
#endif /* CONFIG_WPS */
+ if (hapd->conf->wpa) {
+ ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa);
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+
if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
ret = os_snprintf(pos, end - pos, "key_mgmt=");
if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
- if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
- ret = os_snprintf(pos, end - pos, "WPA-PSK ");
- if (os_snprintf_error(end - pos, ret))
- return pos - buf;
- pos += ret;
- }
- if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
- ret = os_snprintf(pos, end - pos, "WPA-EAP ");
- if (os_snprintf_error(end - pos, ret))
- return pos - buf;
- pos += ret;
- }
-#ifdef CONFIG_IEEE80211R
- if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
- ret = os_snprintf(pos, end - pos, "FT-PSK ");
- if (os_snprintf_error(end - pos, ret))
- return pos - buf;
- pos += ret;
- }
- if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
- ret = os_snprintf(pos, end - pos, "FT-EAP ");
- if (os_snprintf_error(end - pos, ret))
- return pos - buf;
- pos += ret;
- }
-#ifdef CONFIG_SAE
- if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
- ret = os_snprintf(pos, end - pos, "FT-SAE ");
- if (os_snprintf_error(end - pos, ret))
- return pos - buf;
- pos += ret;
- }
-#endif /* CONFIG_SAE */
-#endif /* CONFIG_IEEE80211R */
-#ifdef CONFIG_IEEE80211W
- if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
- ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
- if (os_snprintf_error(end - pos, ret))
- return pos - buf;
- pos += ret;
- }
- if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
- ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
- if (os_snprintf_error(end - pos, ret))
- return pos - buf;
- pos += ret;
- }
-#endif /* CONFIG_IEEE80211W */
-#ifdef CONFIG_SAE
- if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
- ret = os_snprintf(pos, end - pos, "SAE ");
- if (os_snprintf_error(end - pos, ret))
- return pos - buf;
- pos += ret;
- }
-#endif /* CONFIG_SAE */
- if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
- ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
- if (os_snprintf_error(end - pos, ret))
- return pos - buf;
- pos += ret;
- }
- if (hapd->conf->wpa_key_mgmt &
- WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
- ret = os_snprintf(pos, end - pos,
- "WPA-EAP-SUITE-B-192 ");
- if (os_snprintf_error(end - pos, ret))
- return pos - buf;
- pos += ret;
- }
+ pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos);
ret = os_snprintf(pos, end - pos, "\n");
if (os_snprintf_error(end - pos, ret))
@@ -1528,7 +1562,7 @@ void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
{
struct hostapd_data *hapd = ctx;
const struct ether_header *eth;
- const struct iphdr *ip;
+ struct iphdr ip;
const u8 *pos;
unsigned int i;
@@ -1536,14 +1570,14 @@ void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
return;
eth = (const struct ether_header *) buf;
- ip = (const struct iphdr *) (eth + 1);
- pos = (const u8 *) (ip + 1);
+ os_memcpy(&ip, eth + 1, sizeof(ip));
+ pos = &buf[sizeof(*eth) + sizeof(ip)];
- if (ip->ihl != 5 || ip->version != 4 ||
- ntohs(ip->tot_len) != HWSIM_IP_LEN)
+ if (ip.ihl != 5 || ip.version != 4 ||
+ ntohs(ip.tot_len) != HWSIM_IP_LEN)
return;
- for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) {
+ for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
if (*pos != (u8) i)
return;
pos++;
@@ -1599,7 +1633,7 @@ static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
int used;
long int val;
u8 tos;
- u8 buf[HWSIM_PACKETLEN];
+ u8 buf[2 + HWSIM_PACKETLEN];
struct ether_header *eth;
struct iphdr *ip;
u8 *dpos;
@@ -1627,7 +1661,7 @@ static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
return -1;
tos = val;
- eth = (struct ether_header *) buf;
+ eth = (struct ether_header *) &buf[2];
os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
os_memcpy(eth->ether_shost, src, ETH_ALEN);
eth->ether_type = htons(ETHERTYPE_IP);
@@ -1639,14 +1673,14 @@ static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
ip->tos = tos;
ip->tot_len = htons(HWSIM_IP_LEN);
ip->protocol = 1;
- ip->saddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 1);
- ip->daddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 2);
+ ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
+ ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
dpos = (u8 *) (ip + 1);
for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
*dpos++ = i;
- if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, buf,
+ if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2],
HWSIM_PACKETLEN) < 0)
return -1;
@@ -1746,6 +1780,45 @@ static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
#endif /* WPA_TRACE_BFD */
}
+
+static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd)
+{
+#ifdef WPA_TRACE_BFD
+ extern char wpa_trace_test_fail_func[256];
+ extern unsigned int wpa_trace_test_fail_after;
+ char *pos;
+
+ wpa_trace_test_fail_after = atoi(cmd);
+ pos = os_strchr(cmd, ':');
+ if (pos) {
+ pos++;
+ os_strlcpy(wpa_trace_test_fail_func, pos,
+ sizeof(wpa_trace_test_fail_func));
+ } else {
+ wpa_trace_test_fail_after = 0;
+ }
+
+ return 0;
+#else /* WPA_TRACE_BFD */
+ return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
+static int hostapd_ctrl_get_fail(struct hostapd_data *hapd,
+ char *buf, size_t buflen)
+{
+#ifdef WPA_TRACE_BFD
+ extern char wpa_trace_test_fail_func[256];
+ extern unsigned int wpa_trace_test_fail_after;
+
+ return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
+ wpa_trace_test_fail_func);
+#else /* WPA_TRACE_BFD */
+ return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
#endif /* CONFIG_TESTING_OPTIONS */
@@ -1847,41 +1920,134 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
}
-static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
- void *sock_ctx)
+static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd,
+ const char *cmd)
{
- struct hostapd_data *hapd = eloop_ctx;
- char buf[4096];
- int res;
- struct sockaddr_un from;
- socklen_t fromlen = sizeof(from);
- char *reply;
- const int reply_size = 4096;
- int reply_len;
- int level = MSG_DEBUG;
+ u8 addr[ETH_ALEN];
+ struct sta_info *sta;
- res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
- (struct sockaddr *) &from, &fromlen);
- if (res < 0) {
- wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
- strerror(errno));
- return;
+ if (hwaddr_aton(cmd, addr))
+ return -1;
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta || !sta->eapol_sm)
+ return -1;
+
+ eapol_auth_reauthenticate(sta->eapol_sm);
+ return 0;
+}
+
+
+static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ struct sta_info *sta;
+ char *pos = cmd, *param;
+
+ if (hwaddr_aton(pos, addr) || pos[17] != ' ')
+ return -1;
+ pos += 18;
+ param = pos;
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ return -1;
+ *pos++ = '\0';
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta || !sta->eapol_sm)
+ return -1;
+
+ return eapol_auth_set_conf(sta->eapol_sm, param, pos);
+}
+
+
+static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd,
+ char *buf, size_t buflen)
+{
+ char *pos, *end, *stamp;
+ int ret;
+
+ /* cmd: "LOG_LEVEL [<level>]" */
+ if (*cmd == '\0') {
+ pos = buf;
+ end = buf + buflen;
+ ret = os_snprintf(pos, end - pos, "Current level: %s\n"
+ "Timestamp: %d\n",
+ debug_level_str(wpa_debug_level),
+ wpa_debug_timestamp);
+ if (os_snprintf_error(end - pos, ret))
+ ret = 0;
+
+ return ret;
}
- buf[res] = '\0';
- if (os_strcmp(buf, "PING") == 0)
- level = MSG_EXCESSIVE;
- wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
- reply = os_malloc(reply_size);
- if (reply == NULL) {
- if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
- fromlen) < 0) {
- wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
- strerror(errno));
+ while (*cmd == ' ')
+ cmd++;
+
+ stamp = os_strchr(cmd, ' ');
+ if (stamp) {
+ *stamp++ = '\0';
+ while (*stamp == ' ') {
+ stamp++;
}
- return;
}
+ if (os_strlen(cmd)) {
+ int level = str_to_debug_level(cmd);
+ if (level < 0)
+ return -1;
+ wpa_debug_level = level;
+ }
+
+ if (stamp && os_strlen(stamp))
+ wpa_debug_timestamp = atoi(stamp);
+
+ os_memcpy(buf, "OK\n", 3);
+ return 3;
+}
+
+
+#ifdef NEED_AP_MLME
+static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd,
+ char *buf, size_t buflen)
+{
+ struct hostapd_iface *iface = hapd->iface;
+ char *pos, *end;
+ struct hostapd_sta_info *info;
+ struct os_reltime now;
+
+ sta_track_expire(iface, 0);
+
+ pos = buf;
+ end = buf + buflen;
+
+ os_get_reltime(&now);
+ dl_list_for_each_reverse(info, &iface->sta_seen,
+ struct hostapd_sta_info, list) {
+ struct os_reltime age;
+ int ret;
+
+ os_reltime_sub(&now, &info->last_seen, &age);
+ ret = os_snprintf(pos, end - pos, MACSTR " %u\n",
+ MAC2STR(info->addr), (unsigned int) age.sec);
+ if (os_snprintf_error(end - pos, ret))
+ break;
+ pos += ret;
+ }
+
+ return pos - buf;
+}
+#endif /* NEED_AP_MLME */
+
+
+static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+ struct sockaddr_un *from,
+ socklen_t fromlen)
+{
+ int reply_len, res;
+
os_memcpy(reply, "OK\n", 3);
reply_len = 3;
@@ -1938,13 +2104,13 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
reply_size);
} else if (os_strcmp(buf, "ATTACH") == 0) {
- if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
+ if (hostapd_ctrl_iface_attach(hapd, from, fromlen))
reply_len = -1;
} else if (os_strcmp(buf, "DETACH") == 0) {
- if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
+ if (hostapd_ctrl_iface_detach(hapd, from, fromlen))
reply_len = -1;
} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
- if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
+ if (hostapd_ctrl_iface_level(hapd, from, fromlen,
buf + 6))
reply_len = -1;
} else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
@@ -2079,6 +2245,11 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
reply_size);
+ } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
+ if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "GET_FAIL") == 0) {
+ reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size);
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
@@ -2091,6 +2262,20 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
#ifdef RADIUS_SERVER
radius_server_erp_flush(hapd->radius_srv);
#endif /* RADIUS_SERVER */
+ } else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
+ if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
+ if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
+ reply_len = hostapd_ctrl_iface_log_level(
+ hapd, buf + 9, reply, reply_size);
+#ifdef NEED_AP_MLME
+ } else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) {
+ reply_len = hostapd_ctrl_iface_track_sta_list(
+ hapd, reply, reply_size);
+#endif /* NEED_AP_MLME */
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
@@ -2100,6 +2285,50 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
os_memcpy(reply, "FAIL\n", 5);
reply_len = 5;
}
+
+ return reply_len;
+}
+
+
+static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
+ void *sock_ctx)
+{
+ struct hostapd_data *hapd = eloop_ctx;
+ char buf[4096];
+ int res;
+ struct sockaddr_un from;
+ socklen_t fromlen = sizeof(from);
+ char *reply;
+ const int reply_size = 4096;
+ int reply_len;
+ int level = MSG_DEBUG;
+
+ res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
+ (struct sockaddr *) &from, &fromlen);
+ if (res < 0) {
+ wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
+ strerror(errno));
+ return;
+ }
+ buf[res] = '\0';
+ if (os_strcmp(buf, "PING") == 0)
+ level = MSG_EXCESSIVE;
+ wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
+
+ reply = os_malloc(reply_size);
+ if (reply == NULL) {
+ if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
+ fromlen) < 0) {
+ wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
+ strerror(errno));
+ }
+ return;
+ }
+
+ reply_len = hostapd_ctrl_iface_receive_process(hapd, buf,
+ reply, reply_size,
+ &from, fromlen);
+
if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
fromlen) < 0) {
wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
@@ -2130,13 +2359,14 @@ static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
}
-static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global,
+static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
+ enum wpa_msg_type type,
const char *txt, size_t len)
{
struct hostapd_data *hapd = ctx;
if (hapd == NULL)
return;
- hostapd_ctrl_iface_send(hapd, level, txt, len);
+ hostapd_ctrl_iface_send(hapd, level, type, txt, len);
}
@@ -2359,6 +2589,58 @@ static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
}
+static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
+ struct sockaddr_un *from,
+ socklen_t fromlen)
+{
+ struct wpa_ctrl_dst *dst;
+
+ dst = os_zalloc(sizeof(*dst));
+ if (dst == NULL)
+ return -1;
+ os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
+ dst->addrlen = fromlen;
+ dst->debug_level = MSG_INFO;
+ dst->next = interfaces->global_ctrl_dst;
+ interfaces->global_ctrl_dst = dst;
+ wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached (global)",
+ from->sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path));
+ return 0;
+}
+
+
+static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
+ struct sockaddr_un *from,
+ socklen_t fromlen)
+{
+ struct wpa_ctrl_dst *dst, *prev = NULL;
+
+ dst = interfaces->global_ctrl_dst;
+ while (dst) {
+ if (fromlen == dst->addrlen &&
+ os_memcmp(from->sun_path, dst->addr.sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path))
+ == 0) {
+ wpa_hexdump(MSG_DEBUG,
+ "CTRL_IFACE monitor detached (global)",
+ from->sun_path,
+ fromlen -
+ offsetof(struct sockaddr_un, sun_path));
+ if (prev == NULL)
+ interfaces->global_ctrl_dst = dst->next;
+ else
+ prev->next = dst->next;
+ os_free(dst);
+ return 0;
+ }
+ prev = dst;
+ dst = dst->next;
+ }
+ return -1;
+}
+
+
static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
{
#ifdef CONFIG_WPS_TESTING
@@ -2369,6 +2651,214 @@ static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
}
+#ifdef CONFIG_FST
+
+static int
+hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
+ const char *cmd)
+{
+ char ifname[IFNAMSIZ + 1];
+ struct fst_iface_cfg cfg;
+ struct hostapd_data *hapd;
+ struct fst_wpa_obj iface_obj;
+
+ if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
+ hapd = hostapd_get_iface(interfaces, ifname);
+ if (hapd) {
+ if (hapd->iface->fst) {
+ wpa_printf(MSG_INFO, "FST: Already attached");
+ return -1;
+ }
+ fst_hostapd_fill_iface_obj(hapd, &iface_obj);
+ hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
+ &iface_obj, &cfg);
+ if (hapd->iface->fst)
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+
+static int
+hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
+ const char *cmd)
+{
+ char ifname[IFNAMSIZ + 1];
+ struct hostapd_data * hapd;
+
+ if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
+ hapd = hostapd_get_iface(interfaces, ifname);
+ if (hapd) {
+ if (!fst_iface_detach(ifname)) {
+ hapd->iface->fst = NULL;
+ hapd->iface->fst_ies = NULL;
+ return 0;
+ }
+ }
+ }
+
+ return -EINVAL;
+}
+
+#endif /* CONFIG_FST */
+
+
+static struct hostapd_data *
+hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
+ const char *ifname)
+{
+ size_t i, j;
+
+ for (i = 0; i < interfaces->count; i++) {
+ struct hostapd_iface *iface = interfaces->iface[i];
+
+ for (j = 0; j < iface->num_bss; j++) {
+ struct hostapd_data *hapd;
+
+ hapd = iface->bss[j];
+ if (os_strcmp(ifname, hapd->conf->iface) == 0)
+ return hapd;
+ }
+ }
+
+ return NULL;
+}
+
+
+static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd,
+ struct hostapd_data *dst_hapd,
+ const char *param)
+{
+ int res;
+ char *value;
+
+ value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
+ if (!value) {
+ wpa_printf(MSG_ERROR,
+ "DUP: cannot allocate buffer to stringify %s",
+ param);
+ goto error_return;
+ }
+
+ if (os_strcmp(param, "wpa") == 0) {
+ os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d",
+ src_hapd->conf->wpa);
+ } else if (os_strcmp(param, "wpa_key_mgmt") == 0 &&
+ src_hapd->conf->wpa_key_mgmt) {
+ res = hostapd_ctrl_iface_get_key_mgmt(
+ src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
+ if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res))
+ goto error_stringify;
+ } else if (os_strcmp(param, "wpa_pairwise") == 0 &&
+ src_hapd->conf->wpa_pairwise) {
+ res = wpa_write_ciphers(value,
+ value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
+ src_hapd->conf->wpa_pairwise, " ");
+ if (res < 0)
+ goto error_stringify;
+ } else if (os_strcmp(param, "rsn_pairwise") == 0 &&
+ src_hapd->conf->rsn_pairwise) {
+ res = wpa_write_ciphers(value,
+ value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
+ src_hapd->conf->rsn_pairwise, " ");
+ if (res < 0)
+ goto error_stringify;
+ } else if (os_strcmp(param, "wpa_passphrase") == 0 &&
+ src_hapd->conf->ssid.wpa_passphrase) {
+ os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s",
+ src_hapd->conf->ssid.wpa_passphrase);
+ } else if (os_strcmp(param, "wpa_psk") == 0 &&
+ src_hapd->conf->ssid.wpa_psk_set) {
+ wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
+ src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
+ } else {
+ wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param);
+ goto error_return;
+ }
+
+ res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value);
+ os_free(value);
+ return res;
+
+error_stringify:
+ wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param);
+error_return:
+ os_free(value);
+ return -1;
+}
+
+
+static int
+hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
+ char *cmd)
+{
+ char *p_start = cmd, *p_end;
+ struct hostapd_data *src_hapd, *dst_hapd;
+
+ /* cmd: "<src ifname> <dst ifname> <variable name> */
+
+ p_end = os_strchr(p_start, ' ');
+ if (!p_end) {
+ wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'",
+ cmd);
+ return -1;
+ }
+
+ *p_end = '\0';
+ src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
+ if (!src_hapd) {
+ wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'",
+ p_start);
+ return -1;
+ }
+
+ p_start = p_end + 1;
+ p_end = os_strchr(p_start, ' ');
+ if (!p_end) {
+ wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'",
+ cmd);
+ return -1;
+ }
+
+ *p_end = '\0';
+ dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
+ if (!dst_hapd) {
+ wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'",
+ p_start);
+ return -1;
+ }
+
+ p_start = p_end + 1;
+ return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start);
+}
+
+
+static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
+ const char *ifname,
+ char *buf, char *reply,
+ int reply_size,
+ struct sockaddr_un *from,
+ socklen_t fromlen)
+{
+ struct hostapd_data *hapd;
+
+ hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
+ if (hapd == NULL) {
+ int res;
+
+ res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
+ if (os_snprintf_error(reply_size, res))
+ return -1;
+ return res;
+ }
+
+ return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
+ from, fromlen);
+}
+
+
static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
@@ -2377,8 +2867,9 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
int res;
struct sockaddr_un from;
socklen_t fromlen = sizeof(from);
- char reply[24];
+ char *reply;
int reply_len;
+ const int reply_size = 4096;
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
(struct sockaddr *) &from, &fromlen);
@@ -2390,9 +2881,31 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
buf[res] = '\0';
wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
+ reply = os_malloc(reply_size);
+ if (reply == NULL) {
+ if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
+ fromlen) < 0) {
+ wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
+ strerror(errno));
+ }
+ return;
+ }
+
os_memcpy(reply, "OK\n", 3);
reply_len = 3;
+ if (os_strncmp(buf, "IFNAME=", 7) == 0) {
+ char *pos = os_strchr(buf + 7, ' ');
+
+ if (pos) {
+ *pos++ = '\0';
+ reply_len = hostapd_global_ctrl_iface_ifname(
+ interfaces, buf + 7, pos, reply, reply_size,
+ &from, fromlen);
+ goto send_reply;
+ }
+ }
+
if (os_strcmp(buf, "PING") == 0) {
os_memcpy(reply, "PONG\n", 5);
reply_len = 5;
@@ -2407,18 +2920,47 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
reply_len = -1;
+ } else if (os_strcmp(buf, "ATTACH") == 0) {
+ if (hostapd_global_ctrl_iface_attach(interfaces, &from,
+ fromlen))
+ reply_len = -1;
+ } else if (os_strcmp(buf, "DETACH") == 0) {
+ if (hostapd_global_ctrl_iface_detach(interfaces, &from,
+ fromlen))
+ reply_len = -1;
#ifdef CONFIG_MODULE_TESTS
} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
int hapd_module_tests(void);
if (hapd_module_tests() < 0)
reply_len = -1;
#endif /* CONFIG_MODULE_TESTS */
+#ifdef CONFIG_FST
+ } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
+ if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
+ reply_len = os_snprintf(reply, reply_size, "OK\n");
+ else
+ reply_len = -1;
+ } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
+ if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11))
+ reply_len = os_snprintf(reply, reply_size, "OK\n");
+ else
+ reply_len = -1;
+ } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
+ reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
+#endif /* CONFIG_FST */
+ } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
+ if (!hostapd_global_ctrl_iface_dup_network(interfaces,
+ buf + 12))
+ reply_len = os_snprintf(reply, reply_size, "OK\n");
+ else
+ reply_len = -1;
} else {
wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
"ignored");
reply_len = -1;
}
+send_reply:
if (reply_len < 0) {
os_memcpy(reply, "FAIL\n", 5);
reply_len = 5;
@@ -2429,6 +2971,7 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
strerror(errno));
}
+ os_free(reply);
}
@@ -2566,6 +3109,7 @@ fail:
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
{
char *fname = NULL;
+ struct wpa_ctrl_dst *dst, *prev;
if (interfaces->global_ctrl_sock > -1) {
eloop_unregister_read_sock(interfaces->global_ctrl_sock);
@@ -2590,13 +3134,23 @@ void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
strerror(errno));
}
}
- os_free(interfaces->global_iface_path);
- interfaces->global_iface_path = NULL;
+ }
+
+ os_free(interfaces->global_iface_path);
+ interfaces->global_iface_path = NULL;
+
+ dst = interfaces->global_ctrl_dst;
+ interfaces->global_ctrl_dst = NULL;
+ while (dst) {
+ prev = dst;
+ dst = dst->next;
+ os_free(prev);
}
}
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+ enum wpa_msg_type type,
const char *buf, size_t len)
{
struct wpa_ctrl_dst *dst, *next;
@@ -2604,9 +3158,17 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
int idx;
struct iovec io[2];
char levelstr[10];
+ int s;
- dst = hapd->ctrl_dst;
- if (hapd->ctrl_sock < 0 || dst == NULL)
+ if (type != WPA_MSG_ONLY_GLOBAL) {
+ s = hapd->ctrl_sock;
+ dst = hapd->ctrl_dst;
+ } else {
+ s = hapd->iface->interfaces->global_ctrl_sock;
+ dst = hapd->iface->interfaces->global_ctrl_dst;
+ }
+
+ if (s < 0 || dst == NULL)
return;
os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
@@ -2627,16 +3189,22 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
offsetof(struct sockaddr_un, sun_path));
msg.msg_name = &dst->addr;
msg.msg_namelen = dst->addrlen;
- if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
+ if (sendmsg(s, &msg, 0) < 0) {
int _errno = errno;
wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
"%d - %s",
idx, errno, strerror(errno));
dst->errors++;
if (dst->errors > 10 || _errno == ENOENT) {
- hostapd_ctrl_iface_detach(
- hapd, &dst->addr,
- dst->addrlen);
+ if (type != WPA_MSG_ONLY_GLOBAL)
+ hostapd_ctrl_iface_detach(
+ hapd, &dst->addr,
+ dst->addrlen);
+ else
+ hostapd_global_ctrl_iface_detach(
+ hapd->iface->interfaces,
+ &dst->addr,
+ dst->addrlen);
}
} else
dst->errors = 0;
diff --git a/contrib/wpa/hostapd/defconfig b/contrib/wpa/hostapd/defconfig
index 4cde2b5..430f758 100644
--- a/contrib/wpa/hostapd/defconfig
+++ b/contrib/wpa/hostapd/defconfig
@@ -240,6 +240,12 @@ CONFIG_IPV6=y
# requirements described above.
#CONFIG_NO_RANDOM_POOL=y
+# Should we use poll instead of select? Select is used by default.
+#CONFIG_ELOOP_POLL=y
+
+# Should we use epoll instead of select? Select is used by default.
+#CONFIG_ELOOP_EPOLL=y
+
# Select TLS implementation
# openssl = OpenSSL (default)
# gnutls = GnuTLS
@@ -283,6 +289,12 @@ 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
+
+# Enable CLI commands for FST testing
+#CONFIG_FST_TEST=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/contrib/wpa/hostapd/hlr_auc_gw.c b/contrib/wpa/hostapd/hlr_auc_gw.c
index 42d59db..84d0308 100644
--- a/contrib/wpa/hostapd/hlr_auc_gw.c
+++ b/contrib/wpa/hostapd/hlr_auc_gw.c
@@ -87,6 +87,7 @@ struct milenage_parameters {
u8 amf[2];
u8 sqn[6];
int set;
+ size_t res_len;
};
static struct milenage_parameters *milenage_db = NULL;
@@ -96,6 +97,7 @@ static struct milenage_parameters *milenage_db = NULL;
#define EAP_AKA_RAND_LEN 16
#define EAP_AKA_AUTN_LEN 16
#define EAP_AKA_AUTS_LEN 14
+#define EAP_AKA_RES_MIN_LEN 4
#define EAP_AKA_RES_MAX_LEN 16
#define EAP_AKA_IK_LEN 16
#define EAP_AKA_CK_LEN 16
@@ -124,7 +126,8 @@ static int db_table_create_milenage(sqlite3 *db)
" ki CHAR(32) NOT NULL,"
" opc CHAR(32) NOT NULL,"
" amf CHAR(4) NOT NULL,"
- " sqn CHAR(12) NOT NULL"
+ " sqn CHAR(12) NOT NULL,"
+ " res_len INTEGER"
");";
printf("Adding database table for milenage information\n");
@@ -190,6 +193,10 @@ static int get_milenage_cb(void *ctx, int argc, char *argv[], char *col[])
printf("Invalid sqn value in database\n");
return -1;
}
+
+ if (os_strcmp(col[i], "res_len") == 0 && argv[i]) {
+ m->res_len = atoi(argv[i]);
+ }
}
return 0;
@@ -206,8 +213,7 @@ static struct milenage_parameters * db_get_milenage(const char *imsi_txt)
os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi),
"%llu", imsi);
os_snprintf(cmd, sizeof(cmd),
- "SELECT ki,opc,amf,sqn FROM milenage WHERE imsi=%llu;",
- imsi);
+ "SELECT * FROM milenage WHERE imsi=%llu;", imsi);
if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage,
NULL) != SQLITE_OK)
return NULL;
@@ -424,7 +430,7 @@ static int read_milenage(const char *fname)
while (fgets(buf, sizeof(buf), f)) {
line++;
- /* Parse IMSI Ki OPc AMF SQN */
+ /* Parse IMSI Ki OPc AMF SQN [RES_len] */
buf[sizeof(buf) - 1] = '\0';
if (buf[0] == '#')
continue;
@@ -515,7 +521,19 @@ static int read_milenage(const char *fname)
ret = -1;
break;
}
- pos = pos2 + 1;
+
+ if (pos2) {
+ pos = pos2 + 1;
+ m->res_len = atoi(pos);
+ if (m->res_len &&
+ (m->res_len < EAP_AKA_RES_MIN_LEN ||
+ m->res_len > EAP_AKA_RES_MAX_LEN)) {
+ printf("%s:%d - Invalid RES_len (%s)\n",
+ fname, line, pos);
+ ret = -1;
+ break;
+ }
+ }
m->next = milenage_db;
milenage_db = m;
@@ -532,7 +550,7 @@ static int read_milenage(const char *fname)
static void update_milenage_file(const char *fname)
{
FILE *f, *f2;
- char buf[500], *pos;
+ char name[500], buf[500], *pos;
char *end = buf + sizeof(buf);
struct milenage_parameters *m;
size_t imsi_len;
@@ -543,10 +561,10 @@ static void update_milenage_file(const char *fname)
return;
}
- snprintf(buf, sizeof(buf), "%s.new", fname);
- f2 = fopen(buf, "w");
+ snprintf(name, sizeof(name), "%s.new", fname);
+ f2 = fopen(name, "w");
if (f2 == NULL) {
- printf("Could not write Milenage data file '%s'\n", buf);
+ printf("Could not write Milenage data file '%s'\n", name);
fclose(f);
return;
}
@@ -588,14 +606,14 @@ static void update_milenage_file(const char *fname)
fclose(f2);
fclose(f);
- snprintf(buf, sizeof(buf), "%s.bak", fname);
- if (rename(fname, buf) < 0) {
+ snprintf(name, sizeof(name), "%s.bak", fname);
+ if (rename(fname, name) < 0) {
perror("rename");
return;
}
- snprintf(buf, sizeof(buf), "%s.new", fname);
- if (rename(buf, fname) < 0) {
+ snprintf(name, sizeof(name), "%s.new", fname);
+ if (rename(name, fname) < 0) {
perror("rename");
return;
}
@@ -798,6 +816,10 @@ static int aka_req_auth(char *imsi, char *resp, size_t resp_len)
}
milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
autn, ik, ck, res, &res_len);
+ if (m->res_len >= EAP_AKA_RES_MIN_LEN &&
+ m->res_len <= EAP_AKA_RES_MAX_LEN &&
+ m->res_len < res_len)
+ res_len = m->res_len;
} else {
printf("Unknown IMSI: %s\n", imsi);
#ifdef AKA_USE_FIXED_TEST_VALUES
diff --git a/contrib/wpa/hostapd/hlr_auc_gw.milenage_db b/contrib/wpa/hostapd/hlr_auc_gw.milenage_db
index ecd06d7..c156a29 100644
--- a/contrib/wpa/hostapd/hlr_auc_gw.milenage_db
+++ b/contrib/wpa/hostapd/hlr_auc_gw.milenage_db
@@ -5,8 +5,10 @@
# authentication. In case of GSM/EAP-SIM, AMF and SQN values are not used, but
# dummy values will need to be included in this file.
-# IMSI Ki OPc AMF SQN
+# IMSI Ki OPc AMF SQN [RES_len]
232010000000000 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000
+# Example using truncated 32-bit RES instead of 64-bit default
+232010000000001 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000 4
# These values are from Test Set 19 which has the AMF separation bit set to 1
# and as such, is suitable for EAP-AKA' test.
diff --git a/contrib/wpa/hostapd/hostapd.conf b/contrib/wpa/hostapd/hostapd.conf
index 9e81e9e..a0071f7 100644
--- a/contrib/wpa/hostapd/hostapd.conf
+++ b/contrib/wpa/hostapd/hostapd.conf
@@ -127,7 +127,9 @@ ssid=test
# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
# ad = IEEE 802.11ad (60 GHz); a/g options are used with IEEE 802.11n, too, to
-# specify band)
+# specify band). When using ACS (see channel parameter), a special value "any"
+# can be used to indicate that any support band can be used. This special case
+# is currently supported only with drivers with which offloaded ACS is used.
# Default: IEEE 802.11b
hw_mode=g
@@ -170,8 +172,11 @@ channel=1
# Channel list restriction. This option allows hostapd to select one of the
# provided channels when a channel should be automatically selected.
-# Default: not set (allow any enabled channel to be selected)
+# Channel list can be provided as range using hyphen ('-') or individual
+# channels can be specified by space (' ') seperated values
+# Default: all channels allowed in selected hw_mode
#chanlist=100 104 108 112 116
+#chanlist=1 6 11-13
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
beacon_int=100
@@ -275,8 +280,9 @@ ignore_broadcast_ssid=0
# (data0 is the highest priority queue)
# parameters:
# aifs: AIFS (default 2)
-# cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023)
-# cwmax: cwMax (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023); cwMax >= cwMin
+# cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191,
+# 16383, 32767)
+# cwmax: cwMax (same values as cwMin, cwMax >= cwMin)
# burst: maximum length (in milliseconds with precision of up to 0.1 ms) for
# bursting
#
@@ -337,8 +343,9 @@ ignore_broadcast_ssid=0
# note - txop_limit is in units of 32microseconds
# note - acm is admission control mandatory flag. 0 = admission control not
# required, 1 = mandatory
-# note - here cwMin and cmMax are in exponent form. the actual cw value used
-# will be (2^n)-1 where n is the value given here
+# note - Here cwMin and cmMax are in exponent form. The actual cw value used
+# will be (2^n)-1 where n is the value given here. The allowed range for these
+# wmm_ac_??_{cwmin,cwmax} is 0..15 with cwmax >= cwmin.
#
wmm_enabled=1
#
@@ -575,14 +582,16 @@ wmm_ac_vo_acm=0
# 0 = Not supported (default)
# 1 = Supported
#
-# Compressed Steering Number of Beamformer Antennas Supported: [BF-ANTENNA-2]
+# Compressed Steering Number of Beamformer Antennas Supported:
+# [BF-ANTENNA-2] [BF-ANTENNA-3] [BF-ANTENNA-4]
# Beamformee's capability indicating the maximum number of beamformer
# antennas the beamformee can support when sending compressed beamforming
# feedback
# If SU beamformer capable, set to maximum value minus 1
# else reserved (default)
#
-# Number of Sounding Dimensions: [SOUNDING-DIMENSION-2]
+# Number of Sounding Dimensions:
+# [SOUNDING-DIMENSION-2] [SOUNDING-DIMENSION-3] [SOUNDING-DIMENSION-4]
# Beamformer's capability indicating the maximum value of the NUM_STS parameter
# in the TXVECTOR of a VHT NDP
# If SU beamformer capable, set to maximum value minus 1
@@ -593,11 +602,6 @@ wmm_ac_vo_acm=0
# 0 = Not supported or sent by Non-AP STA (default)
# 1 = Supported
#
-# MU Beamformee Capable: [MU-BEAMFORMEE]
-# Indicates support for operation as an MU beamformee
-# 0 = Not supported or sent by AP (default)
-# 1 = Supported
-#
# VHT TXOP PS: [VHT-TXOP-PS]
# Indicates whether or not the AP supports VHT TXOP Power Save Mode
# or whether or not the STA is in VHT TXOP Power Save mode
@@ -764,6 +768,12 @@ eap_server=0
# 2 = check all CRLs in the certificate path
#check_crl=1
+# TLS Session Lifetime in seconds
+# This can be used to allow TLS sessions to be cached and resumed with an
+# abbreviated handshake when using EAP-TLS/TTLS/PEAP.
+# (default: 0 = session caching and resumption disabled)
+#tls_session_lifetime=3600
+
# Cached OCSP stapling response (DER encoded)
# If set, this file is sent as a certificate status response by the EAP server
# if the EAP peer requests certificate status in the ClientHello message.
@@ -787,7 +797,7 @@ eap_server=0
# is in DSA parameters format, it will be automatically converted into DH
# params. This parameter is required if anonymous EAP-FAST is used.
# You can generate DH parameters file with OpenSSL, e.g.,
-# "openssl dhparam -out /etc/hostapd.dh.pem 1024"
+# "openssl dhparam -out /etc/hostapd.dh.pem 2048"
#dh_file=/etc/hostapd.dh.pem
# OpenSSL cipher string
@@ -1247,6 +1257,11 @@ own_ip_addr=127.0.0.1
# 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived
#pmk_r1_push=1
+# Whether to enable FT-over-DS
+# 0 = FT-over-DS disabled
+# 1 = FT-over-DS enabled (default)
+#ft_over_ds=1
+
##### Neighbor table ##########################################################
# Maximum number of entries kept in AP table (either for neigbor table or for
# detecting Overlapping Legacy BSS Condition). The oldest entry will be
@@ -1264,6 +1279,43 @@ own_ip_addr=127.0.0.1
# default: 60
#ap_table_expiration_time=3600
+# Maximum number of stations to track on the operating channel
+# This can be used to detect dualband capable stations before they have
+# associated, e.g., to provide guidance on which colocated BSS to use.
+# Default: 0 (disabled)
+#track_sta_max_num=100
+
+# Maximum age of a station tracking entry in seconds
+# Default: 180
+#track_sta_max_age=180
+
+# Do not reply to group-addressed Probe Request from a station that was seen on
+# another radio.
+# Default: Disabled
+#
+# This can be used with enabled track_sta_max_num configuration on another
+# interface controlled by the same hostapd process to restrict Probe Request
+# frame handling from replying to group-addressed Probe Request frames from a
+# station that has been detected to be capable of operating on another band,
+# e.g., to try to reduce likelihood of the station selecting a 2.4 GHz BSS when
+# the AP operates both a 2.4 GHz and 5 GHz BSS concurrently.
+#
+# Note: Enabling this can cause connectivity issues and increase latency for
+# discovering the AP.
+#no_probe_resp_if_seen_on=wlan1
+
+# Reject authentication from a station that was seen on another radio.
+# Default: Disabled
+#
+# This can be used with enabled track_sta_max_num configuration on another
+# interface controlled by the same hostapd process to reject authentication
+# attempts from a station that has been detected to be capable of operating on
+# another band, e.g., to try to reduce likelihood of the station selecting a
+# 2.4 GHz BSS when the AP operates both a 2.4 GHz and 5 GHz BSS concurrently.
+#
+# Note: Enabling this can cause connectivity issues and increase latency for
+# connecting with the AP.
+#no_auth_if_seen_on=wlan1
##### Wi-Fi Protected Setup (WPS) #############################################
@@ -1430,7 +1482,7 @@ own_ip_addr=127.0.0.1
# 12-digit, all-numeric code that identifies the consumer package.
#upc=123456789012
-# WPS RF Bands (a = 5G, b = 2.4G, g = 2.4G, ag = dual band)
+# WPS RF Bands (a = 5G, b = 2.4G, g = 2.4G, ag = dual band, ad = 60 GHz)
# This value should be set according to RF band(s) supported by the AP if
# hw_mode is not set. For dual band dual concurrent devices, this needs to be
# set to ag to allow both RF bands to be advertized.
@@ -1490,6 +1542,13 @@ own_ip_addr=127.0.0.1
# 1 = enabled
#proxy_arp=1
+# IPv6 Neighbor Advertisement multicast-to-unicast conversion
+# This can be used with Proxy ARP to allow multicast NAs to be forwarded to
+# associated STAs using link layer unicast delivery.
+# 0 = disabled (default)
+# 1 = enabled
+#na_mcast_to_ucast=0
+
##### IEEE 802.11u-2011 #######################################################
# Enable Interworking service
@@ -1738,6 +1797,32 @@ own_ip_addr=127.0.0.1
#
#osu_server_uri=...
+##### 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 IEEE Std 802.11ad-2012.
+
+# Identifier of an FST Group the interface belongs to.
+#fst_group_id=bond0
+
+# Interface priority within the FST Group.
+# Announcing a higher priority for an interface means declaring it more
+# preferable for FST switch.
+# fst_priority is in 1..255 range with 1 being the lowest priority.
+#fst_priority=100
+
+# Default LLT value for this interface in milliseconds. The value used in case
+# no value provided during session setup. Default is 50 ms.
+# fst_llt is in 1..4294967 range (due to spec limitation, see 10.32.2.2
+# Transitioning between states).
+#fst_llt=100
+
##### TESTING OPTIONS #########################################################
#
# The options in this section are only available when the build configuration
diff --git a/contrib/wpa/hostapd/hostapd_cli.c b/contrib/wpa/hostapd/hostapd_cli.c
index 3f00cbb..46c2f37 100644
--- a/contrib/wpa/hostapd/hostapd_cli.c
+++ b/contrib/wpa/hostapd/hostapd_cli.c
@@ -10,22 +10,23 @@
#include <dirent.h>
#include "common/wpa_ctrl.h"
+#include "common/ieee802_11_defs.h"
#include "utils/common.h"
#include "utils/eloop.h"
#include "utils/edit.h"
#include "common/version.h"
-static const char *hostapd_cli_version =
+static const char *const hostapd_cli_version =
"hostapd_cli v" VERSION_STR "\n"
"Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors";
-static const char *hostapd_cli_license =
+static const char *const hostapd_cli_license =
"This software may be distributed under the terms of the BSD license.\n"
"See README for more details.\n";
-static const char *hostapd_cli_full_license =
+static const char *const hostapd_cli_full_license =
"This software may be distributed under the terms of the BSD license.\n"
"\n"
"Redistribution and use in source and binary forms, with or without\n"
@@ -56,7 +57,7 @@ static const char *hostapd_cli_full_license =
"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
"\n";
-static const char *commands_help =
+static const char *const commands_help =
"Commands:\n"
" mib get MIB variables (dot1x, dot11, radius)\n"
" sta <addr> get MIB variables for one station\n"
@@ -96,6 +97,7 @@ static int hostapd_cli_attached = 0;
#define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
#endif /* CONFIG_CTRL_IFACE_DIR */
static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
+static const char *client_socket_dir = NULL;
static char *ctrl_ifname = NULL;
static const char *pid_file = NULL;
@@ -111,13 +113,15 @@ static void usage(void)
"\n"
"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
"[-a<path>] \\\n"
- " [-G<ping interval>] [command..]\n"
+ " [-P<pid file>] [-G<ping interval>] [command..]\n"
"\n"
"Options:\n"
" -h help (show this usage text)\n"
" -v shown version information\n"
" -p<path> path to find control sockets (default: "
"/var/run/hostapd)\n"
+ " -s<dir_path> dir path to open client sockets (default: "
+ CONFIG_CTRL_IFACE_DIR ")\n"
" -a<file> run in daemon mode executing the action file "
"based on events\n"
" from hostapd\n"
@@ -144,7 +148,14 @@ static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
return NULL;
snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
- ctrl_conn = wpa_ctrl_open(cfile);
+ if (client_socket_dir && client_socket_dir[0] &&
+ access(client_socket_dir, F_OK) < 0) {
+ perror(client_socket_dir);
+ free(cfile);
+ return NULL;
+ }
+
+ ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
free(cfile);
return ctrl_conn;
}
@@ -541,7 +552,7 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
char buf[256];
- char ssid_hex[2 * 32 + 1];
+ char ssid_hex[2 * SSID_MAX_LEN + 1];
char key_hex[2 * 64 + 1];
int i;
@@ -552,7 +563,7 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
}
ssid_hex[0] = '\0';
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < SSID_MAX_LEN; i++) {
if (argv[0][i] == '\0')
break;
os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
@@ -921,6 +932,35 @@ static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
+#ifdef CONFIG_FST
+static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ char cmd[256];
+ int res;
+ int i;
+ int total;
+
+ if (argc <= 0) {
+ printf("FST command: parameters are required.\n");
+ return -1;
+ }
+
+ total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
+
+ for (i = 0; i < argc; i++) {
+ res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
+ argv[i]);
+ if (os_snprintf_error(sizeof(cmd) - total, res)) {
+ printf("Too long fst command.\n");
+ return -1;
+ }
+ total += res;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+#endif /* CONFIG_FST */
+
+
static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
int argc, char *argv[])
{
@@ -1009,12 +1049,31 @@ static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
}
+static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char cmd[256];
+ int res;
+
+ res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
+ argc >= 1 ? " " : "",
+ argc >= 1 ? argv[0] : "",
+ argc == 2 ? " " : "",
+ argc == 2 ? argv[1] : "");
+ if (os_snprintf_error(sizeof(cmd), res)) {
+ printf("Too long option\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
struct hostapd_cli_cmd {
const char *cmd;
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
};
-static struct hostapd_cli_cmd hostapd_cli_commands[] = {
+static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "ping", hostapd_cli_cmd_ping },
{ "mib", hostapd_cli_cmd_mib },
{ "relog", hostapd_cli_cmd_relog },
@@ -1048,6 +1107,9 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "get_config", hostapd_cli_cmd_get_config },
{ "help", hostapd_cli_cmd_help },
{ "interface", hostapd_cli_cmd_interface },
+#ifdef CONFIG_FST
+ { "fst", hostapd_cli_cmd_fst },
+#endif /* CONFIG_FST */
{ "level", hostapd_cli_cmd_level },
{ "license", hostapd_cli_cmd_license },
{ "quit", hostapd_cli_cmd_quit },
@@ -1063,13 +1125,14 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "reload", hostapd_cli_cmd_reload },
{ "disable", hostapd_cli_cmd_disable },
{ "erp_flush", hostapd_cli_cmd_erp_flush },
+ { "log_level", hostapd_cli_cmd_log_level },
{ NULL, NULL }
};
static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
- struct hostapd_cli_cmd *cmd, *match = NULL;
+ const struct hostapd_cli_cmd *cmd, *match = NULL;
int count;
count = 0;
@@ -1284,7 +1347,7 @@ int main(int argc, char *argv[])
return -1;
for (;;) {
- c = getopt(argc, argv, "a:BhG:i:p:v");
+ c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
if (c < 0)
break;
switch (c) {
@@ -1310,6 +1373,12 @@ int main(int argc, char *argv[])
case 'p':
ctrl_iface_dir = optarg;
break;
+ case 'P':
+ pid_file = optarg;
+ break;
+ case 's':
+ client_socket_dir = optarg;
+ break;
default:
usage();
return -1;
diff --git a/contrib/wpa/hostapd/main.c b/contrib/wpa/hostapd/main.c
index dd389a8..6c7406a 100644
--- a/contrib/wpa/hostapd/main.c
+++ b/contrib/wpa/hostapd/main.c
@@ -24,6 +24,7 @@
#include "ap/hostapd.h"
#include "ap/ap_config.h"
#include "ap/ap_drv_ops.h"
+#include "fst/fst.h"
#include "config_file.h"
#include "eap_register.h"
#include "ctrl_iface.h"
@@ -533,6 +534,28 @@ static int gen_uuid(const char *txt_addr)
#endif /* CONFIG_WPS */
+#ifndef HOSTAPD_CLEANUP_INTERVAL
+#define HOSTAPD_CLEANUP_INTERVAL 10
+#endif /* HOSTAPD_CLEANUP_INTERVAL */
+
+static int hostapd_periodic_call(struct hostapd_iface *iface, void *ctx)
+{
+ hostapd_periodic_iface(iface);
+ return 0;
+}
+
+
+/* Periodic cleanup tasks */
+static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx)
+{
+ struct hapd_interfaces *interfaces = eloop_ctx;
+
+ eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
+ hostapd_periodic, interfaces, NULL);
+ hostapd_for_each_interface(interfaces, hostapd_periodic_call, NULL);
+}
+
+
int main(int argc, char *argv[])
{
struct hapd_interfaces interfaces;
@@ -561,6 +584,7 @@ int main(int argc, char *argv[])
interfaces.global_iface_path = NULL;
interfaces.global_iface_name = NULL;
interfaces.global_ctrl_sock = -1;
+ interfaces.global_ctrl_dst = NULL;
for (;;) {
c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:vg:G:");
@@ -661,10 +685,24 @@ int main(int argc, char *argv[])
}
if (hostapd_global_init(&interfaces, entropy_file)) {
- wpa_printf(MSG_ERROR, "Failed to initilize global context");
+ wpa_printf(MSG_ERROR, "Failed to initialize global context");
return -1;
}
+ eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
+ hostapd_periodic, &interfaces, NULL);
+
+ if (fst_global_init()) {
+ wpa_printf(MSG_ERROR,
+ "Failed to initialize global FST context");
+ 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 /* CONFIG_FST && CONFIG_CTRL_IFACE */
+
/* Allocate and parse configuration for full interface files */
for (i = 0; i < interfaces.count; i++) {
interfaces.iface[i] = hostapd_interface_init(&interfaces,
@@ -749,6 +787,7 @@ int main(int argc, char *argv[])
}
os_free(interfaces.iface);
+ eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL);
hostapd_global_deinit(pid_file);
os_free(pid_file);
@@ -758,6 +797,8 @@ int main(int argc, char *argv[])
os_free(bss_config);
+ fst_global_deinit();
+
os_program_deinit();
return ret;
OpenPOWER on IntegriCloud