[pkg-wpa-devel] r1909 - in /wpa/trunk: debian/ debian/patches/ hostapd/ hs20/client/ patches/ src/ap/ src/common/ src/crypto/ src/drivers/ src/eap_common/ src/eap_peer/ src/eap_server/ src/eapol_supp/ src/p2p/ src/pae/ src/radius/ src/rsn_supp/ src/tls/ src/utils/ src/wps/ wpa_supplicant/ wpa_supplicant/dbus/

slh-guest at users.alioth.debian.org slh-guest at users.alioth.debian.org
Tue Oct 14 12:39:25 UTC 2014


Author: slh-guest
Date: Tue Oct 14 12:39:25 2014
New Revision: 1909

URL: http://svn.debian.org/wsvn/pkg-wpa/?sc=1&rev=1909
Log:
* New upstream release:
  - fixed by the new upstream version:
    + wpa: arbitrary command execution via action scripts (Closes: #765352).
      wpasupplicant: fixed wpa_cli action script execution to use more
      robust mechanism (CVE-2014-3686).
      hostapd: fixed hostapd_cli action script execution to use more robust
      mechanism (CVE-2014-3686).
    + wpasupplicant: MAC addressing changing broken after updating to 2.2-1
      (Closes: #763775).
    + drop ap_config_c_fix-typo-for-capabilities, applied upstream.

Added:
    wpa/trunk/patches/openssl-0.9.8za-tls-extensions.patch
      - copied unchanged from r1908, wpa/branches/upstream/current/patches/openssl-0.9.8za-tls-extensions.patch
Removed:
    wpa/trunk/debian/patches/ap_config_c_fix-typo-for-capabilities.patch
    wpa/trunk/patches/openssl-0.9.8-tls-extensions.patch
    wpa/trunk/patches/openssl-0.9.8d-tls-extensions.patch
    wpa/trunk/patches/openssl-0.9.8e-tls-extensions.patch
    wpa/trunk/patches/openssl-0.9.8g-tls-extensions.patch
    wpa/trunk/patches/openssl-0.9.8h-tls-extensions.patch
    wpa/trunk/patches/openssl-0.9.8i-tls-extensions.patch
    wpa/trunk/patches/openssl-0.9.8x-tls-extensions.patch
    wpa/trunk/patches/openssl-0.9.9-session-ticket.patch
Modified:
    wpa/trunk/debian/changelog
    wpa/trunk/debian/patches/series
    wpa/trunk/debian/patches/wpa_supplicant-MACsec-fix-build-failure-for-IEEE8021.patch
    wpa/trunk/hostapd/ChangeLog
    wpa/trunk/hostapd/config_file.c
    wpa/trunk/hostapd/ctrl_iface.c
    wpa/trunk/hostapd/hostapd_cli.c
    wpa/trunk/hostapd/main.c
    wpa/trunk/hs20/client/Android.mk
    wpa/trunk/hs20/client/osu_client.c
    wpa/trunk/src/ap/ap_config.c
    wpa/trunk/src/ap/beacon.c
    wpa/trunk/src/ap/ctrl_iface_ap.c
    wpa/trunk/src/ap/dfs.c
    wpa/trunk/src/ap/drv_callbacks.c
    wpa/trunk/src/ap/eap_user_db.c
    wpa/trunk/src/ap/gas_serv.c
    wpa/trunk/src/ap/hostapd.c
    wpa/trunk/src/ap/hostapd.h
    wpa/trunk/src/ap/ieee802_11.c
    wpa/trunk/src/ap/ieee802_11_ht.c
    wpa/trunk/src/ap/ieee802_11_vht.c
    wpa/trunk/src/ap/ieee802_1x.c
    wpa/trunk/src/ap/pmksa_cache_auth.c
    wpa/trunk/src/ap/sta_info.c
    wpa/trunk/src/ap/sta_info.h
    wpa/trunk/src/ap/wnm_ap.c
    wpa/trunk/src/ap/wpa_auth.c
    wpa/trunk/src/ap/wpa_auth_ft.c
    wpa/trunk/src/common/ieee802_11_common.c
    wpa/trunk/src/common/ieee802_11_common.h
    wpa/trunk/src/common/ieee802_11_defs.h
    wpa/trunk/src/common/qca-vendor.h
    wpa/trunk/src/common/sae.c
    wpa/trunk/src/common/version.h
    wpa/trunk/src/common/wpa_common.c
    wpa/trunk/src/common/wpa_common.h
    wpa/trunk/src/common/wpa_ctrl.h
    wpa/trunk/src/crypto/aes-ccm.c
    wpa/trunk/src/crypto/aes-gcm.c
    wpa/trunk/src/crypto/aes-unwrap.c
    wpa/trunk/src/crypto/aes-wrap.c
    wpa/trunk/src/crypto/aes_wrap.h
    wpa/trunk/src/crypto/crypto_openssl.c
    wpa/trunk/src/crypto/milenage.c
    wpa/trunk/src/crypto/tls_openssl.c
    wpa/trunk/src/drivers/driver.h
    wpa/trunk/src/drivers/driver_atheros.c
    wpa/trunk/src/drivers/driver_common.c
    wpa/trunk/src/drivers/driver_nl80211.c
    wpa/trunk/src/drivers/driver_test.c
    wpa/trunk/src/drivers/driver_wext.c
    wpa/trunk/src/drivers/drivers.mak
    wpa/trunk/src/drivers/drivers.mk
    wpa/trunk/src/drivers/nl80211_copy.h
    wpa/trunk/src/eap_common/eap_eke_common.c
    wpa/trunk/src/eap_common/eap_fast_common.c
    wpa/trunk/src/eap_common/eap_fast_common.h
    wpa/trunk/src/eap_common/eap_gpsk_common.c
    wpa/trunk/src/eap_common/eap_ikev2_common.c
    wpa/trunk/src/eap_common/eap_ikev2_common.h
    wpa/trunk/src/eap_common/eap_pwd_common.c
    wpa/trunk/src/eap_common/eap_sim_common.c
    wpa/trunk/src/eap_common/eap_sim_common.h
    wpa/trunk/src/eap_common/ikev2_common.c
    wpa/trunk/src/eap_common/ikev2_common.h
    wpa/trunk/src/eap_peer/eap.c
    wpa/trunk/src/eap_peer/eap_aka.c
    wpa/trunk/src/eap_peer/eap_config.h
    wpa/trunk/src/eap_peer/eap_eke.c
    wpa/trunk/src/eap_peer/eap_fast.c
    wpa/trunk/src/eap_peer/eap_gpsk.c
    wpa/trunk/src/eap_peer/eap_i.h
    wpa/trunk/src/eap_peer/eap_ikev2.c
    wpa/trunk/src/eap_peer/eap_leap.c
    wpa/trunk/src/eap_peer/eap_mschapv2.c
    wpa/trunk/src/eap_peer/eap_pax.c
    wpa/trunk/src/eap_peer/eap_peap.c
    wpa/trunk/src/eap_peer/eap_psk.c
    wpa/trunk/src/eap_peer/eap_pwd.c
    wpa/trunk/src/eap_peer/eap_sake.c
    wpa/trunk/src/eap_peer/eap_sim.c
    wpa/trunk/src/eap_peer/eap_tls.c
    wpa/trunk/src/eap_peer/eap_tnc.c
    wpa/trunk/src/eap_peer/eap_ttls.c
    wpa/trunk/src/eap_peer/ikev2.c
    wpa/trunk/src/eap_peer/mschapv2.c
    wpa/trunk/src/eap_peer/tncc.c
    wpa/trunk/src/eap_server/eap_server.c
    wpa/trunk/src/eap_server/eap_server_aka.c
    wpa/trunk/src/eap_server/eap_server_eke.c
    wpa/trunk/src/eap_server/eap_server_fast.c
    wpa/trunk/src/eap_server/eap_server_gpsk.c
    wpa/trunk/src/eap_server/eap_server_gtc.c
    wpa/trunk/src/eap_server/eap_server_ikev2.c
    wpa/trunk/src/eap_server/eap_server_md5.c
    wpa/trunk/src/eap_server/eap_server_mschapv2.c
    wpa/trunk/src/eap_server/eap_server_pax.c
    wpa/trunk/src/eap_server/eap_server_peap.c
    wpa/trunk/src/eap_server/eap_server_psk.c
    wpa/trunk/src/eap_server/eap_server_pwd.c
    wpa/trunk/src/eap_server/eap_server_sake.c
    wpa/trunk/src/eap_server/eap_server_sim.c
    wpa/trunk/src/eap_server/eap_server_tnc.c
    wpa/trunk/src/eap_server/eap_server_ttls.c
    wpa/trunk/src/eap_server/ikev2.c
    wpa/trunk/src/eapol_supp/eapol_supp_sm.c
    wpa/trunk/src/eapol_supp/eapol_supp_sm.h
    wpa/trunk/src/p2p/p2p.c
    wpa/trunk/src/p2p/p2p.h
    wpa/trunk/src/p2p/p2p_dev_disc.c
    wpa/trunk/src/p2p/p2p_go_neg.c
    wpa/trunk/src/p2p/p2p_group.c
    wpa/trunk/src/p2p/p2p_i.h
    wpa/trunk/src/p2p/p2p_invitation.c
    wpa/trunk/src/p2p/p2p_pd.c
    wpa/trunk/src/p2p/p2p_sd.c
    wpa/trunk/src/p2p/p2p_utils.c
    wpa/trunk/src/pae/ieee802_1x_kay.c
    wpa/trunk/src/radius/radius.c
    wpa/trunk/src/radius/radius.h
    wpa/trunk/src/radius/radius_client.c
    wpa/trunk/src/radius/radius_server.c
    wpa/trunk/src/rsn_supp/peerkey.c
    wpa/trunk/src/rsn_supp/peerkey.h
    wpa/trunk/src/rsn_supp/pmksa_cache.c
    wpa/trunk/src/rsn_supp/tdls.c
    wpa/trunk/src/rsn_supp/wpa.c
    wpa/trunk/src/rsn_supp/wpa.h
    wpa/trunk/src/rsn_supp/wpa_ft.c
    wpa/trunk/src/rsn_supp/wpa_i.h
    wpa/trunk/src/rsn_supp/wpa_ie.c
    wpa/trunk/src/tls/pkcs1.c
    wpa/trunk/src/tls/tlsv1_client_read.c
    wpa/trunk/src/tls/tlsv1_common.c
    wpa/trunk/src/tls/tlsv1_record.c
    wpa/trunk/src/tls/tlsv1_server_read.c
    wpa/trunk/src/tls/x509v3.c
    wpa/trunk/src/utils/browser-android.c
    wpa/trunk/src/utils/browser-system.c
    wpa/trunk/src/utils/browser-wpadebug.c
    wpa/trunk/src/utils/common.c
    wpa/trunk/src/utils/common.h
    wpa/trunk/src/utils/ext_password_test.c
    wpa/trunk/src/utils/http_curl.c
    wpa/trunk/src/utils/os.h
    wpa/trunk/src/utils/os_internal.c
    wpa/trunk/src/utils/os_none.c
    wpa/trunk/src/utils/os_unix.c
    wpa/trunk/src/utils/os_win32.c
    wpa/trunk/src/utils/pcsc_funcs.c
    wpa/trunk/src/utils/wpa_debug.c
    wpa/trunk/src/utils/wpa_debug.h
    wpa/trunk/src/wps/httpread.c
    wpa/trunk/src/wps/wps.c
    wpa/trunk/src/wps/wps_attr_process.c
    wpa/trunk/src/wps/wps_enrollee.c
    wpa/trunk/src/wps/wps_er.c
    wpa/trunk/src/wps/wps_registrar.c
    wpa/trunk/src/wps/wps_upnp.c
    wpa/trunk/wpa_supplicant/Android.mk
    wpa/trunk/wpa_supplicant/ChangeLog
    wpa/trunk/wpa_supplicant/Makefile
    wpa/trunk/wpa_supplicant/README-P2P
    wpa/trunk/wpa_supplicant/ap.c
    wpa/trunk/wpa_supplicant/bss.c
    wpa/trunk/wpa_supplicant/config.c
    wpa/trunk/wpa_supplicant/config.h
    wpa/trunk/wpa_supplicant/config_file.c
    wpa/trunk/wpa_supplicant/config_ssid.h
    wpa/trunk/wpa_supplicant/config_winreg.c
    wpa/trunk/wpa_supplicant/ctrl_iface.c
    wpa/trunk/wpa_supplicant/ctrl_iface_unix.c
    wpa/trunk/wpa_supplicant/dbus/dbus_dict_helpers.c
    wpa/trunk/wpa_supplicant/dbus/dbus_new.c
    wpa/trunk/wpa_supplicant/dbus/dbus_new.h
    wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers.c
    wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers.h
    wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
    wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
    wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_wps.c
    wpa/trunk/wpa_supplicant/dbus/dbus_new_helpers.c
    wpa/trunk/wpa_supplicant/dbus/dbus_old_handlers.c
    wpa/trunk/wpa_supplicant/driver_i.h
    wpa/trunk/wpa_supplicant/eapol_test.c
    wpa/trunk/wpa_supplicant/events.c
    wpa/trunk/wpa_supplicant/gas_query.c
    wpa/trunk/wpa_supplicant/hs20_supplicant.c
    wpa/trunk/wpa_supplicant/interworking.c
    wpa/trunk/wpa_supplicant/main.c
    wpa/trunk/wpa_supplicant/notify.c
    wpa/trunk/wpa_supplicant/notify.h
    wpa/trunk/wpa_supplicant/p2p_supplicant.c
    wpa/trunk/wpa_supplicant/p2p_supplicant.h
    wpa/trunk/wpa_supplicant/scan.c
    wpa/trunk/wpa_supplicant/sme.c
    wpa/trunk/wpa_supplicant/wifi_display.c
    wpa/trunk/wpa_supplicant/wifi_display.h
    wpa/trunk/wpa_supplicant/wnm_sta.c
    wpa/trunk/wpa_supplicant/wpa_cli.c
    wpa/trunk/wpa_supplicant/wpa_supplicant.c
    wpa/trunk/wpa_supplicant/wpa_supplicant.conf
    wpa/trunk/wpa_supplicant/wpa_supplicant_i.h
    wpa/trunk/wpa_supplicant/wpa_supplicant_template.conf
    wpa/trunk/wpa_supplicant/wpas_glue.c
    wpa/trunk/wpa_supplicant/wps_supplicant.c

Modified: wpa/trunk/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/debian/changelog?rev=1909&op=diff
==============================================================================
--- wpa/trunk/debian/changelog	(original)
+++ wpa/trunk/debian/changelog	Tue Oct 14 12:39:25 2014
@@ -1,9 +1,19 @@
-wpa (2.2-2) UNRELEASED; urgency=medium
+wpa (2.3-1) UNRELEASED; urgency=medium
 
   * NOT RELEASED YET
+  * New upstream release:
+    - fixed by the new upstream version:
+      + wpa: arbitrary command execution via action scripts (Closes: #765352).
+        wpasupplicant: fixed wpa_cli action script execution to use more
+        robust mechanism (CVE-2014-3686).
+        hostapd: fixed hostapd_cli action script execution to use more robust
+        mechanism (CVE-2014-3686).
+      + wpasupplicant: MAC addressing changing broken after updating to 2.2-1
+        (Closes: #763775).
+      + drop ap_config_c_fix-typo-for-capabilities, applied upstream.
   * bump standards version to 3.9.6, no changes necessary.
 
- -- Stefan Lippers-Hollmann <s.l-h at gmx.de>  Thu, 18 Sep 2014 06:23:22 +0200
+ -- Stefan Lippers-Hollmann <s.l-h at gmx.de>  Tue, 14 Oct 2014 14:27:24 +0200
 
 wpa (2.2-1) unstable; urgency=medium
 

Modified: wpa/trunk/debian/patches/series
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/debian/patches/series?rev=1909&op=diff
==============================================================================
--- wpa/trunk/debian/patches/series	(original)
+++ wpa/trunk/debian/patches/series	Tue Oct 14 12:39:25 2014
@@ -5,4 +5,3 @@
 12_wpa_gui_knotify_support.patch
 wpa_gui_desktop_add-keywords-entry.patch
 wpa_supplicant-MACsec-fix-build-failure-for-IEEE8021.patch
-ap_config_c_fix-typo-for-capabilities.patch

Modified: wpa/trunk/debian/patches/wpa_supplicant-MACsec-fix-build-failure-for-IEEE8021.patch
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/debian/patches/wpa_supplicant-MACsec-fix-build-failure-for-IEEE8021.patch?rev=1909&op=diff
==============================================================================
--- wpa/trunk/debian/patches/wpa_supplicant-MACsec-fix-build-failure-for-IEEE8021.patch	(original)
+++ wpa/trunk/debian/patches/wpa_supplicant-MACsec-fix-build-failure-for-IEEE8021.patch	Tue Oct 14 12:39:25 2014
@@ -29,9 +29,9 @@
 
 --- a/wpa_supplicant/wpa_supplicant.c
 +++ b/wpa_supplicant/wpa_supplicant.c
-@@ -298,9 +298,9 @@ void wpa_supplicant_initiate_eapol(struc
- 		wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
+@@ -299,9 +299,9 @@ void wpa_supplicant_initiate_eapol(struc
  	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 */
  

Modified: wpa/trunk/hostapd/ChangeLog
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/hostapd/ChangeLog?rev=1909&op=diff
==============================================================================
--- wpa/trunk/hostapd/ChangeLog	(original)
+++ wpa/trunk/hostapd/ChangeLog	Tue Oct 14 12:39:25 2014
@@ -1,4 +1,23 @@
 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

Modified: wpa/trunk/hostapd/config_file.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/hostapd/config_file.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/hostapd/config_file.c	(original)
+++ wpa/trunk/hostapd/config_file.c	Tue Oct 14 12:39:25 2014
@@ -3175,7 +3175,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;
@@ -3204,9 +3203,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++;
 

Modified: wpa/trunk/hostapd/ctrl_iface.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/hostapd/ctrl_iface.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/hostapd/ctrl_iface.c	(original)
+++ wpa/trunk/hostapd/ctrl_iface.c	Tue Oct 14 12:39:25 2014
@@ -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;
@@ -1252,16 +1252,28 @@
 #endif /* CONFIG_TESTING_OPTIONS */
 
 
-static int hostapd_ctrl_iface_chan_switch(struct hostapd_data *hapd, char *pos)
+static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+					  char *pos)
 {
 #ifdef NEED_AP_MLME
 	struct csa_settings settings;
-	int ret = hostapd_parse_csa_settings(pos, &settings);
-
+	int ret;
+	unsigned int i;
+
+	ret = hostapd_parse_csa_settings(pos, &settings);
 	if (ret)
 		return ret;
 
-	return hostapd_switch_channel(hapd, &settings);
+	for (i = 0; i < iface->num_bss; i++) {
+		ret = hostapd_switch_channel(iface->bss[i], &settings);
+		if (ret) {
+			/* FIX: What do we do if CSA fails in the middle of
+			 * submitting multi-BSS CSA requests? */
+			return ret;
+		}
+	}
+
+	return 0;
 #else /* NEED_AP_MLME */
 	return -1;
 #endif /* NEED_AP_MLME */
@@ -1541,7 +1553,7 @@
 			reply_len = -1;
 #endif /* CONFIG_TESTING_OPTIONS */
 	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
-		if (hostapd_ctrl_iface_chan_switch(hapd, buf + 12))
+		if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
 			reply_len = -1;
 	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
 		reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,

Modified: wpa/trunk/hostapd/hostapd_cli.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/hostapd/hostapd_cli.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/hostapd/hostapd_cli.c	(original)
+++ wpa/trunk/hostapd/hostapd_cli.c	Tue Oct 14 12:39:25 2014
@@ -238,28 +238,19 @@
 static int hostapd_cli_exec(const char *program, const char *arg1,
 			    const char *arg2)
 {
-	char *cmd;
+	char *arg;
 	size_t len;
 	int res;
-	int ret = 0;
-
-	len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
-	cmd = os_malloc(len);
-	if (cmd == NULL)
-		return -1;
-	res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
-	if (res < 0 || (size_t) res >= len) {
-		os_free(cmd);
-		return -1;
-	}
-	cmd[len - 1] = '\0';
-#ifndef _WIN32_WCE
-	if (system(cmd) < 0)
-		ret = -1;
-#endif /* _WIN32_WCE */
-	os_free(cmd);
-
-	return ret;
+
+	len = os_strlen(arg1) + os_strlen(arg2) + 2;
+	arg = os_malloc(len);
+	if (arg == NULL)
+		return -1;
+	os_snprintf(arg, len, "%s %s", arg1, arg2);
+	res = os_exec(program, arg, 1);
+	os_free(arg);
+
+	return res;
 }
 
 
@@ -844,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);

Modified: wpa/trunk/hostapd/main.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/hostapd/main.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/hostapd/main.c	(original)
+++ wpa/trunk/hostapd/main.c	Tue Oct 14 12:39:25 2014
@@ -97,14 +97,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();

Modified: wpa/trunk/hs20/client/Android.mk
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/hs20/client/Android.mk?rev=1909&op=diff
==============================================================================
--- wpa/trunk/hs20/client/Android.mk	(original)
+++ wpa/trunk/hs20/client/Android.mk	Tue Oct 14 12:39:25 2014
@@ -8,7 +8,11 @@
 INCLUDES += external/libxml2/include
 INCLUDES += external/curl/include
 INCLUDES += external/webkit/Source/WebKit/gtk
+ifneq ($(wildcard external/icu),)
+INCLUDES += external/icu/icu4c/source/common
+else
 INCLUDES += external/icu4c/common
+endif
 
 
 #GTKCFLAGS := $(shell pkg-config --cflags gtk+-2.0 webkit-1.0)

Modified: wpa/trunk/hs20/client/osu_client.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/hs20/client/osu_client.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/hs20/client/osu_client.c	(original)
+++ wpa/trunk/hs20/client/osu_client.c	Tue Oct 14 12:39:25 2014
@@ -2495,7 +2495,7 @@
 
 	xml_node_get_text_free(ctx->xml, sub_rem_uri);
 	xml_node_get_text_free(ctx->xml, cred_username);
-	os_free(cred_password);
+	str_clear_free(cred_password);
 	xml_node_free(ctx->xml, pps);
 }
 
@@ -2642,7 +2642,7 @@
 
 	xml_node_get_text_free(ctx->xml, uri);
 	xml_node_get_text_free(ctx->xml, cred_username);
-	os_free(cred_password);
+	str_clear_free(cred_password);
 	xml_node_free(ctx->xml, pps);
 
 	return 0;

Modified: wpa/trunk/src/ap/ap_config.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/ap_config.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/ap_config.c	(original)
+++ wpa/trunk/src/ap/ap_config.c	Tue Oct 14 12:39:25 2014
@@ -379,7 +379,7 @@
 {
 	hostapd_config_free_radius_attr(user->accept_attr);
 	os_free(user->identity);
-	os_free(user->password);
+	bin_clear_free(user->password, user->password_len);
 	os_free(user);
 }
 
@@ -388,7 +388,7 @@
 {
 	int i;
 	for (i = 0; i < NUM_WEP_KEYS; i++) {
-		os_free(keys->key[i]);
+		bin_clear_free(keys->key[i], keys->len[i]);
 		keys->key[i] = NULL;
 	}
 }
@@ -406,10 +406,10 @@
 	while (psk) {
 		prev = psk;
 		psk = psk->next;
-		os_free(prev);
-	}
-
-	os_free(conf->ssid.wpa_passphrase);
+		bin_clear_free(prev, sizeof(*prev));
+	}
+
+	str_clear_free(conf->ssid.wpa_passphrase);
 	os_free(conf->ssid.wpa_psk_file);
 	hostapd_config_free_wep(&conf->ssid.wep);
 #ifdef CONFIG_FULL_DYNAMIC_VLAN
@@ -759,7 +759,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 &&

Modified: wpa/trunk/src/ap/beacon.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/beacon.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/beacon.c	(original)
+++ wpa/trunk/src/ap/beacon.c	Tue Oct 14 12:39:25 2014
@@ -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.
@@ -220,7 +224,7 @@
 			continue; /* can use same entry */
 		}
 
-		if (start) {
+		if (start && prev) {
 			pos = hostapd_eid_country_add(pos, end, chan_spacing,
 						      start, prev);
 			start = NULL;
@@ -265,18 +269,18 @@
 {
 	u8 chan;
 
-	if (!hapd->iface->cs_freq_params.freq)
+	if (!hapd->cs_freq_params.freq)
 		return eid;
 
-	if (ieee80211_freq_to_chan(hapd->iface->cs_freq_params.freq, &chan) ==
+	if (ieee80211_freq_to_chan(hapd->cs_freq_params.freq, &chan) ==
 	    NUM_HOSTAPD_MODES)
 		return eid;
 
 	*eid++ = WLAN_EID_CHANNEL_SWITCH;
 	*eid++ = 3;
-	*eid++ = hapd->iface->cs_block_tx;
+	*eid++ = hapd->cs_block_tx;
 	*eid++ = chan;
-	*eid++ = hapd->iface->cs_count;
+	*eid++ = hapd->cs_count;
 
 	return eid;
 }
@@ -286,12 +290,12 @@
 {
 	u8 sec_ch;
 
-	if (!hapd->iface->cs_freq_params.sec_channel_offset)
+	if (!hapd->cs_freq_params.sec_channel_offset)
 		return eid;
 
-	if (hapd->iface->cs_freq_params.sec_channel_offset == -1)
+	if (hapd->cs_freq_params.sec_channel_offset == -1)
 		sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
-	else if (hapd->iface->cs_freq_params.sec_channel_offset == 1)
+	else if (hapd->cs_freq_params.sec_channel_offset == 1)
 		sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
 	else
 		return eid;
@@ -409,7 +413,7 @@
 	pos = hostapd_eid_roaming_consortium(hapd, pos);
 
 	pos = hostapd_add_csa_elems(hapd, pos, (u8 *)resp,
-				    &hapd->iface->cs_c_off_proberesp);
+				    &hapd->cs_c_off_proberesp);
 #ifdef CONFIG_IEEE80211AC
 	pos = hostapd_eid_vht_capabilities(hapd, pos);
 	pos = hostapd_eid_vht_operation(hapd, pos);
@@ -824,7 +828,7 @@
 	tailpos = hostapd_eid_adv_proto(hapd, tailpos);
 	tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
 	tailpos = hostapd_add_csa_elems(hapd, tailpos, tail,
-					&hapd->iface->cs_c_off_beacon);
+					&hapd->cs_c_off_beacon);
 #ifdef CONFIG_IEEE80211AC
 	tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
 	tailpos = hostapd_eid_vht_operation(hapd, tailpos);
@@ -957,7 +961,7 @@
 	struct wpabuf *beacon, *proberesp, *assocresp;
 	int res, ret = -1;
 
-	if (hapd->iface->csa_in_progress) {
+	if (hapd->csa_in_progress) {
 		wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period");
 		return -1;
 	}

Modified: wpa/trunk/src/ap/ctrl_iface_ap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/ctrl_iface_ap.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/ctrl_iface_ap.c	(original)
+++ wpa/trunk/src/ap/ctrl_iface_ap.c	Tue Oct 14 12:39:25 2014
@@ -230,11 +230,12 @@
 	if (mgmt == NULL)
 		return -1;
 
+	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR
-		" with minor reason code %u (stype=%u)",
-		MAC2STR(addr), minor_reason_code, stype);
-
-	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
+		" with minor reason code %u (stype=%u (%s))",
+		MAC2STR(addr), minor_reason_code, stype,
+		fc2str(mgmt->frame_control));
+
 	os_memcpy(mgmt->da, addr, ETH_ALEN);
 	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
 	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);

Modified: wpa/trunk/src/ap/dfs.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/dfs.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/dfs.c	(original)
+++ wpa/trunk/src/ap/dfs.c	Tue Oct 14 12:39:25 2014
@@ -18,9 +18,11 @@
 #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;
@@ -34,6 +36,10 @@
 			break;
 		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;
 		}
@@ -286,6 +301,23 @@
 			res = i;
 			break;
 		}
+	}
+
+	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) {
@@ -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,
@@ -756,6 +789,16 @@
 }
 
 
+static int hostapd_csa_in_progress(struct hostapd_iface *iface)
+{
+	unsigned int i;
+	for (i = 0; i < iface->num_bss; i++)
+		if (iface->bss[i]->csa_in_progress)
+			return 1;
+	return 0;
+}
+
+
 static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
 {
 	struct hostapd_channel_data *channel;
@@ -764,15 +807,15 @@
 	u8 vht_oper_centr_freq_seg1_idx;
 	int skip_radar = 1;
 	struct csa_settings csa_settings;
-	struct hostapd_data *hapd = iface->bss[0];
+	unsigned int i;
 	int err = 1;
 
 	wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
 		   __func__, iface->cac_started ? "yes" : "no",
-		   iface->csa_in_progress ? "yes" : "no");
+		   hostapd_csa_in_progress(iface) ? "yes" : "no");
 
 	/* Check if CSA in progress */
-	if (iface->csa_in_progress)
+	if (hostapd_csa_in_progress(iface))
 		return 0;
 
 	/* Check if active CAC */
@@ -843,7 +886,12 @@
 		return err;
 	}
 
-	err = hostapd_switch_channel(hapd, &csa_settings);
+	for (i = 0; i < iface->num_bss; i++) {
+		err = hostapd_switch_channel(iface->bss[i], &csa_settings);
+		if (err)
+			break;
+	}
+
 	if (err) {
 		wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback",
 			   err);
@@ -882,9 +930,8 @@
 		freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
 
 	/* mark radar frequency as invalid */
-	res = set_dfs_state(iface, freq, ht_enabled, chan_offset,
-			    chan_width, cf1, cf2,
-			    HOSTAPD_CHAN_DFS_UNAVAILABLE);
+	set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
+		      cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE);
 
 	/* Skip if reported radar event not overlapped our channels */
 	res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2);
@@ -914,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;
+}

Modified: wpa/trunk/src/ap/drv_callbacks.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/drv_callbacks.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/drv_callbacks.c	(original)
+++ wpa/trunk/src/ap/drv_callbacks.c	Tue Oct 14 12:39:25 2014
@@ -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) {
@@ -349,6 +352,8 @@
 	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
 	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);
@@ -489,9 +494,10 @@
 	hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx;
 	hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx;
 
-	if (hapd->iface->csa_in_progress &&
-	    freq == hapd->iface->cs_freq_params.freq) {
+	if (hapd->csa_in_progress &&
+	    freq == hapd->cs_freq_params.freq) {
 		hostapd_cleanup_cs_params(hapd);
+		ieee802_11_set_beacon(hapd);
 
 		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED "freq=%d",
 			freq);
@@ -884,6 +890,20 @@
 
 #ifdef NEED_AP_MLME
 
+static void hostapd_event_iface_unavailable(struct hostapd_data *hapd)
+{
+	wpa_printf(MSG_DEBUG, "Interface %s is unavailable -- stopped",
+		   hapd->conf->iface);
+
+	if (hapd->csa_in_progress) {
+		wpa_printf(MSG_INFO, "CSA failed (%s was stopped)",
+			   hapd->conf->iface);
+		hostapd_switch_channel_fallback(hapd->iface,
+						&hapd->cs_freq_params);
+	}
+}
+
+
 static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd,
 					     struct dfs_event *radar)
 {
@@ -1029,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,
@@ -1071,6 +1093,9 @@
 		hostapd_event_get_survey(hapd, &data->survey_results);
 		break;
 #ifdef NEED_AP_MLME
+	case EVENT_INTERFACE_UNAVAILABLE:
+		hostapd_event_iface_unavailable(hapd);
+		break;
 	case EVENT_DFS_RADAR_DETECTED:
 		if (!data)
 			break;

Modified: wpa/trunk/src/ap/eap_user_db.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/eap_user_db.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/eap_user_db.c	(original)
+++ wpa/trunk/src/ap/eap_user_db.c	Tue Oct 14 12:39:25 2014
@@ -83,7 +83,7 @@
 
 	for (i = 0; i < argc; i++) {
 		if (os_strcmp(col[i], "password") == 0 && argv[i]) {
-			os_free(user->password);
+			bin_clear_free(user->password, user->password_len);
 			user->password_len = os_strlen(argv[i]);
 			user->password = (u8 *) os_strdup(argv[i]);
 			user->next = (void *) 1;
@@ -118,7 +118,7 @@
 	if (len <= user->identity_len &&
 	    os_memcmp(argv[id], user->identity, len) == 0 &&
 	    (user->password == NULL || len > user->password_len)) {
-		os_free(user->password);
+		bin_clear_free(user->password, user->password_len);
 		user->password_len = os_strlen(argv[id]);
 		user->password = (u8 *) os_strdup(argv[id]);
 		user->next = (void *) 1;
@@ -158,8 +158,10 @@
 		return NULL;
 	}
 
-	os_free(hapd->tmp_eap_user.identity);
-	os_free(hapd->tmp_eap_user.password);
+	bin_clear_free(hapd->tmp_eap_user.identity,
+		       hapd->tmp_eap_user.identity_len);
+	bin_clear_free(hapd->tmp_eap_user.password,
+		       hapd->tmp_eap_user.password_len);
 	os_memset(&hapd->tmp_eap_user, 0, sizeof(hapd->tmp_eap_user));
 	hapd->tmp_eap_user.phase2 = phase2;
 	hapd->tmp_eap_user.identity = os_zalloc(identity_len + 1);

Modified: wpa/trunk/src/ap/gas_serv.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/gas_serv.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/gas_serv.c	(original)
+++ wpa/trunk/src/ap/gas_serv.c	Tue Oct 14 12:39:25 2014
@@ -414,7 +414,7 @@
 			gas_anqp_set_element_len(buf, realm_data_len);
 		}
 		gas_anqp_set_element_len(buf, len);
-	} else if (nai_home_realm && hapd->conf->nai_realm_data) {
+	} else if (nai_home_realm && hapd->conf->nai_realm_data && home_realm) {
 		hs20_add_nai_home_realm_matches(hapd, buf, home_realm,
 						home_realm_len);
 	}
@@ -686,7 +686,6 @@
 static struct wpabuf *
 gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
 				unsigned int request,
-				struct gas_dialog_info *di,
 				const u8 *home_realm, size_t home_realm_len,
 				const u8 *icon_name, size_t icon_name_len)
 {
@@ -962,7 +961,7 @@
 {
 	struct wpabuf *buf, *tx_buf;
 
-	buf = gas_serv_build_gas_resp_payload(hapd, qi->request, NULL,
+	buf = gas_serv_build_gas_resp_payload(hapd, qi->request,
 					      qi->home_realm_query,
 					      qi->home_realm_query_len,
 					      qi->icon_name, qi->icon_name_len);
@@ -1214,13 +1213,11 @@
 {
 	struct hostapd_data *hapd = ctx;
 	const struct ieee80211_mgmt *mgmt;
-	size_t hdr_len;
 	const u8 *sa, *data;
 	int prot;
 
 	mgmt = (const struct ieee80211_mgmt *) buf;
-	hdr_len = (const u8 *) &mgmt->u.action.u.vs_public_action.action - buf;
-	if (hdr_len > len)
+	if (len < IEEE80211_HDRLEN + 2)
 		return;
 	if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
 	    mgmt->u.action.category != WLAN_ACTION_PROTECTED_DUAL)
@@ -1232,8 +1229,8 @@
 	 */
 	prot = mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL;
 	sa = mgmt->sa;
-	len -= hdr_len;
-	data = &mgmt->u.action.u.public_action.action;
+	len -= IEEE80211_HDRLEN + 1;
+	data = buf + IEEE80211_HDRLEN + 1;
 	switch (data[0]) {
 	case WLAN_PA_GAS_INITIAL_REQ:
 		gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1, prot);

Modified: wpa/trunk/src/ap/hostapd.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/hostapd.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/hostapd.c	(original)
+++ wpa/trunk/src/ap/hostapd.c	Tue Oct 14 12:39:25 2014
@@ -311,8 +311,10 @@
 #endif /* CONFIG_INTERWORKING */
 
 #ifdef CONFIG_SQLITE
-	os_free(hapd->tmp_eap_user.identity);
-	os_free(hapd->tmp_eap_user.password);
+	bin_clear_free(hapd->tmp_eap_user.identity,
+		       hapd->tmp_eap_user.identity_len);
+	bin_clear_free(hapd->tmp_eap_user.password,
+		       hapd->tmp_eap_user.password_len);
 #endif /* CONFIG_SQLITE */
 }
 
@@ -691,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;
 	}
@@ -702,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;
@@ -747,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;
 
 	/*
@@ -781,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)) {
@@ -808,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);
@@ -845,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)) {
@@ -853,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;
@@ -879,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)
@@ -946,35 +947,24 @@
 
 	if (hapd->iface->drv_max_acl_mac_addrs == 0)
 		return;
-	if (!(conf->bss[0]->num_accept_mac || conf->bss[0]->num_deny_mac))
-		return;
 
 	if (conf->bss[0]->macaddr_acl == DENY_UNLESS_ACCEPTED) {
-		if (conf->bss[0]->num_accept_mac) {
-			accept_acl = 1;
-			err = hostapd_set_acl_list(hapd,
-						   conf->bss[0]->accept_mac,
-						   conf->bss[0]->num_accept_mac,
-						   accept_acl);
-			if (err) {
-				wpa_printf(MSG_DEBUG, "Failed to set accept acl");
-				return;
-			}
-		} else {
-			wpa_printf(MSG_DEBUG, "Mismatch between ACL Policy & Accept/deny lists file");
+		accept_acl = 1;
+		err = hostapd_set_acl_list(hapd, conf->bss[0]->accept_mac,
+					   conf->bss[0]->num_accept_mac,
+					   accept_acl);
+		if (err) {
+			wpa_printf(MSG_DEBUG, "Failed to set accept acl");
+			return;
 		}
 	} else if (conf->bss[0]->macaddr_acl == ACCEPT_UNLESS_DENIED) {
-		if (conf->bss[0]->num_deny_mac) {
-			accept_acl = 0;
-			err = hostapd_set_acl_list(hapd, conf->bss[0]->deny_mac,
-						   conf->bss[0]->num_deny_mac,
-						   accept_acl);
-			if (err) {
-				wpa_printf(MSG_DEBUG, "Failed to set deny acl");
-				return;
-			}
-		} else {
-			wpa_printf(MSG_DEBUG, "Mismatch between ACL Policy & Accept/deny lists file");
+		accept_acl = 0;
+		err = hostapd_set_acl_list(hapd, conf->bss[0]->deny_mac,
+					   conf->bss[0]->num_deny_mac,
+					   accept_acl);
+		if (err) {
+			wpa_printf(MSG_DEBUG, "Failed to set deny acl");
+			return;
 		}
 	}
 }
@@ -1191,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 */
 
@@ -2186,13 +2179,12 @@
 }
 
 
-static int hostapd_build_beacon_data(struct hostapd_iface *iface,
+static int hostapd_build_beacon_data(struct hostapd_data *hapd,
 				     struct beacon_data *beacon)
 {
 	struct wpabuf *beacon_extra, *proberesp_extra, *assocresp_extra;
 	struct wpa_driver_ap_params params;
 	int ret;
-	struct hostapd_data *hapd = iface->bss[0];
 
 	os_memset(beacon, 0, sizeof(*beacon));
 	ret = ieee802_11_build_ap_params(hapd, &params);
@@ -2292,12 +2284,12 @@
 
 	if (!params->channel) {
 		/* check if the new channel is supported by hw */
-		channel = hostapd_hw_get_channel(hapd, params->freq);
-		if (!channel)
-			return -1;
-	} else {
-		channel = params->channel;
-	}
+		params->channel = hostapd_hw_get_channel(hapd, params->freq);
+	}
+
+	channel = params->channel;
+	if (!channel)
+		return -1;
 
 	/* if a pointer to old_params is provided we save previous state */
 	if (old_params) {
@@ -2316,14 +2308,15 @@
 }
 
 
-static int hostapd_fill_csa_settings(struct hostapd_iface *iface,
+static int hostapd_fill_csa_settings(struct hostapd_data *hapd,
 				     struct csa_settings *settings)
 {
+	struct hostapd_iface *iface = hapd->iface;
 	struct hostapd_freq_params old_freq;
 	int ret;
 
 	os_memset(&old_freq, 0, sizeof(old_freq));
-	if (!iface || !iface->freq || iface->csa_in_progress)
+	if (!iface || !iface->freq || hapd->csa_in_progress)
 		return -1;
 
 	ret = hostapd_change_config_freq(iface->bss[0], iface->conf,
@@ -2332,7 +2325,7 @@
 	if (ret)
 		return ret;
 
-	ret = hostapd_build_beacon_data(iface, &settings->beacon_after);
+	ret = hostapd_build_beacon_data(hapd, &settings->beacon_after);
 
 	/* change back the configuration */
 	hostapd_change_config_freq(iface->bss[0], iface->conf,
@@ -2342,18 +2335,18 @@
 		return ret;
 
 	/* set channel switch parameters for csa ie */
-	iface->cs_freq_params = settings->freq_params;
-	iface->cs_count = settings->cs_count;
-	iface->cs_block_tx = settings->block_tx;
-
-	ret = hostapd_build_beacon_data(iface, &settings->beacon_csa);
+	hapd->cs_freq_params = settings->freq_params;
+	hapd->cs_count = settings->cs_count;
+	hapd->cs_block_tx = settings->block_tx;
+
+	ret = hostapd_build_beacon_data(hapd, &settings->beacon_csa);
 	if (ret) {
 		free_beacon_data(&settings->beacon_after);
 		return ret;
 	}
 
-	settings->counter_offset_beacon = iface->cs_c_off_beacon;
-	settings->counter_offset_presp = iface->cs_c_off_proberesp;
+	settings->counter_offset_beacon = hapd->cs_c_off_beacon;
+	settings->counter_offset_presp = hapd->cs_c_off_proberesp;
 
 	return 0;
 }
@@ -2361,13 +2354,12 @@
 
 void hostapd_cleanup_cs_params(struct hostapd_data *hapd)
 {
-	os_memset(&hapd->iface->cs_freq_params, 0,
-		  sizeof(hapd->iface->cs_freq_params));
-	hapd->iface->cs_count = 0;
-	hapd->iface->cs_block_tx = 0;
-	hapd->iface->cs_c_off_beacon = 0;
-	hapd->iface->cs_c_off_proberesp = 0;
-	hapd->iface->csa_in_progress = 0;
+	os_memset(&hapd->cs_freq_params, 0, sizeof(hapd->cs_freq_params));
+	hapd->cs_count = 0;
+	hapd->cs_block_tx = 0;
+	hapd->cs_c_off_beacon = 0;
+	hapd->cs_c_off_proberesp = 0;
+	hapd->csa_in_progress = 0;
 }
 
 
@@ -2375,7 +2367,7 @@
 			   struct csa_settings *settings)
 {
 	int ret;
-	ret = hostapd_fill_csa_settings(hapd->iface, settings);
+	ret = hostapd_fill_csa_settings(hapd, settings);
 	if (ret)
 		return ret;
 
@@ -2389,8 +2381,64 @@
 		return ret;
 	}
 
-	hapd->iface->csa_in_progress = 1;
+	hapd->csa_in_progress = 1;
 	return 0;
 }
 
+
+void
+hostapd_switch_channel_fallback(struct hostapd_iface *iface,
+				const struct hostapd_freq_params *freq_params)
+{
+	int vht_seg0_idx = 0, vht_seg1_idx = 0, vht_bw = VHT_CHANWIDTH_USE_HT;
+	unsigned int i;
+
+	wpa_printf(MSG_DEBUG, "Restarting all CSA-related BSSes");
+
+	if (freq_params->center_freq1)
+		vht_seg0_idx = 36 + (freq_params->center_freq1 - 5180) / 5;
+	if (freq_params->center_freq2)
+		vht_seg1_idx = 36 + (freq_params->center_freq2 - 5180) / 5;
+
+	switch (freq_params->bandwidth) {
+	case 0:
+	case 20:
+	case 40:
+		vht_bw = VHT_CHANWIDTH_USE_HT;
+		break;
+	case 80:
+		if (freq_params->center_freq2)
+			vht_bw = VHT_CHANWIDTH_80P80MHZ;
+		else
+			vht_bw = VHT_CHANWIDTH_80MHZ;
+		break;
+	case 160:
+		vht_bw = VHT_CHANWIDTH_160MHZ;
+		break;
+	default:
+		wpa_printf(MSG_WARNING, "Unknown CSA bandwidth: %d",
+			   freq_params->bandwidth);
+		break;
+	}
+
+	iface->freq = freq_params->freq;
+	iface->conf->channel = freq_params->channel;
+	iface->conf->secondary_channel = freq_params->sec_channel_offset;
+	iface->conf->vht_oper_centr_freq_seg0_idx = vht_seg0_idx;
+	iface->conf->vht_oper_centr_freq_seg1_idx = vht_seg1_idx;
+	iface->conf->vht_oper_chwidth = vht_bw;
+	iface->conf->ieee80211n = freq_params->ht_enabled;
+	iface->conf->ieee80211ac = freq_params->vht_enabled;
+
+	/*
+	 * cs_params must not be cleared earlier because the freq_params
+	 * argument may actually point to one of these.
+	 */
+	for (i = 0; i < iface->num_bss; i++)
+		hostapd_cleanup_cs_params(iface->bss[i]);
+
+	hostapd_disable_iface(iface);
+	hostapd_enable_iface(iface);
+}
+
 #endif /* NEED_AP_MLME */

Modified: wpa/trunk/src/ap/hostapd.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/hostapd.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/hostapd.h	(original)
+++ wpa/trunk/src/ap/hostapd.h	Tue Oct 14 12:39:25 2014
@@ -210,6 +210,14 @@
 			   size_t psk_len);
 	void *new_psk_cb_ctx;
 
+	/* channel switch parameters */
+	struct hostapd_freq_params cs_freq_params;
+	u8 cs_count;
+	int cs_block_tx;
+	unsigned int cs_c_off_beacon;
+	unsigned int cs_c_off_proberesp;
+	int csa_in_progress;
+
 #ifdef CONFIG_P2P
 	struct p2p_data *p2p;
 	struct p2p_group *p2p_group;
@@ -342,14 +350,6 @@
 
 	/* lowest observed noise floor in dBm */
 	s8 lowest_nf;
-
-	/* channel switch parameters */
-	struct hostapd_freq_params cs_freq_params;
-	u8 cs_count;
-	int cs_block_tx;
-	unsigned int cs_c_off_beacon;
-	unsigned int cs_c_off_proberesp;
-	int csa_in_progress;
 
 	unsigned int dfs_cac_ms;
 	struct os_reltime dfs_cac_start;
@@ -397,6 +397,9 @@
 const char * hostapd_state_text(enum hostapd_iface_state s);
 int hostapd_switch_channel(struct hostapd_data *hapd,
 			   struct csa_settings *settings);
+void
+hostapd_switch_channel_fallback(struct hostapd_iface *iface,
+				const struct hostapd_freq_params *freq_params);
 void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
 
 /* utils.c */

Modified: wpa/trunk/src/ap/ieee802_11.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/ieee802_11.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/ieee802_11.c	(original)
+++ wpa/trunk/src/ap/ieee802_11.c	Tue Oct 14 12:39:25 2014
@@ -236,7 +236,8 @@
 
 	/* Transaction 3 */
 	if (!iswep || !sta->challenge || !challenge ||
-	    os_memcmp(sta->challenge, challenge, WLAN_AUTH_CHALLENGE_LEN)) {
+	    os_memcmp_const(sta->challenge, challenge,
+			    WLAN_AUTH_CHALLENGE_LEN)) {
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_INFO,
 			       "shared key authentication - invalid "
@@ -402,7 +403,7 @@
 		return -1;
 	if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
 			addr, ETH_ALEN, mac) < 0 ||
-	    os_memcmp(token, mac, SHA256_MAC_LEN) != 0)
+	    os_memcmp_const(token, mac, SHA256_MAC_LEN) != 0)
 		return -1;
 
 	return 0;

Modified: wpa/trunk/src/ap/ieee802_11_ht.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/ieee802_11_ht.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/ieee802_11_ht.c	(original)
+++ wpa/trunk/src/ap/ieee802_11_ht.c	Tue Oct 14 12:39:25 2014
@@ -211,8 +211,7 @@
 	struct ieee80211_2040_intol_chan_report *ic_report;
 	int is_ht_allowed = 1;
 	int i;
-	const u8 *data = (const u8 *) &mgmt->u.action.u.public_action.action;
-	size_t hdr_len;
+	const u8 *data = ((const u8 *) mgmt) + 1;
 
 	hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_DEBUG, "hostapd_public_action - action=%d",
@@ -221,8 +220,7 @@
 	if (!(iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
 		return;
 
-	hdr_len = data - (u8 *) mgmt;
-	if (hdr_len > len)
+	if (len < IEEE80211_HDRLEN + 1)
 		return;
 	data++;
 

Modified: wpa/trunk/src/ap/ieee802_11_vht.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/ieee802_11_vht.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/ieee802_11_vht.c	(original)
+++ wpa/trunk/src/ap/ieee802_11_vht.c	Tue Oct 14 12:39:25 2014
@@ -112,23 +112,9 @@
 u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta,
 		       const u8 *vht_oper_notif)
 {
-	u8 channel_width;
-
 	if (!vht_oper_notif) {
 		sta->flags &= ~WLAN_STA_VHT_OPMODE_ENABLED;
 		return WLAN_STATUS_SUCCESS;
-	}
-
-	channel_width = *vht_oper_notif & VHT_OPMODE_CHANNEL_WIDTH_MASK;
-
-	if (channel_width != VHT_CHANWIDTH_USE_HT &&
-	    channel_width != VHT_CHANWIDTH_80MHZ &&
-	    channel_width != VHT_CHANWIDTH_160MHZ &&
-	    channel_width != VHT_CHANWIDTH_80P80MHZ &&
-	    ((*vht_oper_notif & VHT_OPMODE_CHANNEL_RxNSS_MASK) >>
-	     VHT_OPMODE_NOTIF_RX_NSS_SHIFT) > VHT_RX_NSS_MAX_STREAMS - 1) {
-		sta->flags &= ~WLAN_STA_VHT_OPMODE_ENABLED;
-		return WLAN_STATUS_UNSPECIFIED_FAILURE;
 	}
 
 	sta->flags |= WLAN_STA_VHT_OPMODE_ENABLED;

Modified: wpa/trunk/src/ap/ieee802_1x.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/ieee802_1x.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/ieee802_1x.c	(original)
+++ wpa/trunk/src/ap/ieee802_1x.c	Tue Oct 14 12:39:25 2014
@@ -306,6 +306,67 @@
 }
 
 
+static int add_common_radius_sta_attr_rsn(struct hostapd_data *hapd,
+					  struct hostapd_radius_attr *req_attr,
+					  struct sta_info *sta,
+					  struct radius_msg *msg)
+{
+	u32 suite;
+	int ver, val;
+
+	ver = wpa_auth_sta_wpa_version(sta->wpa_sm);
+	val = wpa_auth_get_pairwise(sta->wpa_sm);
+	suite = wpa_cipher_to_suite(ver, val);
+	if (val != -1 &&
+	    !hostapd_config_get_radius_attr(req_attr,
+					    RADIUS_ATTR_WLAN_PAIRWISE_CIPHER) &&
+	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_PAIRWISE_CIPHER,
+				       suite)) {
+		wpa_printf(MSG_ERROR, "Could not add WLAN-Pairwise-Cipher");
+		return -1;
+	}
+
+	suite = wpa_cipher_to_suite((hapd->conf->wpa & 0x2) ?
+				    WPA_PROTO_RSN : WPA_PROTO_WPA,
+				    hapd->conf->wpa_group);
+	if (!hostapd_config_get_radius_attr(req_attr,
+					    RADIUS_ATTR_WLAN_GROUP_CIPHER) &&
+	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_GROUP_CIPHER,
+				       suite)) {
+		wpa_printf(MSG_ERROR, "Could not add WLAN-Group-Cipher");
+		return -1;
+	}
+
+	val = wpa_auth_sta_key_mgmt(sta->wpa_sm);
+	suite = wpa_akm_to_suite(val);
+	if (val != -1 &&
+	    !hostapd_config_get_radius_attr(req_attr,
+					    RADIUS_ATTR_WLAN_AKM_SUITE) &&
+	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_AKM_SUITE,
+				       suite)) {
+		wpa_printf(MSG_ERROR, "Could not add WLAN-AKM-Suite");
+		return -1;
+	}
+
+#ifdef CONFIG_IEEE80211W
+	if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+		suite = wpa_cipher_to_suite(WPA_PROTO_RSN,
+					    hapd->conf->group_mgmt_cipher);
+		if (!hostapd_config_get_radius_attr(
+			    req_attr, RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER) &&
+		    !radius_msg_add_attr_int32(
+			    msg, RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER, suite)) {
+			wpa_printf(MSG_ERROR,
+				   "Could not add WLAN-Group-Mgmt-Cipher");
+			return -1;
+		}
+	}
+#endif /* CONFIG_IEEE80211W */
+
+	return 0;
+}
+
+
 static int add_common_radius_sta_attr(struct hostapd_data *hapd,
 				      struct hostapd_radius_attr *req_attr,
 				      struct sta_info *sta,
@@ -356,6 +417,25 @@
 			return -1;
 		}
 	}
+
+#ifdef CONFIG_IEEE80211R
+	if (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
+	    sta->wpa_sm &&
+	    (wpa_key_mgmt_ft(wpa_auth_sta_key_mgmt(sta->wpa_sm)) ||
+	     sta->auth_alg == WLAN_AUTH_FT) &&
+	    !hostapd_config_get_radius_attr(req_attr,
+					    RADIUS_ATTR_MOBILITY_DOMAIN_ID) &&
+	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_MOBILITY_DOMAIN_ID,
+				       WPA_GET_BE16(
+					       hapd->conf->mobility_domain))) {
+		wpa_printf(MSG_ERROR, "Could not add Mobility-Domain-Id");
+		return -1;
+	}
+#endif /* CONFIG_IEEE80211R */
+
+	if (hapd->conf->wpa && sta->wpa_sm &&
+	    add_common_radius_sta_attr_rsn(hapd, req_attr, sta, msg) < 0)
+		return -1;
 
 	return 0;
 }
@@ -419,6 +499,22 @@
 		wpa_printf(MSG_ERROR, "Could not add NAS-Port-Type");
 		return -1;
 	}
+
+#ifdef CONFIG_INTERWORKING
+	if (hapd->conf->interworking &&
+	    !is_zero_ether_addr(hapd->conf->hessid)) {
+		os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
+			    MAC2STR(hapd->conf->hessid));
+		buf[sizeof(buf) - 1] = '\0';
+		if (!hostapd_config_get_radius_attr(req_attr,
+						    RADIUS_ATTR_WLAN_HESSID) &&
+		    !radius_msg_add_attr(msg, RADIUS_ATTR_WLAN_HESSID,
+					 (u8 *) buf, os_strlen(buf))) {
+			wpa_printf(MSG_ERROR, "Could not add WLAN-HESSID");
+			return -1;
+		}
+	}
+#endif /* CONFIG_INTERWORKING */
 
 	if (sta && add_common_radius_sta_attr(hapd, req_attr, sta, msg) < 0)
 		return -1;
@@ -1525,6 +1621,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 ==
@@ -2300,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) {
@@ -2334,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,

Modified: wpa/trunk/src/ap/pmksa_cache_auth.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/pmksa_cache_auth.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/pmksa_cache_auth.c	(original)
+++ wpa/trunk/src/ap/pmksa_cache_auth.c	Tue Oct 14 12:39:25 2014
@@ -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;
 }

Modified: wpa/trunk/src/ap/sta_info.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/sta_info.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/sta_info.c	(original)
+++ wpa/trunk/src/ap/sta_info.c	Tue Oct 14 12:39:25 2014
@@ -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) {

Modified: wpa/trunk/src/ap/sta_info.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/sta_info.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/sta_info.h	(original)
+++ wpa/trunk/src/ap/sta_info.h	Tue Oct 14 12:39:25 2014
@@ -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 */
 };
 
 

Modified: wpa/trunk/src/ap/wnm_ap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/wnm_ap.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/wnm_ap.c	(original)
+++ wpa/trunk/src/ap/wnm_ap.c	Tue Oct 14 12:39:25 2014
@@ -376,10 +376,9 @@
 	if (len < IEEE80211_HDRLEN + 2)
 		return -1;
 
-	payload = &mgmt->u.action.category;
-	payload++;
+	payload = ((const u8 *) mgmt) + IEEE80211_HDRLEN + 1;
 	action = *payload++;
-	plen = (((const u8 *) mgmt) + len) - payload;
+	plen = len - IEEE80211_HDRLEN - 2;
 
 	switch (action) {
 	case WNM_BSS_TRANS_MGMT_QUERY:

Modified: wpa/trunk/src/ap/wpa_auth.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/wpa_auth.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/wpa_auth.c	(original)
+++ wpa/trunk/src/ap/wpa_auth.c	Tue Oct 14 12:39:25 2014
@@ -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);
@@ -1490,7 +1491,7 @@
 	os_memset(key->key_mic, 0, 16);
 	if (wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK,
 			      data, data_len, key->key_mic) ||
-	    os_memcmp(mic, key->key_mic, 16) != 0)
+	    os_memcmp_const(mic, key->key_mic, 16) != 0)
 		ret = -1;
 	os_memcpy(key->key_mic, mic, 16);
 	return ret;
@@ -1877,8 +1878,8 @@
 		 * Verify that PMKR1Name from EAPOL-Key message 2/4 matches
 		 * with the value we derived.
 		 */
-		if (os_memcmp(sm->sup_pmk_r1_name, sm->pmk_r1_name,
-			      WPA_PMK_NAME_LEN) != 0) {
+		if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
+				    WPA_PMK_NAME_LEN) != 0) {
 			wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
 					"PMKR1Name mismatch in FT 4-way "
 					"handshake");

Modified: wpa/trunk/src/ap/wpa_auth_ft.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/ap/wpa_auth_ft.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/ap/wpa_auth_ft.c	(original)
+++ wpa/trunk/src/ap/wpa_auth_ft.c	Tue Oct 14 12:39:25 2014
@@ -235,8 +235,8 @@
 	r0 = cache->pmk_r0;
 	while (r0) {
 		if (os_memcmp(r0->spa, spa, ETH_ALEN) == 0 &&
-		    os_memcmp(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN)
-		    == 0) {
+		    os_memcmp_const(r0->pmk_r0_name, pmk_r0_name,
+				    WPA_PMK_NAME_LEN) == 0) {
 			os_memcpy(pmk_r0, r0->pmk_r0, PMK_LEN);
 			if (pairwise)
 				*pairwise = r0->pairwise;
@@ -285,8 +285,8 @@
 	r1 = cache->pmk_r1;
 	while (r1) {
 		if (os_memcmp(r1->spa, spa, ETH_ALEN) == 0 &&
-		    os_memcmp(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN)
-		    == 0) {
+		    os_memcmp_const(r1->pmk_r1_name, pmk_r1_name,
+				    WPA_PMK_NAME_LEN) == 0) {
 			os_memcpy(pmk_r1, r1->pmk_r1, PMK_LEN);
 			if (pairwise)
 				*pairwise = r1->pairwise;
@@ -310,7 +310,8 @@
 	r0kh = sm->wpa_auth->conf.r0kh_list;
 	while (r0kh) {
 		if (r0kh->id_len == sm->r0kh_id_len &&
-		    os_memcmp(r0kh->id, sm->r0kh_id, sm->r0kh_id_len) == 0)
+		    os_memcmp_const(r0kh->id, sm->r0kh_id, sm->r0kh_id_len) ==
+		    0)
 			break;
 		r0kh = r0kh->next;
 	}
@@ -343,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;
 
@@ -458,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;
 	}
@@ -490,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;
@@ -1013,8 +1015,8 @@
 		return WLAN_STATUS_INVALID_PMKID;
 	}
 
-	if (os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0)
-	{
+	if (os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)
+	    != 0) {
 		wpa_printf(MSG_DEBUG, "FT: PMKID in Reassoc Req did not match "
 			   "with the PMKR1Name derived from auth request");
 		return WLAN_STATUS_INVALID_PMKID;
@@ -1060,7 +1062,8 @@
 	}
 
 	if (parse.r0kh_id_len != sm->r0kh_id_len ||
-	    os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) {
+	    os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
+	{
 		wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
 			   "the current R0KH-ID");
 		wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
@@ -1075,8 +1078,8 @@
 		return -1;
 	}
 
-	if (os_memcmp(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder,
-		      FT_R1KH_ID_LEN) != 0) {
+	if (os_memcmp_const(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder,
+			    FT_R1KH_ID_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
 			   "ReassocReq");
 		wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE",
@@ -1087,7 +1090,8 @@
 	}
 
 	if (parse.rsn_pmkid == NULL ||
-	    os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) {
+	    os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN))
+	{
 		wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
 			   "RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
 		return -1;
@@ -1113,7 +1117,7 @@
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
 	}
 
-	if (os_memcmp(mic, ftie->mic, 16) != 0) {
+	if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
 		wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
 		wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR,
 			   MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr));
@@ -1333,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));
@@ -1373,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;
@@ -1461,15 +1467,16 @@
 	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));
 		return -1;
 	}
 
-	if (os_memcmp(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN)
-	    != 0) {
+	if (os_memcmp_const(f.r1kh_id, wpa_auth->conf.r1_key_holder,
+			    FT_R1KH_ID_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull response did not use a "
 			   "matching R1KH-ID");
 		return -1;
@@ -1527,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));
@@ -1544,8 +1552,8 @@
 		return -1;
 	}
 
-	if (os_memcmp(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN)
-	    != 0) {
+	if (os_memcmp_const(f.r1kh_id, wpa_auth->conf.r1_key_holder,
+			    FT_R1KH_ID_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not use a matching "
 			   "R1KH-ID (received " MACSTR " own " MACSTR ")",
 			   MAC2STR(f.r1kh_id),
@@ -1684,6 +1692,11 @@
 		wpa_printf(MSG_DEBUG, "FT: RRB discarded frame with unknown "
 			   "packet_type %d", frame->packet_type);
 		return -1;
+	}
+
+	if (end > pos) {
+		wpa_hexdump(MSG_DEBUG, "FT: Ignore extra data in end",
+			    pos, end - pos);
 	}
 
 	return 0;
@@ -1719,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;
 

Modified: wpa/trunk/src/common/ieee802_11_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/common/ieee802_11_common.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/common/ieee802_11_common.c	(original)
+++ wpa/trunk/src/common/ieee802_11_common.c	Tue Oct 14 12:39:25 2014
@@ -546,3 +546,60 @@
 
 	return num_11b > 0 && num_others == 0;
 }
+
+
+const char * fc2str(u16 fc)
+{
+	u16 stype = WLAN_FC_GET_STYPE(fc);
+#define C2S(x) case x: return #x;
+
+	switch (WLAN_FC_GET_TYPE(fc)) {
+	case WLAN_FC_TYPE_MGMT:
+		switch (stype) {
+		C2S(WLAN_FC_STYPE_ASSOC_REQ)
+		C2S(WLAN_FC_STYPE_ASSOC_RESP)
+		C2S(WLAN_FC_STYPE_REASSOC_REQ)
+		C2S(WLAN_FC_STYPE_REASSOC_RESP)
+		C2S(WLAN_FC_STYPE_PROBE_REQ)
+		C2S(WLAN_FC_STYPE_PROBE_RESP)
+		C2S(WLAN_FC_STYPE_BEACON)
+		C2S(WLAN_FC_STYPE_ATIM)
+		C2S(WLAN_FC_STYPE_DISASSOC)
+		C2S(WLAN_FC_STYPE_AUTH)
+		C2S(WLAN_FC_STYPE_DEAUTH)
+		C2S(WLAN_FC_STYPE_ACTION)
+		}
+		break;
+	case WLAN_FC_TYPE_CTRL:
+		switch (stype) {
+		C2S(WLAN_FC_STYPE_PSPOLL)
+		C2S(WLAN_FC_STYPE_RTS)
+		C2S(WLAN_FC_STYPE_CTS)
+		C2S(WLAN_FC_STYPE_ACK)
+		C2S(WLAN_FC_STYPE_CFEND)
+		C2S(WLAN_FC_STYPE_CFENDACK)
+		}
+		break;
+	case WLAN_FC_TYPE_DATA:
+		switch (stype) {
+		C2S(WLAN_FC_STYPE_DATA)
+		C2S(WLAN_FC_STYPE_DATA_CFACK)
+		C2S(WLAN_FC_STYPE_DATA_CFPOLL)
+		C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
+		C2S(WLAN_FC_STYPE_NULLFUNC)
+		C2S(WLAN_FC_STYPE_CFACK)
+		C2S(WLAN_FC_STYPE_CFPOLL)
+		C2S(WLAN_FC_STYPE_CFACKPOLL)
+		C2S(WLAN_FC_STYPE_QOS_DATA)
+		C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
+		C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
+		C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
+		C2S(WLAN_FC_STYPE_QOS_NULL)
+		C2S(WLAN_FC_STYPE_QOS_CFPOLL)
+		C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
+		}
+		break;
+	}
+	return "WLAN_FC_TYPE_UNKNOWN";
+#undef C2S
+}

Modified: wpa/trunk/src/common/ieee802_11_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/common/ieee802_11_common.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/common/ieee802_11_common.h	(original)
+++ wpa/trunk/src/common/ieee802_11_common.h	Tue Oct 14 12:39:25 2014
@@ -98,4 +98,5 @@
 
 int supp_rates_11b_only(struct ieee802_11_elems *elems);
 
+const char * fc2str(u16 fc);
 #endif /* IEEE802_11_COMMON_H */

Modified: wpa/trunk/src/common/ieee802_11_defs.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/common/ieee802_11_defs.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/common/ieee802_11_defs.h	(original)
+++ wpa/trunk/src/common/ieee802_11_defs.h	Tue Oct 14 12:39:25 2014
@@ -809,6 +809,7 @@
 #define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
 				* 00:50:F2 */
 #define WPA_IE_VENDOR_TYPE 0x0050f201
+#define WMM_IE_VENDOR_TYPE 0x0050f202
 #define WPS_IE_VENDOR_TYPE 0x0050f204
 #define OUI_WFA 0x506f9a
 #define P2P_IE_VENDOR_TYPE 0x506f9a09

Modified: wpa/trunk/src/common/qca-vendor.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/common/qca-vendor.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/common/qca-vendor.h	(original)
+++ wpa/trunk/src/common/qca-vendor.h	Tue Oct 14 12:39:25 2014
@@ -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..19 - reserved for QCA */
+	/* 14..49 - reserved for QCA */
 };
 
 
@@ -64,9 +72,21 @@
 	QCA_WLAN_VENDOR_ATTR_NAN     = 2,
 	/* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */
 	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 */

Modified: wpa/trunk/src/common/sae.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/common/sae.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/common/sae.c	(original)
+++ wpa/trunk/src/common/sae.c	Tue Oct 14 12:39:25 2014
@@ -1051,7 +1051,7 @@
 				   sae->tmp->own_commit_element_ffc,
 				   verifier);
 
-	if (os_memcmp(verifier, data + 2, SHA256_MAC_LEN) != 0) {
+	if (os_memcmp_const(verifier, data + 2, SHA256_MAC_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
 		wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
 			    data + 2, SHA256_MAC_LEN);

Modified: wpa/trunk/src/common/version.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/common/version.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/common/version.h	(original)
+++ wpa/trunk/src/common/version.h	Tue Oct 14 12:39:25 2014
@@ -5,6 +5,6 @@
 #define VERSION_STR_POSTFIX ""
 #endif /* VERSION_STR_POSTFIX */
 
-#define VERSION_STR "2.2" VERSION_STR_POSTFIX
+#define VERSION_STR "2.3" VERSION_STR_POSTFIX
 
 #endif /* VERSION_H */

Modified: wpa/trunk/src/common/wpa_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/common/wpa_common.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/common/wpa_common.c	(original)
+++ wpa/trunk/src/common/wpa_common.c	Tue Oct 14 12:39:25 2014
@@ -1002,6 +1002,30 @@
 }
 
 
+u32 wpa_akm_to_suite(int akm)
+{
+	if (akm & WPA_KEY_MGMT_FT_IEEE8021X)
+		return WLAN_AKM_SUITE_FT_8021X;
+	if (akm & WPA_KEY_MGMT_FT_PSK)
+		return WLAN_AKM_SUITE_FT_PSK;
+	if (akm & WPA_KEY_MGMT_IEEE8021X)
+		return WLAN_AKM_SUITE_8021X;
+	if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256)
+		return WLAN_AKM_SUITE_8021X_SHA256;
+	if (akm & WPA_KEY_MGMT_IEEE8021X)
+		return WLAN_AKM_SUITE_8021X;
+	if (akm & WPA_KEY_MGMT_PSK_SHA256)
+		return WLAN_AKM_SUITE_PSK_SHA256;
+	if (akm & WPA_KEY_MGMT_PSK)
+		return WLAN_AKM_SUITE_PSK;
+	if (akm & WPA_KEY_MGMT_CCKM)
+		return WLAN_AKM_SUITE_CCKM;
+	if (akm & WPA_KEY_MGMT_OSEN)
+		return WLAN_AKM_SUITE_OSEN;
+	return 0;
+}
+
+
 int wpa_compare_rsn_ie(int ft_initial_assoc,
 		       const u8 *ie1, size_t ie1len,
 		       const u8 *ie2, size_t ie2len)

Modified: wpa/trunk/src/common/wpa_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/common/wpa_common.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/common/wpa_common.h	(original)
+++ wpa/trunk/src/common/wpa_common.h	Tue Oct 14 12:39:25 2014
@@ -377,6 +377,7 @@
 
 const char * wpa_cipher_txt(int cipher);
 const char * wpa_key_mgmt_txt(int key_mgmt, int proto);
+u32 wpa_akm_to_suite(int akm);
 int wpa_compare_rsn_ie(int ft_initial_assoc,
 		       const u8 *ie1, size_t ie1len,
 		       const u8 *ie2, size_t ie2len);

Modified: wpa/trunk/src/common/wpa_ctrl.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/common/wpa_ctrl.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/common/wpa_ctrl.h	(original)
+++ wpa/trunk/src/common/wpa_ctrl.h	Tue Oct 14 12:39:25 2014
@@ -239,6 +239,25 @@
 #define WPA_BSS_MASK_DELIM		BIT(17)
 
 
+/* VENDOR_ELEM_* frame id values */
+enum wpa_vendor_elem_frame {
+	VENDOR_ELEM_PROBE_REQ_P2P = 0,
+	VENDOR_ELEM_PROBE_RESP_P2P = 1,
+	VENDOR_ELEM_PROBE_RESP_P2P_GO = 2,
+	VENDOR_ELEM_BEACON_P2P_GO = 3,
+	VENDOR_ELEM_P2P_PD_REQ = 4,
+	VENDOR_ELEM_P2P_PD_RESP = 5,
+	VENDOR_ELEM_P2P_GO_NEG_REQ = 6,
+	VENDOR_ELEM_P2P_GO_NEG_RESP = 7,
+	VENDOR_ELEM_P2P_GO_NEG_CONF = 8,
+	VENDOR_ELEM_P2P_INV_REQ = 9,
+	VENDOR_ELEM_P2P_INV_RESP = 10,
+	VENDOR_ELEM_P2P_ASSOC_REQ = 11,
+	VENDOR_ELEM_P2P_ASSOC_RESP = 12,
+	NUM_VENDOR_ELEM_FRAMES
+};
+
+
 /* wpa_supplicant/hostapd control interface access */
 
 /**
@@ -326,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.
  */

Modified: wpa/trunk/src/crypto/aes-ccm.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/crypto/aes-ccm.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/crypto/aes-ccm.c	(original)
+++ wpa/trunk/src/crypto/aes-ccm.c	Tue Oct 14 12:39:25 2014
@@ -203,7 +203,7 @@
 
 	aes_encrypt_deinit(aes);
 
-	if (os_memcmp(x, t, M) != 0) {
+	if (os_memcmp_const(x, t, M) != 0) {
 		wpa_printf(MSG_EXCESSIVE, "CCM: Auth mismatch");
 		return -1;
 	}

Modified: wpa/trunk/src/crypto/aes-gcm.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/crypto/aes-gcm.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/crypto/aes-gcm.c	(original)
+++ wpa/trunk/src/crypto/aes-gcm.c	Tue Oct 14 12:39:25 2014
@@ -310,7 +310,7 @@
 
 	aes_encrypt_deinit(aes);
 
-	if (os_memcmp(tag, T, 16) != 0) {
+	if (os_memcmp_const(tag, T, 16) != 0) {
 		wpa_printf(MSG_EXCESSIVE, "GCM: Tag mismatch");
 		return -1;
 	}

Modified: wpa/trunk/src/crypto/aes-unwrap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/crypto/aes-unwrap.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/crypto/aes-unwrap.c	(original)
+++ wpa/trunk/src/crypto/aes-unwrap.c	Tue Oct 14 12:39:25 2014
@@ -1,5 +1,5 @@
 /*
- * AES key unwrap (128-bit KEK, RFC3394)
+ * AES key unwrap (RFC3394)
  *
  * Copyright (c) 2003-2007, Jouni Malinen <j at 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);

Modified: wpa/trunk/src/crypto/aes-wrap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/crypto/aes-wrap.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/crypto/aes-wrap.c	(original)
+++ wpa/trunk/src/crypto/aes-wrap.c	Tue Oct 14 12:39:25 2014
@@ -1,5 +1,5 @@
 /*
- * AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * AES Key Wrap Algorithm (RFC3394)
  *
  * Copyright (c) 2003-2007, Jouni Malinen <j at 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;
 		}

Modified: wpa/trunk/src/crypto/aes_wrap.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/crypto/aes_wrap.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/crypto/aes_wrap.h	(original)
+++ wpa/trunk/src/crypto/aes_wrap.h	Tue Oct 14 12:39:25 2014
@@ -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);

Modified: wpa/trunk/src/crypto/crypto_openssl.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/crypto/crypto_openssl.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/crypto/crypto_openssl.c	(original)
+++ wpa/trunk/src/crypto/crypto_openssl.c	Tue Oct 14 12:39:25 2014
@@ -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();
 	}
@@ -340,10 +342,10 @@
 	ret = 0;
 
 error:
-	BN_free(bn_base);
-	BN_free(bn_exp);
-	BN_free(bn_modulus);
-	BN_free(bn_result);
+	BN_clear_free(bn_base);
+	BN_clear_free(bn_exp);
+	BN_clear_free(bn_modulus);
+	BN_clear_free(bn_result);
 	BN_CTX_free(ctx);
 	return ret;
 }
@@ -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;
@@ -571,12 +575,12 @@
 	if (keylen < 0)
 		goto err;
 	wpabuf_put(res, keylen);
-	BN_free(pub_key);
+	BN_clear_free(pub_key);
 
 	return res;
 
 err:
-	BN_free(pub_key);
+	BN_clear_free(pub_key);
 	wpabuf_free(res);
 	return NULL;
 }
@@ -1066,7 +1070,8 @@
 {
 	if (e == NULL)
 		return;
-	BN_free(e->order);
+	BN_clear_free(e->order);
+	BN_clear_free(e->prime);
 	EC_GROUP_free(e->group);
 	BN_CTX_free(e->bnctx);
 	os_free(e);
@@ -1138,8 +1143,8 @@
 		ret = 0;
 	}
 
-	BN_free(x_bn);
-	BN_free(y_bn);
+	BN_clear_free(x_bn);
+	BN_clear_free(y_bn);
 	return ret;
 }
 
@@ -1155,20 +1160,20 @@
 	y = BN_bin2bn(val + len, len, NULL);
 	elem = EC_POINT_new(e->group);
 	if (x == NULL || y == NULL || elem == NULL) {
-		BN_free(x);
-		BN_free(y);
-		EC_POINT_free(elem);
+		BN_clear_free(x);
+		BN_clear_free(y);
+		EC_POINT_clear_free(elem);
 		return NULL;
 	}
 
 	if (!EC_POINT_set_affine_coordinates_GFp(e->group, elem, x, y,
 						 e->bnctx)) {
-		EC_POINT_free(elem);
+		EC_POINT_clear_free(elem);
 		elem = NULL;
 	}
 
-	BN_free(x);
-	BN_free(y);
+	BN_clear_free(x);
+	BN_clear_free(y);
 
 	return (struct crypto_ec_point *) elem;
 }

Modified: wpa/trunk/src/crypto/milenage.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/crypto/milenage.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/crypto/milenage.c	(original)
+++ wpa/trunk/src/crypto/milenage.c	Tue Oct 14 12:39:25 2014
@@ -217,7 +217,7 @@
 	for (i = 0; i < 6; i++)
 		sqn[i] = auts[i] ^ ak[i];
 	if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) ||
-	    memcmp(mac_s, auts + 6, 8) != 0)
+	    os_memcmp_const(mac_s, auts + 6, 8) != 0)
 		return -1;
 	return 0;
 }
@@ -312,7 +312,7 @@
 
 	wpa_hexdump(MSG_DEBUG, "Milenage: MAC_A", mac_a, 8);
 
-	if (os_memcmp(mac_a, autn + 8, 8) != 0) {
+	if (os_memcmp_const(mac_a, autn + 8, 8) != 0) {
 		wpa_printf(MSG_DEBUG, "Milenage: MAC mismatch");
 		wpa_hexdump(MSG_DEBUG, "Milenage: Received MAC_A",
 			    autn + 8, 8);

Modified: wpa/trunk/src/crypto/tls_openssl.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/crypto/tls_openssl.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/crypto/tls_openssl.c	(original)
+++ wpa/trunk/src/crypto/tls_openssl.c	Tue Oct 14 12:39:25 2014
@@ -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;

Modified: wpa/trunk/src/drivers/driver.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/drivers/driver.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/drivers/driver.h	(original)
+++ wpa/trunk/src/drivers/driver.h	Tue Oct 14 12:39:25 2014
@@ -351,7 +351,7 @@
 	 * Mbps from the support rates element(s) in the Probe Request frames
 	 * and not to transmit the frames at any of those rates.
 	 */
-	u8 p2p_probe;
+	unsigned int p2p_probe:1;
 
 	/**
 	 * only_new_results - Request driver to report only new results
@@ -360,7 +360,15 @@
 	 * been detected after this scan request has been started, i.e., to
 	 * flush old cached BSS entries.
 	 */
-	int only_new_results;
+	unsigned int only_new_results:1;
+
+	/**
+	 * low_priority - Requests driver to use a lower scan priority
+	 *
+	 * This is used to request the driver to use a lower scan priority
+	 * if it supports such a thing.
+	 */
+	unsigned int low_priority:1;
 
 	/*
 	 * NOTE: Whenever adding new parameters here, please make sure
@@ -403,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().
@@ -435,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)
-	 */
-	int freq;
+	 * freq - channel parameters
+	 */
+	struct hostapd_freq_params freq;
 
 	/**
 	 * freq_hint - Frequency of the channel the proposed AP is using
@@ -1083,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];
 };
@@ -2495,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
@@ -2504,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
@@ -2795,6 +2802,30 @@
 	 * Returns: Length of written status information or -1 on failure
 	 */
 	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);
@@ -3308,7 +3339,8 @@
 	 * the driver does not support radar detection and another virtual
 	 * interfaces caused the operating channel to change. Other similar
 	 * resource conflicts could also trigger this for station mode
-	 * interfaces.
+	 * interfaces. This event can be propagated when channel switching
+	 * fails.
 	 */
 	EVENT_INTERFACE_UNAVAILABLE,
 
@@ -4163,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[];
 

Modified: wpa/trunk/src/drivers/driver_atheros.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/drivers/driver_atheros.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/drivers/driver_atheros.c	(original)
+++ wpa/trunk/src/drivers/driver_atheros.c	Tue Oct 14 12:39:25 2014
@@ -260,6 +260,17 @@
 	case WPA_CIPHER_CCMP:
 		v = IEEE80211_CIPHER_AES_CCM;
 		break;
+#ifdef ATH_GCM_SUPPORT
+	case WPA_CIPHER_CCMP_256:
+		v = IEEE80211_CIPHER_AES_CCM_256;
+		break;
+	case WPA_CIPHER_GCMP:
+		v = IEEE80211_CIPHER_AES_GCM;
+		break;
+	case WPA_CIPHER_GCMP_256:
+		v = IEEE80211_CIPHER_AES_GCM_256;
+		break;
+#endif /* ATH_GCM_SUPPORT */
 	case WPA_CIPHER_TKIP:
 		v = IEEE80211_CIPHER_TKIP;
 		break;
@@ -294,6 +305,14 @@
 	v = 0;
 	if (params->wpa_pairwise & WPA_CIPHER_CCMP)
 		v |= 1<<IEEE80211_CIPHER_AES_CCM;
+#ifdef ATH_GCM_SUPPORT
+	if (params->wpa_pairwise & WPA_CIPHER_CCMP_256)
+		v |= 1<<IEEE80211_CIPHER_AES_CCM_256;
+	if (params->wpa_pairwise & WPA_CIPHER_GCMP)
+		v |= 1<<IEEE80211_CIPHER_AES_GCM;
+	if (params->wpa_pairwise & WPA_CIPHER_GCMP_256)
+		v |= 1<<IEEE80211_CIPHER_AES_GCM_256;
+#endif /* ATH_GCM_SUPPORT */
 	if (params->wpa_pairwise & WPA_CIPHER_TKIP)
 		v |= 1<<IEEE80211_CIPHER_TKIP;
 	if (params->wpa_pairwise & WPA_CIPHER_NONE)
@@ -471,10 +490,32 @@
 	case WPA_ALG_CCMP:
 		cipher = IEEE80211_CIPHER_AES_CCM;
 		break;
+#ifdef ATH_GCM_SUPPORT
+	case WPA_ALG_CCMP_256:
+		cipher = IEEE80211_CIPHER_AES_CCM_256;
+		break;
+	case WPA_ALG_GCMP:
+		cipher = IEEE80211_CIPHER_AES_GCM;
+		break;
+	case WPA_ALG_GCMP_256:
+		cipher = IEEE80211_CIPHER_AES_GCM_256;
+		break;
+#endif /* ATH_GCM_SUPPORT */
 #ifdef CONFIG_IEEE80211W
 	case WPA_ALG_IGTK:
 		cipher = IEEE80211_CIPHER_AES_CMAC;
 		break;
+#ifdef ATH_GCM_SUPPORT
+	case WPA_ALG_BIP_CMAC_256:
+		cipher = IEEE80211_CIPHER_AES_CMAC_256;
+		break;
+	case WPA_ALG_BIP_GMAC_128:
+		cipher = IEEE80211_CIPHER_AES_GMAC;
+		break;
+	case WPA_ALG_BIP_GMAC_256:
+		cipher = IEEE80211_CIPHER_AES_GMAC_256;
+		break;
+#endif /* ATH_GCM_SUPPORT */
 #endif /* CONFIG_IEEE80211W */
 	default:
 		printf("%s: unknown/unsupported algorithm %d\n",

Modified: wpa/trunk/src/drivers/driver_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/drivers/driver_common.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/drivers/driver_common.c	(original)
+++ wpa/trunk/src/drivers/driver_common.c	Tue Oct 14 12:39:25 2014
@@ -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";
+	}
+}

Modified: wpa/trunk/src/drivers/driver_nl80211.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/drivers/driver_nl80211.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/drivers/driver_nl80211.c	(original)
+++ wpa/trunk/src/drivers/driver_nl80211.c	Tue Oct 14 12:39:25 2014
@@ -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>
@@ -232,6 +235,7 @@
 	unsigned int in_deinit:1;
 	unsigned int wdev_id_set:1;
 	unsigned int added_if:1;
+	unsigned int static_ap:1;
 
 	u8 addr[ETH_ALEN];
 
@@ -252,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;
@@ -306,7 +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;
@@ -321,6 +330,8 @@
 	int eapol_tx_sock;
 
 	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;
@@ -347,6 +358,9 @@
 					    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,
+					    struct hostapd_freq_params *freq);
+
 static int
 wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
 				   const u8 *set_addr, int first);
@@ -413,6 +427,7 @@
 static int wpa_driver_nl80211_authenticate_retry(
 	struct wpa_driver_nl80211_data *drv);
 
+static int i802_set_freq(void *priv, struct hostapd_freq_params *freq);
 static int i802_set_iface_flags(struct i802_bss *bss, int up);
 
 
@@ -574,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)
@@ -1238,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]" : "",
@@ -1291,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,
@@ -1335,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) {
@@ -1343,6 +1396,9 @@
 		return;
 	}
 
+	extra[0] = '\0';
+	pos = extra;
+	end = pos + sizeof(extra);
 	ifname[0] = '\0';
 
 	attrlen = len;
@@ -1357,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);
 	}
-
-	if (ifname[0])
+	extra[sizeof(extra) - 1] = '\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) {
@@ -1381,6 +1455,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;
@@ -1447,6 +1532,17 @@
 	const struct ieee80211_mgmt *mgmt;
 	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;
@@ -1629,10 +1725,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);
@@ -1676,7 +1769,7 @@
 
 	bss->freq = data.ch_switch.freq;
 
-	wpa_supplicant_event(drv->ctx, EVENT_CH_SWITCH, &data);
+	wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH, &data);
 }
 
 
@@ -1735,8 +1828,10 @@
 		rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
 	}
 	wpa_printf(MSG_DEBUG,
-		   "nl80211: RX frame freq=%d ssi_signal=%d stype=%u len=%u",
-		   rx_freq, ssi_signal, stype, (unsigned int) len);
+		   "nl80211: RX frame sa=" MACSTR
+		   " freq=%d ssi_signal=%d stype=%u (%s) len=%u",
+		   MAC2STR(mgmt->sa), rx_freq, ssi_signal, stype, fc2str(fc),
+		   (unsigned int) len);
 	event.rx_mgmt.frame = frame;
 	event.rx_mgmt.frame_len = len;
 	event.rx_mgmt.ssi_signal = ssi_signal;
@@ -3411,6 +3506,7 @@
 	unsigned int p2p_concurrent:1;
 	unsigned int channel_switch_supported:1;
 	unsigned int set_qos_map_supported:1;
+	unsigned int have_low_prio_scan:1;
 };
 
 
@@ -3689,6 +3785,9 @@
 
 	if (flags & NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE)
 		capa->flags |= WPA_DRIVER_FLAGS_HT_2040_COEX;
+
+	if (flags & NL80211_FEATURE_LOW_PRIORITY_SCAN)
+		info->have_low_prio_scan = 1;
 }
 
 
@@ -3835,9 +3934,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);
@@ -3981,6 +4085,7 @@
 	drv->data_tx_status = info.data_tx_status;
 	if (info.set_qos_map_supported)
 		drv->capa.flags |= WPA_DRIVER_FLAGS_QOS_MAPPING;
+	drv->have_low_prio_scan = info.have_low_prio_scan;
 
 	/*
 	 * If poll command and tx status are supported, mac80211 is new enough
@@ -4384,8 +4489,8 @@
 
 	buf[0] = '\0';
 	wpa_snprintf_hex(buf, sizeof(buf), match, match_len);
-	wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x nl_handle=%p match=%s",
-		   type, nl_handle, buf);
+	wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s",
+		   type, fc2str(type), nl_handle, buf);
 
 	nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION);
 
@@ -4538,7 +4643,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);
@@ -4752,6 +4857,9 @@
 	bss->if_dynamic = bss->if_dynamic || drv->global->if_add_wdevid_set;
 	drv->global->if_add_wdevid_set = 0;
 
+	if (!bss->if_dynamic && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
+		bss->static_ap = 1;
+
 	if (wpa_driver_nl80211_capa(drv))
 		return -1;
 
@@ -4767,7 +4875,7 @@
 	if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
 		drv->start_mode_ap = 1;
 
-	if (drv->hostapd)
+	if (drv->hostapd || bss->static_ap)
 		nlmode = NL80211_IFTYPE_AP;
 	else if (bss->if_dynamic)
 		nlmode = nl80211_get_ifmode(bss);
@@ -4807,6 +4915,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,
@@ -4862,6 +4971,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)
@@ -4895,6 +5006,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,
@@ -4949,6 +5070,7 @@
 {
 	struct nl_msg *msg;
 	size_t i;
+	u32 scan_flags = 0;
 
 	msg = nlmsg_alloc();
 	if (!msg)
@@ -5007,9 +5129,17 @@
 
 	if (params->only_new_results) {
 		wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_FLUSH");
-		NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS,
-			    NL80211_SCAN_FLAG_FLUSH);
-	}
+		scan_flags |= NL80211_SCAN_FLAG_FLUSH;
+	}
+
+	if (params->low_priority && drv->have_low_prio_scan) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY");
+		scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY;
+	}
+
+	if (scan_flags)
+		NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS, scan_flags);
 
 	return msg;
 
@@ -7070,8 +7200,10 @@
 
 	mgmt = (struct ieee80211_mgmt *) data;
 	fc = le_to_host16(mgmt->frame_control);
-	wpa_printf(MSG_DEBUG, "nl80211: send_mlme - noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u fc=0x%x nlmode=%d",
-		   noack, freq, no_cck, offchanok, wait_time, fc, drv->nlmode);
+	wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da= " MACSTR
+		   " noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u fc=0x%x (%s) nlmode=%d",
+		   MAC2STR(mgmt->da), noack, freq, no_cck, offchanok, wait_time,
+		   fc, fc2str(fc), drv->nlmode);
 
 	if ((is_sta_interface(drv->nlmode) ||
 	     drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) &&
@@ -7660,6 +7792,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;
@@ -7680,6 +7849,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;
@@ -8454,6 +8627,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;
@@ -8504,9 +8682,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 "
@@ -8521,7 +8696,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);
@@ -8575,8 +8750,7 @@
 
 	wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
 
-	if (wpa_driver_nl80211_set_mode(drv->first_bss,
-					NL80211_IFTYPE_ADHOC)) {
+	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;
@@ -8600,8 +8774,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);
@@ -8679,10 +8861,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;
 
@@ -9016,26 +9198,29 @@
 }
 
 
-static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
-				       enum nl80211_iftype nlmode)
+static int wpa_driver_nl80211_set_mode_impl(
+		struct i802_bss *bss,
+		enum nl80211_iftype nlmode,
+		struct hostapd_freq_params *desired_freq_params)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int ret = -1;
 	int i;
 	int was_ap = is_ap_interface(drv->nlmode);
 	int res;
-
-	res = nl80211_set_mode(drv, drv->ifindex, nlmode);
-	if (res && nlmode == nl80211_get_ifmode(bss))
-		res = 0;
-
-	if (res == 0) {
+	int mode_switch_res;
+
+	mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
+	if (mode_switch_res && nlmode == nl80211_get_ifmode(bss))
+		mode_switch_res = 0;
+
+	if (mode_switch_res == 0) {
 		drv->nlmode = nlmode;
 		ret = 0;
 		goto done;
 	}
 
-	if (res == -ENODEV)
+	if (mode_switch_res == -ENODEV)
 		return -1;
 
 	if (nlmode == drv->nlmode) {
@@ -9055,21 +9240,35 @@
 		res = i802_set_iface_flags(bss, 0);
 		if (res == -EACCES || res == -ENODEV)
 			break;
-		if (res == 0) {
-			/* Try to set the mode again while the interface is
-			 * down */
-			ret = nl80211_set_mode(drv, drv->ifindex, nlmode);
-			if (ret == -EACCES)
-				break;
-			res = i802_set_iface_flags(bss, 1);
-			if (res && !ret)
-				ret = -1;
-			else if (ret != -EBUSY)
-				break;
-		} else
+		if (res != 0) {
 			wpa_printf(MSG_DEBUG, "nl80211: Failed to set "
 				   "interface down");
-		os_sleep(0, 100000);
+			os_sleep(0, 100000);
+			continue;
+		}
+
+		/*
+		 * Setting the mode will fail for some drivers if the phy is
+		 * on a frequency that the mode is disallowed in.
+		 */
+		if (desired_freq_params) {
+			res = i802_set_freq(bss, desired_freq_params);
+			if (res) {
+				wpa_printf(MSG_DEBUG,
+					   "nl80211: Failed to set frequency on interface");
+			}
+		}
+
+		/* Try to set the mode again while the interface is down */
+		mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
+		if (mode_switch_res == -EBUSY) {
+			wpa_printf(MSG_DEBUG,
+				   "nl80211: Delaying mode set while interface going down");
+			os_sleep(0, 100000);
+			continue;
+		}
+		ret = mode_switch_res;
+		break;
 	}
 
 	if (!ret) {
@@ -9077,6 +9276,14 @@
 			   "interface is down");
 		drv->nlmode = nlmode;
 		drv->ignore_if_down_event = 1;
+	}
+
+	/* Bring the interface back up */
+	res = linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1);
+	if (res != 0) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Failed to set interface up after switching mode");
+		ret = -1;
 	}
 
 done:
@@ -9138,6 +9345,21 @@
 	}
 
 	return NL_SKIP;
+}
+
+
+static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
+				       enum nl80211_iftype nlmode)
+{
+	return wpa_driver_nl80211_set_mode_impl(bss, nlmode, NULL);
+}
+
+
+static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
+					    struct hostapd_freq_params *freq)
+{
+	return wpa_driver_nl80211_set_mode_impl(bss, NL80211_IFTYPE_ADHOC,
+						freq);
 }
 
 
@@ -9917,6 +10139,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",
@@ -9933,6 +10171,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);
 
@@ -10177,7 +10416,15 @@
 	if (drv->global)
 		drv->global->if_add_ifindex = ifidx;
 
-	if (ifidx > 0)
+	/*
+	 * Some virtual interfaces need to process EAPOL packets and events on
+	 * the parent interface. This is used mainly with hostapd.
+	 */
+	if (ifidx > 0 &&
+	    (drv->hostapd ||
+	     nlmode == NL80211_IFTYPE_AP_VLAN ||
+	     nlmode == NL80211_IFTYPE_WDS ||
+	     nlmode == NL80211_IFTYPE_MONITOR))
 		add_ifidx(drv, ifidx);
 
 	return 0;
@@ -10495,7 +10742,8 @@
 
 	if (!report) {
 		if (bss->nl_preq && drv->device_ap_sme &&
-		    is_ap_interface(drv->nlmode)) {
+		    is_ap_interface(drv->nlmode) && !bss->in_deinit &&
+		    !bss->static_ap) {
 			/*
 			 * Do not disable Probe Request reporting that was
 			 * enabled in nl80211_setup_ap().
@@ -10883,6 +11131,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")) {
@@ -11374,60 +11623,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;
 }
 
@@ -11435,7 +11642,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;
@@ -11466,6 +11674,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);
@@ -11878,6 +12088,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"
@@ -11894,6 +12105,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),
@@ -12047,7 +12259,7 @@
 		return -ENOMEM;
 
 	nl80211_cmd(drv, msg, 0, NL80211_CMD_CHANNEL_SWITCH);
-	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
 	NLA_PUT_U32(msg, NL80211_ATTR_CH_SWITCH_COUNT, settings->cs_count);
 	ret = nl80211_put_freq_params(msg, &settings->freq_params);
 	if (ret)
@@ -12273,6 +12485,90 @@
 nla_put_failure:
 	nlmsg_free(msg);
 	return -ENOBUFS;
+}
+
+
+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;
 }
 
 
@@ -12367,4 +12663,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,
 };

Modified: wpa/trunk/src/drivers/driver_test.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/drivers/driver_test.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/drivers/driver_test.c	(original)
+++ wpa/trunk/src/drivers/driver_test.c	Tue Oct 14 12:39:25 2014
@@ -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);

Modified: wpa/trunk/src/drivers/driver_wext.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/drivers/driver_wext.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/drivers/driver_wext.c	(original)
+++ wpa/trunk/src/drivers/driver_wext.c	Tue Oct 14 12:39:25 2014
@@ -2027,7 +2027,11 @@
 		 * Stop cfg80211 from trying to associate before we are done
 		 * with all parameters.
 		 */
-		wpa_driver_wext_set_ssid(drv, (u8 *) "", 0);
+		if (wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) {
+			wpa_printf(MSG_DEBUG,
+				   "WEXT: Failed to clear SSID to stop pending cfg80211 association attempts (if any)");
+			/* continue anyway */
+		}
 	}
 
 	if (wpa_driver_wext_set_drop_unencrypted(drv, params->drop_unencrypted)
@@ -2115,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)
@@ -2313,6 +2318,37 @@
 {
 	struct wpa_driver_wext_data *drv = priv;
 	return drv->phyname;
+}
+
+
+static int wpa_driver_wext_signal_poll(void *priv, struct wpa_signal_info *si)
+{
+	struct wpa_driver_wext_data *drv = priv;
+	struct iw_statistics stats;
+	struct iwreq iwr;
+
+	os_memset(si, 0, sizeof(*si));
+	si->current_signal = -9999;
+	si->current_noise = 9999;
+	si->chanwidth = CHAN_WIDTH_UNKNOWN;
+
+	os_memset(&iwr, 0, sizeof(iwr));
+	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+	iwr.u.data.pointer = (caddr_t) &stats;
+	iwr.u.data.length = sizeof(stats);
+	iwr.u.data.flags = 1;
+
+	if (ioctl(drv->ioctl_sock, SIOCGIWSTATS, &iwr) < 0) {
+		wpa_printf(MSG_ERROR, "WEXT: SIOCGIWSTATS: %s",
+			   strerror(errno));
+		return -1;
+	}
+
+	si->current_signal = stats.qual.level -
+		((stats.qual.updated & IW_QUAL_DBM) ? 0x100 : 0);
+	si->current_noise = stats.qual.noise -
+		((stats.qual.updated & IW_QUAL_DBM) ? 0x100 : 0);
+	return 0;
 }
 
 
@@ -2335,4 +2371,5 @@
 	.get_capa = wpa_driver_wext_get_capa,
 	.set_operstate = wpa_driver_wext_set_operstate,
 	.get_radio_name = wext_get_radio_name,
+	.signal_poll = wpa_driver_wext_signal_poll,
 };

Modified: wpa/trunk/src/drivers/drivers.mak
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/drivers/drivers.mak?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/drivers/drivers.mak	(original)
+++ wpa/trunk/src/drivers/drivers.mak	Tue Oct 14 12:39:25 2014
@@ -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
@@ -105,6 +109,9 @@
 CONFIG_L2_PACKET=linux
 NEED_NETLINK=y
 NEED_LINUX_IOCTL=y
+ifdef ATH_GCM_SUPPORT
+CFLAGS += -DATH_GCM_SUPPORT
+endif
 endif
 
 ##### PURE CLIENT DRIVERS

Modified: wpa/trunk/src/drivers/drivers.mk
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/drivers/drivers.mk?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/drivers/drivers.mk	(original)
+++ wpa/trunk/src/drivers/drivers.mk	Tue Oct 14 12:39:25 2014
@@ -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

Modified: wpa/trunk/src/drivers/nl80211_copy.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/drivers/nl80211_copy.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/drivers/nl80211_copy.h	(original)
+++ wpa/trunk/src/drivers/nl80211_copy.h	Tue Oct 14 12:39:25 2014
@@ -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
  */
@@ -889,6 +908,9 @@
 	NL80211_CMD_VENDOR,
 
 	NL80211_CMD_SET_QOS_MAP,
+
+	NL80211_CMD_ADD_TX_TS,
+	NL80211_CMD_DEL_TX_TS,
 
 	/* add new commands above here */
 
@@ -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,12 +1598,45 @@
  *	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.
  *
  * @NL80211_ATTR_IFACE_SOCKET_OWNER: flag attribute, if set during interface
  *	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
@@ -1919,6 +1974,21 @@
 	NL80211_ATTR_TDLS_PEER_CAPABILITY,
 
 	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 */
 
@@ -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,
 };
 
 /**
@@ -4024,6 +4141,25 @@
 enum nl80211_acl_policy {
 	NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED,
 	NL80211_ACL_POLICY_DENY_UNLESS_LISTED,
+};
+
+/**
+ * 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
 };
 
 /**

Modified: wpa/trunk/src/eap_common/eap_eke_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_common/eap_eke_common.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_common/eap_eke_common.c	(original)
+++ wpa/trunk/src/eap_common/eap_eke_common.c	Tue Oct 14 12:39:25 2014
@@ -692,7 +692,7 @@
 	if (eap_eke_mac(sess->mac, sess->ki, prot + block_size,
 			prot_len - block_size - icv_len, icv) < 0)
 		return -1;
-	if (os_memcmp(icv, prot + prot_len - icv_len, icv_len) != 0) {
+	if (os_memcmp_const(icv, prot + prot_len - icv_len, icv_len) != 0) {
 		wpa_printf(MSG_INFO, "EAP-EKE: ICV mismatch in Prot() data");
 		return -1;
 	}

Modified: wpa/trunk/src/eap_common/eap_fast_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_common/eap_fast_common.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_common/eap_fast_common.c	(original)
+++ wpa/trunk/src/eap_common/eap_fast_common.c	Tue Oct 14 12:39:25 2014
@@ -174,7 +174,7 @@
 
 
 int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv,
-		       int tlv_type, u8 *pos, int len)
+		       int tlv_type, u8 *pos, size_t len)
 {
 	switch (tlv_type) {
 	case EAP_TLV_EAP_PAYLOAD_TLV:

Modified: wpa/trunk/src/eap_common/eap_fast_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_common/eap_fast_common.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_common/eap_fast_common.h	(original)
+++ wpa/trunk/src/eap_common/eap_fast_common.h	Tue Oct 14 12:39:25 2014
@@ -102,6 +102,6 @@
 void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk);
 void eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk);
 int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv,
-		       int tlv_type, u8 *pos, int len);
+		       int tlv_type, u8 *pos, size_t len);
 
 #endif /* EAP_FAST_H */

Modified: wpa/trunk/src/eap_common/eap_gpsk_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_common/eap_gpsk_common.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_common/eap_gpsk_common.c	(original)
+++ wpa/trunk/src/eap_common/eap_gpsk_common.c	Tue Oct 14 12:39:25 2014
@@ -284,7 +284,6 @@
 			 u8 *pk, size_t *pk_len)
 {
 	u8 *seed, *pos;
-	size_t seed_len;
 	int ret;
 
 	wpa_printf(MSG_DEBUG, "EAP-GPSK: Deriving keys (%d:%d)",
@@ -296,8 +295,7 @@
 	wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PSK", psk, psk_len);
 
 	/* Seed = RAND_Peer || ID_Peer || RAND_Server || ID_Server */
-	seed_len = 2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len;
-	seed = os_malloc(seed_len);
+	seed = os_malloc(2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len);
 	if (seed == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to allocate memory "
 			   "for key derivation");
@@ -313,17 +311,18 @@
 	pos += EAP_GPSK_RAND_LEN;
 	os_memcpy(pos, id_server, id_server_len);
 	pos += id_server_len;
-	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Seed", seed, seed_len);
+	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Seed", seed, pos - seed);
 
 	switch (specifier) {
 	case EAP_GPSK_CIPHER_AES:
-		ret = eap_gpsk_derive_keys_aes(psk, psk_len, seed, seed_len,
+		ret = eap_gpsk_derive_keys_aes(psk, psk_len, seed, pos - seed,
 					       msk, emsk, sk, sk_len,
 					       pk, pk_len);
 		break;
 #ifdef EAP_GPSK_SHA256
 	case EAP_GPSK_CIPHER_SHA256:
-		ret = eap_gpsk_derive_keys_sha256(psk, psk_len, seed, seed_len,
+		ret = eap_gpsk_derive_keys_sha256(psk, psk_len, seed,
+						  pos - seed,
 						  msk, emsk, sk, sk_len);
 		break;
 #endif /* EAP_GPSK_SHA256 */
@@ -423,7 +422,6 @@
 {
 	u8 *seed, *pos;
 	u8 kdf_out[16];
-	size_t seed_len;
 	int ret;
 
 	wpa_printf(MSG_DEBUG, "EAP-GPSK: Deriving Session ID(%d:%d)",
@@ -441,8 +439,7 @@
 	 * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type ||
 	 *                      CSuite_Sel || inputString)
 	 */
-	seed_len = 2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len;
-	seed = os_malloc(seed_len);
+	seed = os_malloc(2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len);
 	if (seed == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to allocate memory "
 			   "for Session-Id derivation");
@@ -458,11 +455,11 @@
 	pos += EAP_GPSK_RAND_LEN;
 	os_memcpy(pos, id_server, id_server_len);
 	pos += id_server_len;
-	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Seed", seed, seed_len);
+	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Seed", seed, pos - seed);
 
 	ret = eap_gpsk_derive_mid_helper(specifier,
 					 kdf_out, sizeof(kdf_out),
-					 psk, seed, seed_len,
+					 psk, seed, pos - seed,
 					 method_type);
 
 	sid[0] = method_type;

Modified: wpa/trunk/src/eap_common/eap_ikev2_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_common/eap_ikev2_common.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_common/eap_ikev2_common.c	(original)
+++ wpa/trunk/src/eap_common/eap_ikev2_common.c	Tue Oct 14 12:39:25 2014
@@ -52,22 +52,12 @@
 {
 	struct wpabuf *msg;
 
-#ifdef CCNS_PL
-	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 1, code, id);
-	if (msg == NULL) {
-		wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
-			   "for fragment ack");
-		return NULL;
-	}
-	wpabuf_put_u8(msg, 0); /* Flags */
-#else /* CCNS_PL */
 	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id);
 	if (msg == NULL) {
 		wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
 			   "for fragment ack");
 		return NULL;
 	}
-#endif /* CCNS_PL */
 
 	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack");
 
@@ -110,7 +100,7 @@
 		return -1;
 	}
 
-	if (os_memcmp(icv, end - icv_len, icv_len) != 0) {
+	if (os_memcmp_const(icv, end - icv_len, icv_len) != 0) {
 		wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid ICV");
 		wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Calculated ICV",
 			    icv, icv_len);

Modified: wpa/trunk/src/eap_common/eap_ikev2_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_common/eap_ikev2_common.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_common/eap_ikev2_common.h	(original)
+++ wpa/trunk/src/eap_common/eap_ikev2_common.h	Tue Oct 14 12:39:25 2014
@@ -9,16 +9,9 @@
 #ifndef EAP_IKEV2_COMMON_H
 #define EAP_IKEV2_COMMON_H
 
-#ifdef CCNS_PL
-/* incorrect bit order */
-#define IKEV2_FLAGS_LENGTH_INCLUDED 0x01
-#define IKEV2_FLAGS_MORE_FRAGMENTS 0x02
-#define IKEV2_FLAGS_ICV_INCLUDED 0x04
-#else /* CCNS_PL */
 #define IKEV2_FLAGS_LENGTH_INCLUDED 0x80
 #define IKEV2_FLAGS_MORE_FRAGMENTS 0x40
 #define IKEV2_FLAGS_ICV_INCLUDED 0x20
-#endif /* CCNS_PL */
 
 #define IKEV2_FRAGMENT_SIZE 1400
 

Modified: wpa/trunk/src/eap_common/eap_pwd_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_common/eap_pwd_common.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_common/eap_pwd_common.c	(original)
+++ wpa/trunk/src/eap_common/eap_pwd_common.c	Tue Oct 14 12:39:25 2014
@@ -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;
@@ -263,18 +265,18 @@
  fail:
 		EC_GROUP_free(grp->group);
 		grp->group = NULL;
-		EC_POINT_free(grp->pwe);
+		EC_POINT_clear_free(grp->pwe);
 		grp->pwe = NULL;
-		BN_free(grp->order);
+		BN_clear_free(grp->order);
 		grp->order = NULL;
-		BN_free(grp->prime);
+		BN_clear_free(grp->prime);
 		grp->prime = NULL;
 		ret = 1;
 	}
 	/* cleanliness and order.... */
-	BN_free(cofactor);
-	BN_free(x_candidate);
-	BN_free(rnd);
+	BN_clear_free(cofactor);
+	BN_clear_free(x_candidate);
+	BN_clear_free(rnd);
 	os_free(prfbuf);
 
 	return ret;

Modified: wpa/trunk/src/eap_common/eap_sim_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_common/eap_sim_common.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_common/eap_sim_common.c	(original)
+++ wpa/trunk/src/eap_common/eap_sim_common.c	Tue Oct 14 12:39:25 2014
@@ -198,7 +198,7 @@
 		    hmac, EAP_SIM_MAC_LEN);
 	os_free(tmp);
 
-	return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
+	return (os_memcmp_const(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
 }
 
 
@@ -393,7 +393,7 @@
 		    hmac, EAP_SIM_MAC_LEN);
 	os_free(tmp);
 
-	return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
+	return (os_memcmp_const(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
 }
 
 
@@ -893,7 +893,7 @@
 			if (attr->kdf_count == EAP_AKA_PRIME_KDF_MAX) {
 				wpa_printf(MSG_DEBUG, "EAP-AKA': Too many "
 					   "AT_KDF attributes - ignore this");
-				continue;
+				break;
 			}
 			attr->kdf[attr->kdf_count] = WPA_GET_BE16(apos);
 			attr->kdf_count++;
@@ -972,7 +972,6 @@
 struct eap_sim_msg {
 	struct wpabuf *buf;
 	size_t mac, iv, encr; /* index from buf */
-	int type;
 };
 
 
@@ -986,7 +985,6 @@
 	if (msg == NULL)
 		return NULL;
 
-	msg->type = type;
 	msg->buf = wpabuf_alloc(EAP_SIM_INIT_LEN);
 	if (msg->buf == NULL) {
 		os_free(msg);
@@ -1006,7 +1004,8 @@
 }
 
 
-struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, const u8 *k_aut,
+struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, int type,
+				   const u8 *k_aut,
 				   const u8 *extra, size_t extra_len)
 {
 	struct eap_hdr *eap;
@@ -1019,7 +1018,7 @@
 	eap->length = host_to_be16(wpabuf_len(msg->buf));
 
 #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
-	if (k_aut && msg->mac && msg->type == EAP_TYPE_AKA_PRIME) {
+	if (k_aut && msg->mac && type == EAP_TYPE_AKA_PRIME) {
 		eap_sim_add_mac_sha256(k_aut, (u8 *) wpabuf_head(msg->buf),
 				       wpabuf_len(msg->buf),
 				       (u8 *) wpabuf_mhead(msg->buf) +

Modified: wpa/trunk/src/eap_common/eap_sim_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_common/eap_sim_common.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_common/eap_sim_common.h	(original)
+++ wpa/trunk/src/eap_common/eap_sim_common.h	Tue Oct 14 12:39:25 2014
@@ -211,7 +211,8 @@
 struct eap_sim_msg;
 
 struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype);
-struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, const u8 *k_aut,
+struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, int type,
+				   const u8 *k_aut,
 				   const u8 *extra, size_t extra_len);
 void eap_sim_msg_free(struct eap_sim_msg *msg);
 u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr,

Modified: wpa/trunk/src/eap_common/ikev2_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_common/ikev2_common.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_common/ikev2_common.c	(original)
+++ wpa/trunk/src/eap_common/ikev2_common.c	Tue Oct 14 12:39:25 2014
@@ -173,46 +173,12 @@
 }
 
 
-#ifdef CCNS_PL
-/* from des.c */
-struct des3_key_s {
-	u32 ek[3][32];
-	u32 dk[3][32];
-};
-
-void des3_key_setup(const u8 *key, struct des3_key_s *dkey);
-void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt);
-void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain);
-#endif /* CCNS_PL */
-
-
 int ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
 		       const u8 *plain, u8 *crypt, size_t len)
 {
 	struct crypto_cipher *cipher;
 	int encr_alg;
 
-#ifdef CCNS_PL
-	if (alg == ENCR_3DES) {
-		struct des3_key_s des3key;
-		size_t i, blocks;
-		u8 *pos;
-
-		/* ECB mode is used incorrectly for 3DES!? */
-		if (key_len != 24) {
-			wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length");
-			return -1;
-		}
-		des3_key_setup(key, &des3key);
-
-		blocks = len / 8;
-		pos = crypt;
-		for (i = 0; i < blocks; i++) {
-			des3_encrypt(pos, &des3key, pos);
-			pos += 8;
-		}
-	} else {
-#endif /* CCNS_PL */
 	switch (alg) {
 	case ENCR_3DES:
 		encr_alg = CRYPTO_CIPHER_ALG_3DES;
@@ -237,9 +203,6 @@
 		return -1;
 	}
 	crypto_cipher_deinit(cipher);
-#ifdef CCNS_PL
-	}
-#endif /* CCNS_PL */
 
 	return 0;
 }
@@ -251,31 +214,6 @@
 	struct crypto_cipher *cipher;
 	int encr_alg;
 
-#ifdef CCNS_PL
-	if (alg == ENCR_3DES) {
-		struct des3_key_s des3key;
-		size_t i, blocks;
-
-		/* ECB mode is used incorrectly for 3DES!? */
-		if (key_len != 24) {
-			wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length");
-			return -1;
-		}
-		des3_key_setup(key, &des3key);
-
-		if (len % 8) {
-			wpa_printf(MSG_INFO, "IKEV2: Invalid encrypted "
-				   "length");
-			return -1;
-		}
-		blocks = len / 8;
-		for (i = 0; i < blocks; i++) {
-			des3_decrypt(crypt, &des3key, plain);
-			plain += 8;
-			crypt += 8;
-		}
-	} else {
-#endif /* CCNS_PL */
 	switch (alg) {
 	case ENCR_3DES:
 		encr_alg = CRYPTO_CIPHER_ALG_3DES;
@@ -300,9 +238,6 @@
 		return -1;
 	}
 	crypto_cipher_deinit(cipher);
-#ifdef CCNS_PL
-	}
-#endif /* CCNS_PL */
 
 	return 0;
 }
@@ -542,7 +477,7 @@
 			   "hash");
 		return NULL;
 	}
-	if (os_memcmp(integ, hash, integ_alg->hash_len) != 0) {
+	if (os_memcmp_const(integ, hash, integ_alg->hash_len) != 0) {
 		wpa_printf(MSG_INFO, "IKEV2: Incorrect Integrity Checksum "
 			   "Data");
 		return NULL;
@@ -706,10 +641,6 @@
 	keys->SK_integ_len = integ->key_len;
 	keys->SK_encr_len = encr->key_len;
 	keys->SK_prf_len = prf->key_len;
-#ifdef CCNS_PL
-	/* Uses encryption key length for SK_d; should be PRF length */
-	keys->SK_d_len = keys->SK_encr_len;
-#endif /* CCNS_PL */
 
 	keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len +
 		2 * keys->SK_encr_len + 2 * keys->SK_prf_len;

Modified: wpa/trunk/src/eap_common/ikev2_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_common/ikev2_common.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_common/ikev2_common.h	(original)
+++ wpa/trunk/src/eap_common/ikev2_common.h	Tue Oct 14 12:39:25 2014
@@ -70,11 +70,7 @@
 /* Current IKEv2 version from RFC 4306 */
 #define IKEV2_MjVer 2
 #define IKEV2_MnVer 0
-#ifdef CCNS_PL
-#define IKEV2_VERSION ((IKEV2_MjVer) | ((IKEV2_MnVer) << 4))
-#else /* CCNS_PL */
 #define IKEV2_VERSION (((IKEV2_MjVer) << 4) | (IKEV2_MnVer))
-#endif /* CCNS_PL */
 
 /* IKEv2 Exchange Types */
 enum {

Modified: wpa/trunk/src/eap_peer/eap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap.c	(original)
+++ wpa/trunk/src/eap_peer/eap.c	Tue Oct 14 12:39:25 2014
@@ -92,6 +92,15 @@
 }
 
 
+static void eap_sm_free_key(struct eap_sm *sm)
+{
+	if (sm->eapKeyData) {
+		bin_clear_free(sm->eapKeyData, sm->eapKeyDataLen);
+		sm->eapKeyData = NULL;
+	}
+}
+
+
 static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
 {
 	ext_password_free(sm->ext_pw_buf);
@@ -144,11 +153,13 @@
 	SM_ENTRY(EAP, INITIALIZE);
 	if (sm->fast_reauth && sm->m && sm->m->has_reauth_data &&
 	    sm->m->has_reauth_data(sm, sm->eap_method_priv) &&
-	    !sm->prev_failure) {
+	    !sm->prev_failure &&
+	    sm->last_config == eap_get_config(sm)) {
 		wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for "
 			   "fast reauthentication");
 		sm->m->deinit_for_reauth(sm, sm->eap_method_priv);
 	} else {
+		sm->last_config = eap_get_config(sm);
 		eap_deinit_prev_method(sm, "INITIALIZE");
 	}
 	sm->selectedMethod = EAP_TYPE_NONE;
@@ -159,8 +170,7 @@
 	eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
 	eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
 	eapol_set_bool(sm, EAPOL_eapFail, FALSE);
-	os_free(sm->eapKeyData);
-	sm->eapKeyData = NULL;
+	eap_sm_free_key(sm);
 	os_free(sm->eapSessionId);
 	sm->eapSessionId = NULL;
 	sm->eapKeyAvailable = FALSE;
@@ -404,7 +414,7 @@
 
 	if (sm->m->isKeyAvailable && sm->m->getKey &&
 	    sm->m->isKeyAvailable(sm, sm->eap_method_priv)) {
-		os_free(sm->eapKeyData);
+		eap_sm_free_key(sm);
 		sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
 					       &sm->eapKeyDataLen);
 		os_free(sm->eapSessionId);
@@ -1488,8 +1498,7 @@
 	sm->lastRespData = NULL;
 	wpabuf_free(sm->eapRespData);
 	sm->eapRespData = NULL;
-	os_free(sm->eapKeyData);
-	sm->eapKeyData = NULL;
+	eap_sm_free_key(sm);
 	os_free(sm->eapSessionId);
 	sm->eapSessionId = NULL;
 

Modified: wpa/trunk/src/eap_peer/eap_aka.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_aka.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_aka.c	(original)
+++ wpa/trunk/src/eap_peer/eap_aka.c	Tue Oct 14 12:39:25 2014
@@ -42,7 +42,7 @@
 	u8 *last_eap_identity;
 	size_t last_eap_identity_len;
 	enum {
-		CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE
+		CONTINUE, RESULT_SUCCESS, SUCCESS, FAILURE
 	} state;
 
 	struct wpabuf *id_msgs;
@@ -64,8 +64,6 @@
 		return "CONTINUE";
 	case RESULT_SUCCESS:
 		return "RESULT_SUCCESS";
-	case RESULT_FAILURE:
-		return "RESULT_FAILURE";
 	case SUCCESS:
 		return "SUCCESS";
 	case FAILURE:
@@ -126,6 +124,21 @@
 	return data;
 }
 #endif /* EAP_AKA_PRIME */
+
+
+static void eap_aka_clear_keys(struct eap_aka_data *data, int reauth)
+{
+	if (!reauth) {
+		os_memset(data->mk, 0, EAP_SIM_MK_LEN);
+		os_memset(data->k_aut, 0, EAP_AKA_PRIME_K_AUT_LEN);
+		os_memset(data->k_encr, 0, EAP_SIM_K_ENCR_LEN);
+		os_memset(data->k_re, 0, EAP_AKA_PRIME_K_RE_LEN);
+	}
+	os_memset(data->msk, 0, EAP_SIM_KEYING_DATA_LEN);
+	os_memset(data->emsk, 0, EAP_EMSK_LEN);
+	os_memset(data->autn, 0, EAP_AKA_AUTN_LEN);
+	os_memset(data->auts, 0, EAP_AKA_AUTS_LEN);
+}
 
 
 static void eap_aka_deinit(struct eap_sm *sm, void *priv)
@@ -137,6 +150,7 @@
 		os_free(data->last_eap_identity);
 		wpabuf_free(data->id_msgs);
 		os_free(data->network_name);
+		eap_aka_clear_keys(data, 0);
 		os_free(data);
 	}
 }
@@ -153,7 +167,7 @@
 	pos += os_snprintf(pos, end - pos, ":");
 	pos += wpa_snprintf_hex(pos, end - pos, data->rand, EAP_AKA_RAND_LEN);
 	pos += os_snprintf(pos, end - pos, ":");
-	pos += wpa_snprintf_hex(pos, end - pos, data->autn, EAP_AKA_AUTN_LEN);
+	wpa_snprintf_hex(pos, end - pos, data->autn, EAP_AKA_AUTN_LEN);
 
 	eap_sm_request_sim(sm, req);
 	return 1;
@@ -296,7 +310,7 @@
 	{
 		u8 autn[EAP_AKA_AUTN_LEN];
 		os_memset(autn, '1', EAP_AKA_AUTN_LEN);
-		if (os_memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) {
+		if (os_memcmp_const(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) {
 			wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match "
 				   "with expected value");
 			return -1;
@@ -511,7 +525,7 @@
 #endif /* EAP_AKA_PRIME */
 		sha1_vector(1, &addr, &len, hash);
 
-	if (os_memcmp(hash, checkcode, hash_len) != 0) {
+	if (os_memcmp_const(hash, checkcode, hash_len) != 0) {
 		wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
 		return -1;
 	}
@@ -534,7 +548,7 @@
 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
 			       EAP_AKA_SUBTYPE_CLIENT_ERROR);
 	eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
-	return eap_sim_msg_finish(msg, NULL, NULL, 0);
+	return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
 }
 
 
@@ -551,7 +565,7 @@
 		   "(id=%d)", id);
 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
 			       EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT);
-	return eap_sim_msg_finish(msg, NULL, NULL, 0);
+	return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
 }
 
 
@@ -570,7 +584,7 @@
 	wpa_printf(MSG_DEBUG, "   AT_AUTS");
 	eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts,
 			     EAP_AKA_AUTS_LEN);
-	return eap_sim_msg_finish(msg, NULL, NULL, 0);
+	return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
 }
 
 
@@ -614,7 +628,7 @@
 				identity, identity_len);
 	}
 
-	return eap_sim_msg_finish(msg, NULL, NULL, 0);
+	return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
 }
 
 
@@ -636,7 +650,8 @@
 	}
 	wpa_printf(MSG_DEBUG, "   AT_MAC");
 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
-	return eap_sim_msg_finish(msg, data->k_aut, (u8 *) "", 0);
+	return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, (u8 *) "",
+				  0);
 }
 
 
@@ -678,7 +693,7 @@
 	}
 	wpa_printf(MSG_DEBUG, "   AT_MAC");
 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
-	return eap_sim_msg_finish(msg, data->k_aut, nonce_s,
+	return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, nonce_s,
 				  EAP_SIM_NONCE_S_LEN);
 }
 
@@ -712,7 +727,7 @@
 		wpa_printf(MSG_DEBUG, "   AT_MAC");
 		eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
 	}
-	return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0);
+	return eap_sim_msg_finish(msg, data->eap_method, k_aut, (u8 *) "", 0);
 }
 
 
@@ -792,7 +807,7 @@
 			       EAP_AKA_SUBTYPE_CHALLENGE);
 	wpa_printf(MSG_DEBUG, "   AT_KDF");
 	eap_sim_msg_add(msg, EAP_SIM_AT_KDF, kdf, NULL, 0);
-	return eap_sim_msg_finish(msg, NULL, NULL, 0);
+	return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
 }
 
 
@@ -1025,7 +1040,7 @@
 	if (data->result_ind && attr->result_ind)
 		data->use_result_ind = 1;
 
-	if (data->state != FAILURE && data->state != RESULT_FAILURE) {
+	if (data->state != FAILURE) {
 		eap_aka_state(data, data->use_result_ind ?
 			      RESULT_SUCCESS : SUCCESS);
 	}
@@ -1241,7 +1256,7 @@
 	if (data->result_ind && attr->result_ind)
 		data->use_result_ind = 1;
 
-	if (data->state != FAILURE && data->state != RESULT_FAILURE) {
+	if (data->state != FAILURE) {
 		eap_aka_state(data, data->use_result_ind ?
 			      RESULT_SUCCESS : SUCCESS);
 	}
@@ -1347,9 +1362,7 @@
 		 */
 		ret->methodState = data->use_result_ind ?
 			METHOD_DONE : METHOD_MAY_CONT;
-	} else if (data->state == RESULT_FAILURE)
-		ret->methodState = METHOD_CONT;
-	else if (data->state == RESULT_SUCCESS)
+	} else if (data->state == RESULT_SUCCESS)
 		ret->methodState = METHOD_CONT;
 
 	if (ret->methodState == METHOD_DONE) {
@@ -1376,6 +1389,7 @@
 	data->id_msgs = NULL;
 	data->use_result_ind = 0;
 	data->kdf_negotiation = 0;
+	eap_aka_clear_keys(data, 1);
 }
 
 

Modified: wpa/trunk/src/eap_peer/eap_config.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_config.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_config.h	(original)
+++ wpa/trunk/src/eap_peer/eap_config.h	Tue Oct 14 12:39:25 2014
@@ -157,7 +157,7 @@
 	 *
 	 * If left out, this will be asked through control interface.
 	 */
-	u8 *private_key_passwd;
+	char *private_key_passwd;
 
 	/**
 	 * dh_file - File path to DH/DSA parameters file (in PEM format)
@@ -289,7 +289,7 @@
 	 * This field is like private_key_passwd, but used for phase 2 (inside
 	 * EAP-TTLS/PEAP/FAST tunnel) authentication.
 	 */
-	u8 *private_key2_passwd;
+	char *private_key2_passwd;
 
 	/**
 	 * dh_file2 - File path to DH/DSA parameters file (in PEM format)

Modified: wpa/trunk/src/eap_peer/eap_eke.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_eke.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_eke.c	(original)
+++ wpa/trunk/src/eap_peer/eap_eke.c	Tue Oct 14 12:39:25 2014
@@ -138,7 +138,7 @@
 	os_free(data->serverid);
 	os_free(data->peerid);
 	wpabuf_free(data->msgs);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -451,7 +451,7 @@
 	/* DHComponent_P = Encr(key, y_p) */
 	rpos = wpabuf_put(resp, data->sess.dhcomp_len);
 	if (eap_eke_dhcomp(&data->sess, key, pub, rpos) < 0) {
-		wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_S");
+		wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_P");
 		os_memset(key, 0, sizeof(key));
 		return eap_eke_build_fail(data, ret, reqData,
 					  EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
@@ -523,7 +523,7 @@
 	end = payload + payload_len;
 
 	if (pos + data->sess.pnonce_ps_len + data->sess.prf_len > end) {
-		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit");
+		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm");
 		return eap_eke_build_fail(data, ret, reqData,
 					  EAP_EKE_FAIL_PROTO_ERROR);
 	}
@@ -543,7 +543,7 @@
 	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_P | Nonce_S",
 			nonces, 2 * data->sess.nonce_len);
 	if (os_memcmp(data->nonce_p, nonces, data->sess.nonce_len) != 0) {
-		wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_P does not match trnsmitted Nonce_P");
+		wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_P does not match transmitted Nonce_P");
 		return eap_eke_build_fail(data, ret, reqData,
 					  EAP_EKE_FAIL_AUTHENTICATION_FAIL);
 	}
@@ -566,8 +566,8 @@
 					  EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
 	}
 	wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth_s, data->sess.prf_len);
-	if (os_memcmp(auth_s, pos + data->sess.pnonce_ps_len,
-		      data->sess.prf_len) != 0) {
+	if (os_memcmp_const(auth_s, pos + data->sess.pnonce_ps_len,
+			    data->sess.prf_len) != 0) {
 		wpa_printf(MSG_INFO, "EAP-EKE: Auth_S does not match");
 		return eap_eke_build_fail(data, ret, reqData,
 					  EAP_EKE_FAIL_AUTHENTICATION_FAIL);

Modified: wpa/trunk/src/eap_peer/eap_fast.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_fast.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_fast.c	(original)
+++ wpa/trunk/src/eap_peer/eap_fast.c	Tue Oct 14 12:39:25 2014
@@ -250,6 +250,8 @@
 		pac = pac->next;
 		eap_fast_free_pac(prev);
 	}
+	os_memset(data->key_data, 0, EAP_FAST_KEY_LEN);
+	os_memset(data->emsk, 0, EAP_EMSK_LEN);
 	os_free(data->session_id);
 	wpabuf_free(data->pending_phase2_req);
 	os_free(data);
@@ -767,7 +769,7 @@
 		    "MAC calculation", (u8 *) _bind, bind_len);
 	hmac_sha1(cmk, EAP_FAST_CMK_LEN, (u8 *) _bind, bind_len,
 		  _bind->compound_mac);
-	res = os_memcmp(cmac, _bind->compound_mac, sizeof(cmac));
+	res = os_memcmp_const(cmac, _bind->compound_mac, sizeof(cmac));
 	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Received Compound MAC",
 		    cmac, sizeof(cmac));
 	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Calculated Compound MAC",
@@ -1080,7 +1082,8 @@
 				    struct eap_fast_tlv_parse *tlv,
 				    struct wpabuf **resp)
 {
-	int mandatory, tlv_type, len, res;
+	int mandatory, tlv_type, res;
+	size_t len;
 	u8 *pos, *end;
 
 	os_memset(tlv, 0, sizeof(*tlv));
@@ -1094,13 +1097,14 @@
 		pos += 2;
 		len = WPA_GET_BE16(pos);
 		pos += 2;
-		if (pos + len > end) {
+		if (len > (size_t) (end - pos)) {
 			wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow");
 			return -1;
 		}
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: "
-			   "TLV type %d length %d%s",
-			   tlv_type, len, mandatory ? " (mandatory)" : "");
+			   "TLV type %d length %u%s",
+			   tlv_type, (unsigned int) len,
+			   mandatory ? " (mandatory)" : "");
 
 		res = eap_fast_parse_tlv(tlv, tlv_type, pos, len);
 		if (res == -2)
@@ -1634,6 +1638,8 @@
 		os_free(data);
 		return NULL;
 	}
+	os_memset(data->key_data, 0, EAP_FAST_KEY_LEN);
+	os_memset(data->emsk, 0, EAP_EMSK_LEN);
 	os_free(data->session_id);
 	data->session_id = NULL;
 	if (data->phase2_priv && data->phase2_method &&

Modified: wpa/trunk/src/eap_peer/eap_gpsk.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_gpsk.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_gpsk.c	(original)
+++ wpa/trunk/src/eap_peer/eap_gpsk.c	Tue Oct 14 12:39:25 2014
@@ -134,8 +134,11 @@
 	struct eap_gpsk_data *data = priv;
 	os_free(data->id_server);
 	os_free(data->id_peer);
-	os_free(data->psk);
-	os_free(data);
+	if (data->psk) {
+		os_memset(data->psk, 0, data->psk_len);
+		os_free(data->psk);
+	}
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -236,6 +239,8 @@
 					       size_t *list_len,
 					       const u8 *pos, const u8 *end)
 {
+	size_t len;
+
 	if (pos == NULL)
 		return NULL;
 
@@ -243,22 +248,24 @@
 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet");
 		return NULL;
 	}
-	*list_len = WPA_GET_BE16(pos);
+	len = WPA_GET_BE16(pos);
 	pos += 2;
-	if (end - pos < (int) *list_len) {
+	if (len > (size_t) (end - pos)) {
 		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow");
 		return NULL;
 	}
-	if (*list_len == 0 || (*list_len % sizeof(struct eap_gpsk_csuite))) {
+	if (len == 0 || (len % sizeof(struct eap_gpsk_csuite))) {
 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %lu",
-			   (unsigned long) *list_len);
-		return NULL;
-	}
+			   (unsigned long) len);
+		return NULL;
+	}
+
+	if (eap_gpsk_select_csuite(sm, data, pos, len) < 0)
+		return NULL;
+
 	*list = pos;
-	pos += *list_len;
-
-	if (eap_gpsk_select_csuite(sm, data, *list, *list_len) < 0)
-		return NULL;
+	*list_len = len;
+	pos += len;
 
 	return pos;
 }
@@ -561,7 +568,7 @@
 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
 		return NULL;
 	}
-	if (os_memcmp(mic, pos, miclen) != 0) {
+	if (os_memcmp_const(mic, pos, miclen) != 0) {
 		wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3");
 		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
 		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);

Modified: wpa/trunk/src/eap_peer/eap_i.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_i.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_i.h	(original)
+++ wpa/trunk/src/eap_peer/eap_i.h	Tue Oct 14 12:39:25 2014
@@ -345,6 +345,7 @@
 	struct wps_context *wps;
 
 	int prev_failure;
+	struct eap_peer_config *last_config;
 
 	struct ext_password_data *ext_pw;
 	struct wpabuf *ext_pw_buf;

Modified: wpa/trunk/src/eap_peer/eap_ikev2.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_ikev2.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_ikev2.c	(original)
+++ wpa/trunk/src/eap_peer/eap_ikev2.c	Tue Oct 14 12:39:25 2014
@@ -113,7 +113,7 @@
 	wpabuf_free(data->in_buf);
 	wpabuf_free(data->out_buf);
 	ikev2_responder_deinit(&data->ikev2);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -154,12 +154,6 @@
 			send_len -= 4;
 		}
 	}
-#ifdef CCNS_PL
-	/* Some issues figuring out the length of the message if Message Length
-	 * field not included?! */
-	if (!(flags & IKEV2_FLAGS_LENGTH_INCLUDED))
-		flags |= IKEV2_FLAGS_LENGTH_INCLUDED;
-#endif /* CCNS_PL */
 
 	plen = 1 + send_len;
 	if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
@@ -381,12 +375,7 @@
 		   "Message Length %u", flags, message_length);
 
 	if (data->state == WAIT_FRAG_ACK) {
-#ifdef CCNS_PL
-		if (len > 1) /* Empty Flags field included in ACK */
-#else /* CCNS_PL */
-		if (len != 0)
-#endif /* CCNS_PL */
-		{
+		if (len != 0) {
 			wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload "
 				   "in WAIT_FRAG_ACK state");
 			ret->ignore = TRUE;

Modified: wpa/trunk/src/eap_peer/eap_leap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_leap.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_leap.c	(original)
+++ wpa/trunk/src/eap_peer/eap_leap.c	Tue Oct 14 12:39:25 2014
@@ -244,7 +244,7 @@
 	ret->methodState = METHOD_DONE;
 	ret->allowNotifications = FALSE;
 
-	if (os_memcmp(pos, expected, LEAP_RESPONSE_LEN) != 0) {
+	if (os_memcmp_const(pos, expected, LEAP_RESPONSE_LEN) != 0) {
 		wpa_printf(MSG_WARNING, "EAP-LEAP: AP sent an invalid "
 			   "response - authentication failed");
 		wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Expected response from AP",
@@ -383,6 +383,9 @@
 	wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: master key", key, LEAP_KEY_LEN);
 	*len = LEAP_KEY_LEN;
 
+	os_memset(pw_hash, 0, sizeof(pw_hash));
+	os_memset(pw_hash_hash, 0, sizeof(pw_hash_hash));
+
 	return key;
 }
 

Modified: wpa/trunk/src/eap_peer/eap_mschapv2.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_mschapv2.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_mschapv2.c	(original)
+++ wpa/trunk/src/eap_peer/eap_mschapv2.c	Tue Oct 14 12:39:25 2014
@@ -140,7 +140,7 @@
 	os_free(data->peer_challenge);
 	os_free(data->auth_challenge);
 	wpabuf_free(data->prev_challenge);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -303,18 +303,23 @@
 			WPA_EVENT_PASSWORD_CHANGED
 			"EAP-MSCHAPV2: Password changed successfully");
 		data->prev_error = 0;
-		os_free(config->password);
+		bin_clear_free(config->password, config->password_len);
 		if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
 			/* TODO: update external storage */
 		} else if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) {
 			config->password = os_malloc(16);
 			config->password_len = 16;
-			if (config->password) {
-				nt_password_hash(config->new_password,
-						 config->new_password_len,
-						 config->password);
+			if (config->password &&
+			    nt_password_hash(config->new_password,
+					     config->new_password_len,
+					     config->password)) {
+				bin_clear_free(config->password,
+					       config->password_len);
+				config->password = NULL;
+				config->password_len = 0;
 			}
-			os_free(config->new_password);
+			bin_clear_free(config->new_password,
+				       config->new_password_len);
 		} else {
 			config->password = config->new_password;
 			config->password_len = config->new_password_len;
@@ -549,15 +554,17 @@
 	/* Encrypted-Hash */
 	if (pwhash) {
 		u8 new_password_hash[16];
-		nt_password_hash(new_password, new_password_len,
-				 new_password_hash);
+		if (nt_password_hash(new_password, new_password_len,
+				     new_password_hash))
+			goto fail;
 		nt_password_hash_encrypted_with_block(password,
 						      new_password_hash,
 						      cp->encr_hash);
 	} else {
-		old_nt_password_hash_encrypted_with_new_nt_password_hash(
-			new_password, new_password_len,
-			password, password_len, cp->encr_hash);
+		if (old_nt_password_hash_encrypted_with_new_nt_password_hash(
+			    new_password, new_password_len,
+			    password, password_len, cp->encr_hash))
+			goto fail;
 	}
 
 	/* Peer-Challenge */
@@ -594,9 +601,13 @@
 
 	/* Likewise, generate master_key here since we have the needed data
 	 * available. */
-	nt_password_hash(new_password, new_password_len, password_hash);
-	hash_nt_password_hash(password_hash, password_hash_hash);
-	get_master_key(password_hash_hash, cp->nt_response, data->master_key);
+	if (nt_password_hash(new_password, new_password_len, password_hash) ||
+	    hash_nt_password_hash(password_hash, password_hash_hash) ||
+	    get_master_key(password_hash_hash, cp->nt_response,
+			   data->master_key)) {
+		data->auth_response_valid = 0;
+		goto fail;
+	}
 	data->master_key_valid = 1;
 
 	/* Flags */

Modified: wpa/trunk/src/eap_peer/eap_pax.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_pax.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_pax.c	(original)
+++ wpa/trunk/src/eap_peer/eap_pax.c	Tue Oct 14 12:39:25 2014
@@ -86,7 +86,7 @@
 {
 	struct eap_pax_data *data = priv;
 	os_free(data->cid);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -278,7 +278,7 @@
 	eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
 		    data->rand.r.y, EAP_PAX_RAND_LEN,
 		    (u8 *) data->cid, data->cid_len, NULL, 0, mac);
-	if (os_memcmp(pos, mac, EAP_PAX_MAC_LEN) != 0) {
+	if (os_memcmp_const(pos, mac, EAP_PAX_MAC_LEN) != 0) {
 		wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(B, CID) "
 			   "received");
 		wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected MAC_CK(B, CID)",
@@ -415,7 +415,7 @@
 			    wpabuf_head(reqData), mlen, NULL, 0, NULL, 0,
 			    icvbuf);
 	}
-	if (os_memcmp(icv, icvbuf, EAP_PAX_ICV_LEN) != 0) {
+	if (os_memcmp_const(icv, icvbuf, EAP_PAX_ICV_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "EAP-PAX: invalid ICV - ignoring the "
 			   "message");
 		wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected ICV",

Modified: wpa/trunk/src/eap_peer/eap_peap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_peap.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_peap.c	(original)
+++ wpa/trunk/src/eap_peer/eap_peap.c	Tue Oct 14 12:39:25 2014
@@ -170,6 +170,15 @@
 }
 
 
+static void eap_peap_free_key(struct eap_peap_data *data)
+{
+	if (data->key_data) {
+		bin_clear_free(data->key_data, EAP_TLS_KEY_LEN);
+		data->key_data = NULL;
+	}
+}
+
+
 static void eap_peap_deinit(struct eap_sm *sm, void *priv)
 {
 	struct eap_peap_data *data = priv;
@@ -179,7 +188,7 @@
 		data->phase2_method->deinit(sm, data->phase2_priv);
 	os_free(data->phase2_types);
 	eap_peer_tls_ssl_deinit(sm, &data->ssl);
-	os_free(data->key_data);
+	eap_peap_free_key(data);
 	os_free(data->session_id);
 	wpabuf_free(data->pending_phase2_req);
 	os_free(data);
@@ -423,7 +432,7 @@
 		    buf, sizeof(buf));
 	hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
 
-	if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) {
+	if (os_memcmp_const(mac, pos, SHA1_MAC_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
 			   "cryptobinding TLV");
 		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received MAC",
@@ -1005,7 +1014,7 @@
 			char *label;
 			wpa_printf(MSG_DEBUG,
 				   "EAP-PEAP: TLS done, proceed to Phase 2");
-			os_free(data->key_data);
+			eap_peap_free_key(data);
 			/* draft-josefsson-ppext-eap-tls-eap-05.txt
 			 * specifies that PEAPv1 would use "client PEAP
 			 * encryption" as the label. However, most existing
@@ -1115,8 +1124,7 @@
 static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
 {
 	struct eap_peap_data *data = priv;
-	os_free(data->key_data);
-	data->key_data = NULL;
+	eap_peap_free_key(data);
 	os_free(data->session_id);
 	data->session_id = NULL;
 	if (eap_peer_tls_reauth_init(sm, &data->ssl)) {

Modified: wpa/trunk/src/eap_peer/eap_psk.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_psk.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_psk.c	(original)
+++ wpa/trunk/src/eap_peer/eap_psk.c	Tue Oct 14 12:39:25 2014
@@ -76,7 +76,7 @@
 	struct eap_psk_data *data = priv;
 	os_free(data->id_s);
 	os_free(data->id_p);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -237,7 +237,7 @@
 		return NULL;
 	}
 	os_free(buf);
-	if (os_memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) {
+	if (os_memcmp_const(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) {
 		wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third "
 			   "message");
 		ret->methodState = METHOD_DONE;

Modified: wpa/trunk/src/eap_peer/eap_pwd.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_pwd.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_pwd.c	(original)
+++ wpa/trunk/src/eap_peer/eap_pwd.c	Tue Oct 14 12:39:25 2014
@@ -123,7 +123,7 @@
 	if ((data->password = os_malloc(password_len)) == NULL) {
 		wpa_printf(MSG_INFO, "EAP-PWD: memory allocation psk fail");
 		BN_CTX_free(data->bnctx);
-		os_free(data->id_peer);
+		bin_clear_free(data->id_peer, data->id_peer_len);
 		os_free(data);
 		return NULL;
 	}
@@ -148,26 +148,26 @@
 {
 	struct eap_pwd_data *data = priv;
 
-	BN_free(data->private_value);
-	BN_free(data->server_scalar);
-	BN_free(data->my_scalar);
-	BN_free(data->k);
+	BN_clear_free(data->private_value);
+	BN_clear_free(data->server_scalar);
+	BN_clear_free(data->my_scalar);
+	BN_clear_free(data->k);
 	BN_CTX_free(data->bnctx);
-	EC_POINT_free(data->my_element);
-	EC_POINT_free(data->server_element);
-	os_free(data->id_peer);
-	os_free(data->id_server);
-	os_free(data->password);
+	EC_POINT_clear_free(data->my_element);
+	EC_POINT_clear_free(data->server_element);
+	bin_clear_free(data->id_peer, data->id_peer_len);
+	bin_clear_free(data->id_server, data->id_server_len);
+	bin_clear_free(data->password, data->password_len);
 	if (data->grp) {
 		EC_GROUP_free(data->grp->group);
-		EC_POINT_free(data->grp->pwe);
-		BN_free(data->grp->order);
-		BN_free(data->grp->prime);
+		EC_POINT_clear_free(data->grp->pwe);
+		BN_clear_free(data->grp->order);
+		BN_clear_free(data->grp->prime);
 		os_free(data->grp);
 	}
 	wpabuf_free(data->inbuf);
 	wpabuf_free(data->outbuf);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -317,11 +317,15 @@
 		goto fin;
 	}
 
-	BN_rand_range(data->private_value, data->grp->order);
-	BN_rand_range(mask, data->grp->order);
-	BN_add(data->my_scalar, data->private_value, mask);
-	BN_mod(data->my_scalar, data->my_scalar, data->grp->order,
-	       data->bnctx);
+	if (BN_rand_range(data->private_value, data->grp->order) != 1 ||
+	    BN_rand_range(mask, data->grp->order) != 1 ||
+	    BN_add(data->my_scalar, data->private_value, mask) != 1 ||
+	    BN_mod(data->my_scalar, data->my_scalar, data->grp->order,
+		   data->bnctx) != 1) {
+		wpa_printf(MSG_INFO,
+			   "EAP-pwd (peer): unable to get randomness");
+		goto fin;
+	}
 
 	if (!EC_POINT_mul(data->grp->group, data->my_element, NULL,
 			  data->grp->pwe, mask, data->bnctx)) {
@@ -336,7 +340,7 @@
 		wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail");
 		goto fin;
 	}
-	BN_free(mask);
+	BN_clear_free(mask);
 
 	if (((x = BN_new()) == NULL) ||
 	    ((y = BN_new()) == NULL)) {
@@ -471,11 +475,11 @@
 fin:
 	os_free(scalar);
 	os_free(element);
-	BN_free(x);
-	BN_free(y);
-	BN_free(cofactor);
-	EC_POINT_free(K);
-	EC_POINT_free(point);
+	BN_clear_free(x);
+	BN_clear_free(y);
+	BN_clear_free(cofactor);
+	EC_POINT_clear_free(K);
+	EC_POINT_clear_free(point);
 	if (data->outbuf == NULL)
 		eap_pwd_state(data, FAILURE);
 	else
@@ -589,7 +593,7 @@
 	eap_pwd_h_final(hash, conf);
 
 	ptr = (u8 *) payload;
-	if (os_memcmp(conf, ptr, SHA256_MAC_LEN)) {
+	if (os_memcmp_const(conf, ptr, SHA256_MAC_LEN)) {
 		wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm did not verify");
 		goto fin;
 	}
@@ -680,9 +684,9 @@
 	wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);
 
 fin:
-	os_free(cruft);
-	BN_free(x);
-	BN_free(y);
+	bin_clear_free(cruft, BN_num_bytes(data->grp->prime));
+	BN_clear_free(x);
+	BN_clear_free(y);
 	if (data->outbuf == NULL) {
 		ret->methodState = METHOD_DONE;
 		ret->decision = DECISION_FAIL;
@@ -782,6 +786,8 @@
 		tot_len = WPA_GET_BE16(pos);
 		wpa_printf(MSG_DEBUG, "EAP-pwd: Incoming fragments whose "
 			   "total length = %d", tot_len);
+		if (tot_len > 15000)
+			return NULL;
 		data->inbuf = wpabuf_alloc(tot_len);
 		if (data->inbuf == NULL) {
 			wpa_printf(MSG_INFO, "Out of memory to buffer "

Modified: wpa/trunk/src/eap_peer/eap_sake.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_sake.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_sake.c	(original)
+++ wpa/trunk/src/eap_peer/eap_sake.c	Tue Oct 14 12:39:25 2014
@@ -108,7 +108,7 @@
 	struct eap_sake_data *data = priv;
 	os_free(data->serverid);
 	os_free(data->peerid);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -315,7 +315,7 @@
 			     data->peerid, data->peerid_len, 0,
 			     wpabuf_head(reqData), wpabuf_len(reqData),
 			     attr.mic_s, mic_s);
-	if (os_memcmp(attr.mic_s, mic_s, EAP_SAKE_MIC_LEN) != 0) {
+	if (os_memcmp_const(attr.mic_s, mic_s, EAP_SAKE_MIC_LEN) != 0) {
 		wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_S");
 		eap_sake_state(data, FAILURE);
 		ret->methodState = METHOD_DONE;

Modified: wpa/trunk/src/eap_peer/eap_sim.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_sim.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_sim.c	(original)
+++ wpa/trunk/src/eap_peer/eap_sim.c	Tue Oct 14 12:39:25 2014
@@ -43,7 +43,7 @@
 	u8 *last_eap_identity;
 	size_t last_eap_identity_len;
 	enum {
-		CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE
+		CONTINUE, RESULT_SUCCESS, SUCCESS, FAILURE
 	} state;
 	int result_ind, use_result_ind;
 };
@@ -57,8 +57,6 @@
 		return "CONTINUE";
 	case RESULT_SUCCESS:
 		return "RESULT_SUCCESS";
-	case RESULT_FAILURE:
-		return "RESULT_FAILURE";
 	case SUCCESS:
 		return "SUCCESS";
 	case FAILURE:
@@ -132,6 +130,20 @@
 }
 
 
+static void eap_sim_clear_keys(struct eap_sim_data *data, int reauth)
+{
+	if (!reauth) {
+		os_memset(data->mk, 0, EAP_SIM_MK_LEN);
+		os_memset(data->k_aut, 0, EAP_SIM_K_AUT_LEN);
+		os_memset(data->k_encr, 0, EAP_SIM_K_ENCR_LEN);
+	}
+	os_memset(data->kc, 0, 3 * EAP_SIM_KC_LEN);
+	os_memset(data->sres, 0, 3 * EAP_SIM_SRES_LEN);
+	os_memset(data->msk, 0, EAP_SIM_KEYING_DATA_LEN);
+	os_memset(data->emsk, 0, EAP_EMSK_LEN);
+}
+
+
 static void eap_sim_deinit(struct eap_sm *sm, void *priv)
 {
 	struct eap_sim_data *data = priv;
@@ -140,6 +152,7 @@
 		os_free(data->pseudonym);
 		os_free(data->reauth_id);
 		os_free(data->last_eap_identity);
+		eap_sim_clear_keys(data, 0);
 		os_free(data);
 	}
 }
@@ -451,7 +464,7 @@
 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
 			       EAP_SIM_SUBTYPE_CLIENT_ERROR);
 	eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
-	return eap_sim_msg_finish(msg, NULL, NULL, 0);
+	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0);
 }
 
 
@@ -504,7 +517,7 @@
 				identity, identity_len);
 	}
 
-	return eap_sim_msg_finish(msg, NULL, NULL, 0);
+	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0);
 }
 
 
@@ -522,7 +535,8 @@
 	}
 	wpa_printf(MSG_DEBUG, "   AT_MAC");
 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
-	return eap_sim_msg_finish(msg, data->k_aut, (u8 *) data->sres,
+	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut,
+				  (u8 *) data->sres,
 				  data->num_chal * EAP_SIM_SRES_LEN);
 }
 
@@ -564,7 +578,7 @@
 	}
 	wpa_printf(MSG_DEBUG, "   AT_MAC");
 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
-	return eap_sim_msg_finish(msg, data->k_aut, nonce_s,
+	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, nonce_s,
 				  EAP_SIM_NONCE_S_LEN);
 }
 
@@ -598,7 +612,7 @@
 		wpa_printf(MSG_DEBUG, "   AT_MAC");
 		eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
 	}
-	return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0);
+	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, k_aut, (u8 *) "", 0);
 }
 
 
@@ -788,7 +802,7 @@
 	if (data->result_ind && attr->result_ind)
 		data->use_result_ind = 1;
 
-	if (data->state != FAILURE && data->state != RESULT_FAILURE) {
+	if (data->state != FAILURE) {
 		eap_sim_state(data, data->use_result_ind ?
 			      RESULT_SUCCESS : SUCCESS);
 	}
@@ -989,7 +1003,7 @@
 	if (data->result_ind && attr->result_ind)
 		data->use_result_ind = 1;
 
-	if (data->state != FAILURE && data->state != RESULT_FAILURE) {
+	if (data->state != FAILURE) {
 		eap_sim_state(data, data->use_result_ind ?
 			      RESULT_SUCCESS : SUCCESS);
 	}
@@ -1088,9 +1102,7 @@
 			DECISION_UNCOND_SUCC : DECISION_COND_SUCC;
 		ret->methodState = data->use_result_ind ?
 			METHOD_DONE : METHOD_MAY_CONT;
-	} else if (data->state == RESULT_FAILURE)
-		ret->methodState = METHOD_CONT;
-	else if (data->state == RESULT_SUCCESS)
+	} else if (data->state == RESULT_SUCCESS)
 		ret->methodState = METHOD_CONT;
 
 	if (ret->methodState == METHOD_DONE) {
@@ -1113,6 +1125,7 @@
 	struct eap_sim_data *data = priv;
 	eap_sim_clear_identities(sm, data, CLEAR_EAP_ID);
 	data->use_result_ind = 0;
+	eap_sim_clear_keys(data, 1);
 }
 
 

Modified: wpa/trunk/src/eap_peer/eap_tls.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_tls.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_tls.c	(original)
+++ wpa/trunk/src/eap_peer/eap_tls.c	Tue Oct 14 12:39:25 2014
@@ -125,13 +125,22 @@
 #endif /* CONFIG_HS20 */
 
 
+static void eap_tls_free_key(struct eap_tls_data *data)
+{
+	if (data->key_data) {
+		bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
+		data->key_data = NULL;
+	}
+}
+
+
 static void eap_tls_deinit(struct eap_sm *sm, void *priv)
 {
 	struct eap_tls_data *data = priv;
 	if (data == NULL)
 		return;
 	eap_peer_tls_ssl_deinit(sm, &data->ssl);
-	os_free(data->key_data);
+	eap_tls_free_key(data);
 	os_free(data->session_id);
 	os_free(data);
 }
@@ -181,7 +190,7 @@
 	ret->methodState = METHOD_DONE;
 	ret->decision = DECISION_UNCOND_SUCC;
 
-	os_free(data->key_data);
+	eap_tls_free_key(data);
 	data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
 						 "client EAP encryption",
 						 EAP_TLS_KEY_LEN +
@@ -267,8 +276,7 @@
 static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv)
 {
 	struct eap_tls_data *data = priv;
-	os_free(data->key_data);
-	data->key_data = NULL;
+	eap_tls_free_key(data);
 	os_free(data->session_id);
 	data->session_id = NULL;
 	if (eap_peer_tls_reauth_init(sm, &data->ssl)) {

Modified: wpa/trunk/src/eap_peer/eap_tnc.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_tnc.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_tnc.c	(original)
+++ wpa/trunk/src/eap_peer/eap_tnc.c	Tue Oct 14 12:39:25 2014
@@ -243,7 +243,8 @@
 		message_length = WPA_GET_BE32(pos);
 		pos += 4;
 
-		if (message_length < (u32) (end - pos)) {
+		if (message_length < (u32) (end - pos) ||
+		    message_length > 75000) {
 			wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message "
 				   "Length (%d; %ld remaining in this msg)",
 				   message_length, (long) (end - pos));

Modified: wpa/trunk/src/eap_peer/eap_ttls.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/eap_ttls.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/eap_ttls.c	(original)
+++ wpa/trunk/src/eap_peer/eap_ttls.c	Tue Oct 14 12:39:25 2014
@@ -133,6 +133,15 @@
 }
 
 
+static void eap_ttls_free_key(struct eap_ttls_data *data)
+{
+	if (data->key_data) {
+		bin_clear_free(data->key_data, EAP_TLS_KEY_LEN);
+		data->key_data = NULL;
+	}
+}
+
+
 static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
 {
 	struct eap_ttls_data *data = priv;
@@ -141,7 +150,7 @@
 	eap_ttls_phase2_eap_deinit(sm, data);
 	os_free(data->phase2_eap_types);
 	eap_peer_tls_ssl_deinit(sm, &data->ssl);
-	os_free(data->key_data);
+	eap_ttls_free_key(data);
 	os_free(data->session_id);
 	wpabuf_free(data->pending_phase2_req);
 	os_free(data);
@@ -213,7 +222,7 @@
 static int eap_ttls_v0_derive_key(struct eap_sm *sm,
 				  struct eap_ttls_data *data)
 {
-	os_free(data->key_data);
+	eap_ttls_free_key(data);
 	data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
 						 "ttls keying material",
 						 EAP_TLS_KEY_LEN);
@@ -491,16 +500,6 @@
 
 	wpabuf_put(msg, pos - buf);
 	*resp = msg;
-
-	if (sm->workaround) {
-		/* At least FreeRADIUS seems to be terminating
-		 * EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success
-		 * packet. */
-		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: EAP workaround - "
-			   "allow success without tunneled response");
-		ret->methodState = METHOD_MAY_CONT;
-		ret->decision = DECISION_COND_SUCC;
-	}
 
 	return 0;
 #else /* EAP_MSCHAPv2 */
@@ -1540,8 +1539,7 @@
 static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv)
 {
 	struct eap_ttls_data *data = priv;
-	os_free(data->key_data);
-	data->key_data = NULL;
+	eap_ttls_free_key(data);
 	os_free(data->session_id);
 	data->session_id = NULL;
 	if (eap_peer_tls_reauth_init(sm, &data->ssl)) {

Modified: wpa/trunk/src/eap_peer/ikev2.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/ikev2.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/ikev2.c	(original)
+++ wpa/trunk/src/eap_peer/ikev2.c	Tue Oct 14 12:39:25 2014
@@ -72,27 +72,10 @@
 	os_memcpy(pos, data->i_spi, IKEV2_SPI_LEN);
 	pos += IKEV2_SPI_LEN;
 	os_memcpy(pos, data->r_spi, IKEV2_SPI_LEN);
-#ifdef CCNS_PL
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-	{
-		int i;
-		u8 *tmp = pos - IKEV2_SPI_LEN;
-		/* Incorrect byte re-ordering on little endian hosts.. */
-		for (i = 0; i < IKEV2_SPI_LEN; i++)
-			*tmp++ = data->i_spi[IKEV2_SPI_LEN - 1 - i];
-		for (i = 0; i < IKEV2_SPI_LEN; i++)
-			*tmp++ = data->r_spi[IKEV2_SPI_LEN - 1 - i];
-	}
-#endif
-#endif /* CCNS_PL */
 
 	/* SKEYSEED = prf(Ni | Nr, g^ir) */
 	/* Use zero-padding per RFC 4306, Sect. 2.14 */
 	pad_len = data->dh->prime_len - wpabuf_len(shared);
-#ifdef CCNS_PL
-	/* Shared secret is not zero-padded correctly */
-	pad_len = 0;
-#endif /* CCNS_PL */
 	pad = os_zalloc(pad_len ? pad_len : 1);
 	if (pad == NULL) {
 		wpabuf_free(shared);
@@ -179,21 +162,12 @@
 						   "Transform Attr for AES");
 					break;
 				}
-#ifdef CCNS_PL
-				if (WPA_GET_BE16(pos) != 0x001d /* ?? */) {
-					wpa_printf(MSG_DEBUG, "IKEV2: Not a "
-						   "Key Size attribute for "
-						   "AES");
-					break;
-				}
-#else /* CCNS_PL */
 				if (WPA_GET_BE16(pos) != 0x800e) {
 					wpa_printf(MSG_DEBUG, "IKEV2: Not a "
 						   "Key Size attribute for "
 						   "AES");
 					break;
 				}
-#endif /* CCNS_PL */
 				if (WPA_GET_BE16(pos + 2) != 128) {
 					wpa_printf(MSG_DEBUG, "IKEV2: "
 						   "Unsupported AES key size "
@@ -456,14 +430,6 @@
 		return -1;
 	}
 
-#ifdef CCNS_PL
-	/* Zeros are removed incorrectly from the beginning of the nonces */
-	while (ni_len > 1 && *ni == 0) {
-		ni_len--;
-		ni++;
-	}
-#endif /* CCNS_PL */
-
 	data->i_nonce_len = ni_len;
 	os_memcpy(data->i_nonce, ni, ni_len);
 	wpa_hexdump(MSG_MSGDUMP, "IKEV2: Ni",
@@ -599,7 +565,7 @@
 		return -1;
 
 	if (auth_len != prf->hash_len ||
-	    os_memcmp(auth, auth_data, auth_len) != 0) {
+	    os_memcmp_const(auth, auth_data, auth_len) != 0) {
 		wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data");
 		wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data",
 			    auth, auth_len);
@@ -887,16 +853,7 @@
 	phdr->flags = 0;
 
 	p = wpabuf_put(msg, sizeof(*p));
-#ifdef CCNS_PL
-	/* Seems to require that the Proposal # is 1 even though RFC 4306
-	 * Sect 3.3.1 has following requirement "When a proposal is accepted,
-	 * all of the proposal numbers in the SA payload MUST be the same and
-	 * MUST match the number on the proposal sent that was accepted.".
-	 */
-	p->proposal_num = 1;
-#else /* CCNS_PL */
 	p->proposal_num = data->proposal.proposal_num;
-#endif /* CCNS_PL */
 	p->protocol_id = IKEV2_PROTOCOL_IKE;
 	p->num_transforms = 4;
 
@@ -906,11 +863,7 @@
 	WPA_PUT_BE16(t->transform_id, data->proposal.encr);
 	if (data->proposal.encr == ENCR_AES_CBC) {
 		/* Transform Attribute: Key Len = 128 bits */
-#ifdef CCNS_PL
-		wpabuf_put_be16(msg, 0x001d); /* ?? */
-#else /* CCNS_PL */
 		wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */
-#endif /* CCNS_PL */
 		wpabuf_put_be16(msg, 128); /* 128-bit key */
 	}
 	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t;
@@ -1082,11 +1035,7 @@
 	phdr = wpabuf_put(msg, sizeof(*phdr));
 	phdr->next_payload = next_payload;
 	phdr->flags = 0;
-#ifdef CCNS_PL
-	wpabuf_put_u8(msg, 1); /* Protocol ID: IKE_SA notification */
-#else /* CCNS_PL */
 	wpabuf_put_u8(msg, 0); /* Protocol ID: no existing SA */
-#endif /* CCNS_PL */
 	wpabuf_put_u8(msg, 0); /* SPI Size */
 	wpabuf_put_be16(msg, data->error_type);
 
@@ -1130,13 +1079,6 @@
 	data->r_nonce_len = IKEV2_NONCE_MIN_LEN;
 	if (random_get_bytes(data->r_nonce, data->r_nonce_len))
 		return NULL;
-#ifdef CCNS_PL
-	/* Zeros are removed incorrectly from the beginning of the nonces in
-	 * key derivation; as a workaround, make sure Nr does not start with
-	 * zero.. */
-	if (data->r_nonce[0] == 0)
-		data->r_nonce[0] = 1;
-#endif /* CCNS_PL */
 	wpa_hexdump(MSG_DEBUG, "IKEV2: Nr", data->r_nonce, data->r_nonce_len);
 
 	msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1500);

Modified: wpa/trunk/src/eap_peer/mschapv2.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/mschapv2.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/mschapv2.c	(original)
+++ wpa/trunk/src/eap_peer/mschapv2.c	Tue Oct 14 12:39:25 2014
@@ -117,8 +117,8 @@
 	    buf[0] != 'S' || buf[1] != '=' ||
 	    hexstr2bin((char *) (buf + 2), recv_response,
 		       MSCHAPV2_AUTH_RESPONSE_LEN) ||
-	    os_memcmp(auth_response, recv_response,
-		      MSCHAPV2_AUTH_RESPONSE_LEN) != 0)
+	    os_memcmp_const(auth_response, recv_response,
+			    MSCHAPV2_AUTH_RESPONSE_LEN) != 0)
 		return -1;
 	return 0;
 }

Modified: wpa/trunk/src/eap_peer/tncc.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_peer/tncc.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_peer/tncc.c	(original)
+++ wpa/trunk/src/eap_peer/tncc.c	Tue Oct 14 12:39:25 2014
@@ -1092,8 +1092,10 @@
 			int error = 0;
 
 			imc = tncc_parse_imc(pos + 4, line_end, &error);
-			if (error)
+			if (error) {
+				os_free(config);
 				return -1;
+			}
 			if (imc) {
 				if (last == NULL)
 					tncc->imc = imc;

Modified: wpa/trunk/src/eap_server/eap_server.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server.c	(original)
+++ wpa/trunk/src/eap_server/eap_server.c	Tue Oct 14 12:39:25 2014
@@ -168,7 +168,7 @@
 	sm->eap_if.eapSuccess = FALSE;
 	sm->eap_if.eapFail = FALSE;
 	sm->eap_if.eapTimeout = FALSE;
-	os_free(sm->eap_if.eapKeyData);
+	bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
 	sm->eap_if.eapKeyData = NULL;
 	sm->eap_if.eapKeyDataLen = 0;
 	sm->eap_if.eapKeyAvailable = FALSE;
@@ -346,7 +346,7 @@
 	sm->m->process(sm, sm->eap_method_priv, sm->eap_if.eapRespData);
 	if (sm->m->isDone(sm, sm->eap_method_priv)) {
 		eap_sm_Policy_update(sm, NULL, 0);
-		os_free(sm->eap_if.eapKeyData);
+		bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
 		if (sm->m->getKey) {
 			sm->eap_if.eapKeyData = sm->m->getKey(
 				sm, sm->eap_method_priv,
@@ -632,7 +632,7 @@
 	if (sm->eap_if.aaaEapKeyAvailable) {
 		EAP_COPY(&sm->eap_if.eapKeyData, sm->eap_if.aaaEapKeyData);
 	} else {
-		os_free(sm->eap_if.eapKeyData);
+		bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
 		sm->eap_if.eapKeyData = NULL;
 		sm->eap_if.eapKeyDataLen = 0;
 	}
@@ -1260,7 +1260,7 @@
 {
 	if (user == NULL)
 		return;
-	os_free(user->password);
+	bin_clear_free(user->password, user->password_len);
 	user->password = NULL;
 	os_free(user);
 }
@@ -1352,7 +1352,7 @@
 	if (sm->m && sm->eap_method_priv)
 		sm->m->reset(sm, sm->eap_method_priv);
 	wpabuf_free(sm->eap_if.eapReqData);
-	os_free(sm->eap_if.eapKeyData);
+	bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
 	wpabuf_free(sm->lastReqData);
 	wpabuf_free(sm->eap_if.eapRespData);
 	os_free(sm->identity);
@@ -1361,7 +1361,7 @@
 	os_free(sm->eap_fast_a_id_info);
 	wpabuf_free(sm->eap_if.aaaEapReqData);
 	wpabuf_free(sm->eap_if.aaaEapRespData);
-	os_free(sm->eap_if.aaaEapKeyData);
+	bin_clear_free(sm->eap_if.aaaEapKeyData, sm->eap_if.aaaEapKeyDataLen);
 	eap_user_free(sm->user);
 	wpabuf_free(sm->assoc_wps_ie);
 	wpabuf_free(sm->assoc_p2p_ie);

Modified: wpa/trunk/src/eap_server/eap_server_aka.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_aka.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_aka.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_aka.c	Tue Oct 14 12:39:25 2014
@@ -241,7 +241,7 @@
 	os_free(data->next_reauth_id);
 	wpabuf_free(data->id_msgs);
 	os_free(data->network_name);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -336,7 +336,7 @@
 	else
 		sha1_vector(1, &addr, &len, hash);
 
-	if (os_memcmp(hash, checkcode, hash_len) != 0) {
+	if (os_memcmp_const(hash, checkcode, hash_len) != 0) {
 		wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
 		return -1;
 	}
@@ -377,7 +377,7 @@
 		wpa_printf(MSG_DEBUG, "   AT_PERMANENT_ID_REQ");
 		eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
 	}
-	buf = eap_sim_msg_finish(msg, NULL, NULL, 0);
+	buf = eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
 	if (eap_aka_add_id_msg(data, buf) < 0) {
 		wpabuf_free(buf);
 		return NULL;
@@ -534,7 +534,7 @@
 
 	wpa_printf(MSG_DEBUG, "   AT_MAC");
 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
-	return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
+	return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0);
 }
 
 
@@ -581,7 +581,7 @@
 
 	wpa_printf(MSG_DEBUG, "   AT_MAC");
 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
-	return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
+	return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0);
 }
 
 
@@ -620,7 +620,7 @@
 		wpa_printf(MSG_DEBUG, "   AT_MAC");
 		eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
 	}
-	return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
+	return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0);
 }
 
 
@@ -963,7 +963,7 @@
 	 */
 	if (attr->res == NULL || attr->res_len < data->res_len ||
 	    attr->res_len_bits != data->res_len * 8 ||
-	    os_memcmp(attr->res, data->res, data->res_len) != 0) {
+	    os_memcmp_const(attr->res, data->res, data->res_len) != 0) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
 			   "include valid AT_RES (attr len=%lu, res len=%lu "
 			   "bits, expected %lu bits)",

Modified: wpa/trunk/src/eap_server/eap_server_eke.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_eke.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_eke.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_eke.c	Tue Oct 14 12:39:25 2014
@@ -104,7 +104,7 @@
 	eap_eke_session_clean(&data->sess);
 	os_free(data->peerid);
 	wpabuf_free(data->msgs);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -635,8 +635,8 @@
 		return;
 	}
 	wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth_p, data->sess.prf_len);
-	if (os_memcmp(auth_p, payload + data->sess.pnonce_len,
-		      data->sess.prf_len) != 0) {
+	if (os_memcmp_const(auth_p, payload + data->sess.pnonce_len,
+			    data->sess.prf_len) != 0) {
 		wpa_printf(MSG_INFO, "EAP-EKE: Auth_P does not match");
 		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
 		return;

Modified: wpa/trunk/src/eap_server/eap_server_fast.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_fast.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_fast.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_fast.c	Tue Oct 14 12:39:25 2014
@@ -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);
@@ -187,7 +187,7 @@
 		switch (*pos) {
 		case PAC_OPAQUE_TYPE_PAD:
 			pos = end;
-			break;
+			goto done;
 		case PAC_OPAQUE_TYPE_KEY:
 			if (pos[1] != EAP_FAST_PAC_KEY_LEN) {
 				wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid "
@@ -218,6 +218,7 @@
 
 		pos += 2 + pos[1];
 	}
+done:
 
 	if (pac_key == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC-Key included in "
@@ -511,7 +512,7 @@
 	os_free(data->key_block_p);
 	wpabuf_free(data->pending_phase2_resp);
 	os_free(data->identity);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -730,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;
@@ -1123,7 +1124,8 @@
 static int eap_fast_parse_tlvs(struct wpabuf *data,
 			       struct eap_fast_tlv_parse *tlv)
 {
-	int mandatory, tlv_type, len, res;
+	int mandatory, tlv_type, res;
+	size_t len;
 	u8 *pos, *end;
 
 	os_memset(tlv, 0, sizeof(*tlv));
@@ -1136,13 +1138,14 @@
 		pos += 2;
 		len = WPA_GET_BE16(pos);
 		pos += 2;
-		if (pos + len > end) {
+		if (len > (size_t) (end - pos)) {
 			wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow");
 			return -1;
 		}
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: "
-			   "TLV type %d length %d%s",
-			   tlv_type, len, mandatory ? " (mandatory)" : "");
+			   "TLV type %d length %u%s",
+			   tlv_type, (unsigned int) len,
+			   mandatory ? " (mandatory)" : "");
 
 		res = eap_fast_parse_tlv(tlv, tlv_type, pos, len);
 		if (res == -2)
@@ -1196,7 +1199,7 @@
 		return -1;
 	}
 
-	if (os_memcmp(data->crypto_binding_nonce, b->nonce, 31) != 0 ||
+	if (os_memcmp_const(data->crypto_binding_nonce, b->nonce, 31) != 0 ||
 	    (data->crypto_binding_nonce[31] | 1) != b->nonce[31]) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid nonce in "
 			   "Crypto-Binding");
@@ -1210,7 +1213,7 @@
 		    (u8 *) b, bind_len);
 	hmac_sha1(data->cmk, EAP_FAST_CMK_LEN, (u8 *) b, bind_len,
 		  b->compound_mac);
-	if (os_memcmp(cmac, b->compound_mac, sizeof(cmac)) != 0) {
+	if (os_memcmp_const(cmac, b->compound_mac, sizeof(cmac)) != 0) {
 		wpa_hexdump(MSG_MSGDUMP,
 			    "EAP-FAST: Calculated Compound MAC",
 			    b->compound_mac, sizeof(cmac));

Modified: wpa/trunk/src/eap_server/eap_server_gpsk.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_gpsk.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_gpsk.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_gpsk.c	Tue Oct 14 12:39:25 2014
@@ -95,7 +95,7 @@
 {
 	struct eap_gpsk_data *data = priv;
 	os_free(data->id_peer);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -433,7 +433,7 @@
 		eap_gpsk_state(data, FAILURE);
 		return;
 	}
-	if (os_memcmp(mic, pos, miclen) != 0) {
+	if (os_memcmp_const(mic, pos, miclen) != 0) {
 		wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-2");
 		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
 		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
@@ -502,7 +502,7 @@
 		eap_gpsk_state(data, FAILURE);
 		return;
 	}
-	if (os_memcmp(mic, pos, miclen) != 0) {
+	if (os_memcmp_const(mic, pos, miclen) != 0) {
 		wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-4");
 		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
 		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);

Modified: wpa/trunk/src/eap_server/eap_server_gtc.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_gtc.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_gtc.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_gtc.c	Tue Oct 14 12:39:25 2014
@@ -175,7 +175,7 @@
 	}
 
 	if (rlen != sm->user->password_len ||
-	    os_memcmp(pos, sm->user->password, rlen) != 0) {
+	    os_memcmp_const(pos, sm->user->password, rlen) != 0) {
 		wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Failure");
 		data->state = FAILURE;
 	} else {

Modified: wpa/trunk/src/eap_server/eap_server_ikev2.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_ikev2.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_ikev2.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_ikev2.c	Tue Oct 14 12:39:25 2014
@@ -127,7 +127,7 @@
 	wpabuf_free(data->in_buf);
 	wpabuf_free(data->out_buf);
 	ikev2_initiator_deinit(&data->ikev2);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 

Modified: wpa/trunk/src/eap_server/eap_server_md5.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_md5.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_md5.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_md5.c	Tue Oct 14 12:39:25 2014
@@ -126,7 +126,7 @@
 		return;
 	}
 
-	if (os_memcmp(hash, pos, CHAP_MD5_LEN) == 0) {
+	if (os_memcmp_const(hash, pos, CHAP_MD5_LEN) == 0) {
 		wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Success");
 		data->state = SUCCESS;
 	} else {

Modified: wpa/trunk/src/eap_server/eap_server_mschapv2.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_mschapv2.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_mschapv2.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_mschapv2.c	Tue Oct 14 12:39:25 2014
@@ -91,7 +91,7 @@
 		return;
 
 	os_free(data->peer_challenge);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -393,7 +393,7 @@
 		return;
 	}
 
-	if (os_memcmp(nt_response, expected, 24) == 0) {
+	if (os_memcmp_const(nt_response, expected, 24) == 0) {
 		const u8 *pw_hash;
 		u8 pw_hash_buf[16], pw_hash_hash[16];
 

Modified: wpa/trunk/src/eap_server/eap_server_pax.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_pax.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_pax.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_pax.c	Tue Oct 14 12:39:25 2014
@@ -64,7 +64,7 @@
 {
 	struct eap_pax_data *data = priv;
 	os_free(data->cid);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -268,7 +268,7 @@
 			    wpabuf_mhead(respData),
 			    wpabuf_len(respData) - EAP_PAX_ICV_LEN,
 			    NULL, 0, NULL, 0, icvbuf);
-		if (os_memcmp(icvbuf, icv, EAP_PAX_ICV_LEN) != 0) {
+		if (os_memcmp_const(icvbuf, icv, EAP_PAX_ICV_LEN) != 0) {
 			wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV");
 			wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV",
 				    icvbuf, EAP_PAX_ICV_LEN);
@@ -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) {
@@ -395,7 +400,7 @@
 		    data->rand.r.x, EAP_PAX_RAND_LEN,
 		    data->rand.r.y, EAP_PAX_RAND_LEN,
 		    (u8 *) data->cid, data->cid_len, mac);
-	if (os_memcmp(mac, pos, EAP_PAX_MAC_LEN) != 0) {
+	if (os_memcmp_const(mac, pos, EAP_PAX_MAC_LEN) != 0) {
 		wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(A, B, CID) in "
 			   "PAX_STD-2");
 		wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected MAC_CK(A, B, CID)",
@@ -417,7 +422,7 @@
 		    wpabuf_head(respData),
 		    wpabuf_len(respData) - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0,
 		    icvbuf);
-	if (os_memcmp(icvbuf, pos, EAP_PAX_ICV_LEN) != 0) {
+	if (os_memcmp_const(icvbuf, pos, EAP_PAX_ICV_LEN) != 0) {
 		wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV in PAX_STD-2");
 		wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV",
 			    icvbuf, EAP_PAX_ICV_LEN);

Modified: wpa/trunk/src/eap_server/eap_server_peap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_peap.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_peap.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_peap.c	Tue Oct 14 12:39:25 2014
@@ -172,7 +172,7 @@
 	wpabuf_free(data->pending_phase2_resp);
 	os_free(data->phase2_key);
 	wpabuf_free(data->soh_response);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -593,7 +593,7 @@
 	buf[60] = EAP_TYPE_PEAP;
 	hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
 
-	if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) {
+	if (os_memcmp_const(mac, pos, SHA1_MAC_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
 			   "cryptobinding TLV");
 		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20);

Modified: wpa/trunk/src/eap_server/eap_server_psk.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_psk.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_psk.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_psk.c	Tue Oct 14 12:39:25 2014
@@ -47,7 +47,7 @@
 {
 	struct eap_psk_data *data = priv;
 	os_free(data->id_p);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -314,7 +314,7 @@
 	}
 	os_free(buf);
 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", resp->mac_p, EAP_PSK_MAC_LEN);
-	if (os_memcmp(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) {
+	if (os_memcmp_const(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) {
 		wpa_printf(MSG_INFO, "EAP-PSK: Invalid MAC_P");
 		wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Expected MAC_P",
 			    mac, EAP_PSK_MAC_LEN);

Modified: wpa/trunk/src/eap_server/eap_server_pwd.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_pwd.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_pwd.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_pwd.c	Tue Oct 14 12:39:25 2014
@@ -106,7 +106,7 @@
 	if (data->password == NULL) {
 		wpa_printf(MSG_INFO, "EAP-PWD: Memory allocation password "
 			   "fail");
-		os_free(data->id_server);
+		bin_clear_free(data->id_server, data->id_server_len);
 		os_free(data);
 		return NULL;
 	}
@@ -116,8 +116,8 @@
 	data->bnctx = BN_CTX_new();
 	if (data->bnctx == NULL) {
 		wpa_printf(MSG_INFO, "EAP-PWD: bn context allocation fail");
-		os_free(data->password);
-		os_free(data->id_server);
+		bin_clear_free(data->password, data->password_len);
+		bin_clear_free(data->id_server, data->id_server_len);
 		os_free(data);
 		return NULL;
 	}
@@ -135,26 +135,26 @@
 {
 	struct eap_pwd_data *data = priv;
 
-	BN_free(data->private_value);
-	BN_free(data->peer_scalar);
-	BN_free(data->my_scalar);
-	BN_free(data->k);
+	BN_clear_free(data->private_value);
+	BN_clear_free(data->peer_scalar);
+	BN_clear_free(data->my_scalar);
+	BN_clear_free(data->k);
 	BN_CTX_free(data->bnctx);
-	EC_POINT_free(data->my_element);
-	EC_POINT_free(data->peer_element);
-	os_free(data->id_peer);
-	os_free(data->id_server);
-	os_free(data->password);
+	EC_POINT_clear_free(data->my_element);
+	EC_POINT_clear_free(data->peer_element);
+	bin_clear_free(data->id_peer, data->id_peer_len);
+	bin_clear_free(data->id_server, data->id_server_len);
+	bin_clear_free(data->password, data->password_len);
 	if (data->grp) {
 		EC_GROUP_free(data->grp->group);
-		EC_POINT_free(data->grp->pwe);
-		BN_free(data->grp->order);
-		BN_free(data->grp->prime);
+		EC_POINT_clear_free(data->grp->pwe);
+		BN_clear_free(data->grp->order);
+		BN_clear_free(data->grp->prime);
 		os_free(data->grp);
 	}
 	wpabuf_free(data->inbuf);
 	wpabuf_free(data->outbuf);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -210,11 +210,15 @@
 		goto fin;
 	}
 
-	BN_rand_range(data->private_value, data->grp->order);
-	BN_rand_range(mask, data->grp->order);
-	BN_add(data->my_scalar, data->private_value, mask);
-	BN_mod(data->my_scalar, data->my_scalar, data->grp->order,
-	       data->bnctx);
+	if (BN_rand_range(data->private_value, data->grp->order) != 1 ||
+	    BN_rand_range(mask, data->grp->order) != 1 ||
+	    BN_add(data->my_scalar, data->private_value, mask) != 1 ||
+	    BN_mod(data->my_scalar, data->my_scalar, data->grp->order,
+		   data->bnctx) != 1) {
+		wpa_printf(MSG_INFO,
+			   "EAP-pwd (server): unable to get randomness");
+		goto fin;
+	}
 
 	if (!EC_POINT_mul(data->grp->group, data->my_element, NULL,
 			  data->grp->pwe, mask, data->bnctx)) {
@@ -230,7 +234,7 @@
 			   "fail");
 		goto fin;
 	}
-	BN_free(mask);
+	BN_clear_free(mask);
 
 	if (((x = BN_new()) == NULL) ||
 	    ((y = BN_new()) == NULL)) {
@@ -282,8 +286,8 @@
 fin:
 	os_free(scalar);
 	os_free(element);
-	BN_free(x);
-	BN_free(y);
+	BN_clear_free(x);
+	BN_clear_free(y);
 	if (data->outbuf == NULL)
 		eap_pwd_state(data, FAILURE);
 }
@@ -406,9 +410,9 @@
 	wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);
 
 fin:
-	os_free(cruft);
-	BN_free(x);
-	BN_free(y);
+	bin_clear_free(cruft, BN_num_bytes(data->grp->prime));
+	BN_clear_free(x);
+	BN_clear_free(y);
 	if (data->outbuf == NULL)
 		eap_pwd_state(data, FAILURE);
 }
@@ -724,11 +728,11 @@
 	res = 1;
 
 fin:
-	EC_POINT_free(K);
-	EC_POINT_free(point);
-	BN_free(cofactor);
-	BN_free(x);
-	BN_free(y);
+	EC_POINT_clear_free(K);
+	EC_POINT_clear_free(point);
+	BN_clear_free(cofactor);
+	BN_clear_free(x);
+	BN_clear_free(y);
 
 	if (res)
 		eap_pwd_state(data, PWD_Confirm_Req);
@@ -835,7 +839,7 @@
 	eap_pwd_h_final(hash, conf);
 
 	ptr = (u8 *) payload;
-	if (os_memcmp(conf, ptr, SHA256_MAC_LEN)) {
+	if (os_memcmp_const(conf, ptr, SHA256_MAC_LEN)) {
 		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm did not "
 			   "verify");
 		goto fin;
@@ -851,9 +855,9 @@
 		eap_pwd_state(data, SUCCESS);
 
 fin:
-	os_free(cruft);
-	BN_free(x);
-	BN_free(y);
+	bin_clear_free(cruft, BN_num_bytes(data->grp->prime));
+	BN_clear_free(x);
+	BN_clear_free(y);
 }
 
 
@@ -900,6 +904,8 @@
 		tot_len = WPA_GET_BE16(pos);
 		wpa_printf(MSG_DEBUG, "EAP-pwd: Incoming fragments, total "
 			   "length = %d", tot_len);
+		if (tot_len > 15000)
+			return;
 		data->inbuf = wpabuf_alloc(tot_len);
 		if (data->inbuf == NULL) {
 			wpa_printf(MSG_INFO, "EAP-pwd: Out of memory to "

Modified: wpa/trunk/src/eap_server/eap_server_sake.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_sake.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_sake.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_sake.c	Tue Oct 14 12:39:25 2014
@@ -83,7 +83,7 @@
 {
 	struct eap_sake_data *data = priv;
 	os_free(data->peerid);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -351,7 +351,7 @@
 			     data->peerid, data->peerid_len, 1,
 			     wpabuf_head(respData), wpabuf_len(respData),
 			     attr.mic_p, mic_p);
-	if (os_memcmp(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) {
+	if (os_memcmp_const(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) {
 		wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_P");
 		eap_sake_state(data, FAILURE);
 		return;
@@ -388,7 +388,7 @@
 			     data->peerid, data->peerid_len, 1,
 			     wpabuf_head(respData), wpabuf_len(respData),
 			     attr.mic_p, mic_p);
-	if (os_memcmp(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) {
+	if (os_memcmp_const(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) {
 		wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_P");
 		eap_sake_state(data, FAILURE);
 	} else

Modified: wpa/trunk/src/eap_server/eap_server_sim.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_sim.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_sim.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_sim.c	Tue Oct 14 12:39:25 2014
@@ -94,7 +94,7 @@
 	struct eap_sim_data *data = priv;
 	os_free(data->next_pseudonym);
 	os_free(data->next_reauth_id);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -140,7 +140,7 @@
 	ver[1] = EAP_SIM_VERSION;
 	eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver),
 			ver, sizeof(ver));
-	return eap_sim_msg_finish(msg, NULL, NULL, 0);
+	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0);
 }
 
 
@@ -240,8 +240,8 @@
 
 	wpa_printf(MSG_DEBUG, "   AT_MAC");
 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
-	return eap_sim_msg_finish(msg, data->k_aut, data->nonce_mt,
-				  EAP_SIM_NONCE_MT_LEN);
+	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut,
+				  data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
 }
 
 
@@ -278,7 +278,7 @@
 
 	wpa_printf(MSG_DEBUG, "   AT_MAC");
 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
-	return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
+	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, NULL, 0);
 }
 
 
@@ -317,7 +317,7 @@
 		wpa_printf(MSG_DEBUG, "   AT_MAC");
 		eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
 	}
-	return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
+	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, NULL, 0);
 }
 
 

Modified: wpa/trunk/src/eap_server/eap_server_tnc.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_tnc.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_tnc.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_tnc.c	Tue Oct 14 12:39:25 2014
@@ -480,7 +480,8 @@
 		message_length = WPA_GET_BE32(pos);
 		pos += 4;
 
-		if (message_length < (u32) (end - pos)) {
+		if (message_length < (u32) (end - pos) ||
+		    message_length > 75000) {
 			wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message "
 				   "Length (%d; %ld remaining in this msg)",
 				   message_length, (long) (end - pos));

Modified: wpa/trunk/src/eap_server/eap_server_ttls.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/eap_server_ttls.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/eap_server_ttls.c	(original)
+++ wpa/trunk/src/eap_server/eap_server_ttls.c	Tue Oct 14 12:39:25 2014
@@ -336,7 +336,7 @@
 		data->phase2_method->reset(sm, data->phase2_priv);
 	eap_server_tls_ssl_deinit(sm, &data->ssl);
 	wpabuf_free(data->pending_phase2_eap_resp);
-	os_free(data);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -509,8 +509,8 @@
 	}
 
 	if (sm->user->password_len != user_password_len ||
-	    os_memcmp(sm->user->password, user_password, user_password_len) !=
-	    0) {
+	    os_memcmp_const(sm->user->password, user_password,
+			    user_password_len) != 0) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Invalid user password");
 		eap_ttls_state(data, FAILURE);
 		return;
@@ -558,7 +558,8 @@
 		return;
 	}
 
-	if (os_memcmp(challenge, chal, EAP_TTLS_CHAP_CHALLENGE_LEN) != 0 ||
+	if (os_memcmp_const(challenge, chal, EAP_TTLS_CHAP_CHALLENGE_LEN)
+	    != 0 ||
 	    password[0] != chal[EAP_TTLS_CHAP_CHALLENGE_LEN]) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Challenge mismatch");
 		os_free(chal);
@@ -571,7 +572,8 @@
 	chap_md5(password[0], sm->user->password, sm->user->password_len,
 		 challenge, challenge_len, hash);
 
-	if (os_memcmp(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) == 0) {
+	if (os_memcmp_const(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) ==
+	    0) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Correct user password");
 		eap_ttls_state(data, SUCCESS);
 	} else {
@@ -616,7 +618,8 @@
 		return;
 	}
 
-	if (os_memcmp(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN) != 0 ||
+	if (os_memcmp_const(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN)
+	    != 0 ||
 	    response[0] != chal[EAP_TTLS_MSCHAP_CHALLENGE_LEN]) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Challenge mismatch");
 		os_free(chal);
@@ -631,7 +634,7 @@
 		nt_challenge_response(challenge, sm->user->password,
 				      sm->user->password_len, nt_response);
 
-	if (os_memcmp(nt_response, response + 2 + 24, 24) == 0) {
+	if (os_memcmp_const(nt_response, response + 2 + 24, 24) == 0) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Correct response");
 		eap_ttls_state(data, SUCCESS);
 	} else {
@@ -703,7 +706,8 @@
 		return;
 	}
 
-	if (os_memcmp(challenge, chal, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) != 0 ||
+	if (os_memcmp_const(challenge, chal, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN)
+	    != 0 ||
 	    response[0] != chal[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Challenge mismatch");
 		os_free(chal);
@@ -736,7 +740,7 @@
 	}
 
 	rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8;
-	if (os_memcmp(nt_response, rx_resp, 24) == 0) {
+	if (os_memcmp_const(nt_response, rx_resp, 24) == 0) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct "
 			   "NT-Response");
 		data->mschapv2_resp_ok = 1;

Modified: wpa/trunk/src/eap_server/ikev2.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eap_server/ikev2.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eap_server/ikev2.c	(original)
+++ wpa/trunk/src/eap_server/ikev2.c	Tue Oct 14 12:39:25 2014
@@ -633,7 +633,7 @@
 		return -1;
 
 	if (auth_len != prf->hash_len ||
-	    os_memcmp(auth, auth_data, auth_len) != 0) {
+	    os_memcmp_const(auth, auth_data, auth_len) != 0) {
 		wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data");
 		wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data",
 			    auth, auth_len);

Modified: wpa/trunk/src/eapol_supp/eapol_supp_sm.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eapol_supp/eapol_supp_sm.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eapol_supp/eapol_supp_sm.c	(original)
+++ wpa/trunk/src/eapol_supp/eapol_supp_sm.c	Tue Oct 14 12:39:25 2014
@@ -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;
@@ -719,8 +721,8 @@
 	hmac_md5(keydata.sign_key, sign_key_len,
 		 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
 		 key->key_signature);
-	if (os_memcmp(orig_key_sign, key->key_signature,
-		      IEEE8021X_KEY_SIGN_LEN) != 0) {
+	if (os_memcmp_const(orig_key_sign, key->key_signature,
+			    IEEE8021X_KEY_SIGN_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
 			   "EAPOL-Key packet");
 		os_memcpy(key->key_signature, orig_key_sign,
@@ -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 */
@@ -1523,7 +1526,7 @@
 	size_t eap_len;
 
 #ifdef CONFIG_EAP_PROXY
-	if (sm->use_eap_proxy) {
+	if (sm && sm->use_eap_proxy) {
 		/* Get key from EAP proxy */
 		if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) {
 			wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");

Modified: wpa/trunk/src/eapol_supp/eapol_supp_sm.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/eapol_supp/eapol_supp_sm.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/eapol_supp/eapol_supp_sm.h	(original)
+++ wpa/trunk/src/eapol_supp/eapol_supp_sm.h	Tue Oct 14 12:39:25 2014
@@ -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;

Modified: wpa/trunk/src/p2p/p2p.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/p2p/p2p.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/p2p/p2p.c	(original)
+++ wpa/trunk/src/p2p/p2p.c	Tue Oct 14 12:39:25 2014
@@ -12,6 +12,7 @@
 #include "eloop.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
+#include "common/wpa_ctrl.h"
 #include "wps/wps_i.h"
 #include "p2p_i.h"
 #include "p2p.h"
@@ -183,6 +184,14 @@
 	p2p_dbg(p2p, "State %s -> %s",
 		p2p_state_txt(p2p->state), p2p_state_txt(new_state));
 	p2p->state = new_state;
+
+	if (new_state == P2P_IDLE && p2p->pending_channel) {
+		p2p_dbg(p2p, "Apply change in listen channel");
+		p2p->cfg->reg_class = p2p->pending_reg_class;
+		p2p->cfg->channel = p2p->pending_channel;
+		p2p->pending_reg_class = 0;
+		p2p->pending_channel = 0;
+	}
 }
 
 
@@ -250,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)
@@ -600,6 +610,46 @@
 }
 
 
+static void p2p_update_peer_vendor_elems(struct p2p_device *dev, const u8 *ies,
+					 size_t ies_len)
+{
+	const u8 *pos, *end;
+	u8 id, len;
+
+	wpabuf_free(dev->info.vendor_elems);
+	dev->info.vendor_elems = NULL;
+
+	end = ies + ies_len;
+
+	for (pos = ies; pos + 1 < end; pos += len) {
+		id = *pos++;
+		len = *pos++;
+
+		if (pos + len > end)
+			break;
+
+		if (id != WLAN_EID_VENDOR_SPECIFIC || len < 3)
+			continue;
+
+		if (len >= 4) {
+			u32 type = WPA_GET_BE32(pos);
+
+			if (type == WPA_IE_VENDOR_TYPE ||
+			    type == WMM_IE_VENDOR_TYPE ||
+			    type == WPS_IE_VENDOR_TYPE ||
+			    type == P2P_IE_VENDOR_TYPE ||
+			    type == WFD_IE_VENDOR_TYPE)
+				continue;
+		}
+
+		/* Unknown vendor element - make raw IE data available */
+		if (wpabuf_resize(&dev->info.vendor_elems, 2 + len) < 0)
+			break;
+		wpabuf_put_data(dev->info.vendor_elems, pos - 2, 2 + len);
+	}
+}
+
+
 /**
  * p2p_add_device - Add peer entries based on scan results or P2P frames
  * @p2p: P2P module context from p2p_init()
@@ -748,6 +798,8 @@
 
 	p2p_parse_free(&msg);
 
+	p2p_update_peer_vendor_elems(dev, ies, ies_len);
+
 	if (dev->flags & P2P_DEV_REPORTED)
 		return 0;
 
@@ -817,6 +869,7 @@
 	}
 
 	wpabuf_free(dev->info.wfd_subelems);
+	wpabuf_free(dev->info.vendor_elems);
 	wpabuf_free(dev->go_neg_conf);
 
 	os_free(dev);
@@ -1234,8 +1287,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 */
@@ -1553,7 +1606,7 @@
 int p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params)
 {
 	p2p_build_ssid(p2p, params->ssid, &params->ssid_len);
-	p2p_random(params->passphrase, 8);
+	p2p_random(params->passphrase, p2p->cfg->passphrase_len);
 	return 0;
 }
 
@@ -1587,7 +1640,7 @@
 					       p2p->op_channel);
 		os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
 		res.ssid_len = p2p->ssid_len;
-		p2p_random(res.passphrase, 8);
+		p2p_random(res.passphrase, p2p->cfg->passphrase_len);
 	} else {
 		res.freq = peer->oper_freq;
 		if (p2p->ssid_len) {
@@ -1772,8 +1825,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);
 }
 
@@ -1783,6 +1845,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);
@@ -1949,6 +2015,9 @@
 		extra = wpabuf_len(p2p->wfd_ie_probe_resp);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P])
+		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P]);
+
 	buf = wpabuf_alloc(1000 + extra);
 	if (buf == NULL)
 		return NULL;
@@ -1968,6 +2037,10 @@
 	if (p2p->wfd_ie_probe_resp)
 		wpabuf_put_buf(buf, p2p->wfd_ie_probe_resp);
 #endif /* CONFIG_WIFI_DISPLAY */
+
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P])
+		wpabuf_put_buf(buf,
+			       p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P]);
 
 	/* P2P IE */
 	len = p2p_buf_add_ie_hdr(buf);
@@ -2244,6 +2317,9 @@
 		extra = wpabuf_len(p2p->wfd_ie_assoc_req);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ])
+		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ]);
+
 	/*
 	 * (Re)Association Request - P2P IE
 	 * P2P Capability attribute (shall be present)
@@ -2259,6 +2335,10 @@
 		wpabuf_put_buf(tmp, p2p->wfd_ie_assoc_req);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ])
+		wpabuf_put_buf(tmp,
+			       p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ]);
+
 	peer = bssid ? p2p_get_device(p2p, bssid) : NULL;
 
 	lpos = p2p_buf_add_ie_hdr(tmp);
@@ -2380,7 +2460,8 @@
 {
 	struct p2p_data *p2p;
 
-	if (cfg->max_peers < 1)
+	if (cfg->max_peers < 1 ||
+	    cfg->passphrase_len < 8 || cfg->passphrase_len > 63)
 		return NULL;
 
 	p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg));
@@ -2413,7 +2494,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;
@@ -2706,6 +2788,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);
@@ -2844,6 +2939,10 @@
 	if (p2p->wfd_ie_probe_req)
 		wpabuf_put_buf(ies, p2p->wfd_ie_probe_req);
 #endif /* CONFIG_WIFI_DISPLAY */
+
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P])
+		wpabuf_put_buf(ies,
+			       p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P]);
 
 	len = p2p_buf_add_ie_hdr(ies);
 	p2p_buf_add_capability(ies, p2p->dev_capab &
@@ -2870,6 +2969,10 @@
 	if (p2p && p2p->wfd_ie_probe_req)
 		len += wpabuf_len(p2p->wfd_ie_probe_req);
 #endif /* CONFIG_WIFI_DISPLAY */
+
+	if (p2p && p2p->vendor_elem &&
+	    p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P])
+		len += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P]);
 
 	return len;
 }
@@ -2928,7 +3031,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);
@@ -3991,17 +4095,47 @@
 }
 
 
-int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel)
+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)
 {
 	if (p2p_channel_to_freq(reg_class, channel) < 0)
 		return -1;
 
 	p2p_dbg(p2p, "Set Listen channel: reg_class %u channel %u",
 		reg_class, channel);
-	p2p->cfg->reg_class = reg_class;
-	p2p->cfg->channel = channel;
+
+	/*
+	 * Listen channel was set in configuration or set by control interface;
+	 * cannot override it.
+	 */
+	if (p2p->cfg->channel_forced && forced == 0)
+		return -1;
+
+	if (p2p->state == P2P_IDLE) {
+		p2p->cfg->reg_class = reg_class;
+		p2p->cfg->channel = channel;
+		p2p->cfg->channel_forced = forced;
+	} else {
+		p2p_dbg(p2p, "Defer setting listen channel");
+		p2p->pending_reg_class = reg_class;
+		p2p->pending_channel = channel;
+		p2p->pending_channel_forced = forced;
+	}
 
 	return 0;
+}
+
+
+u8 p2p_get_listen_channel(struct p2p_data *p2p)
+{
+	return p2p->cfg->channel;
 }
 
 
@@ -4462,6 +4596,19 @@
 }
 
 
+void p2p_loop_on_known_peers(struct p2p_data *p2p,
+			     void (*peer_callback)(struct p2p_peer_info *peer,
+						   void *user_data),
+			     void *user_data)
+{
+	struct p2p_device *dev, *n;
+
+	dl_list_for_each_safe(dev, n, &p2p->devices, struct p2p_device, list) {
+		peer_callback(&dev->info, user_data);
+	}
+}
+
+
 #ifdef CONFIG_WPS_NFC
 
 static struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p,
@@ -4688,3 +4835,18 @@
 }
 
 #endif /* CONFIG_WPS_NFC */
+
+
+int p2p_set_passphrase_len(struct p2p_data *p2p, unsigned int len)
+{
+	if (len < 8 || len > 63)
+		return -1;
+	p2p->cfg->passphrase_len = len;
+	return 0;
+}
+
+
+void p2p_set_vendor_elems(struct p2p_data *p2p, struct wpabuf **vendor_elem)
+{
+	p2p->vendor_elem = vendor_elem;
+}

Modified: wpa/trunk/src/p2p/p2p.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/p2p/p2p.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/p2p/p2p.h	(original)
+++ wpa/trunk/src/p2p/p2p.h	Tue Oct 14 12:39:25 2014
@@ -230,6 +230,14 @@
 	 * wfd_subelems - Wi-Fi Display subelements from WFD IE(s)
 	 */
 	struct wpabuf *wfd_subelems;
+
+	/**
+	 * vendor_elems - Unrecognized vendor elements
+	 *
+	 * This buffer includes any other vendor element than P2P, WPS, and WFD
+	 * IE(s) from the frame that was used to discover the peer.
+	 */
+	struct wpabuf *vendor_elems;
 };
 
 enum p2p_prov_disc_status {
@@ -265,6 +273,12 @@
 	 * channel - Own listen channel
 	 */
 	u8 channel;
+
+	/**
+	 * channel_forced - the listen channel was forced by configuration
+	 *                  or by control interface and cannot be overridden
+	 */
+	u8 channel_forced;
 
 	/**
 	 * Regulatory class for own operational channel
@@ -387,6 +401,14 @@
 	 * max_listen - Maximum listen duration in ms
 	 */
 	unsigned int max_listen;
+
+	/**
+	 * passphrase_len - Passphrase length (8..63)
+	 *
+	 * This parameter controls the length of the random passphrase that is
+	 * generated at the GO.
+	 */
+	unsigned int passphrase_len;
 
 	/**
 	 * cb_ctx - Context to use with callback functions
@@ -1669,7 +1691,24 @@
  */
 void p2p_set_managed_oper(struct p2p_data *p2p, int enabled);
 
-int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel);
+/**
+ * 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);
+
+u8 p2p_get_listen_channel(struct p2p_data *p2p);
 
 int p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len);
 
@@ -1771,7 +1810,7 @@
  * @group: P2P group context from p2p_group_init()
  * @next: iteration pointer, must be a pointer to a void * that is set to %NULL
  *	on the first call and not modified later
- * Returns: A P2P Interface Address for each call and %NULL for no more members
+ * Returns: A P2P Device Address for each call and %NULL for no more members
  */
 const u8 * p2p_iterate_group_members(struct p2p_group *group, void **next);
 
@@ -1791,6 +1830,26 @@
  * Returns: 1 if client is connected or 0 if not
  */
 int p2p_group_is_client_connected(struct p2p_group *group, const u8 *dev_addr);
+
+/**
+ * p2p_group_get_config - Get the group configuration
+ * @group: P2P group context from p2p_group_init()
+ * Returns: The group configuration pointer
+ */
+const struct p2p_group_config * p2p_group_get_config(struct p2p_group *group);
+
+/**
+ * p2p_loop_on_all_groups - Run the given callback on all groups
+ * @p2p: P2P module context from p2p_init()
+ * @group_callback: The callback function pointer
+ * @user_data: Some user data pointer which can be %NULL
+ *
+ * The group_callback function can stop the iteration by returning 0.
+ */
+void p2p_loop_on_all_groups(struct p2p_data *p2p,
+			    int (*group_callback)(struct p2p_group *group,
+						  void *user_data),
+			    void *user_data);
 
 /**
  * p2p_get_peer_found - Get P2P peer info structure of a found peer
@@ -1951,4 +2010,13 @@
 				      int go_intent,
 				      const u8 *own_interface_addr);
 
+int p2p_set_passphrase_len(struct p2p_data *p2p, unsigned int len);
+
+void p2p_loop_on_known_peers(struct p2p_data *p2p,
+			     void (*peer_callback)(struct p2p_peer_info *peer,
+						   void *user_data),
+			     void *user_data);
+
+void p2p_set_vendor_elems(struct p2p_data *p2p, struct wpabuf **vendor_elem);
+
 #endif /* P2P_H */

Modified: wpa/trunk/src/p2p/p2p_dev_disc.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/p2p/p2p_dev_disc.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/p2p/p2p_dev_disc.c	(original)
+++ wpa/trunk/src/p2p/p2p_dev_disc.c	Tue Oct 14 12:39:25 2014
@@ -68,6 +68,7 @@
 {
 	struct p2p_device *go;
 	struct wpabuf *req;
+	unsigned int wait_time;
 
 	go = p2p_get_device(p2p, dev->member_in_go_dev);
 	if (go == NULL || dev->oper_freq <= 0) {
@@ -88,9 +89,12 @@
 	os_memcpy(p2p->pending_client_disc_addr, dev->info.p2p_device_addr,
 		  ETH_ALEN);
 	p2p->pending_action_state = P2P_PENDING_DEV_DISC_REQUEST;
+	wait_time = 1000;
+	if (p2p->cfg->max_listen && wait_time > p2p->cfg->max_listen)
+		wait_time = p2p->cfg->max_listen;
 	if (p2p_send_action(p2p, dev->oper_freq, go->info.p2p_device_addr,
 			    p2p->cfg->dev_addr, go->info.p2p_device_addr,
-			    wpabuf_head(req), wpabuf_len(req), 1000) < 0) {
+			    wpabuf_head(req), wpabuf_len(req), wait_time) < 0) {
 		p2p_dbg(p2p, "Failed to send Action frame");
 		wpabuf_free(req);
 		/* TODO: how to recover from failure? */

Modified: wpa/trunk/src/p2p/p2p_go_neg.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/p2p/p2p_go_neg.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/p2p/p2p_go_neg.c	(original)
+++ wpa/trunk/src/p2p/p2p_go_neg.c	Tue Oct 14 12:39:25 2014
@@ -10,6 +10,7 @@
 
 #include "common.h"
 #include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
 #include "wps/wps_defs.h"
 #include "p2p_i.h"
 #include "p2p.h"
@@ -141,6 +142,9 @@
 	if (p2p->wfd_ie_go_neg)
 		extra = wpabuf_len(p2p->wfd_ie_go_neg);
 #endif /* CONFIG_WIFI_DISPLAY */
+
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ])
+		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ]);
 
 	buf = wpabuf_alloc(1000 + extra);
 	if (buf == NULL)
@@ -191,6 +195,9 @@
 		wpabuf_put_buf(buf, p2p->wfd_ie_go_neg);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ])
+		wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ]);
+
 	return buf;
 }
 
@@ -268,6 +275,9 @@
 		extra = wpabuf_len(p2p->wfd_ie_go_neg);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP])
+		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]);
+
 	buf = wpabuf_alloc(1000 + extra);
 	if (buf == NULL)
 		return NULL;
@@ -336,6 +346,8 @@
 		wpabuf_put_buf(buf, p2p->wfd_ie_go_neg);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP])
+		wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]);
 
 	return buf;
 }
@@ -844,6 +856,9 @@
 		extra = wpabuf_len(p2p->wfd_ie_go_neg);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF])
+		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]);
+
 	buf = wpabuf_alloc(1000 + extra);
 	if (buf == NULL)
 		return NULL;
@@ -888,6 +903,9 @@
 		wpabuf_put_buf(buf, p2p->wfd_ie_go_neg);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF])
+		wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]);
+
 	return buf;
 }
 
@@ -940,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");

Modified: wpa/trunk/src/p2p/p2p_group.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/p2p/p2p_group.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/p2p/p2p_group.c	(original)
+++ wpa/trunk/src/p2p/p2p_group.c	Tue Oct 14 12:39:25 2014
@@ -11,6 +11,7 @@
 #include "common.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
+#include "common/wpa_ctrl.h"
 #include "wps/wps_defs.h"
 #include "wps/wps_i.h"
 #include "p2p_i.h"
@@ -214,6 +215,10 @@
 		extra = wpabuf_len(group->p2p->wfd_ie_beacon);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	if (group->p2p->vendor_elem &&
+	    group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO])
+		extra += wpabuf_len(group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO]);
+
 	ie = wpabuf_alloc(257 + extra);
 	if (ie == NULL)
 		return NULL;
@@ -222,6 +227,11 @@
 	if (group->p2p->wfd_ie_beacon)
 		wpabuf_put_buf(ie, group->p2p->wfd_ie_beacon);
 #endif /* CONFIG_WIFI_DISPLAY */
+
+	if (group->p2p->vendor_elem &&
+	    group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO])
+		wpabuf_put_buf(ie,
+			       group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO]);
 
 	len = p2p_buf_add_ie_hdr(ie);
 	p2p_group_add_common_ies(group, ie);
@@ -448,6 +458,13 @@
 	ie = p2p_group_encaps_probe_resp(p2p_subelems);
 	wpabuf_free(p2p_subelems);
 
+	if (group->p2p->vendor_elem &&
+	    group->p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P_GO]) {
+		struct wpabuf *extra;
+		extra = wpabuf_dup(group->p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P_GO]);
+		ie = wpabuf_concat(extra, ie);
+	}
+
 #ifdef CONFIG_WIFI_DISPLAY
 	if (group->wfd_ie) {
 		struct wpabuf *wfd = wpabuf_dup(group->wfd_ie);
@@ -634,6 +651,10 @@
 		extra = wpabuf_len(group->wfd_ie);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	if (group->p2p->vendor_elem &&
+	    group->p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_RESP])
+		extra += wpabuf_len(group->p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_RESP]);
+
 	/*
 	 * (Re)Association Response - P2P IE
 	 * Status attribute (shall be present when association request is
@@ -648,6 +669,11 @@
 	if (group->wfd_ie)
 		wpabuf_put_buf(resp, group->wfd_ie);
 #endif /* CONFIG_WIFI_DISPLAY */
+
+	if (group->p2p->vendor_elem &&
+	    group->p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_RESP])
+		wpabuf_put_buf(resp,
+			       group->p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_RESP]);
 
 	rlen = p2p_buf_add_ie_hdr(resp);
 	if (status != P2P_SC_SUCCESS)
@@ -973,7 +999,7 @@
 	if (!iter)
 		return NULL;
 
-	return iter->addr;
+	return iter->dev_addr;
 }
 
 
@@ -1013,3 +1039,23 @@
 {
 	return group->cfg->freq;
 }
+
+
+const struct p2p_group_config * p2p_group_get_config(struct p2p_group *group)
+{
+	return group->cfg;
+}
+
+
+void p2p_loop_on_all_groups(struct p2p_data *p2p,
+			    int (*group_callback)(struct p2p_group *group,
+						  void *user_data),
+			    void *user_data)
+{
+	unsigned int i;
+
+	for (i = 0; i < p2p->num_groups; i++) {
+		if (!group_callback(p2p->groups[i], user_data))
+			break;
+	}
+}

Modified: wpa/trunk/src/p2p/p2p_i.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/p2p/p2p_i.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/p2p/p2p_i.h	(original)
+++ wpa/trunk/src/p2p/p2p_i.h	Tue Oct 14 12:39:25 2014
@@ -480,6 +480,10 @@
 	unsigned int search_delay;
 	int in_search_delay;
 
+	u8 pending_reg_class;
+	u8 pending_channel;
+	u8 pending_channel_forced;
+
 #ifdef CONFIG_WIFI_DISPLAY
 	struct wpabuf *wfd_ie_beacon;
 	struct wpabuf *wfd_ie_probe_req;
@@ -495,6 +499,8 @@
 #endif /* CONFIG_WIFI_DISPLAY */
 
 	u16 authorized_oob_dev_pw_id;
+
+	struct wpabuf **vendor_elem;
 };
 
 /**

Modified: wpa/trunk/src/p2p/p2p_invitation.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/p2p/p2p_invitation.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/p2p/p2p_invitation.c	(original)
+++ wpa/trunk/src/p2p/p2p_invitation.c	Tue Oct 14 12:39:25 2014
@@ -10,6 +10,7 @@
 
 #include "common.h"
 #include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
 #include "p2p_i.h"
 #include "p2p.h"
 
@@ -44,6 +45,9 @@
 	if (wfd_ie)
 		extra = wpabuf_len(wfd_ie);
 #endif /* CONFIG_WIFI_DISPLAY */
+
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ])
+		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ]);
 
 	buf = wpabuf_alloc(1000 + extra);
 	if (buf == NULL)
@@ -86,6 +90,9 @@
 		wpabuf_put_buf(buf, wfd_ie);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ])
+		wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ]);
+
 	if (dev_pw_id >= 0) {
 		/* WSC IE in Invitation Request for NFC static handover */
 		p2p_build_wps_ie(p2p, buf, dev_pw_id, 0);

Modified: wpa/trunk/src/p2p/p2p_pd.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/p2p/p2p_pd.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/p2p/p2p_pd.c	(original)
+++ wpa/trunk/src/p2p/p2p_pd.c	Tue Oct 14 12:39:25 2014
@@ -10,6 +10,7 @@
 
 #include "common.h"
 #include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
 #include "wps/wps_defs.h"
 #include "p2p_i.h"
 #include "p2p.h"
@@ -52,6 +53,9 @@
 	if (p2p->wfd_ie_prov_disc_req)
 		extra = wpabuf_len(p2p->wfd_ie_prov_disc_req);
 #endif /* CONFIG_WIFI_DISPLAY */
+
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
+		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
 
 	buf = wpabuf_alloc(1000 + extra);
 	if (buf == NULL)
@@ -76,6 +80,9 @@
 	if (p2p->wfd_ie_prov_disc_req)
 		wpabuf_put_buf(buf, p2p->wfd_ie_prov_disc_req);
 #endif /* CONFIG_WIFI_DISPLAY */
+
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
+		wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
 
 	return buf;
 }
@@ -111,6 +118,9 @@
 		extra = wpabuf_len(wfd_ie);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
+		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
+
 	buf = wpabuf_alloc(100 + extra);
 	if (buf == NULL)
 		return NULL;
@@ -124,6 +134,9 @@
 	if (wfd_ie)
 		wpabuf_put_buf(buf, wfd_ie);
 #endif /* CONFIG_WIFI_DISPLAY */
+
+	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
+		wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
 
 	return buf;
 }

Modified: wpa/trunk/src/p2p/p2p_sd.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/p2p/p2p_sd.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/p2p/p2p_sd.c	(original)
+++ wpa/trunk/src/p2p/p2p_sd.c	Tue Oct 14 12:39:25 2014
@@ -266,6 +266,7 @@
 	int ret = 0;
 	struct p2p_sd_query *query;
 	int freq;
+	unsigned int wait_time;
 
 	freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
 	if (freq <= 0) {
@@ -290,22 +291,15 @@
 	p2p->sd_query = query;
 	p2p->pending_action_state = P2P_PENDING_SD;
 
+	wait_time = 5000;
+	if (p2p->cfg->max_listen && wait_time > p2p->cfg->max_listen)
+		wait_time = p2p->cfg->max_listen;
 	if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
 			    p2p->cfg->dev_addr, dev->info.p2p_device_addr,
-			    wpabuf_head(req), wpabuf_len(req), 5000) < 0) {
+			    wpabuf_head(req), wpabuf_len(req), wait_time) < 0) {
 		p2p_dbg(p2p, "Failed to send Action frame");
 		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);
 

Modified: wpa/trunk/src/p2p/p2p_utils.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/p2p/p2p_utils.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/p2p/p2p_utils.c	(original)
+++ wpa/trunk/src/p2p/p2p_utils.c	Tue Oct 14 12:39:25 2014
@@ -146,6 +146,15 @@
 
 		*op_class = 124; /* 5 GHz, channels 149..161 */
 		*channel = (freq - 5000) / 5;
+		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;
 	}
 
@@ -388,17 +397,19 @@
 			       const struct p2p_channels *channels)
 {
 	unsigned int i;
-	int freq;
+	int freq = 0;
+	const struct p2p_channels *tmpc = channels ?
+		channels : &p2p->cfg->channels;
+
+	if (tmpc == NULL)
+		return 0;
 
 	for (i = 0; p2p->cfg->pref_chan && i < p2p->cfg->num_pref_chan; i++) {
 		freq = p2p_channel_to_freq(p2p->cfg->pref_chan[i].op_class,
 					   p2p->cfg->pref_chan[i].chan);
-		if (freq <= 0)
-			continue;
-		if (!channels || p2p_channels_includes_freq(channels, freq))
+		if (p2p_channels_includes_freq(tmpc, freq))
 			return freq;
 	}
-
 	return 0;
 }
 
@@ -439,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];
 }
@@ -479,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 */
@@ -490,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;
 }

Modified: wpa/trunk/src/pae/ieee802_1x_kay.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/pae/ieee802_1x_kay.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/pae/ieee802_1x_kay.c	(original)
+++ wpa/trunk/src/pae/ieee802_1x_kay.c	Tue Oct 14 12:39:25 2014
@@ -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);
@@ -2942,8 +2942,9 @@
 						 mka_msg_len);
 
 	if (msg_icv) {
-		if (os_memcmp(msg_icv, icv,
-			      mka_alg_tbl[kay->mka_algindex].icv_len) != 0) {
+		if (os_memcmp_const(msg_icv, icv,
+				    mka_alg_tbl[kay->mka_algindex].icv_len) !=
+		    0) {
 			wpa_printf(MSG_ERROR,
 				   "KaY: Computed ICV is not equal to Received ICV");
 		return -1;

Modified: wpa/trunk/src/radius/radius.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/radius/radius.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/radius/radius.c	(original)
+++ wpa/trunk/src/radius/radius.c	Tue Oct 14 12:39:25 2014
@@ -233,6 +233,17 @@
 	{ RADIUS_ATTR_NAS_IPV6_ADDRESS, "NAS-IPv6-Address", RADIUS_ATTR_IPV6 },
 	{ RADIUS_ATTR_ERROR_CAUSE, "Error-Cause", RADIUS_ATTR_INT32 },
 	{ RADIUS_ATTR_EAP_KEY_NAME, "EAP-Key-Name", RADIUS_ATTR_HEXDUMP },
+	{ RADIUS_ATTR_MOBILITY_DOMAIN_ID, "Mobility-Domain-Id",
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_WLAN_HESSID, "WLAN-HESSID", RADIUS_ATTR_TEXT },
+	{ RADIUS_ATTR_WLAN_PAIRWISE_CIPHER, "WLAN-Pairwise-Cipher",
+	  RADIUS_ATTR_HEXDUMP },
+	{ RADIUS_ATTR_WLAN_GROUP_CIPHER, "WLAN-Group-Cipher",
+	  RADIUS_ATTR_HEXDUMP },
+	{ RADIUS_ATTR_WLAN_AKM_SUITE, "WLAN-AKM-Suite",
+	  RADIUS_ATTR_HEXDUMP },
+	{ RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER, "WLAN-Group-Mgmt-Pairwise-Cipher",
+	  RADIUS_ATTR_HEXDUMP },
 };
 #define RADIUS_ATTRS ARRAY_SIZE(radius_attrs)
 
@@ -508,7 +519,7 @@
 	addr[3] = secret;
 	len[3] = secret_len;
 	md5_vector(4, addr, len, hash);
-	return os_memcmp(msg->hdr->authenticator, hash, MD5_MAC_LEN) != 0;
+	return os_memcmp_const(msg->hdr->authenticator, hash, MD5_MAC_LEN) != 0;
 }
 
 
@@ -535,7 +546,7 @@
 	addr[3] = secret;
 	len[3] = secret_len;
 	md5_vector(4, addr, len, hash);
-	if (os_memcmp(msg->hdr->authenticator, hash, MD5_MAC_LEN) != 0)
+	if (os_memcmp_const(msg->hdr->authenticator, hash, MD5_MAC_LEN) != 0)
 		return 1;
 
 	for (i = 0; i < msg->attr_used; i++) {
@@ -568,7 +579,7 @@
 	os_memcpy(msg->hdr->authenticator, orig_authenticator,
 		  sizeof(orig_authenticator));
 
-	return os_memcmp(orig, auth, MD5_MAC_LEN) != 0;
+	return os_memcmp_const(orig, auth, MD5_MAC_LEN) != 0;
 }
 
 
@@ -801,7 +812,7 @@
 			  sizeof(orig_authenticator));
 	}
 
-	if (os_memcmp(orig, auth, MD5_MAC_LEN) != 0) {
+	if (os_memcmp_const(orig, auth, MD5_MAC_LEN) != 0) {
 		wpa_printf(MSG_INFO, "Invalid Message-Authenticator!");
 		return 1;
 	}
@@ -838,7 +849,7 @@
 	addr[3] = secret;
 	len[3] = secret_len;
 	md5_vector(4, addr, len, hash);
-	if (os_memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) {
+	if (os_memcmp_const(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) {
 		wpa_printf(MSG_INFO, "Response Authenticator invalid!");
 		return 1;
 	}

Modified: wpa/trunk/src/radius/radius.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/radius/radius.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/radius/radius.h	(original)
+++ wpa/trunk/src/radius/radius.h	Tue Oct 14 12:39:25 2014
@@ -92,6 +92,12 @@
        RADIUS_ATTR_NAS_IPV6_ADDRESS = 95,
        RADIUS_ATTR_ERROR_CAUSE = 101,
        RADIUS_ATTR_EAP_KEY_NAME = 102,
+       RADIUS_ATTR_MOBILITY_DOMAIN_ID = 177,
+       RADIUS_ATTR_WLAN_HESSID = 181,
+       RADIUS_ATTR_WLAN_PAIRWISE_CIPHER = 186,
+       RADIUS_ATTR_WLAN_GROUP_CIPHER = 187,
+       RADIUS_ATTR_WLAN_AKM_SUITE = 188,
+       RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER = 189,
 };
 
 

Modified: wpa/trunk/src/radius/radius_client.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/radius/radius_client.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/radius/radius_client.c	(original)
+++ wpa/trunk/src/radius/radius_client.c	Tue Oct 14 12:39:25 2014
@@ -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 */

Modified: wpa/trunk/src/radius/radius_server.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/radius/radius_server.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/radius/radius_server.c	(original)
+++ wpa/trunk/src/radius/radius_server.c	Tue Oct 14 12:39:25 2014
@@ -623,7 +623,7 @@
 
 	os_memset(&tmp, 0, sizeof(tmp));
 	res = data->get_eap_user(data->conf_ctx, user, user_len, 0, &tmp);
-	os_free(tmp.password);
+	bin_clear_free(tmp.password, tmp.password_len);
 
 	if (res != 0) {
 		RADIUS_DEBUG("User-Name not found from user database");
@@ -852,7 +852,7 @@
 					 os_strlen(sess->username), 0, &tmp);
 		if (res || !tmp.macacl || tmp.password == NULL) {
 			RADIUS_DEBUG("No MAC ACL user entry");
-			os_free(tmp.password);
+			bin_clear_free(tmp.password, tmp.password_len);
 			code = RADIUS_CODE_ACCESS_REJECT;
 		} else {
 			u8 buf[128];
@@ -861,10 +861,10 @@
 				(u8 *) client->shared_secret,
 				client->shared_secret_len,
 				buf, sizeof(buf));
-			os_free(tmp.password);
+			bin_clear_free(tmp.password, tmp.password_len);
 
 			if (res < 0 || pw_len != (size_t) res ||
-			    os_memcmp(pw, buf, res) != 0) {
+			    os_memcmp_const(pw, buf, res) != 0) {
 				RADIUS_DEBUG("Incorrect User-Password");
 				code = RADIUS_CODE_ACCESS_REJECT;
 			}
@@ -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;

Modified: wpa/trunk/src/rsn_supp/peerkey.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/rsn_supp/peerkey.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/rsn_supp/peerkey.c	(original)
+++ wpa/trunk/src/rsn_supp/peerkey.c	Tue Oct 14 12:39:25 2014
@@ -653,11 +653,11 @@
 static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm,
 					      struct wpa_peerkey *peerkey,
 					      const struct wpa_eapol_key *key,
-					      u16 ver)
+					      u16 ver, const u8 *key_data,
+					      size_t key_data_len)
 {
 	struct wpa_eapol_ie_parse ie;
-	const u8 *kde;
-	size_t len, kde_buf_len;
+	size_t kde_buf_len;
 	struct wpa_ptk *stk;
 	u8 buf[8], *kde_buf, *pos;
 	be32 lifetime;
@@ -668,14 +668,13 @@
 	os_memset(&ie, 0, sizeof(ie));
 
 	/* RSN: msg 1/4 should contain SMKID for the selected SMK */
-	kde = (const u8 *) (key + 1);
-	len = WPA_GET_BE16(key->key_data_length);
-	wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", kde, len);
-	if (wpa_supplicant_parse_ies(kde, len, &ie) < 0 || ie.pmkid == NULL) {
+	wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", key_data, key_data_len);
+	if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0 ||
+	    ie.pmkid == NULL) {
 		wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4");
 		return;
 	}
-	if (os_memcmp(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
+	if (os_memcmp_const(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
 		wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4",
 			    ie.pmkid, PMKID_LEN);
 		return;
@@ -760,11 +759,10 @@
 static void wpa_supplicant_process_stk_2_of_4(struct wpa_sm *sm,
 					      struct wpa_peerkey *peerkey,
 					      const struct wpa_eapol_key *key,
-					      u16 ver)
+					      u16 ver, const u8 *key_data,
+					      size_t key_data_len)
 {
 	struct wpa_eapol_ie_parse kde;
-	const u8 *keydata;
-	size_t len;
 
 	wpa_printf(MSG_DEBUG, "RSN: RX message 2 of STK 4-Way Handshake from "
 		   MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
@@ -773,16 +771,14 @@
 
 	/* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE
 	 * from the peer. It may also include Lifetime KDE. */
-	keydata = (const u8 *) (key + 1);
-	len = WPA_GET_BE16(key->key_data_length);
-	wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", keydata, len);
-	if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0 ||
+	wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", key_data, key_data_len);
+	if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0 ||
 	    kde.pmkid == NULL || kde.rsn_ie == NULL) {
 		wpa_printf(MSG_DEBUG, "RSN: No SMKID or RSN IE in STK 2/4");
 		return;
 	}
 
-	if (os_memcmp(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
+	if (os_memcmp_const(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
 		wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 2/4",
 			    kde.pmkid, PMKID_LEN);
 		return;
@@ -809,11 +805,11 @@
 static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm,
 					      struct wpa_peerkey *peerkey,
 					      const struct wpa_eapol_key *key,
-					      u16 ver)
+					      u16 ver, const u8 *key_data,
+					      size_t key_data_len)
 {
 	struct wpa_eapol_ie_parse kde;
-	const u8 *keydata;
-	size_t len, key_len;
+	size_t key_len;
 	const u8 *_key;
 	u8 key_buf[32], rsc[6];
 
@@ -824,10 +820,8 @@
 
 	/* RSN: msg 3/4 should contain Initiator RSN IE. It may also include
 	 * Lifetime KDE. */
-	keydata = (const u8 *) (key + 1);
-	len = WPA_GET_BE16(key->key_data_length);
-	wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", keydata, len);
-	if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0) {
+	wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", key_data, key_data_len);
+	if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0) {
 		wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in "
 			   "STK 3/4");
 		return;
@@ -935,7 +929,7 @@
 		os_memset(key->key_mic, 0, 16);
 		wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len,
 				  key->key_mic);
-		if (os_memcmp(mic, key->key_mic, 16) != 0) {
+		if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
 			wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
 				   "when using TSTK - ignoring TSTK");
 		} else {
@@ -951,7 +945,7 @@
 		os_memset(key->key_mic, 0, 16);
 		wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len,
 				  key->key_mic);
-		if (os_memcmp(mic, key->key_mic, 16) != 0) {
+		if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
 			wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
 				   "- dropping packet");
 			return -1;
@@ -1117,21 +1111,25 @@
 
 
 void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey,
-			   struct wpa_eapol_key *key, u16 key_info, u16 ver)
+			   struct wpa_eapol_key *key, u16 key_info, u16 ver,
+			   const u8 *key_data, size_t key_data_len)
 {
 	if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) ==
 	    (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) {
 		/* 3/4 STK 4-Way Handshake */
-		wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver);
+		wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver,
+						  key_data, key_data_len);
 	} else if (key_info & WPA_KEY_INFO_ACK) {
 		/* 1/4 STK 4-Way Handshake */
-		wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver);
+		wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver,
+						  key_data, key_data_len);
 	} else if (key_info & WPA_KEY_INFO_SECURE) {
 		/* 4/4 STK 4-Way Handshake */
 		wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver);
 	} else {
 		/* 2/4 STK 4-Way Handshake */
-		wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver);
+		wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver,
+						  key_data, key_data_len);
 	}
 }
 

Modified: wpa/trunk/src/rsn_supp/peerkey.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/rsn_supp/peerkey.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/rsn_supp/peerkey.h	(original)
+++ wpa/trunk/src/rsn_supp/peerkey.h	Tue Oct 14 12:39:25 2014
@@ -41,7 +41,8 @@
 				 struct wpa_eapol_key *key, u16 ver,
 				 const u8 *buf, size_t len);
 void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey,
-			   struct wpa_eapol_key *key, u16 key_info, u16 ver);
+			   struct wpa_eapol_key *key, u16 key_info, u16 ver,
+			   const u8 *key_data, size_t key_data_len);
 void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr,
 			  struct wpa_eapol_key *key, size_t extra_len,
 			  u16 key_info, u16 ver);
@@ -60,7 +61,8 @@
 
 static inline void
 peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey,
-		      struct wpa_eapol_key *key, u16 key_info, u16 ver)
+		      struct wpa_eapol_key *key, u16 key_info, u16 ver,
+		      const u8 *key_data, size_t key_data_len)
 {
 }
 

Modified: wpa/trunk/src/rsn_supp/pmksa_cache.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/rsn_supp/pmksa_cache.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/rsn_supp/pmksa_cache.c	(original)
+++ wpa/trunk/src/rsn_supp/pmksa_cache.c	Tue Oct 14 12:39:25 2014
@@ -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));
 }
 
 
@@ -152,9 +152,9 @@
 	while (pos) {
 		if (os_memcmp(aa, pos->aa, ETH_ALEN) == 0) {
 			if (pos->pmk_len == pmk_len &&
-			    os_memcmp(pos->pmk, pmk, pmk_len) == 0 &&
-			    os_memcmp(pos->pmkid, entry->pmkid, PMKID_LEN) ==
-			    0) {
+			    os_memcmp_const(pos->pmk, pmk, pmk_len) == 0 &&
+			    os_memcmp_const(pos->pmkid, entry->pmkid,
+					    PMKID_LEN) == 0) {
 				wpa_printf(MSG_DEBUG, "WPA: reusing previous "
 					   "PMKSA entry");
 				os_free(entry);

Modified: wpa/trunk/src/rsn_supp/tdls.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/rsn_supp/tdls.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/rsn_supp/tdls.c	(original)
+++ wpa/trunk/src/rsn_supp/tdls.c	Tue Oct 14 12:39:25 2014
@@ -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 "
@@ -564,7 +568,7 @@
 		wpa_tdls_ftie_mic(peer->tpk.kck, trans_seq, lnkid,
 				  peer->rsnie_p, timeoutie, (u8 *) ftie,
 				  mic);
-		if (os_memcmp(mic, ftie->mic, 16) != 0) {
+		if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
 			wpa_printf(MSG_INFO, "TDLS: Invalid MIC in FTIE - "
 				   "dropping packet");
 			wpa_hexdump(MSG_DEBUG, "TDLS: Received MIC",
@@ -591,7 +595,7 @@
 	if (peer->tpk_set) {
 		wpa_tdls_key_mic_teardown(peer->tpk.kck, trans_seq, rcode,
 					  dtoken, lnkid, (u8 *) ftie, mic);
-		if (os_memcmp(mic, ftie->mic, 16) != 0) {
+		if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
 			wpa_printf(MSG_INFO, "TDLS: Invalid MIC in Teardown - "
 				   "dropping packet");
 			return -1;
@@ -631,7 +635,33 @@
 }
 
 
-static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
+static void wpa_tdls_peer_remove_from_list(struct wpa_sm *sm,
+					   struct wpa_tdls_peer *peer)
+{
+	struct wpa_tdls_peer *cur, *prev;
+
+	cur = sm->tdls;
+	prev = NULL;
+	while (cur && cur != peer) {
+		prev = cur;
+		cur = cur->next;
+	}
+
+	if (cur != peer) {
+		wpa_printf(MSG_ERROR, "TDLS: Could not find peer " MACSTR
+			   " to remove it from the list",
+			   MAC2STR(peer->addr));
+		return;
+	}
+
+	if (prev)
+		prev->next = peer->next;
+	else
+		sm->tdls = peer->next;
+}
+
+
+static void wpa_tdls_peer_clear(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 {
 	wpa_printf(MSG_DEBUG, "TDLS: Clear state for peer " MACSTR,
 		   MAC2STR(peer->addr));
@@ -663,6 +693,14 @@
 }
 
 
+static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
+{
+	wpa_tdls_peer_clear(sm, peer);
+	wpa_tdls_peer_remove_from_list(sm, peer);
+	os_free(peer);
+}
+
+
 static void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
 			    struct wpa_tdls_lnkid *lnkid)
 {
@@ -759,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;
@@ -802,7 +840,7 @@
 }
 
 
-void wpa_tdls_disable_link(struct wpa_sm *sm, const u8 *addr)
+void wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr)
 {
 	struct wpa_tdls_peer *peer;
 
@@ -811,8 +849,25 @@
 			break;
 	}
 
-	if (peer)
+	if (!peer || !peer->tpk_success) {
+		wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
+			   " not connected - cannot teardown unreachable link",
+			   MAC2STR(addr));
+		return;
+	}
+
+	if (wpa_tdls_is_external_setup(sm)) {
+		/*
+		 * Disable the link, send a teardown packet through the
+		 * AP, and then reset link data.
+		 */
+		wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, addr);
+		wpa_tdls_send_teardown(sm, addr,
+				       WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE);
+		wpa_tdls_peer_free(sm, peer);
+	} else {
 		wpa_tdls_disable_peer_link(sm, peer);
+	}
 }
 
 
@@ -917,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);
 }
 
 
@@ -1133,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;
@@ -1223,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;
@@ -1320,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;
@@ -1331,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));
-
-	return wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
-				 dialog_token, 0, 0, NULL, 0);
+	if (!wpa_tdls_get_privacy(sm))
+		goto skip_rsn_ies;
+
+	/* 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;
 }
 
 
@@ -1361,10 +1494,17 @@
 
 	dialog_token = buf[sizeof(struct wpa_tdls_frame)];
 
+	/*
+	 * Some APs will tack on a weird IE to the end of a TDLS
+	 * discovery request packet. This needn't fail the response,
+	 * since the required IE are verified separately.
+	 */
 	if (wpa_supplicant_parse_ies(buf + sizeof(struct wpa_tdls_frame) + 1,
 				     len - (sizeof(struct wpa_tdls_frame) + 1),
-				     &kde) < 0)
-		return -1;
+				     &kde) < 0) {
+		wpa_printf(MSG_DEBUG,
+			   "TDLS: Failed to parse IEs in Discovery Request - ignore as an interop workaround");
+	}
 
 	if (!kde.lnkid) {
 		wpa_printf(MSG_DEBUG, "TDLS: Link ID not found in Discovery "
@@ -1396,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);
 }
 
 
@@ -1570,6 +1710,23 @@
 		    (u8 *) peer->supp_oper_classes,
 		    peer->supp_oper_classes_len);
 	return 0;
+}
+
+
+static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
+				int add)
+{
+	return wpa_sm_tdls_peer_addset(sm, peer->addr, add, peer->aid,
+				       peer->capability,
+				       peer->supp_rates, peer->supp_rates_len,
+				       peer->ht_capabilities,
+				       peer->vht_capabilities,
+				       peer->qos_info, peer->wmm_capable,
+				       peer->ext_capab, peer->ext_capab_len,
+				       peer->supp_channels,
+				       peer->supp_channels_len,
+				       peer->supp_oper_classes,
+				       peer->supp_oper_classes_len);
 }
 
 
@@ -1620,16 +1777,16 @@
 			wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while "
 				   "direct link is enabled - tear down the "
 				   "old link first");
-			wpa_tdls_disable_peer_link(sm, peer);
-		}
-
-		/*
-		 * An entry is already present, so check if we already sent a
-		 * TDLS Setup Request. If so, compare MAC addresses and let the
-		 * STA with the lower MAC address continue as the initiator.
-		 * The other negotiation is terminated.
-		 */
-		if (peer->initiator) {
+			wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
+			wpa_tdls_peer_clear(sm, peer);
+		} else if (peer->initiator) {
+			/*
+			 * An entry is already present, so check if we already
+			 * sent a TDLS Setup Request. If so, compare MAC
+			 * addresses and let the STA with the lower MAC address
+			 * continue as the initiator. The other negotiation is
+			 * terminated.
+			 */
 			if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) {
 				wpa_printf(MSG_DEBUG, "TDLS: Discard request "
 					   "from peer with higher address "
@@ -1641,7 +1798,9 @@
 					   MACSTR " (terminate previously "
 					   "initiated negotiation",
 					   MAC2STR(src_addr));
-				wpa_tdls_disable_peer_link(sm, peer);
+				wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK,
+						 peer->addr);
+				wpa_tdls_peer_clear(sm, peer);
 			}
 		}
 	}
@@ -1666,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;
 	}
 
@@ -1707,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);
 	}
 
@@ -1831,7 +1992,6 @@
 		if (os_get_random(peer->rnonce, WPA_NONCE_LEN)) {
 			wpa_msg(sm->ctx->ctx, MSG_WARNING,
 				"TDLS: Failed to get random data for responder nonce");
-			wpa_tdls_peer_free(sm, peer);
 			goto error;
 		}
 	}
@@ -1886,22 +2046,33 @@
 	wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
 
 skip_rsn_check:
-	/* add the peer to the driver as a "setup in progress" peer */
-	wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
-				NULL, 0, NULL, 0, NULL, 0);
+#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");
 	if (wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer) < 0) {
-		wpa_tdls_disable_peer_link(sm, peer);
+		wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
 		goto error;
 	}
 
 	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);
 	return -1;
 }
 
@@ -1930,20 +2101,6 @@
 #endif /* CONFIG_TDLS_TESTING */
 	}
 
-	/* add supported rates, capabilities, and qos_info to the TDLS peer */
-	if (wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->aid,
-				    peer->capability,
-				    peer->supp_rates, peer->supp_rates_len,
-				    peer->ht_capabilities,
-				    peer->vht_capabilities,
-				    peer->qos_info, peer->ext_capab,
-				    peer->ext_capab_len,
-				    peer->supp_channels,
-				    peer->supp_channels_len,
-				    peer->supp_oper_classes,
-				    peer->supp_oper_classes_len) < 0)
-		return -1;
-
 	if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) {
 		wpa_printf(MSG_INFO, "TDLS: Could not configure key to the "
 			   "driver");
@@ -2097,6 +2254,13 @@
 	}
 	wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
 		    kde.rsn_ie, kde.rsn_ie_len);
+
+	if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) {
+		wpa_printf(MSG_INFO,
+			   "TDLS: Too long Responder RSN IE in TPK M2");
+		status = WLAN_STATUS_INVALID_RSNIE;
+		goto error;
+	}
 
 	/*
 	 * FIX: bitwise comparison of RSN IE is not the correct way of
@@ -2190,12 +2354,14 @@
 skip_rsn:
 	peer->dtoken = dtoken;
 
+	/* add supported rates, capabilities, and qos_info to the TDLS peer */
+	if (wpa_tdls_addset_peer(sm, peer, 0) < 0)
+		goto error;
+
 	wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / "
 		   "TPK Handshake Message 3");
-	if (wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer) < 0) {
-		wpa_tdls_disable_peer_link(sm, peer);
-		return -1;
-	}
+	if (wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer) < 0)
+		goto error;
 
 	if (!peer->tpk_success) {
 		/*
@@ -2214,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;
@@ -2263,9 +2429,16 @@
 	pos += 2 /* status code */ + 1 /* dialog token */;
 
 	ielen = len - (pos - buf); /* start of IE in buf */
+
+	/*
+	 * Don't reject the message if failing to parse IEs. The IEs we need are
+	 * explicitly checked below. Some APs piggy-back broken IEs to the end
+	 * of a TDLS Confirm packet, which will fail the link if we don't ignore
+	 * this error.
+	 */
 	if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) {
-		wpa_printf(MSG_INFO, "TDLS: Failed to parse KDEs in TPK M3");
-		goto error;
+		wpa_printf(MSG_DEBUG,
+			   "TDLS: Failed to parse KDEs in TPK M3 - ignore as an interop workaround");
 	}
 
 	if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
@@ -2350,6 +2523,10 @@
 	}
 
 skip_rsn:
+	/* add supported rates, capabilities, and qos_info to the TDLS peer */
+	if (wpa_tdls_addset_peer(sm, peer, 0) < 0)
+		goto error;
+
 	if (!peer->tpk_success) {
 		/*
 		 * Enable Link only when tpk_success is 0, signifying that this
@@ -2359,14 +2536,12 @@
 		ret = wpa_tdls_enable_link(sm, peer);
 		if (ret < 0) {
 			wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
-			wpa_tdls_do_teardown(
-				sm, peer,
-				WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
+			goto error;
 		}
 	}
 	return ret;
 error:
-	wpa_tdls_disable_peer_link(sm, peer);
+	wpa_tdls_do_teardown(sm, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
 	return -1;
 }
 
@@ -2429,8 +2604,11 @@
 	peer->initiator = 1;
 
 	/* add the peer to the driver as a "setup in progress" peer */
-	wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
-				NULL, 0, NULL, 0, NULL, 0);
+	if (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_disable_peer_link(sm, peer);
+		return -1;
+	}
 
 	peer->tpk_in_progress = 1;
 
@@ -2580,13 +2758,14 @@
 
 void wpa_tdls_teardown_peers(struct wpa_sm *sm)
 {
-	struct wpa_tdls_peer *peer;
+	struct wpa_tdls_peer *peer, *tmp;
 
 	peer = sm->tdls;
 
 	wpa_printf(MSG_DEBUG, "TDLS: Tear down peers");
 
 	while (peer) {
+		tmp = peer->next;
 		wpa_printf(MSG_DEBUG, "TDLS: Tear down peer " MACSTR,
 			   MAC2STR(peer->addr));
 		if (sm->tdls_external_setup)
@@ -2595,7 +2774,7 @@
 		else
 			wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
 
-		peer = peer->next;
+		peer = tmp;
 	}
 }
 
@@ -2605,7 +2784,6 @@
 	struct wpa_tdls_peer *peer, *tmp;
 
 	peer = sm->tdls;
-	sm->tdls = NULL;
 
 	while (peer) {
 		int res;
@@ -2614,7 +2792,6 @@
 		wpa_printf(MSG_DEBUG, "TDLS: Remove peer " MACSTR " (res=%d)",
 			   MAC2STR(peer->addr), res);
 		wpa_tdls_peer_free(sm, peer);
-		os_free(peer);
 		peer = tmp;
 	}
 }

Modified: wpa/trunk/src/rsn_supp/wpa.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/rsn_supp/wpa.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/rsn_supp/wpa.c	(original)
+++ wpa/trunk/src/rsn_supp/wpa.c	Tue Oct 14 12:39:25 2014
@@ -162,7 +162,7 @@
 	}
 
 	if (pmkid && sm->cur_pmksa &&
-	    os_memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
+	    os_memcmp_const(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
 		wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN);
 		wpa_sm_set_pmk_from_pmksa(sm);
 		wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache",
@@ -379,7 +379,8 @@
 static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
 					  const unsigned char *src_addr,
 					  const struct wpa_eapol_key *key,
-					  u16 ver)
+					  u16 ver, const u8 *key_data,
+					  size_t key_data_len)
 {
 	struct wpa_eapol_ie_parse ie;
 	struct wpa_ptk *ptk;
@@ -401,10 +402,9 @@
 
 	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
 		/* RSN: msg 1/4 should contain PMKID for the selected PMK */
-		const u8 *_buf = (const u8 *) (key + 1);
-		size_t len = WPA_GET_BE16(key->key_data_length);
-		wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", _buf, len);
-		if (wpa_supplicant_parse_ies(_buf, len, &ie) < 0)
+		wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data",
+			    key_data, key_data_len);
+		if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
 			goto failed;
 		if (ie.pmkid) {
 			wpa_hexdump(MSG_DEBUG, "RSN: PMKID from "
@@ -906,7 +906,8 @@
 		return -1;
 	}
 
-	if (os_memcmp(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) {
+	if (os_memcmp_const(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0)
+	{
 		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
 			"FT: PMKR1Name mismatch in "
 			"FT 4-way handshake message 3/4");
@@ -1068,10 +1069,10 @@
 
 static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
 					  const struct wpa_eapol_key *key,
-					  u16 ver)
-{
-	u16 key_info, keylen, len;
-	const u8 *pos;
+					  u16 ver, const u8 *key_data,
+					  size_t key_data_len)
+{
+	u16 key_info, keylen;
 	struct wpa_eapol_ie_parse ie;
 
 	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
@@ -1080,10 +1081,8 @@
 
 	key_info = WPA_GET_BE16(key->key_info);
 
-	pos = (const u8 *) (key + 1);
-	len = WPA_GET_BE16(key->key_data_length);
-	wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len);
-	if (wpa_supplicant_parse_ies(pos, len, &ie) < 0)
+	wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len);
+	if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
 		goto failed;
 	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
@@ -1238,21 +1237,14 @@
 
 static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
 					     const struct wpa_eapol_key *key,
-					     size_t keydatalen, int key_info,
-					     size_t extra_len, u16 ver,
-					     struct wpa_gtk_data *gd)
+					     const u8 *key_data,
+					     size_t key_data_len, u16 key_info,
+					     u16 ver, struct wpa_gtk_data *gd)
 {
 	size_t maxkeylen;
 
 	gd->gtk_len = WPA_GET_BE16(key->key_length);
-	maxkeylen = keydatalen;
-	if (keydatalen > extra_len) {
-		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
-			"WPA: Truncated EAPOL-Key packet: "
-			"key_data_length=%lu > extra_len=%lu",
-			(unsigned long) keydatalen, (unsigned long) extra_len);
-		return -1;
-	}
+	maxkeylen = key_data_len;
 	if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
 		if (maxkeylen < 8) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
@@ -1272,16 +1264,16 @@
 		WPA_KEY_INFO_KEY_INDEX_SHIFT;
 	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
 		u8 ek[32];
-		if (keydatalen > sizeof(gd->gtk)) {
+		if (key_data_len > sizeof(gd->gtk)) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: RC4 key data too long (%lu)",
-				(unsigned long) keydatalen);
+				(unsigned long) key_data_len);
 			return -1;
 		}
 		os_memcpy(ek, key->key_iv, 16);
 		os_memcpy(ek + 16, sm->ptk.kek, 16);
-		os_memcpy(gd->gtk, key + 1, keydatalen);
-		if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) {
+		os_memcpy(gd->gtk, key_data, key_data_len);
+		if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) {
 			os_memset(ek, 0, sizeof(ek));
 			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
 				"WPA: RC4 failed");
@@ -1289,22 +1281,22 @@
 		}
 		os_memset(ek, 0, sizeof(ek));
 	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
-		if (keydatalen % 8) {
+		if (maxkeylen % 8) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: Unsupported AES-WRAP len %lu",
-				(unsigned long) keydatalen);
+				(unsigned long) maxkeylen);
 			return -1;
 		}
 		if (maxkeylen > sizeof(gd->gtk)) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: AES-WRAP key data "
 				"too long (keydatalen=%lu maxkeylen=%lu)",
-				(unsigned long) keydatalen,
+				(unsigned long) key_data_len,
 				(unsigned long) maxkeylen);
 			return -1;
 		}
-		if (aes_unwrap(sm->ptk.kek, maxkeylen / 8,
-			       (const u8 *) (key + 1), 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");
@@ -1360,9 +1352,10 @@
 static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
 					  const unsigned char *src_addr,
 					  const struct wpa_eapol_key *key,
-					  int extra_len, u16 ver)
-{
-	u16 key_info, keydatalen;
+					  const u8 *key_data,
+					  size_t key_data_len, u16 ver)
+{
+	u16 key_info;
 	int rekey, ret;
 	struct wpa_gtk_data gd;
 
@@ -1373,17 +1366,15 @@
 		"Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
 
 	key_info = WPA_GET_BE16(key->key_info);
-	keydatalen = WPA_GET_BE16(key->key_data_length);
 
 	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
-		ret = wpa_supplicant_process_1_of_2_rsn(sm,
-							(const u8 *) (key + 1),
-							keydatalen, key_info,
+		ret = wpa_supplicant_process_1_of_2_rsn(sm, key_data,
+							key_data_len, key_info,
 							&gd);
 	} else {
-		ret = wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen,
-							key_info, extra_len,
-							ver, &gd);
+		ret = wpa_supplicant_process_1_of_2_wpa(sm, key, key_data,
+							key_data_len,
+							key_info, ver, &gd);
 	}
 
 	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
@@ -1429,7 +1420,7 @@
 		os_memset(key->key_mic, 0, 16);
 		wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len,
 				  key->key_mic);
-		if (os_memcmp(mic, key->key_mic, 16) != 0) {
+		if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: Invalid EAPOL-Key MIC "
 				"when using TPTK - ignoring TPTK");
@@ -1446,7 +1437,7 @@
 		os_memset(key->key_mic, 0, 16);
 		wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len,
 				  key->key_mic);
-		if (os_memcmp(mic, key->key_mic, 16) != 0) {
+		if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: Invalid EAPOL-Key MIC - "
 				"dropping packet");
@@ -1471,12 +1462,11 @@
 
 /* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
 static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
-					   struct wpa_eapol_key *key, u16 ver)
-{
-	u16 keydatalen = WPA_GET_BE16(key->key_data_length);
-
+					   struct wpa_eapol_key *key, u16 ver,
+					   u8 *key_data, size_t *key_data_len)
+{
 	wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",
-		    (u8 *) (key + 1), keydatalen);
+		    key_data, *key_data_len);
 	if (!sm->ptk_set) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"WPA: PTK not available, cannot decrypt EAPOL-Key Key "
@@ -1490,7 +1480,7 @@
 		u8 ek[32];
 		os_memcpy(ek, key->key_iv, 16);
 		os_memcpy(ek + 16, sm->ptk.kek, 16);
-		if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) {
+		if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) {
 			os_memset(ek, 0, sizeof(ek));
 			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
 				"WPA: RC4 failed");
@@ -1501,37 +1491,37 @@
 		   ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
 		   sm->key_mgmt == WPA_KEY_MGMT_OSEN) {
 		u8 *buf;
-		if (keydatalen % 8) {
+		if (*key_data_len < 8 || *key_data_len % 8) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
-				"WPA: Unsupported AES-WRAP len %d",
-				keydatalen);
+				"WPA: Unsupported AES-WRAP len %u",
+				(unsigned int) *key_data_len);
 			return -1;
 		}
-		keydatalen -= 8; /* AES-WRAP adds 8 bytes */
-		buf = os_malloc(keydatalen);
+		*key_data_len -= 8; /* AES-WRAP adds 8 bytes */
+		buf = os_malloc(*key_data_len);
 		if (buf == NULL) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: No memory for AES-UNWRAP buffer");
 			return -1;
 		}
-		if (aes_unwrap(sm->ptk.kek, keydatalen / 8,
-			       (u8 *) (key + 1), buf)) {
+		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,
 				"WPA: AES unwrap failed - "
 				"could not decrypt EAPOL-Key key data");
 			return -1;
 		}
-		os_memcpy(key + 1, buf, keydatalen);
+		os_memcpy(key_data, buf, *key_data_len);
 		os_free(buf);
-		WPA_PUT_BE16(key->key_data_length, keydatalen);
+		WPA_PUT_BE16(key->key_data_length, *key_data_len);
 	} else {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"WPA: Unsupported key_info type %d", ver);
 		return -1;
 	}
 	wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data",
-			(u8 *) (key + 1), keydatalen);
+			key_data, *key_data_len);
 	return 0;
 }
 
@@ -1605,13 +1595,14 @@
 int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
 		    const u8 *buf, size_t len)
 {
-	size_t plen, data_len, extra_len;
-	struct ieee802_1x_hdr *hdr;
+	size_t plen, data_len, key_data_len;
+	const struct ieee802_1x_hdr *hdr;
 	struct wpa_eapol_key *key;
 	u16 key_info, ver;
-	u8 *tmp;
+	u8 *tmp = NULL;
 	int ret = -1;
 	struct wpa_peerkey *peerkey = NULL;
+	u8 *key_data;
 
 #ifdef CONFIG_IEEE80211R
 	sm->ft_completed = 0;
@@ -1626,13 +1617,7 @@
 		return 0;
 	}
 
-	tmp = os_malloc(len);
-	if (tmp == NULL)
-		return -1;
-	os_memcpy(tmp, buf, len);
-
-	hdr = (struct ieee802_1x_hdr *) tmp;
-	key = (struct wpa_eapol_key *) (hdr + 1);
+	hdr = (const struct ieee802_1x_hdr *) buf;
 	plen = be_to_host16(hdr->length);
 	data_len = plen + sizeof(*hdr);
 	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
@@ -1649,6 +1634,7 @@
 		ret = 0;
 		goto out;
 	}
+	wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", buf, len);
 	if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) {
 		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
 			"WPA: EAPOL frame payload size %lu "
@@ -1657,6 +1643,22 @@
 		ret = 0;
 		goto out;
 	}
+	if (data_len < len) {
+		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+			"WPA: ignoring %lu bytes after the IEEE 802.1X data",
+			(unsigned long) len - data_len);
+	}
+
+	/*
+	 * Make a copy of the frame since we need to modify the buffer during
+	 * MAC validation and Key Data decryption.
+	 */
+	tmp = os_malloc(data_len);
+	if (tmp == NULL)
+		goto out;
+	os_memcpy(tmp, buf, data_len);
+	key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr));
+	key_data = (u8 *) (key + 1);
 
 	if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)
 	{
@@ -1668,13 +1670,16 @@
 	}
 	wpa_eapol_key_dump(sm, key);
 
+	key_data_len = WPA_GET_BE16(key->key_data_length);
+	if (key_data_len > plen - sizeof(struct wpa_eapol_key)) {
+		wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
+			"frame - key_data overflow (%u > %u)",
+			(unsigned int) key_data_len,
+			(unsigned int) (plen - sizeof(struct wpa_eapol_key)));
+		goto out;
+	}
+
 	eapol_sm_notify_lower_layer_success(sm->eapol, 0);
-	wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", tmp, len);
-	if (data_len < len) {
-		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
-			"WPA: ignoring %lu bytes after the IEEE 802.1X data",
-			(unsigned long) len - data_len);
-	}
 	key_info = WPA_GET_BE16(key->key_info);
 	ver = key_info & WPA_KEY_INFO_TYPE_MASK;
 	if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
@@ -1814,22 +1819,11 @@
 		goto out;
 #endif /* CONFIG_PEERKEY */
 
-	extra_len = data_len - sizeof(*hdr) - sizeof(*key);
-
-	if (WPA_GET_BE16(key->key_data_length) > extra_len) {
-		wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
-			"frame - key_data overflow (%d > %lu)",
-			WPA_GET_BE16(key->key_data_length),
-			(unsigned long) extra_len);
-		goto out;
-	}
-	extra_len = WPA_GET_BE16(key->key_data_length);
-
 	if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&
 	    (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
-		if (wpa_supplicant_decrypt_key_data(sm, key, ver))
+		if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data,
+						    &key_data_len))
 			goto out;
-		extra_len = WPA_GET_BE16(key->key_data_length);
 	}
 
 	if (key_info & WPA_KEY_INFO_KEY_TYPE) {
@@ -1841,24 +1835,28 @@
 		}
 		if (peerkey) {
 			/* PeerKey 4-Way Handshake */
-			peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver);
+			peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver,
+					      key_data, key_data_len);
 		} else if (key_info & WPA_KEY_INFO_MIC) {
 			/* 3/4 4-Way Handshake */
-			wpa_supplicant_process_3_of_4(sm, key, ver);
+			wpa_supplicant_process_3_of_4(sm, key, ver, key_data,
+						      key_data_len);
 		} else {
 			/* 1/4 4-Way Handshake */
 			wpa_supplicant_process_1_of_4(sm, src_addr, key,
-						      ver);
+						      ver, key_data,
+						      key_data_len);
 		}
 	} else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
 		/* PeerKey SMK Handshake */
-		peerkey_rx_eapol_smk(sm, src_addr, key, extra_len, key_info,
+		peerkey_rx_eapol_smk(sm, src_addr, key, key_data_len, key_info,
 				     ver);
 	} else {
 		if (key_info & WPA_KEY_INFO_MIC) {
 			/* 1/2 Group Key Handshake */
 			wpa_supplicant_process_1_of_2(sm, src_addr, key,
-						      extra_len, ver);
+						      key_data, key_data_len,
+						      ver);
 		} else {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: EAPOL-Key (Group) without Mic bit - "

Modified: wpa/trunk/src/rsn_supp/wpa.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/rsn_supp/wpa.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/rsn_supp/wpa.h	(original)
+++ wpa/trunk/src/rsn_supp/wpa.h	Tue Oct 14 12:39:25 2014
@@ -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,
@@ -385,7 +385,7 @@
 void wpa_tdls_teardown_peers(struct wpa_sm *sm);
 void wpa_tdls_deinit(struct wpa_sm *sm);
 void wpa_tdls_enable(struct wpa_sm *sm, int enabled);
-void wpa_tdls_disable_link(struct wpa_sm *sm, const u8 *addr);
+void wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr);
 const char * wpa_tdls_get_link_status(struct wpa_sm *sm, const u8 *addr);
 int wpa_tdls_is_external_setup(struct wpa_sm *sm);
 

Modified: wpa/trunk/src/rsn_supp/wpa_ft.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/rsn_supp/wpa_ft.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/rsn_supp/wpa_ft.c	(original)
+++ wpa/trunk/src/rsn_supp/wpa_ft.c	Tue Oct 14 12:39:25 2014
@@ -442,7 +442,8 @@
 	}
 
 	if (parse.r0kh_id_len != sm->r0kh_id_len ||
-	    os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) {
+	    os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
+	{
 		wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
 			   "the current R0KH-ID");
 		wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
@@ -458,7 +459,8 @@
 	}
 
 	if (parse.rsn_pmkid == NULL ||
-	    os_memcmp(parse.rsn_pmkid, sm->pmk_r0_name, WPA_PMK_NAME_LEN)) {
+	    os_memcmp_const(parse.rsn_pmkid, sm->pmk_r0_name, WPA_PMK_NAME_LEN))
+	{
 		wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name (PMKID) in "
 			   "RSNIE");
 		return -1;
@@ -564,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;
@@ -643,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;
@@ -727,7 +730,8 @@
 	}
 
 	if (parse.r0kh_id_len != sm->r0kh_id_len ||
-	    os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) {
+	    os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
+	{
 		wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
 			   "the current R0KH-ID");
 		wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
@@ -742,14 +746,15 @@
 		return -1;
 	}
 
-	if (os_memcmp(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) {
+	if (os_memcmp_const(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
 			   "ReassocResp");
 		return -1;
 	}
 
 	if (parse.rsn_pmkid == NULL ||
-	    os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) {
+	    os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN))
+	{
 		wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
 			   "RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
 		return -1;
@@ -775,7 +780,7 @@
 		return -1;
 	}
 
-	if (os_memcmp(mic, ftie->mic, 16) != 0) {
+	if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
 		wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
 		wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
 		wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);

Modified: wpa/trunk/src/rsn_supp/wpa_i.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/rsn_supp/wpa_i.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/rsn_supp/wpa_i.h	(original)
+++ wpa/trunk/src/rsn_supp/wpa_i.h	Tue Oct 14 12:39:25 2014
@@ -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,

Modified: wpa/trunk/src/rsn_supp/wpa_ie.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/rsn_supp/wpa_ie.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/rsn_supp/wpa_ie.c	(original)
+++ wpa/trunk/src/rsn_supp/wpa_ie.c	Tue Oct 14 12:39:25 2014
@@ -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];

Modified: wpa/trunk/src/tls/pkcs1.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/tls/pkcs1.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/tls/pkcs1.c	(original)
+++ wpa/trunk/src/tls/pkcs1.c	Tue Oct 14 12:39:25 2014
@@ -298,7 +298,7 @@
 		    hdr.payload, hdr.length);
 
 	if (hdr.length != hash_len ||
-	    os_memcmp(hdr.payload, hash, hdr.length) != 0) {
+	    os_memcmp_const(hdr.payload, hash, hdr.length) != 0) {
 		wpa_printf(MSG_INFO, "PKCS #1: Digest value does not match calculated hash");
 		os_free(decrypted);
 		return -1;

Modified: wpa/trunk/src/tls/tlsv1_client_read.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/tls/tlsv1_client_read.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/tls/tlsv1_client_read.c	(original)
+++ wpa/trunk/src/tls/tlsv1_client_read.c	Tue Oct 14 12:39:25 2014
@@ -962,7 +962,7 @@
 	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
 			verify_data, TLS_VERIFY_DATA_LEN);
 
-	if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
+	if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
 		wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data");
 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
 			  TLS_ALERT_DECRYPT_ERROR);

Modified: wpa/trunk/src/tls/tlsv1_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/tls/tlsv1_common.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/tls/tlsv1_common.c	(original)
+++ wpa/trunk/src/tls/tlsv1_common.c	Tue Oct 14 12:39:25 2014
@@ -481,7 +481,8 @@
 	}
 #endif /* CONFIG_TLSV12 */
 
-	if (buflen != data_len || os_memcmp(decrypted, data, data_len) != 0) {
+	if (buflen != data_len ||
+	    os_memcmp_const(decrypted, data, data_len) != 0) {
 		wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in CertificateVerify - did not match calculated hash");
 		os_free(buf);
 		*alert = TLS_ALERT_DECRYPT_ERROR;

Modified: wpa/trunk/src/tls/tlsv1_record.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/tls/tlsv1_record.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/tls/tlsv1_record.c	(original)
+++ wpa/trunk/src/tls/tlsv1_record.c	Tue Oct 14 12:39:25 2014
@@ -456,7 +456,7 @@
 			return -1;
 		}
 		if (hlen != rl->hash_size ||
-		    os_memcmp(hash, out_data + plen, hlen) != 0 ||
+		    os_memcmp_const(hash, out_data + plen, hlen) != 0 ||
 		    force_mac_error) {
 			wpa_printf(MSG_DEBUG, "TLSv1: Invalid HMAC value in "
 				   "received message (force_mac_error=%d)",

Modified: wpa/trunk/src/tls/tlsv1_server_read.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/tls/tlsv1_server_read.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/tls/tlsv1_server_read.c	(original)
+++ wpa/trunk/src/tls/tlsv1_server_read.c	Tue Oct 14 12:39:25 2014
@@ -1135,7 +1135,7 @@
 	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)",
 			verify_data, TLS_VERIFY_DATA_LEN);
 
-	if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
+	if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
 		tlsv1_server_log(conn, "Mismatch in verify_data");
 		return -1;
 	}

Modified: wpa/trunk/src/tls/x509v3.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/tls/x509v3.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/tls/x509v3.c	(original)
+++ wpa/trunk/src/tls/x509v3.c	Tue Oct 14 12:39:25 2014
@@ -1776,7 +1776,7 @@
 	}
 
 	if (hdr.length != hash_len ||
-	    os_memcmp(hdr.payload, hash, hdr.length) != 0) {
+	    os_memcmp_const(hdr.payload, hash, hdr.length) != 0) {
 		wpa_printf(MSG_INFO, "X509: Certificate Digest does not match "
 			   "with calculated tbsCertificate hash");
 		os_free(data);

Modified: wpa/trunk/src/utils/browser-android.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/browser-android.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/browser-android.c	(original)
+++ wpa/trunk/src/utils/browser-android.c	Tue Oct 14 12:39:25 2014
@@ -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");
 	}
 

Modified: wpa/trunk/src/utils/browser-system.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/browser-system.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/browser-system.c	(original)
+++ wpa/trunk/src/utils/browser-system.c	Tue Oct 14 12:39:25 2014
@@ -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);

Modified: wpa/trunk/src/utils/browser-wpadebug.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/browser-wpadebug.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/browser-wpadebug.c	(original)
+++ wpa/trunk/src/utils/browser-wpadebug.c	Tue Oct 14 12:39:25 2014
@@ -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");
 	}
 

Modified: wpa/trunk/src/utils/common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/common.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/common.c	(original)
+++ wpa/trunk/src/utils/common.c	Tue Oct 14 12:39:25 2014
@@ -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':
@@ -827,3 +827,42 @@
 
 	*res = n;
 }
+
+
+void str_clear_free(char *str)
+{
+	if (str) {
+		size_t len = os_strlen(str);
+		os_memset(str, 0, len);
+		os_free(str);
+	}
+}
+
+
+void bin_clear_free(void *bin, size_t len)
+{
+	if (bin) {
+		os_memset(bin, 0, len);
+		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;
+}

Modified: wpa/trunk/src/utils/common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/common.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/common.h	(original)
+++ wpa/trunk/src/utils/common.h	Tue Oct 14 12:39:25 2014
@@ -535,6 +535,13 @@
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
 
+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
  * networking socket uses that do not really result in a real problem and

Modified: wpa/trunk/src/utils/ext_password_test.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/ext_password_test.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/ext_password_test.c	(original)
+++ wpa/trunk/src/utils/ext_password_test.c	Tue Oct 14 12:39:25 2014
@@ -36,7 +36,7 @@
 {
 	struct ext_password_test_data *data = ctx;
 
-	os_free(data->params);
+	str_clear_free(data->params);
 	os_free(data);
 }
 

Modified: wpa/trunk/src/utils/http_curl.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/http_curl.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/http_curl.c	(original)
+++ wpa/trunk/src/utils/http_curl.c	Tue Oct 14 12:39:25 2014
@@ -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";
@@ -1368,8 +1368,8 @@
 			       client_cert, client_key);
 	os_free(address);
 	os_free(ca_fname);
-	os_free(username);
-	os_free(password);
+	str_clear_free(username);
+	str_clear_free(password);
 	os_free(client_cert);
 	os_free(client_key);
 	return ret;
@@ -1487,8 +1487,8 @@
 
 	os_free(ctx->svc_address);
 	os_free(ctx->svc_ca_fname);
-	os_free(ctx->svc_username);
-	os_free(ctx->svc_password);
+	str_clear_free(ctx->svc_username);
+	str_clear_free(ctx->svc_password);
 	os_free(ctx->svc_client_cert);
 	os_free(ctx->svc_client_key);
 

Modified: wpa/trunk/src/utils/os.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/os.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/os.h	(original)
+++ wpa/trunk/src/utils/os.h	Tue Oct 14 12:39:25 2014
@@ -583,6 +583,32 @@
  * This function matches in behavior with the strlcpy(3) function in OpenBSD.
  */
 size_t os_strlcpy(char *dest, const char *src, size_t siz);
+
+/**
+ * os_memcmp_const - Constant time memory comparison
+ * @a: First buffer to compare
+ * @b: Second buffer to compare
+ * @len: Number of octets to compare
+ * Returns: 0 if buffers are equal, non-zero if not
+ *
+ * This function is meant for comparing passwords or hash values where
+ * difference in execution time could provide external observer information
+ * about the location of the difference in the memory buffers. The return value
+ * does not behave like os_memcmp(), i.e., os_memcmp_const() cannot be used to
+ * sort items into a defined order. Unlike os_memcmp(), execution time of
+ * os_memcmp_const() does not depend on the contents of the compared memory
+ * buffers, but only on the total compared length.
+ */
+int os_memcmp_const(const void *a, const void *b, size_t len);
+
+/**
+ * os_exec - Execute an external program
+ * @program: Path to the program
+ * @arg: Command line argument string
+ * @wait_completion: Whether to wait until the program execution completes
+ * Returns: 0 on success, -1 on error
+ */
+int os_exec(const char *program, const char *arg, int wait_completion);
 
 
 #ifdef OS_REJECT_C_LIB_FUNCTIONS

Modified: wpa/trunk/src/utils/os_internal.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/os_internal.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/os_internal.c	(original)
+++ wpa/trunk/src/utils/os_internal.c	Tue Oct 14 12:39:25 2014
@@ -463,6 +463,20 @@
 }
 
 
+int os_memcmp_const(const void *a, const void *b, size_t len)
+{
+	const u8 *aa = a;
+	const u8 *bb = b;
+	size_t i;
+	u8 res;
+
+	for (res = 0, i = 0; i < len; i++)
+		res |= aa[i] ^ bb[i];
+
+	return res;
+}
+
+
 char * os_strstr(const char *haystack, const char *needle)
 {
 	size_t len = os_strlen(needle);

Modified: wpa/trunk/src/utils/os_none.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/os_none.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/os_none.c	(original)
+++ wpa/trunk/src/utils/os_none.c	Tue Oct 14 12:39:25 2014
@@ -218,6 +218,11 @@
 }
 
 
+int os_memcmp_const(const void *a, const void *b, size_t len)
+{
+	return 0;
+}
+
 char * os_strstr(const char *haystack, const char *needle)
 {
 	return NULL;

Modified: wpa/trunk/src/utils/os_unix.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/os_unix.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/os_unix.c	(original)
+++ wpa/trunk/src/utils/os_unix.c	Tue Oct 14 12:39:25 2014
@@ -9,10 +9,11 @@
 #include "includes.h"
 
 #include <time.h>
+#include <sys/wait.h>
 
 #ifdef ANDROID
 #include <sys/capability.h>
-#include <linux/prctl.h>
+#include <sys/prctl.h>
 #include <private/android_filesystem_config.h>
 #endif /* ANDROID */
 
@@ -450,6 +451,20 @@
 }
 
 
+int os_memcmp_const(const void *a, const void *b, size_t len)
+{
+	const u8 *aa = a;
+	const u8 *bb = b;
+	size_t i;
+	u8 res;
+
+	for (res = 0, i = 0; i < len; i++)
+		res |= aa[i] ^ bb[i];
+
+	return res;
+}
+
+
 #ifdef WPA_TRACE
 
 void * os_malloc(size_t size)
@@ -540,3 +555,57 @@
 }
 
 #endif /* WPA_TRACE */
+
+
+int os_exec(const char *program, const char *arg, int wait_completion)
+{
+	pid_t pid;
+	int pid_status;
+
+	pid = fork();
+	if (pid < 0) {
+		perror("fork");
+		return -1;
+	}
+
+	if (pid == 0) {
+		/* run the external command in the child process */
+		const int MAX_ARG = 30;
+		char *_program, *_arg, *pos;
+		char *argv[MAX_ARG + 1];
+		int i;
+
+		_program = os_strdup(program);
+		_arg = os_strdup(arg);
+
+		argv[0] = _program;
+
+		i = 1;
+		pos = _arg;
+		while (i < MAX_ARG && pos && *pos) {
+			while (*pos == ' ')
+				pos++;
+			if (*pos == '\0')
+				break;
+			argv[i++] = pos;
+			pos = os_strchr(pos, ' ');
+			if (pos)
+				*pos++ = '\0';
+		}
+		argv[i] = NULL;
+
+		execv(program, argv);
+		perror("execv");
+		os_free(_program);
+		os_free(_arg);
+		exit(0);
+		return -1;
+	}
+
+	if (wait_completion) {
+		/* wait for the child process to complete in the parent */
+		waitpid(pid, &pid_status, 0);
+	}
+
+	return 0;
+}

Modified: wpa/trunk/src/utils/os_win32.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/os_win32.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/os_win32.c	(original)
+++ wpa/trunk/src/utils/os_win32.c	Tue Oct 14 12:39:25 2014
@@ -244,3 +244,23 @@
 
 	return s - src - 1;
 }
+
+
+int os_memcmp_const(const void *a, const void *b, size_t len)
+{
+	const u8 *aa = a;
+	const u8 *bb = b;
+	size_t i;
+	u8 res;
+
+	for (res = 0, i = 0; i < len; i++)
+		res |= aa[i] ^ bb[i];
+
+	return res;
+}
+
+
+int os_exec(const char *program, const char *arg, int wait_completion)
+{
+	return -1;
+}

Modified: wpa/trunk/src/utils/pcsc_funcs.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/pcsc_funcs.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/pcsc_funcs.c	(original)
+++ wpa/trunk/src/utils/pcsc_funcs.c	Tue Oct 14 12:39:25 2014
@@ -1406,6 +1406,12 @@
 		pos += IK_LEN;
 		wpa_hexdump(MSG_DEBUG, "SCARD: IK", ik, IK_LEN);
 
+		if (end > pos) {
+			wpa_hexdump(MSG_DEBUG,
+				    "SCARD: Ignore extra data in end",
+				    pos, end - pos);
+		}
+
 		return 0;
 	}
 

Modified: wpa/trunk/src/utils/wpa_debug.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/wpa_debug.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/wpa_debug.c	(original)
+++ wpa/trunk/src/utils/wpa_debug.c	Tue Oct 14 12:39:25 2014
@@ -685,6 +685,34 @@
 }
 
 
+void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...)
+{
+	va_list ap;
+	char *buf;
+	int buflen;
+	int len;
+
+	if (!wpa_msg_cb)
+		return;
+
+	va_start(ap, fmt);
+	buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
+	va_end(ap);
+
+	buf = os_malloc(buflen);
+	if (buf == NULL) {
+		wpa_printf(MSG_ERROR,
+			   "wpa_msg_global_ctrl: Failed to allocate message buffer");
+		return;
+	}
+	va_start(ap, fmt);
+	len = vsnprintf(buf, buflen, fmt, ap);
+	va_end(ap);
+	wpa_msg_cb(ctx, level, 1, buf, len);
+	os_free(buf);
+}
+
+
 void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...)
 {
 	va_list ap;

Modified: wpa/trunk/src/utils/wpa_debug.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/utils/wpa_debug.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/utils/wpa_debug.h	(original)
+++ wpa/trunk/src/utils/wpa_debug.h	Tue Oct 14 12:39:25 2014
@@ -160,6 +160,7 @@
 #define wpa_msg(args...) do { } while (0)
 #define wpa_msg_ctrl(args...) do { } while (0)
 #define wpa_msg_global(args...) do { } while (0)
+#define wpa_msg_global_ctrl(args...) do { } while (0)
 #define wpa_msg_no_global(args...) do { } while (0)
 #define wpa_msg_register_cb(f) do { } while (0)
 #define wpa_msg_register_ifname_cb(f) do { } while (0)
@@ -209,6 +210,21 @@
  * specified by the context data).
  */
 void wpa_msg_global(void *ctx, int level, const char *fmt, ...)
+PRINTF_FORMAT(3, 4);
+
+/**
+ * wpa_msg_global_ctrl - Conditional global printf for ctrl_iface monitors
+ * @ctx: Pointer to context data; this is the ctx variable registered
+ *	with struct wpa_driver_ops::init()
+ * @level: priority level (MSG_*) of the message
+ * @fmt: printf format string, followed by optional arguments
+ *
+ * This function is used to print conditional debugging and error messages.
+ * This function is like wpa_msg_global(), but it sends the output only to the
+ * attached global ctrl_iface monitors. In other words, it can be used for
+ * frequent events that do not need to be sent to syslog.
+ */
+void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...)
 PRINTF_FORMAT(3, 4);
 
 /**

Modified: wpa/trunk/src/wps/httpread.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/wps/httpread.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/wps/httpread.c	(original)
+++ wpa/trunk/src/wps/httpread.c	Tue Oct 14 12:39:25 2014
@@ -413,8 +413,8 @@
 		 */
 		if (httpread_debug >= 10)
 			wpa_printf(MSG_DEBUG, "httpread ok eof(%p)", h);
-			h->got_body = 1;
-			goto got_file;
+		h->got_body = 1;
+		goto got_file;
 	}
 	rbp = readbuf;
 

Modified: wpa/trunk/src/wps/wps.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/wps/wps.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/wps/wps.c	(original)
+++ wpa/trunk/src/wps/wps.c	Tue Oct 14 12:39:25 2014
@@ -89,7 +89,7 @@
 	if (cfg->pbc) {
 		/* Use special PIN '00000000' for PBC */
 		data->dev_pw_id = DEV_PW_PUSHBUTTON;
-		os_free(data->dev_password);
+		bin_clear_free(data->dev_password, data->dev_password_len);
 		data->dev_password = (u8 *) os_strdup("00000000");
 		if (data->dev_password == NULL) {
 			os_free(data);
@@ -122,7 +122,8 @@
 		data->new_ap_settings =
 			os_malloc(sizeof(*data->new_ap_settings));
 		if (data->new_ap_settings == NULL) {
-			os_free(data->dev_password);
+			bin_clear_free(data->dev_password,
+				       data->dev_password_len);
 			os_free(data);
 			return NULL;
 		}
@@ -173,11 +174,11 @@
 	wpabuf_free(data->dh_pubkey_e);
 	wpabuf_free(data->dh_pubkey_r);
 	wpabuf_free(data->last_msg);
-	os_free(data->dev_password);
-	os_free(data->alt_dev_password);
-	os_free(data->new_psk);
+	bin_clear_free(data->dev_password, data->dev_password_len);
+	bin_clear_free(data->alt_dev_password, data->alt_dev_password_len);
+	bin_clear_free(data->new_psk, data->new_psk_len);
 	wps_device_data_free(&data->peer_dev);
-	os_free(data->new_ap_settings);
+	bin_clear_free(data->new_ap_settings, sizeof(*data->new_ap_settings));
 	dh5_free(data->dh_ctx);
 	os_free(data);
 }

Modified: wpa/trunk/src/wps/wps_attr_process.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/wps/wps_attr_process.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/wps/wps_attr_process.c	(original)
+++ wpa/trunk/src/wps/wps_attr_process.c	Tue Oct 14 12:39:25 2014
@@ -41,7 +41,7 @@
 	len[1] = wpabuf_len(msg) - 4 - WPS_AUTHENTICATOR_LEN;
 	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash);
 
-	if (os_memcmp(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) {
+	if (os_memcmp_const(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator");
 		return -1;
 	}
@@ -71,7 +71,7 @@
 	}
 
 	hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash);
-	if (os_memcmp(hash, key_wrap_auth, WPS_KWA_LEN) != 0) {
+	if (os_memcmp_const(hash, key_wrap_auth, WPS_KWA_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: Invalid KWA");
 		return -1;
 	}

Modified: wpa/trunk/src/wps/wps_enrollee.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/wps/wps_enrollee.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/wps/wps_enrollee.c	(original)
+++ wpa/trunk/src/wps/wps_enrollee.c	Tue Oct 14 12:39:25 2014
@@ -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)",
@@ -525,8 +535,8 @@
 	if (wps->peer_pubkey_hash_set) {
 		u8 hash[WPS_HASH_LEN];
 		sha256_vector(1, &pk, &pk_len, hash);
-		if (os_memcmp(hash, wps->peer_pubkey_hash,
-			      WPS_OOB_PUBKEY_HASH_LEN) != 0) {
+		if (os_memcmp_const(hash, wps->peer_pubkey_hash,
+				    WPS_OOB_PUBKEY_HASH_LEN) != 0) {
 			wpa_printf(MSG_ERROR, "WPS: Public Key hash mismatch");
 			wpa_hexdump(MSG_DEBUG, "WPS: Received public key",
 				    pk, pk_len);
@@ -605,7 +615,7 @@
 	len[3] = wpabuf_len(wps->dh_pubkey_r);
 	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
 
-	if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
+	if (os_memcmp_const(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does "
 			   "not match with the pre-committed value");
 		wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
@@ -645,7 +655,7 @@
 	len[3] = wpabuf_len(wps->dh_pubkey_r);
 	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
 
-	if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
+	if (os_memcmp_const(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does "
 			   "not match with the pre-committed value");
 		wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
@@ -892,7 +902,7 @@
 
 	if (wps->alt_dev_password && wps->alt_dev_pw_id == id) {
 		wpa_printf(MSG_DEBUG, "WPS: Found a matching Device Password");
-		os_free(wps->dev_password);
+		bin_clear_free(wps->dev_password, wps->dev_password_len);
 		wps->dev_pw_id = wps->alt_dev_pw_id;
 		wps->dev_password = wps->alt_dev_password;
 		wps->dev_password_len = wps->alt_dev_password_len;

Modified: wpa/trunk/src/wps/wps_er.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/wps/wps_er.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/wps/wps_er.c	(original)
+++ wpa/trunk/src/wps/wps_er.c	Tue Oct 14 12:39:25 2014
@@ -579,12 +579,15 @@
 	wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number);
 
 	ap->udn = xml_get_first_item(data, "UDN");
-	wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn);
-	pos = os_strstr(ap->udn, "uuid:");
-	if (pos) {
-		pos += 5;
-		if (uuid_str2bin(pos, ap->uuid) < 0)
-			wpa_printf(MSG_DEBUG, "WPS ER: Invalid UUID in UDN");
+	if (ap->udn) {
+		wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn);
+		pos = os_strstr(ap->udn, "uuid:");
+		if (pos) {
+			pos += 5;
+			if (uuid_str2bin(pos, ap->uuid) < 0)
+				wpa_printf(MSG_DEBUG,
+					   "WPS ER: Invalid UUID in UDN");
+		}
 	}
 
 	ap->upc = xml_get_first_item(data, "UPC");

Modified: wpa/trunk/src/wps/wps_registrar.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/wps/wps_registrar.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/wps/wps_registrar.c	(original)
+++ wpa/trunk/src/wps/wps_registrar.c	Tue Oct 14 12:39:25 2014
@@ -42,7 +42,7 @@
 static void wps_remove_nfc_pw_token(struct wps_nfc_pw_token *token)
 {
 	dl_list_del(&token->list);
-	os_free(token);
+	bin_clear_free(token, sizeof(*token));
 }
 
 
@@ -91,7 +91,7 @@
 
 static void wps_free_pin(struct wps_uuid_pin *pin)
 {
-	os_free(pin->pin);
+	bin_clear_free(pin->pin, pin->pin_len);
 	os_free(pin);
 }
 
@@ -826,7 +826,7 @@
 	{
 		if (dev_pw && pin->pin &&
 		    (dev_pw_len != pin->pin_len ||
-		     os_memcmp(dev_pw, pin->pin, dev_pw_len) != 0))
+		     os_memcmp_const(dev_pw, pin->pin, dev_pw_len) != 0))
 			continue; /* different PIN */
 		if (pin->wildcard_uuid) {
 			wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID",
@@ -1343,7 +1343,7 @@
 	const u8 *pin;
 	size_t pin_len = 0;
 
-	os_free(wps->dev_password);
+	bin_clear_free(wps->dev_password, wps->dev_password_len);
 	wps->dev_password = NULL;
 
 	if (wps->pbc) {
@@ -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;
@@ -2211,7 +2218,7 @@
 	len[3] = wpabuf_len(wps->dh_pubkey_r);
 	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
 
-	if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
+	if (os_memcmp_const(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: E-Hash1 derived from E-S1 does "
 			   "not match with the pre-committed value");
 		wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
@@ -2251,7 +2258,7 @@
 	len[3] = wpabuf_len(wps->dh_pubkey_r);
 	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
 
-	if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
+	if (os_memcmp_const(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: E-Hash2 derived from E-S2 does "
 			   "not match with the pre-committed value");
 		wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e);
@@ -2591,8 +2598,9 @@
 
 			addr[0] = attr->public_key;
 			sha256_vector(1, addr, &attr->public_key_len, hash);
-			if (os_memcmp(hash, wps->nfc_pw_token->pubkey_hash,
-				      WPS_OOB_PUBKEY_HASH_LEN) != 0) {
+			if (os_memcmp_const(hash,
+					    wps->nfc_pw_token->pubkey_hash,
+					    WPS_OOB_PUBKEY_HASH_LEN) != 0) {
 				wpa_printf(MSG_ERROR, "WPS: Public Key hash "
 					   "mismatch");
 				wps->state = SEND_M2D;

Modified: wpa/trunk/src/wps/wps_upnp.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/src/wps/wps_upnp.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/src/wps/wps_upnp.c	(original)
+++ wpa/trunk/src/wps/wps_upnp.c	Tue Oct 14 12:39:25 2014
@@ -227,6 +227,8 @@
 
 	t = time(NULL);
 	date = gmtime(&t);
+	if (date == NULL)
+		return;
 	wpabuf_printf(buf, "%s, %02d %s %d %02d:%02d:%02d GMT",
 		      &weekday_str[date->tm_wday * 4], date->tm_mday,
 		      &month_str[date->tm_mon * 4], date->tm_year + 1900,
@@ -594,7 +596,10 @@
 	wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
 	wpabuf_put_be16(msg, WPS_NONCE_LEN);
 	wpabuf_put(msg, WPS_NONCE_LEN);
-	wps_build_wfa_ext(msg, 0, NULL, 0);
+	if (wps_build_wfa_ext(msg, 0, NULL, 0)) {
+		wpabuf_free(msg);
+		return NULL;
+	}
 	return msg;
 }
 

Modified: wpa/trunk/wpa_supplicant/Android.mk
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/Android.mk?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/Android.mk	(original)
+++ wpa/trunk/wpa_supplicant/Android.mk	Tue Oct 14 12:39:25 2014
@@ -36,10 +36,6 @@
 # Disable roaming in wpa_supplicant
 ifdef CONFIG_NO_ROAMING
 L_CFLAGS += -DCONFIG_NO_ROAMING
-endif
-
-ifeq ($(BOARD_WLAN_DEVICE), bcmdhd)
-L_CFLAGS += -DP2P_CONCURRENT_SEARCH_DELAY=0
 endif
 
 # Use Android specific directory for control interface sockets

Modified: wpa/trunk/wpa_supplicant/ChangeLog
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/ChangeLog?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/ChangeLog	(original)
+++ wpa/trunk/wpa_supplicant/ChangeLog	Tue Oct 14 12:39:25 2014
@@ -1,4 +1,69 @@
 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

Modified: wpa/trunk/wpa_supplicant/Makefile
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/Makefile?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/Makefile	(original)
+++ wpa/trunk/wpa_supplicant/Makefile	Tue Oct 14 12:39:25 2014
@@ -1499,6 +1499,9 @@
 ifdef CONFIG_WPS
 OBJS += ../src/wps/wps_module_tests.o
 endif
+ifndef CONFIG_P2P
+OBJS += ../src/utils/bitfield.o
+endif
 endif
 
 OBJS += ../src/drivers/driver_common.o

Modified: wpa/trunk/wpa_supplicant/README-P2P
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/README-P2P?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/README-P2P	(original)
+++ wpa/trunk/wpa_supplicant/README-P2P	Tue Oct 14 12:39:25 2014
@@ -554,6 +554,13 @@
 
 Set country code (this is included in some P2P messages).
 
+set p2p_search_delay <delay>
+
+Set p2p_search_delay which adds extra delay in milliseconds between
+concurrent search iterations to make p2p_find friendlier to concurrent
+operations by avoiding it from taking 100% of radio resources. The
+default value is 500 ms.
+
 Status
 
 p2p_peers [discovered]

Modified: wpa/trunk/wpa_supplicant/ap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/ap.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/ap.c	(original)
+++ wpa/trunk/wpa_supplicant/ap.c	Tue Oct 14 12:39:25 2014
@@ -373,18 +373,16 @@
 #ifdef CONFIG_P2P
 	struct wpa_supplicant *wpa_s = ctx;
 	const struct ieee80211_mgmt *mgmt;
-	size_t hdr_len;
 
 	mgmt = (const struct ieee80211_mgmt *) buf;
-	hdr_len = (const u8 *) &mgmt->u.action.u.vs_public_action.action - buf;
-	if (hdr_len > len)
+	if (len < IEEE80211_HDRLEN + 1)
 		return;
 	if (mgmt->u.action.category != WLAN_ACTION_PUBLIC)
 		return;
 	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
 			   mgmt->u.action.category,
-			   &mgmt->u.action.u.vs_public_action.action,
-			   len - hdr_len, freq);
+			   buf + IEEE80211_HDRLEN + 1,
+			   len - IEEE80211_HDRLEN - 1, freq);
 #endif /* CONFIG_P2P */
 }
 
@@ -440,16 +438,14 @@
 #ifdef CONFIG_P2P
 	struct wpa_supplicant *wpa_s = ctx;
 	const struct ieee80211_mgmt *mgmt;
-	size_t hdr_len;
 
 	mgmt = (const struct ieee80211_mgmt *) buf;
-	hdr_len = (const u8 *) &mgmt->u.action.u.vs_public_action.action - buf;
-	if (hdr_len > len)
+	if (len < IEEE80211_HDRLEN + 1)
 		return -1;
 	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
 			   mgmt->u.action.category,
-			   &mgmt->u.action.u.vs_public_action.action,
-			   len - hdr_len, freq);
+			   buf + IEEE80211_HDRLEN + 1,
+			   len - IEEE80211_HDRLEN - 1, freq);
 #endif /* CONFIG_P2P */
 	return 0;
 }
@@ -459,23 +455,17 @@
 			   const u8 *bssid, const u8 *ie, size_t ie_len,
 			   int ssi_signal)
 {
-#ifdef CONFIG_P2P
 	struct wpa_supplicant *wpa_s = ctx;
 	return wpas_p2p_probe_req_rx(wpa_s, sa, da, bssid, ie, ie_len,
 				     ssi_signal);
-#else /* CONFIG_P2P */
-	return 0;
-#endif /* CONFIG_P2P */
 }
 
 
 static void ap_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
 				  const u8 *uuid_e)
 {
-#ifdef CONFIG_P2P
 	struct wpa_supplicant *wpa_s = ctx;
 	wpas_p2p_wps_success(wpa_s, mac_addr, 1);
-#endif /* CONFIG_P2P */
 }
 
 
@@ -523,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)
@@ -672,11 +662,7 @@
 	wpa_s->current_ssid = NULL;
 	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
 	wpa_s->assoc_freq = 0;
-#ifdef CONFIG_P2P
-	if (wpa_s->ap_iface->bss)
-		wpa_s->ap_iface->bss[0]->p2p_group = NULL;
-	wpas_p2p_group_deinit(wpa_s);
-#endif /* CONFIG_P2P */
+	wpas_p2p_ap_deinit(wpa_s);
 	wpa_s->ap_iface->driver_ap_teardown =
 		!!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
 

Modified: wpa/trunk/wpa_supplicant/bss.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/bss.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/bss.c	(original)
+++ wpa/trunk/wpa_supplicant/bss.c	Tue Oct 14 12:39:25 2014
@@ -489,6 +489,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);
 }
 
 

Modified: wpa/trunk/wpa_supplicant/config.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/config.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/config.c	(original)
+++ wpa/trunk/wpa_supplicant/config.c	Tue Oct 14 12:39:25 2014
@@ -286,7 +286,7 @@
 {
 #ifdef CONFIG_EXT_PASSWORD
 	if (os_strncmp(value, "ext:", 4) == 0) {
-		os_free(ssid->passphrase);
+		str_clear_free(ssid->passphrase);
 		ssid->passphrase = NULL;
 		ssid->psk_set = 0;
 		os_free(ssid->ext_psk);
@@ -322,7 +322,7 @@
 		    os_memcmp(ssid->passphrase, value, len) == 0)
 			return 0;
 		ssid->psk_set = 0;
-		os_free(ssid->passphrase);
+		str_clear_free(ssid->passphrase);
 		ssid->passphrase = dup_binstr(value, len);
 		if (ssid->passphrase == NULL)
 			return -1;
@@ -341,7 +341,7 @@
 		return -1;
 	}
 
-	os_free(ssid->passphrase);
+	str_clear_free(ssid->passphrase);
 	ssid->passphrase = NULL;
 
 	ssid->psk_set = 1;
@@ -435,7 +435,7 @@
 static char * wpa_config_write_proto(const struct parse_data *data,
 				     struct wpa_ssid *ssid)
 {
-	int first = 1, ret;
+	int ret;
 	char *buf, *pos, *end;
 
 	pos = buf = os_zalloc(20);
@@ -444,27 +444,32 @@
 	end = buf + 20;
 
 	if (ssid->proto & WPA_PROTO_WPA) {
-		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
+		ret = os_snprintf(pos, end - pos, "%sWPA",
+				  pos == buf ? "" : " ");
 		if (ret < 0 || ret >= end - pos)
 			return buf;
 		pos += ret;
-		first = 0;
 	}
 
 	if (ssid->proto & WPA_PROTO_RSN) {
-		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
+		ret = os_snprintf(pos, end - pos, "%sRSN",
+				  pos == buf ? "" : " ");
 		if (ret < 0 || ret >= end - pos)
 			return buf;
 		pos += ret;
-		first = 0;
 	}
 
 	if (ssid->proto & WPA_PROTO_OSEN) {
-		ret = os_snprintf(pos, end - pos, "%sOSEN", first ? "" : " ");
+		ret = os_snprintf(pos, end - pos, "%sOSEN",
+				  pos == buf ? "" : " ");
 		if (ret < 0 || ret >= end - pos)
 			return buf;
 		pos += ret;
-		first = 0;
+	}
+
+	if (pos == buf) {
+		os_free(buf);
+		buf = NULL;
 	}
 
 	return buf;
@@ -672,6 +677,11 @@
 	}
 #endif /* CONFIG_WPS */
 
+	if (pos == buf) {
+		os_free(buf);
+		buf = NULL;
+	}
+
 	return buf;
 }
 #endif /* NO_CONFIG_WRITE */
@@ -863,6 +873,11 @@
 		pos += ret;
 	}
 
+	if (pos == buf) {
+		os_free(buf);
+		buf = NULL;
+	}
+
 	return buf;
 }
 #endif /* NO_CONFIG_WRITE */
@@ -1115,7 +1130,7 @@
 
 	if (os_strcmp(value, "NULL") == 0) {
 		wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
-		os_free(ssid->eap.password);
+		bin_clear_free(ssid->eap.password, ssid->eap.password_len);
 		ssid->eap.password = NULL;
 		ssid->eap.password_len = 0;
 		return 0;
@@ -1126,7 +1141,7 @@
 		char *name = os_strdup(value + 4);
 		if (name == NULL)
 			return -1;
-		os_free(ssid->eap.password);
+		bin_clear_free(ssid->eap.password, ssid->eap.password_len);
 		ssid->eap.password = (u8 *) name;
 		ssid->eap.password_len = os_strlen(name);
 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
@@ -1148,7 +1163,7 @@
 		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
 				      (u8 *) tmp, res_len);
 
-		os_free(ssid->eap.password);
+		bin_clear_free(ssid->eap.password, ssid->eap.password_len);
 		ssid->eap.password = (u8 *) tmp;
 		ssid->eap.password_len = res_len;
 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
@@ -1177,7 +1192,7 @@
 
 	wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
 
-	os_free(ssid->eap.password);
+	bin_clear_free(ssid->eap.password, ssid->eap.password_len);
 	ssid->eap.password = hash;
 	ssid->eap.password_len = 16;
 	ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
@@ -1247,7 +1262,7 @@
 			   line, (unsigned int) *len);
 	}
 	os_memcpy(key, buf, *len);
-	os_free(buf);
+	str_clear_free(buf);
 	res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
 	if (res >= 0 && (size_t) res < sizeof(title))
 		wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
@@ -1736,6 +1751,10 @@
 #ifdef CONFIG_MACSEC
 	{ INT_RANGE(macsec_policy, 0, 1) },
 #endif /* CONFIG_MACSEC */
+#ifdef CONFIG_HS20
+	{ INT(update_identifier) },
+#endif /* CONFIG_HS20 */
+	{ INT_RANGE(mac_addr, 0, 2) },
 };
 
 #undef OFFSET
@@ -1845,14 +1864,14 @@
 static void eap_peer_config_free(struct eap_peer_config *eap)
 {
 	os_free(eap->eap_methods);
-	os_free(eap->identity);
+	bin_clear_free(eap->identity, eap->identity_len);
 	os_free(eap->anonymous_identity);
-	os_free(eap->password);
+	bin_clear_free(eap->password, eap->password_len);
 	os_free(eap->ca_cert);
 	os_free(eap->ca_path);
 	os_free(eap->client_cert);
 	os_free(eap->private_key);
-	os_free(eap->private_key_passwd);
+	str_clear_free(eap->private_key_passwd);
 	os_free(eap->dh_file);
 	os_free(eap->subject_match);
 	os_free(eap->altsubject_match);
@@ -1861,7 +1880,7 @@
 	os_free(eap->ca_path2);
 	os_free(eap->client_cert2);
 	os_free(eap->private_key2);
-	os_free(eap->private_key2_passwd);
+	str_clear_free(eap->private_key2_passwd);
 	os_free(eap->dh_file2);
 	os_free(eap->subject_match2);
 	os_free(eap->altsubject_match2);
@@ -1869,7 +1888,7 @@
 	os_free(eap->phase1);
 	os_free(eap->phase2);
 	os_free(eap->pcsc);
-	os_free(eap->pin);
+	str_clear_free(eap->pin);
 	os_free(eap->engine_id);
 	os_free(eap->key_id);
 	os_free(eap->cert_id);
@@ -1877,13 +1896,13 @@
 	os_free(eap->key2_id);
 	os_free(eap->cert2_id);
 	os_free(eap->ca_cert2_id);
-	os_free(eap->pin2);
+	str_clear_free(eap->pin2);
 	os_free(eap->engine2_id);
 	os_free(eap->otp);
 	os_free(eap->pending_req_otp);
 	os_free(eap->pac_file);
-	os_free(eap->new_password);
-	os_free(eap->external_sim_resp);
+	bin_clear_free(eap->new_password, eap->new_password_len);
+	str_clear_free(eap->external_sim_resp);
 }
 #endif /* IEEE8021X_EAPOL */
 
@@ -1900,7 +1919,8 @@
 	struct psk_list_entry *psk;
 
 	os_free(ssid->ssid);
-	os_free(ssid->passphrase);
+	os_memset(ssid->psk, 0, sizeof(ssid->psk));
+	str_clear_free(ssid->passphrase);
 	os_free(ssid->ext_psk);
 #ifdef IEEE8021X_EAPOL
 	eap_peer_config_free(&ssid->eap);
@@ -1927,14 +1947,14 @@
 	size_t i;
 
 	os_free(cred->realm);
-	os_free(cred->username);
-	os_free(cred->password);
+	str_clear_free(cred->username);
+	str_clear_free(cred->password);
 	os_free(cred->ca_cert);
 	os_free(cred->client_cert);
 	os_free(cred->private_key);
-	os_free(cred->private_key_passwd);
+	str_clear_free(cred->private_key_passwd);
 	os_free(cred->imsi);
-	os_free(cred->milenage);
+	str_clear_free(cred->milenage);
 	for (i = 0; i < cred->num_domain; i++)
 		os_free(cred->domain[i]);
 	os_free(cred->domain);
@@ -2004,7 +2024,7 @@
 	os_free(config->pkcs11_engine_path);
 	os_free(config->pkcs11_module_path);
 	os_free(config->pcsc_reader);
-	os_free(config->pcsc_pin);
+	str_clear_free(config->pcsc_pin);
 	os_free(config->driver_param);
 	os_free(config->device_name);
 	os_free(config->manufacturer);
@@ -2192,6 +2212,7 @@
 #ifdef CONFIG_IEEE80211W
 	ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
 #endif /* CONFIG_IEEE80211W */
+	ssid->mac_addr = -1;
 }
 
 
@@ -2388,7 +2409,7 @@
 					wpa_printf(MSG_DEBUG, "Do not allow "
 						   "key_data field to be "
 						   "exposed");
-					os_free(res);
+					str_clear_free(res);
 					return os_strdup("*");
 				}
 
@@ -2534,7 +2555,7 @@
 
 	if (os_strcmp(var, "password") == 0 &&
 	    os_strncmp(value, "ext:", 4) == 0) {
-		os_free(cred->password);
+		str_clear_free(cred->password);
 		cred->password = os_strdup(value);
 		cred->ext_password = 1;
 		return 0;
@@ -2597,13 +2618,13 @@
 	}
 
 	if (os_strcmp(var, "username") == 0) {
-		os_free(cred->username);
+		str_clear_free(cred->username);
 		cred->username = val;
 		return 0;
 	}
 
 	if (os_strcmp(var, "password") == 0) {
-		os_free(cred->password);
+		str_clear_free(cred->password);
 		cred->password = val;
 		cred->ext_password = 0;
 		return 0;
@@ -2628,7 +2649,7 @@
 	}
 
 	if (os_strcmp(var, "private_key_passwd") == 0) {
-		os_free(cred->private_key_passwd);
+		str_clear_free(cred->private_key_passwd);
 		cred->private_key_passwd = val;
 		return 0;
 	}
@@ -2640,7 +2661,7 @@
 	}
 
 	if (os_strcmp(var, "milenage") == 0) {
-		os_free(cred->milenage);
+		str_clear_free(cred->milenage);
 		cred->milenage = val;
 		return 0;
 	}
@@ -2808,7 +2829,7 @@
 }
 
 
-char * alloc_int_str(int val)
+static char * alloc_int_str(int val)
 {
 	char *buf;
 
@@ -2820,7 +2841,7 @@
 }
 
 
-char * alloc_strdup(const char *str)
+static char * alloc_strdup(const char *str)
 {
 	if (str == NULL)
 		return NULL;
@@ -3192,7 +3213,7 @@
 {
 	if (blob) {
 		os_free(blob->name);
-		os_free(blob->data);
+		bin_clear_free(blob->data, blob->len);
 		os_free(blob);
 	}
 }
@@ -3256,6 +3277,7 @@
 	config->p2p_go_intent = DEFAULT_P2P_GO_INTENT;
 	config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
 	config->p2p_go_max_inactivity = DEFAULT_P2P_GO_MAX_INACTIVITY;
+	config->p2p_optimize_listen_chan = DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN;
 	config->bss_max_count = DEFAULT_BSS_MAX_COUNT;
 	config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
 	config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
@@ -3266,6 +3288,8 @@
 	config->wmm_ac_params[1] = ac_bk;
 	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);
@@ -3834,9 +3858,12 @@
 	{ INT_RANGE(persistent_reconnect, 0, 1), 0 },
 	{ INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS },
 	{ INT(p2p_group_idle), 0 },
+	{ INT_RANGE(p2p_passphrase_len, 8, 63),
+	  CFG_CHANGED_P2P_PASSPHRASE_LEN },
 	{ FUNC(p2p_pref_chan), CFG_CHANGED_P2P_PREF_CHAN },
 	{ FUNC(p2p_no_go_freq), CFG_CHANGED_P2P_PREF_CHAN },
 	{ INT_RANGE(p2p_add_cli_chan, 0, 1), 0 },
+	{ INT_RANGE(p2p_optimize_listen_chan, 0, 1), 0 },
 	{ INT(p2p_go_ht40), 0 },
 	{ INT(p2p_go_vht), 0 },
 	{ INT(p2p_disabled), 0 },
@@ -3884,6 +3911,10 @@
 	{ INT(tdls_external_control), 0},
 	{ 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

Modified: wpa/trunk/wpa_supplicant/config.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/config.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/config.h	(original)
+++ wpa/trunk/wpa_supplicant/config.h	Tue Oct 14 12:39:25 2014
@@ -19,12 +19,15 @@
 #define DEFAULT_P2P_GO_INTENT 7
 #define DEFAULT_P2P_INTRA_BSS 1
 #define DEFAULT_P2P_GO_MAX_INACTIVITY (5 * 60)
+#define DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN 0
 #define DEFAULT_BSS_MAX_COUNT 200
 #define DEFAULT_BSS_EXPIRATION_AGE 180
 #define DEFAULT_BSS_EXPIRATION_SCAN_COUNT 2
 #define DEFAULT_MAX_NUM_STA 128
 #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"
@@ -315,6 +318,7 @@
 #define CFG_CHANGED_P2P_PREF_CHAN BIT(13)
 #define CFG_CHANGED_EXT_PW_BACKEND BIT(14)
 #define CFG_CHANGED_NFC_PASSWORD_TOKEN BIT(15)
+#define CFG_CHANGED_P2P_PASSPHRASE_LEN BIT(16)
 
 /**
  * struct wpa_config - wpa_supplicant configuration data
@@ -685,6 +689,7 @@
 	struct wpa_freq_range_list p2p_no_go_freq;
 	int p2p_add_cli_chan;
 	int p2p_ignore_shared_freq;
+	int p2p_optimize_listen_chan;
 
 	struct wpabuf *wps_vendor_ext_m1;
 
@@ -713,6 +718,14 @@
 	int p2p_group_idle;
 
 	/**
+	 * p2p_passphrase_len - Passphrase length (8..63) for P2P GO
+	 *
+	 * This parameter controls the length of the random passphrase that is
+	 * generated at the GO.
+	 */
+	unsigned int p2p_passphrase_len;
+
+	/**
 	 * bss_max_count - Maximum number of BSS entries to keep in memory
 	 */
 	unsigned int bss_max_count;
@@ -1029,6 +1042,43 @@
 	 * If set, these wowlan triggers will be configured.
 	 */
 	char *wowlan_triggers;
+
+	/**
+	 * p2p_search_delay - Extra delay between concurrent search iterations
+	 *
+	 * Add extra delay (in milliseconds) between search iterations when
+	 * there is a concurrent operation to make p2p_find friendlier to
+	 * concurrent operations by avoiding it from taking 100% of radio
+	 * 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;
 };
 
 

Modified: wpa/trunk/wpa_supplicant/config_file.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/config_file.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/config_file.c	(original)
+++ wpa/trunk/wpa_supplicant/config_file.c	Tue Oct 14 12:39:25 2014
@@ -739,6 +739,10 @@
 #ifdef CONFIG_MACSEC
 	INT(macsec_policy);
 #endif /* CONFIG_MACSEC */
+#ifdef CONFIG_HS20
+	INT(update_identifier);
+#endif /* CONFIG_HS20 */
+	write_int(f, "mac_addr", ssid->mac_addr, -1);
 
 #undef STR
 #undef INT
@@ -790,7 +794,8 @@
 		const char *name;
 		name = eap_get_name(cred->eap_method[0].vendor,
 				    cred->eap_method[0].method);
-		fprintf(f, "\teap=%s\n", name);
+		if (name)
+			fprintf(f, "\teap=%s\n", name);
 	}
 	if (cred->phase1)
 		fprintf(f, "\tphase1=\"%s\"\n", cred->phase1);
@@ -1015,6 +1020,9 @@
 		fprintf(f, "p2p_intra_bss=%u\n", config->p2p_intra_bss);
 	if (config->p2p_group_idle)
 		fprintf(f, "p2p_group_idle=%u\n", config->p2p_group_idle);
+	if (config->p2p_passphrase_len)
+		fprintf(f, "p2p_passphrase_len=%u\n",
+			config->p2p_passphrase_len);
 	if (config->p2p_pref_chan) {
 		unsigned int i;
 		fprintf(f, "p2p_pref_chan=");
@@ -1034,6 +1042,10 @@
 	}
 	if (config->p2p_add_cli_chan)
 		fprintf(f, "p2p_add_cli_chan=%d\n", config->p2p_add_cli_chan);
+	if (config->p2p_optimize_listen_chan !=
+	    DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN)
+		fprintf(f, "p2p_optimize_listen_chan=%d\n",
+			config->p2p_optimize_listen_chan);
 	if (config->p2p_go_ht40)
 		fprintf(f, "p2p_go_ht40=%u\n", config->p2p_go_ht40);
 	if (config->p2p_go_vht)
@@ -1159,11 +1171,25 @@
 			config->tdls_external_control);
 
 	if (config->wowlan_triggers)
-		fprintf(f, "wowlan_triggers=\"%s\"\n",
+		fprintf(f, "wowlan_triggers=%s\n",
 			config->wowlan_triggers);
 
 	if (config->bgscan)
 		fprintf(f, "bgscan=\"%s\"\n", config->bgscan);
+
+	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 */

Modified: wpa/trunk/wpa_supplicant/config_ssid.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/config_ssid.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/config_ssid.h	(original)
+++ wpa/trunk/wpa_supplicant/config_ssid.h	Tue Oct 14 12:39:25 2014
@@ -647,6 +647,25 @@
 	 */
 	int macsec_policy;
 #endif /* CONFIG_MACSEC */
+
+#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 */

Modified: wpa/trunk/wpa_supplicant/config_winreg.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/config_winreg.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/config_winreg.c	(original)
+++ wpa/trunk/wpa_supplicant/config_winreg.c	Tue Oct 14 12:39:25 2014
@@ -930,6 +930,9 @@
 		  MGMT_FRAME_PROTECTION_DEFAULT);
 #endif /* CONFIG_IEEE80211W */
 	STR(id_str);
+#ifdef CONFIG_HS20
+	INT(update_identifier);
+#endif /* CONFIG_HS20 */
 
 #undef STR
 #undef INT

Modified: wpa/trunk/wpa_supplicant/ctrl_iface.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/ctrl_iface.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/ctrl_iface.c	(original)
+++ wpa/trunk/wpa_supplicant/ctrl_iface.c	Tue Oct 14 12:39:25 2014
@@ -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);
@@ -584,6 +585,13 @@
 	u8 peer[ETH_ALEN];
 	int ret;
 
+	if (os_strcmp(addr, "*") == 0) {
+		/* remove everyone */
+		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
+		wpa_tdls_teardown_peers(wpa_s->wpa);
+		return 0;
+	}
+
 	if (hwaddr_aton(addr, peer)) {
 		wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
 			   "address '%s'", addr);
@@ -1529,6 +1537,11 @@
 		struct wpa_ssid *ssid = wpa_s->current_ssid;
 		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
 				  MAC2STR(wpa_s->bssid));
+		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;
@@ -1761,22 +1774,29 @@
 #endif /* CONFIG_WPS */
 
 #ifdef ANDROID
-	wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
-		     "id=%d state=%d BSSID=" MACSTR " SSID=%s",
-		     wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
-		     wpa_s->wpa_state,
-		     MAC2STR(wpa_s->bssid),
-		     wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
-		     wpa_ssid_txt(wpa_s->current_ssid->ssid,
-				  wpa_s->current_ssid->ssid_len) : "");
-	if (wpa_s->wpa_state == WPA_COMPLETED) {
-		struct wpa_ssid *ssid = wpa_s->current_ssid;
-		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
-			     "- connection to " MACSTR
-			     " completed %s [id=%d id_str=%s]",
-			     MAC2STR(wpa_s->bssid), "(auth)",
-			     ssid ? ssid->id : -1,
-			     ssid && ssid->id_str ? ssid->id_str : "");
+	/*
+	 * Allow using the STATUS command with default behavior, say for debug,
+	 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
+	 * events with STATUS-NO_EVENTS.
+	 */
+	if (os_strcmp(params, "-NO_EVENTS")) {
+		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
+			     "id=%d state=%d BSSID=" MACSTR " SSID=%s",
+			     wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
+			     wpa_s->wpa_state,
+			     MAC2STR(wpa_s->bssid),
+			     wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
+			     wpa_ssid_txt(wpa_s->current_ssid->ssid,
+					  wpa_s->current_ssid->ssid_len) : "");
+		if (wpa_s->wpa_state == WPA_COMPLETED) {
+			struct wpa_ssid *ssid = wpa_s->current_ssid;
+			wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
+				     "- connection to " MACSTR
+				     " completed %s [id=%d id_str=%s]",
+				     MAC2STR(wpa_s->bssid), "(auth)",
+				     ssid ? ssid->id : -1,
+				     ssid && ssid->id_str ? ssid->id_str : "");
+		}
 	}
 #endif /* ANDROID */
 
@@ -2465,6 +2485,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);
 		}
@@ -2482,6 +2504,9 @@
 			   "id=%d", id);
 		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
@@ -2557,9 +2582,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, ' ');
@@ -2585,8 +2611,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;
 }
 
 
@@ -4708,6 +4741,22 @@
 		return pos - buf;
 	pos += res;
 
+	if (info->vendor_elems) {
+		res = os_snprintf(pos, end - pos, "vendor_elems=");
+		if (res < 0 || res >= end - pos)
+			return pos - buf;
+		pos += res;
+
+		pos += wpa_snprintf_hex(pos, end - pos,
+					wpabuf_head(info->vendor_elems),
+					wpabuf_len(info->vendor_elems));
+
+		res = os_snprintf(pos, end - pos, "\n");
+		if (res < 0 || res >= end - pos)
+			return pos - buf;
+		pos += res;
+	}
+
 	return pos - buf;
 }
 
@@ -4760,7 +4809,7 @@
 
 	if (os_strcmp(cmd, "listen_channel") == 0) {
 		return p2p_set_listen_channel(wpa_s->global->p2p, 81,
-					      atoi(param));
+					      atoi(param), 1);
 	}
 
 	if (os_strcmp(cmd, "ssid_postfix") == 0) {
@@ -5368,7 +5417,7 @@
 	if (len == 0 && cred && cred->realm)
 		return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
 
-	if (len % 1)
+	if (len & 1)
 		return -1;
 	len /= 2;
 	buf = os_malloc(len);
@@ -5515,28 +5564,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)
 {
@@ -5561,7 +5588,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;
@@ -5979,6 +6006,25 @@
 }
 
 
+static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value)
+{
+	const char *pos = value;
+
+	while (pos) {
+		if (*pos == ' ' || *pos == '\0')
+			break;
+		if (wpa_s->scan_id_count == MAX_SCAN_ID)
+			return -1;
+		wpa_s->scan_id[wpa_s->scan_id_count++] = atoi(pos);
+		pos = os_strchr(pos, ',');
+		if (pos)
+			pos++;
+	}
+
+	return 0;
+}
+
+
 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
 			   char *reply, int reply_size, int *reply_len)
 {
@@ -5992,6 +6038,7 @@
 	wpa_s->manual_scan_passive = 0;
 	wpa_s->manual_scan_use_id = 0;
 	wpa_s->manual_scan_only_new = 0;
+	wpa_s->scan_id_count = 0;
 
 	if (params) {
 		if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
@@ -6014,6 +6061,12 @@
 		pos = os_strstr(params, "only_new=1");
 		if (pos)
 			wpa_s->manual_scan_only_new = 1;
+
+		pos = os_strstr(params, "scan_id=");
+		if (pos && scan_id_list_parse(wpa_s, pos + 8) < 0) {
+			*reply_len = -1;
+			return;
+		}
 	} else {
 		os_free(wpa_s->manual_scan_freqs);
 		wpa_s->manual_scan_freqs = NULL;
@@ -6192,6 +6245,210 @@
 }
 
 #endif /* CONFIG_TESTING_OPTIONS */
+
+
+static void wpas_ctrl_vendor_elem_update(struct wpa_supplicant *wpa_s)
+{
+	unsigned int i;
+	char buf[30];
+
+	wpa_printf(MSG_DEBUG, "Update vendor elements");
+
+	for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
+		if (wpa_s->vendor_elem[i]) {
+			os_snprintf(buf, sizeof(buf), "frame[%u]", i);
+			wpa_hexdump_buf(MSG_DEBUG, buf, wpa_s->vendor_elem[i]);
+		}
+	}
+
+#ifdef CONFIG_P2P
+	if (wpa_s->parent == wpa_s &&
+	    wpa_s->global->p2p &&
+	    !wpa_s->global->p2p_disabled)
+		p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
+#endif /* CONFIG_P2P */
+}
+
+
+static struct wpa_supplicant *
+wpas_ctrl_vendor_elem_iface(struct wpa_supplicant *wpa_s,
+			    enum wpa_vendor_elem_frame frame)
+{
+	switch (frame) {
+#ifdef CONFIG_P2P
+	case VENDOR_ELEM_PROBE_REQ_P2P:
+	case VENDOR_ELEM_PROBE_RESP_P2P:
+	case VENDOR_ELEM_PROBE_RESP_P2P_GO:
+	case VENDOR_ELEM_BEACON_P2P_GO:
+	case VENDOR_ELEM_P2P_PD_REQ:
+	case VENDOR_ELEM_P2P_PD_RESP:
+	case VENDOR_ELEM_P2P_GO_NEG_REQ:
+	case VENDOR_ELEM_P2P_GO_NEG_RESP:
+	case VENDOR_ELEM_P2P_GO_NEG_CONF:
+	case VENDOR_ELEM_P2P_INV_REQ:
+	case VENDOR_ELEM_P2P_INV_RESP:
+	case VENDOR_ELEM_P2P_ASSOC_REQ:
+		return wpa_s->parent;
+#endif /* CONFIG_P2P */
+	default:
+		return wpa_s;
+	}
+}
+
+
+static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
+{
+	char *pos = cmd;
+	int frame;
+	size_t len;
+	struct wpabuf *buf;
+	struct ieee802_11_elems elems;
+
+	frame = atoi(pos);
+	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
+		return -1;
+	wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
+
+	pos = os_strchr(pos, ' ');
+	if (pos == NULL)
+		return -1;
+	pos++;
+
+	len = os_strlen(pos);
+	if (len == 0)
+		return 0;
+	if (len & 1)
+		return -1;
+	len /= 2;
+
+	buf = wpabuf_alloc(len);
+	if (buf == NULL)
+		return -1;
+
+	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
+		wpabuf_free(buf);
+		return -1;
+	}
+
+	if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
+	    ParseFailed) {
+		wpabuf_free(buf);
+		return -1;
+	}
+
+	if (wpa_s->vendor_elem[frame] == NULL) {
+		wpa_s->vendor_elem[frame] = buf;
+		wpas_ctrl_vendor_elem_update(wpa_s);
+		return 0;
+	}
+
+	if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
+		wpabuf_free(buf);
+		return -1;
+	}
+
+	wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
+	wpabuf_free(buf);
+	wpas_ctrl_vendor_elem_update(wpa_s);
+
+	return 0;
+}
+
+
+static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
+				     char *buf, size_t buflen)
+{
+	int frame = atoi(cmd);
+
+	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
+		return -1;
+	wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
+
+	if (wpa_s->vendor_elem[frame] == NULL)
+		return 0;
+
+	return wpa_snprintf_hex(buf, buflen,
+				wpabuf_head_u8(wpa_s->vendor_elem[frame]),
+				wpabuf_len(wpa_s->vendor_elem[frame]));
+}
+
+
+static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
+{
+	char *pos = cmd;
+	int frame;
+	size_t len;
+	u8 *buf;
+	struct ieee802_11_elems elems;
+	u8 *ie, *end;
+
+	frame = atoi(pos);
+	if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
+		return -1;
+	wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
+
+	pos = os_strchr(pos, ' ');
+	if (pos == NULL)
+		return -1;
+	pos++;
+
+	if (*pos == '*') {
+		wpabuf_free(wpa_s->vendor_elem[frame]);
+		wpa_s->vendor_elem[frame] = NULL;
+		wpas_ctrl_vendor_elem_update(wpa_s);
+		return 0;
+	}
+
+	if (wpa_s->vendor_elem[frame] == NULL)
+		return -1;
+
+	len = os_strlen(pos);
+	if (len == 0)
+		return 0;
+	if (len & 1)
+		return -1;
+	len /= 2;
+
+	buf = os_malloc(len);
+	if (buf == NULL)
+		return -1;
+
+	if (hexstr2bin(pos, buf, len) < 0) {
+		os_free(buf);
+		return -1;
+	}
+
+	if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
+		os_free(buf);
+		return -1;
+	}
+
+	ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
+	end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
+
+	for (; ie + 1 < end; ie += 2 + ie[1]) {
+		if (ie + len > end)
+			break;
+		if (os_memcmp(ie, buf, len) != 0)
+			continue;
+
+		if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
+			wpabuf_free(wpa_s->vendor_elem[frame]);
+			wpa_s->vendor_elem[frame] = NULL;
+		} else {
+			os_memmove(ie, ie + len,
+				   end - (ie + len));
+			wpa_s->vendor_elem[frame]->used -= len;
+		}
+		os_free(buf);
+		wpas_ctrl_vendor_elem_update(wpa_s);
+		return 0;
+	}
+
+	os_free(buf);
+
+	return -1;
+}
 
 
 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
@@ -6260,6 +6517,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;
@@ -6759,6 +7018,15 @@
 		if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
 			reply_len = -1;
 #endif /* CONFIG_TESTING_OPTIONS */
+	} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
+		if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
+			reply_len = -1;
+	} else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
+		reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
+						      reply_size);
+	} else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
+		if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
+			reply_len = -1;
 	} else {
 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;

Modified: wpa/trunk/wpa_supplicant/ctrl_iface_unix.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/ctrl_iface_unix.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/ctrl_iface_unix.c	(original)
+++ wpa/trunk/wpa_supplicant/ctrl_iface_unix.c	Tue Oct 14 12:39:25 2014
@@ -990,7 +990,13 @@
 			goto fail;
 		}
 	} else {
-		chmod(ctrl, S_IRWXU);
+		if (chmod(ctrl, S_IRWXU) < 0) {
+			wpa_printf(MSG_DEBUG,
+				   "chmod[global_ctrl_interface=%s](S_IRWXU): %s",
+				   ctrl, strerror(errno));
+			/* continue anyway since group change was not required
+			 */
+		}
 	}
 
 havesock:

Modified: wpa/trunk/wpa_supplicant/dbus/dbus_dict_helpers.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/dbus/dbus_dict_helpers.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/dbus/dbus_dict_helpers.c	(original)
+++ wpa/trunk/wpa_supplicant/dbus/dbus_dict_helpers.c	Tue Oct 14 12:39:25 2014
@@ -881,6 +881,8 @@
 		}
 
 		dbus_message_iter_recurse(iter, &iter_array);
+		os_memset(&tmpentry, 0, sizeof(tmpentry));
+		tmpentry.type = DBUS_TYPE_ARRAY;
 		if (_wpa_dbus_dict_entry_get_byte_array(&iter_array, &tmpentry)
 					== FALSE)
 			goto cleanup;
@@ -932,6 +934,7 @@
 		break;
 	case DBUS_TYPE_ARRAY:
 		success = _wpa_dbus_dict_entry_get_binarray(&iter_array, entry);
+		break;
 	default:
 		break;
 	}

Modified: wpa/trunk/wpa_supplicant/dbus/dbus_new.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/dbus/dbus_new.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/dbus/dbus_new.c	(original)
+++ wpa/trunk/wpa_supplicant/dbus/dbus_new.c	Tue Oct 14 12:39:25 2014
@@ -24,6 +24,7 @@
 #include "dbus_common_i.h"
 #include "dbus_new_handlers_p2p.h"
 #include "p2p/p2p.h"
+#include "../p2p_supplicant.h"
 
 #ifdef CONFIG_AP /* until needed by something else */
 
@@ -945,37 +946,49 @@
 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
 					const char *role)
 {
-
+	int error = 1;
 	DBusMessage *msg;
-	DBusMessageIter iter;
+	DBusMessageIter iter, dict_iter;
 	struct wpas_dbus_priv *iface = wpa_s->global->dbus;
-	char *ifname = wpa_s->ifname;
 
 	/* Do nothing if the control interface is not turned on */
 	if (iface == NULL)
 		return;
 
-	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+	if (!wpa_s->dbus_groupobj_path)
+		return;
+
+	msg = dbus_message_new_signal(wpa_s->parent->dbus_new_path,
 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
 				      "GroupFinished");
 	if (msg == NULL)
 		return;
 
 	dbus_message_iter_init_append(msg, &iter);
-
-	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname)) {
-		wpa_printf(MSG_ERROR, "dbus: Failed to construct GroupFinished"
-				      "signal -not enough memory for ifname ");
-		goto err;
-	}
-
-	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &role))
-		wpa_printf(MSG_ERROR, "dbus: Failed to construct GroupFinished"
-				      "signal -not enough memory for role ");
-	else
-		dbus_connection_send(iface->con, msg, NULL);
-
-err:
+	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
+		goto nomem;
+
+	if (!wpa_dbus_dict_append_object_path(&dict_iter,
+					      "interface_object",
+					      wpa_s->dbus_new_path))
+		goto nomem;
+
+	if (!wpa_dbus_dict_append_string(&dict_iter, "role", role))
+		goto nomem;
+
+	if (!wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
+					      wpa_s->dbus_groupobj_path) ||
+	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
+		goto nomem;
+
+	error = 0;
+	dbus_connection_send(iface->con, msg, NULL);
+
+nomem:
+	if (error > 0)
+		wpa_printf(MSG_ERROR,
+			   "dbus: Failed to construct GroupFinished");
+
 	dbus_message_unref(msg);
 }
 
@@ -1151,6 +1164,69 @@
 }
 
 
+struct group_changed_data {
+	struct wpa_supplicant *wpa_s;
+	struct p2p_peer_info *info;
+};
+
+
+static int match_group_where_peer_is_client(struct p2p_group *group,
+					    void *user_data)
+{
+	struct group_changed_data *data = user_data;
+	const struct p2p_group_config *cfg;
+	struct wpa_supplicant *wpa_s_go;
+
+	if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
+		return 1;
+
+	cfg = p2p_group_get_config(group);
+
+	wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
+					 cfg->ssid_len);
+	if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
+		wpas_dbus_signal_peer_groups_changed(
+			data->wpa_s->parent, data->info->p2p_device_addr);
+		return 0;
+	}
+
+	return 1;
+}
+
+
+static void signal_peer_groups_changed(struct p2p_peer_info *info,
+				       void *user_data)
+{
+	struct group_changed_data *data = user_data;
+	struct wpa_supplicant *wpa_s_go;
+
+	wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s,
+					     info->p2p_device_addr);
+	if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
+		wpas_dbus_signal_peer_groups_changed(data->wpa_s->parent,
+						     info->p2p_device_addr);
+		return;
+	}
+
+	data->info = info;
+	p2p_loop_on_all_groups(data->wpa_s->global->p2p,
+			       match_group_where_peer_is_client, data);
+	data->info = NULL;
+}
+
+
+static void peer_groups_changed(struct wpa_supplicant *wpa_s)
+{
+	struct group_changed_data data;
+
+	os_memset(&data, 0, sizeof(data));
+	data.wpa_s = wpa_s;
+
+	p2p_loop_on_known_peers(wpa_s->global->p2p,
+				signal_peer_groups_changed, &data);
+}
+
+
 /**
  * wpas_dbus_signal_p2p_group_started - Signals P2P group has
  * started. Emitted when a group is successfully started
@@ -1210,6 +1286,9 @@
 		goto nomem;
 
 	dbus_connection_send(iface->con, msg, NULL);
+
+	if (client)
+		peer_groups_changed(wpa_s);
 
 nomem:
 	dbus_message_unref(msg);
@@ -1398,15 +1477,15 @@
  * constructed using p2p i/f addr used for connecting.
  *
  * @wpa_s: %wpa_supplicant network interface data
- * @member_addr: addr (p2p i/f) of the peer joining the group
+ * @peer_addr: P2P Device Address of the peer joining the group
  */
 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
-				      const u8 *member)
+				      const u8 *peer_addr)
 {
 	struct wpas_dbus_priv *iface;
 	DBusMessage *msg;
 	DBusMessageIter iter;
-	char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
 
 	iface = wpa_s->global->dbus;
 
@@ -1417,10 +1496,10 @@
 	if (!wpa_s->dbus_groupobj_path)
 		return;
 
-	os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-			"%s/"  WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/"
+	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
 			COMPACT_MACSTR,
-			wpa_s->dbus_groupobj_path, MAC2STR(member));
+			wpa_s->parent->dbus_new_path, MAC2STR(peer_addr));
 
 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
@@ -1429,14 +1508,16 @@
 		return;
 
 	dbus_message_iter_init_append(msg, &iter);
-	path = groupmember_obj_path;
+	path = peer_obj_path;
 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
 					    &path))
 		goto err;
 
 	dbus_connection_send(iface->con, msg, NULL);
-
 	dbus_message_unref(msg);
+
+	wpas_dbus_signal_peer_groups_changed(wpa_s->parent, peer_addr);
+
 	return;
 
 err:
@@ -1449,18 +1530,18 @@
  *
  * Method to emit a signal for a peer disconnecting the group.
  * The signal will carry path to the group member object
- * constructed using p2p i/f addr used for connecting.
+ * constructed using the P2P Device Address of the peer.
  *
  * @wpa_s: %wpa_supplicant network interface data
- * @member_addr: addr (p2p i/f) of the peer joining the group
+ * @peer_addr: P2P Device Address of the peer joining the group
  */
 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
-				      const u8 *member)
+					    const u8 *peer_addr)
 {
 	struct wpas_dbus_priv *iface;
 	DBusMessage *msg;
 	DBusMessageIter iter;
-	char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
 
 	iface = wpa_s->global->dbus;
 
@@ -1471,10 +1552,10 @@
 	if (!wpa_s->dbus_groupobj_path)
 		return;
 
-	os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-			"%s/"  WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/"
+	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
 			COMPACT_MACSTR,
-			wpa_s->dbus_groupobj_path, MAC2STR(member));
+			wpa_s->dbus_groupobj_path, MAC2STR(peer_addr));
 
 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
@@ -1483,14 +1564,16 @@
 		return;
 
 	dbus_message_iter_init_append(msg, &iter);
-	path = groupmember_obj_path;
+	path = peer_obj_path;
 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
 					    &path))
 		goto err;
 
 	dbus_connection_send(iface->con, msg, NULL);
-
 	dbus_message_unref(msg);
+
+	wpas_dbus_signal_peer_groups_changed(wpa_s->parent, peer_addr);
+
 	return;
 
 err:
@@ -1877,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);
@@ -2011,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 }
 };
 
@@ -2301,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 }
 };
 
@@ -2435,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,
 	  {
@@ -2857,6 +2960,10 @@
 	{ "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
 	  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
@@ -3069,8 +3176,7 @@
 	},
 	{ "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
 	  {
-		  { "ifname", "s", ARG_OUT },
-		  { "role", "s", ARG_OUT },
+		  { "properties", "a{sv}", ARG_OUT },
 		  END_ARGS
 	  }
 	},
@@ -3271,11 +3377,21 @@
 	  wpas_dbus_getter_p2p_peer_device_address,
 	  NULL
 	},
+	{ "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
+	  wpas_dbus_getter_p2p_peer_groups,
+	  NULL
+	},
 	{ NULL, NULL, NULL, NULL, NULL }
 };
 
 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
-
+	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
+	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
+	  {
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
 	{ NULL, NULL, { END_ARGS } }
 };
 
@@ -3459,6 +3575,20 @@
 }
 
 
+void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
+					  const u8 *dev_addr)
+{
+	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+
+	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
+		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
+
+	wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
+				       WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
+}
+
+
 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
 	{ "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
 	  wpas_dbus_getter_p2p_group_members,
@@ -3604,6 +3734,8 @@
 		return;
 	}
 
+	peer_groups_changed(wpa_s);
+
 	wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
 		   wpa_s->dbus_groupobj_path);
 
@@ -3613,109 +3745,6 @@
 	os_free(wpa_s->dbus_groupobj_path);
 	wpa_s->dbus_groupobj_path = NULL;
 }
-
-static const struct wpa_dbus_property_desc
-wpas_dbus_p2p_groupmember_properties[] = {
-	{ NULL, NULL, NULL, NULL, NULL }
-};
-
-/**
- * wpas_dbus_register_p2p_groupmember - Register a p2p groupmember
- * object with dbus
- * @wpa_s: wpa_supplicant interface structure
- * @p2p_if_addr: i/f addr of the device joining this group
- *
- * Registers p2p groupmember representing object with dbus
- */
-void wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
-					const u8 *p2p_if_addr)
-{
-	struct wpas_dbus_priv *ctrl_iface;
-	struct wpa_dbus_object_desc *obj_desc = NULL;
-	struct groupmember_handler_args *arg;
-	char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
-
-	/* Do nothing if the control interface is not turned on */
-	if (wpa_s == NULL || wpa_s->global == NULL)
-		return;
-
-	ctrl_iface = wpa_s->global->dbus;
-	if (ctrl_iface == NULL)
-		return;
-
-	if (!wpa_s->dbus_groupobj_path)
-		return;
-
-	os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-		"%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
-		wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
-
-	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
-	if (!obj_desc) {
-		wpa_printf(MSG_ERROR, "Not enough memory "
-			   "to create object description");
-		goto err;
-	}
-
-	/* allocate memory for handlers arguments */
-	arg = os_zalloc(sizeof(struct groupmember_handler_args));
-	if (!arg) {
-		wpa_printf(MSG_ERROR, "Not enough memory "
-			   "to create arguments for method");
-		goto err;
-	}
-
-	arg->wpa_s = wpa_s;
-	os_memcpy(arg->member_addr, p2p_if_addr, ETH_ALEN);
-
-	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
-			   wpas_dbus_p2p_groupmember_properties, NULL);
-
-	if (wpa_dbus_register_object_per_iface(ctrl_iface, groupmember_obj_path,
-					       wpa_s->ifname, obj_desc))
-		goto err;
-
-	wpa_printf(MSG_INFO,
-		   "dbus: Registered group member object '%s' successfully",
-		   groupmember_obj_path);
-	return;
-
-err:
-	free_dbus_object_desc(obj_desc);
-}
-
-/**
- * wpas_dbus_unregister_p2p_groupmember - Unregister a p2p groupmember
- * object with dbus
- * @wpa_s: wpa_supplicant interface structure
- * @p2p_if_addr: i/f addr of the device joining this group
- *
- * Unregisters p2p groupmember representing object with dbus
- */
-void wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
-					  const u8 *p2p_if_addr)
-{
-	struct wpas_dbus_priv *ctrl_iface;
-	char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
-
-	/* Do nothing if the control interface is not turned on */
-	if (wpa_s == NULL || wpa_s->global == NULL)
-		return;
-
-	ctrl_iface = wpa_s->global->dbus;
-	if (ctrl_iface == NULL)
-		return;
-
-	if (!wpa_s->dbus_groupobj_path)
-		return;
-
-	os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-		"%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
-		wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
-
-	wpa_dbus_unregister_object_per_iface(ctrl_iface, groupmember_obj_path);
-}
-
 
 static const struct wpa_dbus_property_desc
 	wpas_dbus_persistent_group_properties[] = {

Modified: wpa/trunk/wpa_supplicant/dbus/dbus_new.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/dbus/dbus_new.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/dbus/dbus_new.h	(original)
+++ wpa/trunk/wpa_supplicant/dbus/dbus_new.h	Tue Oct 14 12:39:25 2014
@@ -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
@@ -78,10 +79,6 @@
 
 #define WPAS_DBUS_NEW_P2P_PEERS_PART	"Peers"
 #define	WPAS_DBUS_NEW_IFACE_P2P_PEER WPAS_DBUS_NEW_INTERFACE ".Peer"
-
-#define WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART	"Members"
-#define	WPAS_DBUS_NEW_IFACE_P2P_GROUPMEMBER \
-	WPAS_DBUS_NEW_INTERFACE ".GroupMember"
 
 /* Top-level Errors */
 #define WPAS_DBUS_ERROR_UNKNOWN_ERROR \
@@ -177,6 +174,8 @@
 				  const u8 *dev_addr);
 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
 					   const u8 *dev_addr);
+void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
+					  const u8 *dev_addr);
 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
 					const char *role);
 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
@@ -201,10 +200,6 @@
 					  int nid);
 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
 					    int status, const u8 *bssid);
-void wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
-					const u8 *p2p_if_addr);
-void wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
-					  const u8 *p2p_if_addr);
 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
 					    const u8 *member);
 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
@@ -360,6 +355,12 @@
 }
 
 static inline void
+wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
+				     const u8 *dev_addr)
+{
+}
+
+static inline void
 wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
 				   const char *role)
 {

Modified: wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers.c	(original)
+++ wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers.c	Tue Oct 14 12:39:25 2014
@@ -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
@@ -271,6 +272,7 @@
 			wpa_config_update_prio_list(wpa_s->conf);
 
 		os_free(value);
+		value = NULL;
 		wpa_dbus_dict_entry_clear(&entry);
 	}
 
@@ -439,8 +441,13 @@
 	}
 
 	for (i = 0; i < array_len; i++) {
-		dbus_message_iter_append_basic(&array_iter, type,
-					       array + i * element_size);
+		if (!dbus_message_iter_append_basic(&array_iter, type,
+						    array + i * element_size)) {
+			dbus_set_error(error, DBUS_ERROR_FAILED,
+				       "%s: failed to construct message 2.5",
+				       __func__);
+			return FALSE;
+		}
 	}
 
 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
@@ -506,7 +513,7 @@
 		return FALSE;
 	}
 
-	for (i = 0; i < array_len; i++) {
+	for (i = 0; i < array_len && array[i]; i++) {
 		wpa_dbus_dict_bin_array_add_element(&array_iter,
 						    wpabuf_head(array[i]),
 						    wpabuf_len(array[i]));
@@ -561,24 +568,28 @@
 			goto error;
 		if (!os_strcmp(entry.key, "Driver") &&
 		    (entry.type == DBUS_TYPE_STRING)) {
+			os_free(driver);
 			driver = os_strdup(entry.str_value);
 			wpa_dbus_dict_entry_clear(&entry);
 			if (driver == NULL)
 				goto error;
 		} else if (!os_strcmp(entry.key, "Ifname") &&
 			   (entry.type == DBUS_TYPE_STRING)) {
+			os_free(ifname);
 			ifname = os_strdup(entry.str_value);
 			wpa_dbus_dict_entry_clear(&entry);
 			if (ifname == NULL)
 				goto error;
 		} else if (!os_strcmp(entry.key, "ConfigFile") &&
 			   (entry.type == DBUS_TYPE_STRING)) {
+			os_free(confname);
 			confname = os_strdup(entry.str_value);
 			wpa_dbus_dict_entry_clear(&entry);
 			if (confname == NULL)
 				goto error;
 		} else if (!os_strcmp(entry.key, "BridgeIfname") &&
 			   (entry.type == DBUS_TYPE_STRING)) {
+			os_free(bridge_ifname);
 			bridge_ifname = os_strdup(entry.str_value);
 			wpa_dbus_dict_entry_clear(&entry);
 			if (bridge_ifname == NULL)
@@ -1391,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
@@ -3945,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

Modified: wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers.h	(original)
+++ wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers.h	Tue Oct 14 12:39:25 2014
@@ -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);
 
@@ -291,6 +297,14 @@
 dbus_bool_t wpas_dbus_setter_process_credentials(DBusMessageIter *iter,
 						 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);

Modified: wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_p2p.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_p2p.c	(original)
+++ wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_p2p.c	Tue Oct 14 12:39:25 2014
@@ -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.
@@ -830,6 +831,11 @@
 				       wpa_s->conf->p2p_no_group_iface))
 		goto err_no_mem;
 
+	/* P2P Search Delay */
+	if (!wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
+					 wpa_s->conf->p2p_search_delay))
+		goto err_no_mem;
+
 	if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
 	    !dbus_message_iter_close_container(iter, &variant_iter))
 		goto err_no_mem;
@@ -982,6 +988,9 @@
 		else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
 			 entry.type == DBUS_TYPE_BOOLEAN)
 			wpa_s->conf->p2p_no_group_iface = entry.bool_value;
+		else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
+			 entry.type == DBUS_TYPE_UINT32)
+			wpa_s->conf->p2p_search_delay = entry.uint32_value;
 		else
 			goto error;
 
@@ -1135,6 +1144,7 @@
 		break;
 	default:
 		str = "device";
+		break;
 	}
 
 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
@@ -1446,7 +1456,7 @@
 						       void *user_data)
 {
 	struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
-	int i, num;
+	unsigned int i, num = 0;
 	struct peer_handler_args *peer_args = user_data;
 	const struct p2p_peer_info *info;
 
@@ -1459,7 +1469,8 @@
 	}
 
 	/* Add WPS vendor extensions attribute */
-	for (i = 0, num = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
+	os_memset(vendor_extension, 0, sizeof(vendor_extension));
+	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
 		if (info->wps_vendor_ext[i] == NULL)
 			continue;
 		vendor_extension[num] = info->wps_vendor_ext[i];
@@ -1518,6 +1529,106 @@
 	return wpas_dbus_simple_array_property_getter(
 		iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
 		ETH_ALEN, error);
+}
+
+
+struct peer_group_data {
+	struct wpa_supplicant *wpa_s;
+	const struct p2p_peer_info *info;
+	char **paths;
+	unsigned int nb_paths;
+	int error;
+};
+
+
+static int match_group_where_peer_is_client(struct p2p_group *group,
+					    void *user_data)
+{
+	struct peer_group_data *data = user_data;
+	const struct p2p_group_config *cfg;
+	struct wpa_supplicant *wpa_s_go;
+	char **paths;
+
+	if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
+		return 1;
+
+	cfg = p2p_group_get_config(group);
+
+	wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
+					 cfg->ssid_len);
+	if (wpa_s_go == NULL)
+		return 1;
+
+	paths = os_realloc_array(data->paths, data->nb_paths + 1,
+				 sizeof(char *));
+	if (paths == NULL)
+		goto out_of_memory;
+
+	data->paths = paths;
+	data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
+	data->nb_paths++;
+
+	return 1;
+
+out_of_memory:
+	data->error = ENOMEM;
+	return 0;
+}
+
+
+dbus_bool_t wpas_dbus_getter_p2p_peer_groups(DBusMessageIter *iter,
+					     DBusError *error,
+					     void *user_data)
+{
+	struct peer_handler_args *peer_args = user_data;
+	const struct p2p_peer_info *info;
+	struct peer_group_data data;
+	struct wpa_supplicant *wpa_s_go;
+	dbus_bool_t success = FALSE;
+
+	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+				  peer_args->p2p_device_addr, 0);
+	if (info == NULL) {
+		dbus_set_error(error, DBUS_ERROR_FAILED,
+			       "failed to find peer");
+		return FALSE;
+	}
+
+	os_memset(&data, 0, sizeof(data));
+	wpa_s_go = wpas_get_p2p_client_iface(peer_args->wpa_s,
+					     info->p2p_device_addr);
+	if (wpa_s_go) {
+		data.paths = os_calloc(1, sizeof(char *));
+		if (data.paths == NULL)
+			goto out_of_memory;
+		data.paths[0] = wpa_s_go->dbus_groupobj_path;
+		data.nb_paths = 1;
+	}
+
+	data.wpa_s = peer_args->wpa_s;
+	data.info = info;
+
+	p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
+			       match_group_where_peer_is_client, &data);
+	if (data.error)
+		goto out_of_memory;
+
+	if (data.paths == NULL) {
+		return wpas_dbus_simple_array_property_getter(
+			iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
+	}
+
+	success = wpas_dbus_simple_array_property_getter(iter,
+							 DBUS_TYPE_OBJECT_PATH,
+							 data.paths,
+							 data.nb_paths, error);
+	goto out;
+
+out_of_memory:
+	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
+out:
+	os_free(data.paths);
+	return success;
 }
 
 
@@ -1870,9 +1981,9 @@
 		if (!paths[i])
 			goto out_of_memory;
 		os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
-			    "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART
+			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
 			    "/" COMPACT_MACSTR,
-			    wpa_s->dbus_groupobj_path, MAC2STR(addr));
+			    wpa_s->parent->dbus_new_path, MAC2STR(addr));
 		i++;
 	}
 
@@ -2006,8 +2117,9 @@
 	struct wpa_supplicant *wpa_s = user_data;
 	struct hostapd_data *hapd;
 	struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
-	int num_vendor_ext = 0;
-	int i;
+	unsigned int i, num_vendor_ext = 0;
+
+	os_memset(vendor_ext, 0, sizeof(vendor_ext));
 
 	/* Verify correct role for this property */
 	if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
@@ -2018,11 +2130,9 @@
 		/* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
 		for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
 			if (hapd->conf->wps_vendor_ext[i] == NULL)
-				vendor_ext[i] = NULL;
-			else {
-				vendor_ext[num_vendor_ext++] =
-					hapd->conf->wps_vendor_ext[i];
-			}
+				continue;
+			vendor_ext[num_vendor_ext++] =
+				hapd->conf->wps_vendor_ext[i];
 		}
 	}
 
@@ -2031,7 +2141,7 @@
 							    DBUS_TYPE_BYTE,
 							    vendor_ext,
 							    num_vendor_ext,
-						 error);
+							    error);
 }
 
 
@@ -2480,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 */

Modified: wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_p2p.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_p2p.h	(original)
+++ wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_p2p.h	Tue Oct 14 12:39:25 2014
@@ -14,11 +14,6 @@
 	u8 p2p_device_addr[ETH_ALEN];
 };
 
-struct groupmember_handler_args {
-	struct wpa_supplicant *wpa_s;
-	u8 member_addr[ETH_ALEN];
-};
-
 /*
  * P2P Device methods
  */
@@ -151,6 +146,10 @@
 						     DBusError *error,
 						     void *user_data);
 
+dbus_bool_t wpas_dbus_getter_p2p_peer_groups(DBusMessageIter *iter,
+					     DBusError *error,
+					     void *user_data);
+
 /*
  * P2P Group properties
  */
@@ -211,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 */

Modified: wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_wps.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_wps.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_wps.c	(original)
+++ wpa/trunk/wpa_supplicant/dbus/dbus_new_handlers_wps.c	Tue Oct 14 12:39:25 2014
@@ -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;
+}

Modified: wpa/trunk/wpa_supplicant/dbus/dbus_new_helpers.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/dbus/dbus_new_helpers.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/dbus/dbus_new_helpers.c	(original)
+++ wpa/trunk/wpa_supplicant/dbus/dbus_new_helpers.c	Tue Oct 14 12:39:25 2014
@@ -38,27 +38,25 @@
 
 		if (!dbus_message_iter_open_container(dict_iter,
 						      DBUS_TYPE_DICT_ENTRY,
-						      NULL, &entry_iter)) {
-			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
-			                     "no memory");
-			return FALSE;
-		}
-		if (!dbus_message_iter_append_basic(&entry_iter,
+						      NULL, &entry_iter) ||
+		    !dbus_message_iter_append_basic(&entry_iter,
 						    DBUS_TYPE_STRING,
-						    &dsc->dbus_property)) {
-			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
-			                     "no memory");
-			return FALSE;
-		}
+						    &dsc->dbus_property))
+			goto error;
 
 		/* An error getting a property fails the request entirely */
 		if (!dsc->getter(&entry_iter, error, user_data))
 			return FALSE;
 
-		dbus_message_iter_close_container(dict_iter, &entry_iter);
+		if (!dbus_message_iter_close_container(dict_iter, &entry_iter))
+			goto error;
 	}
 
 	return TRUE;
+
+error:
+	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
+	return FALSE;
 }
 
 
@@ -111,7 +109,12 @@
 		return reply;
 	}
 
-	wpa_dbus_dict_close_write(&iter, &dict_iter);
+	if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
+		dbus_message_unref(reply);
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      "out of memory");
+	}
+
 	return reply;
 }
 

Modified: wpa/trunk/wpa_supplicant/dbus/dbus_old_handlers.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/dbus/dbus_old_handlers.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/dbus/dbus_old_handlers.c	(original)
+++ wpa/trunk/wpa_supplicant/dbus/dbus_old_handlers.c	Tue Oct 14 12:39:25 2014
@@ -113,24 +113,28 @@
 				goto error;
 			if (!strcmp(entry.key, "driver") &&
 			    (entry.type == DBUS_TYPE_STRING)) {
+				os_free(driver);
 				driver = os_strdup(entry.str_value);
 				wpa_dbus_dict_entry_clear(&entry);
 				if (driver == NULL)
 					goto error;
 			} else if (!strcmp(entry.key, "driver-params") &&
 				   (entry.type == DBUS_TYPE_STRING)) {
+				os_free(driver_param);
 				driver_param = os_strdup(entry.str_value);
 				wpa_dbus_dict_entry_clear(&entry);
 				if (driver_param == NULL)
 					goto error;
 			} else if (!strcmp(entry.key, "config-file") &&
 				   (entry.type == DBUS_TYPE_STRING)) {
+				os_free(confname);
 				confname = os_strdup(entry.str_value);
 				wpa_dbus_dict_entry_clear(&entry);
 				if (confname == NULL)
 					goto error;
 			} else if (!strcmp(entry.key, "bridge-ifname") &&
 				   (entry.type == DBUS_TYPE_STRING)) {
+				os_free(bridge_ifname);
 				bridge_ifname = os_strdup(entry.str_value);
 				wpa_dbus_dict_entry_clear(&entry);
 				if (bridge_ifname == NULL)
@@ -346,7 +350,7 @@
 DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message,
 					   struct wpa_supplicant *wpa_s)
 {
-	DBusMessage *reply = NULL;
+	DBusMessage *reply;
 	DBusMessageIter iter;
 	DBusMessageIter sub_iter;
 	struct wpa_bss *bss;
@@ -354,9 +358,10 @@
 	/* Create and initialize the return message */
 	reply = dbus_message_new_method_return(message);
 	dbus_message_iter_init_append(reply, &iter);
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-					 DBUS_TYPE_OBJECT_PATH_AS_STRING,
-					 &sub_iter);
+	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+					      DBUS_TYPE_OBJECT_PATH_AS_STRING,
+					      &sub_iter))
+		goto error;
 
 	/* Loop through scan results and append each result's object path */
 	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
@@ -370,13 +375,21 @@
 			    "%s/" WPAS_DBUS_BSSIDS_PART "/"
 			    WPAS_DBUS_BSSID_FORMAT,
 			    wpa_s->dbus_path, MAC2STR(bss->bssid));
-		dbus_message_iter_append_basic(&sub_iter,
-					       DBUS_TYPE_OBJECT_PATH, &path);
-	}
-
-	dbus_message_iter_close_container(&iter, &sub_iter);
-
-	return reply;
+		if (!dbus_message_iter_append_basic(&sub_iter,
+						    DBUS_TYPE_OBJECT_PATH,
+						    &path))
+			goto error;
+	}
+
+	if (!dbus_message_iter_close_container(&iter, &sub_iter))
+		goto error;
+
+	return reply;
+
+error:
+	dbus_message_unref(reply);
+	return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
+				      "an internal error occurred returning scan results");
 }
 
 
@@ -415,7 +428,7 @@
 		if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid",
 						     (const char *) (ie + 2),
 						     ie[1]))
-		goto error;
+			goto error;
 	}
 
 	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
@@ -1200,16 +1213,19 @@
 			goto error;
 		if (!strcmp(entry.key, "opensc_engine_path") &&
 		    (entry.type == DBUS_TYPE_STRING)) {
+			os_free(opensc_engine_path);
 			opensc_engine_path = os_strdup(entry.str_value);
 			if (opensc_engine_path == NULL)
 				goto error;
 		} else if (!strcmp(entry.key, "pkcs11_engine_path") &&
 			   (entry.type == DBUS_TYPE_STRING)) {
+			os_free(pkcs11_engine_path);
 			pkcs11_engine_path = os_strdup(entry.str_value);
 			if (pkcs11_engine_path == NULL)
 				goto error;
 		} else if (!strcmp(entry.key, "pkcs11_module_path") &&
 				 (entry.type == DBUS_TYPE_STRING)) {
+			os_free(pkcs11_module_path);
 			pkcs11_module_path = os_strdup(entry.str_value);
 			if (pkcs11_module_path == NULL)
 				goto error;

Modified: wpa/trunk/wpa_supplicant/driver_i.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/driver_i.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/driver_i.h	(original)
+++ wpa/trunk/wpa_supplicant/driver_i.h	Tue Oct 14 12:39:25 2014
@@ -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;
 }
@@ -630,6 +630,22 @@
 		return -1;
 	return wpa_s->driver->vendor_cmd(wpa_s->drv_priv, vendor_id, subcmd,
 					 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);
 }
 
 

Modified: wpa/trunk/wpa_supplicant/eapol_test.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/eapol_test.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/eapol_test.c	(original)
+++ wpa/trunk/wpa_supplicant/eapol_test.c	Tue Oct 14 12:39:25 2014
@@ -73,6 +73,9 @@
 	struct extra_radius_attr *extra_attrs;
 
 	FILE *server_cert_file;
+
+	const char *pcsc_reader;
+	const char *pcsc_pin;
 };
 
 static struct eapol_test_data eapol_test;
@@ -954,7 +957,7 @@
 }
 
 
-static int scard_test(void)
+static int scard_test(struct eapol_test_data *e)
 {
 	struct scard_data *scard;
 	size_t len;
@@ -985,10 +988,10 @@
 	unsigned char aka_ik[IK_LEN];
 	unsigned char aka_ck[CK_LEN];
 
-	scard = scard_init(NULL);
+	scard = scard_init(e->pcsc_reader);
 	if (scard == NULL)
 		return -1;
-	if (scard_set_pin(scard, "1234")) {
+	if (scard_set_pin(scard, e->pcsc_pin)) {
 		wpa_printf(MSG_WARNING, "PIN validation failed");
 		scard_deinit(scard);
 		return -1;
@@ -1063,7 +1066,7 @@
 }
 
 
-static int scard_get_triplets(int argc, char *argv[])
+static int scard_get_triplets(struct eapol_test_data *e, int argc, char *argv[])
 {
 	struct scard_data *scard;
 	size_t len;
@@ -1085,7 +1088,7 @@
 		wpa_debug_level = 99;
 	}
 
-	scard = scard_init(NULL);
+	scard = scard_init(e->pcsc_reader);
 	if (scard == NULL) {
 		printf("Failed to open smartcard connection\n");
 		return -1;
@@ -1143,7 +1146,8 @@
 	       "[-s<AS secret>]\\\n"
 	       "           [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
 	       "           [-M<client MAC address>] [-o<server cert file] \\\n"
-	       "           [-N<attr spec>] \\\n"
+	       "           [-N<attr spec>] [-R<PC/SC reader>] "
+	       "[-P<PC/SC PIN>] \\\n"
 	       "           [-A<client IP>]\n"
 	       "eapol_test scard\n"
 	       "eapol_test sim <PIN> <num triplets> [debug]\n"
@@ -1208,12 +1212,13 @@
 	os_memset(&eapol_test, 0, sizeof(eapol_test));
 	eapol_test.connect_info = "CONNECT 11Mbps 802.11b";
 	os_memcpy(eapol_test.own_addr, "\x02\x00\x00\x00\x00\x01", ETH_ALEN);
+	eapol_test.pcsc_pin = "1234";
 
 	wpa_debug_level = 0;
 	wpa_debug_show_keys = 1;
 
 	for (;;) {
-		c = getopt(argc, argv, "a:A:c:C:eM:nN:o:p:r:s:St:W");
+		c = getopt(argc, argv, "a:A:c:C:eM:nN:o:p:P:r:R:s:St:W");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -1254,8 +1259,14 @@
 		case 'p':
 			as_port = atoi(optarg);
 			break;
+		case 'P':
+			eapol_test.pcsc_pin = optarg;
+			break;
 		case 'r':
 			eapol_test.eapol_test_num_reauths = atoi(optarg);
+			break;
+		case 'R':
+			eapol_test.pcsc_reader = optarg;
 			break;
 		case 's':
 			as_secret = optarg;
@@ -1304,11 +1315,11 @@
 	}
 
 	if (argc > optind && os_strcmp(argv[optind], "scard") == 0) {
-		return scard_test();
+		return scard_test(&eapol_test);
 	}
 
 	if (argc > optind && os_strcmp(argv[optind], "sim") == 0) {
-		return scard_get_triplets(argc - optind - 1,
+		return scard_get_triplets(&eapol_test, argc - optind - 1,
 					  &argv[optind + 1]);
 	}
 
@@ -1342,6 +1353,11 @@
 	if (wpa_s.conf->ssid == NULL) {
 		printf("No networks defined.\n");
 		return -1;
+	}
+
+	if (eapol_test.pcsc_reader) {
+		os_free(wpa_s.conf->pcsc_reader);
+		wpa_s.conf->pcsc_reader = os_strdup(eapol_test.pcsc_reader);
 	}
 
 	wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret,

Modified: wpa/trunk/wpa_supplicant/events.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/events.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/events.c	(original)
+++ wpa/trunk/wpa_supplicant/events.c	Tue Oct 14 12:39:25 2014
@@ -83,14 +83,31 @@
 }
 
 
+static void wpa_supplicant_update_current_bss(struct wpa_supplicant *wpa_s)
+{
+	struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid);
+
+	if (!bss) {
+		wpa_supplicant_update_scan_results(wpa_s);
+
+		/* Get the BSS from the new scan results */
+		bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid);
+	}
+
+	if (bss)
+		wpa_s->current_bss = bss;
+}
+
+
 static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_ssid *ssid, *old_ssid;
-	struct wpa_bss *bss;
 	int res;
 
-	if (wpa_s->conf->ap_scan == 1 && wpa_s->current_ssid)
+	if (wpa_s->conf->ap_scan == 1 && wpa_s->current_ssid) {
+		wpa_supplicant_update_current_bss(wpa_s);
 		return 0;
+	}
 
 	wpa_dbg(wpa_s, MSG_DEBUG, "Select network based on association "
 		"information");
@@ -136,16 +153,7 @@
 	old_ssid = wpa_s->current_ssid;
 	wpa_s->current_ssid = ssid;
 
-	bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid);
-	if (!bss) {
-		wpa_supplicant_update_scan_results(wpa_s);
-
-		/* Get the BSS from the new scan results */
-		bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid);
-	}
-
-	if (bss)
-		wpa_s->current_bss = bss;
+	wpa_supplicant_update_current_bss(wpa_s);
 
 	wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
 	wpa_supplicant_initiate_eapol(wpa_s);
@@ -342,7 +350,7 @@
 	wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is configured to use SIM "
 		"(sim=%d aka=%d) - initialize PCSC", sim, aka);
 
-	wpa_s->scard = scard_init(NULL);
+	wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
 	if (wpa_s->scard == NULL) {
 		wpa_msg(wpa_s, MSG_WARNING, "Failed to initialize SIM "
 			"(pcsc-lite)");
@@ -574,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)) {
 		/*
@@ -592,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)) {
 		/*
@@ -1872,6 +1880,8 @@
 
 #ifdef CONFIG_AP
 	if (wpa_s->ap_iface) {
+		if (!data)
+			return;
 		hostapd_notif_assoc(wpa_s->ap_iface->bss[0],
 				    data->assoc_info.addr,
 				    data->assoc_info.req_ies,
@@ -1921,6 +1931,7 @@
 #ifdef CONFIG_SME
 	os_memcpy(wpa_s->sme.prev_bssid, bssid, ETH_ALEN);
 	wpa_s->sme.prev_bssid_set = 1;
+	wpa_s->sme.last_unprot_disconnect.sec = 0;
 #endif /* CONFIG_SME */
 
 	wpa_msg(wpa_s, MSG_INFO, "Associated with " MACSTR, MAC2STR(bssid));
@@ -1956,7 +1967,8 @@
 	    wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE ||
 	    (wpa_s->current_ssid &&
 	     wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS)) {
-		if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE &&
+		if (wpa_s->current_ssid &&
+		    wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE &&
 		    (wpa_s->drv_flags &
 		     WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) {
 			/*
@@ -2147,10 +2159,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 &&
@@ -2752,7 +2766,7 @@
 	struct wpa_supplicant *ifs;
 
 	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
-		reg_init_str(info->type), reg_type_str(info->type),
+		reg_init_str(info->initiator), reg_type_str(info->type),
 		info->alpha2[0] ? " alpha2=" : "",
 		info->alpha2[0] ? info->alpha2 : "");
 
@@ -2763,9 +2777,7 @@
 	wpa_s->hw.modes = wpa_drv_get_hw_feature_data(
 		wpa_s, &wpa_s->hw.num_modes, &wpa_s->hw.flags);
 
-#ifdef CONFIG_P2P
 	wpas_p2p_update_channel_list(wpa_s);
-#endif /* CONFIG_P2P */
 
 	/*
 	 * Check other interfaces to see if they share the same radio. If
@@ -2785,9 +2797,9 @@
 
 
 static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
-				      const struct ieee80211_mgmt *mgmt,
-				      size_t len, int freq)
-{
+				      const u8 *frame, size_t len, int freq)
+{
+	const struct ieee80211_mgmt *mgmt;
 	const u8 *payload;
 	size_t plen;
 	u8 category;
@@ -2795,9 +2807,10 @@
 	if (len < IEEE80211_HDRLEN + 2)
 		return;
 
-	payload = &mgmt->u.action.category;
+	mgmt = (const struct ieee80211_mgmt *) frame;
+	payload = frame + IEEE80211_HDRLEN;
 	category = *payload++;
-	plen = (((const u8 *) mgmt) + len) - payload;
+	plen = len - IEEE80211_HDRLEN - 1;
 
 	wpa_dbg(wpa_s, MSG_DEBUG, "Received Action frame: SA=" MACSTR
 		" Category=%u DataLen=%d freq=%d MHz",
@@ -2860,10 +2873,8 @@
 	}
 #endif /* CONFIG_INTERWORKING */
 
-#ifdef CONFIG_P2P
 	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
 			   category, payload, plen, freq);
-#endif /* CONFIG_P2P */
 }
 
 
@@ -2985,15 +2996,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:
@@ -3220,7 +3233,8 @@
 
 			if (stype == WLAN_FC_STYPE_ACTION) {
 				wpas_event_rx_mgmt_action(
-					wpa_s, mgmt, data->rx_mgmt.frame_len,
+					wpa_s, data->rx_mgmt.frame,
+					data->rx_mgmt.frame_len,
 					data->rx_mgmt.freq);
 				break;
 			}
@@ -3263,14 +3277,12 @@
 			break;
 		}
 #endif /* CONFIG_AP */
-#ifdef CONFIG_P2P
 		wpas_p2p_probe_req_rx(wpa_s, data->rx_probe_req.sa,
 				      data->rx_probe_req.da,
 				      data->rx_probe_req.bssid,
 				      data->rx_probe_req.ie,
 				      data->rx_probe_req.ie_len,
 				      data->rx_probe_req.ssi_signal);
-#endif /* CONFIG_P2P */
 		break;
 	case EVENT_REMAIN_ON_CHANNEL:
 #ifdef CONFIG_OFFCHANNEL
@@ -3278,21 +3290,17 @@
 			wpa_s, data->remain_on_channel.freq,
 			data->remain_on_channel.duration);
 #endif /* CONFIG_OFFCHANNEL */
-#ifdef CONFIG_P2P
 		wpas_p2p_remain_on_channel_cb(
 			wpa_s, data->remain_on_channel.freq,
 			data->remain_on_channel.duration);
-#endif /* CONFIG_P2P */
 		break;
 	case EVENT_CANCEL_REMAIN_ON_CHANNEL:
 #ifdef CONFIG_OFFCHANNEL
 		offchannel_cancel_remain_on_channel_cb(
 			wpa_s, data->remain_on_channel.freq);
 #endif /* CONFIG_OFFCHANNEL */
-#ifdef CONFIG_P2P
 		wpas_p2p_cancel_remain_on_channel_cb(
 			wpa_s, data->remain_on_channel.freq);
-#endif /* CONFIG_P2P */
 		break;
 	case EVENT_EAPOL_RX:
 		wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src,
@@ -3377,9 +3385,7 @@
 			wpa_s, &data->channel_list_changed);
 		break;
 	case EVENT_INTERFACE_UNAVAILABLE:
-#ifdef CONFIG_P2P
 		wpas_p2p_interface_unavailable(wpa_s);
-#endif /* CONFIG_P2P */
 		break;
 	case EVENT_BEST_CHANNEL:
 		wpa_dbg(wpa_s, MSG_DEBUG, "Best channel event received "
@@ -3389,11 +3395,9 @@
 		wpa_s->best_24_freq = data->best_chan.freq_24;
 		wpa_s->best_5_freq = data->best_chan.freq_5;
 		wpa_s->best_overall_freq = data->best_chan.freq_overall;
-#ifdef CONFIG_P2P
 		wpas_p2p_update_best_channels(wpa_s, data->best_chan.freq_24,
 					      data->best_chan.freq_5,
 					      data->best_chan.freq_overall);
-#endif /* CONFIG_P2P */
 		break;
 	case EVENT_UNPROT_DEAUTH:
 		wpa_supplicant_event_unprot_deauth(wpa_s,
@@ -3411,7 +3415,8 @@
 #endif /* CONFIG_AP */
 #ifdef CONFIG_TDLS
 		if (data)
-			wpa_tdls_disable_link(wpa_s->wpa, data->low_ack.addr);
+			wpa_tdls_disable_unreachable_link(wpa_s->wpa,
+							  data->low_ack.addr);
 #endif /* CONFIG_TDLS */
 		break;
 	case EVENT_IBSS_PEER_LOST:

Modified: wpa/trunk/wpa_supplicant/gas_query.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/gas_query.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/gas_query.c	(original)
+++ wpa/trunk/wpa_supplicant/gas_query.c	Tue Oct 14 12:39:25 2014
@@ -256,6 +256,7 @@
 static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
 			struct wpabuf *req)
 {
+	unsigned int wait_time;
 	int res, prot = pmf_in_use(gas->wpa_s, query->addr);
 
 	wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u "
@@ -266,10 +267,14 @@
 		*categ = WLAN_ACTION_PROTECTED_DUAL;
 	}
 	os_get_reltime(&query->last_oper);
+	wait_time = 1000;
+	if (gas->wpa_s->max_remain_on_chan &&
+	    wait_time > gas->wpa_s->max_remain_on_chan)
+		wait_time = gas->wpa_s->max_remain_on_chan;
 	res = offchannel_send_action(gas->wpa_s, query->freq, query->addr,
 				     gas->wpa_s->own_addr, query->addr,
-				     wpabuf_head(req), wpabuf_len(req), 1000,
-				     gas_query_tx_status, 0);
+				     wpabuf_head(req), wpabuf_len(req),
+				     wait_time, gas_query_tx_status, 0);
 	if (res == 0)
 		query->offchannel_tx_started = 1;
 	return res;
@@ -592,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) {
@@ -601,6 +607,14 @@
 		}
 
 		gas_query_free(query, 1);
+		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;
 	}
 

Modified: wpa/trunk/wpa_supplicant/hs20_supplicant.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/hs20_supplicant.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/hs20_supplicant.c	(original)
+++ wpa/trunk/wpa_supplicant/hs20_supplicant.c	Tue Oct 14 12:39:25 2014
@@ -109,7 +109,13 @@
 {
 	struct wpa_cred *cred;
 
-	if (ssid == NULL || ssid->parent_cred == NULL)
+	if (ssid == NULL)
+		return 0;
+
+	if (ssid->update_identifier)
+		return ssid->update_identifier;
+
+	if (ssid->parent_cred == NULL)
 		return 0;
 
 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {

Modified: wpa/trunk/wpa_supplicant/interworking.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/interworking.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/interworking.c	(original)
+++ wpa/trunk/wpa_supplicant/interworking.c	Tue Oct 14 12:39:25 2014
@@ -796,8 +796,8 @@
 		*pos++ = imsi[4];
 		*pos++ = imsi[5];
 	}
-	pos += os_snprintf(pos, end - pos, ".mcc%c%c%c.3gppnetwork.org",
-			   imsi[0], imsi[1], imsi[2]);
+	os_snprintf(pos, end - pos, ".mcc%c%c%c.3gppnetwork.org",
+		    imsi[0], imsi[1], imsi[2]);
 
 	return 0;
 }
@@ -1515,6 +1515,7 @@
 	u16 count, i;
 	char buf[100];
 	int excluded = 0, *excl = allow_excluded ? &excluded : NULL;
+	const char *name;
 
 	if (wpa_s->conf->cred == NULL || bss == NULL)
 		return -1;
@@ -1728,11 +1729,12 @@
 		if (wpa_config_set(ssid, "pac_file",
 				   "\"blob://pac_interworking\"", 0) < 0)
 			goto fail;
-		os_snprintf(buf, sizeof(buf), "\"auth=%s\"",
-			    eap_get_name(EAP_VENDOR_IETF,
-					 eap->inner_method ?
-					 eap->inner_method :
-					 EAP_TYPE_MSCHAPV2));
+		name = eap_get_name(EAP_VENDOR_IETF,
+				    eap->inner_method ? eap->inner_method :
+				    EAP_TYPE_MSCHAPV2);
+		if (name == NULL)
+			goto fail;
+		os_snprintf(buf, sizeof(buf), "\"auth=%s\"", name);
 		if (wpa_config_set(ssid, "phase2", buf, 0) < 0)
 			goto fail;
 		break;
@@ -2899,7 +2901,7 @@
 	struct wpa_bss *bss;
 	int res;
 	size_t len;
-	u8 query_resp_len_limit = 0, pame_bi = 0;
+	u8 query_resp_len_limit = 0;
 
 	freq = wpa_s->assoc_freq;
 	bss = wpa_bss_get_bssid(wpa_s, dst);
@@ -2923,8 +2925,7 @@
 	/* Advertisement Protocol IE */
 	wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
 	wpabuf_put_u8(buf, 1 + wpabuf_len(adv_proto)); /* Length */
-	wpabuf_put_u8(buf, (query_resp_len_limit & 0x7f) |
-		      (pame_bi ? 0x80 : 0));
+	wpabuf_put_u8(buf, query_resp_len_limit & 0x7f);
 	wpabuf_put_buf(buf, adv_proto);
 
 	/* GAS Query */

Modified: wpa/trunk/wpa_supplicant/main.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/main.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/main.c	(original)
+++ wpa/trunk/wpa_supplicant/main.c	Tue Oct 14 12:39:25 2014
@@ -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 */
 	}

Modified: wpa/trunk/wpa_supplicant/notify.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/notify.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/notify.c	(original)
+++ wpa/trunk/wpa_supplicant/notify.c	Tue Oct 14 12:39:25 2014
@@ -79,12 +79,10 @@
 	/* notify the new DBus API */
 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATE);
 
-#ifdef CONFIG_P2P
 	if (new_state == WPA_COMPLETED)
 		wpas_p2p_notif_connected(wpa_s);
 	else if (old_state >= WPA_ASSOCIATED && new_state < WPA_ASSOCIATED)
 		wpas_p2p_notif_disconnected(wpa_s);
-#endif /* CONFIG_P2P */
 
 	sme_state_changed(wpa_s);
 
@@ -258,9 +256,7 @@
 		wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
 	if (!ssid->p2p_group && wpa_s->global->p2p_group_formation != wpa_s)
 		wpas_dbus_unregister_network(wpa_s, ssid->id);
-#ifdef CONFIG_P2P
 	wpas_p2p_network_removed(wpa_s, ssid);
-#endif /* CONFIG_P2P */
 }
 
 
@@ -346,6 +342,12 @@
 				   unsigned int id)
 {
 	wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_RATES, id);
+}
+
+
+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);
 }
 
 
@@ -442,9 +444,9 @@
 				   const struct wpa_ssid *ssid,
 				   const char *role)
 {
+	wpas_dbus_signal_p2p_group_removed(wpa_s, role);
+
 	wpas_dbus_unregister_p2p_group(wpa_s, ssid);
-
-	wpas_dbus_signal_p2p_group_removed(wpa_s, role);
 }
 
 
@@ -541,17 +543,10 @@
 	wpas_p2p_notify_ap_sta_authorized(wpa_s, p2p_dev_addr);
 
 	/*
-	 * Register a group member object corresponding to this peer and
-	 * emit a PeerJoined signal. This will check if it really is a
-	 * P2P group.
-	 */
-	wpas_dbus_register_p2p_groupmember(wpa_s, sta);
-
-	/*
 	 * Create 'peer-joined' signal on group object -- will also
 	 * check P2P itself.
 	 */
-	wpas_dbus_signal_p2p_peer_joined(wpa_s, sta);
+	wpas_dbus_signal_p2p_peer_joined(wpa_s, p2p_dev_addr);
 #endif /* CONFIG_P2P */
 
 	/* Notify listeners a new station has been authorized */
@@ -560,20 +555,15 @@
 
 
 static void wpas_notify_ap_sta_deauthorized(struct wpa_supplicant *wpa_s,
-					    const u8 *sta)
+					    const u8 *sta,
+					    const u8 *p2p_dev_addr)
 {
 #ifdef CONFIG_P2P
-	/*
-	 * Unregister a group member object corresponding to this peer
-	 * if this is a P2P group.
-	 */
-	wpas_dbus_unregister_p2p_groupmember(wpa_s, sta);
-
 	/*
 	 * Create 'peer-disconnected' signal on group object if this
 	 * is a P2P group.
 	 */
-	wpas_dbus_signal_p2p_peer_disconnected(wpa_s, sta);
+	wpas_dbus_signal_p2p_peer_disconnected(wpa_s, p2p_dev_addr);
 #endif /* CONFIG_P2P */
 
 	/* Notify listeners a station has been deauthorized */
@@ -588,7 +578,7 @@
 	if (authorized)
 		wpas_notify_ap_sta_authorized(wpa_s, mac_addr, p2p_dev_addr);
 	else
-		wpas_notify_ap_sta_deauthorized(wpa_s, mac_addr);
+		wpas_notify_ap_sta_deauthorized(wpa_s, mac_addr, p2p_dev_addr);
 }
 
 
@@ -643,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);
+}

Modified: wpa/trunk/wpa_supplicant/notify.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/notify.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/notify.h	(original)
+++ wpa/trunk/wpa_supplicant/notify.h	Tue Oct 14 12:39:25 2014
@@ -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 */

Modified: wpa/trunk/wpa_supplicant/p2p_supplicant.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/p2p_supplicant.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/p2p_supplicant.c	(original)
+++ wpa/trunk/wpa_supplicant/p2p_supplicant.c	Tue Oct 14 12:39:25 2014
@@ -82,10 +82,6 @@
 #define P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE 15
 #endif /* P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE */
 
-#ifndef P2P_CONCURRENT_SEARCH_DELAY
-#define P2P_CONCURRENT_SEARCH_DELAY 500
-#endif /* P2P_CONCURRENT_SEARCH_DELAY */
-
 #define P2P_MGMT_DEVICE_PREFIX		"p2p-dev-"
 
 enum p2p_group_removal_reason {
@@ -126,6 +122,7 @@
 static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
 static void wpas_stop_listen(void *ctx);
 static void wpas_p2p_psk_failure_removal(void *eloop_ctx, void *timeout_ctx);
+static void wpas_p2p_group_deinit(struct wpa_supplicant *wpa_s);
 
 
 /*
@@ -155,29 +152,32 @@
  * Get the frequencies that are currently in use by one or more of the virtual
  * interfaces, and that are also valid for P2P operation.
  */
-static int wpas_p2p_valid_oper_freqs(struct wpa_supplicant *wpa_s,
-				     int *p2p_freqs, unsigned int len)
-{
-	int *freqs;
+static unsigned int
+wpas_p2p_valid_oper_freqs(struct wpa_supplicant *wpa_s,
+			  struct wpa_used_freq_data *p2p_freqs,
+			  unsigned int len)
+{
+	struct wpa_used_freq_data *freqs;
 	unsigned int num, i, j;
 
-	freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
+	freqs = os_calloc(wpa_s->num_multichan_concurrent,
+			  sizeof(struct wpa_used_freq_data));
 	if (!freqs)
-		return -1;
-
-	num = get_shared_radio_freqs(wpa_s, freqs,
-				     wpa_s->num_multichan_concurrent);
-
-	os_memset(p2p_freqs, 0, sizeof(int) * len);
+		return 0;
+
+	num = get_shared_radio_freqs_data(wpa_s, freqs,
+					  wpa_s->num_multichan_concurrent);
+
+	os_memset(p2p_freqs, 0, sizeof(struct wpa_used_freq_data) * len);
 
 	for (i = 0, j = 0; i < num && j < len; i++) {
-		if (p2p_supported_freq(wpa_s->global->p2p, freqs[i]))
+		if (p2p_supported_freq(wpa_s->global->p2p, freqs[i].freq))
 			p2p_freqs[j++] = freqs[i];
 	}
 
 	os_free(freqs);
 
-	dump_freq_array(wpa_s, "valid for P2P", p2p_freqs, j);
+	dump_freq_data(wpa_s, "valid for P2P", p2p_freqs, j);
 
 	return j;
 }
@@ -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;
@@ -786,7 +799,7 @@
 		os_memcpy(n + s->num_p2p_clients * ETH_ALEN, addr, ETH_ALEN);
 		s->p2p_client_list = n;
 		s->num_p2p_clients++;
-	} else if (!found) {
+	} else if (!found && s->p2p_client_list) {
 		/* Not enough room for an additional entry - drop the oldest
 		 * entry */
 		os_memmove(s->p2p_client_list,
@@ -803,11 +816,55 @@
 }
 
 
+static void wpas_p2p_group_started(struct wpa_supplicant *wpa_s,
+				   int go, struct wpa_ssid *ssid, int freq,
+				   const u8 *psk, const char *passphrase,
+				   const u8 *go_dev_addr, int persistent,
+				   const char *extra)
+{
+	const char *ssid_txt;
+	char psk_txt[65];
+
+	if (psk)
+		wpa_snprintf_hex(psk_txt, sizeof(psk_txt), psk, 32);
+	else
+		psk_txt[0] = '\0';
+
+	if (ssid)
+		ssid_txt = wpa_ssid_txt(ssid->ssid, ssid->ssid_len);
+	else
+		ssid_txt = "";
+
+	if (passphrase && passphrase[0] == '\0')
+		passphrase = NULL;
+
+	/*
+	 * Include PSK/passphrase only in the control interface message and
+	 * leave it out from the debug log entry.
+	 */
+	wpa_msg_global_ctrl(wpa_s->parent, MSG_INFO,
+			    P2P_EVENT_GROUP_STARTED
+			    "%s %s ssid=\"%s\" freq=%d%s%s%s%s%s go_dev_addr="
+			    MACSTR "%s%s",
+			    wpa_s->ifname, go ? "GO" : "client", ssid_txt, freq,
+			    psk ? " psk=" : "", psk_txt,
+			    passphrase ? " passphrase=\"" : "",
+			    passphrase ? passphrase : "",
+			    passphrase ? "\"" : "",
+			    MAC2STR(go_dev_addr),
+			    persistent ? " [PERSISTENT]" : "", extra);
+	wpa_printf(MSG_INFO, P2P_EVENT_GROUP_STARTED
+		   "%s %s ssid=\"%s\" freq=%d go_dev_addr=" MACSTR "%s%s",
+		   wpa_s->ifname, go ? "GO" : "client", ssid_txt, freq,
+		   MAC2STR(go_dev_addr), persistent ? " [PERSISTENT]" : "",
+		   extra);
+}
+
+
 static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
 					   int success)
 {
 	struct wpa_ssid *ssid;
-	const char *ssid_txt;
 	int client;
 	int persistent;
 	u8 go_dev_addr[ETH_ALEN];
@@ -846,7 +903,6 @@
 
 	persistent = 0;
 	if (ssid) {
-		ssid_txt = wpa_ssid_txt(ssid->ssid, ssid->ssid_len);
 		client = ssid->mode == WPAS_MODE_INFRA;
 		if (ssid->mode == WPAS_MODE_P2P_GO) {
 			persistent = ssid->p2p_persistent_group;
@@ -858,7 +914,6 @@
 							       ssid->ssid,
 							       ssid->ssid_len);
 	} else {
-		ssid_txt = "";
 		client = wpa_s->p2p_group_interface ==
 			P2P_GROUP_INTERFACE_CLIENT;
 		os_memset(go_dev_addr, 0, ETH_ALEN);
@@ -872,26 +927,13 @@
 		 * packets.
 		 */
 		wpa_s->show_group_started = 1;
-	} else if (ssid && ssid->passphrase == NULL && ssid->psk_set) {
-		char psk[65];
-		wpa_snprintf_hex(psk, sizeof(psk), ssid->psk, 32);
-		wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
-			       "%s GO ssid=\"%s\" freq=%d psk=%s go_dev_addr="
-			       MACSTR "%s",
-			       wpa_s->ifname, ssid_txt, ssid->frequency, psk,
-			       MAC2STR(go_dev_addr),
-			       persistent ? " [PERSISTENT]" : "");
-		wpas_p2p_cross_connect_setup(wpa_s);
-		wpas_p2p_set_group_idle_timeout(wpa_s);
 	} else {
-		wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
-			       "%s GO ssid=\"%s\" freq=%d passphrase=\"%s\" "
-			       "go_dev_addr=" MACSTR "%s",
-			       wpa_s->ifname, ssid_txt,
-			       ssid ? ssid->frequency : 0,
-			       ssid && ssid->passphrase ? ssid->passphrase : "",
-			       MAC2STR(go_dev_addr),
-			       persistent ? " [PERSISTENT]" : "");
+		wpas_p2p_group_started(wpa_s, 1, ssid,
+				       ssid ? ssid->frequency : 0,
+				       ssid && ssid->passphrase == NULL &&
+				       ssid->psk_set ? ssid->psk : NULL,
+				       ssid ? ssid->passphrase : NULL,
+				       go_dev_addr, persistent, "");
 		wpas_p2p_cross_connect_setup(wpa_s);
 		wpas_p2p_set_group_idle_timeout(wpa_s);
 	}
@@ -938,16 +980,8 @@
 }
 
 
-static void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s,
-					   unsigned int freq,
-					   const u8 *dst, const u8 *src,
-					   const u8 *bssid,
-					   const u8 *data, size_t data_len,
-					   enum offchannel_send_action_result
-					   result)
-{
-	enum p2p_send_action_result res = P2P_SEND_ACTION_SUCCESS;
-
+static void wpas_p2p_action_tx_clear(struct wpa_supplicant *wpa_s)
+{
 	if (wpa_s->p2p_send_action_work) {
 		struct send_action_work *awork;
 		awork = wpa_s->p2p_send_action_work->ctx;
@@ -970,6 +1004,20 @@
 				wpa_s, NULL);
 		}
 	}
+}
+
+
+static void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s,
+					   unsigned int freq,
+					   const u8 *dst, const u8 *src,
+					   const u8 *bssid,
+					   const u8 *data, size_t data_len,
+					   enum offchannel_send_action_result
+					   result)
+{
+	enum p2p_send_action_result res = P2P_SEND_ACTION_SUCCESS;
+
+	wpas_p2p_action_tx_clear(wpa_s);
 
 	if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled)
 		return;
@@ -1203,32 +1251,12 @@
 		wpa_printf(MSG_DEBUG, "P2P: Group setup without provisioning");
 		if (wpa_s->global->p2p_group_formation == wpa_s)
 			wpa_s->global->p2p_group_formation = NULL;
-		if (os_strlen(params->passphrase) > 0) {
-			wpa_msg_global(wpa_s->parent, MSG_INFO,
-				       P2P_EVENT_GROUP_STARTED
-				       "%s GO ssid=\"%s\" freq=%d "
-				       "passphrase=\"%s\" go_dev_addr=" MACSTR
-				       "%s", wpa_s->ifname,
-				       wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
-				       ssid->frequency, params->passphrase,
-				       MAC2STR(wpa_s->global->p2p_dev_addr),
-				       params->persistent_group ?
-				       " [PERSISTENT]" : "");
-		} else {
-			char psk[65];
-			wpa_snprintf_hex(psk, sizeof(psk), params->psk,
-					 sizeof(params->psk));
-			wpa_msg_global(wpa_s->parent, MSG_INFO,
-				       P2P_EVENT_GROUP_STARTED
-				       "%s GO ssid=\"%s\" freq=%d psk=%s "
-				       "go_dev_addr=" MACSTR "%s",
-				       wpa_s->ifname,
-				       wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
-				       ssid->frequency, psk,
-				       MAC2STR(wpa_s->global->p2p_dev_addr),
-				       params->persistent_group ?
-				       " [PERSISTENT]" : "");
-		}
+		wpas_p2p_group_started(wpa_s, 1, ssid, ssid->frequency,
+				       params->passphrase[0] == '\0' ?
+				       params->psk : NULL,
+				       params->passphrase,
+				       wpa_s->global->p2p_dev_addr,
+				       params->persistent_group, "");
 
 		os_get_reltime(&wpa_s->global->p2p_go_wait_client);
 		if (params->persistent_group) {
@@ -1693,14 +1721,15 @@
 	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_FOUND MACSTR
 		       " p2p_dev_addr=" MACSTR
 		       " pri_dev_type=%s name='%s' config_methods=0x%x "
-		       "dev_capab=0x%x group_capab=0x%x%s%s",
+		       "dev_capab=0x%x group_capab=0x%x%s%s%s",
 		       MAC2STR(addr), MAC2STR(info->p2p_device_addr),
 		       wps_dev_type_bin2str(info->pri_dev_type, devtype,
 					    sizeof(devtype)),
 		       info->device_name, info->config_methods,
 		       info->dev_capab, info->group_capab,
 		       wfd_dev_info_hex ? " wfd_dev_info=0x" : "",
-		       wfd_dev_info_hex ? wfd_dev_info_hex : "");
+		       wfd_dev_info_hex ? wfd_dev_info_hex : "",
+		       info->vendor_elems ? " vendor_elems=1" : "");
 
 	os_free(wfd_dev_info_hex);
 #endif /* CONFIG_NO_STDOUT_DEBUG */
@@ -2918,6 +2947,45 @@
 }
 
 
+/**
+ * Pick the best frequency to use from all the currently used frequencies.
+ */
+static int wpas_p2p_pick_best_used_freq(struct wpa_supplicant *wpa_s,
+					struct wpa_used_freq_data *freqs,
+					unsigned int num)
+{
+	unsigned int i, c;
+
+	/* find a candidate freq that is supported by P2P */
+	for (c = 0; c < num; c++)
+		if (p2p_supported_freq(wpa_s->global->p2p, freqs[c].freq))
+			break;
+
+	if (c == num)
+		return 0;
+
+	/* once we have a candidate, try to find a 'better' one */
+	for (i = c + 1; i < num; i++) {
+		if (!p2p_supported_freq(wpa_s->global->p2p, freqs[i].freq))
+			continue;
+
+		/*
+		 * 1. Infrastructure station interfaces have higher preference.
+		 * 2. P2P Clients have higher preference.
+		 * 3. All others.
+		 */
+		if (freqs[i].flags & WPA_FREQ_USED_BY_INFRA_STATION) {
+			c = i;
+			break;
+		}
+
+		if ((freqs[i].flags & WPA_FREQ_USED_BY_P2P_CLIENT))
+			c = i;
+	}
+	return freqs[c].freq;
+}
+
+
 static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
 				  const u8 *go_dev_addr, const u8 *ssid,
 				  size_t ssid_len, int *go, u8 *group_bssid,
@@ -2927,8 +2995,9 @@
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	struct wpa_ssid *s;
-	int res;
+	struct wpa_used_freq_data *freqs;
 	struct wpa_supplicant *grp;
+	int best_freq;
 
 	if (!persistent_group) {
 		wpa_printf(MSG_DEBUG, "P2P: Invitation from " MACSTR
@@ -3020,15 +3089,25 @@
 accept_inv:
 	wpas_p2p_set_own_freq_preference(wpa_s, 0);
 
+	best_freq = 0;
+	freqs = os_calloc(wpa_s->num_multichan_concurrent,
+			  sizeof(struct wpa_used_freq_data));
+	if (freqs) {
+		int num_channels = wpa_s->num_multichan_concurrent;
+		int num = wpas_p2p_valid_oper_freqs(wpa_s, freqs, num_channels);
+		best_freq = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num);
+		os_free(freqs);
+	}
+
 	/* Get one of the frequencies currently in use */
-	if (wpas_p2p_valid_oper_freqs(wpa_s, &res, 1) > 0) {
+	if (best_freq > 0) {
 		wpa_printf(MSG_DEBUG, "P2P: Trying to prefer a channel already used by one of the interfaces");
-		wpas_p2p_set_own_freq_preference(wpa_s, res);
+		wpas_p2p_set_own_freq_preference(wpa_s, best_freq);
 
 		if (wpa_s->num_multichan_concurrent < 2 ||
 		    wpas_p2p_num_unused_channels(wpa_s) < 1) {
 			wpa_printf(MSG_DEBUG, "P2P: No extra channels available - trying to force channel to match a channel already used by one of the interfaces");
-			*force_freq = res;
+			*force_freq = best_freq;
 		}
 	}
 
@@ -3138,7 +3217,7 @@
 			      ETH_ALEN) == 0)
 			break;
 	}
-	if (i >= ssid->num_p2p_clients) {
+	if (i >= ssid->num_p2p_clients || !ssid->p2p_client_list) {
 		if (ssid->mode != WPAS_MODE_P2P_GO &&
 		    os_memcmp(ssid->bssid, peer, ETH_ALEN) == 0) {
 			wpa_printf(MSG_DEBUG, "P2P: Remove persistent group %d "
@@ -3400,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[] = {
@@ -3425,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 }
 };
 
@@ -3634,10 +3714,31 @@
 }
 
 
-static int wpas_go_connected(void *ctx, const u8 *dev_addr)
-{
-	struct wpa_supplicant *wpa_s = ctx;
-
+struct wpa_supplicant * wpas_get_p2p_go_iface(struct wpa_supplicant *wpa_s,
+					      const u8 *ssid, size_t ssid_len)
+{
+	for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+		struct wpa_ssid *s = wpa_s->current_ssid;
+		if (s == NULL)
+			continue;
+		if (s->mode != WPAS_MODE_P2P_GO &&
+		    s->mode != WPAS_MODE_AP &&
+		    s->mode != WPAS_MODE_P2P_GROUP_FORMATION)
+			continue;
+		if (s->ssid_len != ssid_len ||
+		    os_memcmp(ssid, s->ssid, ssid_len) != 0)
+			continue;
+		return wpa_s;
+	}
+
+	return NULL;
+
+}
+
+
+struct wpa_supplicant * wpas_get_p2p_client_iface(struct wpa_supplicant *wpa_s,
+						  const u8 *peer_dev_addr)
+{
 	for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
 		struct wpa_ssid *ssid = wpa_s->current_ssid;
 		if (ssid == NULL)
@@ -3647,11 +3748,19 @@
 		if (wpa_s->wpa_state != WPA_COMPLETED &&
 		    wpa_s->wpa_state != WPA_GROUP_HANDSHAKE)
 			continue;
-		if (os_memcmp(wpa_s->go_dev_addr, dev_addr, ETH_ALEN) == 0)
-			return 1;
-	}
-
-	return 0;
+		if (os_memcmp(wpa_s->go_dev_addr, peer_dev_addr, ETH_ALEN) == 0)
+			return wpa_s;
+	}
+
+	return NULL;
+}
+
+
+static int wpas_go_connected(void *ctx, const u8 *dev_addr)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	return wpas_get_p2p_client_iface(wpa_s, dev_addr) != NULL;
 }
 
 
@@ -3677,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;
@@ -3708,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;
@@ -3767,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)
@@ -3819,20 +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;
-	}
-	wpa_printf(MSG_DEBUG, "P2P: Own listen channel: %d", p2p.channel);
+		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:%d",
+		   p2p.reg_class, p2p.channel);
 
 	if (wpa_s->conf->p2p_oper_reg_class &&
 	    wpa_s->conf->p2p_oper_channel) {
@@ -3843,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);
@@ -3865,12 +3990,6 @@
 		p2p.country[2] = 0x04;
 	} 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);
@@ -3896,6 +4015,12 @@
 	p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss;
 
 	p2p.max_listen = wpa_s->max_remain_on_chan;
+
+	if (wpa_s->conf->p2p_passphrase_len >= 8 &&
+	    wpa_s->conf->p2p_passphrase_len <= 63)
+		p2p.passphrase_len = wpa_s->conf->p2p_passphrase_len;
+	else
+		p2p.passphrase_len = 8;
 
 	global->p2p = p2p_init(&p2p);
 	if (global->p2p == NULL)
@@ -3965,16 +4090,13 @@
  *
  * This function deinitializes the global (per device) P2P module.
  */
-void wpas_p2p_deinit_global(struct wpa_global *global)
+static void wpas_p2p_deinit_global(struct wpa_global *global)
 {
 	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)
@@ -4099,26 +4221,25 @@
 
 static int wpas_check_freq_conflict(struct wpa_supplicant *wpa_s, int freq)
 {
-	int *freqs, res, num, i;
+	int res;
+	unsigned int num, i;
+	struct wpa_used_freq_data *freqs;
 
 	if (wpas_p2p_num_unused_channels(wpa_s) > 0) {
 		/* Multiple channels are supported and not all are in use */
 		return 0;
 	}
 
-	freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
+	freqs = os_calloc(wpa_s->num_multichan_concurrent,
+			  sizeof(struct wpa_used_freq_data));
 	if (!freqs)
 		return 1;
 
 	num = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
 					wpa_s->num_multichan_concurrent);
-	if (num < 0) {
-		res = 1;
-		goto exit_free;
-	}
 
 	for (i = 0; i < num; i++) {
-		if (freqs[i] == freq) {
+		if (freqs[i].freq == freq) {
 			wpa_printf(MSG_DEBUG, "P2P: Frequency %d MHz in use by another virtual interface and can be used",
 				   freq);
 			res = 0;
@@ -4126,6 +4247,7 @@
 		}
 	}
 
+	wpa_printf(MSG_DEBUG, "P2P: No valid operating frequencies");
 	res = 1;
 
 exit_free:
@@ -4251,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",
@@ -4559,18 +4681,28 @@
 static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
 				int *force_freq, int *pref_freq, int go)
 {
-	int *freqs, res;
+	struct wpa_used_freq_data *freqs;
+	int res, best_freq, num_unused;
 	unsigned int freq_in_use = 0, num, i;
 
-	freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
+	freqs = os_calloc(wpa_s->num_multichan_concurrent,
+			  sizeof(struct wpa_used_freq_data));
 	if (!freqs)
 		return -1;
 
-	num = get_shared_radio_freqs(wpa_s, freqs,
-				     wpa_s->num_multichan_concurrent);
+	num = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
+					wpa_s->num_multichan_concurrent);
+
+	/*
+	 * It is possible that the total number of used frequencies is bigger
+	 * than the number of frequencies used for P2P, so get the system wide
+	 * number of unused frequencies.
+	 */
+	num_unused = wpas_p2p_num_unused_channels(wpa_s);
+
 	wpa_printf(MSG_DEBUG,
-		   "P2P: Setup freqs: freq=%d num_MCC=%d shared_freqs=%u",
-		   freq, wpa_s->num_multichan_concurrent, num);
+		   "P2P: Setup freqs: freq=%d num_MCC=%d shared_freqs=%u num_unused=%d",
+		   freq, wpa_s->num_multichan_concurrent, num, num_unused);
 
 	if (freq > 0) {
 		int ret;
@@ -4587,11 +4719,11 @@
 		}
 
 		for (i = 0; i < num; i++) {
-			if (freqs[i] == freq)
+			if (freqs[i].freq == freq)
 				freq_in_use = 1;
 		}
 
-		if (num == wpa_s->num_multichan_concurrent && !freq_in_use) {
+		if (num_unused <= 0 && !freq_in_use) {
 			wpa_printf(MSG_DEBUG, "P2P: Cannot start P2P group on %u MHz as there are no available channels",
 				   freq);
 			res = -2;
@@ -4603,34 +4735,28 @@
 		goto exit_ok;
 	}
 
-	for (i = 0; i < num; i++) {
-		if (!p2p_supported_freq(wpa_s->global->p2p, freqs[i]))
-			continue;
-
-		if (*pref_freq == 0 && num < wpa_s->num_multichan_concurrent) {
+	best_freq = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num);
+
+	/* We have a candidate frequency to use */
+	if (best_freq > 0) {
+		if (*pref_freq == 0 && num_unused > 0) {
 			wpa_printf(MSG_DEBUG, "P2P: Try to prefer a frequency (%u MHz) we are already using",
-				   freqs[i]);
-			*pref_freq = freqs[i];
+				   best_freq);
+			*pref_freq = best_freq;
 		} else {
 			wpa_printf(MSG_DEBUG, "P2P: Try to force us to use frequency (%u MHz) which is already in use",
-				   freqs[i]);
-			*force_freq = freqs[i];
-		}
-		break;
-	}
-
-	if (i == num) {
-		if (num < wpa_s->num_multichan_concurrent && num > 0) {
-			wpa_printf(MSG_DEBUG, "P2P: Current operating channels are not available for P2P. Try to use another channel");
-			*force_freq = 0;
-		} else if (num < wpa_s->num_multichan_concurrent) {
-			wpa_printf(MSG_DEBUG, "P2P: No current operating channels - try to use a new channel");
-			*force_freq = 0;
-		} else {
-			wpa_printf(MSG_DEBUG, "P2P: All channels are in use and none of them are P2P enabled. Cannot start P2P group");
-			res = -2;
-			goto exit_free;
-		}
+				   best_freq);
+			*force_freq = best_freq;
+		}
+	} else if (num_unused > 0) {
+		wpa_printf(MSG_DEBUG,
+			   "P2P: Current operating channels are not available for P2P. Try to use another channel");
+		*force_freq = 0;
+	} else {
+		wpa_printf(MSG_DEBUG,
+			   "P2P: All channels are in use and none of them are P2P enabled. Cannot start P2P group");
+		res = -2;
+		goto exit_free;
 	}
 
 exit_ok:
@@ -4921,7 +5047,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);
@@ -4938,7 +5065,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 "
@@ -4961,13 +5089,65 @@
 }
 
 
+static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s,
+					struct p2p_go_neg_results *params,
+					const struct p2p_channels *channels)
+{
+	unsigned int i, r;
+
+	/* first try some random selection of the social channels */
+	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) &&
+		    p2p_supported_freq(wpa_s->global->p2p, params->freq))
+			goto out;
+	}
+
+	/* try all channels in reg. class 81 */
+	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) &&
+		    p2p_supported_freq(wpa_s->global->p2p, params->freq))
+			goto out;
+	}
+
+	/* 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)",
+		   params->freq);
+	return 0;
+}
+
+
 static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
 				   struct p2p_go_neg_results *params,
 				   int freq, int ht40, int vht,
 				   const struct p2p_channels *channels)
 {
-	int res, *freqs;
-	unsigned int pref_freq;
+	struct wpa_used_freq_data *freqs;
+	unsigned int pref_freq, cand_freq;
 	unsigned int num, i;
 
 	os_memset(params, 0, sizeof(*params));
@@ -5032,58 +5212,59 @@
 		wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz from preferred "
 			   "channels", params->freq);
 	} else {
-		int chan;
-		for (chan = 0; chan < 11; chan++) {
-			params->freq = 2412 + chan * 5;
-			if (!wpas_p2p_disallowed_freq(wpa_s->global,
-						      params->freq) &&
-			    freq_included(channels, params->freq))
+		/* no preference, select some channel */
+		if (wpas_p2p_select_freq_no_pref(wpa_s, params, channels) < 0)
+			return -1;
+	}
+
+	freqs = os_calloc(wpa_s->num_multichan_concurrent,
+			  sizeof(struct wpa_used_freq_data));
+	if (!freqs)
+		return -1;
+
+	num = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
+					wpa_s->num_multichan_concurrent);
+
+	cand_freq = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num);
+
+	/* First try the best used frequency if possible */
+	if (!freq && cand_freq > 0 && freq_included(channels, cand_freq)) {
+		params->freq = cand_freq;
+	} else if (!freq) {
+		/* Try any of the used frequencies */
+		for (i = 0; i < num; i++) {
+			if (freq_included(channels, freqs[i].freq)) {
+				wpa_printf(MSG_DEBUG, "P2P: Force GO on a channel we are already using (%u MHz)",
+					   freqs[i].freq);
+				params->freq = freqs[i].freq;
 				break;
-		}
-		if (chan == 11) {
-			wpa_printf(MSG_DEBUG, "P2P: No 2.4 GHz channel "
-				   "allowed");
-			return -1;
-		}
-		wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz (no preference "
-			   "known)", params->freq);
-	}
-
-	freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
-	if (!freqs)
-		return -1;
-
-	res = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
-					wpa_s->num_multichan_concurrent);
-	if (res < 0) {
-		os_free(freqs);
-		return -1;
-	}
-	num = res;
-
-	for (i = 0; i < num; i++) {
-		if (freq && freqs[i] == freq)
-			break;
-		if (!freq && freq_included(channels, freqs[i])) {
-			wpa_printf(MSG_DEBUG, "P2P: Force GO on a channel we are already using (%u MHz)",
-				   freqs[i]);
-			params->freq = freqs[i];
-			break;
-		}
-	}
-
-	if (i == num) {
-		if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
-			if (freq)
-				wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on freq (%u MHz) as all the channels are in use", freq);
-			else
+			}
+		}
+
+		if (i == num) {
+			if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
 				wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using");
-			os_free(freqs);
-			return -1;
-		} else if (num == 0) {
-			wpa_printf(MSG_DEBUG, "P2P: Use one of the free channels");
-		} else {
-			wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using. Use one of the free channels");
+				os_free(freqs);
+				return -1;
+			} else {
+				wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using. Use one of the free channels");
+			}
+		}
+	} else {
+		for (i = 0; i < num; i++) {
+			if (freqs[i].freq == freq)
+				break;
+		}
+
+		if (i == num) {
+			if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
+				if (freq)
+					wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on freq (%u MHz) as all the channels are in use", freq);
+				os_free(freqs);
+				return -1;
+			} else {
+				wpa_printf(MSG_DEBUG, "P2P: Use one of the free channels");
+			}
 		}
 	}
 
@@ -5549,6 +5730,8 @@
 	if (!offchannel_pending_action_tx(wpa_s))
 		return;
 
+	wpas_p2p_action_tx_clear(wpa_s);
+
 	wpa_printf(MSG_DEBUG, "P2P: Drop pending Action TX due to new "
 		   "operation request");
 	offchannel_clear_pending_action_tx(wpa_s);
@@ -5652,6 +5835,8 @@
 	int ret;
 
 	if (wpa_s->global->p2p_disabled)
+		return -1;
+	if (wpa_s->conf->p2p_disabled)
 		return -1;
 	if (wpa_s->global->p2p == NULL)
 		return -1;
@@ -5718,7 +5903,7 @@
 }
 
 
-void wpas_p2p_group_deinit(struct wpa_supplicant *wpa_s)
+static void wpas_p2p_group_deinit(struct wpa_supplicant *wpa_s)
 {
 	p2p_group_deinit(wpa_s->p2p_group);
 	wpa_s->p2p_group = NULL;
@@ -5884,7 +6069,6 @@
 void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_ssid *ssid = wpa_s->current_ssid;
-	const char *ssid_txt;
 	u8 go_dev_addr[ETH_ALEN];
 	int network_id = -1;
 	int persistent;
@@ -5902,7 +6086,6 @@
 
 	wpa_s->show_group_started = 0;
 
-	ssid_txt = wpa_ssid_txt(ssid->ssid, ssid->ssid_len);
 	os_memset(go_dev_addr, 0, ETH_ALEN);
 	if (ssid->bssid_set)
 		os_memcpy(go_dev_addr, ssid->bssid, ETH_ALEN);
@@ -5925,24 +6108,11 @@
 			    ip[8], ip[9], ip[10], ip[11]);
 	}
 
-	if (ssid->passphrase == NULL && ssid->psk_set) {
-		char psk[65];
-		wpa_snprintf_hex(psk, sizeof(psk), ssid->psk, 32);
-		wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
-			       "%s client ssid=\"%s\" freq=%d psk=%s "
-			       "go_dev_addr=" MACSTR "%s%s",
-			       wpa_s->ifname, ssid_txt, freq, psk,
-			       MAC2STR(go_dev_addr),
-			       persistent ? " [PERSISTENT]" : "", ip_addr);
-	} else {
-		wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
-			       "%s client ssid=\"%s\" freq=%d "
-			       "passphrase=\"%s\" go_dev_addr=" MACSTR "%s%s",
-			       wpa_s->ifname, ssid_txt, freq,
-			       ssid->passphrase ? ssid->passphrase : "",
-			       MAC2STR(go_dev_addr),
-			       persistent ? " [PERSISTENT]" : "", ip_addr);
-	}
+	wpas_p2p_group_started(wpa_s, 0, ssid, freq,
+			       ssid->passphrase == NULL && ssid->psk_set ?
+			       ssid->psk : NULL,
+			       ssid->passphrase, go_dev_addr, persistent,
+			       ip_addr);
 
 	if (persistent)
 		network_id = wpas_p2p_store_persistent_group(wpa_s->parent,
@@ -6183,20 +6353,27 @@
 		u8 reg_class, channel;
 		int ret;
 		unsigned int r;
+		u8 channel_forced;
+
 		if (wpa_s->conf->p2p_listen_reg_class &&
 		    wpa_s->conf->p2p_listen_channel) {
 			reg_class = wpa_s->conf->p2p_listen_reg_class;
 			channel = wpa_s->conf->p2p_listen_channel;
+			channel_forced = 1;
 		} else {
 			reg_class = 81;
 			/*
 			 * Pick one of the social channels randomly as the
 			 * listen channel.
 			 */
-			os_get_random((u8 *) &r, sizeof(r));
-			channel = 1 + (r % 3) * 5;
-		}
-		ret = p2p_set_listen_channel(p2p, reg_class, channel);
+			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,
+					     channel_forced);
 		if (ret)
 			wpa_printf(MSG_ERROR, "P2P: Own listen channel update "
 				   "failed: %d", ret);
@@ -6216,8 +6393,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,
@@ -6239,6 +6418,9 @@
 				   "update failed");
 		}
 	}
+
+	if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_PASSPHRASE_LEN)
+		p2p_set_passphrase_len(p2p, wpa_s->conf->p2p_passphrase_len);
 }
 
 
@@ -6764,8 +6946,8 @@
 	if (wpa_s->wpa_state > WPA_SCANNING) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use %u ms search delay due to "
 			"concurrent operation",
-			P2P_CONCURRENT_SEARCH_DELAY);
-		return P2P_CONCURRENT_SEARCH_DELAY;
+			wpa_s->conf->p2p_search_delay);
+		return wpa_s->conf->p2p_search_delay;
 	}
 
 	dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
@@ -6774,8 +6956,9 @@
 			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use %u ms search "
 				"delay due to concurrent operation on "
 				"interface %s",
-				P2P_CONCURRENT_SEARCH_DELAY, ifs->ifname);
-			return P2P_CONCURRENT_SEARCH_DELAY;
+				wpa_s->conf->p2p_search_delay,
+				ifs->ifname);
+			return wpa_s->conf->p2p_search_delay;
 		}
 	}
 
@@ -7678,3 +7861,80 @@
 }
 
 #endif /* CONFIG_WPS_NFC */
+
+
+static void wpas_p2p_optimize_listen_channel(struct wpa_supplicant *wpa_s,
+					     struct wpa_used_freq_data *freqs,
+					     unsigned int num)
+{
+	u8 curr_chan, cand, chan;
+	unsigned int i;
+
+	curr_chan = p2p_get_listen_channel(wpa_s->global->p2p);
+	for (i = 0, cand = 0; i < num; i++) {
+		ieee80211_freq_to_chan(freqs[i].freq, &chan);
+		if (curr_chan == chan) {
+			cand = 0;
+			break;
+		}
+
+		if (chan == 1 || chan == 6 || chan == 11)
+			cand = chan;
+	}
+
+	if (cand) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"P2P: Update Listen channel to %u baased on operating channel",
+			cand);
+		p2p_set_listen_channel(wpa_s->global->p2p, 81, cand, 0);
+	}
+}
+
+
+void wpas_p2p_indicate_state_change(struct wpa_supplicant *wpa_s)
+{
+	struct wpa_used_freq_data *freqs;
+	unsigned int num = wpa_s->num_multichan_concurrent;
+
+	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
+		return;
+
+	/*
+	 * If possible, optimize the Listen channel to be a channel that is
+	 * already used by one of the other interfaces.
+	 */
+	if (!wpa_s->conf->p2p_optimize_listen_chan)
+		return;
+
+	if (!wpa_s->current_ssid || wpa_s->wpa_state != WPA_COMPLETED)
+		return;
+
+	freqs = os_calloc(num, sizeof(struct wpa_used_freq_data));
+	if (!freqs)
+		return;
+
+	num = get_shared_radio_freqs_data(wpa_s, freqs, num);
+
+	wpas_p2p_optimize_listen_channel(wpa_s, freqs, num);
+	os_free(freqs);
+}
+
+
+void wpas_p2p_deinit_iface(struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s == wpa_s->parent)
+		wpas_p2p_group_remove(wpa_s, "*");
+	if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
+		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
+			"the management interface is being removed");
+		wpas_p2p_deinit_global(wpa_s->global);
+	}
+}
+
+
+void wpas_p2p_ap_deinit(struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s->ap_iface->bss)
+		wpa_s->ap_iface->bss[0]->p2p_group = NULL;
+	wpas_p2p_group_deinit(wpa_s);
+}

Modified: wpa/trunk/wpa_supplicant/p2p_supplicant.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/p2p_supplicant.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/p2p_supplicant.h	(original)
+++ wpa/trunk/wpa_supplicant/p2p_supplicant.h	Tue Oct 14 12:39:25 2014
@@ -16,19 +16,17 @@
 struct p2p_channels;
 struct wps_event_fail;
 
-int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s);
-void wpas_p2p_deinit(struct wpa_supplicant *wpa_s);
-void wpas_p2p_deinit_global(struct wpa_global *global);
-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,
+						  const u8 *peer_dev_addr);
 int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 		     const char *pin, enum p2p_wps_method wps_method,
 		     int persistent_group, int auto_join, int join,
 		     int auth, int go_intent, int freq, int persistent_id,
 		     int pd, int ht40, int vht);
-void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
-				   unsigned int freq, unsigned int duration);
-void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
-					  unsigned int freq);
 int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
                                           int freq, struct wpa_ssid *ssid);
 int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname);
@@ -41,8 +39,6 @@
 				  int connection_timeout);
 struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
 				       struct wpa_ssid *ssid);
-void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
-			  int registrar);
 enum wpas_p2p_prov_disc_use {
 	WPAS_P2P_PD_FOR_GO_NEG,
 	WPAS_P2P_PD_FOR_JOIN,
@@ -65,15 +61,7 @@
 int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout);
 int wpas_p2p_assoc_req_ie(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
 			  u8 *buf, size_t len, int p2p_group);
-int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr,
-			  const u8 *dst, const u8 *bssid,
-			  const u8 *ie, size_t ie_len,
-			  int ssi_signal);
-void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da,
-			const u8 *sa, const u8 *bssid,
-			u8 category, const u8 *data, size_t len, int freq);
 void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies);
-void wpas_p2p_group_deinit(struct wpa_supplicant *wpa_s);
 void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s);
 u64 wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst,
 			const struct wpabuf *tlvs);
@@ -101,7 +89,6 @@
 		    int ht40, int vht, int pref_freq);
 int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
 			  const u8 *peer_addr, const u8 *go_dev_addr);
-void wpas_p2p_completed(struct wpa_supplicant *wpa_s);
 int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
 			  u32 interval1, u32 duration2, u32 interval2);
 int wpas_p2p_ext_listen(struct wpa_supplicant *wpa_s, unsigned int period,
@@ -112,26 +99,12 @@
 void wpas_p2p_disassoc_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
 			     u16 reason_code, const u8 *ie, size_t ie_len,
 			     int locally_generated);
-void wpas_p2p_update_config(struct wpa_supplicant *wpa_s);
 int wpas_p2p_set_noa(struct wpa_supplicant *wpa_s, u8 count, int start,
 		     int duration);
 int wpas_p2p_set_cross_connect(struct wpa_supplicant *wpa_s, int enabled);
-void wpas_p2p_notif_connected(struct wpa_supplicant *wpa_s);
-void wpas_p2p_notif_disconnected(struct wpa_supplicant *wpa_s);
-int wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s);
-void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s);
 int wpas_p2p_cancel(struct wpa_supplicant *wpa_s);
-void wpas_p2p_interface_unavailable(struct wpa_supplicant *wpa_s);
-void wpas_p2p_update_best_channels(struct wpa_supplicant *wpa_s,
-				   int freq_24, int freq_5, int freq_overall);
 int wpas_p2p_unauthorize(struct wpa_supplicant *wpa_s, const char *addr);
 int wpas_p2p_disconnect(struct wpa_supplicant *wpa_s);
-void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
-			 struct wps_event_fail *fail);
-int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s);
-int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s);
-void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s,
-			      struct wpa_ssid *ssid);
 struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s,
 					  const u8 *addr, const u8 *ssid,
 					  size_t ssid_len);
@@ -161,9 +134,124 @@
 void wpas_p2p_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx);
 
 #ifdef CONFIG_P2P
+
+int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s);
+void wpas_p2p_deinit(struct wpa_supplicant *wpa_s);
+void wpas_p2p_completed(struct wpa_supplicant *wpa_s);
+void wpas_p2p_update_config(struct wpa_supplicant *wpa_s);
+int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr,
+			  const u8 *dst, const u8 *bssid,
+			  const u8 *ie, size_t ie_len,
+			  int ssi_signal);
+void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
+			  int registrar);
+void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s);
+void wpas_p2p_update_best_channels(struct wpa_supplicant *wpa_s,
+				   int freq_24, int freq_5, int freq_overall);
+void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da,
+			const u8 *sa, const u8 *bssid,
+			u8 category, const u8 *data, size_t len, int freq);
+void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+				   unsigned int freq, unsigned int duration);
+void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+					  unsigned int freq);
+void wpas_p2p_interface_unavailable(struct wpa_supplicant *wpa_s);
+void wpas_p2p_notif_connected(struct wpa_supplicant *wpa_s);
+void wpas_p2p_notif_disconnected(struct wpa_supplicant *wpa_s);
+int wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s);
 int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s);
 void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s);
+void wpas_p2p_indicate_state_change(struct wpa_supplicant *wpa_s);
+void wpas_p2p_deinit_iface(struct wpa_supplicant *wpa_s);
+void wpas_p2p_ap_deinit(struct wpa_supplicant *wpa_s);
+void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s,
+			      struct wpa_ssid *ssid);
+int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s);
+int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s);
+void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
+			 struct wps_event_fail *fail);
+
 #else /* CONFIG_P2P */
+
+static inline int
+wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+
+static inline void wpas_p2p_deinit(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline void wpas_p2p_update_config(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s,
+					const u8 *addr,
+					const u8 *dst, const u8 *bssid,
+					const u8 *ie, size_t ie_len,
+					int ssi_signal)
+{
+	return 0;
+}
+
+static inline void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s,
+					const u8 *peer_addr, int registrar)
+{
+}
+
+static inline void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline void wpas_p2p_update_best_channels(struct wpa_supplicant *wpa_s,
+						 int freq_24, int freq_5,
+						 int freq_overall)
+{
+}
+
+static inline void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s,
+				      const u8 *da,
+				      const u8 *sa, const u8 *bssid,
+				      u8 category, const u8 *data, size_t len,
+				      int freq)
+{
+}
+
+static inline void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+						 unsigned int freq,
+						 unsigned int duration)
+{
+}
+
+static inline void
+wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+				     unsigned int freq)
+{
+}
+
+static inline void wpas_p2p_interface_unavailable(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline void wpas_p2p_notif_connected(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline void wpas_p2p_notif_disconnected(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline int wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+
 static inline int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
 {
 	return 0;
@@ -172,6 +260,39 @@
 static inline void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s)
 {
 }
+
+static inline void wpas_p2p_indicate_state_change(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline void wpas_p2p_deinit_iface(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline void wpas_p2p_ap_deinit(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s,
+					    struct wpa_ssid *ssid)
+{
+}
+
+static inline int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+
+static inline int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+
+static inline void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
+				       struct wps_event_fail *fail)
+{
+}
+
 #endif /* CONFIG_P2P */
 
 #endif /* P2P_SUPPLICANT_H */

Modified: wpa/trunk/wpa_supplicant/scan.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/scan.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/scan.c	(original)
+++ wpa/trunk/wpa_supplicant/scan.c	Tue Oct 14 12:39:25 2014
@@ -155,6 +155,13 @@
 		wpa_supplicant_notify_scanning(wpa_s, 0);
 		wpas_notify_scan_done(wpa_s, 0);
 		wpa_s->scan_work = NULL;
+		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;
 	}
 
@@ -548,6 +555,47 @@
 }
 
 
+static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
+			       struct wpa_driver_scan_params *params,
+			       size_t max_ssids)
+{
+	unsigned int i;
+	struct wpa_ssid *ssid;
+
+	for (i = 0; i < wpa_s->scan_id_count; i++) {
+		unsigned int j;
+
+		ssid = wpa_config_get_network(wpa_s->conf, wpa_s->scan_id[i]);
+		if (!ssid || !ssid->scan_ssid)
+			continue;
+
+		for (j = 0; j < params->num_ssids; j++) {
+			if (params->ssids[j].ssid_len == ssid->ssid_len &&
+			    params->ssids[j].ssid &&
+			    os_memcmp(params->ssids[j].ssid, ssid->ssid,
+				      ssid->ssid_len) == 0)
+				break;
+		}
+		if (j < params->num_ssids)
+			continue; /* already in the list */
+
+		if (params->num_ssids + 1 > max_ssids) {
+			wpa_printf(MSG_DEBUG,
+				   "Over max scan SSIDs for manual request");
+			break;
+		}
+
+		wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s",
+			   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+		params->ssids[params->num_ssids].ssid = ssid->ssid;
+		params->ssids[params->num_ssids].ssid_len = ssid->ssid_len;
+		params->num_ssids++;
+	}
+
+	wpa_s->scan_id_count = 0;
+}
+
+
 static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
@@ -605,13 +653,11 @@
 		return;
 	}
 
-#ifdef CONFIG_P2P
 	if (wpas_p2p_in_progress(wpa_s)) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan while P2P operation is in progress");
 		wpa_supplicant_req_scan(wpa_s, 5, 0);
 		return;
 	}
-#endif /* CONFIG_P2P */
 
 	if (wpa_s->conf->ap_scan == 2)
 		max_ssids = 1;
@@ -760,6 +806,10 @@
 				ssid = wpa_s->conf->ssid;
 		}
 
+		if (wpa_s->scan_id_count &&
+		    wpa_s->last_scan_req == MANUAL_SCAN_REQ)
+			wpa_set_scan_ssids(wpa_s, &params, max_ssids);
+
 		for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) {
 			if (wpas_network_disabled(wpa_s, tssid))
 				continue;
@@ -1201,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 = ¶ms;
 
 scan:
@@ -1859,6 +1916,7 @@
 	params->filter_rssi = src->filter_rssi;
 	params->p2p_probe = src->p2p_probe;
 	params->only_new_results = src->only_new_results;
+	params->low_priority = src->low_priority;
 
 	return params;
 
@@ -1887,7 +1945,7 @@
 int wpas_start_pno(struct wpa_supplicant *wpa_s)
 {
 	int ret, interval;
-	size_t i, num_ssid;
+	size_t i, num_ssid, num_match_ssid;
 	struct wpa_ssid *ssid;
 	struct wpa_driver_scan_params params;
 
@@ -1916,41 +1974,58 @@
 
 	os_memset(&params, 0, sizeof(params));
 
-	num_ssid = 0;
+	num_ssid = num_match_ssid = 0;
 	ssid = wpa_s->conf->ssid;
 	while (ssid) {
-		if (!wpas_network_disabled(wpa_s, ssid))
-			num_ssid++;
+		if (!wpas_network_disabled(wpa_s, ssid)) {
+			num_match_ssid++;
+			if (ssid->scan_ssid)
+				num_ssid++;
+		}
 		ssid = ssid->next;
 	}
+
+	if (num_match_ssid == 0) {
+		wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
+		return -1;
+	}
+
+	if (num_match_ssid > num_ssid) {
+		params.num_ssids++; /* wildcard */
+		num_ssid++;
+	}
+
 	if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
 		wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
 			   "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
 		num_ssid = WPAS_MAX_SCAN_SSIDS;
 	}
 
-	if (num_ssid == 0) {
-		wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
-		return -1;
-	}
-
-	params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) *
-					num_ssid);
+	if (num_match_ssid > wpa_s->max_match_sets) {
+		num_match_ssid = wpa_s->max_match_sets;
+		wpa_dbg(wpa_s, MSG_DEBUG, "PNO: Too many SSIDs to match");
+	}
+	params.filter_ssids = os_calloc(num_match_ssid,
+					sizeof(struct wpa_driver_scan_filter));
 	if (params.filter_ssids == NULL)
 		return -1;
 	i = 0;
 	ssid = wpa_s->conf->ssid;
 	while (ssid) {
 		if (!wpas_network_disabled(wpa_s, ssid)) {
-			params.ssids[i].ssid = ssid->ssid;
-			params.ssids[i].ssid_len = ssid->ssid_len;
-			params.num_ssids++;
+			if (ssid->scan_ssid && params.num_ssids < num_ssid) {
+				params.ssids[params.num_ssids].ssid =
+					ssid->ssid;
+				params.ssids[params.num_ssids].ssid_len =
+					 ssid->ssid_len;
+				params.num_ssids++;
+			}
 			os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
 				  ssid->ssid_len);
 			params.filter_ssids[i].ssid_len = ssid->ssid_len;
 			params.num_filter_ssids++;
 			i++;
-			if (i == num_ssid)
+			if (i == num_match_ssid)
 				break;
 		}
 		ssid = ssid->next;

Modified: wpa/trunk/wpa_supplicant/sme.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/sme.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/sme.c	(original)
+++ wpa/trunk/wpa_supplicant/sme.c	Tue Oct 14 12:39:25 2014
@@ -151,7 +151,7 @@
 #endif /* CONFIG_IEEE80211R */
 	int i, bssid_changed;
 	struct wpabuf *resp = NULL;
-	u8 ext_capab[10];
+	u8 ext_capab[18];
 	int ext_capab_len;
 
 	if (bss == NULL) {
@@ -361,17 +361,24 @@
 		hs20 = wpabuf_alloc(20);
 		if (hs20) {
 			int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
+			size_t len;
+
 			wpas_hs20_add_indication(hs20, pps_mo_id);
-			os_memcpy(wpa_s->sme.assoc_req_ie +
-				  wpa_s->sme.assoc_req_ie_len,
-				  wpabuf_head(hs20), wpabuf_len(hs20));
-			wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
+			len = sizeof(wpa_s->sme.assoc_req_ie) -
+				wpa_s->sme.assoc_req_ie_len;
+			if (wpabuf_len(hs20) <= len) {
+				os_memcpy(wpa_s->sme.assoc_req_ie +
+					  wpa_s->sme.assoc_req_ie_len,
+					  wpabuf_head(hs20), wpabuf_len(hs20));
+				wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
+			}
 			wpabuf_free(hs20);
 		}
 	}
 #endif /* CONFIG_HS20 */
 
-	ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
+	ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
+					     sizeof(ext_capab));
 	if (ext_capab_len > 0) {
 		u8 *pos = wpa_s->sme.assoc_req_ie;
 		if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
@@ -735,7 +742,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 ?
@@ -773,7 +780,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);
 
@@ -1166,6 +1173,7 @@
 
 	os_memset(&params, 0, sizeof(params));
 	wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, &params);
+	params.low_priority = 1;
 	wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan");
 
 	if (wpa_supplicant_trigger_scan(wpa_s, &params))
@@ -1310,7 +1318,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;
@@ -1343,6 +1354,7 @@
 				 const u8 *da, u16 reason_code)
 {
 	struct wpa_ssid *ssid;
+	struct os_reltime now;
 
 	if (wpa_s->wpa_state != WPA_COMPLETED)
 		return;
@@ -1358,6 +1370,12 @@
 		return;
 	if (wpa_s->sme.sa_query_count > 0)
 		return;
+
+	os_get_reltime(&now);
+	if (wpa_s->sme.last_unprot_disconnect.sec &&
+	    !os_reltime_expired(&now, &wpa_s->sme.last_unprot_disconnect, 10))
+		return; /* limit SA Query procedure frequency */
+	wpa_s->sme.last_unprot_disconnect = now;
 
 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
 		"possible AP/STA state mismatch - trigger SA Query");

Modified: wpa/trunk/wpa_supplicant/wifi_display.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/wifi_display.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/wifi_display.c	(original)
+++ wpa/trunk/wpa_supplicant/wifi_display.c	Tue Oct 14 12:39:25 2014
@@ -33,6 +33,34 @@
 		wpabuf_free(global->wfd_subelem[i]);
 		global->wfd_subelem[i] = NULL;
 	}
+}
+
+
+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;
 }
 
 
@@ -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)
 {
@@ -276,8 +358,20 @@
 
 	while (i + WIFI_DISPLAY_SUBELEM_HEADER_LEN < buflen) {
 		elen = WPA_GET_BE16(buf + i + 1);
+		if (i + WIFI_DISPLAY_SUBELEM_HEADER_LEN + elen > buflen)
+			break; /* truncated subelement */
 
 		if (buf[i] == id) {
+			/*
+			 * Limit explicitly to an arbitrary length to avoid
+			 * unnecessarily large allocations. In practice, this
+			 * is limited to maximum frame length anyway, so the
+			 * maximum memory allocation here is not really that
+			 * large. Anyway, the Wi-Fi Display subelements that
+			 * are fetched with this function are even shorter.
+			 */
+			if (elen > 1000)
+				break;
 			subelem = os_zalloc(2 * elen + 1);
 			if (!subelem)
 				return NULL;

Modified: wpa/trunk/wpa_supplicant/wifi_display.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/wifi_display.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/wifi_display.h	(original)
+++ wpa/trunk/wpa_supplicant/wifi_display.h	Tue Oct 14 12:39:25 2014
@@ -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);

Modified: wpa/trunk/wpa_supplicant/wnm_sta.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/wnm_sta.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/wnm_sta.c	(original)
+++ wpa/trunk/wpa_supplicant/wnm_sta.c	Tue Oct 14 12:39:25 2014
@@ -921,8 +921,7 @@
 	if (len < IEEE80211_HDRLEN + 2)
 		return;
 
-	pos = &mgmt->u.action.category;
-	pos++;
+	pos = ((const u8 *) mgmt) + IEEE80211_HDRLEN + 1;
 	act = *pos++;
 	end = ((const u8 *) mgmt) + len;
 

Modified: wpa/trunk/wpa_supplicant/wpa_cli.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/wpa_cli.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/wpa_cli.c	(original)
+++ wpa/trunk/wpa_supplicant/wpa_cli.c	Tue Oct 14 12:39:25 2014
@@ -529,6 +529,13 @@
 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "PMKSA");
+}
+
+
+static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
+				   char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
 }
 
 
@@ -628,7 +635,7 @@
 		"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
 		"sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
 		"ignore_old_scan_res", "freq_list", "external_sim",
-		"tdls_external_control"
+		"tdls_external_control", "p2p_search_delay"
 	};
 	int i, num_fields = ARRAY_SIZE(fields);
 
@@ -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" },
@@ -3149,28 +3159,19 @@
 static int wpa_cli_exec(const char *program, const char *arg1,
 			const char *arg2)
 {
-	char *cmd;
+	char *arg;
 	size_t len;
 	int res;
-	int ret = 0;
-
-	len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
-	cmd = os_malloc(len);
-	if (cmd == NULL)
-		return -1;
-	res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
-	if (res < 0 || (size_t) res >= len) {
-		os_free(cmd);
-		return -1;
-	}
-	cmd[len - 1] = '\0';
-#ifndef _WIN32_WCE
-	if (system(cmd) < 0)
-		ret = -1;
-#endif /* _WIN32_WCE */
-	os_free(cmd);
-
-	return ret;
+
+	len = os_strlen(arg1) + os_strlen(arg2) + 2;
+	arg = os_malloc(len);
+	if (arg == NULL)
+		return -1;
+	os_snprintf(arg, len, "%s %s", arg1, arg2);
+	res = os_exec(program, arg, 1);
+	os_free(arg);
+
+	return res;
 }
 
 
@@ -3178,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)) {
@@ -3223,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;
@@ -3385,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';
@@ -3449,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();

Modified: wpa/trunk/wpa_supplicant/wpa_supplicant.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/wpa_supplicant.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/wpa_supplicant.c	(original)
+++ wpa/trunk/wpa_supplicant/wpa_supplicant.c	Tue Oct 14 12:39:25 2014
@@ -297,6 +297,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 */
 
@@ -375,6 +376,8 @@
 
 static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
 {
+	int i;
+
 	bgscan_deinit(wpa_s);
 	autoscan_deinit(wpa_s);
 	scard_deinit(wpa_s->scard);
@@ -400,11 +403,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;
@@ -447,9 +445,7 @@
 	wpa_supplicant_ap_deinit(wpa_s);
 #endif /* CONFIG_AP */
 
-#ifdef CONFIG_P2P
 	wpas_p2p_deinit(wpa_s);
-#endif /* CONFIG_P2P */
 
 #ifdef CONFIG_OFFCHANNEL
 	offchannel_deinit(wpa_s);
@@ -500,6 +496,11 @@
 #ifdef CONFIG_HS20
 	hs20_deinit(wpa_s);
 #endif /* CONFIG_HS20 */
+
+	for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
+		wpabuf_free(wpa_s->vendor_elem[i]);
+		wpa_s->vendor_elem[i] = NULL;
+	}
 }
 
 
@@ -705,9 +706,7 @@
 #endif /* IEEE8021X_EAPOL */
 		wpa_s->after_wps = 0;
 		wpa_s->known_wps_freq = 0;
-#ifdef CONFIG_P2P
 		wpas_p2p_completed(wpa_s);
-#endif /* CONFIG_P2P */
 
 		sme_sched_obss_scan(wpa_s, 1);
 	} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
@@ -736,6 +735,12 @@
 
 	if (wpa_s->wpa_state != old_state) {
 		wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
+
+		/*
+		 * Notify the P2P Device interface about a state change in one
+		 * of the interfaces.
+		 */
+		wpas_p2p_indicate_state_change(wpa_s);
 
 		if (wpa_s->wpa_state == WPA_COMPLETED ||
 		    old_state == WPA_COMPLETED)
@@ -984,6 +989,7 @@
 	} else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
 		/* TODO: parse OSEN element */
+		os_memset(&ie, 0, sizeof(ie));
 		ie.group_cipher = WPA_CIPHER_CCMP;
 		ie.pairwise_cipher = WPA_CIPHER_CCMP;
 		ie.key_mgmt = WPA_KEY_MGMT_OSEN;
@@ -1272,13 +1278,18 @@
 }
 
 
-int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
+int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
 {
 	u8 *pos = buf;
 	u8 len = 6, i;
 
 	if (len < wpa_s->extended_capa_len)
 		len = wpa_s->extended_capa_len;
+	if (buflen < (size_t) len + 2) {
+		wpa_printf(MSG_INFO,
+			   "Not enough room for building extended capabilities element");
+		return -1;
+	}
 
 	*pos++ = WLAN_EID_EXT_CAPAB;
 	*pos++ = len;
@@ -1361,6 +1372,68 @@
 	work->ctx = NULL;
 	wpas_connect_work_free(cwork);
 	radio_work_done(work);
+}
+
+
+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);
 }
 
 
@@ -1378,6 +1451,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);
@@ -1648,10 +1749,15 @@
 		hs20 = wpabuf_alloc(20);
 		if (hs20) {
 			int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
+			size_t len;
+
 			wpas_hs20_add_indication(hs20, pps_mo_id);
-			os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
-				  wpabuf_len(hs20));
-			wpa_ie_len += wpabuf_len(hs20);
+			len = sizeof(wpa_ie) - wpa_ie_len;
+			if (wpabuf_len(hs20) <= len) {
+				os_memcpy(wpa_ie + wpa_ie_len,
+					  wpabuf_head(hs20), wpabuf_len(hs20));
+				wpa_ie_len += wpabuf_len(hs20);
+			}
 			wpabuf_free(hs20);
 		}
 	}
@@ -1666,9 +1772,10 @@
 	 * interoperability issues.
 	 */
 	if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
-		u8 ext_capab[10];
+		u8 ext_capab[18];
 		int ext_capab_len;
-		ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
+		ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
+						     sizeof(ext_capab));
 		if (ext_capab_len > 0) {
 			u8 *pos = wpa_ie;
 			if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
@@ -1728,7 +1835,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;
@@ -1744,8 +1851,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)
@@ -1829,13 +1951,12 @@
 	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)
 				return;
 		}
 	}
@@ -2640,6 +2761,8 @@
 		return -1;
 	}
 
+	wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
+
 	return 0;
 }
 
@@ -2687,6 +2810,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]) {
@@ -2821,7 +2945,7 @@
 				 struct ieee80211_ht_capabilities *htcaps_mask,
 				 int disabled)
 {
-	u16 msk;
+	le16 msk;
 
 	wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
 
@@ -2894,8 +3018,8 @@
 				int disabled)
 {
 	/* Masking these out disables HT40 */
-	u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
-			       HT_CAP_INFO_SHORT_GI40MHZ);
+	le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
+				HT_CAP_INFO_SHORT_GI40MHZ);
 
 	wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
 
@@ -2916,8 +3040,8 @@
 			       int disabled)
 {
 	/* Masking these out disables SGI */
-	u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
-			       HT_CAP_INFO_SHORT_GI40MHZ);
+	le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
+				HT_CAP_INFO_SHORT_GI40MHZ);
 
 	wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
 
@@ -2938,7 +3062,7 @@
 			       int disabled)
 {
 	/* Masking these out disables LDPC */
-	u16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
+	le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
 
 	wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
 
@@ -2979,7 +3103,7 @@
 	wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
 
 	if (ssid->ht40_intolerant) {
-		u16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
+		le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
 		htcaps->ht_capabilities_info |= bit;
 		htcaps_mask->ht_capabilities_info |= bit;
 	}
@@ -3141,8 +3265,8 @@
 }
 
 
-int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
-			     struct wpa_driver_capa *capa)
+static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
+				    struct wpa_driver_capa *capa)
 {
 	struct wowlan_triggers triggers;
 	char *start, *end, *buf;
@@ -3538,11 +3662,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);
-		wpa_config_read(wpa_s->conf_p2p_dev, wpa_s->conf);
-#endif /* CONFIG_P2P */
-
 		/*
 		 * Override ctrl_interface and driver_param if set on command
 		 * line.
@@ -3718,12 +3837,10 @@
 		return -1;
 	}
 
-#ifdef CONFIG_P2P
 	if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
 		wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
 		return -1;
 	}
-#endif /* CONFIG_P2P */
 
 	if (wpa_bss_init(wpa_s) < 0)
 		return -1;
@@ -3774,16 +3891,7 @@
 	}
 
 	wpa_supplicant_cleanup(wpa_s);
-
-#ifdef CONFIG_P2P
-	if (wpa_s == wpa_s->parent)
-		wpas_p2p_group_remove(wpa_s, "*");
-	if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
-		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
-			"the management interface is being removed");
-		wpas_p2p_deinit_global(wpa_s->global);
-	}
-#endif /* CONFIG_P2P */
+	wpas_p2p_deinit_iface(wpa_s);
 
 	wpas_ctrl_radio_work_flush(wpa_s);
 	radio_remove_interface(wpa_s);
@@ -4212,11 +4320,7 @@
 #ifdef CONFIG_WPS
 	wpas_wps_update_config(wpa_s);
 #endif /* CONFIG_WPS */
-
-#ifdef CONFIG_P2P
 	wpas_p2p_update_config(wpa_s);
-#endif /* CONFIG_P2P */
-
 	wpa_s->conf->changed_parameters = 0;
 }
 
@@ -4396,7 +4500,7 @@
 			wpa_s->reassociate = 1;
 		break;
 	case WPA_CTRL_REQ_EAP_PASSWORD:
-		os_free(eap->password);
+		bin_clear_free(eap->password, eap->password_len);
 		eap->password = (u8 *) os_strdup(value);
 		eap->password_len = os_strlen(value);
 		eap->pending_req_password = 0;
@@ -4404,7 +4508,7 @@
 			wpa_s->reassociate = 1;
 		break;
 	case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
-		os_free(eap->new_password);
+		bin_clear_free(eap->new_password, eap->new_password_len);
 		eap->new_password = (u8 *) os_strdup(value);
 		eap->new_password_len = os_strlen(value);
 		eap->pending_req_new_password = 0;
@@ -4412,14 +4516,14 @@
 			wpa_s->reassociate = 1;
 		break;
 	case WPA_CTRL_REQ_EAP_PIN:
-		os_free(eap->pin);
+		str_clear_free(eap->pin);
 		eap->pin = os_strdup(value);
 		eap->pending_req_pin = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;
 		break;
 	case WPA_CTRL_REQ_EAP_OTP:
-		os_free(eap->otp);
+		bin_clear_free(eap->otp, eap->otp_len);
 		eap->otp = (u8 *) os_strdup(value);
 		eap->otp_len = os_strlen(value);
 		os_free(eap->pending_req_otp);
@@ -4427,14 +4531,14 @@
 		eap->pending_req_otp_len = 0;
 		break;
 	case WPA_CTRL_REQ_EAP_PASSPHRASE:
-		os_free(eap->private_key_passwd);
-		eap->private_key_passwd = (u8 *) os_strdup(value);
+		str_clear_free(eap->private_key_passwd);
+		eap->private_key_passwd = os_strdup(value);
 		eap->pending_req_passphrase = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;
 		break;
 	case WPA_CTRL_REQ_SIM:
-		os_free(eap->external_sim_resp);
+		str_clear_free(eap->external_sim_resp);
 		eap->external_sim_resp = os_strdup(value);
 		break;
 	default:
@@ -4633,24 +4737,30 @@
 }
 
 
-void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
-		     int *freq_array, unsigned int len)
+void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
+		    struct wpa_used_freq_data *freqs_data,
+		    unsigned int len)
 {
 	unsigned int i;
 
 	wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
 		len, title);
-	for (i = 0; i < len; i++)
-		wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d", i, freq_array[i]);
+	for (i = 0; i < len; i++) {
+		struct wpa_used_freq_data *cur = &freqs_data[i];
+		wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
+			i, cur->freq, cur->flags);
+	}
 }
 
 
 /*
  * Find the operating frequencies of any of the virtual interfaces that
- * are using the same radio as the current interface.
+ * are using the same radio as the current interface, and in addition, get
+ * information about the interface types that are using the frequency.
  */
-int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
-			   int *freq_array, unsigned int len)
+int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
+				struct wpa_used_freq_data *freqs_data,
+				unsigned int len)
 {
 	struct wpa_supplicant *ifs;
 	u8 bssid[ETH_ALEN];
@@ -4659,31 +4769,12 @@
 
 	wpa_dbg(wpa_s, MSG_DEBUG,
 		"Determining shared radio frequencies (max len %u)", len);
-	os_memset(freq_array, 0, sizeof(int) * len);
-
-	/* First add the frequency of the local interface */
-	if (wpa_s->current_ssid != NULL && wpa_s->assoc_freq != 0) {
-		if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
-		    wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)
-			freq_array[idx++] = wpa_s->current_ssid->frequency;
-		else if (wpa_drv_get_bssid(wpa_s, bssid) == 0)
-			freq_array[idx++] = wpa_s->assoc_freq;
-	}
-
-	/* If get_radio_name is not supported, use only the local freq */
-	if (!wpa_driver_get_radio_name(wpa_s)) {
-		freq = wpa_drv_shared_freq(wpa_s);
-		if (freq > 0 && idx < len &&
-		    (idx == 0 || freq_array[0] != freq))
-			freq_array[idx++] = freq;
-		dump_freq_array(wpa_s, "No get_radio_name", freq_array, idx);
-		return idx;
-	}
+	os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
 
 	dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
 			 radio_list) {
-		if (wpa_s == ifs)
-			continue;
+		if (idx == len)
+			break;
 
 		if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
 			continue;
@@ -4698,13 +4789,45 @@
 
 		/* Hold only distinct freqs */
 		for (i = 0; i < idx; i++)
-			if (freq_array[i] == freq)
+			if (freqs_data[i].freq == freq)
 				break;
 
 		if (i == idx)
-			freq_array[idx++] = freq;
-	}
-
-	dump_freq_array(wpa_s, "completed iteration", freq_array, idx);
+			freqs_data[idx++].freq = freq;
+
+		if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
+			freqs_data[i].flags = ifs->current_ssid->p2p_group ?
+				WPA_FREQ_USED_BY_P2P_CLIENT :
+				WPA_FREQ_USED_BY_INFRA_STATION;
+		}
+	}
+
+	dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
 	return idx;
 }
+
+
+/*
+ * Find the operating frequencies of any of the virtual interfaces that
+ * are using the same radio as the current interface.
+ */
+int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
+			   int *freq_array, unsigned int len)
+{
+	struct wpa_used_freq_data *freqs_data;
+	int num, i;
+
+	os_memset(freq_array, 0, sizeof(int) * len);
+
+	freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
+	if (!freqs_data)
+		return -1;
+
+	num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
+	for (i = 0; i < num; i++)
+		freq_array[i] = freqs_data[i].freq;
+
+	os_free(freqs_data);
+
+	return num;
+}

Modified: wpa/trunk/wpa_supplicant/wpa_supplicant.conf
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/wpa_supplicant.conf?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/wpa_supplicant.conf	(original)
+++ wpa/trunk/wpa_supplicant/wpa_supplicant.conf	Tue Oct 14 12:39:25 2014
@@ -269,6 +269,19 @@
 # inactive stations.
 #p2p_go_max_inactivity=300
 
+# Passphrase length (8..63) for P2P GO
+#
+# This parameter controls the length of the random passphrase that is
+# generated at the GO. Default: 8.
+#p2p_passphrase_len=8
+
+# Extra delay between concurrent P2P search iterations
+#
+# This value adds extra delay in milliseconds between concurrent search
+# iterations to make p2p_find friendlier to concurrent operations by avoiding
+# it from taking 100% of radio resources. The default value is 500 ms.
+#p2p_search_delay=500
+
 # Opportunistic Key Caching (also known as Proactive Key Caching) default
 # This parameter can be used to set the default behavior for the
 # proactive_key_caching parameter. By default, OKC is disabled unless enabled
@@ -318,6 +331,25 @@
 # 0:  Scan all available frequencies. (Default)
 # 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)
 
@@ -949,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

Modified: wpa/trunk/wpa_supplicant/wpa_supplicant_i.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/wpa_supplicant_i.h?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/wpa_supplicant_i.h	(original)
+++ wpa/trunk/wpa_supplicant/wpa_supplicant_i.h	Tue Oct 14 12:39:25 2014
@@ -12,6 +12,7 @@
 #include "utils/list.h"
 #include "common/defs.h"
 #include "common/sae.h"
+#include "common/wpa_ctrl.h"
 #include "wps/wps_defs.h"
 #include "config_ssid.h"
 
@@ -66,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
@@ -365,6 +366,14 @@
 	size_t ssid_len;
 };
 
+#define WPA_FREQ_USED_BY_INFRA_STATION BIT(0)
+#define WPA_FREQ_USED_BY_P2P_CLIENT BIT(1)
+
+struct wpa_used_freq_data {
+	int freq;
+	unsigned int flags;
+};
+
 /**
  * struct wpa_supplicant - Internal data for wpa_supplicant interface
  *
@@ -382,6 +391,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;
@@ -398,10 +408,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;
@@ -412,6 +418,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;
@@ -560,6 +567,9 @@
 	int normal_scans; /* normal scans run before sched_scan */
 	int scan_for_connection; /* whether the scan request was triggered for
 				  * finding a connection */
+#define MAX_SCAN_ID 16
+	int scan_id[MAX_SCAN_ID];
+	unsigned int scan_id_count;
 
 	unsigned int drv_flags;
 	unsigned int drv_enc;
@@ -588,6 +598,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;
@@ -596,6 +607,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;
 
@@ -628,6 +643,7 @@
 					* sa_query_count octets of pending
 					* SA Query transaction identifiers */
 		struct os_reltime sa_query_start;
+		struct os_reltime last_unprot_disconnect;
 		u8 sched_obss_scan;
 		u16 obss_scan_int;
 		u16 bss_max_idle_period;
@@ -848,6 +864,8 @@
 	struct wpa_radio_work *connect_work;
 
 	unsigned int ext_work_id;
+
+	struct wpabuf *vendor_elem[NUM_VENDOR_ELEM_FRAMES];
 };
 
 
@@ -941,7 +959,9 @@
 int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
 		    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);
+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
@@ -969,6 +989,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);
@@ -987,8 +1009,13 @@
 
 int wpas_init_ext_pw(struct wpa_supplicant *wpa_s);
 
-void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
-		     int *freq_array, unsigned int len);
+void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
+		    struct wpa_used_freq_data *freqs_data,
+		    unsigned int len);
+
+int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
+				struct wpa_used_freq_data *freqs_data,
+				unsigned int len);
 int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
 			   int *freq_array, unsigned int len);
 

Modified: wpa/trunk/wpa_supplicant/wpa_supplicant_template.conf
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/wpa_supplicant_template.conf?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/wpa_supplicant_template.conf	(original)
+++ wpa/trunk/wpa_supplicant/wpa_supplicant_template.conf	Tue Oct 14 12:39:25 2014
@@ -1,6 +1,6 @@
 ##### wpa_supplicant configuration file template #####
 update_config=1
-ctrl_interface=wlan0
 eapol_version=1
 ap_scan=1
 fast_reauth=1
+pmf=1

Modified: wpa/trunk/wpa_supplicant/wpas_glue.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/wpas_glue.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/wpas_glue.c	(original)
+++ wpa/trunk/wpa_supplicant/wpas_glue.c	Tue Oct 14 12:39:25 2014
@@ -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;

Modified: wpa/trunk/wpa_supplicant/wps_supplicant.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpa/trunk/wpa_supplicant/wps_supplicant.c?rev=1909&op=diff
==============================================================================
--- wpa/trunk/wpa_supplicant/wps_supplicant.c	(original)
+++ wpa/trunk/wpa_supplicant/wps_supplicant.c	Tue Oct 14 12:39:25 2014
@@ -73,10 +73,8 @@
 
 int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
 {
-#ifdef CONFIG_P2P
 	if (wpas_p2p_wps_eapol_cb(wpa_s) > 0)
 		return 1;
-#endif /* CONFIG_P2P */
 
 	if (!wpa_s->wps_success &&
 	    wpa_s->current_ssid &&
@@ -288,10 +286,53 @@
 		/* 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);
@@ -413,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);
@@ -576,9 +618,7 @@
 	eloop_register_timeout(0, 100000, wpas_wps_clear_timeout, wpa_s, NULL);
 
 	wpas_notify_wps_event_fail(wpa_s, fail);
-#ifdef CONFIG_P2P
 	wpas_p2p_wps_failed(wpa_s, fail);
-#endif /* CONFIG_P2P */
 }
 
 
@@ -637,9 +677,7 @@
 	eloop_register_timeout(10, 0, wpas_wps_reenable_networks_cb, wpa_s,
 			       NULL);
 
-#ifdef CONFIG_P2P
 	wpas_p2p_wps_success(wpa_s, wpa_s->bssid, 0);
-#endif /* CONFIG_P2P */
 }
 
 
@@ -1010,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) {




More information about the Pkg-wpa-devel mailing list