Accumulative patch from commit 97279d8d1ad40bd7d884af8e2fc26dff0163331a

97279d8 nl80211: Drop frame events that are for foreign address
cc2ada8 nl80211: Reduce debug on Probe Request frames
63a965c P2P: Fix after_scan_tx processing during ongoing operations
06b7f58 RSN: Update preauth scan results only based on new scan results
18e00b5 Move wpa_s freeing into wpa_supplicant_deinit_iface()
754632c dbus_new: Add EAP logon/logoff
c2aff6b hostapd: Add some testing options
adc96dc nl80211: Fix nla_nest_start conversion
0606052 wpa_supplicant: Add get_capability freq
c7a39ba Provide TLS alerts to CLI/UI over control interface
2a07a27 P2P: Increase GTK rekeying period to 24 hours
75fa7d1 TDLS: Fix key configuration with current mac80211
8970bae nl80211: Use nla_nest_start/end instead of nla_put_nested

Change-Id: Ic4b568c341657d266b7759513230d4ef206d75b1
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 922f564..70b26a6 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -163,6 +163,13 @@
 	conf->ap_table_max_size = 255;
 	conf->ap_table_expiration_time = 60;
 
+#ifdef CONFIG_TESTING_OPTIONS
+	conf->ignore_probe_probability = 0.0d;
+	conf->ignore_auth_probability = 0.0d;
+	conf->ignore_assoc_probability = 0.0d;
+	conf->ignore_reassoc_probability = 0.0d;
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	return conf;
 }
 
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index d9ef984..f9629a2 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -520,6 +520,13 @@
 	u8 vht_oper_chwidth;
 	u8 vht_oper_centr_freq_seg0_idx;
 	u8 vht_oper_centr_freq_seg1_idx;
+
+#ifdef CONFIG_TESTING_OPTIONS
+	double ignore_probe_probability;
+	double ignore_auth_probability;
+	double ignore_assoc_probability;
+	double ignore_reassoc_probability;
+#endif /* CONFIG_TESTING_OPTIONS */
 };
 
 
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 4c47c75..0ef307d 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -488,6 +488,16 @@
 	/* TODO: verify that supp_rates contains at least one matching rate
 	 * with AP configuration */
 
+#ifdef CONFIG_TESTING_OPTIONS
+	if (hapd->iconf->ignore_probe_probability > 0.0d &&
+	    drand48() < hapd->iconf->ignore_probe_probability) {
+		wpa_printf(MSG_INFO,
+			   "TESTING: ignoring probe request from " MACSTR,
+			   MAC2STR(mgmt->sa));
+		return;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	resp = hostapd_gen_probe_resp(hapd, sta, mgmt, elems.p2p != NULL,
 				      &resp_len);
 	if (resp == NULL)
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 6d22d49..5e3caf1 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -730,6 +730,9 @@
 		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
 		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
 			level = MSG_EXCESSIVE;
+		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
+		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ)
+			level = MSG_EXCESSIVE;
 	}
 
 	wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received",
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 8baa15e..7bef55f 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -557,6 +557,16 @@
 		return;
 	}
 
+#ifdef CONFIG_TESTING_OPTIONS
+	if (hapd->iconf->ignore_auth_probability > 0.0d &&
+	    drand48() < hapd->iconf->ignore_auth_probability) {
+		wpa_printf(MSG_INFO,
+			   "TESTING: ignoring auth frame from " MACSTR,
+			   MAC2STR(mgmt->sa));
+		return;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
 	auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
 	status_code = le_to_host16(mgmt->u.auth.status_code);
@@ -1226,6 +1236,26 @@
 		return;
 	}
 
