Cumulative patch from commit f4e3860f8a770a0db3816196c77baf894c7ccc1e
f4e3860 Fix AP mode default TXOP Limit values for AC_VI and AC_VO
47bd94a TLS testing: Add new test cases for RSA-DHE primes
f5bbb2f TLS client: Reject RSA-DHE prime if it shorter than 768 bits
817742f TLS testing: Fix test_flags check for ApplData report
1120e45 Allow config blobs to be set through ctrl_iface
c3722e1 ACS: Fix VHT20
49b7443 Fix HT40 co-ex scan for some pri/sec channel switches
5bdac4a Remove unused STA entry information
c9d9ee9 Fix hostapd_add_iface error path to deinit partially initialized BSS
6829da3 Fix external radio_work deinit path
8dd9f9c Allow management group cipher to be configured
67d39cf P2P: Do not create another group interface on NFC Token enable
6aa1cd4 wpa_supplicant: Apply VHT_OVERRIDES to wpas_start_assoc_cb()
db63757 hostapd: Supply default parameters for OBSS scan
6e9375e TDLS: Add get_capability tdls command
67e1a40 hostapd: For VHT 20/40, allow center segment 0 to be zero
d0bf06f GAS server: Remove incomplete remote ANQP processing
fdb4535 WPS: Extend per-station PSK to support ER case as well
9a1a538 wpa_supplicant AP: Allow PMF to be enabled with ieee80211w
ce6b9cd Allow reason code to be specified for DEAUTH/DISASSOC test frame
dda8be7 TDLS: Use QoS info from WMM IE obtained in TDLS frames
daa70bd Fix CONFIG_NO_SCAN_PROCESSING=y build
3a8ec73 P2P: Report dev_found event (if not yet done) from GO Neg Req RX
0f23a5e Mark AP disabled if initialization steps fail
Change-Id: I7e499241552147c734fec9b77351b47ffd6e3a7c
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/acs.c b/src/ap/acs.c
index 3e0155c..2491b78 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -639,23 +639,26 @@
static void acs_adjust_vht_center_freq(struct hostapd_iface *iface)
{
+ int offset;
+
wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency");
switch (iface->conf->vht_oper_chwidth) {
case VHT_CHANWIDTH_USE_HT:
- iface->conf->vht_oper_centr_freq_seg0_idx =
- iface->conf->channel + 2;
+ offset = 2 * iface->conf->secondary_channel;
break;
case VHT_CHANWIDTH_80MHZ:
- iface->conf->vht_oper_centr_freq_seg0_idx =
- iface->conf->channel + 6;
+ offset = 6;
break;
default:
/* TODO: How can this be calculated? Adjust
* acs_find_ideal_chan() */
wpa_printf(MSG_INFO, "ACS: Only VHT20/40/80 is supported now");
- break;
+ return;
}
+
+ iface->conf->vht_oper_centr_freq_seg0_idx =
+ iface->conf->channel + offset;
}
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 3ca85a0..14d9ae9 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -73,6 +73,7 @@
#ifdef CONFIG_IEEE80211W
bss->assoc_sa_query_max_timeout = 1000;
bss->assoc_sa_query_retry_timeout = 201;
+ bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
#endif /* CONFIG_IEEE80211W */
#ifdef EAP_SERVER_FAST
/* both anonymous and authenticated provisioning */
@@ -106,9 +107,9 @@
const struct hostapd_wmm_ac_params ac_be =
{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
- { aCWmin - 1, aCWmin, 2, 3000 / 32, 0 };
+ { aCWmin - 1, aCWmin, 2, 3008 / 32, 0 };
const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
- { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 };
+ { aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 };
const struct hostapd_tx_queue_params txq_bk =
{ 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 };
const struct hostapd_tx_queue_params txq_be =
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index aa3a51a..25eb490 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -254,6 +254,7 @@
int wpa_key_mgmt;
#ifdef CONFIG_IEEE80211W
enum mfp_options ieee80211w;
+ int group_mgmt_cipher;
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
unsigned int assoc_sa_query_max_timeout;
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 5ba48c9..83cfd0f 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -503,7 +503,8 @@
case VHT_CHANWIDTH_USE_HT:
if (center_segment1)
return -1;
- if (5000 + center_segment0 * 5 != data->center_freq1 &&
+ if (center_segment0 != 0 &&
+ 5000 + center_segment0 * 5 != data->center_freq1 &&
2407 + center_segment0 * 5 != data->center_freq1)
return -1;
break;
diff --git a/src/ap/ap_mlme.c b/src/ap/ap_mlme.c
index a7129f1..13604ed 100644
--- a/src/ap/ap_mlme.c
+++ b/src/ap/ap_mlme.c
@@ -120,8 +120,6 @@
* reassociation procedure that was initiated by that specific peer MAC entity.
*
* PeerSTAAddress = sta->addr
- *
- * sta->previous_ap contains the "Current AP" information from ReassocReq.
*/
void mlme_reassociate_indication(struct hostapd_data *hapd,
struct sta_info *sta)
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index c27cf3b..11351c4 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -281,6 +281,10 @@
if (hwaddr_aton(txtaddr, addr))
return -1;
+ pos = os_strstr(txtaddr, " reason=");
+ if (pos)
+ reason = atoi(pos + 8);
+
pos = os_strstr(txtaddr, " test=");
if (pos) {
struct ieee80211_mgmt mgmt;
@@ -295,8 +299,7 @@
os_memcpy(mgmt.da, addr, ETH_ALEN);
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
- mgmt.u.deauth.reason_code =
- host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
+ mgmt.u.deauth.reason_code = host_to_le16(reason);
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.deauth),
@@ -313,10 +316,6 @@
}
#endif /* CONFIG_P2P_MANAGER */
- pos = os_strstr(txtaddr, " reason=");
- if (pos)
- reason = atoi(pos + 8);
-
hostapd_drv_sta_deauth(hapd, addr, reason);
sta = ap_get_sta(hapd, addr);
if (sta)
@@ -342,6 +341,10 @@
if (hwaddr_aton(txtaddr, addr))
return -1;
+ pos = os_strstr(txtaddr, " reason=");
+ if (pos)
+ reason = atoi(pos + 8);
+
pos = os_strstr(txtaddr, " test=");
if (pos) {
struct ieee80211_mgmt mgmt;
@@ -356,8 +359,7 @@
os_memcpy(mgmt.da, addr, ETH_ALEN);
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
- mgmt.u.disassoc.reason_code =
- host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
+ mgmt.u.disassoc.reason_code = host_to_le16(reason);
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.deauth),
@@ -374,10 +376,6 @@
}
#endif /* CONFIG_P2P_MANAGER */
- pos = os_strstr(txtaddr, " reason=");
- if (pos)
- reason = atoi(pos + 8);
-
hostapd_drv_sta_disassoc(hapd, addr, reason);
sta = ap_get_sta(hapd, addr);
if (sta)
diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c
index fd1041e..49f6e87 100644
--- a/src/ap/gas_serv.c
+++ b/src/ap/gas_serv.c
@@ -71,7 +71,6 @@
continue;
dia = &sta->gas_dialog[i];
dia->valid = 1;
- dia->index = i;
dia->dialog_token = dialog_token;
sta->gas_dialog_next = (++i == GAS_DIALOG_MAX) ? 0 : i;
return dia;
@@ -744,40 +743,21 @@
}
-static void gas_serv_clear_cached_ies(void *eloop_data, void *user_ctx)
-{
- struct gas_dialog_info *dia = eloop_data;
-
- wpa_printf(MSG_DEBUG, "GAS: Timeout triggered, clearing dialog for "
- "dialog token %d", dia->dialog_token);
-
- gas_serv_dialog_clear(dia);
-}
-
-
struct anqp_query_info {
unsigned int request;
- unsigned int remote_request;
const u8 *home_realm_query;
size_t home_realm_query_len;
const u8 *icon_name;
size_t icon_name_len;
- u16 remote_delay;
};
static void set_anqp_req(unsigned int bit, const char *name, int local,
- unsigned int remote, u16 remote_delay,
struct anqp_query_info *qi)
{
qi->request |= bit;
if (local) {
wpa_printf(MSG_DEBUG, "ANQP: %s (local)", name);
- } else if (bit & remote) {
- wpa_printf(MSG_DEBUG, "ANQP: %s (remote)", name);
- qi->remote_request |= bit;
- if (remote_delay > qi->remote_delay)
- qi->remote_delay = remote_delay;
} else {
wpa_printf(MSG_DEBUG, "ANQP: %s not available", name);
}
@@ -789,43 +769,38 @@
{
switch (info_id) {
case ANQP_CAPABILITY_LIST:
- set_anqp_req(ANQP_REQ_CAPABILITY_LIST, "Capability List", 1, 0,
- 0, qi);
+ set_anqp_req(ANQP_REQ_CAPABILITY_LIST, "Capability List", 1,
+ qi);
break;
case ANQP_VENUE_NAME:
set_anqp_req(ANQP_REQ_VENUE_NAME, "Venue Name",
- hapd->conf->venue_name != NULL, 0, 0, qi);
+ hapd->conf->venue_name != NULL, qi);
break;
case ANQP_NETWORK_AUTH_TYPE:
set_anqp_req(ANQP_REQ_NETWORK_AUTH_TYPE, "Network Auth Type",
- hapd->conf->network_auth_type != NULL,
- 0, 0, qi);
+ hapd->conf->network_auth_type != NULL, qi);
break;
case ANQP_ROAMING_CONSORTIUM:
set_anqp_req(ANQP_REQ_ROAMING_CONSORTIUM, "Roaming Consortium",
- hapd->conf->roaming_consortium != NULL, 0, 0, qi);
+ hapd->conf->roaming_consortium != NULL, qi);
break;
case ANQP_IP_ADDR_TYPE_AVAILABILITY:
set_anqp_req(ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY,
"IP Addr Type Availability",
- hapd->conf->ipaddr_type_configured,
- 0, 0, qi);
+ hapd->conf->ipaddr_type_configured, qi);
break;
case ANQP_NAI_REALM:
set_anqp_req(ANQP_REQ_NAI_REALM, "NAI Realm",
- hapd->conf->nai_realm_data != NULL,
- 0, 0, qi);
+ hapd->conf->nai_realm_data != NULL, qi);
break;
case ANQP_3GPP_CELLULAR_NETWORK:
set_anqp_req(ANQP_REQ_3GPP_CELLULAR_NETWORK,
"3GPP Cellular Network",
- hapd->conf->anqp_3gpp_cell_net != NULL,
- 0, 0, qi);
+ hapd->conf->anqp_3gpp_cell_net != NULL, qi);
break;
case ANQP_DOMAIN_NAME:
set_anqp_req(ANQP_REQ_DOMAIN_NAME, "Domain Name",
- hapd->conf->domain_name != NULL,
- 0, 0, qi);
+ hapd->conf->domain_name != NULL, qi);
break;
default:
wpa_printf(MSG_DEBUG, "ANQP: Unsupported Info Id %u",
@@ -857,33 +832,30 @@
switch (subtype) {
case HS20_STYPE_CAPABILITY_LIST:
set_anqp_req(ANQP_REQ_HS_CAPABILITY_LIST, "HS Capability List",
- 1, 0, 0, qi);
+ 1, qi);
break;
case HS20_STYPE_OPERATOR_FRIENDLY_NAME:
set_anqp_req(ANQP_REQ_OPERATOR_FRIENDLY_NAME,
"Operator Friendly Name",
- hapd->conf->hs20_oper_friendly_name != NULL,
- 0, 0, qi);
+ hapd->conf->hs20_oper_friendly_name != NULL, qi);
break;
case HS20_STYPE_WAN_METRICS:
set_anqp_req(ANQP_REQ_WAN_METRICS, "WAN Metrics",
- hapd->conf->hs20_wan_metrics != NULL,
- 0, 0, qi);
+ hapd->conf->hs20_wan_metrics != NULL, qi);
break;
case HS20_STYPE_CONNECTION_CAPABILITY:
set_anqp_req(ANQP_REQ_CONNECTION_CAPABILITY,
"Connection Capability",
hapd->conf->hs20_connection_capability != NULL,
- 0, 0, qi);
+ qi);
break;
case HS20_STYPE_OPERATING_CLASS:
set_anqp_req(ANQP_REQ_OPERATING_CLASS, "Operating Class",
- hapd->conf->hs20_operating_class != NULL,
- 0, 0, qi);
+ hapd->conf->hs20_operating_class != NULL, qi);
break;
case HS20_STYPE_OSU_PROVIDERS_LIST:
set_anqp_req(ANQP_REQ_OSU_PROVIDERS_LIST, "OSU Providers list",
- hapd->conf->hs20_osu_providers_count, 0, 0, qi);
+ hapd->conf->hs20_osu_providers_count, qi);
break;
default:
wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 subtype %u",
@@ -1150,97 +1122,6 @@
}
-void gas_serv_tx_gas_response(struct hostapd_data *hapd, const u8 *dst,
- struct gas_dialog_info *dialog)
-{
- struct wpabuf *buf, *tx_buf;
- u8 dialog_token = dialog->dialog_token;
- size_t frag_len;
-
- if (dialog->sd_resp == NULL) {
- buf = gas_serv_build_gas_resp_payload(hapd,
- dialog->all_requested,
- dialog, NULL, 0, NULL, 0);
- wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Generated ANQP responses",
- buf);
- if (!buf)
- goto tx_gas_response_done;
- dialog->sd_resp = buf;
- dialog->sd_resp_pos = 0;
- }
- frag_len = wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos;
- if (frag_len > hapd->gas_frag_limit || dialog->comeback_delay ||
- hapd->conf->gas_comeback_delay) {
- u16 comeback_delay_tus = dialog->comeback_delay +
- GAS_SERV_COMEBACK_DELAY_FUDGE;
- u32 comeback_delay_secs, comeback_delay_usecs;
-
- if (hapd->conf->gas_comeback_delay) {
- /* Testing - allow overriding of the delay value */
- comeback_delay_tus = hapd->conf->gas_comeback_delay;
- }
-
- wpa_printf(MSG_DEBUG, "GAS: Response frag_len %u (frag limit "
- "%u) and comeback delay %u, "
- "requesting comebacks", (unsigned int) frag_len,
- (unsigned int) hapd->gas_frag_limit,
- dialog->comeback_delay);
- tx_buf = gas_anqp_build_initial_resp_buf(dialog_token,
- WLAN_STATUS_SUCCESS,
- comeback_delay_tus,
- NULL);
- if (tx_buf) {
- wpa_msg(hapd->msg_ctx, MSG_DEBUG,
- "GAS: Tx GAS Initial Resp (comeback = 10TU)");
- if (dialog->prot)
- convert_to_protected_dual(tx_buf);
- hostapd_drv_send_action(hapd, hapd->iface->freq, 0,
- dst,
- wpabuf_head(tx_buf),
- wpabuf_len(tx_buf));
- }
- wpabuf_free(tx_buf);
-
- /* start a timer of 1.5 * comeback-delay */
- comeback_delay_tus = comeback_delay_tus +
- (comeback_delay_tus / 2);
- comeback_delay_secs = (comeback_delay_tus * 1024) / 1000000;
- comeback_delay_usecs = (comeback_delay_tus * 1024) -
- (comeback_delay_secs * 1000000);
- eloop_register_timeout(comeback_delay_secs,
- comeback_delay_usecs,
- gas_serv_clear_cached_ies, dialog,
- NULL);
- goto tx_gas_response_done;
- }
-
- buf = wpabuf_alloc_copy(wpabuf_head_u8(dialog->sd_resp) +
- dialog->sd_resp_pos, frag_len);
- if (buf == NULL) {
- wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Buffer allocation "
- "failed");
- goto tx_gas_response_done;
- }
- tx_buf = gas_anqp_build_initial_resp_buf(dialog_token,
- WLAN_STATUS_SUCCESS, 0, buf);
- wpabuf_free(buf);
- if (tx_buf == NULL)
- goto tx_gas_response_done;
- wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Initial "
- "Response (frag_id %d frag_len %d)",
- dialog->sd_frag_id, (int) frag_len);
- dialog->sd_frag_id++;
-
- if (dialog->prot)
- convert_to_protected_dual(tx_buf);
- hostapd_drv_send_action(hapd, hapd->iface->freq, 0, dst,
- wpabuf_head(tx_buf), wpabuf_len(tx_buf));
- wpabuf_free(tx_buf);
-tx_gas_response_done:
- gas_serv_clear_cached_ies(dialog, NULL);
-}
-
-
static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd,
const u8 *sa,
const u8 *data, size_t len, int prot)
@@ -1274,33 +1155,6 @@
goto send_resp;
}
- if (dialog->sd_resp == NULL) {
- wpa_printf(MSG_DEBUG, "GAS: Remote request 0x%x received 0x%x",
- dialog->requested, dialog->received);
- if ((dialog->requested & dialog->received) !=
- dialog->requested) {
- wpa_printf(MSG_DEBUG, "GAS: Did not receive response "
- "from remote processing");
- gas_serv_dialog_clear(dialog);
- tx_buf = gas_anqp_build_comeback_resp_buf(
- dialog_token,
- WLAN_STATUS_GAS_RESP_NOT_RECEIVED, 0, 0, 0,
- NULL);
- if (tx_buf == NULL)
- return;
- goto send_resp;
- }
-
- buf = gas_serv_build_gas_resp_payload(hapd,
- dialog->all_requested,
- dialog, NULL, 0, NULL, 0);
- wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Generated ANQP responses",
- buf);
- if (!buf)
- goto rx_gas_comeback_req_done;
- dialog->sd_resp = buf;
- dialog->sd_resp_pos = 0;
- }
frag_len = wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos;
if (frag_len > hapd->gas_frag_limit) {
frag_len = hapd->gas_frag_limit;
@@ -1313,15 +1167,18 @@
if (buf == NULL) {
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Failed to allocate "
"buffer");
- goto rx_gas_comeback_req_done;
+ gas_serv_dialog_clear(dialog);
+ return;
}
tx_buf = gas_anqp_build_comeback_resp_buf(dialog_token,
WLAN_STATUS_SUCCESS,
dialog->sd_frag_id,
more, 0, buf);
wpabuf_free(buf);
- if (tx_buf == NULL)
- goto rx_gas_comeback_req_done;
+ if (tx_buf == NULL) {
+ gas_serv_dialog_clear(dialog);
+ return;
+ }
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Comeback Response "
"(frag_id %d more=%d frag_len=%d)",
dialog->sd_frag_id, more, (int) frag_len);
@@ -1346,10 +1203,6 @@
hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
wpabuf_head(tx_buf), wpabuf_len(tx_buf));
wpabuf_free(tx_buf);
- return;
-
-rx_gas_comeback_req_done:
- gas_serv_clear_cached_ies(dialog, NULL);
}
diff --git a/src/ap/gas_serv.h b/src/ap/gas_serv.h
index 7e392b3..4ec3201 100644
--- a/src/ap/gas_serv.h
+++ b/src/ap/gas_serv.h
@@ -42,29 +42,17 @@
#define ANQP_REQ_ICON_REQUEST \
(0x10000 << HS20_STYPE_ICON_REQUEST)
-/* To account for latencies between hostapd and external ANQP processor */
-#define GAS_SERV_COMEBACK_DELAY_FUDGE 10
-#define GAS_SERV_MIN_COMEBACK_DELAY 100 /* in TU */
-
struct gas_dialog_info {
u8 valid;
- u8 index;
struct wpabuf *sd_resp; /* Fragmented response */
u8 dialog_token;
size_t sd_resp_pos; /* Offset in sd_resp */
u8 sd_frag_id;
- u16 comeback_delay;
int prot; /* whether Protected Dual of Public Action frame is used */
-
- unsigned int requested;
- unsigned int received;
- unsigned int all_requested;
};
struct hostapd_data;
-void gas_serv_tx_gas_response(struct hostapd_data *hapd, const u8 *dst,
- struct gas_dialog_info *dialog);
struct gas_dialog_info *
gas_serv_dialog_find(struct hostapd_data *hapd, const u8 *addr,
u8 dialog_token);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index bc5bb6c..4ed718c 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1093,7 +1093,7 @@
if (ret < 0) {
wpa_printf(MSG_ERROR, "Could not select hw_mode and "
"channel. (%d)", ret);
- return -1;
+ goto fail;
}
if (ret == 1) {
wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback (ACS)");
@@ -1101,7 +1101,7 @@
}
ret = hostapd_check_ht_capab(iface);
if (ret < 0)
- return -1;
+ goto fail;
if (ret == 1) {
wpa_printf(MSG_DEBUG, "Interface initialization will "
"be completed in a callback");
@@ -1112,6 +1112,13 @@
wpa_printf(MSG_DEBUG, "DFS support is enabled");
}
return hostapd_setup_interface_complete(iface, 0);
+
+fail:
+ hostapd_set_state(iface, HAPD_IFACE_DISABLED);
+ wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
+ if (iface->interfaces && iface->interfaces->terminate_on_error)
+ eloop_terminate();
+ return -1;
}
@@ -1129,13 +1136,8 @@
size_t j;
u8 *prev_addr;
- if (err) {
- wpa_printf(MSG_ERROR, "Interface initialization failed");
- hostapd_set_state(iface, HAPD_IFACE_DISABLED);
- if (iface->interfaces && iface->interfaces->terminate_on_error)
- eloop_terminate();
- return -1;
- }
+ if (err)
+ goto fail;
wpa_printf(MSG_DEBUG, "Completing interface initialization");
if (iface->conf->channel) {
@@ -1152,8 +1154,11 @@
#ifdef NEED_AP_MLME
/* Check DFS */
res = hostapd_handle_dfs(iface);
- if (res <= 0)
+ if (res <= 0) {
+ if (res < 0)
+ goto fail;
return res;
+ }
#endif /* NEED_AP_MLME */
if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
@@ -1166,7 +1171,7 @@
hapd->iconf->vht_oper_centr_freq_seg1_idx)) {
wpa_printf(MSG_ERROR, "Could not set channel for "
"kernel driver");
- return -1;
+ goto fail;
}
}
@@ -1177,7 +1182,7 @@
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"Failed to prepare rates table.");
- return -1;
+ goto fail;
}
}
@@ -1185,14 +1190,14 @@
hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {
wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
"kernel driver");
- return -1;
+ goto fail;
}
if (hapd->iconf->fragm_threshold > -1 &&
hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) {
wpa_printf(MSG_ERROR, "Could not set fragmentation threshold "
"for kernel driver");
- return -1;
+ goto fail;
}
prev_addr = hapd->own_addr;
@@ -1202,7 +1207,7 @@
if (j)
os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
if (hostapd_setup_bss(hapd, j == 0))
- return -1;
+ goto fail;
if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
prev_addr = hapd->own_addr;
}
@@ -1217,7 +1222,7 @@
if (hostapd_driver_commit(hapd) < 0) {
wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
"configuration", __func__);
- return -1;
+ goto fail;
}
/*
@@ -1228,7 +1233,7 @@
*/
for (j = 0; j < iface->num_bss; j++) {
if (hostapd_init_wps_complete(iface->bss[j]))
- return -1;
+ goto fail;
}
hostapd_set_state(iface, HAPD_IFACE_ENABLED);
@@ -1242,6 +1247,14 @@
iface->interfaces->terminate_on_error--;
return 0;
+
+fail:
+ wpa_printf(MSG_ERROR, "Interface initialization failed");
+ hostapd_set_state(iface, HAPD_IFACE_DISABLED);
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
+ if (iface->interfaces && iface->interfaces->terminate_on_error)
+ eloop_terminate();
+ return -1;
}
@@ -1824,6 +1837,7 @@
if (start_ctrl_iface_bss(hapd) < 0 ||
(hapd_iface->state == HAPD_IFACE_ENABLED &&
hostapd_setup_bss(hapd, -1))) {
+ hostapd_cleanup(hapd);
hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
hapd_iface->conf->num_bss--;
hapd_iface->num_bss--;
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 28e92fd..d319ce0 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -327,7 +327,7 @@
int match;
pri_chan = iface->conf->channel;
- sec_chan = iface->conf->secondary_channel * 4;
+ sec_chan = pri_chan + iface->conf->secondary_channel * 4;
pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan);
if (iface->conf->secondary_channel > 0)
sec_freq = pri_freq + 20;
@@ -351,6 +351,7 @@
"channel to get secondary channel with no Beacons "
"from other BSSes");
ieee80211n_switch_pri_sec(iface);
+ return 1;
}
/*
diff --git a/src/ap/iapp.c b/src/ap/iapp.c
index bad080f..9b2900f 100644
--- a/src/ap/iapp.c
+++ b/src/ap/iapp.c
@@ -242,29 +242,22 @@
*/
void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta)
{
- struct ieee80211_mgmt *assoc;
- u16 seq;
+ u16 seq = 0; /* TODO */
if (iapp == NULL)
return;
- assoc = sta->last_assoc_req;
- seq = assoc ? WLAN_GET_SEQ_SEQ(le_to_host16(assoc->seq_ctrl)) : 0;
-
/* IAPP-ADD.request(MAC Address, Sequence Number, Timeout) */
hostapd_logger(iapp->hapd, sta->addr, HOSTAPD_MODULE_IAPP,
HOSTAPD_LEVEL_DEBUG, "IAPP-ADD.request(seq=%d)", seq);
iapp_send_layer2_update(iapp, sta->addr);
iapp_send_add(iapp, sta->addr, seq);
- if (assoc && WLAN_FC_GET_STYPE(le_to_host16(assoc->frame_control)) ==
- WLAN_FC_STYPE_REASSOC_REQ) {
- /* IAPP-MOVE.request(MAC Address, Sequence Number, Old AP,
- * Context Block, Timeout)
- */
- /* TODO: Send IAPP-MOVE to the old AP; Map Old AP BSSID to
- * IP address */
- }
+ /* TODO: If this was reassociation:
+ * IAPP-MOVE.request(MAC Address, Sequence Number, Old AP,
+ * Context Block, Timeout)
+ * TODO: Send IAPP-MOVE to the old AP; Map Old AP BSSID to
+ * IP address */
}
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index c97cef1..14fb567 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1445,17 +1445,6 @@
}
#endif /* CONFIG_IEEE80211W */
- if (reassoc) {
- os_memcpy(sta->previous_ap, mgmt->u.reassoc_req.current_ap,
- ETH_ALEN);
- }
-
- if (sta->last_assoc_req)
- os_free(sta->last_assoc_req);
- sta->last_assoc_req = os_malloc(len);
- if (sta->last_assoc_req)
- os_memcpy(sta->last_assoc_req, mgmt, len);
-
/* Make sure that the previously registered inactivity timer will not
* remove the STA immediately. */
sta->timeout_next = STA_NULLFUNC;
@@ -1924,7 +1913,7 @@
status = le_to_host16(mgmt->u.assoc_resp.status_code);
if (status != WLAN_STATUS_SUCCESS)
- goto fail;
+ return;
/* Stop previous accounting session, if one is started, and allocate
* new session id for the new session. */
@@ -1986,7 +1975,7 @@
ap_sta_disconnect(hapd, sta, sta->addr,
WLAN_REASON_DISASSOC_AP_BUSY);
- goto fail;
+ return;
}
if (sta->flags & WLAN_STA_WDS) {
@@ -2006,11 +1995,11 @@
* interface selection is not going to change anymore.
*/
if (ap_sta_bind_vlan(hapd, sta, 0) < 0)
- goto fail;
+ return;
} else if (sta->vlan_id) {
/* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
if (ap_sta_bind_vlan(hapd, sta, 0) < 0)
- goto fail;
+ return;
}
hostapd_set_sta_flags(hapd, sta);
@@ -2022,13 +2011,6 @@
hapd->new_assoc_sta_cb(hapd, sta, !new_assoc);
ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
-
- fail:
- /* Copy of the association request is not needed anymore */
- if (sta->last_assoc_req) {
- os_free(sta->last_assoc_req);
- sta->last_assoc_req = NULL;
- }
}
diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
index a166178..138d049 100644
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -54,7 +54,20 @@
scan_params->width_trigger_scan_interval =
host_to_le16(hapd->iconf->obss_interval);
- /* TODO: Fill in more parameters (supplicant ignores them) */
+ /* Fill in default values for remaining parameters
+ * (IEEE Std 802.11-2012, 8.4.2.61 and MIB defval) */
+ scan_params->scan_passive_dwell =
+ host_to_le16(20);
+ scan_params->scan_active_dwell =
+ host_to_le16(10);
+ scan_params->scan_passive_total_per_channel =
+ host_to_le16(200);
+ scan_params->scan_active_total_per_channel =
+ host_to_le16(20);
+ scan_params->channel_transition_delay_factor =
+ host_to_le16(5);
+ scan_params->scan_activity_threshold =
+ host_to_le16(25);
pos += sizeof(*scan_params);
}
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index b78fd01..12403f9 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -170,6 +170,8 @@
switch (idx) {
case 0: /* Bits 0-7 */
+ if (hapd->iconf->obss_interval)
+ *pos |= 0x01; /* Bit 0 - Coexistence management */
break;
case 1: /* Bits 8-15 */
break;
@@ -223,6 +225,8 @@
len = 4;
if (len < 3 && hapd->conf->wnm_sleep_mode)
len = 3;
+ if (len < 1 && hapd->iconf->obss_interval)
+ len = 1;
if (len < 7 && hapd->conf->ssid.utf8_ssid)
len = 7;
#ifdef CONFIG_WNM
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index c7d051b..f5417de 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -239,7 +239,6 @@
radius_client_flush_auth(hapd->radius, sta->addr);
#endif /* CONFIG_NO_RADIUS */
- os_free(sta->last_assoc_req);
os_free(sta->challenge);
#ifdef CONFIG_IEEE80211W
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index c0bab6f..2dbdeb1 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -61,7 +61,6 @@
unsigned int hs20_deauth_requested:1;
u16 auth_alg;
- u8 previous_ap[6];
enum {
STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE,
@@ -74,9 +73,6 @@
/* IEEE 802.1X related data */
struct eapol_state_machine *eapol_sm;
- /* IEEE 802.11f (IAPP) related data */
- struct ieee80211_mgmt *last_assoc_req;
-
u32 acct_session_id_hi;
u32 acct_session_id_lo;
struct os_reltime acct_session_start;
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 7d89edf..4d19bb0 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -1918,7 +1918,9 @@
static int ieee80211w_kde_len(struct wpa_state_machine *sm)
{
if (sm->mgmt_frame_prot) {
- return 2 + RSN_SELECTOR_LEN + sizeof(struct wpa_igtk_kde);
+ size_t len;
+ len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
+ return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len;
}
return 0;
@@ -1930,6 +1932,7 @@
struct wpa_igtk_kde igtk;
struct wpa_group *gsm = sm->group;
u8 rsc[WPA_KEY_RSC_LEN];
+ size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
if (!sm->mgmt_frame_prot)
return pos;
@@ -1941,17 +1944,18 @@
os_memset(igtk.pn, 0, sizeof(igtk.pn));
else
os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
- os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
+ os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
if (sm->wpa_auth->conf.disable_gtk) {
/*
* Provide unique random IGTK to each STA to prevent use of
* IGTK in the BSS.
*/
- if (random_get_bytes(igtk.igtk, WPA_IGTK_LEN) < 0)
+ if (random_get_bytes(igtk.igtk, len) < 0)
return pos;
}
pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
- (const u8 *) &igtk, sizeof(igtk), NULL, 0);
+ (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
+ NULL, 0);
return pos;
}
@@ -2457,15 +2461,16 @@
#ifdef CONFIG_IEEE80211W
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+ size_t len;
+ len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
inc_byte_array(group->Counter, WPA_NONCE_LEN);
if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
wpa_auth->addr, group->GNonce,
- group->IGTK[group->GN_igtk - 4],
- WPA_IGTK_LEN) < 0)
+ group->IGTK[group->GN_igtk - 4], len) < 0)
ret = -1;
wpa_hexdump_key(MSG_DEBUG, "IGTK",
- group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN);
+ group->IGTK[group->GN_igtk - 4], len);
}
#endif /* CONFIG_IEEE80211W */
@@ -2582,26 +2587,27 @@
{
struct wpa_group *gsm = sm->group;
u8 *start = pos;
+ size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
/*
* IGTK subelement:
* Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
*/
*pos++ = WNM_SLEEP_SUBELEM_IGTK;
- *pos++ = 2 + 6 + WPA_IGTK_LEN;
+ *pos++ = 2 + 6 + len;
WPA_PUT_LE16(pos, gsm->GN_igtk);
pos += 2;
if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
return 0;
pos += 6;
- os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
- pos += WPA_IGTK_LEN;
+ os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
+ pos += len;
wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
gsm->GN_igtk);
wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
- gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
+ gsm->IGTK[gsm->GN_igtk - 4], len);
return pos - start;
}
@@ -2656,12 +2662,19 @@
ret = -1;
#ifdef CONFIG_IEEE80211W
- if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION &&
- wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK,
- broadcast_ether_addr, group->GN_igtk,
- group->IGTK[group->GN_igtk - 4],
- WPA_IGTK_LEN) < 0)
- ret = -1;
+ if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+ enum wpa_alg alg;
+ size_t len;
+
+ alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher);
+ len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
+
+ if (ret == 0 &&
+ wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
+ broadcast_ether_addr, group->GN_igtk,
+ group->IGTK[group->GN_igtk - 4], len) < 0)
+ ret = -1;
+ }
#endif /* CONFIG_IEEE80211W */
return ret;
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index d99db69..3ab3e3d 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -142,6 +142,7 @@
int tx_status;
#ifdef CONFIG_IEEE80211W
enum mfp_options ieee80211w;
+ int group_mgmt_cipher;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
#define SSID_LEN 32
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index da5fea7..6ee9a4f 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -49,6 +49,7 @@
wconf->okc = conf->okc;
#ifdef CONFIG_IEEE80211W
wconf->ieee80211w = conf->ieee80211w;
+ wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
wconf->ssid_len = conf->ssid.ssid_len;
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index fcd5878..2e1bdcf 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -154,7 +154,7 @@
Boolean first_sta_seen;
Boolean reject_4way_hs_for_entropy;
#ifdef CONFIG_IEEE80211W
- u8 IGTK[2][WPA_IGTK_LEN];
+ u8 IGTK[2][WPA_IGTK_MAX_LEN];
int GN_igtk, GM_igtk;
#endif /* CONFIG_IEEE80211W */
};
diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
index 7a49751..e957c6e 100644
--- a/src/ap/wpa_auth_ie.c
+++ b/src/ap/wpa_auth_ie.c
@@ -261,7 +261,25 @@
}
/* Management Group Cipher Suite */
- RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
+ switch (conf->group_mgmt_cipher) {
+ case WPA_CIPHER_AES_128_CMAC:
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
+ break;
+ case WPA_CIPHER_BIP_GMAC_128:
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_128);
+ break;
+ case WPA_CIPHER_BIP_GMAC_256:
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256);
+ break;
+ case WPA_CIPHER_BIP_CMAC_256:
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_CMAC_256);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG,
+ "Invalid group management cipher (0x%x)",
+ conf->group_mgmt_cipher);
+ return -1;
+ }
pos += RSN_SELECTOR_LEN;
}
#endif /* CONFIG_IEEE80211W */
@@ -586,7 +604,8 @@
return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
}
- if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
+ if (data.mgmt_group_cipher != wpa_auth->conf.group_mgmt_cipher)
+ {
wpa_printf(MSG_DEBUG, "Unsupported management group "
"cipher %d", data.mgmt_group_cipher);
return WPA_INVALID_MGMT_GROUP_CIPHER;