am dc5da6ac: am b73408d1: am fdb708a3: P2P: Validate SSID element length before copying it

* commit 'dc5da6ac19accd8d31dc8977a48d01422b3862f5':
  P2P: Validate SSID element length before copying it
diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog
index 9de9438..f0e4604 100644
--- a/hostapd/ChangeLog
+++ b/hostapd/ChangeLog
@@ -1,5 +1,24 @@
 ChangeLog for hostapd
 
+2014-10-09 - v2.3
+	* fixed number of minor issues identified in static analyzer warnings
+	* fixed DFS and channel switch operation for multi-BSS cases
+	* started to use constant time comparison for various password and hash
+	  values to reduce possibility of any externally measurable timing
+	  differences
+	* extended explicit clearing of freed memory and expired keys to avoid
+	  keeping private data in memory longer than necessary
+	* added support for number of new RADIUS attributes from RFC 7268
+	  (Mobility-Domain-Id, WLAN-HESSID, WLAN-Pairwise-Cipher,
+	  WLAN-Group-Cipher, WLAN-AKM-Suite, WLAN-Group-Mgmt-Pairwise-Cipher)
+	* fixed GET_CONFIG wpa_pairwise_cipher value
+	* added code to clear bridge FDB entry on station disconnection
+	* fixed PMKSA cache timeout from Session-Timeout for WPA/WPA2 cases
+	* fixed OKC PMKSA cache entry fetch to avoid a possible infinite loop
+	  in case the first entry does not match
+	* fixed hostapd_cli action script execution to use more robust mechanism
+	  (CVE-2014-3686)
+
 2014-06-04 - v2.2
 	* fixed SAE confirm-before-commit validation to avoid a potential
 	  segmentation fault in an unexpected message sequence that could be
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 4c0e3f8..44de826 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3178,7 +3178,6 @@
 struct hostapd_config * hostapd_config_read(const char *fname)
 {
 	struct hostapd_config *conf;
-	struct hostapd_bss_config *bss;
 	FILE *f;
 	char buf[512], *pos;
 	int line = 0;
@@ -3207,9 +3206,11 @@
 		return NULL;
 	}
 
-	bss = conf->last_bss = conf->bss[0];
+	conf->last_bss = conf->bss[0];
 
 	while (fgets(buf, sizeof(buf), f)) {
+		struct hostapd_bss_config *bss;
+
 		bss = conf->last_bss;
 		line++;
 
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 9ce7829..591c395 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1010,7 +1010,7 @@
 			return pos - buf;
 		pos += ret;
 
-		ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
+		ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
 					" ");
 		if (ret < 0)
 			return pos - buf;
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 95f28d3..9e62bef 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -835,6 +835,8 @@
 	hostapd_cli_close_connection();
 	os_free(ctrl_ifname);
 	ctrl_ifname = os_strdup(argv[0]);
+	if (ctrl_ifname == NULL)
+		return -1;
 
 	if (hostapd_cli_open_connection(ctrl_ifname)) {
 		printf("Connected to interface '%s.\n", ctrl_ifname);
diff --git a/hostapd/main.c b/hostapd/main.c
index af4d85d..c3af704 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -99,14 +99,15 @@
 	else if (hapd && hapd->conf)
 		os_snprintf(format, maxlen, "%s:%s%s %s",
 			    hapd->conf->iface, module_str ? " " : "",
-			    module_str, txt);
+			    module_str ? module_str : "", txt);
 	else if (addr)
 		os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
 			    MAC2STR(addr), module_str ? " " : "",
-			    module_str, txt);
+			    module_str ? module_str : "", txt);
 	else
 		os_snprintf(format, maxlen, "%s%s%s",
-			    module_str, module_str ? ": " : "", txt);
+			    module_str ? module_str : "",
+			    module_str ? ": " : "", txt);
 
 	if ((conf_stdout & module) && level >= conf_stdout_level) {
 		wpa_debug_print_timestamp();
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index d127550..c7da69e 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -761,7 +761,7 @@
 	    conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
 		bss->disable_11n = 1;
 		wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
-			   "allowed, disabling HT capabilites");
+			   "allowed, disabling HT capabilities");
 	}
 
 	if (full_config && conf->ieee80211n &&
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index b3b6149..4cae0d9 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -113,6 +113,10 @@
 	    hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
 		return eid;
 
+	/* Let host drivers add this IE if DFS support is offloaded */
+	if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
+		return eid;
+
 	/*
 	 * There is no DFS support and power constraint was not directly
 	 * requested by config option.
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 20419f3..a6ec20b 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -18,10 +18,12 @@
 #include "dfs.h"
 
 
-static int dfs_get_used_n_chans(struct hostapd_iface *iface)
+static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
 {
 	int n_chans = 1;
 
+	*seg1 = 0;
+
 	if (iface->conf->ieee80211n && iface->conf->secondary_channel)
 		n_chans = 2;
 
@@ -35,6 +37,10 @@
 		case VHT_CHANWIDTH_160MHZ:
 			n_chans = 8;
 			break;
+		case VHT_CHANWIDTH_80P80MHZ:
+			n_chans = 4;
+			*seg1 = 4;
+			break;
 		default:
 			break;
 		}
@@ -170,10 +176,10 @@
 {
 	struct hostapd_hw_modes *mode;
 	struct hostapd_channel_data *chan;
-	int i, channel_idx = 0, n_chans;
+	int i, channel_idx = 0, n_chans, n_chans1;
 
 	mode = iface->current_mode;
-	n_chans = dfs_get_used_n_chans(iface);
+	n_chans = dfs_get_used_n_chans(iface, &n_chans1);
 
 	wpa_printf(MSG_DEBUG, "DFS new chan checking %d channels", n_chans);
 	for (i = 0; i < mode->num_channels; i++) {
@@ -246,12 +252,15 @@
 
 
 /* Return start channel idx we will use for mode->channels[idx] */
-static int dfs_get_start_chan_idx(struct hostapd_iface *iface)
+static int dfs_get_start_chan_idx(struct hostapd_iface *iface, int *seg1_start)
 {
 	struct hostapd_hw_modes *mode;
 	struct hostapd_channel_data *chan;
 	int channel_no = iface->conf->channel;
 	int res = -1, i;
+	int chan_seg1 = -1;
+
+	*seg1_start = -1;
 
 	/* HT40- */
 	if (iface->conf->ieee80211n && iface->conf->secondary_channel == -1)
@@ -270,9 +279,15 @@
 			channel_no =
 				iface->conf->vht_oper_centr_freq_seg0_idx - 14;
 			break;
+		case VHT_CHANWIDTH_80P80MHZ:
+			channel_no =
+				iface->conf->vht_oper_centr_freq_seg0_idx - 6;
+			chan_seg1 =
+				iface->conf->vht_oper_centr_freq_seg1_idx - 6;
+			break;
 		default:
 			wpa_printf(MSG_INFO,
-				   "DFS only VHT20/40/80/160 is supported now");
+				   "DFS only VHT20/40/80/160/80+80 is supported now");
 			channel_no = -1;
 			break;
 		}
@@ -288,6 +303,23 @@
 		}
 	}
 
+	if (res != -1 && chan_seg1 > -1) {
+		int found = 0;
+
+		/* Get idx for seg1 */
+		mode = iface->current_mode;
+		for (i = 0; i < mode->num_channels; i++) {
+			chan = &mode->channels[i];
+			if (chan->chan == chan_seg1) {
+				*seg1_start = i;
+				found = 1;
+				break;
+			}
+		}
+		if (!found)
+			res = -1;
+	}
+
 	if (res == -1) {
 		wpa_printf(MSG_DEBUG,
 			   "DFS chan_idx seems wrong; num-ch: %d ch-no: %d conf-ch-no: %d 11n: %d sec-ch: %d vht-oper-width: %d",
@@ -511,17 +543,17 @@
 static int dfs_are_channels_overlapped(struct hostapd_iface *iface, int freq,
 				       int chan_width, int cf1, int cf2)
 {
-	int start_chan_idx;
+	int start_chan_idx, start_chan_idx1;
 	struct hostapd_hw_modes *mode;
 	struct hostapd_channel_data *chan;
-	int n_chans, i, j, frequency = freq, radar_n_chans = 1;
+	int n_chans, n_chans1, i, j, frequency = freq, radar_n_chans = 1;
 	u8 radar_chan;
 	int res = 0;
 
 	/* Our configuration */
 	mode = iface->current_mode;
-	start_chan_idx = dfs_get_start_chan_idx(iface);
-	n_chans = dfs_get_used_n_chans(iface);
+	start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1);
+	n_chans = dfs_get_used_n_chans(iface, &n_chans1);
 
 	/* Check we are on DFS channel(s) */
 	if (!dfs_check_chans_radar(iface, start_chan_idx, n_chans))
@@ -604,19 +636,20 @@
 int hostapd_handle_dfs(struct hostapd_iface *iface)
 {
 	struct hostapd_channel_data *channel;
-	int res, n_chans, start_chan_idx;
+	int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1;
 	int skip_radar = 0;
 
 	iface->cac_started = 0;
 
 	do {
 		/* Get start (first) channel for current configuration */
-		start_chan_idx = dfs_get_start_chan_idx(iface);
+		start_chan_idx = dfs_get_start_chan_idx(iface,
+							&start_chan_idx1);
 		if (start_chan_idx == -1)
 			return -1;
 
 		/* Get number of used channels, depend on width */
-		n_chans = dfs_get_used_n_chans(iface);
+		n_chans = dfs_get_used_n_chans(iface, &n_chans1);
 
 		/* Setup CAC time */
 		iface->dfs_cac_ms = dfs_get_cac_time(iface, start_chan_idx,
@@ -928,20 +961,25 @@
 
 int hostapd_is_dfs_required(struct hostapd_iface *iface)
 {
-	int n_chans, start_chan_idx;
+	int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res;
 
 	if (!iface->conf->ieee80211h || !iface->current_mode ||
 	    iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
 		return 0;
 
 	/* Get start (first) channel for current configuration */
-	start_chan_idx = dfs_get_start_chan_idx(iface);
+	start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1);
 	if (start_chan_idx == -1)
 		return -1;
 
 	/* Get number of used channels, depend on width */
-	n_chans = dfs_get_used_n_chans(iface);
+	n_chans = dfs_get_used_n_chans(iface, &n_chans1);
 
 	/* Check if any of configured channels require DFS */
-	return dfs_check_chans_radar(iface, start_chan_idx, n_chans);
+	res = dfs_check_chans_radar(iface, start_chan_idx, n_chans);
+	if (res)
+		return res;
+	if (start_chan_idx1 >= 0 && n_chans1 > 0)
+		res = dfs_check_chans_radar(iface, start_chan_idx1, n_chans1);
+	return res;
 }
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 93804de..3bde720 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -340,6 +340,9 @@
 					sta->auth_alg, req_ies, req_ies_len);
 
 	hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
+
+	if (sta->auth_alg == WLAN_AUTH_FT)
+		ap_sta_set_authorized(hapd, sta, 1);
 #else /* CONFIG_IEEE80211R */
 	/* Keep compiler silent about unused variables */
 	if (status) {
@@ -350,6 +353,8 @@
 	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
 	sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
 
+	hostapd_set_sta_flags(hapd, sta);
+
 	if (reassoc && (sta->auth_alg == WLAN_AUTH_FT))
 		wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
 	else
@@ -1044,6 +1049,8 @@
 				       data->eapol_rx.data_len);
 		break;
 	case EVENT_ASSOC:
+		if (!data)
+			return;
 		hostapd_notif_assoc(hapd, data->assoc_info.addr,
 				    data->assoc_info.req_ies,
 				    data->assoc_info.req_ies_len,
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 26aca2b..3142391 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -693,10 +693,10 @@
 	u8 if_addr[ETH_ALEN];
 
 	wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s), first=%d)",
-		   __func__, hapd, hapd->conf->iface, first);
+		   __func__, hapd, conf->iface, first);
 
 #ifdef EAP_SERVER_TNC
-	if (hapd->conf->tnc && tncs_global_init() < 0) {
+	if (conf->tnc && tncs_global_init() < 0) {
 		wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
 		return -1;
 	}
@@ -704,37 +704,37 @@
 
 	if (hapd->started) {
 		wpa_printf(MSG_ERROR, "%s: Interface %s was already started",
-			   __func__, hapd->conf->iface);
+			   __func__, conf->iface);
 		return -1;
 	}
 	hapd->started = 1;
 
 	if (!first || first == -1) {
-		if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
+		if (hostapd_mac_comp_empty(conf->bssid) == 0) {
 			/* Allocate the next available BSSID. */
 			do {
 				inc_byte_array(hapd->own_addr, ETH_ALEN);
 			} while (mac_in_conf(hapd->iconf, hapd->own_addr));
 		} else {
 			/* Allocate the configured BSSID. */
-			os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN);
+			os_memcpy(hapd->own_addr, conf->bssid, ETH_ALEN);
 
 			if (hostapd_mac_comp(hapd->own_addr,
 					     hapd->iface->bss[0]->own_addr) ==
 			    0) {
 				wpa_printf(MSG_ERROR, "BSS '%s' may not have "
 					   "BSSID set to the MAC address of "
-					   "the radio", hapd->conf->iface);
+					   "the radio", conf->iface);
 				return -1;
 			}
 		}
 
 		hapd->interface_added = 1;
 		if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
-				   hapd->conf->iface, hapd->own_addr, hapd,
+				   conf->iface, hapd->own_addr, hapd,
 				   &hapd->drv_priv, force_ifname, if_addr,
-				   hapd->conf->bridge[0] ? hapd->conf->bridge :
-				   NULL, first == -1)) {
+				   conf->bridge[0] ? conf->bridge : NULL,
+				   first == -1)) {
 			wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
 				   MACSTR ")", MAC2STR(hapd->own_addr));
 			hapd->interface_added = 0;
@@ -749,7 +749,7 @@
 	hostapd_set_privacy(hapd, 0);
 
 	hostapd_broadcast_wep_clear(hapd);
-	if (hostapd_setup_encryption(hapd->conf->iface, hapd))
+	if (hostapd_setup_encryption(conf->iface, hapd))
 		return -1;
 
 	/*
@@ -783,9 +783,8 @@
 	if (!hostapd_drv_none(hapd)) {
 		wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
 			   " and ssid \"%s\"",
-			   hapd->conf->iface, MAC2STR(hapd->own_addr),
-			   wpa_ssid_txt(hapd->conf->ssid.ssid,
-					hapd->conf->ssid.ssid_len));
+			   conf->iface, MAC2STR(hapd->own_addr),
+			   wpa_ssid_txt(conf->ssid.ssid, conf->ssid.ssid_len));
 	}
 
 	if (hostapd_setup_wpa_psk(conf)) {
@@ -810,17 +809,17 @@
 		return -1;
 	}
 
-	if (hapd->conf->radius_das_port) {
+	if (conf->radius_das_port) {
 		struct radius_das_conf das_conf;
 		os_memset(&das_conf, 0, sizeof(das_conf));
-		das_conf.port = hapd->conf->radius_das_port;
-		das_conf.shared_secret = hapd->conf->radius_das_shared_secret;
+		das_conf.port = conf->radius_das_port;
+		das_conf.shared_secret = conf->radius_das_shared_secret;
 		das_conf.shared_secret_len =
-			hapd->conf->radius_das_shared_secret_len;
-		das_conf.client_addr = &hapd->conf->radius_das_client_addr;
-		das_conf.time_window = hapd->conf->radius_das_time_window;
+			conf->radius_das_shared_secret_len;
+		das_conf.client_addr = &conf->radius_das_client_addr;
+		das_conf.time_window = conf->radius_das_time_window;
 		das_conf.require_event_timestamp =
-			hapd->conf->radius_das_require_event_timestamp;
+			conf->radius_das_require_event_timestamp;
 		das_conf.ctx = hapd;
 		das_conf.disconnect = hostapd_das_disconnect;
 		hapd->radius_das = radius_das_init(&das_conf);
@@ -847,7 +846,7 @@
 		return -1;
 	}
 
-	if ((hapd->conf->wpa || hapd->conf->osen) && hostapd_setup_wpa(hapd))
+	if ((conf->wpa || conf->osen) && hostapd_setup_wpa(hapd))
 		return -1;
 
 	if (accounting_init(hapd)) {
@@ -855,8 +854,8 @@
 		return -1;
 	}
 
-	if (hapd->conf->ieee802_11f &&
-	    (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) {
+	if (conf->ieee802_11f &&
+	    (hapd->iapp = iapp_init(hapd, conf->iapp_iface)) == NULL) {
 		wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
 			   "failed.");
 		return -1;
@@ -881,7 +880,7 @@
 		return -1;
 	}
 
-	if (!hapd->conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
 		return -1;
 
 	if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
@@ -1182,12 +1181,15 @@
 			   iface->conf->channel, iface->freq);
 
 #ifdef NEED_AP_MLME
-		/* Check DFS */
-		res = hostapd_handle_dfs(iface);
-		if (res <= 0) {
-			if (res < 0)
-				goto fail;
-			return res;
+		/* Handle DFS only if it is not offloaded to the driver */
+		if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) {
+			/* Check DFS */
+			res = hostapd_handle_dfs(iface);
+			if (res <= 0) {
+				if (res < 0)
+					goto fail;
+				return res;
+			}
 		}
 #endif /* NEED_AP_MLME */
 
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index e4681e9..2d09b67 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -1622,6 +1622,9 @@
 		if (ap_sta_bind_vlan(hapd, sta, old_vlanid) < 0)
 			break;
 
+		sta->session_timeout_set = !!session_timeout_set;
+		sta->session_timeout = session_timeout;
+
 		/* RFC 3580, Ch. 3.17 */
 		if (session_timeout_set && termination_action ==
 		    RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) {
@@ -2396,6 +2399,7 @@
 	size_t len;
 	/* TODO: get PMKLifetime from WPA parameters */
 	static const int dot11RSNAConfigPMKLifetime = 43200;
+	unsigned int session_timeout;
 
 #ifdef CONFIG_HS20
 	if (remediation && !sta->remediation) {
@@ -2430,9 +2434,13 @@
 #endif /* CONFIG_HS20 */
 
 	key = ieee802_1x_get_key(sta->eapol_sm, &len);
+	if (sta->session_timeout_set)
+		session_timeout = sta->session_timeout;
+	else
+		session_timeout = dot11RSNAConfigPMKLifetime;
 	if (success && key && len >= PMK_LEN && !sta->remediation &&
 	    !sta->hs20_deauth_requested &&
-	    wpa_auth_pmksa_add(sta->wpa_sm, key, dot11RSNAConfigPMKLifetime,
+	    wpa_auth_pmksa_add(sta->wpa_sm, key, session_timeout,
 			       sta->eapol_sm) == 0) {
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
 			       HOSTAPD_LEVEL_DEBUG,
diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c
index 4720b59..9de4cff 100644
--- a/src/ap/pmksa_cache_auth.c
+++ b/src/ap/pmksa_cache_auth.c
@@ -37,14 +37,12 @@
 
 static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
 {
-	if (entry == NULL)
-		return;
 	os_free(entry->identity);
 	wpabuf_free(entry->cui);
 #ifndef CONFIG_NO_RADIUS
 	radius_free_class(&entry->radius_class);
 #endif /* CONFIG_NO_RADIUS */
-	os_free(entry);
+	bin_clear_free(entry, sizeof(*entry));
 }
 
 
@@ -52,38 +50,42 @@
 			    struct rsn_pmksa_cache_entry *entry)
 {
 	struct rsn_pmksa_cache_entry *pos, *prev;
+	unsigned int hash;
 
 	pmksa->pmksa_count--;
 	pmksa->free_cb(entry, pmksa->ctx);
-	pos = pmksa->pmkid[PMKID_HASH(entry->pmkid)];
+
+	/* unlink from hash list */
+	hash = PMKID_HASH(entry->pmkid);
+	pos = pmksa->pmkid[hash];
 	prev = NULL;
 	while (pos) {
 		if (pos == entry) {
-			if (prev != NULL) {
-				prev->hnext = pos->hnext;
-			} else {
-				pmksa->pmkid[PMKID_HASH(entry->pmkid)] =
-					pos->hnext;
-			}
+			if (prev != NULL)
+				prev->hnext = entry->hnext;
+			else
+				pmksa->pmkid[hash] = entry->hnext;
 			break;
 		}
 		prev = pos;
 		pos = pos->hnext;
 	}
 
+	/* unlink from entry list */
 	pos = pmksa->pmksa;
 	prev = NULL;
 	while (pos) {
 		if (pos == entry) {
 			if (prev != NULL)
-				prev->next = pos->next;
+				prev->next = entry->next;
 			else
-				pmksa->pmksa = pos->next;
+				pmksa->pmksa = entry->next;
 			break;
 		}
 		prev = pos;
 		pos = pos->next;
 	}
+
 	_pmksa_cache_free_entry(entry);
 }
 
@@ -188,6 +190,7 @@
 				   struct rsn_pmksa_cache_entry *entry)
 {
 	struct rsn_pmksa_cache_entry *pos, *prev;
+	int hash;
 
 	/* Add the new entry; order by expiration time */
 	pos = pmksa->pmksa;
@@ -205,8 +208,10 @@
 		entry->next = prev->next;
 		prev->next = entry;
 	}
-	entry->hnext = pmksa->pmkid[PMKID_HASH(entry->pmkid)];
-	pmksa->pmkid[PMKID_HASH(entry->pmkid)] = entry;
+
+	hash = PMKID_HASH(entry->pmkid);
+	entry->hnext = pmksa->pmkid[hash];
+	pmksa->pmkid[hash] = entry;
 
 	pmksa->pmksa_count++;
 	if (prev == NULL)
@@ -342,6 +347,8 @@
 		_pmksa_cache_free_entry(prev);
 	}
 	eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
+	pmksa->pmksa_count = 0;
+	pmksa->pmksa = NULL;
 	for (i = 0; i < PMKID_HASH_SIZE; i++)
 		pmksa->pmkid[i] = NULL;
 	os_free(pmksa);
@@ -361,18 +368,22 @@
 {
 	struct rsn_pmksa_cache_entry *entry;
 
-	if (pmkid)
-		entry = pmksa->pmkid[PMKID_HASH(pmkid)];
-	else
-		entry = pmksa->pmksa;
-	while (entry) {
-		if ((spa == NULL ||
-		     os_memcmp(entry->spa, spa, ETH_ALEN) == 0) &&
-		    (pmkid == NULL ||
-		     os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0))
-			return entry;
-		entry = pmkid ? entry->hnext : entry->next;
+	if (pmkid) {
+		for (entry = pmksa->pmkid[PMKID_HASH(pmkid)]; entry;
+		     entry = entry->hnext) {
+			if ((spa == NULL ||
+			     os_memcmp(entry->spa, spa, ETH_ALEN) == 0) &&
+			    os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)
+				return entry;
+		}
+	} else {
+		for (entry = pmksa->pmksa; entry; entry = entry->next) {
+			if (spa == NULL ||
+			    os_memcmp(entry->spa, spa, ETH_ALEN) == 0)
+				return entry;
+		}
 	}
+
 	return NULL;
 }
 
@@ -394,15 +405,13 @@
 	struct rsn_pmksa_cache_entry *entry;
 	u8 new_pmkid[PMKID_LEN];
 
-	entry = pmksa->pmksa;
-	while (entry) {
+	for (entry = pmksa->pmksa; entry; entry = entry->next) {
 		if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
 			continue;
 		rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid,
 			  wpa_key_mgmt_sha256(entry->akmp));
 		if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0)
 			return entry;
-		entry = entry->next;
 	}
 	return NULL;
 }
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 60f0768..efd2a72 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -956,12 +956,12 @@
 			dev_addr = addr;
 	} else
 		dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
-#endif /* CONFIG_P2P */
 
 	if (dev_addr)
 		os_snprintf(buf, sizeof(buf), MACSTR " p2p_dev_addr=" MACSTR,
 			    MAC2STR(sta->addr), MAC2STR(dev_addr));
 	else
+#endif /* CONFIG_P2P */
 		os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
 
 	if (authorized) {
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 03db98f..faf32d8 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -60,6 +60,7 @@
 	unsigned int qos_map_enabled:1;
 	unsigned int remediation:1;
 	unsigned int hs20_deauth_requested:1;
+	unsigned int session_timeout_set:1;
 
 	u16 auth_alg;
 
@@ -135,6 +136,8 @@
 #ifdef CONFIG_SAE
 	struct sae_data *sae;
 #endif /* CONFIG_SAE */
+
+	u32 session_timeout; /* valid only if session_timeout_set == 1 */
 };
 
 
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 2bb8aab..1a16b5c 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -1390,7 +1390,8 @@
 		if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
 		    sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
 		    version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