+#ifdef CONFIG_TESTING_OPTIONS
+	if (reassoc) {
+		if (hapd->iconf->ignore_reassoc_probability > 0.0d &&
+		    drand48() < hapd->iconf->ignore_reassoc_probability) {
+			wpa_printf(MSG_INFO,
+				   "TESTING: ignoring reassoc request from "
+				   MACSTR, MAC2STR(mgmt->sa));
+			return;
+		}
+	} else {
+		if (hapd->iconf->ignore_assoc_probability > 0.0d &&
+		    drand48() < hapd->iconf->ignore_assoc_probability) {
+			wpa_printf(MSG_INFO,
+				   "TESTING: ignoring assoc request from "
+				   MACSTR, MAC2STR(mgmt->sa));
+			return;
+		}
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	if (reassoc) {
 		capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info);
 		listen_interval = le_to_host16(
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index dbabe8c..aab228b 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -44,6 +44,8 @@
 #define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT "
 /** EAP TLS certificate chain validation error */
 #define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR "
+/** EAP status */
+#define WPA_EVENT_EAP_STATUS "CTRL-EVENT-EAP-STATUS "
 /** EAP authentication completed successfully */
 #define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
 /** EAP authentication failed (EAP-Failure received) */
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index c59d5bf..0b5a7dc 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -1308,7 +1308,7 @@
 	u16 fc, stype;
 	int ssi_signal = 0;
 
-	wpa_printf(MSG_DEBUG, "nl80211: Frame event");
+	wpa_printf(MSG_MSGDUMP, "nl80211: Frame event");
 	mgmt = (const struct ieee80211_mgmt *) frame;
 	if (len < 24) {
 		wpa_printf(MSG_DEBUG, "nl80211: Too short action frame");
@@ -1485,12 +1485,16 @@
 }
 
 
-static void mlme_event(struct wpa_driver_nl80211_data *drv,
+static void mlme_event(struct i802_bss *bss,
 		       enum nl80211_commands cmd, struct nlattr *frame,
 		       struct nlattr *addr, struct nlattr *timed_out,
 		       struct nlattr *freq, struct nlattr *ack,
 		       struct nlattr *cookie, struct nlattr *sig)
 {
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	const u8 *data;
+	size_t len;
+
 	if (timed_out && addr) {
 		mlme_timeout_event(drv, cmd, addr);
 		return;
@@ -1502,7 +1506,23 @@
 		return;
 	}
 
-	wpa_printf(MSG_DEBUG, "nl80211: MLME event %d", cmd);
+	data = nla_data(frame);
+	len = nla_len(frame);
+	if (len < 4 + ETH_ALEN) {
+		wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d on %s(" MACSTR
+			   ") - too short",
+			   cmd, bss->ifname, MAC2STR(bss->addr));
+		return;
+	}
+	wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d on %s(" MACSTR ") A1="
+		   MACSTR, cmd, bss->ifname, MAC2STR(bss->addr),
+		   MAC2STR(data + 4));
+	if (cmd != NL80211_CMD_FRAME_TX_STATUS && !(data[4] & 0x01) &&
+	    os_memcmp(bss->addr, data + 4, ETH_ALEN) != 0) {
+		wpa_printf(MSG_MSGDUMP, "nl80211: %s: Ignore MLME frame event "
+			   "for foreign address", bss->ifname);
+		return;
+	}
 	wpa_hexdump(MSG_MSGDUMP, "nl80211: MLME event frame",
 		    nla_data(frame), nla_len(frame));
 
@@ -2301,7 +2321,7 @@
 	case NL80211_CMD_FRAME_TX_STATUS:
 	case NL80211_CMD_UNPROT_DEAUTHENTICATE:
 	case NL80211_CMD_UNPROT_DISASSOCIATE:
-		mlme_event(drv, cmd, tb[NL80211_ATTR_FRAME],
+		mlme_event(bss, cmd, tb[NL80211_ATTR_FRAME],
 			   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
 			   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
 			   tb[NL80211_ATTR_COOKIE],
@@ -2450,7 +2470,7 @@
 	switch (gnlh->cmd) {
 	case NL80211_CMD_FRAME:
 	case NL80211_CMD_FRAME_TX_STATUS:
-		mlme_event(bss->drv, gnlh->cmd, tb[NL80211_ATTR_FRAME],
+		mlme_event(bss, gnlh->cmd, tb[NL80211_ATTR_FRAME],
 			   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
 			   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
 			   tb[NL80211_ATTR_COOKIE],
@@ -2477,7 +2497,7 @@
 {
 	struct nl_cb *cb = eloop_ctx;
 
-	wpa_printf(MSG_DEBUG, "nl80211: Event message available");
+	wpa_printf(MSG_MSGDUMP, "nl80211: Event message available");
 
 	nl_recvmsgs(handle, cb);
 }
@@ -3812,7 +3832,6 @@
 		    struct wpa_driver_scan_params *params)
 {
 	struct nl_msg *msg;
-	int err;
 	size_t i;
 
 	msg = nlmsg_alloc();
@@ -3825,23 +3844,20 @@
 		goto fail;
 
 	if (params->num_ssids) {
-		struct nl_msg *ssids = nlmsg_alloc();
+		struct nlattr *ssids;
+
+		ssids = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
 		if (ssids == NULL)
 			goto fail;
 		for (i = 0; i < params->num_ssids; i++) {
 			wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID",
 					  params->ssids[i].ssid,
 					  params->ssids[i].ssid_len);
-			if (nla_put(ssids, i + 1, params->ssids[i].ssid_len,
-				    params->ssids[i].ssid) < 0) {
-				nlmsg_free(ssids);
+			if (nla_put(msg, i + 1, params->ssids[i].ssid_len,
+				    params->ssids[i].ssid) < 0)
 				goto fail;
-			}
 		}
-		err = nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
-		nlmsg_free(ssids);
-		if (err < 0)
-			goto fail;
+		nla_nest_end(msg, ssids);
 	}
 
 	if (params->extra_ies) {
@@ -3853,22 +3869,17 @@
 	}
 
 	if (params->freqs) {
-		struct nl_msg *freqs = nlmsg_alloc();
+		struct nlattr *freqs;
+		freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
 		if (freqs == NULL)
 			goto fail;
 		for (i = 0; params->freqs[i]; i++) {
 			wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
 				   "MHz", params->freqs[i]);
-			if (nla_put_u32(freqs, i + 1, params->freqs[i]) < 0) {
-				nlmsg_free(freqs);
+			if (nla_put_u32(msg, i + 1, params->freqs[i]) < 0)
 				goto fail;
-			}
 		}
-		err = nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES,
-				     freqs);
-		nlmsg_free(freqs);
-		if (err < 0)
-			goto fail;
+		nla_nest_end(msg, freqs);
 	}
 
 	os_free(drv->filter_ssids);
@@ -3895,7 +3906,7 @@
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int ret = -1, timeout;
-	struct nl_msg *msg, *rates = NULL;
+	struct nl_msg *msg = NULL;
 
 	wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
 	drv->scan_for_auth = 0;
@@ -3905,9 +3916,11 @@
 		return -1;
 
 	if (params->p2p_probe) {
+		struct nlattr *rates;
+
 		wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates");
 
-		rates = nlmsg_alloc();
+		rates = nla_nest_start(msg, NL80211_ATTR_SCAN_SUPP_RATES);
 		if (rates == NULL)
 			goto nla_put_failure;
 
@@ -3917,11 +3930,9 @@
 		 * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
 		 * rates are left enabled.
 		 */
-		NLA_PUT(rates, NL80211_BAND_2GHZ, 8,
+		NLA_PUT(msg, NL80211_BAND_2GHZ, 8,
 			"\x0c\x12\x18\x24\x30\x48\x60\x6c");
-		if (nla_put_nested(msg, NL80211_ATTR_SCAN_SUPP_RATES, rates) <
-		    0)
-			goto nla_put_failure;
+		nla_nest_end(msg, rates);
 
 		NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
 	}
@@ -3975,7 +3986,6 @@
 
 nla_put_failure:
 	nlmsg_free(msg);
-	nlmsg_free(rates);
 	return ret;
 }
 
@@ -3995,8 +4005,6 @@
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int ret = -1;
 	struct nl_msg *msg;
-	struct nl_msg *match_set_ssid = NULL, *match_sets = NULL;
-	struct nl_msg *match_set_rssi = NULL;
 	size_t i;
 
 	wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: sched_scan request");
@@ -4015,46 +4023,42 @@
 	if ((drv->num_filter_ssids &&
 	    (int) drv->num_filter_ssids <= drv->capa.max_match_sets) ||
 	    params->filter_rssi) {
-		match_sets = nlmsg_alloc();
+		struct nlattr *match_sets;
+		match_sets = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
 		if (match_sets == NULL)
 			goto nla_put_failure;
 
 		for (i = 0; i < drv->num_filter_ssids; i++) {
+			struct nlattr *match_set_ssid;
 			wpa_hexdump_ascii(MSG_MSGDUMP,
 					  "nl80211: Sched scan filter SSID",
 					  drv->filter_ssids[i].ssid,
 					  drv->filter_ssids[i].ssid_len);
 
-			match_set_ssid = nlmsg_alloc();
+			match_set_ssid = nla_nest_start(msg, i + 1);
 			if (match_set_ssid == NULL)
 				goto nla_put_failure;
-			NLA_PUT(match_set_ssid,
-				NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
+			NLA_PUT(msg, NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
 				drv->filter_ssids[i].ssid_len,
 				drv->filter_ssids[i].ssid);
 
-			if (nla_put_nested(match_sets, i + 1, match_set_ssid) <
-			    0)
-				goto nla_put_failure;
+			nla_nest_end(msg, match_set_ssid);
 		}
 
 		if (params->filter_rssi) {
-			match_set_rssi = nlmsg_alloc();
+			struct nlattr *match_set_rssi;
+			match_set_rssi = nla_nest_start(msg, 0);
 			if (match_set_rssi == NULL)
 				goto nla_put_failure;
-			NLA_PUT_U32(match_set_rssi,
-				    NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
+			NLA_PUT_U32(msg, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
 				    params->filter_rssi);
 			wpa_printf(MSG_MSGDUMP,
 				   "nl80211: Sched scan RSSI filter %d dBm",
 				   params->filter_rssi);
-			if (nla_put_nested(match_sets, 0, match_set_rssi) < 0)
-				goto nla_put_failure;
+			nla_nest_end(msg, match_set_rssi);
 		}
 
-		if (nla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH,
-				   match_sets) < 0)
-			goto nla_put_failure;
+		nla_nest_end(msg, match_sets);
 	}
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
@@ -4072,9 +4076,6 @@
 		   "scan interval %d msec", ret, interval);
 
 nla_put_failure:
-	nlmsg_free(match_set_ssid);
-	nlmsg_free(match_sets);
-	nlmsg_free(match_set_rssi);
 	nlmsg_free(msg);
 	return ret;
 }
@@ -4563,18 +4564,15 @@
 				    NL80211_KEYTYPE_GROUP);
 		}
 	} else if (addr && is_broadcast_ether_addr(addr)) {
-		struct nl_msg *types;
-		int err;
+		struct nlattr *types;
+
 		wpa_printf(MSG_DEBUG, "   broadcast key");
-		types = nlmsg_alloc();
+
+		types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
 		if (!types)
 			goto nla_put_failure;
-		NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
-		err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,
-				     types);
-		nlmsg_free(types);
-		if (err)
-			goto nla_put_failure;
+		NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
+		nla_nest_end(msg, types);
 	}
 	NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
