Cumulative patch from commit b2b688d18d40cd667d0faa149b4a7172166b3bd4

b2b688d P2P: Fix crash when failed to create GO interface
6197169 WPS NFC: Fix build without CONFIG_AP=y
e1ae5d7 SAE: Fix build without CONFIG_AP=y
813e7b3 P2P: Remove group from timeout on PSK failure
5bf9a6c P2P: Add event messages for possible PSK failures on P2P groups
eac8dab P2P: Document per-client keys and p2p_remove_client
43c693c P2P: Do not store duplicate PSK entries for the same device
f2c5660 P2P: Add a command for removing a client from all groups
01a57fe P2P: Maintain list of per-client PSKs for persistent groups
759fd76 P2P: Select PSK based on Device Address instead of Interface Address
94ddef3 P2P: Make peer's P2P Device Address available to authenticator
52177fb P2P: Store P2P Device Address in per-device PSK records
05766ed P2P: Allow per-device PSK to be assigned
698e921 wpa_cli: Add tab completion for p2p_set field values
0b5fb86 P2P: Stop listen state when listen-only duration is over
02a3e5c wpa_cli: Allow first DISCONNECTED event to be reported
cdf8bfa Disallow WEP configuration in WPA network
731ef43 D-Bus: Fix per-iface object unregistration on not existing objects
447969e D-Bus: Do not send network notification for all P2P groups
eb32460 Fix switching from EAP-SIM to EAP-AKA/AKA'
f2b3f4d P2P: Allow P2P functionality to be disabled per interface
50f4f2a hostapd: Add Automatic Channel Selection (ACS) support
43ee470 P2P: Immediate group removal in GC in case of deauthentication
fcf2052 Fix MNC length for Swisscom SIM cards

Bug: 10606228, 10513949

Change-Id: I63ba0e2ab4fa76e6afa7a34be42e8e847e1511b0
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index ba1f207..a379d65 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -70,7 +70,7 @@
 static struct wpa_ctrl *mon_conn;
 static int wpa_cli_quit = 0;
 static int wpa_cli_attached = 0;
-static int wpa_cli_connected = 0;
+static int wpa_cli_connected = -1;
 static int wpa_cli_last_id = 0;
 #ifndef CONFIG_CTRL_IFACE_DIR
 #define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
@@ -2055,6 +2055,50 @@
 }
 
 
+static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
+{
+	int arg = get_cmd_arg_num(str, pos);
+	const char *fields[] = {
+		"discoverability",
+		"managed",
+		"listen_channel",
+		"ssid_postfix",
+		"noa",
+		"ps",
+		"oppps",
+		"ctwindow",
+		"disabled",
+		"conc_pref",
+		"force_long_sd",
+		"peer_filter",
+		"cross_connect",
+		"go_apsd",
+		"client_apsd",
+		"disallow_freq",
+		"disc_int",
+		"per_sta_psk",
+	};
+	int i, num_fields = sizeof(fields) / sizeof(fields[0]);
+
+	if (arg == 1) {
+		char **res = os_calloc(num_fields + 1, sizeof(char *));
+		if (res == NULL)
+			return NULL;
+		for (i = 0; i < num_fields; i++) {
+			res[i] = os_strdup(fields[i]);
+			if (res[i] == NULL)
+				return res;
+		}
+		return res;
+	}
+
+	if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
+		return cli_txt_list_array(&p2p_peers);
+
+	return NULL;
+}
+
+
 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "P2P_FLUSH");
@@ -2105,6 +2149,13 @@
 	return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
 }
 
+
+static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
+					 char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
+}
+
 #endif /* CONFIG_P2P */
 
 #ifdef CONFIG_WIFI_DISPLAY
@@ -2706,7 +2757,8 @@
 	{ "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
 	  cli_cmd_flag_none,
 	  "<address> = show information about known P2P peer" },
-	{ "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
+	{ "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
+	  cli_cmd_flag_none,
 	  "<field> <value> = set a P2P parameter" },
 	{ "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
 	  "= flush P2P state" },
@@ -2722,6 +2774,9 @@
 	{ "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
 	  cli_cmd_flag_none,
 	  "[<period> <interval>] = set extended listen timing" },
+	{ "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
+	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
+	  "<address|iface=address> = remove a peer from all groups" },
 #endif /* CONFIG_P2P */
 #ifdef CONFIG_WIFI_DISPLAY
 	{ "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
@@ -3080,7 +3135,7 @@
 
 		os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
 
-		if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
+		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");