-			if (aes_wrap(sm->PTK.kek, (key_data_len - 8) / 8, buf,
+			if (aes_wrap(sm->PTK.kek, 16,
+				     (key_data_len - 8) / 8, buf,
 				     (u8 *) (key + 1))) {
 				os_free(hdr);
 				os_free(buf);
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 8a6ca71..781f15f 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -344,7 +344,8 @@
 	os_memcpy(f.s1kh_id, sm->addr, ETH_ALEN);
 	os_memset(f.pad, 0, sizeof(f.pad));
 
-	if (aes_wrap(r0kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
+	if (aes_wrap(r0kh->key, sizeof(r0kh->key),
+		     (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
 		     f.nonce, frame.nonce) < 0)
 		return -1;
 
@@ -459,7 +460,7 @@
 	WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03);
 	subelem[4] = gsm->GTK_len;
 	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5);
-	if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 13)) {
+	if (aes_wrap(sm->PTK.kek, 16, key_len / 8, key, subelem + 13)) {
 		os_free(subelem);
 		return NULL;
 	}
@@ -491,7 +492,7 @@
 	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos);
 	pos += 6;
 	*pos++ = WPA_IGTK_LEN;
-	if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8,
+	if (aes_wrap(sm->PTK.kek, 16, WPA_IGTK_LEN / 8,
 		     gsm->IGTK[gsm->GN_igtk - 4], pos)) {
 		os_free(subelem);
 		return NULL;
@@ -1336,7 +1337,8 @@
 	frame = (struct ft_r0kh_r1kh_pull_frame *) data;
 	/* aes_unwrap() does not support inplace decryption, so use a temporary
 	 * buffer for the data. */
-	if (aes_unwrap(r1kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
+	if (aes_unwrap(r1kh->key, sizeof(r1kh->key),
+		       (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
 		       frame->nonce, f.nonce) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
 			   "request from " MACSTR, MAC2STR(src_addr));
@@ -1376,7 +1378,8 @@
 	r.pairwise = host_to_le16(pairwise);
 	os_memset(r.pad, 0, sizeof(r.pad));
 
-	if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
+	if (aes_wrap(r1kh->key, sizeof(r1kh->key),
+		     (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
 		     r.nonce, resp.nonce) < 0) {
 		os_memset(pmk_r0, 0, PMK_LEN);
 		return -1;
@@ -1464,7 +1467,8 @@
 	frame = (struct ft_r0kh_r1kh_resp_frame *) data;
 	/* aes_unwrap() does not support inplace decryption, so use a temporary
 	 * buffer for the data. */
-	if (aes_unwrap(r0kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
+	if (aes_unwrap(r0kh->key, sizeof(r0kh->key),
+		       (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
 		       frame->nonce, f.nonce) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
 			   "response from " MACSTR, MAC2STR(src_addr));
@@ -1530,7 +1534,8 @@
 	frame = (struct ft_r0kh_r1kh_push_frame *) data;
 	/* aes_unwrap() does not support inplace decryption, so use a temporary
 	 * buffer for the data. */
-	if (aes_unwrap(r0kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
+	if (aes_unwrap(r0kh->key, sizeof(r0kh->key),
+		       (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
 		       frame->timestamp, f.timestamp) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 push from "
 			   MACSTR, MAC2STR(src_addr));
@@ -1727,7 +1732,8 @@
 	WPA_PUT_LE32(f.timestamp, now.sec);
 	f.pairwise = host_to_le16(pairwise);
 	os_memset(f.pad, 0, sizeof(f.pad));
-	if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
+	if (aes_wrap(r1kh->key, sizeof(r1kh->key),
+		     (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
 		     f.timestamp, frame.timestamp) < 0)
 		return;
 
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index 4d9efd5..ad3bdfd 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -32,6 +32,13 @@
  *
  * @QCA_NL80211_VENDOR_SUBCMD_TEST: Test command/event
  *
+ * @QCA_NL80211_VENDOR_SUBCMD_ROAMING: Set roaming policy for drivers that use
+ *	internal BSS-selection. This command uses
+ *	@QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY to specify the new roaming policy
+ *	for the current connection (i.e., changes policy set by the nl80211
+ *	Connect command). @QCA_WLAN_VENDOR_ATTR_MAC_ADDR may optionally be
+ *	included to indicate which BSS to use in case roaming is disabled.
+ *
  * @QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY: Recommendation of frequency
  *	ranges to avoid to reduce issues due to interference or internal
  *	co-existence information in the driver. The event data structure is
@@ -47,12 +54,13 @@
 enum qca_nl80211_vendor_subcmds {
 	QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
 	QCA_NL80211_VENDOR_SUBCMD_TEST = 1,
-	/* subcmds 2..9 not yet allocated */
+	/* subcmds 2..8 not yet allocated */
+	QCA_NL80211_VENDOR_SUBCMD_ROAMING = 9,
 	QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY = 10,
 	QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY =  11,
 	QCA_NL80211_VENDOR_SUBCMD_NAN =  12,
 	QCA_NL80211_VENDOR_SUBMCD_STATS_EXT = 13,
-	/* 14..33 - reserved for QCA */
+	/* 14..49 - reserved for QCA */
 };
 
 
@@ -66,9 +74,19 @@
 	QCA_WLAN_VENDOR_ATTR_STATS_EXT     = 3,
 	/* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */
 	QCA_WLAN_VENDOR_ATTR_IFINDEX     = 4,
+	/* used by QCA_NL80211_VENDOR_SUBCMD_ROAMING, u32 with values defined
+	 * by enum qca_roaming_policy. */
+	QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY = 5,
+	QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6,
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_MAX	= QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
 };
 
+
+enum qca_roaming_policy {
+	QCA_ROAMING_NOT_ALLOWED,
+	QCA_ROAMING_ALLOWED_WITHIN_ESS,
+};
+
 #endif /* QCA_VENDOR_H */
diff --git a/src/common/version.h b/src/common/version.h
index 1f25432..726289d 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -5,6 +5,6 @@
 #define VERSION_STR_POSTFIX ""
 #endif /* VERSION_STR_POSTFIX */
 
-#define VERSION_STR "2.3-devel" VERSION_STR_POSTFIX
+#define VERSION_STR "2.3" VERSION_STR_POSTFIX
 
 #endif /* VERSION_H */
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index d91594e..4812f8d 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -345,9 +345,10 @@
  * @reply_len: Length of the reply buffer
  * Returns: 0 on success, -1 on failure
  *
- * This function will receive a pending control interface message. This
- * function will block if no messages are available. The received response will
- * be written to reply and reply_len is set to the actual length of the reply.
+ * This function will receive a pending control interface message. The received
+ * response will be written to reply and reply_len is set to the actual length
+ * of the reply.
+
  * wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach()
  * must have been used to register the control interface as an event monitor.
  */
diff --git a/src/crypto/aes-unwrap.c b/src/crypto/aes-unwrap.c
index 9dd5160..ec793d9 100644
--- a/src/crypto/aes-unwrap.c
+++ b/src/crypto/aes-unwrap.c
@@ -1,5 +1,5 @@
 /*
- * AES key unwrap (128-bit KEK, RFC3394)
+ * AES key unwrap (RFC3394)
  *
  * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
  *
@@ -14,26 +14,29 @@
 #include "aes_wrap.h"
 
 /**
- * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (RFC3394)
  * @kek: Key encryption key (KEK)
+ * @kek_len: Length of KEK in octets
  * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
  * bytes
  * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits
  * @plain: Plaintext key, n * 64 bits
  * Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
  */
-int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
+int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
+	       u8 *plain)
 {
-	u8 a[8], *r, b[16];
+	u8 a[8], *r, b[AES_BLOCK_SIZE];
 	int i, j;
 	void *ctx;
+	unsigned int t;
 
 	/* 1) Initialize variables. */
 	os_memcpy(a, cipher, 8);
 	r = plain;
 	os_memcpy(r, cipher + 8, 8 * n);
 
-	ctx = aes_decrypt_init(kek, 16);
+	ctx = aes_decrypt_init(kek, kek_len);
 	if (ctx == NULL)
 		return -1;
 
@@ -48,7 +51,11 @@
 		r = plain + (n - 1) * 8;
 		for (i = n; i >= 1; i--) {
 			os_memcpy(b, a, 8);
-			b[7] ^= n * j + i;
+			t = n * j + i;
+			b[7] ^= t;
+			b[6] ^= t >> 8;
+			b[5] ^= t >> 16;
+			b[4] ^= t >> 24;
 
 			os_memcpy(b + 8, r, 8);
 			aes_decrypt(ctx, b, b);
diff --git a/src/crypto/aes-wrap.c b/src/crypto/aes-wrap.c
index 89d6f94..7ed34e8 100644
--- a/src/crypto/aes-wrap.c
+++ b/src/crypto/aes-wrap.c
@@ -1,5 +1,5 @@
 /*
- * AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * AES Key Wrap Algorithm (RFC3394)
  *
  * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
  *
@@ -14,19 +14,21 @@
 #include "aes_wrap.h"
 
 /**
- * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
- * @kek: 16-octet Key encryption key (KEK)
+ * aes_wrap - Wrap keys with AES Key Wrap Algorithm (RFC3394)
+ * @kek: Key encryption key (KEK)
+ * @kek_len: Length of KEK in octets
  * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
  * bytes
  * @plain: Plaintext key to be wrapped, n * 64 bits
  * @cipher: Wrapped key, (n + 1) * 64 bits
  * Returns: 0 on success, -1 on failure
  */
-int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
+int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
 {
-	u8 *a, *r, b[16];
+	u8 *a, *r, b[AES_BLOCK_SIZE];
 	int i, j;
 	void *ctx;
+	unsigned int t;
 
 	a = cipher;
 	r = cipher + 8;
@@ -35,7 +37,7 @@
 	os_memset(a, 0xa6, 8);
 	os_memcpy(r, plain, 8 * n);
 
-	ctx = aes_encrypt_init(kek, 16);
+	ctx = aes_encrypt_init(kek, kek_len);
 	if (ctx == NULL)
 		return -1;
 
@@ -53,7 +55,11 @@
 			os_memcpy(b + 8, r, 8);
 			aes_encrypt(ctx, b, b);
 			os_memcpy(a, b, 8);
-			a[7] ^= n * j + i;
+			t = n * j + i;
+			a[7] ^= t;
+			a[6] ^= t >> 8;
+			a[5] ^= t >> 16;
+			a[4] ^= t >> 24;
 			os_memcpy(r, b + 8, 8);
 			r += 8;
 		}
diff --git a/src/crypto/aes_wrap.h b/src/crypto/aes_wrap.h
index 0433c04..6b3727c 100644
--- a/src/crypto/aes_wrap.h
+++ b/src/crypto/aes_wrap.h
@@ -1,7 +1,7 @@
 /*
  * AES-based functions
  *
- * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * - AES Key Wrap Algorithm (RFC3394)
  * - One-Key CBC MAC (OMAC1) hash with AES-128
  * - AES-128 CTR mode encryption
  * - AES-128 EAX mode encryption/decryption
@@ -18,8 +18,10 @@
 #ifndef AES_WRAP_H
 #define AES_WRAP_H
 
-int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher);
-int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain);
+int __must_check aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain,
+			  u8 *cipher);
+int __must_check aes_unwrap(const u8 *kek, size_t kek_len, int n,
+			    const u8 *cipher, u8 *plain);
 int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem,
 				      const u8 *addr[], const size_t *len,
 				      u8 *mac);
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index f02aaac..b4c59d1 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -40,7 +40,7 @@
 
 static BIGNUM * get_group5_prime(void)
 {
-#if OPENSSL_VERSION_NUMBER < 0x00908000
+#if OPENSSL_VERSION_NUMBER < 0x00908000 || defined(OPENSSL_IS_BORINGSSL)
 	static const unsigned char RFC3526_PRIME_1536[] = {
 		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
 		0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
@@ -130,7 +130,7 @@
 	}
 	pkey[i] = next | 1;
 
-	DES_set_key(&pkey, &ks);
+	DES_set_key((DES_cblock *) &pkey, &ks);
 	DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks,
 			DES_ENCRYPT);
 }
@@ -199,8 +199,10 @@
 	switch (keylen) {
 	case 16:
 		return EVP_aes_128_ecb();
+#ifndef OPENSSL_IS_BORINGSSL
 	case 24:
 		return EVP_aes_192_ecb();
+#endif /* OPENSSL_IS_BORINGSSL */
 	case 32:
 		return EVP_aes_256_ecb();
 	}
@@ -378,9 +380,11 @@
 		case 16:
 			cipher = EVP_aes_128_cbc();
 			break;
+#ifndef OPENSSL_IS_BORINGSSL
 		case 24:
 			cipher = EVP_aes_192_cbc();
 			break;
+#endif /* OPENSSL_IS_BORINGSSL */
 		case 32:
 			cipher = EVP_aes_256_cbc();
 			break;
@@ -1067,6 +1071,7 @@
 	if (e == NULL)
 		return;
 	BN_clear_free(e->order);
+	BN_clear_free(e->prime);
 	EC_GROUP_free(e->group);
 	BN_CTX_free(e->bnctx);
 	os_free(e);
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index d2d6600..e153422 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -38,14 +38,26 @@
 #define OPENSSL_SUPPORTS_CTX_APP_DATA
 #endif
 
-#ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT
-#ifdef SSL_OP_NO_TICKET
+#if OPENSSL_VERSION_NUMBER < 0x10000000L
+/* ERR_remove_thread_state replaces ERR_remove_state and the latter is
+ * deprecated. However, OpenSSL 0.9.8 doesn't include
+ * ERR_remove_thread_state. */
+#define ERR_remove_thread_state(tid) ERR_remove_state(0)
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
 /*
  * Session ticket override patch was merged into OpenSSL 0.9.9 tree on
  * 2008-11-15. This version uses a bit different API compared to the old patch.
  */
 #define CONFIG_OPENSSL_TICKET_OVERRIDE
 #endif
+
+#if defined(OPENSSL_IS_BORINGSSL)
+/* stack_index_t is the return type of OpenSSL's sk_XXX_num() functions. */
+typedef size_t stack_index_t;
+#else
+typedef int stack_index_t;
 #endif
 
 #ifdef SSL_set_tlsext_status_type
@@ -853,7 +865,7 @@
 		ENGINE_cleanup();
 #endif /* OPENSSL_NO_ENGINE */
 		CRYPTO_cleanup_all_ex_data();
-		ERR_remove_state(0);
+		ERR_remove_thread_state(NULL);
 		ERR_free_strings();
 		EVP_cleanup();
 		os_free(tls_global->ocsp_stapling_response);
@@ -1102,7 +1114,8 @@
 {
 	GENERAL_NAME *gen;
 	void *ext;
-	int i, found = 0;
+	int found = 0;
+	stack_index_t i;
 
 	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
 
@@ -1204,6 +1217,7 @@
 	GENERAL_NAME *gen;
 	void *ext;
 	int i;
+	stack_index_t j;
 	int dns_name = 0;
 	X509_NAME *name;
 
@@ -1211,8 +1225,8 @@
 
 	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
 
-	for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
-		gen = sk_GENERAL_NAME_value(ext, i);
+	for (j = 0; ext && j < sk_GENERAL_NAME_num(ext); j++) {
+		gen = sk_GENERAL_NAME_value(ext, j);
 		if (gen->type != GEN_DNS)
 			continue;
 		dns_name++;
@@ -1639,7 +1653,7 @@
 	if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
 		BIO *bio = BIO_from_keystore(&ca_cert[11]);
 		STACK_OF(X509_INFO) *stack = NULL;
-		int i;
+		stack_index_t i;
 
 		if (bio) {
 			stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
@@ -3386,9 +3400,15 @@
  * commented out unless explicitly needed for EAP-FAST in order to be able to
  * build this file with unmodified openssl. */
 
+#ifdef OPENSSL_IS_BORINGSSL
+static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
+			   STACK_OF(SSL_CIPHER) *peer_ciphers,
+			   const SSL_CIPHER **cipher, void *arg)
+#else /* OPENSSL_IS_BORINGSSL */
 static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
 			   STACK_OF(SSL_CIPHER) *peer_ciphers,
 			   SSL_CIPHER **cipher, void *arg)
+#endif /* OPENSSL_IS_BORINGSSL */
 {
 	struct tls_connection *conn = arg;
 	int ret;
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 352c163..6af7294 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -411,6 +411,25 @@
 			  */
 };
 
+struct hostapd_freq_params {
+	int mode;
+	int freq;
+	int channel;
+	/* for HT */
+	int ht_enabled;
+	int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled,
+				 * secondary channel below primary, 1 = HT40
+				 * enabled, secondary channel above primary */
+
+	/* for VHT */
+	int vht_enabled;
+
+	/* valid for both HT and VHT, center_freq2 is non-zero
+	 * only for bandwidth 80 and an 80+80 channel */
+	int center_freq1, center_freq2;
+	int bandwidth;
+};
+
 /**
  * struct wpa_driver_associate_params - Association parameters
  * Data for struct wpa_driver_ops::associate().
@@ -443,11 +462,9 @@
 	size_t ssid_len;
 
 	/**
-	 * freq - Frequency of the channel the selected AP is using
-	 * Frequency that the selected AP is using (in MHz as
-	 * reported in the scan results)
+	 * freq - channel parameters
 	 */
-	int freq;
+	struct hostapd_freq_params freq;
 
 	/**
 	 * freq_hint - Frequency of the channel the proposed AP is using
@@ -1091,25 +1108,6 @@
 	size_t supp_oper_classes_len;
 };
 
-struct hostapd_freq_params {
-	int mode;
-	int freq;
-	int channel;
-	/* for HT */
-	int ht_enabled;
-	int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled,
-				 * secondary channel below primary, 1 = HT40
-				 * enabled, secondary channel above primary */
-
-	/* for VHT */
-	int vht_enabled;
-
-	/* valid for both HT and VHT, center_freq2 is non-zero
-	 * only for bandwidth 80 and an 80+80 channel */
-	int center_freq1, center_freq2;
-	int bandwidth;
-};
-
 struct mac_address {
 	u8 addr[ETH_ALEN];
 };
@@ -2503,6 +2501,7 @@
 	 * @dialog_token: Dialog Token to use in the message (if needed)
 	 * @status_code: Status Code or Reason Code to use (if needed)
 	 * @peer_capab: TDLS peer capability (TDLS_PEER_* bitfield)
+	 * @initiator: Is the current end the TDLS link initiator
 	 * @buf: TDLS IEs to add to the message
 	 * @len: Length of buf in octets
 	 * Returns: 0 on success, negative (<0) on failure
@@ -2512,7 +2511,7 @@
 	 */
 	int (*send_tdls_mgmt)(void *priv, const u8 *dst, u8 action_code,
 			      u8 dialog_token, u16 status_code, u32 peer_capab,
-			      const u8 *buf, size_t len);
+			      int initiator, const u8 *buf, size_t len);
 
 	/**
 	 * tdls_oper - Ask the driver to perform high-level TDLS operations
@@ -2804,6 +2803,30 @@
 	 */
 	int (*status)(void *priv, char *buf, size_t buflen);
 
+	/**
+	 * roaming - Set roaming policy for driver-based BSS selection
+	 * @priv: Private driver interface data
+	 * @allowed: Whether roaming within ESS is allowed
+	 * @bssid: Forced BSSID if roaming is disabled or %NULL if not set
+	 * Returns: Length of written status information or -1 on failure
+	 *
+	 * This optional callback can be used to update roaming policy from the
+	 * associate() command (bssid being set there indicates that the driver
+	 * should not roam before getting this roaming() call to allow roaming.
+	 * If the driver does not indicate WPA_DRIVER_FLAGS_BSS_SELECTION
+	 * capability, roaming policy is handled within wpa_supplicant and there
+	 * is no need to implement or react to this callback.
+	 */
+	int (*roaming)(void *priv, int allowed, const u8 *bssid);
+
+	/**
+	 * set_mac_addr - Set MAC address
+	 * @priv: Private driver interface data
+	 * @addr: MAC address to use or %NULL for setting back to permanent
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_mac_addr)(void *priv, const u8 *addr);
+
 #ifdef CONFIG_MACSEC
 	int (*macsec_init)(void *priv, struct macsec_init_params *params);
 
@@ -4172,6 +4195,9 @@
 /* Convert wpa_event_type to a string for logging */
 const char * event_to_string(enum wpa_event_type event);
 
+/* Convert chan_width to a string for logging and control interfaces */
+const char * channel_width_to_string(enum chan_width width);
+
 /* NULL terminated array of linked in driver wrappers */
 extern struct wpa_driver_ops *wpa_drivers[];
 
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index 3058cd5..77e6905 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -84,3 +84,24 @@
 	return "UNKNOWN";
 #undef E2S
 }
+
+
+const char * channel_width_to_string(enum chan_width width)
+{
+	switch (width) {
+	case CHAN_WIDTH_20_NOHT:
+		return "20 MHz (no HT)";
+	case CHAN_WIDTH_20:
+		return "20 MHz";
+	case CHAN_WIDTH_40:
+		return "40 MHz";
+	case CHAN_WIDTH_80:
+		return "80 MHz";
+	case CHAN_WIDTH_80P80:
+		return "80+80 MHz";
+	case CHAN_WIDTH_160:
+		return "160 MHz";
+	default:
+		return "unknown";
+	}
+}
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 8ebf7d9..4c8f29f 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -19,6 +19,9 @@
 #include <netlink/genl/genl.h>
 #include <netlink/genl/family.h>
 #include <netlink/genl/ctrl.h>
+#ifdef CONFIG_LIBNL3_ROUTE
+#include <netlink/route/neighbour.h>
+#endif /* CONFIG_LIBNL3_ROUTE */
 #include <linux/rtnetlink.h>
 #include <netpacket/packet.h>
 #include <linux/filter.h>
@@ -253,6 +256,7 @@
 	struct dl_list list;
 	struct dl_list wiphy_list;
 	char phyname[32];
+	u8 perm_addr[ETH_ALEN];
 	void *ctx;
 	int ifindex;
 	int if_removed;
@@ -307,8 +311,11 @@
 	unsigned int start_iface_up:1;
 	unsigned int test_use_roc_tx:1;
 	unsigned int ignore_deauth_event:1;
+	unsigned int roaming_vendor_cmd_avail:1;
 	unsigned int dfs_vendor_cmd_avail:1;
 	unsigned int have_low_prio_scan:1;
+	unsigned int force_connect_cmd:1;
+	unsigned int addr_changed:1;
 
 	u64 remain_on_chan_cookie;
 	u64 send_action_cookie;
@@ -324,6 +331,8 @@
 
 	int eapol_sock; /* socket for EAPOL frames */
 
+	struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */
+
 	int default_if_indices[16];
 	int *if_indices;
 	int num_if_indices;
@@ -349,7 +358,8 @@
 					    void *timeout_ctx);
 static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
 				       enum nl80211_iftype nlmode);
-static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, int freq);
+static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
+					    struct hostapd_freq_params *freq);
 
 static int
 wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
@@ -579,6 +589,20 @@
 }
 
 
+static struct i802_bss * get_bss_ifindex(struct wpa_driver_nl80211_data *drv,
+					 int ifindex)
+{
+	struct i802_bss *bss;
+
+	for (bss = drv->first_bss; bss; bss = bss->next) {
+		if (bss->ifindex == ifindex)
+			return bss;
+	}
+
+	return NULL;
+}
+
+
 static void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
 {
 	if (drv->associated)
@@ -1243,8 +1267,9 @@
 	}
 	extra[sizeof(extra) - 1] = '\0';
 
-	wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_flags=0x%x (%s%s%s%s)",
-		   ifi->ifi_index, ifname, extra, ifi->ifi_flags,
+	wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
+		   ifi->ifi_index, ifname, extra, ifi->ifi_family,
+		   ifi->ifi_flags,
 		   (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
 		   (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
 		   (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
@@ -1296,6 +1321,28 @@
 				   "event since interface %s is marked "
 				   "removed", drv->first_bss->ifname);
 		} else {
+			struct i802_bss *bss;
+			u8 addr[ETH_ALEN];
+
+			/* Re-read MAC address as it may have changed */
+			bss = get_bss_ifindex(drv, ifi->ifi_index);
+			if (bss &&
+			    linux_get_ifhwaddr(drv->global->ioctl_sock,
+					       bss->ifname, addr) < 0) {
+				wpa_printf(MSG_DEBUG,
+					   "nl80211: %s: failed to re-read MAC address",
+					   bss->ifname);
+			} else if (bss &&
+				   os_memcmp(addr, bss->addr, ETH_ALEN) != 0) {
+				wpa_printf(MSG_DEBUG,
+					   "nl80211: Own MAC address on ifindex %d (%s) changed from "
+					   MACSTR " to " MACSTR,
+					   ifi->ifi_index, bss->ifname,
+					   MAC2STR(bss->addr),
+					   MAC2STR(addr));
+				os_memcpy(bss->addr, addr, ETH_ALEN);
+			}
+
 			wpa_printf(MSG_DEBUG, "nl80211: Interface up");
 			drv->if_disabled = 0;
 			wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
@@ -1340,6 +1387,7 @@
 	struct rtattr *attr;
 	u32 brid = 0;
 	char ifname[IFNAMSIZ + 1];
+	char extra[100], *pos, *end;
 
 	drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
 	if (!drv) {
@@ -1348,6 +1396,9 @@
 		return;
 	}
 
+	extra[0] = '\0';
+	pos = extra;
+	end = pos + sizeof(extra);
 	ifname[0] = '\0';
 
 	attrlen = len;
@@ -1362,12 +1413,30 @@
 			break;
 		case IFLA_MASTER:
 			brid = nla_get_u32((struct nlattr *) attr);
+			pos += os_snprintf(pos, end - pos, " master=%u", brid);
+			break;
+		case IFLA_OPERSTATE:
+			pos += os_snprintf(pos, end - pos, " operstate=%u",
+					   nla_get_u32((struct nlattr *) attr));
+			break;
+		case IFLA_LINKMODE:
+			pos += os_snprintf(pos, end - pos, " linkmode=%u",
+					   nla_get_u32((struct nlattr *) attr));
 			break;
 		}
 		attr = RTA_NEXT(attr, attrlen);
 	}
+	extra[sizeof(extra) - 1] = '\0';
 
-	if (ifname[0])
+	wpa_printf(MSG_DEBUG, "RTM_DELLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
+		   ifi->ifi_index, ifname, extra, ifi->ifi_family,
+		   ifi->ifi_flags,
+		   (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
+		   (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
+		   (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
+		   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
+
+	if (ifname[0] && (ifi->ifi_family != AF_BRIDGE || !brid))
 		wpa_driver_nl80211_event_dellink(drv, ifname);
 
 	if (ifi->ifi_family == AF_BRIDGE && brid) {
@@ -1387,6 +1456,17 @@
 	const struct ieee80211_mgmt *mgmt;
 	union wpa_event_data event;
 
+	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
+	    drv->force_connect_cmd) {
+		/*
+		 * Avoid reporting two association events that would confuse
+		 * the core code.
+		 */
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Ignore auth event when using driver SME");
+		return;
+	}
+
 	wpa_printf(MSG_DEBUG, "nl80211: Authenticate event");
 	mgmt = (const struct ieee80211_mgmt *) frame;
 	if (len < 24 + sizeof(mgmt->u.auth)) {
@@ -1453,6 +1533,17 @@
 	union wpa_event_data event;
 	u16 status;
 
+	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
+	    drv->force_connect_cmd) {
+		/*
+		 * Avoid reporting two association events that would confuse
+		 * the core code.
+		 */
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Ignore assoc event when using driver SME");
+		return;
+	}
+
 	wpa_printf(MSG_DEBUG, "nl80211: Associate event");
 	mgmt = (const struct ieee80211_mgmt *) frame;
 	if (len < 24 + sizeof(mgmt->u.assoc_resp)) {
@@ -1500,6 +1591,7 @@
 			       struct nlattr *resp_ie)
 {
 	union wpa_event_data event;
+	u16 status_code;
 
 	if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
 		/*
@@ -1511,21 +1603,41 @@
 		return;
 	}
 
-	if (cmd == NL80211_CMD_CONNECT)
-		wpa_printf(MSG_DEBUG, "nl80211: Connect event");
-	else if (cmd == NL80211_CMD_ROAM)
+	status_code = status ? nla_get_u16(status) : WLAN_STATUS_SUCCESS;
+
+	if (cmd == NL80211_CMD_CONNECT) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Connect event (status=%u ignore_next_local_disconnect=%d)",
+			   status_code, drv->ignore_next_local_disconnect);
+	} else if (cmd == NL80211_CMD_ROAM) {
 		wpa_printf(MSG_DEBUG, "nl80211: Roam event");
+	}
 
 	os_memset(&event, 0, sizeof(event));
-	if (cmd == NL80211_CMD_CONNECT &&
-	    nla_get_u16(status) != WLAN_STATUS_SUCCESS) {
+	if (cmd == NL80211_CMD_CONNECT && status_code != WLAN_STATUS_SUCCESS) {
 		if (addr)
 			event.assoc_reject.bssid = nla_data(addr);
+		if (drv->ignore_next_local_disconnect) {
+			drv->ignore_next_local_disconnect = 0;
+			if (!event.assoc_reject.bssid ||
+			    (os_memcmp(event.assoc_reject.bssid,
+				       drv->auth_attempt_bssid,
+				       ETH_ALEN) != 0)) {
+				/*
+				 * Ignore the event that came without a BSSID or
+				 * for the old connection since this is likely
+				 * not relevant to the new Connect command.
+				 */
+				wpa_printf(MSG_DEBUG,
+					   "nl80211: Ignore connection failure event triggered during reassociation");
+				return;
+			}
+		}
 		if (resp_ie) {
 			event.assoc_reject.resp_ies = nla_data(resp_ie);
 			event.assoc_reject.resp_ies_len = nla_len(resp_ie);
 		}
-		event.assoc_reject.status_code = nla_get_u16(status);
+		event.assoc_reject.status_code = status_code;
 		wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
 		return;
 	}
@@ -1634,10 +1746,7 @@
 		return;
 
 	ifidx = nla_get_u32(ifindex);
-	for (bss = drv->first_bss; bss; bss = bss->next)
-		if (bss->ifindex == ifidx)
-			break;
-
+	bss = get_bss_ifindex(drv, ifidx);
 	if (bss == NULL) {
 		wpa_printf(MSG_WARNING, "nl80211: Unknown ifindex (%d) for channel switch, ignoring",
 			   ifidx);
@@ -3846,9 +3955,14 @@
 				continue;
 			}
 			vinfo = nla_data(nl);
-			if (vinfo->subcmd ==
-			    QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY)
+			switch (vinfo->subcmd) {
+			case QCA_NL80211_VENDOR_SUBCMD_ROAMING:
+				drv->roaming_vendor_cmd_avail = 1;
+				break;
+			case QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY:
 				drv->dfs_vendor_cmd_avail = 1;
+				break;
+			}
 
 			wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
 				   vinfo->vendor_id, vinfo->subcmd);
@@ -4550,7 +4664,7 @@
 #ifdef CONFIG_HS20
 	/* WNM-Notification */
 	if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x1a", 2) < 0)
-		return -1;
+		ret = -1;
 #endif /* CONFIG_HS20 */
 
 	nl80211_mgmt_handle_register_eloop(bss);
@@ -4822,6 +4936,7 @@
 	if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
 			       bss->addr))
 		return -1;
+	os_memcpy(drv->perm_addr, bss->addr, ETH_ALEN);
 
 	if (send_rfkill_event) {
 		eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
@@ -4877,6 +4992,8 @@
 			wpa_printf(MSG_INFO, "nl80211: Failed to remove "
 				   "interface %s from bridge %s: %s",
 				   bss->ifname, bss->brname, strerror(errno));
+		if (drv->rtnl_sk)
+			nl80211_handle_destroy(drv->rtnl_sk);
 	}
 	if (bss->added_bridge) {
 		if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
@@ -4910,6 +5027,16 @@
 
 	if (!drv->start_iface_up)
 		(void) i802_set_iface_flags(bss, 0);
+
+	if (drv->addr_changed) {
+		linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0);
+		if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+				       drv->perm_addr) < 0) {
+			wpa_printf(MSG_DEBUG,
+				   "nl80211: Could not restore permanent MAC address");
+		}
+	}
+
 	if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) {
 		if (!drv->hostapd || !drv->start_mode_ap)
 			wpa_driver_nl80211_set_mode(bss,
@@ -7686,6 +7813,43 @@
 }
 
 
+static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr)
+{
+#ifdef CONFIG_LIBNL3_ROUTE
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct rtnl_neigh *rn;
+	struct nl_addr *nl_addr;
+	int err;
+
+	rn = rtnl_neigh_alloc();
+	if (!rn)
+		return;
+
+	rtnl_neigh_set_family(rn, AF_BRIDGE);
+	rtnl_neigh_set_ifindex(rn, bss->ifindex);
+	nl_addr = nl_addr_build(AF_BRIDGE, (void *) addr, ETH_ALEN);
+	if (!nl_addr) {
+		rtnl_neigh_put(rn);
+		return;
+	}
+	rtnl_neigh_set_lladdr(rn, nl_addr);
+
+	err = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
+	if (err < 0) {
+		wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for "
+			   MACSTR " ifindex=%d failed: %s", MAC2STR(addr),
+			   bss->ifindex, nl_geterror(err));
+	} else {
+		wpa_printf(MSG_DEBUG, "nl80211: deleted bridge FDB entry for "
+			   MACSTR, MAC2STR(addr));
+	}
+
+	nl_addr_put(nl_addr);
+	rtnl_neigh_put(rn);
+#endif /* CONFIG_LIBNL3_ROUTE */
+}
+
+
 static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -7706,6 +7870,10 @@
 	wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR
 		   " --> %d (%s)",
 		   bss->ifname, MAC2STR(addr), ret, strerror(-ret));
+
+	if (drv->rtnl_sk)
+		rtnl_neigh_delete_fdb_entry(bss, addr);
+
 	if (ret == -ENOENT)
 		return 0;
 	return ret;
@@ -8480,6 +8648,11 @@
 	struct nlattr *flags;
 	struct nl80211_sta_flag_update upd;
 
+	wpa_printf(MSG_DEBUG, "nl80211: Set STA flags - ifname=%s addr=" MACSTR
+		   " total_flags=0x%x flags_or=0x%x flags_and=0x%x authorized=%d",
+		   bss->ifname, MAC2STR(addr), total_flags, flags_or, flags_and,
+		   !!(total_flags & WPA_STA_AUTHORIZED));
+
 	msg = nlmsg_alloc();
 	if (!msg)
 		return -ENOMEM;
@@ -8530,9 +8703,6 @@
 				 struct wpa_driver_associate_params *params)
 {
 	enum nl80211_iftype nlmode, old_mode;
-	struct hostapd_freq_params freq = {
-		.freq = params->freq,
-	};
 
 	if (params->p2p) {
 		wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P "
@@ -8547,7 +8717,7 @@
 		return -1;
 	}
 
-	if (nl80211_set_channel(drv->first_bss, &freq, 0)) {
+	if (nl80211_set_channel(drv->first_bss, &params->freq, 0)) {
 		if (old_mode != nlmode)
 			wpa_driver_nl80211_set_mode(drv->first_bss, old_mode);
 		nl80211_remove_monitor_interface(drv);
@@ -8601,7 +8771,7 @@
 
 	wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
 
-	if (wpa_driver_nl80211_set_mode_ibss(drv->first_bss, params->freq)) {
+	if (wpa_driver_nl80211_set_mode_ibss(drv->first_bss, &params->freq)) {
 		wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
 			   "IBSS mode");
 		return -1;
@@ -8625,8 +8795,16 @@
 	os_memcpy(drv->ssid, params->ssid, params->ssid_len);
 	drv->ssid_len = params->ssid_len;
 
-	wpa_printf(MSG_DEBUG, "  * freq=%d", params->freq);
-	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
+	wpa_printf(MSG_DEBUG, "  * freq=%d", params->freq.freq);
+	wpa_printf(MSG_DEBUG, "  * ht_enabled=%d", params->freq.ht_enabled);
+	wpa_printf(MSG_DEBUG, "  * sec_channel_offset=%d",
+		   params->freq.sec_channel_offset);
+	wpa_printf(MSG_DEBUG, "  * vht_enabled=%d", params->freq.vht_enabled);
+	wpa_printf(MSG_DEBUG, "  * center_freq1=%d", params->freq.center_freq1);
+	wpa_printf(MSG_DEBUG, "  * center_freq2=%d", params->freq.center_freq2);
+	wpa_printf(MSG_DEBUG, "  * bandwidth=%d", params->freq.bandwidth);
+	if (nl80211_put_freq_params(msg, &params->freq) < 0)
+		goto nla_put_failure;
 
 	if (params->beacon_int > 0) {
 		wpa_printf(MSG_DEBUG, "  * beacon_int=%d", params->beacon_int);
@@ -8704,10 +8882,10 @@
 			params->bssid_hint);
 	}
 
-	if (params->freq) {
-		wpa_printf(MSG_DEBUG, "  * freq=%d", params->freq);
-		NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
-		drv->assoc_freq = params->freq;
+	if (params->freq.freq) {
+		wpa_printf(MSG_DEBUG, "  * freq=%d", params->freq.freq);
+		NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq.freq);
+		drv->assoc_freq = params->freq.freq;
 	} else
 		drv->assoc_freq = 0;
 
@@ -8929,7 +9107,15 @@
 	struct wpa_driver_nl80211_data *drv,
 	struct wpa_driver_associate_params *params)
 {
-	int ret = wpa_driver_nl80211_try_connect(drv, params);
+	int ret;
+
+	/* Store the connection attempted bssid for future use */
+	if (params->bssid)
+		os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
+	else
+		os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
+
+	ret = wpa_driver_nl80211_try_connect(drv, params);
 	if (ret == -EALREADY) {
 		/*
 		 * cfg80211 does not currently accept new connections if
@@ -9198,13 +9384,11 @@
 }
 
 
-static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, int freq)
+static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
+					    struct hostapd_freq_params *freq)
 {
-	struct hostapd_freq_params freq_params;
-	os_memset(&freq_params, 0, sizeof(freq_params));
-	freq_params.freq = freq;
 	return wpa_driver_nl80211_set_mode_impl(bss, NL80211_IFTYPE_ADHOC,
-						&freq_params);
+						freq);
 }
 
 
@@ -9984,6 +10168,22 @@
 	    i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0)
 		goto failed;
 
+#ifdef CONFIG_LIBNL3_ROUTE
+	if (bss->added_if_into_bridge) {
+		drv->rtnl_sk = nl_socket_alloc();
+		if (drv->rtnl_sk == NULL) {
+			wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
+			goto failed;
+		}
+
+		if (nl_connect(drv->rtnl_sk, NETLINK_ROUTE)) {
+			wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
+				   strerror(errno));
+			goto failed;
+		}
+	}
+#endif /* CONFIG_LIBNL3_ROUTE */
+
 	drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
 	if (drv->eapol_sock < 0) {
 		wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s",
@@ -10000,6 +10200,7 @@
 	if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
 			       params->own_addr))
 		goto failed;
+	os_memcpy(drv->perm_addr, params->own_addr, ETH_ALEN);
 
 	memcpy(bss->addr, params->own_addr, ETH_ALEN);
 
@@ -10959,6 +11160,7 @@
 		struct i802_bss *bss = priv;
 		struct wpa_driver_nl80211_data *drv = bss->drv;
 		drv->capa.flags &= ~WPA_DRIVER_FLAGS_SME;
+		drv->force_connect_cmd = 1;
 	}
 
 	if (os_strstr(param, "no_offchannel_tx=1")) {
@@ -11450,60 +11652,18 @@
 
 	nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_RADAR_DETECT);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
-	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq);
 
-	if (freq->vht_enabled) {
-		switch (freq->bandwidth) {
-		case 20:
-			NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
-				    NL80211_CHAN_WIDTH_20);
-			break;
-		case 40:
-			NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
-				    NL80211_CHAN_WIDTH_40);
-			break;
-		case 80:
-			if (freq->center_freq2)
-				NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
-					    NL80211_CHAN_WIDTH_80P80);
-			else
-				NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
-					    NL80211_CHAN_WIDTH_80);
-			break;
-		case 160:
-			NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
-				    NL80211_CHAN_WIDTH_160);
-			break;
-		default:
-			return -1;
-		}
-		NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, freq->center_freq1);
-		if (freq->center_freq2)
-			NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2,
-				    freq->center_freq2);
-	} else if (freq->ht_enabled) {
-		switch (freq->sec_channel_offset) {
-		case -1:
-			NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
-				    NL80211_CHAN_HT40MINUS);
-			break;
-		case 1:
-			NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
-				    NL80211_CHAN_HT40PLUS);
-			break;
-		default:
-			NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
-				    NL80211_CHAN_HT20);
-			break;
-		}
-	}
+	if (nl80211_put_freq_params(msg, freq) < 0)
+		goto nla_put_failure;
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	msg = NULL;
 	if (ret == 0)
 		return 0;
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: "
 		   "%d (%s)", ret, strerror(-ret));
 nla_put_failure:
+	nlmsg_free(msg);
 	return -1;
 }
 
@@ -11511,7 +11671,8 @@
 
 static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
 				  u8 dialog_token, u16 status_code,
-				  u32 peer_capab, const u8 *buf, size_t len)
+				  u32 peer_capab, int initiator, const u8 *buf,
+				  size_t len)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -11542,6 +11703,8 @@
 		 */
 		NLA_PUT_U32(msg, NL80211_ATTR_TDLS_PEER_CAPABILITY, peer_capab);
 	}
+	if (initiator)
+		NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_INITIATOR);
 	NLA_PUT(msg, NL80211_ATTR_IE, len, buf);
 
 	return send_and_recv_msgs(drv, msg, NULL, NULL);
@@ -11954,6 +12117,7 @@
 
 	res = os_snprintf(pos, end - pos,
 			  "phyname=%s\n"
+			  "perm_addr=" MACSTR "\n"
 			  "drv_ifindex=%d\n"
 			  "operstate=%d\n"
 			  "scan_state=%s\n"
@@ -11970,6 +12134,7 @@
 			  "eapol_tx_sock=%d\n"
 			  "%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
 			  drv->phyname,
+			  MAC2STR(drv->perm_addr),
 			  drv->ifindex,
 			  drv->operstate,
 			  scan_state_str(drv->scan_state),
@@ -12352,6 +12517,90 @@
 }
 
 
+static int nl80211_roaming(void *priv, int allowed, const u8 *bssid)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+	struct nlattr *params;
+
+	wpa_printf(MSG_DEBUG, "nl80211: Roaming policy: allowed=%d", allowed);
+
+	if (!drv->roaming_vendor_cmd_avail) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Ignore roaming policy change since driver does not provide command for setting it");
+		return -1;
+	}
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -ENOMEM;
+
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_VENDOR);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+	NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA);
+	NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+		    QCA_NL80211_VENDOR_SUBCMD_ROAMING);
+
+	params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+	if (!params)
+		goto nla_put_failure;
+	NLA_PUT_U32(msg, QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY,
+		    allowed ? QCA_ROAMING_ALLOWED_WITHIN_ESS :
+		    QCA_ROAMING_NOT_ALLOWED);
+	if (bssid)
+		NLA_PUT(msg, QCA_WLAN_VENDOR_ATTR_MAC_ADDR, ETH_ALEN, bssid);
+	nla_nest_end(msg, params);
+
+	return send_and_recv_msgs(drv, msg, NULL, NULL);
+
+ nla_put_failure:
+	nlmsg_free(msg);
+	return -1;
+}
+
+
+static int nl80211_set_mac_addr(void *priv, const u8 *addr)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	int new_addr = addr != NULL;
+
+	if (!addr)
+		addr = drv->perm_addr;
+
+	if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) < 0)
+		return -1;
+
+	if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, addr) < 0)
+	{
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: failed to set_mac_addr for %s to " MACSTR,
+			   bss->ifname, MAC2STR(addr));
+		if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname,
+					  1) < 0) {
+			wpa_printf(MSG_DEBUG,
+				   "nl80211: Could not restore interface UP after failed set_mac_addr");
+		}
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "nl80211: set_mac_addr for %s to " MACSTR,
+		   bss->ifname, MAC2STR(addr));
+	drv->addr_changed = new_addr;
+	os_memcpy(bss->addr, addr, ETH_ALEN);
+
+	if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1) < 0)
+	{
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Could not restore interface UP after set_mac_addr");
+	}
+
+	return 0;
+}
+
+
 const struct wpa_driver_ops wpa_driver_nl80211_ops = {
 	.name = "nl80211",
 	.desc = "Linux nl80211/cfg80211",
@@ -12443,4 +12692,6 @@
 	.vendor_cmd = nl80211_vendor_cmd,
 	.set_qos_map = nl80211_set_qos_map,
 	.set_wowlan = nl80211_set_wowlan,
+	.roaming = nl80211_roaming,
+	.set_mac_addr = nl80211_set_mac_addr,
 };
diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c
index 3608b52..66edfa7 100644
--- a/src/drivers/driver_test.c
+++ b/src/drivers/driver_test.c
@@ -1478,7 +1478,7 @@
 	struct wpa_driver_test_data *drv = dbss->drv;
 	wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
 		   "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
-		   __func__, priv, params->freq, params->pairwise_suite,
+		   __func__, priv, params->freq.freq, params->pairwise_suite,
 		   params->group_suite, params->key_mgmt_suite,
 		   params->auth_alg, params->mode);
 	wpa_driver_update_mode(drv, params->mode == IEEE80211_MODE_AP);
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 459ac48..1b3a757 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -2119,7 +2119,8 @@
 	if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_MFP, value) < 0)
 		ret = -1;
 #endif /* CONFIG_IEEE80211W */
-	if (params->freq && wpa_driver_wext_set_freq(drv, params->freq) < 0)
+	if (params->freq.freq &&
+	    wpa_driver_wext_set_freq(drv, params->freq.freq) < 0)
 		ret = -1;
 	if (!drv->cfg80211 &&
 	    wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0)
diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
index 40aaba5..cdb913e 100644
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -36,6 +36,10 @@
   DRV_LIBS += -lnl-3
   DRV_LIBS += -lnl-genl-3
   DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3
+ifdef CONFIG_LIBNL3_ROUTE
+  DRV_LIBS += -lnl-route-3
+  DRV_CFLAGS += -DCONFIG_LIBNL3_ROUTE
+endif
 else
   ifdef CONFIG_LIBNL_TINY
     DRV_LIBS += -lnl-tiny
diff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk
index db8561a..9fa70d9 100644
--- a/src/drivers/drivers.mk
+++ b/src/drivers/drivers.mk
@@ -31,6 +31,10 @@
   DRV_LIBS += -lnl-3
   DRV_LIBS += -lnl-genl-3
   DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3
+ifdef CONFIG_LIBNL3_ROUTE
+  DRV_LIBS += -lnl-route-3
+  DRV_CFLAGS += -DCONFIG_LIBNL3_ROUTE
+endif
 else
   ifdef CONFIG_LIBNL_TINY
     DRV_LIBS += -lnl-tiny
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 406010d..4b28dc0 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -503,6 +503,9 @@
  *	TX status event pertaining to the TX request.
  *	%NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
  *	management frames at CCK rate or not in 2GHz band.
+ *	%NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA
+ *	counters which will be updated to the current value. This attribute
+ *	is used during CSA period.
  * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this
  *	command may be used with the corresponding cookie to cancel the wait
  *	time if it is known that it is no longer necessary.
@@ -719,6 +722,22 @@
  *	QoS mapping is relevant for IP packets, it is only valid during an
  *	association. This is cleared on disassociation and AP restart.
  *
+ * @NL80211_CMD_ADD_TX_TS: Ask the kernel to add a traffic stream for the given
+ *	%NL80211_ATTR_TSID and %NL80211_ATTR_MAC with %NL80211_ATTR_USER_PRIO
+ *	and %NL80211_ATTR_ADMITTED_TIME parameters.
+ *	Note that the action frame handshake with the AP shall be handled by
+ *	userspace via the normal management RX/TX framework, this only sets
+ *	up the TX TS in the driver/device.
+ *	If the admitted time attribute is not added then the request just checks
+ *	if a subsequent setup could be successful, the intent is to use this to
+ *	avoid setting up a session with the AP when local restrictions would
+ *	make that impossible. However, the subsequent "real" setup may still
+ *	fail even if the check was successful.
+ * @NL80211_CMD_DEL_TX_TS: Remove an existing TS with the %NL80211_ATTR_TSID
+ *	and %NL80211_ATTR_MAC parameters. It isn't necessary to call this
+ *	before removing a station entry entirely, or before disassociating
+ *	or similar, cleanup will happen in the driver/device in this case.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -890,6 +909,9 @@
 
 	NL80211_CMD_SET_QOS_MAP,
 
+	NL80211_CMD_ADD_TX_TS,
+	NL80211_CMD_DEL_TX_TS,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -1525,10 +1547,10 @@
  *	operation).
  * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information
  *	for the time while performing a channel switch.
- * @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter
- *	field in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
- * @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter
- *	field in the probe response (%NL80211_ATTR_PROBE_RESP).
+ * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel
+ *	switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
+ * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel
+ *	switch counters in the probe response (%NL80211_ATTR_PROBE_RESP).
  *
  * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32.
  *	As specified in the &enum nl80211_rxmgmt_flags.
@@ -1576,6 +1598,11 @@
  *	advertise values that cannot always be met. In such cases, an attempt
  *	to add a new station entry with @NL80211_CMD_NEW_STATION may fail.
  *
+ * @NL80211_ATTR_CSA_C_OFFSETS_TX: An array of csa counter offsets (u16) which
+ *	should be updated when the frame is transmitted.
+ * @NL80211_ATTR_MAX_CSA_COUNTERS: U8 attribute used to advertise the maximum
+ *	supported number of csa counters.
+ *
  * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32.
  *	As specified in the &enum nl80211_tdls_peer_capability.
  *