@@ -4608,29 +4606,21 @@
 	else
 		NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);
 	if (addr && is_broadcast_ether_addr(addr)) {
-		struct nl_msg *types;
-		int err;
-		types = nlmsg_alloc();
+		struct nlattr *types;
+
+		types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
 		if (!types)
 			goto nla_put_failure;
-		NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
-		err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,
-				     types);
-		nlmsg_free(types);
-		if (err)
-			goto nla_put_failure;
+		NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
+		nla_nest_end(msg, types);
 	} else if (addr) {
-		struct nl_msg *types;
-		int err;
-		types = nlmsg_alloc();
+		struct nlattr *types;
+
+		types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
 		if (!types)
 			goto nla_put_failure;
-		NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_UNICAST);
-		err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,
-				     types);
-		nlmsg_free(types);
-		if (err)
-			goto nla_put_failure;
+		NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_UNICAST);
+		nla_nest_end(msg, types);
 	}
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
@@ -6102,7 +6092,7 @@
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct nl_msg *msg, *wme = NULL;
+	struct nl_msg *msg;
 	struct nl80211_sta_flag_update upd;
 	int ret = -ENOBUFS;
 
@@ -6169,18 +6159,18 @@
 	NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
 
 	if (params->flags & WPA_STA_WMM) {
-		wme = nlmsg_alloc();
+		struct nlattr *wme = nla_nest_start(msg, NL80211_ATTR_STA_WME);
+
 		if (!wme)
 			goto nla_put_failure;
 
 		wpa_printf(MSG_DEBUG, "  * qosinfo=0x%x", params->qosinfo);
-		NLA_PUT_U8(wme, NL80211_STA_WME_UAPSD_QUEUES,
+		NLA_PUT_U8(msg, NL80211_STA_WME_UAPSD_QUEUES,
 				params->qosinfo & WMM_QOSINFO_STA_AC_MASK);
-		NLA_PUT_U8(wme, NL80211_STA_WME_MAX_SP,
+		NLA_PUT_U8(msg, NL80211_STA_WME_MAX_SP,
 				(params->qosinfo >> WMM_QOSINFO_STA_SP_SHIFT) &
 				WMM_QOSINFO_STA_SP_MASK);
-		if (nla_put_nested(msg, NL80211_ATTR_STA_WME, wme) < 0)
-			goto nla_put_failure;
+		nla_nest_end(msg, wme);
 	}
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
@@ -6192,7 +6182,6 @@
 	if (ret == -EEXIST)
 		ret = 0;
  nla_put_failure:
-	nlmsg_free(wme);
 	nlmsg_free(msg);
 	return ret;
 }
@@ -6276,7 +6265,7 @@
 				     enum nl80211_iftype iftype,
 				     const u8 *addr, int wds)
 {
-	struct nl_msg *msg, *flags = NULL;
+	struct nl_msg *msg;
 	int ifidx;
 	int ret = -ENOBUFS;
 
@@ -6293,20 +6282,15 @@
 	NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);
 
 	if (iftype == NL80211_IFTYPE_MONITOR) {
-		int err;
+		struct nlattr *flags;
 
-		flags = nlmsg_alloc();
+		flags = nla_nest_start(msg, NL80211_ATTR_MNTR_FLAGS);
 		if (!flags)
 			goto nla_put_failure;
 
-		NLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES);
+		NLA_PUT_FLAG(msg, NL80211_MNTR_FLAG_COOK_FRAMES);
 
