Cumulative patch from commit bacb984b2d10c0dccb3b05b7779d5d4c5662e8b2

bacb984 radiotap: Update radiotap parser to library version
e9b32da Propagate scan failures over D-Bus
142817b Add a wpa_supplicant ctrl_iface event for regdom changes
150fd0b WPS: Split eapol_cb reconnect to a separate code path
ded4f94 WPS: Close p2p_group and temporary parameters to all network blocks
d6a36f3 nl80211: Mask out deauth even after own deauth request
e74dd0e Add forgotten ampdu_factor into wpa_supplicant.conf
759ff2f Re-enable use of wildcard SSID with passphrase
023b466 Fix a debug print to have a space between words
0cd8602 Add CTRL-EVENT-SIGNAL-CHANGE for bgscan signal update events
bd8838a Fix ctrl_iface BLACKLIST return value

Change-Id: I4099b6a33f062d2b6a74c995941a2c534df90b3e
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 01be089..abffaae 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -1861,10 +1861,10 @@
 	 * skipped when processing scan results.
 	 */
 	ret = wpa_blacklist_add(wpa_s, bssid);
-	if (ret != 0)
+	if (ret < 0)
 		return -1;
 	ret = wpa_blacklist_add(wpa_s, bssid);
-	if (ret != 0)
+	if (ret < 0)
 		return -1;
 	os_memcpy(buf, "OK\n", 3);
 	return 3;
@@ -5819,7 +5819,7 @@
 			continue;
 		ework = work->ctx;
 		wpa_dbg(wpa_s, MSG_DEBUG,
-			"Flushing %sexternal radio work %u (%s)",
+			"Flushing%s external radio work %u (%s)",
 			work->started ? " started" : "", ework->id,
 			ework->type);
 		if (work->started)
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 7aee923..1aec9be 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -83,7 +83,7 @@
 #define	WPAS_DBUS_NEW_IFACE_P2P_GROUPMEMBER \
 	WPAS_DBUS_NEW_INTERFACE ".GroupMember"
 
-/* Errors */
+/* Top-level Errors */
 #define WPAS_DBUS_ERROR_UNKNOWN_ERROR \
 	WPAS_DBUS_NEW_INTERFACE ".UnknownError"
 #define WPAS_DBUS_ERROR_INVALID_ARGS \
@@ -120,6 +120,9 @@
 #define WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM \
 	WPAS_DBUS_NEW_INTERFACE ".SubscriptionNotYou"
 
+/* Interface-level errors */
+#define WPAS_DBUS_ERROR_IFACE_SCAN_ERROR \
+	WPAS_DBUS_NEW_IFACE_INTERFACE ".ScanError"
 
 void wpas_dbus_subscribe_noc(struct wpas_dbus_priv *priv);
 void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv);
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index ffa59b2..33a1ba9 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -116,6 +116,27 @@
 }
 
 
+/**
+ * wpas_dbus_error_scan_error - Return a new ScanError error message
+ * @message: Pointer to incoming dbus message this error refers to
+ * @error: Optional string to be used as the error message
+ * Returns: a dbus error message
+ *
+ * Convenience function to create and return a scan error
+ */
+DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
+					 const char *error)
+{
+	DBusMessage *reply;
+
+	reply = dbus_message_new_error(message,
+				       WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
+				       error);
+
+	return reply;
+}
+
+
 static const char *dont_quote[] = {
 	"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
 	"opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
@@ -1330,7 +1351,10 @@
 				"passive scan");
 			goto out;
 		} else if (params.freqs && params.freqs[0]) {
-			wpa_supplicant_trigger_scan(wpa_s, &params);
+			if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
+				reply = wpas_dbus_error_scan_error(
+					message, "Scan request rejected");
+			}
 		} else {
 			wpa_s->scan_req = MANUAL_SCAN_REQ;
 			wpa_supplicant_req_scan(wpa_s, 0, 0);
@@ -1343,7 +1367,10 @@
 #ifdef CONFIG_AUTOSCAN
 		autoscan_deinit(wpa_s);
 #endif /* CONFIG_AUTOSCAN */
-		wpa_supplicant_trigger_scan(wpa_s, &params);
+		if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
+			reply = wpas_dbus_error_scan_error(
+				message, "Scan request rejected");
+		}
 	} else {
 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
 			   "Unknown scan type: %s", type);
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index fc00b68..7eedd83 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2724,10 +2724,52 @@
 }
 
 
-static void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s)
+static const char * reg_init_str(enum reg_change_initiator init)
+{
+	switch (init) {
+	case REGDOM_SET_BY_CORE:
+		return "CORE";
+	case REGDOM_SET_BY_USER:
+		return "USER";
+	case REGDOM_SET_BY_DRIVER:
+		return "DRIVER";
+	case REGDOM_SET_BY_COUNTRY_IE:
+		return "COUNTRY_IE";
+	case REGDOM_BEACON_HINT:
+		return "BEACON_HINT";
+	}
+	return "?";
+}
+
+
+static const char * reg_type_str(enum reg_type type)
+{
+	switch (type) {
+	case REGDOM_TYPE_UNKNOWN:
+		return "UNKNOWN";
+	case REGDOM_TYPE_COUNTRY:
+		return "COUNTRY";
+	case REGDOM_TYPE_WORLD:
+		return "WORLD";
+	case REGDOM_TYPE_CUSTOM_WORLD:
+		return "CUSTOM_WORLD";
+	case REGDOM_TYPE_INTERSECTION:
+		return "INTERSECTION";
+	}
+	return "?";
+}
+
+
+static void wpa_supplicant_update_channel_list(
+	struct wpa_supplicant *wpa_s, struct channel_list_changed *info)
 {
 	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),