@@ -1583,6 +1610,34 @@
  *	creation then the new interface will be owned by the netlink socket
  *	that created it and will be destroyed when the socket is closed
  *
+ * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is
+ *	the TDLS link initiator.
+ *
+ * @NL80211_ATTR_USE_RRM: flag for indicating whether the current connection
+ *	shall support Radio Resource Measurements (11k). This attribute can be
+ *	used with %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests.
+ *	User space applications are expected to use this flag only if the
+ *	underlying device supports these minimal RRM features:
+ *		%NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES,
+ *		%NL80211_FEATURE_QUIET,
+ *	If this flag is used, driver must add the Power Capabilities IE to the
+ *	association request. In addition, it must also set the RRM capability
+ *	flag in the association request's Capability Info field.
+ *
+ * @NL80211_ATTR_WIPHY_DYN_ACK: flag attribute used to enable ACK timeout
+ *	estimation algorithm (dynack). In order to activate dynack
+ *	%NL80211_FEATURE_ACKTO_ESTIMATION feature flag must be set by lower
+ *	drivers to indicate dynack capability. Dynack is automatically disabled
+ *	setting valid value for coverage class.
+ *
+ * @NL80211_ATTR_TSID: a TSID value (u8 attribute)
+ * @NL80211_ATTR_USER_PRIO: user priority value (u8 attribute)
+ * @NL80211_ATTR_ADMITTED_TIME: admitted time in units of 32 microseconds
+ *	(per second) (u16 attribute)
+ *
+ * @NL80211_ATTR_SMPS_MODE: SMPS mode to use (ap mode). see
+ *	&enum nl80211_smps_mode.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1920,6 +1975,21 @@
 
 	NL80211_ATTR_IFACE_SOCKET_OWNER,
 
+	NL80211_ATTR_CSA_C_OFFSETS_TX,
+	NL80211_ATTR_MAX_CSA_COUNTERS,
+
+	NL80211_ATTR_TDLS_INITIATOR,
+
+	NL80211_ATTR_USE_RRM,
+
+	NL80211_ATTR_WIPHY_DYN_ACK,
+
+	NL80211_ATTR_TSID,
+	NL80211_ATTR_USER_PRIO,
+	NL80211_ATTR_ADMITTED_TIME,
+
+	NL80211_ATTR_SMPS_MODE,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2188,6 +2258,8 @@
  *	Contains a nested array of signal strength attributes (u8, dBm)
  * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
  *	Same format as NL80211_STA_INFO_CHAIN_SIGNAL.
+ * @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the
+ *	802.11 header (u32, kbps)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
  */
@@ -2219,6 +2291,7 @@
 	NL80211_STA_INFO_TX_BYTES64,
 	NL80211_STA_INFO_CHAIN_SIGNAL,
 	NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
+	NL80211_STA_INFO_EXPECTED_THROUGHPUT,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
@@ -3036,14 +3109,20 @@
  * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets)
  * @NL80211_BSS_FREQUENCY: frequency in MHz (u32)
  * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64)
+ *	(if @NL80211_BSS_PRESP_DATA is present then this is known to be
+ *	from a probe response, otherwise it may be from the same beacon
+ *	that the NL80211_BSS_BEACON_TSF will be from)
  * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16)
  * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16)
  * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the
  *	raw information elements from the probe response/beacon (bin);
- *	if the %NL80211_BSS_BEACON_IES attribute is present, the IEs here are
- *	from a Probe Response frame; otherwise they are from a Beacon frame.
+ *	if the %NL80211_BSS_BEACON_IES attribute is present and the data is
+ *	different then the IEs here are from a Probe Response frame; otherwise
+ *	they are from a Beacon frame.
  *	However, if the driver does not indicate the source of the IEs, these
  *	IEs may be from either frame subtype.
+ *	If present, the @NL80211_BSS_PRESP_DATA attribute indicates that the
+ *	data here is known to be from a probe response, without any heuristics.
  * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon
  *	in mBm (100 * dBm) (s32)
  * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
@@ -3055,6 +3134,10 @@
  *	yet been received
  * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel
  *	(u32, enum nl80211_bss_scan_width)
+ * @NL80211_BSS_BEACON_TSF: TSF of the last received beacon (u64)
+ *	(not present if no beacon frame has been received yet)
+ * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and
+ *	@NL80211_BSS_TSF is known to be from a probe response (flag attribute)
  * @__NL80211_BSS_AFTER_LAST: internal
  * @NL80211_BSS_MAX: highest BSS attribute
  */
@@ -3072,6 +3155,8 @@
 	NL80211_BSS_SEEN_MS_AGO,
 	NL80211_BSS_BEACON_IES,
 	NL80211_BSS_CHAN_WIDTH,
+	NL80211_BSS_BEACON_TSF,
+	NL80211_BSS_PRESP_DATA,
 
 	/* keep last */
 	__NL80211_BSS_AFTER_LAST,
@@ -3688,6 +3773,8 @@
  *	different channels may be used within this group.
  * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap
  *	of supported channel widths for radar detection.
+ * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap
+ *	of supported regulatory regions for radar detection.
  * @NUM_NL80211_IFACE_COMB: number of attributes
  * @MAX_NL80211_IFACE_COMB: highest attribute number
  *
@@ -3721,6 +3808,7 @@
 	NL80211_IFACE_COMB_STA_AP_BI_MATCH,
 	NL80211_IFACE_COMB_NUM_CHANNELS,
 	NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
+	NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
 
 	/* keep last */
 	NUM_NL80211_IFACE_COMB,
@@ -3894,6 +3982,8 @@
  * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested
  *	to work properly to suppport receiving regulatory hints from
  *	cellular base stations.
+ * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: (no longer available, only
+ *	here to reserve the value for API/ABI compatibility)
  * @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of
  *	equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station
  *	mode
@@ -3932,13 +4022,33 @@
  * @NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE: This driver supports dynamic
  *	channel bandwidth change (e.g., HT 20 <-> 40 MHz channel) during the
  *	lifetime of a BSS.
+ * @NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES: This device adds a DS Parameter
+ *	Set IE to probe requests.
+ * @NL80211_FEATURE_WFA_TPC_IE_IN_PROBES: This device adds a WFA TPC Report IE
+ *	to probe requests.
+ * @NL80211_FEATURE_QUIET: This device, in client mode, supports Quiet Period
+ *	requests sent to it by an AP.
+ * @NL80211_FEATURE_TX_POWER_INSERTION: This device is capable of inserting the
+ *	current tx power value into the TPC Report IE in the spectrum
+ *	management TPC Report action frame, and in the Radio Measurement Link
+ *	Measurement Report action frame.
+ * @NL80211_FEATURE_ACKTO_ESTIMATION: This driver supports dynamic ACK timeout
+ *	estimation (dynack). %NL80211_ATTR_WIPHY_DYN_ACK flag attribute is used
+ *	to enable dynack.
+ * @NL80211_FEATURE_STATIC_SMPS: Device supports static spatial
+ *	multiplexing powersave, ie. can turn off all but one chain
+ *	even on HT connections that should be using more chains.
+ * @NL80211_FEATURE_DYNAMIC_SMPS: Device supports dynamic spatial
+ *	multiplexing powersave, ie. can turn off all but one chain
+ *	and then wake the rest up as required after, for example,
+ *	rts/cts handshake.
  */
 enum nl80211_feature_flags {
 	NL80211_FEATURE_SK_TX_STATUS			= 1 << 0,
 	NL80211_FEATURE_HT_IBSS				= 1 << 1,
 	NL80211_FEATURE_INACTIVITY_TIMER		= 1 << 2,
 	NL80211_FEATURE_CELL_BASE_REG_HINTS		= 1 << 3,
-	/* bit 4 is reserved - don't use */
+	NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL	= 1 << 4,
 	NL80211_FEATURE_SAE				= 1 << 5,
 	NL80211_FEATURE_LOW_PRIORITY_SCAN		= 1 << 6,
 	NL80211_FEATURE_SCAN_FLUSH			= 1 << 7,
@@ -3953,6 +4063,13 @@
 	NL80211_FEATURE_USERSPACE_MPM			= 1 << 16,
 	NL80211_FEATURE_ACTIVE_MONITOR			= 1 << 17,
 	NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE	= 1 << 18,
+	NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES	= 1 << 19,
+	NL80211_FEATURE_WFA_TPC_IE_IN_PROBES		= 1 << 20,
+	NL80211_FEATURE_QUIET				= 1 << 21,
+	NL80211_FEATURE_TX_POWER_INSERTION		= 1 << 22,
+	NL80211_FEATURE_ACKTO_ESTIMATION		= 1 << 23,
+	NL80211_FEATURE_STATIC_SMPS			= 1 << 24,
+	NL80211_FEATURE_DYNAMIC_SMPS			= 1 << 25,
 };
 
 /**
@@ -4027,6 +4144,25 @@
 };
 
 /**
+ * enum nl80211_smps_mode - SMPS mode
+ *
+ * Requested SMPS mode (for AP mode)
+ *
+ * @NL80211_SMPS_OFF: SMPS off (use all antennas).
+ * @NL80211_SMPS_STATIC: static SMPS (use a single antenna)
+ * @NL80211_SMPS_DYNAMIC: dynamic smps (start with a single antenna and
+ *	turn on other antennas after CTS/RTS).
+ */
+enum nl80211_smps_mode {
+	NL80211_SMPS_OFF,
+	NL80211_SMPS_STATIC,
+	NL80211_SMPS_DYNAMIC,
+
+	__NL80211_SMPS_AFTER_LAST,
+	NL80211_SMPS_MAX = __NL80211_SMPS_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_radar_event - type of radar event for DFS operation
  *
  * Type of event to be used with NL80211_ATTR_RADAR_EVENT to inform userspace
diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
index fdcff7f..631c363 100644
--- a/src/eap_common/eap_pwd_common.c
+++ b/src/eap_common/eap_pwd_common.c
@@ -106,9 +106,11 @@
         case 21:
 		nid = NID_secp521r1;
 		break;
+#ifndef OPENSSL_IS_BORINGSSL
         case 25:
 		nid = NID_X9_62_prime192v1;
 		break;
+#endif /* OPENSSL_IS_BORINGSSL */
         case 26:
 		nid = NID_secp224r1;
 		break;
diff --git a/src/eap_server/eap_server_fast.c b/src/eap_server/eap_server_fast.c
index 4691e72..2692bce 100644
--- a/src/eap_server/eap_server_fast.c
+++ b/src/eap_server/eap_server_fast.c
@@ -161,8 +161,8 @@
 		return 0;
 	}
 
-	if (aes_unwrap(data->pac_opaque_encr, (pac_opaque_len - 8) / 8,
-		       pac_opaque, buf) < 0) {
+	if (aes_unwrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr),
+		       (pac_opaque_len - 8) / 8, pac_opaque, buf) < 0) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to decrypt "
 			   "PAC-Opaque");
 		os_free(buf);
@@ -731,8 +731,8 @@
 		os_free(pac_buf);
 		return NULL;
 	}
-	if (aes_wrap(data->pac_opaque_encr, pac_len / 8, pac_buf,
-		     pac_opaque) < 0) {
+	if (aes_wrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr),
+		     pac_len / 8, pac_buf, pac_opaque) < 0) {
 		os_free(pac_buf);
 		os_free(pac_opaque);
 		return NULL;
diff --git a/src/eap_server/eap_server_pax.c b/src/eap_server/eap_server_pax.c
index c87848c..d9d4375 100644
--- a/src/eap_server/eap_server_pax.c
+++ b/src/eap_server/eap_server_pax.c
@@ -287,7 +287,7 @@
 	struct eap_pax_hdr *resp;
 	u8 mac[EAP_PAX_MAC_LEN], icvbuf[EAP_PAX_ICV_LEN];
 	const u8 *pos;
-	size_t len, left;
+	size_t len, left, cid_len;
 	int i;
 
 	if (data->state != PAX_STD_1)
@@ -320,7 +320,12 @@
 		wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (CID)");
 		return;
 	}
-	data->cid_len = WPA_GET_BE16(pos);
+	cid_len = WPA_GET_BE16(pos);
+	if (cid_len > 1500) {
+		wpa_printf(MSG_INFO, "EAP-PAX: Too long CID");
+		return;
+	}
+	data->cid_len = cid_len;
 	os_free(data->cid);
 	data->cid = os_malloc(data->cid_len);
 	if (data->cid == NULL) {
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index cf3506d..70258be 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -255,12 +255,14 @@
 		 * delay authentication. Use a short timeout to send the first
 		 * EAPOL-Start if Authenticator does not start authentication.
 		 */
-#ifdef CONFIG_WPS
-		/* Reduce latency on starting WPS negotiation. */
-		sm->startWhen = 1;
-#else /* CONFIG_WPS */
-		sm->startWhen = 3;
-#endif /* CONFIG_WPS */
+		if (sm->conf.wps) {
+			/* Reduce latency on starting WPS negotiation. */
+			wpa_printf(MSG_DEBUG,
+				   "EAPOL: Using shorter startWhen for WPS");
+			sm->startWhen = 1;
+		} else {
+			sm->startWhen = 2;
+		}
 	}
 	eapol_enable_timer_tick(sm);
 	sm->eapolEap = FALSE;
@@ -1242,7 +1244,7 @@
 		return 0;
 	}
 #ifdef CONFIG_WPS
-	if (sm->conf.workaround &&
+	if (sm->conf.wps && sm->conf.workaround &&
 	    plen < len - sizeof(*hdr) &&
 	    hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
 	    len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
@@ -1491,6 +1493,7 @@
 	sm->conf.required_keys = conf->required_keys;
 	sm->conf.fast_reauth = conf->fast_reauth;
 	sm->conf.workaround = conf->workaround;
+	sm->conf.wps = conf->wps;
 #ifdef CONFIG_EAP_PROXY
 	if (sm->use_eap_proxy) {
 		/* Using EAP Proxy, so skip EAP state machine update */
diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h
index d76c8c2..5b37314 100644
--- a/src/eapol_supp/eapol_supp_sm.h
+++ b/src/eapol_supp/eapol_supp_sm.h
@@ -58,6 +58,11 @@
 	 * external_sim - Use external processing for SIM/USIM operations
 	 */
 	int external_sim;
+
+	/**
+	 * wps - Whether this connection is used for WPS
+	 */
+	int wps;
 };
 
 struct eapol_sm;
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 667b96b..28c3aa0 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -259,7 +259,8 @@
 		return;
 	}
 
-	os_get_random((u8 *) &r, sizeof(r));
+	if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+		r = 0;
 	tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) +
 	      p2p->min_disc_int) * 100;
 	if (p2p->max_disc_tu >= 0 && tu > (unsigned int) p2p->max_disc_tu)
@@ -1287,8 +1288,8 @@
 	} else if (p2p_channel_random_social(&p2p->cfg->channels,
 					     &p2p->op_reg_class,
 					     &p2p->op_channel) == 0) {
-		p2p_dbg(p2p, "Select random available social channel %d from 2.4 GHz band as operating channel preference",
-			p2p->op_channel);
+		p2p_dbg(p2p, "Select random available social channel (op_class %u channel %u) as operating channel preference",
+			p2p->op_reg_class, p2p->op_channel);
 	} else {
 		/* Select any random available channel from the first available
 		 * operating class */
@@ -1825,8 +1826,17 @@
 	struct p2p_data *p2p = eloop_ctx;
 	if (p2p->go_neg_peer == NULL)
 		return;
+	if (p2p->pending_listen_freq) {
+		p2p_dbg(p2p, "Clear pending_listen_freq for p2p_go_neg_start");
+		p2p->pending_listen_freq = 0;
+	}
 	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
 	p2p->go_neg_peer->status = P2P_SC_SUCCESS;
+	/*
+	 * Set new timeout to make sure a previously set one does not expire
+	 * too quickly while waiting for the GO Negotiation to complete.
+	 */
+	p2p_set_timeout(p2p, 0, 500000);
 	p2p_connect_send(p2p, p2p->go_neg_peer);
 }
 
@@ -1836,6 +1846,10 @@
 	struct p2p_data *p2p = eloop_ctx;
 	if (p2p->invite_peer == NULL)
 		return;
+	if (p2p->pending_listen_freq) {
+		p2p_dbg(p2p, "Clear pending_listen_freq for p2p_invite_start");
+		p2p->pending_listen_freq = 0;
+	}
 	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
 	p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr,
 			p2p->invite_dev_pw_id);
@@ -2481,7 +2495,8 @@
 	p2p->max_disc_int = 3;
 	p2p->max_disc_tu = -1;
 
-	os_get_random(&p2p->next_tie_breaker, 1);
+	if (os_get_random(&p2p->next_tie_breaker, 1) < 0)
+		p2p->next_tie_breaker = 0;
 	p2p->next_tie_breaker &= 0x01;
 	if (cfg->sd_request)
 		p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
@@ -2774,6 +2789,19 @@
 		return;
 	}
 
+	if (p2p->sd_query->for_all_peers) {
+		/* Update the pending broadcast SD query count for this device
+		 */
+		p2p->sd_peer->sd_pending_bcast_queries--;
+
+		/*
+		 * If there are no pending broadcast queries for this device,
+		 * mark it as done (-1).
+		 */
+		if (p2p->sd_peer->sd_pending_bcast_queries == 0)
+			p2p->sd_peer->sd_pending_bcast_queries = -1;
+	}
+
 	/* Wait for response from the peer */
 	p2p_set_state(p2p, P2P_SD_DURING_FIND);
 	p2p_set_timeout(p2p, 0, 200000);
@@ -3004,7 +3032,8 @@
 		 * make it less likely to hit cases where we could end up in
 		 * sync with peer not listening.
 		 */
-		os_get_random((u8 *) &r, sizeof(r));
+		if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+			r = 0;
 		timeout += r % 100000;
 	}
 	p2p_set_timeout(p2p, 0, timeout);
@@ -4076,6 +4105,13 @@
 }
 
 
+int p2p_config_get_random_social(struct p2p_config *p2p, u8 *op_class,
+				 u8 *op_channel)
+{
+	return p2p_channel_random_social(&p2p->channels, op_class, op_channel);
+}
+
+
 int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel,
 			   u8 forced)
 {
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index dee79df..076a2ac 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1691,6 +1691,20 @@
  */
 void p2p_set_managed_oper(struct p2p_data *p2p, int enabled);
 
+/**
+ * p2p_config_get_random_social - Return a random social channel
+ * @p2p: P2P config
+ * @op_class: Selected operating class
+ * @op_channel: Selected social channel
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is used before p2p_init is called. A random social channel
+ * from supports bands 2.4 GHz (channels 1,6,11) and 60 GHz (channel 2) is
+ * returned on success.
+ */
+int p2p_config_get_random_social(struct p2p_config *p2p, u8 *op_class,
+				 u8 *op_channel);
+
 int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel,
 			   u8 forced);
 
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index bd7a2cf..21fae3f 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -958,7 +958,10 @@
 			p2p_dbg(p2p, "Wait for the peer to become ready for GO Negotiation");
 			dev->flags |= P2P_DEV_NOT_YET_READY;
 			os_get_reltime(&dev->go_neg_wait_started);
-			p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
+			if (p2p->state == P2P_CONNECT_LISTEN)
+				p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
+			else
+				p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
 			p2p_set_timeout(p2p, 0, 0);
 		} else {
 			p2p_dbg(p2p, "Stop GO Negotiation attempt");
diff --git a/src/p2p/p2p_sd.c b/src/p2p/p2p_sd.c
index 6235b1d..13119c2 100644
--- a/src/p2p/p2p_sd.c
+++ b/src/p2p/p2p_sd.c
@@ -301,16 +301,6 @@
 		ret = -1;
 	}
 
-	/* Update the pending broadcast SD query count for this device */
-	dev->sd_pending_bcast_queries--;
-
-	/*
-	 * If there are no pending broadcast queries for this device, mark it as
-	 * done (-1).
-	 */
-	if (dev->sd_pending_bcast_queries == 0)
-		dev->sd_pending_bcast_queries = -1;
-
 	wpabuf_free(req);
 
 	return ret;
diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c
index 189300a..23acce7 100644
--- a/src/p2p/p2p_utils.c
+++ b/src/p2p/p2p_utils.c
@@ -149,6 +149,15 @@
 		return 0;
 	}
 
+	if (freq >= 58320 && freq <= 64800) {
+		if ((freq - 58320) % 2160)
+			return -1;
+
+		*op_class = 180; /* 60 GHz, channels 1..4 */
+		*channel = (freq - 56160) / 2160;
+		return 0;
+	}
+
 	return -1;
 }
 
@@ -441,7 +450,8 @@
 static u8 p2p_channel_pick_random(const u8 *channels, unsigned int num_channels)
 {
 	unsigned int r;
-	os_get_random((u8 *) &r, sizeof(r));
+	if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+		r = 0;
 	r %= num_channels;
 	return channels[r];
 }
@@ -481,7 +491,7 @@
 int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class,
 			      u8 *op_channel)
 {
-	u8 chan[3];
+	u8 chan[4];
 	unsigned int num_channels = 0;
 
 	/* Try to find available social channels from 2.4 GHz */
@@ -492,11 +502,18 @@
 	if (p2p_channels_includes(chans, 81, 11))
 		chan[num_channels++] = 11;
 
+	/* Try to find available social channels from 60 GHz */
+	if (p2p_channels_includes(chans, 180, 2))
+		chan[num_channels++] = 2;
+
 	if (num_channels == 0)
 		return -1;
 
-	*op_class = 81;
 	*op_channel = p2p_channel_pick_random(chan, num_channels);
+	if (*op_channel == 2)
+		*op_class = 180;
+	else
+		*op_class = 81;
 
 	return 0;
 }
diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c
index 56c195a..b1cf32d 100644
--- a/src/pae/ieee802_1x_kay.c
+++ b/src/pae/ieee802_1x_kay.c
@@ -1451,7 +1451,7 @@
 		os_memcpy(body->sak, cipher_suite_tbl[cs_index].id, CS_ID_LEN);
 		sak_pos = CS_ID_LEN;
 	}
-	if (aes_wrap(participant->kek.key,
+	if (aes_wrap(participant->kek.key, 16,
 		     cipher_suite_tbl[cs_index].sak_len / 8,
 		     sak->key, body->sak + sak_pos)) {
 		wpa_printf(MSG_ERROR, "KaY: AES wrap failed");
@@ -1611,7 +1611,7 @@
 		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
 		return -1;
 	}
-	if (aes_unwrap(participant->kek.key, sak_len >> 3, wrap_sak,
+	if (aes_unwrap(participant->kek.key, 16, sak_len >> 3, wrap_sak,
 		       unwrap_sak)) {
 		wpa_printf(MSG_ERROR, "KaY: AES unwrap failed");
 		os_free(unwrap_sak);
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
index 10056a6..e2766e2 100644
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -1080,19 +1080,23 @@
 	switch (nserv->addr.af) {
 	case AF_INET:
 		claddrlen = sizeof(claddr);
-		getsockname(sel_sock, (struct sockaddr *) &claddr, &claddrlen);
-		wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
-			   inet_ntoa(claddr.sin_addr), ntohs(claddr.sin_port));
+		if (getsockname(sel_sock, (struct sockaddr *) &claddr,
+				&claddrlen) == 0) {
+			wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
+				   inet_ntoa(claddr.sin_addr),
+				   ntohs(claddr.sin_port));
+		}
 		break;
 #ifdef CONFIG_IPV6
 	case AF_INET6: {
 		claddrlen = sizeof(claddr6);
-		getsockname(sel_sock, (struct sockaddr *) &claddr6,
-			    &claddrlen);
-		wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
-			   inet_ntop(AF_INET6, &claddr6.sin6_addr,
-				     abuf, sizeof(abuf)),
-			   ntohs(claddr6.sin6_port));
+		if (getsockname(sel_sock, (struct sockaddr *) &claddr6,
+				&claddrlen) == 0) {
+			wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
+				   inet_ntop(AF_INET6, &claddr6.sin6_addr,
+					     abuf, sizeof(abuf)),
+				   ntohs(claddr6.sin6_port));
+		}
 		break;
 	}
 #endif /* CONFIG_IPV6 */
diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c
index 24348a3..00394b4 100644
--- a/src/radius/radius_server.c
+++ b/src/radius/radius_server.c
@@ -1926,7 +1926,7 @@
 			if (inet_ntop(AF_INET6, &cli->addr6, abuf,
 				      sizeof(abuf)) == NULL)
 				abuf[0] = '\0';
-			if (inet_ntop(AF_INET6, &cli->mask6, abuf,
+			if (inet_ntop(AF_INET6, &cli->mask6, mbuf,
 				      sizeof(mbuf)) == NULL)
 				mbuf[0] = '\0';
 		}
@@ -2048,8 +2048,6 @@
 				sess = s;
 				break;
 			}
-			if (sess)
-				break;
 		}
 		if (sess)
 			break;
diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c
index b5a87fc..885291a 100644
--- a/src/rsn_supp/pmksa_cache.c
+++ b/src/rsn_supp/pmksa_cache.c
@@ -35,7 +35,7 @@
 
 static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
 {
-	os_free(entry);
+	bin_clear_free(entry, sizeof(*entry));
 }
 
 
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index cd34223..8cb19a2 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -218,26 +218,29 @@
 static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst,
 				 u8 action_code, u8 dialog_token,
 				 u16 status_code, u32 peer_capab,
-				 const u8 *buf, size_t len)
+				 int initiator, const u8 *buf, size_t len)
 {
 	return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token,
-				     status_code, peer_capab, buf, len);
+				     status_code, peer_capab, initiator, buf,
+				     len);
 }
 
 
 static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code,
 			     u8 dialog_token, u16 status_code, u32 peer_capab,