-		err = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags);
-
-		nlmsg_free(flags);
-
-		if (err)
-			goto nla_put_failure;
+		nla_nest_end(msg, flags);
 	} else if (wds) {
 		NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds);
 	}
@@ -6939,19 +6923,14 @@
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct nl_msg *msg, *flags = NULL;
+	struct nl_msg *msg;
+	struct nlattr *flags;
 	struct nl80211_sta_flag_update upd;
 
 	msg = nlmsg_alloc();
 	if (!msg)
 		return -ENOMEM;
 
-	flags = nlmsg_alloc();
-	if (!flags) {
-		nlmsg_free(msg);
-		return -ENOMEM;
-	}
-
 	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
@@ -6962,35 +6941,34 @@
 	 * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This
 	 * can be removed eventually.
 	 */
+	flags = nla_nest_start(msg, NL80211_ATTR_STA_FLAGS);
+	if (!flags)
+		goto nla_put_failure;
 	if (total_flags & WPA_STA_AUTHORIZED)
-		NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED);
+		NLA_PUT_FLAG(msg, NL80211_STA_FLAG_AUTHORIZED);
 
 	if (total_flags & WPA_STA_WMM)
-		NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME);
+		NLA_PUT_FLAG(msg, NL80211_STA_FLAG_WME);
 
 	if (total_flags & WPA_STA_SHORT_PREAMBLE)