+		info->alpha2[0] ? " alpha2=" : "",
+		info->alpha2[0] ? info->alpha2 : "");
+
 	if (wpa_s->drv_priv == NULL)
 		return; /* Ignore event during drv initialization */
 
@@ -3272,6 +3314,12 @@
 					data->eapol_rx.data_len);
 		break;
 	case EVENT_SIGNAL_CHANGE:
+		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SIGNAL_CHANGE
+			"above=%d signal=%d noise=%d txrate=%d",
+			data->signal_change.above_threshold,
+			data->signal_change.current_signal,
+			data->signal_change.current_noise,
+			data->signal_change.current_txrate);
 		bgscan_notify_signal_change(
 			wpa_s, data->signal_change.above_threshold,
 			data->signal_change.current_signal,
@@ -3324,7 +3372,8 @@
 		wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
 		break;
 	case EVENT_CHANNEL_LIST_CHANGED:
-		wpa_supplicant_update_channel_list(wpa_s);
+		wpa_supplicant_update_channel_list(
+			wpa_s, &data->channel_list_changed);
 		break;
 	case EVENT_INTERFACE_UNAVAILABLE:
 #ifdef CONFIG_P2P
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 5c6f625..a9fbf00 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -4382,7 +4382,7 @@
 	}
 
 	if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
-	    !ssid->ext_psk)
+	    (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
 		return 1;
 
 	return 0;
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 3358250..629d886 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -962,6 +962,9 @@
 # 0  = Enable MAX-AMSDU if hardware supports it.
 # 1  = Disable AMSDU
 #
+# ampdu_factor: Maximum A-MPDU Length Exponent
+# Value: 0-3, see 7.3.2.56.3 in IEEE Std 802.11n-2009.
+#
 # ampdu_density:  Allow overriding AMPDU density configuration.
 #  Treated as hint by the kernel.
 # -1 = Do not make any changes.
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 22b8e71..2b58749 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -52,6 +52,25 @@
 }
 
 
+static void wpas_wps_assoc_with_cred(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+	int use_fast_assoc = timeout_ctx != NULL;
+
+	wpa_printf(MSG_DEBUG, "WPS: Continuing association after eapol_cb");
+	if (!use_fast_assoc ||
+	    wpa_supplicant_fast_associate(wpa_s) != 1)
+		wpa_supplicant_req_scan(wpa_s, 0, 0);
+}
+
+
+static void wpas_wps_assoc_with_cred_cancel(struct wpa_supplicant *wpa_s)
+{
+	eloop_cancel_timeout(wpas_wps_assoc_with_cred, wpa_s, (void *) 0);
+	eloop_cancel_timeout(wpas_wps_assoc_with_cred, wpa_s, (void *) 1);
+}
+
+
 int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_P2P
@@ -124,9 +143,18 @@
 			wpabuf_free(wps);
 		}
 
-		if (!use_fast_assoc ||
-		    wpa_supplicant_fast_associate(wpa_s) != 1)
-			wpa_supplicant_req_scan(wpa_s, 0, 0);
+		/*
+		 * Complete the next step from an eloop timeout to allow pending
+		 * driver events related to the disconnection to be processed
+		 * first. This makes it less likely for disconnection event to
+		 * cause problems with the following connection.
+		 */
+		wpa_printf(MSG_DEBUG, "WPS: Continue association from timeout");
+		wpas_wps_assoc_with_cred_cancel(wpa_s);
+		eloop_register_timeout(0, 10000,
+				       wpas_wps_assoc_with_cred, wpa_s,
+				       use_fast_assoc ? (void *) 1 :
+				       (void *) 0);
 		return 1;
 	}
 
@@ -370,6 +398,17 @@
 		ssid = wpa_config_add_network(wpa_s->conf);
 		if (ssid == NULL)
 			return -1;
+		if (wpa_s->current_ssid) {
+			/*
+			 * Should the GO issue multiple credentials for some
+			 * reason, each credential should be marked as a
+			 * temporary P2P group similarly to the one that gets
+			 * marked as such based on the pre-configured values
+			 * used for the WPS network block.
+			 */
+			ssid->p2p_group = wpa_s->current_ssid->p2p_group;
+			ssid->temporary = wpa_s->current_ssid->temporary;
+		}
 		wpas_notify_network_added(wpa_s, ssid);
 	}
 
@@ -1420,6 +1459,7 @@
 
 void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
 {
+	wpas_wps_assoc_with_cred_cancel(wpa_s);
 	eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_wps_clear_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_wps_reenable_networks_cb, wpa_s, NULL);