-			     const u8 *msg, size_t msg_len)
+			     int initiator, const u8 *msg, size_t msg_len)
 {
 	struct wpa_tdls_peer *peer;
 
 	wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u "
-		   "dialog_token=%u status_code=%u peer_capab=%u msg_len=%u",
+		   "dialog_token=%u status_code=%u peer_capab=%u initiator=%d "
+		   "msg_len=%u",
 		   MAC2STR(dest), action_code, dialog_token, status_code,
-		   peer_capab, (unsigned int) msg_len);
+		   peer_capab, initiator, (unsigned int) msg_len);
 
 	if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token,
-				  status_code, peer_capab, msg, msg_len)) {
+				  status_code, peer_capab, initiator, msg,
+				  msg_len)) {
 		wpa_printf(MSG_INFO, "TDLS: Failed to send message "
 			   "(action_code=%u)", action_code);
 		return -1;
@@ -333,6 +336,7 @@
 					  peer->sm_tmr.dialog_token,
 					  peer->sm_tmr.status_code,
 					  peer->sm_tmr.peer_capab,
+					  peer->initiator,
 					  peer->sm_tmr.buf,
 					  peer->sm_tmr.buf_len)) {
 			wpa_printf(MSG_INFO, "TDLS: Failed to retry "
@@ -793,7 +797,7 @@
 
 	/* request driver to send Teardown using this FTIE */
 	wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0,
-			  reason_code, 0, rbuf, pos - rbuf);
+			  reason_code, 0, peer->initiator, rbuf, pos - rbuf);
 	os_free(rbuf);
 
 	return 0;
@@ -968,17 +972,19 @@
  *	appropriate status code mentioning reason for error/failure.
  * @dst 	- MAC addr of Peer station
  * @tdls_action - TDLS frame type for which error code is sent
+ * @initiator   - was this end the initiator of the connection
  * @status 	- status code mentioning reason
  */
 
 static int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst,
-			       u8 tdls_action, u8 dialog_token, u16 status)
+			       u8 tdls_action, u8 dialog_token, int initiator,
+			       u16 status)
 {
 	wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR
 		   " (action=%u status=%u)",
 		   MAC2STR(dst), tdls_action, status);
 	return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status,
-				 0, NULL, 0);
+				 0, initiator, NULL, 0);
 }
 
 
@@ -1184,7 +1190,7 @@
 		   MAC2STR(peer->addr));
 
 	status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST,
-				   1, 0, 0, rbuf, pos - rbuf);
+				   1, 0, 0, peer->initiator, rbuf, pos - rbuf);
 	os_free(rbuf);
 
 	return status;
@@ -1274,7 +1280,8 @@
 
 skip_ies:
 	status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE,
-				   dtoken, 0, 0, rbuf, pos - rbuf);
+				   dtoken, 0, 0, peer->initiator, rbuf,
+				   pos - rbuf);
 	os_free(rbuf);
 
 	return status;
@@ -1371,7 +1378,8 @@
 		peer_capab |= TDLS_PEER_WMM;
 
 	status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM,
-				   dtoken, 0, peer_capab, rbuf, pos - rbuf);
+				   dtoken, 0, peer_capab, peer->initiator,
+				   rbuf, pos - rbuf);
 	os_free(rbuf);
 
 	return status;
@@ -1382,11 +1390,85 @@
 					    struct wpa_tdls_peer *peer,
 					    u8 dialog_token)
 {
+	size_t buf_len = 0;
+	struct wpa_tdls_timeoutie timeoutie;
+	u16 rsn_capab;
+	u8 *rbuf, *pos, *count_pos;
+	u16 count;
+	struct rsn_ie_hdr *hdr;
+	int status;
+
 	wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Discovery Response "
 		   "(peer " MACSTR ")", MAC2STR(peer->addr));
+	if (!wpa_tdls_get_privacy(sm))
+		goto skip_rsn_ies;
 
-	return wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
-				 dialog_token, 0, 0, NULL, 0);
+	/* Filling RSN IE */
+	hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
+	hdr->elem_id = WLAN_EID_RSN;
+	WPA_PUT_LE16(hdr->version, RSN_VERSION);
+	pos = (u8 *) (hdr + 1);
+	RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
+	pos += RSN_SELECTOR_LEN;
+	count_pos = pos;
+	pos += 2;
+	count = 0;
+
+	/*
+	* AES-CCMP is the default encryption preferred for TDLS, so
+	* RSN IE is filled only with CCMP cipher suite.
+	* Note: TKIP is not used to encrypt TDLS link.
+	*
+	* Regardless of the cipher used on the AP connection, select CCMP
+	* here.
+	*/
+	RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
+	pos += RSN_SELECTOR_LEN;
+	count++;
+	WPA_PUT_LE16(count_pos, count);
+	WPA_PUT_LE16(pos, 1);
+	pos += 2;
+	RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
+	pos += RSN_SELECTOR_LEN;
+
+	rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
+	rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
+	WPA_PUT_LE16(pos, rsn_capab);
+	pos += 2;
+	hdr->len = (pos - (u8 *) hdr) - 2;
+	peer->rsnie_i_len = pos - peer->rsnie_i;
+
+	wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for Discovery Response",
+		    (u8 *) hdr, hdr->len + 2);
+skip_rsn_ies:
+	buf_len = 0;
+	if (wpa_tdls_get_privacy(sm)) {
+		/* Peer RSN IE, Lifetime */
+		buf_len += peer->rsnie_i_len +
+			sizeof(struct wpa_tdls_timeoutie);
+	}
+	rbuf = os_zalloc(buf_len + 1);
+	if (rbuf == NULL) {
+		wpa_tdls_peer_free(sm, peer);
+		return -1;
+	}
+	pos = rbuf;
+
+	if (!wpa_tdls_get_privacy(sm))
+		goto skip_ies;
+	/* Initiator RSN IE */
+	pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
+	/* Lifetime */
+	peer->lifetime = TPK_LIFETIME;
+	pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
+				     sizeof(timeoutie), peer->lifetime);
+	wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
+skip_ies:
+	status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
+				   dialog_token, 0, 0, 0, rbuf, pos - rbuf);
+	os_free(rbuf);
+
+	return status;
 }
 
 
@@ -1454,7 +1536,7 @@
 	wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer "
 		   MACSTR, MAC2STR(addr));
 	return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST,
-				 1, 0, 0, NULL, 0);
+				 1, 0, 0, 1, NULL, 0);
 }
 
 
@@ -1639,8 +1721,8 @@
 				       peer->supp_rates, peer->supp_rates_len,
 				       peer->ht_capabilities,
 				       peer->vht_capabilities,
-				       peer->qos_info, peer->ext_capab,
-				       peer->ext_capab_len,
+				       peer->qos_info, peer->wmm_capable,
+				       peer->ext_capab, peer->ext_capab_len,
 				       peer->supp_channels,
 				       peer->supp_channels_len,
 				       peer->supp_oper_classes,
@@ -1743,7 +1825,7 @@
 	lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
 	if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
 		wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS");
-		status = WLAN_STATUS_NOT_IN_SAME_BSS;
+		status = WLAN_STATUS_REQUEST_DECLINED;
 		goto error;
 	}
 
@@ -1784,6 +1866,8 @@
 		wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of "
 			   "TDLS setup - send own request");
 		peer->initiator = 1;
+		wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
+					NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0);
 		wpa_tdls_send_tpk_m1(sm, peer);
 	}
 
@@ -1962,10 +2046,18 @@
 	wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
 
 skip_rsn_check:
+#ifdef CONFIG_TDLS_TESTING
+	if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT)
+		goto skip_add_peer;
+#endif /* CONFIG_TDLS_TESTING */
+
 	/* add supported rates, capabilities, and qos_info to the TDLS peer */
 	if (wpa_tdls_addset_peer(sm, peer, 1) < 0)
 		goto error;
 
+#ifdef CONFIG_TDLS_TESTING
+skip_add_peer:
+#endif /* CONFIG_TDLS_TESTING */
 	peer->tpk_in_progress = 1;
 
 	wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
@@ -1977,7 +2069,7 @@
 	return 0;
 
 error:
-	wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken,
+	wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0,
 			    status);
 	if (peer)
 		wpa_tdls_peer_free(sm, peer);
@@ -2288,7 +2380,7 @@
 	return ret;
 
 error:
-	wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken,
+	wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 1,
 			    status);
 	wpa_tdls_disable_peer_link(sm, peer);
 	return -1;
@@ -2513,7 +2605,7 @@
 
 	/* add the peer to the driver as a "setup in progress" peer */
 	if (wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
-				    NULL, 0, NULL, 0, NULL, 0, NULL, 0)) {
+				    NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0)) {
 		wpa_tdls_disable_peer_link(sm, peer);
 		return -1;
 	}
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index d6fb6a1..8f561b9 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -1295,7 +1295,8 @@
 				(unsigned long) maxkeylen);
 			return -1;
 		}
-		if (aes_unwrap(sm->ptk.kek, maxkeylen / 8, key_data, gd->gtk)) {
+		if (aes_unwrap(sm->ptk.kek, 16, maxkeylen / 8, key_data,
+			       gd->gtk)) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: AES unwrap failed - could not decrypt "
 				"GTK");
@@ -1503,7 +1504,7 @@
 				"WPA: No memory for AES-UNWRAP buffer");
 			return -1;
 		}
-		if (aes_unwrap(sm->ptk.kek, *key_data_len / 8,
+		if (aes_unwrap(sm->ptk.kek, 16, *key_data_len / 8,
 			       key_data, buf)) {
 			os_free(buf);
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 07a7bf9..63032b0 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -55,14 +55,14 @@
 	int (*send_tdls_mgmt)(void *ctx, const u8 *dst,
 			      u8 action_code, u8 dialog_token,
 			      u16 status_code, u32 peer_capab,
-			      const u8 *buf, size_t len);
+			      int initiator, const u8 *buf, size_t len);
 	int (*tdls_oper)(void *ctx, int oper, const u8 *peer);
 	int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add, u16 aid,
 				u16 capability, const u8 *supp_rates,
 				size_t supp_rates_len,
 				const struct ieee80211_ht_capabilities *ht_capab,
 				const struct ieee80211_vht_capabilities *vht_capab,
-				u8 qosinfo, const u8 *ext_capab,
+				u8 qosinfo, int wmm, const u8 *ext_capab,
 				size_t ext_capab_len, const u8 *supp_channels,
 				size_t supp_channels_len,
 				const u8 *supp_oper_classes,
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 4a75b92..3b3c9d0 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -566,7 +566,7 @@
 		return -1;
 	}
 	gtk_len = gtk_elem_len - 19;
-	if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk_elem + 11, gtk)) {
+	if (aes_unwrap(sm->ptk.kek, 16, gtk_len / 8, gtk_elem + 11, gtk)) {
 		wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
 			   "decrypt GTK");
 		return -1;
@@ -645,7 +645,8 @@
 		return -1;
 	}
 
-	if (aes_unwrap(sm->ptk.kek, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk)) {
+	if (aes_unwrap(sm->ptk.kek, 16, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk))
+	{
 		wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
 			   "decrypt IGTK");
 		return -1;
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index e20e9da..839b545 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -268,12 +268,14 @@
 static inline int wpa_sm_send_tdls_mgmt(struct wpa_sm *sm, const u8 *dst,
 					u8 action_code, u8 dialog_token,
 					u16 status_code, u32 peer_capab,
-					const u8 *buf, size_t len)
+					int initiator, const u8 *buf,
+					size_t len)
 {
 	if (sm->ctx->send_tdls_mgmt)
 		return sm->ctx->send_tdls_mgmt(sm->ctx->ctx, dst, action_code,
 					       dialog_token, status_code,
-					       peer_capab, buf, len);
+					       peer_capab, initiator, buf,
+					       len);
 	return -1;
 }
 
@@ -291,16 +293,16 @@
 			size_t supp_rates_len,
 			const struct ieee80211_ht_capabilities *ht_capab,
 			const struct ieee80211_vht_capabilities *vht_capab,
-			u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len,
-			const u8 *supp_channels, size_t supp_channels_len,
-			const u8 *supp_oper_classes,
+			u8 qosinfo, int wmm, const u8 *ext_capab,
+			size_t ext_capab_len, const u8 *supp_channels,
+			size_t supp_channels_len, const u8 *supp_oper_classes,
 			size_t supp_oper_classes_len)
 {
 	if (sm->ctx->tdls_peer_addset)
 		return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
 						 aid, capability, supp_rates,
 						 supp_rates_len, ht_capab,
-						 vht_capab, qosinfo,
+						 vht_capab, qosinfo, wmm,
 						 ext_capab, ext_capab_len,
 						 supp_channels,
 						 supp_channels_len,
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index 2329033..93e8cf6 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -549,7 +549,7 @@
 			ie->ht_capabilities_len = pos[1];
 		} else if (*pos == WLAN_EID_VHT_AID) {
 			if (pos[1] >= 2)
-				ie->aid = WPA_GET_LE16(pos + 2);
+				ie->aid = WPA_GET_LE16(pos + 2) & 0x3fff;
 		} else if (*pos == WLAN_EID_VHT_CAP) {
 			ie->vht_capabilities = pos + 2;
 			ie->vht_capabilities_len = pos[1];
diff --git a/src/utils/browser-android.c b/src/utils/browser-android.c
index a066392..d5ff5b5 100644
--- a/src/utils/browser-android.c
+++ b/src/utils/browser-android.c
@@ -75,7 +75,7 @@
 	os_memset(&data, 0, sizeof(data));
 
 	ret = os_snprintf(cmd, sizeof(cmd),
-			  "am start -a android.intent.action.VIEW -d '%s' "
+			  "start -a android.intent.action.VIEW -d %s "
 			  "-n com.android.browser/.BrowserActivity", url);
 	if (ret < 0 || (size_t) ret >= sizeof(cmd)) {
 		wpa_printf(MSG_ERROR, "Too long URL");
@@ -94,7 +94,7 @@
 		return -1;
 	}
 
-	if (system(cmd) != 0) {
+	if (os_exec("/system/bin/am", cmd, 1) != 0) {
 		wpa_printf(MSG_INFO, "Failed to launch Android browser");
 		eloop_cancel_timeout(browser_timeout, NULL, NULL);
 		http_server_deinit(http);
@@ -109,7 +109,7 @@
 	eloop_destroy();
 
 	wpa_printf(MSG_INFO, "Closing Android browser");
-	if (system("input keyevent 3") != 0) {
+	if (os_exec("/system/bin/input", "keyevent 3", 1) != 0) {
 		wpa_printf(MSG_INFO, "Failed to inject keyevent");
 	}
 
diff --git a/src/utils/browser-system.c b/src/utils/browser-system.c
index 2884d34..a080e2c 100644
--- a/src/utils/browser-system.c
+++ b/src/utils/browser-system.c
@@ -92,7 +92,7 @@
 		return -1;
 	}
 
-	if (system(cmd) != 0) {
+	if (os_exec("/usr/bin/x-www-browser", url, 0) != 0) {
 		wpa_printf(MSG_INFO, "Failed to launch browser");
 		eloop_cancel_timeout(browser_timeout, NULL, NULL);
 		http_server_deinit(http);
diff --git a/src/utils/browser-wpadebug.c b/src/utils/browser-wpadebug.c
index eeb8f65..ce3054b 100644
--- a/src/utils/browser-wpadebug.c
+++ b/src/utils/browser-wpadebug.c
@@ -76,7 +76,7 @@
 	os_memset(&data, 0, sizeof(data));
 
 	ret = os_snprintf(cmd, sizeof(cmd),
-			  "am start -a android.action.MAIN "
+			  "start -a android.action.MAIN "
 			  "-c android.intent.category.LAUNCHER "
 			  "-n w1.fi.wpadebug/.WpaWebViewActivity "
 			  "-e w1.fi.wpadebug.URL '%s'", url);
@@ -97,7 +97,7 @@
 		return -1;
 	}
 
-	if (system(cmd) != 0) {
+	if (os_exec("/system/bin/am", cmd, 1) != 0) {
 		wpa_printf(MSG_INFO, "Failed to launch wpadebug browser");
 		eloop_cancel_timeout(browser_timeout, NULL, NULL);
 		http_server_deinit(http);
@@ -112,10 +112,11 @@
 	eloop_destroy();
 
 	wpa_printf(MSG_INFO, "Closing Android browser");
-	if (system("am start -a android.action.MAIN "
-		   "-c android.intent.category.LAUNCHER "
-		   "-n w1.fi.wpadebug/.WpaWebViewActivity "
-		   "-e w1.fi.wpadebug.URL FINISH") != 0) {
+	if (os_exec("/system/bin/am",
+		    "start -a android.action.MAIN "
+		    "-c android.intent.category.LAUNCHER "
+		    "-n w1.fi.wpadebug/.WpaWebViewActivity "
+		    "-e w1.fi.wpadebug.URL FINISH", 1) != 0) {
 		wpa_printf(MSG_INFO, "Failed to close wpadebug browser");
 	}
 
diff --git a/src/utils/common.c b/src/utils/common.c
index 5b017e5..9902004 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -362,7 +362,7 @@
 			*txt++ = '\\';
 			*txt++ = '\\';
 			break;
-		case '\e':
+		case '\033':
 			*txt++ = '\\';
 			*txt++ = 'e';
 			break;
@@ -427,7 +427,7 @@
 				pos++;
 				break;
 			case 'e':
-				buf[len++] = '\e';
+				buf[len++] = '\033';
 				pos++;
 				break;
 			case 'x':
@@ -846,3 +846,23 @@
 		os_free(bin);
 	}
 }
+
+
+int random_mac_addr(u8 *addr)
+{
+	if (os_get_random(addr, ETH_ALEN) < 0)
+		return -1;
+	addr[0] &= 0xfe; /* unicast */
+	addr[0] |= 0x02; /* locally administered */
+	return 0;
+}
+
+
+int random_mac_addr_keep_oui(u8 *addr)
+{
+	if (os_get_random(addr + 3, 3) < 0)
+		return -1;
+	addr[0] &= 0xfe; /* unicast */
+	addr[0] |= 0x02; /* locally administered */
+	return 0;
+}
diff --git a/src/utils/common.h b/src/utils/common.h
index 2bc8fe1..14d9ad1 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -538,6 +538,9 @@
 void str_clear_free(char *str);
 void bin_clear_free(void *bin, size_t len);
 
+int random_mac_addr(u8 *addr);
+int random_mac_addr_keep_oui(u8 *addr);
+
 
 /*
  * gcc 4.4 ends up generating strict-aliasing warnings about some very common
diff --git a/src/utils/http_curl.c b/src/utils/http_curl.c
index eb79b86..0c18269 100644
--- a/src/utils/http_curl.c
+++ b/src/utils/http_curl.c
@@ -1099,7 +1099,6 @@
 				certs = NULL;
 			}
 			if (ctx->peer_issuer_issuer) {
-				X509 *cert;
 				cert = X509_dup(ctx->peer_issuer_issuer);
 				if (cert && !sk_X509_push(certs, cert)) {
 					tls_show_errors(
@@ -1178,9 +1177,10 @@
 
 	if (status == V_OCSP_CERTSTATUS_GOOD)
 		return 1;
-	if (status == V_OCSP_CERTSTATUS_REVOKED)
+	if (status == V_OCSP_CERTSTATUS_REVOKED) {
 		ctx->last_err = "Server certificate has been revoked";
 		return 0;
+	}
 	if (ctx->ocsp == MANDATORY_OCSP) {
 		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required");
 		ctx->last_err = "OCSP status unknown";
diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c
index f7d41b4..9f5a90c 100644
--- a/src/wps/wps_enrollee.c
+++ b/src/wps/wps_enrollee.c
@@ -175,6 +175,12 @@
 	}
 	wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
 
+	if (wps->wps->ap && random_pool_ready() != 1) {
+		wpa_printf(MSG_INFO,
+			   "WPS: Not enough entropy in random pool to proceed - do not allow AP PIN to be used");
+		return NULL;
+	}
+
 	msg = wpabuf_alloc(1000);
 	if (msg == NULL)
 		return NULL;
@@ -268,8 +274,12 @@
 		char hex[65];
 		u8 psk[32];
 		/* Generate a random per-device PSK */
-		if (random_get_bytes(psk, sizeof(psk)) < 0)
+		if (random_pool_ready() != 1 ||
+		    random_get_bytes(psk, sizeof(psk)) < 0) {
+			wpa_printf(MSG_INFO,
+				   "WPS: Could not generate random PSK");
 			return -1;
+		}
 		wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK",
 				psk, sizeof(psk));
 		wpa_printf(MSG_DEBUG, "WPS:  * Network Key (len=%u)",
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 00c8299..b90cc25 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -1640,8 +1640,12 @@
 	    !wps->wps->registrar->disable_auto_conf) {
 		u8 r[16];
 		/* Generate a random passphrase */
-		if (random_get_bytes(r, sizeof(r)) < 0)
+		if (random_pool_ready() != 1 ||
+		    random_get_bytes(r, sizeof(r)) < 0) {
+			wpa_printf(MSG_INFO,
+				   "WPS: Could not generate random PSK");
 			return -1;
+		}
 		os_free(wps->new_psk);
 		wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len);
 		if (wps->new_psk == NULL)
@@ -1674,7 +1678,10 @@
 		wps->new_psk = os_malloc(wps->new_psk_len);
 		if (wps->new_psk == NULL)
 			return -1;
-		if (random_get_bytes(wps->new_psk, wps->new_psk_len) < 0) {
+		if (random_pool_ready() != 1 ||
+		    random_get_bytes(wps->new_psk, wps->new_psk_len) < 0) {
+			wpa_printf(MSG_INFO,
+				   "WPS: Could not generate random PSK");
 			os_free(wps->new_psk);
 			wps->new_psk = NULL;
 			return -1;
diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog
index 5558a5e..f09e7a0 100644
--- a/wpa_supplicant/ChangeLog
+++ b/wpa_supplicant/ChangeLog
@@ -1,5 +1,70 @@
 ChangeLog for wpa_supplicant
 
+2014-10-09 - v2.3
+	* fixed number of minor issues identified in static analyzer warnings
+	* fixed wfd_dev_info to be more careful and not read beyond the buffer
+	  when parsing invalid information for P2P-DEVICE-FOUND
+	* extended P2P and GAS query operations to support drivers that have
+	  maximum remain-on-channel time below 1000 ms (500 ms is the current
+	  minimum supported value)
+	* added p2p_search_delay parameter to make the default p2p_find delay
+	  configurable
+	* improved P2P operating channel selection for various multi-channel
+	  concurrency cases
+	* fixed some TDLS failure cases to clean up driver state
+	* fixed dynamic interface addition cases with nl80211 to avoid adding
+	  ifindex values to incorrect interface to skip foreign interface events
+	  properly
+	* added TDLS workaround for some APs that may add extra data to the
+	  end of a short frame
+	* fixed EAP-AKA' message parser with multiple AT_KDF attributes
+	* added configuration option (p2p_passphrase_len) to allow longer
+	  passphrases to be generated for P2P groups
+	* fixed IBSS channel configuration in some corner cases
+	* improved HT/VHT/QoS parameter setup for TDLS
+	* modified D-Bus interface for P2P peers/groups
+	* started to use constant time comparison for various password and hash
+	  values to reduce possibility of any externally measurable timing
+	  differences
+	* extended explicit clearing of freed memory and expired keys to avoid
+	  keeping private data in memory longer than necessary
+	* added optional scan_id parameter to the SCAN command to allow manual
+	  scan requests for active scans for specific configured SSIDs
+	* fixed CTRL-EVENT-REGDOM-CHANGE event init parameter value
+	* added option to set Hotspot 2.0 Rel 2 update_identifier in network
+	  configuration to support external configuration
+	* modified Android PNO functionality to send Probe Request frames only
+	  for hidden SSIDs (based on scan_ssid=1)
+	* added generic mechanism for adding vendor elements into frames at
+	  runtime (VENDOR_ELEM_ADD, VENDOR_ELEM_GET, VENDOR_ELEM_REMOVE)
+	* added fields to show unrecognized vendor elements in P2P_PEER
+	* removed EAP-TTLS/MSCHAPv2 interoperability workaround so that
+	  MS-CHAP2-Success is required to be present regardless of
+	  eap_workaround configuration
+	* modified EAP fast session resumption to allow results to be used only
+	  with the same network block that generated them
+	* extended freq_list configuration to apply for sched_scan as well as
+	  normal scan
+	* modified WPS to merge mixed-WPA/WPA2 credentials from a single session
+	* fixed nl80211/RTM_DELLINK processing when a P2P GO interface is
+	  removed from a bridge
+	* fixed number of small P2P issues to make negotiations more robust in
+	  corner cases
+	* added experimental support for using temporary, random local MAC
+	  address (mac_addr and preassoc_mac_addr parameters); this is disabled
+	  by default (i.e., previous behavior of using permanent address is
+	  maintained if configuration is not changed)
+	* added D-Bus interface for setting/clearing WFD IEs
+	* fixed TDLS AID configuration for VHT
+	* modified -m<conf> configuration file to be used only for the P2P
+	  non-netdev management device and do not load this for the default
+	  station interface or load the station interface configuration for
+	  the P2P management interface
+	* fixed external MAC address changes while wpa_supplicant is running
+	* started to enable HT (if supported by the driver) for IBSS
+	* fixed wpa_cli action script execution to use more robust mechanism
+	  (CVE-2014-3686)
+
 2014-06-04 - v2.2
 	* added DFS indicator to get_capability freq
 	* added/fixed nl80211 functionality
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index f9aa807..7c93498 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -513,7 +513,7 @@
 	}
 	if (ssid->frequency == 0)
 		ssid->frequency = 2462; /* default channel 11 */
-	params.freq = ssid->frequency;
+	params.freq.freq = ssid->frequency;
 
 	params.wpa_proto = ssid->proto;
 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index f99a8a7..1de51e5 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -174,6 +174,31 @@
 }
 
 
+static void wpa_bss_update_pending_connect(struct wpa_supplicant *wpa_s,
+					   struct wpa_bss *old_bss,
+					   struct wpa_bss *new_bss)
+{
+	struct wpa_radio_work *work;
+	struct wpa_connect_work *cwork;
+
+	work = radio_work_pending(wpa_s, "sme-connect");
+	if (!work)
+		work = radio_work_pending(wpa_s, "connect");
+	if (!work)
+		return;
+
+	cwork = work->ctx;
+	if (cwork->bss != old_bss)
+		return;
+
+	wpa_printf(MSG_DEBUG,
+		   "Update BSS pointer for the pending connect radio work");
+	cwork->bss = new_bss;
+	if (!new_bss)
+		cwork->bss_removed = 1;
+}
+
+
 static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
 			   const char *reason)
 {
@@ -190,6 +215,7 @@
 			}
 		}
 	}
+	wpa_bss_update_pending_connect(wpa_s, bss, NULL);
 	dl_list_del(&bss->list);
 	dl_list_del(&bss->list_id);
 	wpa_s->num_bss--;
@@ -489,6 +515,8 @@
 
 	if (changes & WPA_BSS_RATES_CHANGED_FLAG)
 		wpas_notify_bss_rates_changed(wpa_s, bss->id);
+
+	wpas_notify_bss_seen(wpa_s, bss->id);
 }
 
 