-		NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE);
+		NLA_PUT_FLAG(msg, NL80211_STA_FLAG_SHORT_PREAMBLE);
 
 	if (total_flags & WPA_STA_MFP)
-		NLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP);
+		NLA_PUT_FLAG(msg, NL80211_STA_FLAG_MFP);
 
 	if (total_flags & WPA_STA_TDLS_PEER)
-		NLA_PUT_FLAG(flags, NL80211_STA_FLAG_TDLS_PEER);
+		NLA_PUT_FLAG(msg, NL80211_STA_FLAG_TDLS_PEER);
 
-	if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))
-		goto nla_put_failure;
+	nla_nest_end(msg, flags);
 
 	os_memset(&upd, 0, sizeof(upd));
 	upd.mask = sta_flags_nl80211(flags_or | ~flags_and);
 	upd.set = sta_flags_nl80211(flags_or);
 	NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
 
-	nlmsg_free(flags);
-
 	return send_and_recv_msgs(drv, msg, NULL, NULL);
  nla_put_failure:
 	nlmsg_free(msg);
-	nlmsg_free(flags);
 	return -ENOBUFS;
 }
 
@@ -8692,7 +8670,7 @@
 	if (!msg)
 		return -1;
 
-	wpa_printf(MSG_DEBUG, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
+	wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
 		   "no_ack=%d offchanok=%d",
 		   freq, wait, no_cck, no_ack, offchanok);
 	nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME);
