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;