@@ -541,6 +569,7 @@
 			}
 			if (wpa_s->current_bss == bss)
 				wpa_s->current_bss = nbss;
+			wpa_bss_update_pending_connect(wpa_s, bss, nbss);
 			bss = nbss;
 			os_memcpy(bss + 1, res + 1,
 				  res->ie_len + res->beacon_ie_len);
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 8cd4a2f..b7f259b 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1754,6 +1754,7 @@
 #ifdef CONFIG_HS20
 	{ INT(update_identifier) },
 #endif /* CONFIG_HS20 */
+	{ INT_RANGE(mac_addr, 0, 2) },
 };
 
 #undef OFFSET
@@ -2211,6 +2212,7 @@
 #ifdef CONFIG_IEEE80211W
 	ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
 #endif /* CONFIG_IEEE80211W */
+	ssid->mac_addr = -1;
 }
 
 
@@ -3287,6 +3289,7 @@
 	config->wmm_ac_params[2] = ac_vi;
 	config->wmm_ac_params[3] = ac_vo;
 	config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY;
+	config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
 
 	if (ctrl_interface)
 		config->ctrl_interface = os_strdup(ctrl_interface);
@@ -3909,6 +3912,9 @@
 	{ STR(osu_dir), 0 },
 	{ STR(wowlan_triggers), 0 },
 	{ INT(p2p_search_delay), 0},
+	{ INT(mac_addr), 0 },
+	{ INT(rand_addr_lifetime), 0 },
+	{ INT(preassoc_mac_addr), 0 },
 };
 
 #undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 52add9d..3fd4192 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -27,6 +27,7 @@
 #define DEFAULT_ACCESS_NETWORK_TYPE 15
 #define DEFAULT_SCAN_CUR_FREQ 0
 #define DEFAULT_P2P_SEARCH_DELAY 500
+#define DEFAULT_RAND_ADDR_LIFETIME 60
 
 #include "config_ssid.h"
 #include "wps/wps.h"
@@ -1051,6 +1052,33 @@
 	 * resources.
 	 */
 	unsigned int p2p_search_delay;
+
+	/**
+	 * mac_addr - MAC address policy default
+	 *
+	 * 0 = use permanent MAC address
+	 * 1 = use random MAC address for each ESS connection
+	 * 2 = like 1, but maintain OUI (with local admin bit set)
+	 *
+	 * By default, permanent MAC address is used unless policy is changed by
+	 * the per-network mac_addr parameter. Global mac_addr=1 can be used to
+	 * change this default behavior.
+	 */
+	int mac_addr;
+
+	/**
+	 * rand_addr_lifetime - Lifetime of random MAC address in seconds
+	 */
+	unsigned int rand_addr_lifetime;
+
+	/**
+	 * preassoc_mac_addr - Pre-association MAC address policy
+	 *
+	 * 0 = use permanent MAC address
+	 * 1 = use random MAC address
+	 * 2 = like 1, but maintain OUI (with local admin bit set)
+	 */
+	int preassoc_mac_addr;
 };
 
 
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 73ad57a..ef909a1 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -20,6 +20,9 @@
 #include "eap_peer/eap_methods.h"
 #include "eap_peer/eap.h"
 
+#ifdef ANDROID
+#include <sys/stat.h>
+#endif
 
 static int newline_terminated(const char *buf, size_t buflen)
 {
@@ -742,6 +745,7 @@
 #ifdef CONFIG_HS20
 	INT(update_identifier);
 #endif /* CONFIG_HS20 */
+	write_int(f, "mac_addr", ssid->mac_addr, -1);
 
 #undef STR
 #undef INT
@@ -1179,6 +1183,16 @@
 	if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY)
 		fprintf(f, "p2p_search_delay=%u\n",
 			config->p2p_search_delay);
+
+	if (config->mac_addr)
+		fprintf(f, "mac_addr=%d\n", config->mac_addr);
+
+	if (config->rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME)
+		fprintf(f, "rand_addr_lifetime=%u\n",
+			config->rand_addr_lifetime);
+
+	if (config->preassoc_mac_addr)
+		fprintf(f, "preassoc_mac_addr=%d\n", config->preassoc_mac_addr);
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
@@ -1194,12 +1208,21 @@
 	struct wpa_config_blob *blob;
 #endif /* CONFIG_NO_CONFIG_BLOBS */
 	int ret = 0;
+	int tmp_len = os_strlen(name) + 5;       /* allow space for .tmp suffix */
+	char *tmp_name = os_malloc(tmp_len);
 
-	wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name);
+	if (tmp_name == NULL)
+		tmp_name = (char *)name;
+	else
+		os_snprintf(tmp_name, tmp_len, "%s.tmp", name);
 
-	f = fopen(name, "w");
+	wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", tmp_name);
+
+	f = fopen(tmp_name, "w");
 	if (f == NULL) {
-		wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name);
+		wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", tmp_name);
+		if (tmp_name != name)
+			os_free(tmp_name);
 		return -1;
 	}
 
@@ -1234,6 +1257,17 @@
 
 	fclose(f);
 
+	if (tmp_name != name) {
+		int chmod_ret = 0;
+#ifdef ANDROID
+		chmod_ret = chmod(tmp_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+#endif
+		if (chmod_ret != 0 || rename(tmp_name, name) != 0)
+			ret = -1;
+
+		os_free(tmp_name);
+	}
+
 	wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully",
 		   name, ret ? "un" : "");
 	return ret;
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index ab474ff..f50b2d4 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -651,6 +651,21 @@
 #ifdef CONFIG_HS20
 	int update_identifier;
 #endif /* CONFIG_HS20 */
+
+	unsigned int wps_run;
+
+	/**
+	 * mac_addr - MAC address policy
+	 *
+	 * 0 = use permanent MAC address
+	 * 1 = use random MAC address for each ESS connection
+	 * 2 = like 1, but maintain OUI (with local admin bit set)
+	 *
+	 * Internally, special value -1 is used to indicate that the parameter
+	 * was not specified in the configuration (i.e., default behavior is
+	 * followed).
+	 */
+	int mac_addr;
 };
 
 #endif /* CONFIG_SSID_H */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 79806d9..a4c26e4 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -41,6 +41,7 @@
 #include "autoscan.h"
 #include "wnm_sta.h"
 #include "offchannel.h"
+#include "drivers/driver.h"
 
 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
 					    char *buf, int len);
@@ -1539,6 +1540,11 @@
 		if (ret < 0 || ret >= end - pos)
 			return pos - buf;
 		pos += ret;
+		ret = os_snprintf(pos, end - pos, "freq=%u\n",
+				  wpa_s->assoc_freq);
+		if (ret < 0 || ret >= end - pos)
+			return pos - buf;
+		pos += ret;
 		if (ssid) {
 			u8 *_ssid = ssid->ssid;
 			size_t ssid_len = ssid->ssid_len;
@@ -1976,9 +1982,9 @@
 
 
 static int wpa_supplicant_ctrl_iface_list_networks(
-	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
+	struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
 {
-	char *pos, *end;
+	char *pos, *end, *prev;
 	struct wpa_ssid *ssid;
 	int ret;
 
@@ -1991,12 +1997,24 @@
 	pos += ret;
 
 	ssid = wpa_s->conf->ssid;
+
+	/* skip over ssids until we find next one */
+	if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
+		int last_id = atoi(cmd + 8);
+		if (last_id != -1) {
+			while (ssid != NULL && ssid->id <= last_id) {
+				ssid = ssid->next;
+			}
+		}
+	}
+
 	while (ssid) {
+		prev = pos;
 		ret = os_snprintf(pos, end - pos, "%d\t%s",
 				  ssid->id,
 				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
 		if (ret < 0 || ret >= end - pos)
-			return pos - buf;
+			return prev - buf;
 		pos += ret;
 		if (ssid->bssid_set) {
 			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
@@ -2005,7 +2023,7 @@
 			ret = os_snprintf(pos, end - pos, "\tany");
 		}
 		if (ret < 0 || ret >= end - pos)
-			return pos - buf;
+			return prev - buf;
 		pos += ret;
 		ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
 				  ssid == wpa_s->current_ssid ?
@@ -2016,11 +2034,11 @@
 				  ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
 				  "");
 		if (ret < 0 || ret >= end - pos)
-			return pos - buf;
+			return prev - buf;
 		pos += ret;
 		ret = os_snprintf(pos, end - pos, "\n");
 		if (ret < 0 || ret >= end - pos)
-			return pos - buf;
+			return prev - buf;
 		pos += ret;
 
 		ssid = ssid->next;
@@ -2479,6 +2497,8 @@
 			struct wpa_ssid *remove_ssid = ssid;
 			id = ssid->id;
 			ssid = ssid->next;
+			if (wpa_s->last_ssid == remove_ssid)
+				wpa_s->last_ssid = NULL;
 			wpas_notify_network_removed(wpa_s, remove_ssid);
 			wpa_config_remove_network(wpa_s->conf, id);
 		}
@@ -2497,6 +2517,9 @@
 		return -1;
 	}
 
+	if (wpa_s->last_ssid == ssid)
+		wpa_s->last_ssid = NULL;
+
 	if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
 #ifdef CONFIG_SME
 		wpa_s->sme.prev_bssid_set = 0;
@@ -2571,9 +2594,10 @@
 static int wpa_supplicant_ctrl_iface_set_network(
 	struct wpa_supplicant *wpa_s, char *cmd)
 {
-	int id;
+	int id, ret, prev_bssid_set;
 	struct wpa_ssid *ssid;
 	char *name, *value;
+	u8 prev_bssid[ETH_ALEN];
 
 	/* cmd: "<network id> <variable name> <value>" */
 	name = os_strchr(cmd, ' ');
@@ -2599,8 +2623,15 @@
 		return -1;
 	}
 
-	return wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
-							value);
+	prev_bssid_set = ssid->bssid_set;
+	os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
+	ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
+						       value);
+	if (ret == 0 &&
+	    (ssid->bssid_set != prev_bssid_set ||
+	     os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0))
+		wpas_notify_network_bssid_set_changed(wpa_s, ssid);
+	return ret;
 }
 
 
@@ -5545,28 +5576,6 @@
 #endif /* CONFIG_WNM */
 
 
-/* Get string representation of channel width */
-static const char * channel_width_name(enum chan_width width)
-{
-	switch (width) {
-	case CHAN_WIDTH_20_NOHT:
-		return "20 MHz (no HT)";
-	case CHAN_WIDTH_20:
-		return "20 MHz";
-	case CHAN_WIDTH_40:
-		return "40 MHz";
-	case CHAN_WIDTH_80:
-		return "80 MHz";
-	case CHAN_WIDTH_80P80:
-		return "80+80 MHz";
-	case CHAN_WIDTH_160:
-		return "160 MHz";
-	default:
-		return "unknown";
-	}
-}
-
-
 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
 				      size_t buflen)
 {
@@ -5591,7 +5600,7 @@
 
 	if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
 		ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
-				  channel_width_name(si.chanwidth));
+				  channel_width_to_string(si.chanwidth));
 		if (ret < 0 || ret > end - pos)
 			return -1;
 		pos += ret;
@@ -6440,7 +6449,7 @@
 			wpa_s->vendor_elem[frame] = NULL;
 		} else {
 			os_memmove(ie, ie + len,
-				   wpabuf_len(wpa_s->vendor_elem[frame]) - len);
+				   end - (ie + len));
 			wpa_s->vendor_elem[frame]->used -= len;
 		}
 		os_free(buf);
@@ -6520,6 +6529,8 @@
 	} else if (os_strcmp(buf, "PMKSA") == 0) {
 		reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
 						    reply_size);
+	} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
+		wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
 	} else if (os_strncmp(buf, "SET ", 4) == 0) {
 		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
 			reply_len = -1;
@@ -6837,9 +6848,12 @@
 	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_log_level(
 			wpa_s, buf + 9, reply, reply_size);
+	} else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
+		reply_len = wpa_supplicant_ctrl_iface_list_networks(
+			wpa_s, buf + 14, reply, reply_size);
 	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_list_networks(
-			wpa_s, reply, reply_size);
+			wpa_s, NULL, reply, reply_size);
 	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
 #ifdef CONFIG_SME
 		wpa_s->sme.prev_bssid_set = 0;
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index e9f6589..5e58c5b 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -1960,6 +1960,9 @@
 	case WPAS_DBUS_BSS_PROP_IES:
 		prop = "IEs";
 		break;
+	case WPAS_DBUS_BSS_PROP_AGE:
+		prop = "Age";
+		break;
 	default:
 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
 			   __func__, property);
@@ -2094,6 +2097,12 @@
 	  wpas_dbus_getter_global_capabilities,
 	  NULL
 	},
+#ifdef CONFIG_WIFI_DISPLAY
+	{ "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
+	  wpas_dbus_getter_global_wfd_ies,
+	  wpas_dbus_setter_global_wfd_ies
+	},
+#endif /* CONFIG_WIFI_DISPLAY */
 	{ NULL, NULL, NULL, NULL, NULL }
 };
 
@@ -2384,6 +2393,10 @@
 	  wpas_dbus_getter_bss_ies,
 	  NULL
 	},
+	{ "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
+	  wpas_dbus_getter_bss_age,
+	  NULL
+	},
 	{ NULL, NULL, NULL, NULL, NULL }
 };
 
@@ -2518,6 +2531,13 @@
 		  END_ARGS
 	  }
 	},
+	{ "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_signal_poll,
+	  {
+		  { "args", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
 	  (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
 	  {
@@ -2941,6 +2961,10 @@
 	  wpas_dbus_getter_process_credentials,
 	  wpas_dbus_setter_process_credentials
 	},
+	{ "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
+	  wpas_dbus_getter_config_methods,
+	  wpas_dbus_setter_config_methods
+	},
 #endif /* CONFIG_WPS */
 #ifdef CONFIG_P2P
 	{ "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 881d351..5f32bbf 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -41,6 +41,7 @@
 	WPAS_DBUS_BSS_PROP_RSN,
 	WPAS_DBUS_BSS_PROP_WPS,
 	WPAS_DBUS_BSS_PROP_IES,
+	WPAS_DBUS_BSS_PROP_AGE,
 };
 
 #define WPAS_DBUS_OBJECT_PATH_MAX 150
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index 6dc5f76..9f6c4a3 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -27,6 +27,7 @@
 #include "dbus_new_handlers.h"
 #include "dbus_dict_helpers.h"
 #include "dbus_common_i.h"
+#include "drivers/driver.h"
 
 static const char *debug_strings[] = {
 	"excessive", "msgdump", "debug", "info", "warning", "error", NULL
@@ -1401,6 +1402,88 @@
 }
 
 
+/**
+ * wpas_dbus_handler_signal_poll - Request immediate signal properties
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL indicating success or DBus error message on failure
+ *
+ * Handler function for "SignalPoll" method call of a network device. Requests
+ * that wpa_supplicant read signal properties like RSSI, noise, and link
+ * speed and return them.
+ */
+DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
+					    struct wpa_supplicant *wpa_s)
+{
+	struct wpa_signal_info si;
+	DBusMessage *reply = NULL;
+	DBusMessageIter iter, iter_dict, variant_iter;
+	int ret;
+
+	ret = wpa_drv_signal_poll(wpa_s, &si);
+	if (ret) {
+		return dbus_message_new_error(message, DBUS_ERROR_FAILED,
+					      "Failed to read signal");
+	}
+
+	reply = dbus_message_new_method_return(message);
+	if (reply == NULL)
+		goto nomem;
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
+					      "a{sv}", &variant_iter))
+		goto nomem;
+	if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
+		goto nomem;
+
+	if (!wpa_dbus_dict_append_int32(&iter_dict, "rssi", si.current_signal))
+		goto nomem;
+	if (!wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
+					si.current_txrate / 1000))
+		goto nomem;
+	if (!wpa_dbus_dict_append_int32(&iter_dict, "noise", si.current_noise))
+		goto nomem;
+	if (!wpa_dbus_dict_append_uint32(&iter_dict, "frequency", si.frequency))
+		goto nomem;
+
+	if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
+		if (!wpa_dbus_dict_append_string(&iter_dict, "width",
+					channel_width_to_string(si.chanwidth)))
+			goto nomem;
+	}
+
+	if (si.center_frq1 > 0 && si.center_frq2 > 0) {
+		if (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
+						si.center_frq1))
+			goto nomem;
+		if (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
+						si.center_frq2))
+			goto nomem;
+	}
+
+	if (si.avg_signal) {
+		if (!wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
+						si.avg_signal))
+			goto nomem;
+	}
+
+	if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
+		goto nomem;
+	if (!dbus_message_iter_close_container(&iter, &variant_iter))
+		goto nomem;
+
+	return reply;
+
+nomem:
+	if (reply)
+		dbus_message_unref(reply);
+	reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
+	return reply;
+}
+
+
 /*
  * wpas_dbus_handler_disconnect - Terminate the current connection
  * @message: Pointer to incoming dbus message
@@ -3955,6 +4038,35 @@
 
 
 /**
+ * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for BSS age
+ */
+dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
+				     void *user_data)
+{
+	struct bss_handler_args *args = user_data;
+	struct wpa_bss *res;
+	struct os_reltime now, diff = { 0, 0 };
+	u32 age;
+
+	res = get_bss_helper(args, error, __func__);
+	if (!res)
+		return FALSE;
+
+	os_get_reltime(&now);
+	os_reltime_sub(&now, &res->last_update, &diff);
+	age = diff.sec > 0 ? diff.sec : 0;
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
+						error);
+}
+
+
+/**
  * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
  * @iter: Pointer to incoming dbus message iter
  * @error: Location to store error on failure
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index 461970d..f6a83cd 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -87,6 +87,9 @@
 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
 				     struct wpa_supplicant *wpa_s);
 
+DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
+					    struct wpa_supplicant *wpa_s);
+
 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
 					   struct wpa_supplicant *wpa_s);
 
@@ -268,6 +271,9 @@
 dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
 				     void *user_data);
 
+dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
+				     void *user_data);
+
 dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
 				     void *user_data);
 
@@ -292,6 +298,14 @@
 						 DBusError *error,
 						 void *user_data);
 
+dbus_bool_t wpas_dbus_getter_config_methods(DBusMessageIter *iter,
+					    DBusError *error,
+					    void *user_data);
+
+dbus_bool_t wpas_dbus_setter_config_methods(DBusMessageIter *iter,
+					    DBusError *error,
+					    void *user_data);
+
 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
 					      struct wpa_supplicant *wpa_s);
 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index c9ecc7b..7867f0c 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -26,6 +26,7 @@
 #include "ap/wps_hostapd.h"
 
 #include "../p2p_supplicant.h"
+#include "../wifi_display.h"
 
 /**
  * Parses out the mac address from the peer object path.
@@ -2589,3 +2590,77 @@
 	return NULL;
 
 }
+
+
+#ifdef CONFIG_WIFI_DISPLAY
+
+dbus_bool_t wpas_dbus_getter_global_wfd_ies(DBusMessageIter *iter,
+					    DBusError *error, void *user_data)
+{
+	struct wpa_global *global = user_data;
+	struct wpabuf *ie;
+	dbus_bool_t ret;
+
+	ie = wifi_display_get_wfd_ie(global);
+	if (ie == NULL)
+		return wpas_dbus_simple_array_property_getter(iter,
+							      DBUS_TYPE_BYTE,
+							      NULL, 0, error);
+
+	ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
+						     wpabuf_head(ie),
+						     wpabuf_len(ie), error);
+	wpabuf_free(ie);
+
+	return ret;
+}
+
+
+dbus_bool_t wpas_dbus_setter_global_wfd_ies(DBusMessageIter *iter,
+					    DBusError *error, void *user_data)
+{
+	struct wpa_global *global = user_data;
+	DBusMessageIter variant, array;
+	struct wpabuf *ie = NULL;
+	const u8 *data;
+	int len;
+
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
+		goto err;
+
+	dbus_message_iter_recurse(iter, &variant);
+	if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
+		goto err;
+
+	dbus_message_iter_recurse(&variant, &array);
+	dbus_message_iter_get_fixed_array(&array, &data, &len);
+	if (len == 0) {
+		wifi_display_enable(global, 0);
+		wifi_display_deinit(global);
+
+		return TRUE;
+	}
+
+	ie = wpabuf_alloc(len);
+	if (ie == NULL)
+		goto err;
+
+	wpabuf_put_data(ie, data, len);
+	if (wifi_display_subelem_set_from_ies(global, ie) != 0)
+		goto err;
+
+	if (global->wifi_display == 0)
+		wifi_display_enable(global, 1);
+
+	wpabuf_free(ie);
+
+	return TRUE;
+err:
+	wpabuf_free(ie);
+
+	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
+			     "invalid message format");
+	return FALSE;
+}
+
+#endif /* CONFIG_WIFI_DISPLAY */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
index 67dbfc9..6e67c89 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
@@ -210,5 +210,16 @@
 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
 	DBusMessage *message, struct wpa_supplicant *wpa_s);
 
+#ifdef CONFIG_WIFI_DISPLAY
+
+dbus_bool_t wpas_dbus_getter_global_wfd_ies(DBusMessageIter *iter,
+					    DBusError *error,
+					    void *user_data);
+
+dbus_bool_t wpas_dbus_setter_global_wfd_ies(DBusMessageIter *iter,
+					    DBusError *error,
+					    void *user_data);
+
+#endif /* CONFIG_WIFI_DISPLAY */
 
 #endif /* DBUS_NEW_HANDLERS_P2P_H */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_wps.c b/wpa_supplicant/dbus/dbus_new_handlers_wps.c
index 4ad5e7e..8ecf7db 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_wps.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_wps.c
@@ -389,3 +389,60 @@
 
 	return TRUE;
 }