@@ -8719,7 +8697,7 @@
 			   freq, wait);
 		goto nla_put_failure;
 	}
-	wpa_printf(MSG_DEBUG, "nl80211: Frame TX command accepted%s; "
+	wpa_printf(MSG_MSGDUMP, "nl80211: Frame TX command accepted%s; "
 		   "cookie 0x%llx", no_ack ? " (no ACK)" : "",
 		   (long long unsigned int) cookie);
 
@@ -9068,7 +9046,8 @@
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct nl_msg *msg, *cqm = NULL;
+	struct nl_msg *msg;
+	struct nlattr *cqm;
 	int ret = -1;
 
 	wpa_printf(MSG_DEBUG, "nl80211: Signal monitor threshold=%d "
@@ -9082,20 +9061,18 @@
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
 
-	cqm = nlmsg_alloc();
+	cqm = nla_nest_start(msg, NL80211_ATTR_CQM);
 	if (cqm == NULL)
 		goto nla_put_failure;
 
-	NLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_THOLD, threshold);
-	NLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_HYST, hysteresis);
-	if (nla_put_nested(msg, NL80211_ATTR_CQM, cqm) < 0)
-		goto nla_put_failure;
+	NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_THOLD, threshold);
+	NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_HYST, hysteresis);
+	nla_nest_end(msg, cqm);
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	msg = NULL;
 
 nla_put_failure:
-	nlmsg_free(cqm);
 	nlmsg_free(msg);
 	return ret;
 }
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index 2e56086..9b054fc 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -1533,6 +1533,10 @@
 {
 	if (sm) {
 		sm->userLogoff = logoff;
+		if (!logoff) {
+			/* If there is a delayed txStart queued, start now. */
+			sm->startWhen = 0;
+		}
 		eapol_sm_step(sm);
 	}
 }
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 2b5e5bd..00fbb90 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -988,8 +988,7 @@
 	enum p2p_after_scan op;
 
 	if (p2p->after_scan_tx) {
-		/* TODO: schedule p2p_run_after_scan to be called from TX
-		 * status callback(?) */
+		p2p->after_scan_tx_in_progress = 1;
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send pending "
 			"Action frame at p2p_scan completion");
 		p2p->cfg->send_action(p2p->cfg->cb_ctx,
@@ -3167,6 +3166,18 @@
 	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
 	switch (state) {
 	case P2P_NO_PENDING_ACTION:
+		if (p2p->after_scan_tx_in_progress) {
+			p2p->after_scan_tx_in_progress = 0;
+			if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING &&
+			    p2p_run_after_scan(p2p))
+				break;
+			if (p2p->state == P2P_SEARCH) {
+				wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+					"P2P: Continue find after "
+					"after_scan_tx completion");
+				p2p_continue_find(p2p);
+			}
+		}
 		break;
 	case P2P_PENDING_GO_NEG_REQUEST:
 		p2p_go_neg_req_cb(p2p, success);
@@ -3202,6 +3213,8 @@
 		p2p_go_disc_req_cb(p2p, success);
 		break;
 	}
+
+	p2p->after_scan_tx_in_progress = 0;
 }
 
 
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index d5ce52f..008f3f0 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -398,6 +398,7 @@
 	} start_after_scan;
 	u8 after_scan_peer[ETH_ALEN];
 	struct p2p_pending_action_tx *after_scan_tx;
+	unsigned int after_scan_tx_in_progress:1;
 
 	/* Requested device types for find/search */
 	unsigned int num_req_dev_types;
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 8ceaf6c..069e22b 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -86,6 +86,7 @@
 
 struct wpa_tdls_peer {
 	struct wpa_tdls_peer *next;
+	unsigned int reconfig_key:1;
 	int initiator; /* whether this end was initiator for TDLS setup */
 	u8 addr[ETH_ALEN]; /* other end MAC address */
 	u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */
@@ -616,6 +617,7 @@
 		   MAC2STR(peer->addr));
 	eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
 	eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
+	peer->reconfig_key = 0;
 	peer->initiator = 0;
 	os_free(peer->sm_tmr.buf);
 	peer->sm_tmr.buf = NULL;
@@ -1751,7 +1753,7 @@
 }
 
 
-static void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
+static int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 {
 	peer->tpk_success = 1;
 	eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
@@ -1775,13 +1777,22 @@
 	}
 
 	/* add supported rates, capabilities, and qos_info to the TDLS peer */
-	wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->capability,
-				peer->supp_rates, peer->supp_rates_len,
-				peer->ht_capabilities, peer->vht_capabilities,
-				peer->qos_info, peer->ext_capab,
-				peer->ext_capab_len);
+	if (wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->capability,
+				    peer->supp_rates, peer->supp_rates_len,
+				    peer->ht_capabilities,
+				    peer->vht_capabilities,
+				    peer->qos_info, peer->ext_capab,
+				    peer->ext_capab_len) < 0)
+		return -1;
 
-	wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
+	if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) {
+		wpa_printf(MSG_INFO, "TDLS: Could not configure key to the "
+			   "driver");
+		return -1;
+	}
+	peer->reconfig_key = 0;
+
+	return wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
 }
 
 
@@ -1800,6 +1811,7 @@
 	int ielen;
 	u16 status;
 	const u8 *pos;
+	int ret;
 
 	wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 "
 		   "(Peer " MACSTR ")", MAC2STR(src_addr));
@@ -1992,7 +2004,15 @@
 		return -1;
 	}
 
-	wpa_tdls_set_key(sm, peer);
+	if (wpa_tdls_set_key(sm, peer) < 0) {
+		/*
+		 * Some drivers may not be able to config the key prior to full
+		 * STA entry having been configured.
+		 */
+		wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after "
+			   "STA entry is complete");
+		peer->reconfig_key = 1;
+	}
 
 skip_rsn:
 	peer->dtoken = dtoken;
@@ -2001,9 +2021,13 @@
 		   "TPK Handshake Message 3");
 	wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer);
 
-	wpa_tdls_enable_link(sm, peer);
-
-	return 0;
+	ret = wpa_tdls_enable_link(sm, peer);
+	if (ret < 0) {
+		wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
+		wpa_tdls_do_teardown(sm, peer,
+				     WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED, 1);
+	}
+	return ret;
 
 error:
 	wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken,
@@ -2026,6 +2050,7 @@
 	u16 status;
 	const u8 *pos;
 	u32 lifetime;
+	int ret;
 
 	wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 "
 		   "(Peer " MACSTR ")", MAC2STR(src_addr));
@@ -2136,13 +2161,24 @@
 		return -1;
 	}
 
-	if (wpa_tdls_set_key(sm, peer) < 0)
-		return -1;
+	if (wpa_tdls_set_key(sm, peer) < 0) {
+		/*
+		 * Some drivers may not be able to config the key prior to full
+		 * STA entry having been configured.
+		 */
+		wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after "
+			   "STA entry is complete");
+		peer->reconfig_key = 1;
+	}
 
 skip_rsn:
-	wpa_tdls_enable_link(sm, peer);
-
-	return 0;
+	ret = wpa_tdls_enable_link(sm, peer);
+	if (ret < 0) {
+		wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
+		wpa_tdls_do_teardown(sm, peer,
+				     WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED, 1);
+	}
+	return ret;
 }