+
+
+/**
+ * wpas_dbus_getter_config_methods - Get current WPS configuration methods
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "ConfigMethods" property. Returned boolean will be true if
+ * providing the relevant string worked, or false otherwise.
+ */
+dbus_bool_t wpas_dbus_getter_config_methods(DBusMessageIter *iter,
+					    DBusError *error,
+					    void *user_data)
+{
+	struct wpa_supplicant *wpa_s = user_data;
+	char *methods = wpa_s->conf->config_methods;
+
+	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
+						&methods, error);
+}
+
+
+/**
+ * wpas_dbus_setter_config_methods - Set WPS configuration methods
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Setter for "ConfigMethods" property. Sets the methods string, apply such
+ * change and returns true on success. Returns false otherwise.
+ */
+dbus_bool_t wpas_dbus_setter_config_methods(DBusMessageIter *iter,
+					    DBusError *error,
+					    void *user_data)
+{
+	struct wpa_supplicant *wpa_s = user_data;
+	char *methods, *new_methods;
+
+	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
+					      &methods))
+		return FALSE;
+
+	new_methods = os_strdup(methods);
+	if (!new_methods)
+		return FALSE;
+
+	os_free(wpa_s->conf->config_methods);
+	wpa_s->conf->config_methods = new_methods;
+
+	wpa_s->conf->changed_parameters |= CFG_CHANGED_CONFIG_METHODS;
+	wpa_supplicant_update_config(wpa_s);
+
+	return TRUE;
+}
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 00703d9..649de9b 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -532,14 +532,14 @@
 static inline int wpa_drv_send_tdls_mgmt(struct wpa_supplicant *wpa_s,
 					 const u8 *dst, u8 action_code,
 					 u8 dialog_token, u16 status_code,
-					 u32 peer_capab, const u8 *buf,
-					 size_t len)
+					 u32 peer_capab, int initiator,
+					 const u8 *buf, size_t len)
 {
 	if (wpa_s->driver->send_tdls_mgmt) {
 		return wpa_s->driver->send_tdls_mgmt(wpa_s->drv_priv, dst,
 						     action_code, dialog_token,
 						     status_code, peer_capab,
-						     buf, len);
+						     initiator, buf, len);
 	}
 	return -1;
 }
@@ -632,6 +632,22 @@
 					 data, data_len, buf);
 }
 
+static inline int wpa_drv_roaming(struct wpa_supplicant *wpa_s, int allowed,
+				  const u8 *bssid)
+{
+	if (!wpa_s->driver->roaming)
+		return -1;
+	return wpa_s->driver->roaming(wpa_s->drv_priv, allowed, bssid);
+}
+
+static inline int wpa_drv_set_mac_addr(struct wpa_supplicant *wpa_s,
+				       const u8 *addr)
+{
+	if (!wpa_s->driver->set_mac_addr)
+		return -1;
+	return wpa_s->driver->set_mac_addr(wpa_s->drv_priv, addr);
+}
+
 
 #ifdef CONFIG_MACSEC
 
diff --git a/wpa_supplicant/eap_proxy_dummy.mak b/wpa_supplicant/eap_proxy_dummy.mak
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wpa_supplicant/eap_proxy_dummy.mak
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index ba9e083..985fa6e 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -582,7 +582,7 @@
 }
 
 
-static int ht_supported(const struct hostapd_hw_modes *mode)
+int ht_supported(const struct hostapd_hw_modes *mode)
 {
 	if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) {
 		/*
@@ -600,7 +600,7 @@
 }
 
 
-static int vht_supported(const struct hostapd_hw_modes *mode)
+int vht_supported(const struct hostapd_hw_modes *mode)
 {
 	if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) {
 		/*
@@ -2163,10 +2163,12 @@
 	}
 	if (!wpa_s->disconnected &&
 	    (!wpa_s->auto_reconnect_disabled ||
-	     wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)) {
+	     wpa_s->key_mgmt == WPA_KEY_MGMT_WPS ||
+	     wpas_wps_searching(wpa_s))) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect enabled: try to "
-			"reconnect (wps=%d wpa_state=%d)",
+			"reconnect (wps=%d/%d wpa_state=%d)",
 			wpa_s->key_mgmt == WPA_KEY_MGMT_WPS,
+			wpas_wps_searching(wpa_s),
 			wpa_s->wpa_state);
 		if (wpa_s->wpa_state == WPA_COMPLETED &&
 		    wpa_s->current_ssid &&
@@ -2998,15 +3000,17 @@
 			wpa_s->own_scan_running = 1;
 			if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
 			    wpa_s->manual_scan_use_id) {
-				wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED "id=%u",
-					wpa_s->manual_scan_id);
+				wpa_msg_ctrl(wpa_s, MSG_INFO,
+					     WPA_EVENT_SCAN_STARTED "id=%u",
+					     wpa_s->manual_scan_id);
 			} else {
-				wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
+				wpa_msg_ctrl(wpa_s, MSG_INFO,
+					     WPA_EVENT_SCAN_STARTED);
 			}
 		} else {
 			wpa_dbg(wpa_s, MSG_DEBUG, "External program started a scan");
 			wpa_s->external_scan_running = 1;
-			wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
+			wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
 		}
 		break;
 	case EVENT_SCAN_RESULTS:
diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c
index 3986268..3a89674 100644
--- a/wpa_supplicant/gas_query.c
+++ b/wpa_supplicant/gas_query.c
@@ -597,6 +597,7 @@
 {
 	struct gas_query_pending *query = work->ctx;
 	struct gas_query *gas = query->gas;
+	struct wpa_supplicant *wpa_s = gas->wpa_s;
 
 	if (deinit) {
 		if (work->started) {
@@ -609,6 +610,14 @@
 		return;
 	}
 
+	if (wpas_update_random_addr_disassoc(wpa_s) < 0) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"Failed to assign random MAC address for GAS");
+		gas_query_free(query, 1);
+		radio_work_done(work);
+		return;
+	}
+
 	gas->work = work;
 
 	if (gas_query_tx(gas, query, query->req) < 0) {
diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c
index d2e839d..e596468 100644
--- a/wpa_supplicant/main.c
+++ b/wpa_supplicant/main.c
@@ -331,7 +331,8 @@
 		if (wpa_s->global->p2p == NULL &&
 		    (wpa_s->drv_flags &
 		     WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
-		    wpas_p2p_add_p2pdev_interface(wpa_s) < 0)
+		    wpas_p2p_add_p2pdev_interface(wpa_s, iface->conf_p2p_dev) <
+		    0)
 			exitcode = -1;
 #endif /* CONFIG_P2P */
 	}
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 3b730cf..617ce84 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -345,6 +345,12 @@
 }
 
 
+void wpas_notify_bss_seen(struct wpa_supplicant *wpa_s, unsigned int id)
+{
+	wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_AGE, id);
+}
+
+
 void wpas_notify_blob_added(struct wpa_supplicant *wpa_s, const char *name)
 {
 	wpas_dbus_signal_blob_added(wpa_s, name);
@@ -627,3 +633,18 @@
 		     "status='%s' parameter='%s'",
 		     status, parameter);
 }
+
+
+void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s,
+					   struct wpa_ssid *ssid)
+{
+	if (wpa_s->current_ssid != ssid)
+		return;
+
+	wpa_dbg(wpa_s, MSG_DEBUG,
+		"Network bssid config changed for the current network - within-ESS roaming %s",
+		ssid->bssid_set ? "disabled" : "enabled");
+
+	wpa_drv_roaming(wpa_s, !ssid->bssid_set,
+			ssid->bssid_set ? ssid->bssid : NULL);
+}
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index 58675ac..7feb530 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -71,6 +71,7 @@
 				 unsigned int id);
 void wpas_notify_bss_rates_changed(struct wpa_supplicant *wpa_s,
 				   unsigned int id);
+void wpas_notify_bss_seen(struct wpa_supplicant *wpa_s, unsigned int id);
 void wpas_notify_blob_added(struct wpa_supplicant *wpa_s, const char *name);
 void wpas_notify_blob_removed(struct wpa_supplicant *wpa_s, const char *name);
 
@@ -127,5 +128,7 @@
 		      const u8 *ie, size_t ie_len, u32 ssi_signal);
 void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status,
 			    const char *parameter);
+void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s,
+					   struct wpa_ssid *ssid);
 
 #endif /* NOTIFY_H */
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 3eea9e8..640154c 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -286,8 +286,10 @@
 	struct wpa_supplicant *wpa_s = ctx;
 	struct wpa_driver_scan_params *params = NULL;
 	struct wpabuf *wps_ie, *ies;
+	unsigned int num_channels = 0;
+	int social_channels_freq[] = { 2412, 2437, 2462, 60480 };
 	size_t ielen;
-	u8 *n;
+	u8 *n, i;
 
 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
 		return -1;
@@ -341,25 +343,34 @@
 
 	switch (type) {
 	case P2P_SCAN_SOCIAL:
-		params->freqs = os_malloc(4 * sizeof(int));
+		params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 1,
+					  sizeof(int));
 		if (params->freqs == NULL)
 			goto fail;
-		params->freqs[0] = 2412;
-		params->freqs[1] = 2437;
-		params->freqs[2] = 2462;
-		params->freqs[3] = 0;
+		for (i = 0; i < ARRAY_SIZE(social_channels_freq); i++) {
+			if (p2p_supported_freq(wpa_s->global->p2p,
+					       social_channels_freq[i]))
+				params->freqs[num_channels++] =
+					social_channels_freq[i];
+		}
+		params->freqs[num_channels++] = 0;
 		break;
 	case P2P_SCAN_FULL:
 		break;
 	case P2P_SCAN_SOCIAL_PLUS_ONE:
-		params->freqs = os_malloc(5 * sizeof(int));
+		params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 2,
+					  sizeof(int));
 		if (params->freqs == NULL)
 			goto fail;
-		params->freqs[0] = 2412;
-		params->freqs[1] = 2437;
-		params->freqs[2] = 2462;
-		params->freqs[3] = freq;
-		params->freqs[4] = 0;
+		for (i = 0; i < ARRAY_SIZE(social_channels_freq); i++) {
+			if (p2p_supported_freq(wpa_s->global->p2p,
+					       social_channels_freq[i]))
+				params->freqs[num_channels++] =
+					social_channels_freq[i];
+		}
+		if (p2p_supported_freq(wpa_s->global->p2p, freq))
+			params->freqs[num_channels++] = freq;
+		params->freqs[num_channels++] = 0;
 		break;
 	}
 
@@ -449,11 +460,16 @@
 		 (ssid && ssid->mode == WPAS_MODE_INFRA)) {
 		wpa_s->reassociate = 0;
 		wpa_s->disconnected = 1;
-		wpa_supplicant_deauthenticate(wpa_s,
-					      WLAN_REASON_DEAUTH_LEAVING);
 		gtype = "client";
 	} else
 		gtype = "GO";
+
+	if (removal_reason != P2P_GROUP_REMOVAL_SILENT && ssid)
+		wpas_notify_p2p_group_removed(wpa_s, ssid, gtype);
+
+	if (os_strcmp(gtype, "client") == 0)
+		wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+
 	if (wpa_s->cross_connect_in_use) {
 		wpa_s->cross_connect_in_use = 0;
 		wpa_msg_global(wpa_s->parent, MSG_INFO,
@@ -511,9 +527,6 @@
 	 */
 	wpa_s->global->p2p_go_wait_client.sec = 0;
 
-	if (removal_reason != P2P_GROUP_REMOVAL_SILENT && ssid)
-		wpas_notify_p2p_group_removed(wpa_s, ssid, gtype);
-
 	if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
 		struct wpa_global *global;
 		char *ifname;
@@ -3466,7 +3479,7 @@
 	u8 min_chan;
 	u8 max_chan;
 	u8 inc;
-	enum { BW20, BW40PLUS, BW40MINUS, BW80 } bw;
+	enum { BW20, BW40PLUS, BW40MINUS, BW80, BW2160 } bw;
 };
 
 static struct p2p_oper_class_map op_class[] = {
@@ -3491,6 +3504,7 @@
 	 * removing invalid channels.
 	 */
 	{ HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80 },
+	{ HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160 },
 	{ -1, 0, 0, 0, 0, BW20 }
 };
 
@@ -3772,7 +3786,8 @@
 }
 
 
-int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s)
+int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s,
+				  const char *conf_p2p_dev)
 {
 	struct wpa_interface iface;
 	struct wpa_supplicant *p2pdev_wpa_s;
@@ -3803,8 +3818,8 @@
 	 * If a P2P Device configuration file was given, use it as the interface
 	 * configuration file (instead of using parent's configuration file.
 	 */
-	if (wpa_s->conf_p2p_dev) {
-		iface.confname = wpa_s->conf_p2p_dev;
+	if (conf_p2p_dev) {
+		iface.confname = conf_p2p_dev;
 		iface.ctrl_interface = NULL;
 	} else {
 		iface.confname = wpa_s->confname;
@@ -3862,7 +3877,6 @@
 int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
 {
 	struct p2p_config p2p;
-	unsigned int r;
 	int i;
 
 	if (wpa_s->conf->p2p_disabled)
@@ -3914,22 +3928,32 @@
 		p2p.config_methods = wpa_s->wps->config_methods;
 	}
 
+	if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels)) {
+		wpa_printf(MSG_ERROR,
+			   "P2P: Failed to configure supported channel list");
+		return -1;
+	}
+
 	if (wpa_s->conf->p2p_listen_reg_class &&
 	    wpa_s->conf->p2p_listen_channel) {
 		p2p.reg_class = wpa_s->conf->p2p_listen_reg_class;
 		p2p.channel = wpa_s->conf->p2p_listen_channel;
 		p2p.channel_forced = 1;
 	} else {
-		p2p.reg_class = 81;
 		/*
 		 * Pick one of the social channels randomly as the listen
 		 * channel.
 		 */
-		os_get_random((u8 *) &r, sizeof(r));
-		p2p.channel = 1 + (r % 3) * 5;
+		if (p2p_config_get_random_social(&p2p, &p2p.reg_class,
+						 &p2p.channel) != 0) {
+			wpa_printf(MSG_ERROR,
+				   "P2P: Failed to select random social channel as listen channel");
+			return -1;
+		}
 		p2p.channel_forced = 0;
 	}
-	wpa_printf(MSG_DEBUG, "P2P: Own listen channel: %d", p2p.channel);
+	wpa_printf(MSG_DEBUG, "P2P: Own listen channel: %d:%d",
+		   p2p.reg_class, p2p.channel);
 
 	if (wpa_s->conf->p2p_oper_reg_class &&
 	    wpa_s->conf->p2p_oper_channel) {
@@ -3940,13 +3964,17 @@
 			   "%d:%d", p2p.op_reg_class, p2p.op_channel);
 
 	} else {
-		p2p.op_reg_class = 81;
 		/*
-		 * Use random operation channel from (1, 6, 11) if no other
-		 * preference is indicated.
+		 * Use random operation channel from 2.4 GHz band social
+		 * channels (1, 6, 11) or band 60 GHz social channel (2) if no
+		 * other preference is indicated.
 		 */
-		os_get_random((u8 *) &r, sizeof(r));
-		p2p.op_channel = 1 + (r % 3) * 5;
+		if (p2p_config_get_random_social(&p2p, &p2p.op_reg_class,
+						 &p2p.op_channel) != 0) {
+			wpa_printf(MSG_ERROR,
+				   "P2P: Failed to select random social channel as operation channel");
+			return -1;
+		}
 		p2p.cfg_op_channel = 0;
 		wpa_printf(MSG_DEBUG, "P2P: Random operating channel: "
 			   "%d:%d", p2p.op_reg_class, p2p.op_channel);
@@ -3963,12 +3991,6 @@
 	} else
 		os_memcpy(p2p.country, "XX\x04", 3);
 
-	if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels)) {
-		wpa_printf(MSG_ERROR, "P2P: Failed to configure supported "
-			   "channel list");
-		return -1;
-	}
-
 	os_memcpy(p2p.pri_dev_type, wpa_s->conf->device_type,
 		  WPS_DEV_TYPE_LEN);
 
@@ -4073,11 +4095,8 @@
 	struct wpa_supplicant *wpa_s, *tmp;
 
 	wpa_s = global->ifaces;
-	if (wpa_s)
-		wpas_p2p_service_flush(wpa_s);
 
-	if (global->p2p == NULL)
-		return;
+	wpas_p2p_service_flush(global->p2p_init_wpa_s);
 
 	/* Remove remaining P2P group interfaces */
 	while (wpa_s && wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
@@ -4354,8 +4373,8 @@
 	    p2p_get_interface_addr(wpa_s->global->p2p,
 				   wpa_s->pending_join_dev_addr,
 				   iface_addr) == 0 &&
-	    os_memcmp(iface_addr, wpa_s->pending_join_dev_addr, ETH_ALEN) != 0)
-	{
+	    os_memcmp(iface_addr, wpa_s->pending_join_dev_addr, ETH_ALEN) != 0
+	    && !wpa_bss_get_bssid(wpa_s, wpa_s->pending_join_iface_addr)) {
 		wpa_printf(MSG_DEBUG, "P2P: Overwrite pending interface "
 			   "address for join from " MACSTR " to " MACSTR
 			   " based on newly discovered P2P peer entry",
@@ -5027,7 +5046,8 @@
 			wpa_printf(MSG_DEBUG, "P2P: Use best 2.4 GHz band "
 				   "channel: %d MHz", freq);
 		} else {
-			os_get_random((u8 *) &r, sizeof(r));
+			if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+				return -1;
 			freq = 2412 + (r % 3) * 25;
 			wpa_printf(MSG_DEBUG, "P2P: Use random 2.4 GHz band "
 				   "channel: %d MHz", freq);
@@ -5044,7 +5064,8 @@
 			wpa_printf(MSG_DEBUG, "P2P: Use best 5 GHz band "
 				   "channel: %d MHz", freq);
 		} else {
-			os_get_random((u8 *) &r, sizeof(r));
+			if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+				return -1;
 			freq = 5180 + (r % 4) * 20;
 			if (!p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
 				wpa_printf(MSG_DEBUG, "P2P: Could not select "
@@ -5074,12 +5095,14 @@
 	unsigned int i, r;
 
 	/* first try some random selection of the social channels */
-	os_get_random((u8 *) &r, sizeof(r));
+	if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+		return -1;
 
 	for (i = 0; i < 3; i++) {
 		params->freq = 2412 + ((r + i) % 3) * 25;
 		if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
-		    freq_included(channels, params->freq))
+		    freq_included(channels, params->freq) &&
+		    p2p_supported_freq(wpa_s->global->p2p, params->freq))
 			goto out;
 	}
 
@@ -5087,11 +5110,28 @@
 	for (i = 0; i < 11; i++) {
 		params->freq = 2412 + i * 5;
 		if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
-		    freq_included(channels, params->freq))
+		    freq_included(channels, params->freq) &&
+		    p2p_supported_freq(wpa_s->global->p2p, params->freq))
 			goto out;
 	}
 
-	wpa_printf(MSG_DEBUG, "P2P: No 2.4 GHz channel allowed");
+	/* try social channel class 180 channel 2 */
+	params->freq = 58320 + 1 * 2160;
+	if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
+	    freq_included(channels, params->freq) &&
+	    p2p_supported_freq(wpa_s->global->p2p, params->freq))
+		goto out;
+
+	/* try all channels in reg. class 180 */
+	for (i = 0; i < 4; i++) {
+		params->freq = 58320 + i * 2160;
+		if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
+		    freq_included(channels, params->freq) &&
+		    p2p_supported_freq(wpa_s->global->p2p, params->freq))
+			goto out;
+	}
+
+	wpa_printf(MSG_DEBUG, "P2P: No 2.4 and 60 GHz channel allowed");
 	return -1;
 out:
 	wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz (no preference known)",
@@ -5795,6 +5835,8 @@
 
 	if (wpa_s->global->p2p_disabled)
 		return -1;
+	if (wpa_s->conf->p2p_disabled)
+		return -1;
 	if (wpa_s->global->p2p == NULL)
 		return -1;
 	if (bss == NULL)
@@ -6323,8 +6365,10 @@
 			 * Pick one of the social channels randomly as the
 			 * listen channel.
 			 */
-			os_get_random((u8 *) &r, sizeof(r));
-			channel = 1 + (r % 3) * 5;
+			if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+				channel = 1;
+			else
+				channel = 1 + (r % 3) * 5;
 			channel_forced = 0;
 		}
 		ret = p2p_set_listen_channel(p2p, reg_class, channel,
@@ -6348,8 +6392,10 @@
 			 * Use random operation channel from (1, 6, 11)
 			 *if no other preference is indicated.
 			 */
-			os_get_random((u8 *) &r, sizeof(r));
-			op_channel = 1 + (r % 3) * 5;
+			if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+				op_channel = 1;
+			else
+				op_channel = 1 + (r % 3) * 5;
 			cfg_op_channel = 0;
 		}
 		ret = p2p_set_oper_channel(p2p, op_reg_class, op_channel,
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index d79ec03..8e23c18 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -16,7 +16,8 @@
 struct p2p_channels;
 struct wps_event_fail;
 
-int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s);
+int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s,
+				  const char *conf_p2p_dev);
 struct wpa_supplicant * wpas_get_p2p_go_iface(struct wpa_supplicant *wpa_s,
 					      const u8 *ssid, size_t ssid_len);
 struct wpa_supplicant * wpas_get_p2p_client_iface(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 40eb8d8..debceb9 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -158,6 +158,13 @@
 		return;
 	}
 
+	if (wpas_update_random_addr_disassoc(wpa_s) < 0) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"Failed to assign random MAC address for a scan");
+		radio_work_done(work);
+		return;
+	}
+
 	wpa_supplicant_notify_scanning(wpa_s, 1);
 
 	if (wpa_s->clear_driver_scan_cache)
@@ -1244,6 +1251,13 @@
 	if (wpa_s->conf->filter_rssi)
 		params.filter_rssi = wpa_s->conf->filter_rssi;
 
+	/* See if user specified frequencies. If so, scan only those. */
+	if (wpa_s->conf->freq_list && !params.freqs) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"Optimize scan based on conf->freq_list");
+		int_array_concat(&params.freqs, wpa_s->conf->freq_list);
+	}
+
 	scan_params = &params;
 
 scan:
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 5188b9f..e616319 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -487,7 +487,8 @@
 
 	wpa_s->connect_work = work;
 
-	if (!wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid)) {
+	if (cwork->bss_removed ||
+	    !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid)) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
 		wpas_connect_work_done(wpa_s);
 		return;
@@ -742,7 +743,7 @@
 	params.bssid = bssid;
 	params.ssid = wpa_s->sme.ssid;
 	params.ssid_len = wpa_s->sme.ssid_len;
-	params.freq = wpa_s->sme.freq;
+	params.freq.freq = wpa_s->sme.freq;
 	params.bg_scan_period = wpa_s->current_ssid ?
 		wpa_s->current_ssid->bg_scan_period : -1;
 	params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
@@ -780,7 +781,7 @@
 	wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
 		" (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
 		params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "",
-		params.freq);
+		params.freq.freq);
 
 	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
 
@@ -1318,7 +1319,10 @@
 	wpa_s->sme.sa_query_trans_id = nbuf;
 	wpa_s->sme.sa_query_count++;
 
-	os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);
+	if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
+		wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
+		return;
+	}
 
 	timeout = sa_query_retry_timeout;
 	sec = ((timeout / 1000) * 1024) / 1000;
diff --git a/wpa_supplicant/wifi_display.c b/wpa_supplicant/wifi_display.c
index b6f9236..6dc41de 100644
--- a/wpa_supplicant/wifi_display.c
+++ b/wpa_supplicant/wifi_display.c
@@ -36,6 +36,34 @@
 }
 
 
+struct wpabuf * wifi_display_get_wfd_ie(struct wpa_global *global)
+{
+	struct wpabuf *ie;
+	size_t len;
+	int i;
+
+	if (global->p2p == NULL)
+		return NULL;
+
+	len = 0;
+	for (i = 0; i < MAX_WFD_SUBELEMS; i++) {
+		if (global->wfd_subelem[i])
+			len += wpabuf_len(global->wfd_subelem[i]);
+	}
+
+	ie = wpabuf_alloc(len);
+	if (ie == NULL)
+		return NULL;
+
+	for (i = 0; i < MAX_WFD_SUBELEMS; i++) {
+		if (global->wfd_subelem[i])
+			wpabuf_put_buf(ie, global->wfd_subelem[i]);
+	}
+
+	return ie;
+}
+
+
 static int wifi_display_update_wfd_ie(struct wpa_global *global)
 {
 	struct wpabuf *ie, *buf;
@@ -238,6 +266,60 @@
 }
 
 
+int wifi_display_subelem_set_from_ies(struct wpa_global *global,
+				      struct wpabuf *ie)
+{
+	int subelements[MAX_WFD_SUBELEMS] = {};
+	const u8 *pos, *end;
+	int len, subelem;
+	struct wpabuf *e;
+
+	wpa_printf(MSG_DEBUG, "WFD IEs set: %p - %lu",
+		   ie, ie ? (unsigned long) wpabuf_len(ie) : 0);
+
+	if (ie == NULL || wpabuf_len(ie) < 6)
+		return -1;
+
+	pos = wpabuf_head(ie);
+	end = pos + wpabuf_len(ie);
+
+	while (end > pos) {
+		if (pos + 3 > end)
+			break;
+
+		len = WPA_GET_BE16(pos + 1) + 3;
+
+		wpa_printf(MSG_DEBUG, "WFD Sub-Element ID %d - len %d",
+			   *pos, len - 3);
+
+		if (pos + len > end)
+			break;
+
+		subelem = *pos;
+		if (subelem < MAX_WFD_SUBELEMS && subelements[subelem] == 0) {
+			e = wpabuf_alloc_copy(pos, len);
+			if (e == NULL)
+				return -1;
+
+			wpabuf_free(global->wfd_subelem[subelem]);
+			global->wfd_subelem[subelem] = e;
+			subelements[subelem] = 1;
+		}
+
+		pos += len;
+	}
+
+	for (subelem = 0; subelem < MAX_WFD_SUBELEMS; subelem++) {
+		if (subelements[subelem] == 0) {
+			wpabuf_free(global->wfd_subelem[subelem]);
+			global->wfd_subelem[subelem] = NULL;
+		}
+	}
+
+	return wifi_display_update_wfd_ie(global);
+}
+
+
 int wifi_display_subelem_get(struct wpa_global *global, char *cmd,
 			     char *buf, size_t buflen)
 {
diff --git a/wpa_supplicant/wifi_display.h b/wpa_supplicant/wifi_display.h
index 7554817..0966bdb 100644
--- a/wpa_supplicant/wifi_display.h
+++ b/wpa_supplicant/wifi_display.h
@@ -13,7 +13,10 @@
 int wifi_display_init(struct wpa_global *global);
 void wifi_display_deinit(struct wpa_global *global);
 void wifi_display_enable(struct wpa_global *global, int enabled);
+struct wpabuf *wifi_display_get_wfd_ie(struct wpa_global *global);
 int wifi_display_subelem_set(struct wpa_global *global, char *cmd);
+int wifi_display_subelem_set_from_ies(struct wpa_global *global,
+				      struct wpabuf *ie);
 int wifi_display_subelem_get(struct wpa_global *global, char *cmd,
 			     char *buf, size_t buflen);
 char * wifi_display_subelem_hex(const struct wpabuf *wfd_subelems, u8 id);
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 0ad6187..fe30b41 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -532,6 +532,13 @@
 }
 
 
+static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
+				   char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
+}
+
+
 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	print_help(argc > 0 ? argv[0] : NULL);
@@ -2519,6 +2526,9 @@
 	{ "pmksa", wpa_cli_cmd_pmksa, NULL,
 	  cli_cmd_flag_none,
 	  "= show PMKSA cache" },
+	{ "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
+	  cli_cmd_flag_none,
+	  "= flush PMKSA cache entries" },
 	{ "reassociate", wpa_cli_cmd_reassociate, NULL,
 	  cli_cmd_flag_none,
 	  "= force reassociation" },
@@ -3169,15 +3179,29 @@
 {
 	const char *pos;
 	char *copy = NULL, *id, *pos2;
+	const char *ifname = ctrl_ifname;
+	char ifname_buf[100];
 
 	pos = msg;
+	if (os_strncmp(pos, "IFNAME=", 7) == 0) {
+		const char *end;
+		end = os_strchr(pos + 7, ' ');
+		if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
+			pos += 7;
+			os_memcpy(ifname_buf, pos, end - pos);
+			ifname_buf[end - pos] = '\0';
+			ifname = ifname_buf;
+			pos = end + 1;
+		}
+	}
 	if (*pos == '<') {
+		const char *prev = pos;
 		/* skip priority */
 		pos = os_strchr(pos, '>');
 		if (pos)
 			pos++;
 		else
-			pos = msg;
+			pos = prev;
 	}
 
 	if (str_match(pos, WPA_EVENT_CONNECTED)) {
@@ -3214,37 +3238,37 @@
 		if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
 			wpa_cli_connected = 1;
 			wpa_cli_last_id = new_id;
-			wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
+			wpa_cli_exec(action_file, ifname, "CONNECTED");
 		}
 	} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
 		if (wpa_cli_connected) {
 			wpa_cli_connected = 0;
-			wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
+			wpa_cli_exec(action_file, ifname, "DISCONNECTED");
 		}
 	} else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
-		wpa_cli_exec(action_file, ctrl_ifname, pos);
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
-		wpa_cli_exec(action_file, ctrl_ifname, pos);
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
-		wpa_cli_exec(action_file, ctrl_ifname, pos);
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
-		wpa_cli_exec(action_file, ctrl_ifname, pos);
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
-		wpa_cli_exec(action_file, ctrl_ifname, pos);
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_match(pos, WPS_EVENT_SUCCESS)) {
-		wpa_cli_exec(action_file, ctrl_ifname, pos);
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_match(pos, WPS_EVENT_FAIL)) {
-		wpa_cli_exec(action_file, ctrl_ifname, pos);
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_match(pos, AP_STA_CONNECTED)) {
-		wpa_cli_exec(action_file, ctrl_ifname, pos);
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_match(pos, AP_STA_DISCONNECTED)) {
-		wpa_cli_exec(action_file, ctrl_ifname, pos);
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
-		wpa_cli_exec(action_file, ctrl_ifname, pos);
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
-		wpa_cli_exec(action_file, ctrl_ifname, pos);
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
-		wpa_cli_exec(action_file, ctrl_ifname, pos);
+		wpa_cli_exec(action_file, ifname, pos);
 	} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
 		printf("wpa_supplicant is terminating - stop monitoring\n");
 		wpa_cli_quit = 1;
@@ -3376,7 +3400,7 @@
 		return;
 	}
 	while (wpa_ctrl_pending(ctrl) > 0) {
-		char buf[256];
+		char buf[4096];
 		size_t len = sizeof(buf) - 1;
 		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
 			buf[len] = '\0';
@@ -3440,10 +3464,18 @@
 
 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
 {
-	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
-		printf("Connection to wpa_supplicant lost - trying to "
-		       "reconnect\n");
-		wpa_cli_close_connection();
+	if (ctrl_conn) {
+		int res;
+		char *prefix = ifname_prefix;
+
+		ifname_prefix = NULL;
+		res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
+		ifname_prefix = prefix;
+		if (res) {
+			printf("Connection to wpa_supplicant lost - trying to "
+			       "reconnect\n");
+			wpa_cli_close_connection();
+		}
 	}
 	if (!ctrl_conn)
 		wpa_cli_reconnect();
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 9d21fe0..eef3d21 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -300,6 +300,7 @@
 		wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
 		wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
 	eapol_conf.external_sim = wpa_s->conf->external_sim;
+	eapol_conf.wps = wpa_s->key_mgmt == WPA_KEY_MGMT_WPS;
 	eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
 #endif /* IEEE8021X_EAPOL */
 
@@ -405,11 +406,6 @@
 	os_free(wpa_s->confanother);
 	wpa_s->confanother = NULL;
 
-#ifdef CONFIG_P2P
-	os_free(wpa_s->conf_p2p_dev);
-	wpa_s->conf_p2p_dev = NULL;
-#endif /* CONFIG_P2P */
-
 	wpa_sm_set_eapol(wpa_s->wpa, NULL);
 	eapol_sm_deinit(wpa_s->eapol);
 	wpa_s->eapol = NULL;
@@ -1382,6 +1378,68 @@
 }
 
 
+int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
+{
+	struct os_reltime now;
+	u8 addr[ETH_ALEN];
+
+	os_get_reltime(&now);
+	if (wpa_s->last_mac_addr_style == style &&
+	    wpa_s->last_mac_addr_change.sec != 0 &&
+	    !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
+				wpa_s->conf->rand_addr_lifetime)) {
+		wpa_msg(wpa_s, MSG_DEBUG,
+			"Previously selected random MAC address has not yet expired");
+		return 0;
+	}
+
+	switch (style) {
+	case 1:
+		if (random_mac_addr(addr) < 0)
+			return -1;
+		break;
+	case 2:
+		os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
+		if (random_mac_addr_keep_oui(addr) < 0)
+			return -1;
+		break;
+	default:
+		return -1;
+	}
+
+	if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"Failed to set random MAC address");
+		return -1;
+	}
+
+	os_get_reltime(&wpa_s->last_mac_addr_change);
+	wpa_s->mac_addr_changed = 1;
+	wpa_s->last_mac_addr_style = style;
+
+	if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"Could not update MAC address information");
+		return -1;
+	}
+
+	wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
+		MAC2STR(addr));
+
+	return 0;
+}
+
+
+int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
+	    !wpa_s->conf->preassoc_mac_addr)
+		return 0;
+
+	return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
+}
+
+
 static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
 
 /**
@@ -1396,6 +1454,34 @@
 			      struct wpa_bss *bss, struct wpa_ssid *ssid)
 {
 	struct wpa_connect_work *cwork;
+	int rand_style;
+
+	if (ssid->mac_addr == -1)
+		rand_style = wpa_s->conf->mac_addr;
+	else
+		rand_style = ssid->mac_addr;
+
+	if (wpa_s->last_ssid == ssid) {
+		wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
+	} else if (rand_style > 0) {
+		if (wpas_update_random_addr(wpa_s, rand_style) < 0)
+			return;
+		wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
+	} else if (wpa_s->mac_addr_changed) {
+		if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
+			wpa_msg(wpa_s, MSG_INFO,
+				"Could not restore permanent MAC address");
+			return;
+		}
+		wpa_s->mac_addr_changed = 0;
+		if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
+			wpa_msg(wpa_s, MSG_INFO,
+				"Could not update MAC address information");
+			return;
+		}
+		wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
+	}
+	wpa_s->last_ssid = ssid;
 
 #ifdef CONFIG_IBSS_RSN
 	ibss_rsn_deinit(wpa_s->ibss_rsn);
@@ -1498,7 +1584,7 @@
 
 	wpa_s->connect_work = work;
 
-	if (!wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
+	if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
 		wpas_connect_work_done(wpa_s);
 		return;
@@ -1535,6 +1621,7 @@
 		   (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
 		/* Use ap_scan==1 style network selection to find the network
 		 */
+		wpas_connect_work_done(wpa_s);
 		wpa_s->scan_req = MANUAL_SCAN_REQ;
 		wpa_s->reassociate = 1;
 		wpa_supplicant_req_scan(wpa_s, 0, 0);
@@ -1585,6 +1672,7 @@
 					      wpa_ie, &wpa_ie_len)) {
 			wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
 				"key management and encryption suites");
+			wpas_connect_work_done(wpa_s);
 			return;
 		}
 	} else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
@@ -1604,6 +1692,7 @@
 			wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
 				"key management and encryption suites (no "
 				"scan results)");
+			wpas_connect_work_done(wpa_s);
 			return;
 		}
 #ifdef CONFIG_WPS
@@ -1752,7 +1841,7 @@
 				   MAC2STR(bss->bssid), bss->freq,
 				   ssid->bssid_set);
 			params.bssid = bss->bssid;
-			params.freq = bss->freq;
+			params.freq.freq = bss->freq;
 		}
 		params.bssid_hint = bss->bssid;
 		params.freq_hint = bss->freq;
@@ -1768,8 +1857,23 @@
 	}
 
 	if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
-	    params.freq == 0)
-		params.freq = ssid->frequency; /* Initial channel for IBSS */
+	    params.freq.freq == 0) {
+		enum hostapd_hw_mode hw_mode;
+		u8 channel;
+
+		params.freq.freq = ssid->frequency;
+
+		hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
+		for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
+			if (wpa_s->hw.modes[i].mode == hw_mode) {
+				struct hostapd_hw_modes *mode;
+
+				mode = &wpa_s->hw.modes[i];
+				params.freq.ht_enabled = ht_supported(mode);
+				break;
+			}
+		}
+	}
 
 	if (ssid->mode == WPAS_MODE_IBSS) {
 		if (ssid->beacon_int)
@@ -1853,14 +1957,15 @@
 	if (wpa_s->num_multichan_concurrent < 2) {
 		int freq, num;
 		num = get_shared_radio_freqs(wpa_s, &freq, 1);
-		if (num > 0 && freq > 0 && freq != params.freq) {
+		if (num > 0 && freq > 0 && freq != params.freq.freq) {
 			wpa_printf(MSG_DEBUG,
 				   "Assoc conflicting freq found (%d != %d)",
-				   freq, params.freq);
-			if (wpas_p2p_handle_frequency_conflicts(wpa_s,
-								params.freq,
-								ssid) < 0)
+				   freq, params.freq.freq);
+			if (wpas_p2p_handle_frequency_conflicts(
+				    wpa_s, params.freq.freq, ssid) < 0) {
+				wpas_connect_work_done(wpa_s);
 				return;
+			}
 		}
 	}
 #endif /* CONFIG_P2P */
@@ -2664,6 +2769,8 @@
 		return -1;
 	}
 
+	wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
+
 	return 0;
 }
 
@@ -2711,6 +2818,7 @@
 
 	wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
 		MAC2STR(wpa_s->own_addr));
+	os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
 	wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
 
 	if (wpa_s->bridge_ifname[0]) {
@@ -3409,17 +3517,18 @@
 }
 
 
-int radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
+struct wpa_radio_work *
+radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
 {
 	struct wpa_radio_work *work;
 	struct wpa_radio *radio = wpa_s->radio;
 
 	dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
 		if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
-			return 1;
+			return work;
 	}
 
-	return 0;
+	return NULL;
 }
 
 
@@ -3507,13 +3616,6 @@
 		wpa_s->confanother = os_rel2abs_path(iface->confanother);
 		wpa_config_read(wpa_s->confanother, wpa_s->conf);
 
-#ifdef CONFIG_P2P
-		wpa_s->conf_p2p_dev = os_rel2abs_path(iface->conf_p2p_dev);
-#ifndef ANDROID_P2P
-		wpa_config_read(wpa_s->conf_p2p_dev, wpa_s->conf);
-#endif
-#endif /* CONFIG_P2P */
-
 		/*
 		 * Override ctrl_interface and driver_param if set on command
 		 * line.
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 2a0dc20..89da0da 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -332,6 +332,25 @@
 # 1:  Scan current operating frequency if another VIF on the same radio
 #     is already associated.
 
+# MAC address policy default
+# 0 = use permanent MAC address
+# 1 = use random MAC address for each ESS connection
+# 2 = like 1, but maintain OUI (with local admin bit set)
+#
+# By default, permanent MAC address is used unless policy is changed by
+# the per-network mac_addr parameter. Global mac_addr=1 can be used to
+# change this default behavior.
+#mac_addr=0
+
+# Lifetime of random MAC address in seconds (default: 60)
+#rand_addr_lifetime=60
+
+# MAC address policy for pre-association operations (scanning, ANQP)
+# 0 = use permanent MAC address
+# 1 = use random MAC address
+# 2 = like 1, but maintain OUI (with local admin bit set)
+#preassoc_mac_addr=0
+
 # Interworking (IEEE 802.11u)
 
 # Enable Interworking
@@ -962,6 +981,12 @@
 # Beacon interval (default: 100 TU)
 #beacon_int=100
 
+# MAC address policy
+# 0 = use permanent MAC address
+# 1 = use random MAC address for each ESS connection
+# 2 = like 1, but maintain OUI (with local admin bit set)
+#mac_addr=0
+
 # disable_ht: Whether HT (802.11n) should be disabled.
 # 0 = HT enabled (if AP supports it)
 # 1 = HT disabled
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index bf3d19d..ae9dddd 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -67,7 +67,7 @@
 
 #ifdef CONFIG_P2P
 	/**
-	 * conf_p2p_dev - Additional configuration file used to hold the
+	 * conf_p2p_dev - Configuration file used to hold the
 	 * P2P Device configuration parameters.
 	 *
 	 * This can also be %NULL. In such a case, if a P2P Device dedicated
@@ -320,10 +320,12 @@
 void radio_remove_works(struct wpa_supplicant *wpa_s,
 			const char *type, int remove_all);
 void radio_work_check_next(struct wpa_supplicant *wpa_s);
-int radio_work_pending(struct wpa_supplicant *wpa_s, const char *type);
+struct wpa_radio_work *
+radio_work_pending(struct wpa_supplicant *wpa_s, const char *type);
 
 struct wpa_connect_work {
 	unsigned int sme:1;
+	unsigned int bss_removed:1;
 	struct wpa_bss *bss;
 	struct wpa_ssid *ssid;
 };
@@ -391,6 +393,7 @@
 	struct l2_packet_data *l2;
 	struct l2_packet_data *l2_br;
 	unsigned char own_addr[ETH_ALEN];
+	unsigned char perm_addr[ETH_ALEN];
 	char ifname[100];
 #ifdef CONFIG_CTRL_IFACE_DBUS
 	char *dbus_path;
@@ -407,10 +410,6 @@
 	char *confname;
 	char *confanother;
 
-#ifdef CONFIG_P2P
-	char *conf_p2p_dev;
-#endif /* CONFIG_P2P */
-
 	struct wpa_config *conf;
 	int countermeasures;
 	struct os_reltime last_michael_mic_error;
@@ -421,6 +420,7 @@
 	int disconnected; /* all connections disabled; i.e., do no reassociate
 			   * before this has been cleared */
 	struct wpa_ssid *current_ssid;
+	struct wpa_ssid *last_ssid;
 	struct wpa_bss *current_bss;
 	int ap_ies_from_associnfo;
 	unsigned int assoc_freq;
@@ -600,6 +600,7 @@
 	struct wps_context *wps;
 	int wps_success; /* WPS success event received */
 	struct wps_er *wps_er;
+	unsigned int wps_run;
 	int blacklist_cleared;
 
 	struct wpabuf *pending_eapol_rx;
@@ -608,6 +609,10 @@
 	unsigned int last_eapol_matches_bssid:1;
 	unsigned int eap_expected_failure:1;
 	unsigned int reattach:1; /* reassociation to the same BSS requested */
+	unsigned int mac_addr_changed:1;
+
+	struct os_reltime last_mac_addr_change;
+	int last_mac_addr_style;
 
 	struct ibss_rsn *ibss_rsn;
 
@@ -957,6 +962,8 @@
 		    size_t ssid_len);
 void wpas_request_connection(struct wpa_supplicant *wpa_s);
 int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen);
+int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style);
+int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s);
 
 /**
  * wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response
@@ -984,6 +991,8 @@
 int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s);
 struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
 					     struct wpa_ssid **selected_ssid);
+int ht_supported(const struct hostapd_hw_modes *mode);
+int vht_supported(const struct hostapd_hw_modes *mode);
 
 /* eap_register.c */
 int eap_register_methods(void);
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 350b122..38279b1 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -142,11 +142,29 @@
 
 	if (pmksa_cache_get_current(wpa_s->wpa) &&
 	    type == IEEE802_1X_TYPE_EAPOL_START) {
-		/* Trying to use PMKSA caching - do not send EAPOL-Start frames
-		 * since they will trigger full EAPOL authentication. */
-		wpa_printf(MSG_DEBUG, "RSN: PMKSA caching - do not send "
-			   "EAPOL-Start");
-		return -1;
+		/*
+		 * We were trying to use PMKSA caching and sending EAPOL-Start
+		 * would abort that and trigger full EAPOL authentication.
+		 * However, we've already waited for the AP/Authenticator to
+		 * start 4-way handshake or EAP authentication, and apparently
+		 * it has not done so since the startWhen timer has reached zero
+		 * to get the state machine sending EAPOL-Start. This is not
+		 * really supposed to happen, but an interoperability issue with
+		 * a deployed AP has been identified where the connection fails
+		 * due to that AP failing to operate correctly if PMKID is
+		 * included in the Association Request frame. To work around
+		 * this, assume PMKSA caching failed and try to initiate full
+		 * EAP authentication.
+		 */
+		if (!wpa_s->current_ssid ||
+		    wpa_s->current_ssid->eap_workaround) {
+			wpa_printf(MSG_DEBUG,
+				   "RSN: Timeout on waiting for the AP to initiate 4-way handshake for PMKSA caching or EAP authentication - try to force it to start EAP authentication");
+		} else {
+			wpa_printf(MSG_DEBUG,
+				   "RSN: PMKSA caching - do not send EAPOL-Start");
+			return -1;
+		}
 	}
 
 	if (is_zero_ether_addr(wpa_s->bssid)) {
@@ -562,11 +580,13 @@
 static int wpa_supplicant_send_tdls_mgmt(void *ctx, const u8 *dst,
 					 u8 action_code, u8 dialog_token,
 					 u16 status_code, u32 peer_capab,
-					 const u8 *buf, size_t len)
+					 int initiator, const u8 *buf,
+					 size_t len)
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	return wpa_drv_send_tdls_mgmt(wpa_s, dst, action_code, dialog_token,
-				      status_code, peer_capab, buf, len);
+				      status_code, peer_capab, initiator, buf,
+				      len);
 }
 
 
@@ -582,7 +602,7 @@
 	const u8 *supp_rates, size_t supp_rates_len,
 	const struct ieee80211_ht_capabilities *ht_capab,
 	const struct ieee80211_vht_capabilities *vht_capab,
-	u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len,
+	u8 qosinfo, int wmm, const u8 *ext_capab, size_t ext_capab_len,
 	const u8 *supp_channels, size_t supp_channels_len,
 	const u8 *supp_oper_classes, size_t supp_oper_classes_len)
 {
@@ -597,10 +617,10 @@
 	params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED;
 
 	/*
-	 * TDLS Setup frames do not contain WMM IEs, hence need to depend on
-	 * qosinfo to check if the peer is WMM capable.
+	 * Don't rely only on qosinfo for WMM capability. It may be 0 even when
+	 * present. Allow the WMM IE to also indicate QoS support.
 	 */
-	if (qosinfo)
+	if (wmm || qosinfo)
 		params.flags |= WPA_STA_WMM;
 
 	params.ht_capabilities = ht_capab;
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index fd0d14a..40a5c69 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -286,11 +286,54 @@
 		/* compare security parameters */
 		if (ssid->auth_alg != new_ssid->auth_alg ||
 		    ssid->key_mgmt != new_ssid->key_mgmt ||
-		    ssid->proto != new_ssid->proto ||
-		    ssid->pairwise_cipher != new_ssid->pairwise_cipher ||
 		    ssid->group_cipher != new_ssid->group_cipher)
 			continue;
 
+		/*
+		 * Some existing WPS APs will send two creds in case they are
+		 * configured for mixed mode operation (WPA+WPA2 and TKIP+CCMP).
+		 * Try to merge these two creds if they are received in the same
+		 * M8 message.
+		 */
+		if (ssid->wps_run && ssid->wps_run == new_ssid->wps_run &&
+		    wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
+			if (new_ssid->passphrase && ssid->passphrase &&
+			    os_strcmp(new_ssid->passphrase, ssid->passphrase) !=
+			    0) {
+				wpa_printf(MSG_DEBUG,
+					   "WPS: M8 Creds with different passphrase - do not merge");
+				continue;
+			}
+
+			if (new_ssid->psk_set &&
+			    (!ssid->psk_set ||
+			     os_memcmp(new_ssid->psk, ssid->psk, 32) != 0)) {
+				wpa_printf(MSG_DEBUG,
+					   "WPS: M8 Creds with different PSK - do not merge");
+				continue;
+			}
+
+			if ((new_ssid->passphrase && !ssid->passphrase) ||
+			    (!new_ssid->passphrase && ssid->passphrase)) {
+				wpa_printf(MSG_DEBUG,
+					   "WPS: M8 Creds with different passphrase/PSK type - do not merge");
+				continue;
+			}
+
+			wpa_printf(MSG_DEBUG,
+				   "WPS: Workaround - merge likely WPA/WPA2-mixed mode creds in same M8 message");
+			new_ssid->proto |= ssid->proto;
+			new_ssid->pairwise_cipher |= ssid->pairwise_cipher;
+		} else {
+			/*
+			 * proto and pairwise_cipher difference matter for
+			 * non-mixed-mode creds.
+			 */
+			if (ssid->proto != new_ssid->proto ||
+			    ssid->pairwise_cipher != new_ssid->pairwise_cipher)
+				continue;
+		}
+
 		/* Remove the duplicated older network entry. */
 		wpa_printf(MSG_DEBUG, "Remove duplicate network %d", ssid->id);
 		wpas_notify_network_removed(wpa_s, ssid);
@@ -411,6 +454,7 @@
 	}
 
 	wpa_config_set_network_defaults(ssid);
+	ssid->wps_run = wpa_s->wps_run;
 
 	os_free(ssid->ssid);
 	ssid->ssid = os_malloc(cred->ssid_len);
@@ -1004,6 +1048,9 @@
 {
 	struct wpa_bss *bss;
 
+	wpa_s->wps_run++;
+	if (wpa_s->wps_run == 0)
+		wpa_s->wps_run++;
 	wpa_s->after_wps = 0;
 	wpa_s->known_wps_freq = 0;
 	if (freq) {