Accumulative patch from commit d5b559b6418c2bd09663e0d09e93a6592357fdce

d5b559b WNM: Add disassociation timeout processing for ESS_DISASSOC
f65f539 GAS: Reduce query timeout to two seconds
7a56af5 GAS: Assign new dialog token even if previous one is free
9e1ecab GAS: Ignore replays if previous frag_id without dropping GAS session
fa7ae95 Add test code for fetching the last configured GTK
576bce9 P2P: Direct global ctrl_iface commands automatically for P2P
c4bf83a P2P: No duplicate AP-STA-CONNECTED/DISCONNECTED as global event
7793c95 Clean up AP-STA-CONNECTED/DISCONNECTED prints
92c4465 P2P: Mark P2P events global (not specific to interface)
ed496f1 P2P: Clean up debug prints
710ae9a P2P: Move p2p_find stopped event message into p2p_supplicant.c
47bfe49 Add wpa_msg_global() for global events
214e428 Allow global ctrl_iface monitors
89c7ac5 wpa_cli: Set buffer length the same as in wpa_supplicant_ctrl_iface_process()
faf9a85 Add band option (2.4 vs. 5) for filtering scans
b83b1b2 Android: Clarify keystore include directories
6f1127c Android: Add a top level Android.mk
d2a9e2c Abstract and Android sockets for global ctrl_iface
6fd5cea wpa_cli: Allow global interface to be used in interactive mode
2925756 wpa_supplicant: Add -G argument to specify global ctrl group
cf3bebf Allow global ctrl_iface to be used for per-interface commands
058c863 FT RRB: Fix a memory leak on error path

Change-Id: I32a4afb43894167a30c4b0df18fd4846a2945c7c
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/README b/wpa_supplicant/README
index f439632..78df89e 100644
--- a/wpa_supplicant/README
+++ b/wpa_supplicant/README
@@ -410,6 +410,7 @@
 
 usage:
   wpa_supplicant [-BddfhKLqqtuvwW] [-P<pid file>] [-g<global ctrl>] \
+        [-G<group>] \
         -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-p<driver_param>] \
         [-b<br_ifname> [-N -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \
         [-p<driver_param>] [-b<br_ifname>] ...]
@@ -424,6 +425,7 @@
   -D = driver name (can be multiple drivers: nl80211,wext)
   -f = Log output to default log location (normally /tmp)
   -g = global ctrl_interface
+  -G = global ctrl_interface group
   -K = include keys (passwords, etc.) in debug output
   -t = include timestamp in debug messages
   -h = show this help text
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index e8bfe0c..6b5dc3f 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -461,6 +461,14 @@
 			return -1;
 		return res;
 #endif /* CONFIG_WIFI_DISPLAY */
+#ifdef CONFIG_TESTING_GET_GTK
+	} else if (os_strcmp(cmd, "gtk") == 0) {
+		if (wpa_s->last_gtk_len == 0)
+			return -1;
+		res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
+				       wpa_s->last_gtk_len);
+		return res;
+#endif /* CONFIG_TESTING_GET_GTK */
 	}
 
 	if (res < 0 || (unsigned int) res >= buflen)
@@ -5840,6 +5848,126 @@
 }
 
 
+static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
+					    const char *ifname,
+					    char *cmd, size_t *resp_len)
+{
+	struct wpa_supplicant *wpa_s;
+
+	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+		if (os_strcmp(ifname, wpa_s->ifname) == 0)
+			break;
+	}
+
+	if (wpa_s == NULL) {
+		char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
+		if (resp)
+			*resp_len = os_strlen(resp);
+		else
+			*resp_len = 1;
+		return resp;
+	}
+
+	return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
+}
+
+
+static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
+					       char *buf, size_t *resp_len)
+{
+#ifdef CONFIG_P2P
+	static const char * cmd[] = {
+		"P2P_FIND",
+		"P2P_STOP_FIND",
+		"P2P_LISTEN",
+		"P2P_GROUP_ADD",
+		"P2P_GET_PASSPHRASE",
+		"P2P_SERVICE_UPDATE",
+		"P2P_SERVICE_FLUSH",
+		"P2P_FLUSH",
+		"P2P_CANCEL",
+		"P2P_PRESENCE_REQ",
+		"P2P_EXT_LISTEN",
+		NULL
+	};
+	static const char * prefix[] = {
+		"P2P_FIND ",
+		"P2P_CONNECT ",
+		"P2P_LISTEN ",
+		"P2P_GROUP_REMOVE ",
+		"P2P_GROUP_ADD ",
+		"P2P_PROV_DISC ",
+		"P2P_SERV_DISC_REQ ",
+		"P2P_SERV_DISC_CANCEL_REQ ",
+		"P2P_SERV_DISC_RESP ",
+		"P2P_SERV_DISC_EXTERNAL ",
+		"P2P_SERVICE_ADD ",
+		"P2P_SERVICE_DEL ",
+		"P2P_REJECT ",
+		"P2P_INVITE ",
+		"P2P_PEER ",
+		"P2P_SET ",
+		"P2P_UNAUTHORIZE ",
+		"P2P_PRESENCE_REQ ",
+		"P2P_EXT_LISTEN ",
+		NULL
+	};
+	int found = 0;
+	int i;
+
+	if (global->p2p_init_wpa_s == NULL)
+		return NULL;
+
+	for (i = 0; !found && cmd[i]; i++) {
+		if (os_strcmp(buf, cmd[i]) == 0)
+			found = 1;
+	}
+
+	for (i = 0; !found && prefix[i]; i++) {
+		if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
+			found = 1;
+	}
+
+	if (found)
+		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
+							 buf, resp_len);
+#endif /* CONFIG_P2P */
+	return NULL;
+}
+
+
+static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
+					       char *buf, size_t *resp_len)
+{
+#ifdef CONFIG_WIFI_DISPLAY
+	if (global->p2p_init_wpa_s == NULL)
+		return NULL;
+	if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
+	    os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
+		return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
+							 buf, resp_len);
+#endif /* CONFIG_WIFI_DISPLAY */
+	return NULL;
+}
+
+
+static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
+					   char *buf, size_t *resp_len)
+{
+	char *ret;
+
+	ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
+	if (ret)
+		return ret;
+
+	ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
+	if (ret)
+		return ret;
+
+	return NULL;
+}
+
+
 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
 						char *buf, size_t *resp_len)
 {
@@ -5848,6 +5976,20 @@
 	int reply_len;
 	int level = MSG_DEBUG;
 
+	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
+		char *pos = os_strchr(buf + 7, ' ');
+		if (pos) {
+			*pos++ = '\0';
+			return wpas_global_ctrl_iface_ifname(global,
+							     buf + 7, pos,
+							     resp_len);
+		}
+	}
+
+	reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
+	if (reply)
+		return reply;
+
 	if (os_strcmp(buf, "PING") == 0)
 		level = MSG_EXCESSIVE;
 	wpa_hexdump_ascii(level, "RX global ctrl_iface",
diff --git a/wpa_supplicant/ctrl_iface_named_pipe.c b/wpa_supplicant/ctrl_iface_named_pipe.c
index fd417ff..dc02db2 100644
--- a/wpa_supplicant/ctrl_iface_named_pipe.c
+++ b/wpa_supplicant/ctrl_iface_named_pipe.c
@@ -423,7 +423,7 @@
 }
 
 
-static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
+static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, int global,
 					     const char *txt, size_t len)
 {
 	struct wpa_supplicant *wpa_s = ctx;
diff --git a/wpa_supplicant/ctrl_iface_udp.c b/wpa_supplicant/ctrl_iface_udp.c
index 994f9b1..f3b660d 100644
--- a/wpa_supplicant/ctrl_iface_udp.c
+++ b/wpa_supplicant/ctrl_iface_udp.c
@@ -255,7 +255,7 @@
 }
 
 
-static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
+static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, int global,
 					     const char *txt, size_t len)
 {
 	struct wpa_supplicant *wpa_s = ctx;
diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c
index 4dfabc8..545fefd 100644
--- a/wpa_supplicant/ctrl_iface_unix.c
+++ b/wpa_supplicant/ctrl_iface_unix.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / UNIX domain socket -based control interface
- * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -50,12 +50,20 @@
 };
 
 
-static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
+struct ctrl_iface_global_priv {
+	struct wpa_global *global;
+	int sock;
+	struct dl_list ctrl_dst;
+};
+
+
+static void wpa_supplicant_ctrl_iface_send(const char *ifname, int sock,
+					   struct dl_list *ctrl_dst,
 					   int level, const char *buf,
 					   size_t len);
 
 
-static int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv,
+static int wpa_supplicant_ctrl_iface_attach(struct dl_list *ctrl_dst,
 					    struct sockaddr_un *from,
 					    socklen_t fromlen)
 {
@@ -67,7 +75,7 @@
 	os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
 	dst->addrlen = fromlen;
 	dst->debug_level = MSG_INFO;
-	dl_list_add(&priv->ctrl_dst, &dst->list);
+	dl_list_add(ctrl_dst, &dst->list);
 	wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
 		    (u8 *) from->sun_path,
 		    fromlen - offsetof(struct sockaddr_un, sun_path));
@@ -75,13 +83,13 @@
 }
 
 
-static int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv,
+static int wpa_supplicant_ctrl_iface_detach(struct dl_list *ctrl_dst,
 					    struct sockaddr_un *from,
 					    socklen_t fromlen)
 {
 	struct wpa_ctrl_dst *dst;
 
-	dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) {
+	dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
 		if (fromlen == dst->addrlen &&
 		    os_memcmp(from->sun_path, dst->addr.sun_path,
 			      fromlen - offsetof(struct sockaddr_un, sun_path))
@@ -148,14 +156,16 @@
 	buf[res] = '\0';
 
 	if (os_strcmp(buf, "ATTACH") == 0) {
-		if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen))
+		if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, &from,
+						     fromlen))
 			reply_len = 1;
 		else {
 			new_attached = 1;
 			reply_len = 2;
 		}
 	} else if (os_strcmp(buf, "DETACH") == 0) {
-		if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen))
+		if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, &from,
+						     fromlen))
 			reply_len = 1;
 		else
 			reply_len = 2;
@@ -264,13 +274,30 @@
 }
 
 
-static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
+static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, int global,
 					     const char *txt, size_t len)
 {
 	struct wpa_supplicant *wpa_s = ctx;
-	if (wpa_s == NULL || wpa_s->ctrl_iface == NULL)
+
+	if (wpa_s == NULL)
 		return;
-	wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len);
+
+	if (global != 2 && wpa_s->global->ctrl_iface) {
+		struct ctrl_iface_global_priv *priv = wpa_s->global->ctrl_iface;
+		if (!dl_list_empty(&priv->ctrl_dst)) {
+			wpa_supplicant_ctrl_iface_send(global ? NULL :
+						       wpa_s->ifname,
+						       priv->sock,
+						       &priv->ctrl_dst,
+						       level, txt, len);
+		}
+	}
+
+	if (wpa_s->ctrl_iface == NULL)
+		return;
+	wpa_supplicant_ctrl_iface_send(NULL, wpa_s->ctrl_iface->sock,
+				       &wpa_s->ctrl_iface->ctrl_dst,
+				       level, txt, len);
 }
 
 
@@ -543,14 +570,17 @@
 
 /**
  * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors
- * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
+ * @ifname: Interface name for global control socket or %NULL
+ * @sock: Local socket fd
+ * @ctrl_dst: List of attached listeners
  * @level: Priority level of the message
  * @buf: Message data
  * @len: Message length
  *
  * Send a packet to all monitor programs attached to the control interface.
  */
-static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
+static void wpa_supplicant_ctrl_iface_send(const char *ifname, int sock,
+					   struct dl_list *ctrl_dst,
 					   int level, const char *buf,
 					   size_t len)
 {
@@ -558,32 +588,45 @@
 	char levelstr[10];
 	int idx, res;
 	struct msghdr msg;
-	struct iovec io[2];
+	struct iovec io[5];
 
-	if (priv->sock < 0 || dl_list_empty(&priv->ctrl_dst))
+	if (sock < 0 || dl_list_empty(ctrl_dst))
 		return;
 
 	res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
 	if (res < 0 || (size_t) res >= sizeof(levelstr))
 		return;
-	io[0].iov_base = levelstr;
-	io[0].iov_len = os_strlen(levelstr);
-	io[1].iov_base = (char *) buf;
-	io[1].iov_len = len;
+	idx = 0;
+	if (ifname) {
+		io[idx].iov_base = "IFNAME=";
+		io[idx].iov_len = 7;
+		idx++;
+		io[idx].iov_base = (char *) ifname;
+		io[idx].iov_len = os_strlen(ifname);
+		idx++;
+		io[idx].iov_base = " ";
+		io[idx].iov_len = 1;
+		idx++;
+	}
+	io[idx].iov_base = levelstr;
+	io[idx].iov_len = os_strlen(levelstr);
+	idx++;
+	io[idx].iov_base = (char *) buf;
+	io[idx].iov_len = len;
+	idx++;
 	os_memset(&msg, 0, sizeof(msg));
 	msg.msg_iov = io;
-	msg.msg_iovlen = 2;
+	msg.msg_iovlen = idx;
 
 	idx = 0;
-	dl_list_for_each_safe(dst, next, &priv->ctrl_dst, struct wpa_ctrl_dst,
-			      list) {
+	dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
 		if (level >= dst->debug_level) {
 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
 				    (u8 *) dst->addr.sun_path, dst->addrlen -
 				    offsetof(struct sockaddr_un, sun_path));
 			msg.msg_name = (void *) &dst->addr;
 			msg.msg_namelen = dst->addrlen;
-			if (sendmsg(priv->sock, &msg, 0) < 0) {
+			if (sendmsg(sock, &msg, 0) < 0) {
 				int _errno = errno;
 				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
 					   "%d - %s",
@@ -593,7 +636,7 @@
 				    (_errno != ENOBUFS && dst->errors > 10) ||
 				    _errno == ENOENT) {
 					wpa_supplicant_ctrl_iface_detach(
-						priv, &dst->addr,
+						ctrl_dst, &dst->addr,
 						dst->addrlen);
 				}
 			} else
@@ -626,8 +669,8 @@
 
 		if (os_strcmp(buf, "ATTACH") == 0) {
 			/* handle ATTACH signal of first monitor interface */
-			if (!wpa_supplicant_ctrl_iface_attach(priv, &from,
-							      fromlen)) {
+			if (!wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst,
+							      &from, fromlen)) {
 				sendto(priv->sock, "OK\n", 3, 0,
 				       (struct sockaddr *) &from, fromlen);
 				/* OK to continue */
@@ -647,21 +690,16 @@
 
 /* Global ctrl_iface */
 
-struct ctrl_iface_global_priv {
-	struct wpa_global *global;
-	int sock;
-};
-
-
 static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
 						     void *sock_ctx)
 {
 	struct wpa_global *global = eloop_ctx;
+	struct ctrl_iface_global_priv *priv = sock_ctx;
 	char buf[256];
 	int res;
 	struct sockaddr_un from;
 	socklen_t fromlen = sizeof(from);
-	char *reply;
+	char *reply = NULL;
 	size_t reply_len;
 
 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
@@ -672,16 +710,32 @@
 	}
 	buf[res] = '\0';
 
-	reply = wpa_supplicant_global_ctrl_iface_process(global, buf,
-							 &reply_len);
+	if (os_strcmp(buf, "ATTACH") == 0) {
+		if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, &from,
+						     fromlen))
+			reply_len = 1;
+		else
+			reply_len = 2;
+	} else if (os_strcmp(buf, "DETACH") == 0) {
+		if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, &from,
+						     fromlen))
+			reply_len = 1;
+		else
+			reply_len = 2;
+	} else {
+		reply = wpa_supplicant_global_ctrl_iface_process(global, buf,
+								 &reply_len);
+	}
 
 	if (reply) {
 		sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
 		       fromlen);
 		os_free(reply);
-	} else if (reply_len) {
+	} else if (reply_len == 1) {
 		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
 		       fromlen);
+	} else if (reply_len == 2) {
+		sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, fromlen);
 	}
 }
 
@@ -691,24 +745,48 @@
 {
 	struct ctrl_iface_global_priv *priv;
 	struct sockaddr_un addr;
+	const char *ctrl = global->params.ctrl_interface;
 
 	priv = os_zalloc(sizeof(*priv));
 	if (priv == NULL)
 		return NULL;
+	dl_list_init(&priv->ctrl_dst);
 	priv->global = global;
 	priv->sock = -1;
 
-	if (global->params.ctrl_interface == NULL)
+	if (ctrl == NULL)
 		return priv;
 
-#ifdef ANDROID
-	priv->sock = android_get_control_socket(global->params.ctrl_interface);
-	if (priv->sock >= 0)
-		goto havesock;
-#endif /* ANDROID */
+	wpa_printf(MSG_DEBUG, "Global control interface '%s'", ctrl);
 
-	wpa_printf(MSG_DEBUG, "Global control interface '%s'",
-		   global->params.ctrl_interface);
+#ifdef ANDROID
+	if (os_strncmp(ctrl, "@android:", 9) == 0) {
+		priv->sock = android_get_control_socket(ctrl + 9);
+		if (priv->sock < 0) {
+			wpa_printf(MSG_ERROR, "Failed to open Android control "
+				   "socket '%s'", ctrl + 9);
+			goto fail;
+		}
+		wpa_printf(MSG_DEBUG, "Using Android control socket '%s'",
+			   ctrl + 9);
+		goto havesock;
+	}
+
+	if (os_strncmp(ctrl, "@abstract:", 10) != 0) {
+		/*
+		 * Backwards compatibility - try to open an Android control
+		 * socket and if that fails, assume this was a UNIX domain
+		 * socket instead.
+		 */
+		priv->sock = android_get_control_socket(ctrl);
+		if (priv->sock >= 0) {
+			wpa_printf(MSG_DEBUG,
+				   "Using Android control socket '%s'",
+				   ctrl);
+			goto havesock;
+		}
+	}
+#endif /* ANDROID */
 
 	priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
 	if (priv->sock < 0) {
@@ -721,8 +799,23 @@
 	addr.sun_len = sizeof(addr);
 #endif /* __FreeBSD__ */
 	addr.sun_family = AF_UNIX;
-	os_strlcpy(addr.sun_path, global->params.ctrl_interface,
-		   sizeof(addr.sun_path));
+
+	if (os_strncmp(ctrl, "@abstract:", 10) == 0) {
+		addr.sun_path[0] = '\0';
+		os_strlcpy(addr.sun_path + 1, ctrl + 10,
+			   sizeof(addr.sun_path) - 1);
+		if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) <
+		    0) {
+			wpa_printf(MSG_ERROR, "supp-global-ctrl-iface-init: "
+				   "bind(PF_UNIX) failed: %s", strerror(errno));
+			goto fail;
+		}
+		wpa_printf(MSG_DEBUG, "Using Abstract control socket '%s'",
+			   ctrl + 10);
+		goto havesock;
+	}
+
+	os_strlcpy(addr.sun_path, ctrl, sizeof(addr.sun_path));
 	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
 		perror("supp-global-ctrl-iface-init (will try fixup): "
 		       "bind(PF_UNIX)");
@@ -731,11 +824,11 @@
 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
 				   " allow connections - assuming it was left"
 				   "over from forced program termination");
-			if (unlink(global->params.ctrl_interface) < 0) {
+			if (unlink(ctrl) < 0) {
 				perror("unlink[ctrl_iface]");
 				wpa_printf(MSG_ERROR, "Could not unlink "
 					   "existing ctrl_iface socket '%s'",
-					   global->params.ctrl_interface);
+					   ctrl);
 				goto fail;
 			}
 			if (bind(priv->sock, (struct sockaddr *) &addr,
@@ -745,23 +838,59 @@
 			}
 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
 				   "ctrl_iface socket '%s'",
-				   global->params.ctrl_interface);
+				   ctrl);
 		} else {
 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
 				   "be in use - cannot override it");
 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
 				   "not used anymore",
-				   global->params.ctrl_interface);
+				   ctrl);
 			goto fail;
 		}
 	}
 
-#ifdef ANDROID
+	wpa_printf(MSG_DEBUG, "Using UNIX control socket '%s'", ctrl);
+
+	if (global->params.ctrl_interface_group) {
+		char *gid_str = global->params.ctrl_interface_group;
+		gid_t gid = 0;
+		struct group *grp;
+		char *endp;
+
+		grp = getgrnam(gid_str);
+		if (grp) {
+			gid = grp->gr_gid;
+			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
+				   " (from group name '%s')",
+				   (int) gid, gid_str);
+		} else {
+			/* Group name not found - try to parse this as gid */
+			gid = strtol(gid_str, &endp, 10);
+			if (*gid_str == '\0' || *endp != '\0') {
+				wpa_printf(MSG_ERROR, "CTRL: Invalid group "
+					   "'%s'", gid_str);
+				goto fail;
+			}
+			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
+				   (int) gid);
+		}
+		if (chown(ctrl, -1, gid) < 0) {
+			perror("chown[global_ctrl_interface/ifname]");
+			goto fail;
+		}
+
+		if (chmod(ctrl, S_IRWXU | S_IRWXG) < 0) {
+			perror("chmod[global_ctrl_interface/ifname]");
+			goto fail;
+		}
+	} else {
+		chmod(ctrl, S_IRWXU);
+	}
+
 havesock:
-#endif /* ANDROID */
 	eloop_register_read_sock(priv->sock,
 				 wpa_supplicant_global_ctrl_iface_receive,
-				 global, NULL);
+				 global, priv);
 
 	return priv;
 
@@ -776,11 +905,16 @@
 void
 wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
 {
+	struct wpa_ctrl_dst *dst, *prev;
+
 	if (priv->sock >= 0) {
 		eloop_unregister_read_sock(priv->sock);
 		close(priv->sock);
 	}
 	if (priv->global->params.ctrl_interface)
 		unlink(priv->global->params.ctrl_interface);
+	dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
+			      list)
+		os_free(dst);
 	os_free(priv);
 }
diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c
index 27bcc7a..06a97d3 100644
--- a/wpa_supplicant/gas_query.c
+++ b/wpa_supplicant/gas_query.c
@@ -20,7 +20,7 @@
 
 
 /** GAS query timeout in seconds */
-#define GAS_QUERY_TIMEOUT_PERIOD 5
+#define GAS_QUERY_TIMEOUT_PERIOD 2
 
 
 /**
@@ -271,6 +271,11 @@
 	if (frag_id != query->next_frag_id) {
 		wpa_printf(MSG_DEBUG, "GAS: Unexpected frag_id in response "
 			   "from " MACSTR, MAC2STR(query->addr));
+		if (frag_id + 1 == query->next_frag_id) {
+			wpa_printf(MSG_DEBUG, "GAS: Drop frame as possible "
+				   "retry of previous fragment");
+			return;
+		}
 		gas_query_done(gas, query, GAS_QUERY_PEER_ERROR);
 		return;
 	}
@@ -461,16 +466,20 @@
 {
 	struct gas_query_pending *query;
 	int dialog_token;
+	static int next_start = 0;
 
 	if (wpabuf_len(req) < 3)
 		return -1;
 
 	for (dialog_token = 0; dialog_token < 256; dialog_token++) {
-		if (gas_query_dialog_token_available(gas, dst, dialog_token))
+		if (gas_query_dialog_token_available(
+			    gas, dst, (next_start + dialog_token) % 256))
 			break;
 	}
 	if (dialog_token == 256)
 		return -1; /* Too many pending queries */
+	dialog_token = (next_start + dialog_token) % 256;
+	next_start = (dialog_token + 1) % 256;
 
 	query = os_zalloc(sizeof(*query));
 	if (query == NULL)
diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c
index f45c1b7..1b3364c 100644
--- a/wpa_supplicant/main.c
+++ b/wpa_supplicant/main.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / main() function for UNIX like OSes and MinGW
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -25,6 +25,7 @@
 	       "usage:\n"
 	       "  wpa_supplicant [-BddhKLqqstuvW] [-P<pid file>] "
 	       "[-g<global ctrl>] \\\n"
+	       "        [-G<group>] \\\n"
 	       "        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
 	       "[-p<driver_param>] \\\n"
 	       "        [-b<br_ifname>] [-f<debug file>] [-e<entropy file>] "
@@ -59,6 +60,7 @@
 	printf("  -f = log output to debug file instead of stdout\n");
 #endif /* CONFIG_DEBUG_FILE */
 	printf("  -g = global ctrl_interface\n"
+	       "  -G = global ctrl_interface group\n"
 	       "  -K = include keys (passwords, etc.) in debug output\n");
 #ifdef CONFIG_DEBUG_SYSLOG
 	printf("  -s = log output to syslog instead of stdout\n");
@@ -157,7 +159,7 @@
 
 	for (;;) {
 		c = getopt(argc, argv,
-			   "b:Bc:C:D:de:f:g:hi:I:KLNo:O:p:P:qsTtuvW");
+			   "b:Bc:C:D:de:f:g:G:hi:I:KLNo:O:p:P:qsTtuvW");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -197,6 +199,9 @@
 		case 'g':
 			params.ctrl_interface = optarg;
 			break;
+		case 'G':
+			params.ctrl_interface_group = optarg;
+			break;
 		case 'h':
 			usage();
 			exitcode = 0;
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index b760e7f..7c19d0c 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -321,9 +321,9 @@
 		gtype = "GO";
 	if (wpa_s->cross_connect_in_use) {
 		wpa_s->cross_connect_in_use = 0;
-		wpa_msg(wpa_s->parent, MSG_INFO,
-			P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
-			wpa_s->ifname, wpa_s->cross_connect_uplink);
+		wpa_msg_global(wpa_s->parent, MSG_INFO,
+			       P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
+			       wpa_s->ifname, wpa_s->cross_connect_uplink);
 	}
 	switch (removal_reason) {
 	case P2P_GROUP_REMOVAL_REQUESTED:
@@ -351,9 +351,9 @@
 		break;
 	}
 	if (removal_reason != P2P_GROUP_REMOVAL_SILENT) {
-		wpa_msg(wpa_s->parent, MSG_INFO,
-			P2P_EVENT_GROUP_REMOVED "%s %s%s",
-			wpa_s->ifname, gtype, reason);
+		wpa_msg_global(wpa_s->parent, MSG_INFO,
+			       P2P_EVENT_GROUP_REMOVED "%s %s%s",
+			       wpa_s->ifname, gtype, reason);
 	}
 
 #ifdef ANDROID_P2P
@@ -663,14 +663,15 @@
 	wpa_s->p2p_in_provisioning = 0;
 
 	if (!success) {
-		wpa_msg(wpa_s->parent, MSG_INFO,
-			P2P_EVENT_GROUP_FORMATION_FAILURE);
+		wpa_msg_global(wpa_s->parent, MSG_INFO,
+			       P2P_EVENT_GROUP_FORMATION_FAILURE);
 		wpas_p2p_group_delete(wpa_s,
 				      P2P_GROUP_REMOVAL_FORMATION_FAILED);
 		return;
 	}
 
-	wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_FORMATION_SUCCESS);
+	wpa_msg_global(wpa_s->parent, MSG_INFO,
+		       P2P_EVENT_GROUP_FORMATION_SUCCESS);
 
 	ssid = wpa_s->current_ssid;
 	if (ssid && ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
@@ -717,22 +718,23 @@
 	} else if (ssid && ssid->passphrase == NULL && ssid->psk_set) {
 		char psk[65];
 		wpa_snprintf_hex(psk, sizeof(psk), ssid->psk, 32);
-		wpa_msg(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]" : "");
+		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(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]" : "");
+		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_cross_connect_setup(wpa_s);
 		wpas_p2p_set_group_idle_timeout(wpa_s);
 	}
@@ -855,26 +857,30 @@
 		if (wpa_s->global->p2p_group_formation == wpa_s)
 			wpa_s->global->p2p_group_formation = NULL;
 		if (os_strlen(params->passphrase) > 0) {
-			wpa_msg(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]" :
-				"");
+			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(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]" :
-				"");
+			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]" : "");
 		}
 
 		if (params->persistent_group)
@@ -948,8 +954,8 @@
 	if (os_strlen(params->passphrase) > 0) {
 		ssid->passphrase = os_strdup(params->passphrase);
 		if (ssid->passphrase == NULL) {
-			wpa_msg(wpa_s, MSG_ERROR, "P2P: Failed to copy "
-				"passphrase for GO");
+			wpa_msg_global(wpa_s, MSG_ERROR,
+				       "P2P: Failed to copy passphrase for GO");
 			wpa_config_remove_network(wpa_s->conf, ssid->id);
 			return;
 		}
@@ -1145,8 +1151,9 @@
 	}
 
 	if (res->status) {
-		wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_FAILURE "status=%d",
-			res->status);
+		wpa_msg_global(wpa_s, MSG_INFO,
+			       P2P_EVENT_GO_NEG_FAILURE "status=%d",
+			       res->status);
 		wpas_notify_p2p_go_neg_completed(wpa_s, res);
 		wpas_p2p_remove_pending_group_interface(wpa_s);
 		return;
@@ -1155,7 +1162,7 @@
 	if (wpa_s->p2p_go_ht40)
 		res->ht40 = 1;
 
-	wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS);
+	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS);
 	wpas_notify_p2p_go_neg_completed(wpa_s, res);
 
 	if (res->role_go && wpa_s->p2p_persistent_id >= 0) {
@@ -1215,8 +1222,8 @@
 void wpas_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id)
 {
 	struct wpa_supplicant *wpa_s = ctx;
-	wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_REQUEST MACSTR
-		" dev_passwd_id=%u", MAC2STR(src), dev_passwd_id);
+	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_REQUEST MACSTR
+		       " dev_passwd_id=%u", MAC2STR(src), dev_passwd_id);
 
 	wpas_notify_p2p_go_neg_req(wpa_s, src, dev_passwd_id);
 }
@@ -1239,16 +1246,16 @@
 					WFD_DEV_INFO_SIZE);
 	}
 #endif /* CONFIG_WIFI_DISPLAY */
-	wpa_msg(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",
-		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[0] ? " wfd_dev_info=0x" : "", wfd_dev_info_hex);
+	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",
+		       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[0] ? " wfd_dev_info=0x" : "", wfd_dev_info_hex);
 #endif /* CONFIG_NO_STDOUT_DEBUG */
 
 	wpas_notify_p2p_device_found(ctx, info->p2p_device_addr, new_device);
@@ -1259,13 +1266,20 @@
 {
 	struct wpa_supplicant *wpa_s = ctx;
 
-	wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_LOST
-		"p2p_dev_addr=" MACSTR, MAC2STR(dev_addr));
+	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_LOST
+		       "p2p_dev_addr=" MACSTR, MAC2STR(dev_addr));
 
 	wpas_notify_p2p_device_lost(wpa_s, dev_addr);
 }
 
 
+static void wpas_find_stopped(void *ctx)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_FIND_STOPPED);
+}
+
+
 static int wpas_start_listen(void *ctx, unsigned int freq,
 			     unsigned int duration,
 			     const struct wpabuf *probe_resp_ie)
@@ -2274,16 +2288,16 @@
 					 const u8 *peer, const char *params,
 					 unsigned int generated_pin)
 {
-	wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_SHOW_PIN MACSTR " %08d%s",
-		MAC2STR(peer), generated_pin, params);
+	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_SHOW_PIN MACSTR
+		       " %08d%s", MAC2STR(peer), generated_pin, params);
 }
 
 
 static void wpas_prov_disc_local_keypad(struct wpa_supplicant *wpa_s,
 					const u8 *peer, const char *params)
 {
-	wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_ENTER_PIN MACSTR "%s",
-		MAC2STR(peer), params);
+	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_ENTER_PIN MACSTR
+		       "%s", MAC2STR(peer), params);
 }
 
 
@@ -2335,8 +2349,8 @@
 	} else if (config_methods & WPS_CONFIG_KEYPAD)
 		wpas_prov_disc_local_keypad(wpa_s, peer, params);
 	else if (config_methods & WPS_CONFIG_PUSHBUTTON)
-		wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_REQ MACSTR
-			"%s", MAC2STR(peer), params);
+		wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_REQ
+			       MACSTR "%s", MAC2STR(peer), params);
 
 	wpas_notify_p2p_provision_discovery(wpa_s, peer, 1 /* request */,
 					    P2P_PROV_DISC_SUCCESS,
@@ -2374,8 +2388,8 @@
 		wpas_prov_disc_local_display(wpa_s, peer, params,
 					     generated_pin);
 	} else if (config_methods & WPS_CONFIG_PUSHBUTTON)
-		wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_RESP MACSTR
-			"%s", MAC2STR(peer), params);
+		wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_RESP
+			       MACSTR "%s", MAC2STR(peer), params);
 
 	wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */,
 					    P2P_PROV_DISC_SUCCESS,
@@ -2404,9 +2418,9 @@
 		return;
 	}
 
-	wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
-		" p2p_dev_addr=" MACSTR " status=%d",
-		MAC2STR(peer), status);
+	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
+		       " p2p_dev_addr=" MACSTR " status=%d",
+		       MAC2STR(peer), status);
 
 	wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */,
 					    status, 0, 0);
@@ -2557,27 +2571,30 @@
 
 	if (!s) {
 		if (bssid) {
-			wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
-				"sa=" MACSTR " go_dev_addr=" MACSTR
-				" bssid=" MACSTR " unknown-network",
-				MAC2STR(sa), MAC2STR(go_dev_addr),
-				MAC2STR(bssid));
+			wpa_msg_global(wpa_s, MSG_INFO,
+				       P2P_EVENT_INVITATION_RECEIVED
+				       "sa=" MACSTR " go_dev_addr=" MACSTR
+				       " bssid=" MACSTR " unknown-network",
+				       MAC2STR(sa), MAC2STR(go_dev_addr),
+				       MAC2STR(bssid));
 		} else {
-			wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
-				"sa=" MACSTR " go_dev_addr=" MACSTR
-				" unknown-network",
-				MAC2STR(sa), MAC2STR(go_dev_addr));
+			wpa_msg_global(wpa_s, MSG_INFO,
+				       P2P_EVENT_INVITATION_RECEIVED
+				       "sa=" MACSTR " go_dev_addr=" MACSTR
+				       " unknown-network",
+				       MAC2STR(sa), MAC2STR(go_dev_addr));
 		}
 		return;
 	}
 
 	if (s->mode == WPAS_MODE_P2P_GO && op_freq) {
-		wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED "sa="
-			MACSTR " persistent=%d freq=%d",
-			MAC2STR(sa), s->id, op_freq);
+		wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
+			       "sa=" MACSTR " persistent=%d freq=%d",
+			       MAC2STR(sa), s->id, op_freq);
 	} else {
-		wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED "sa="
-			MACSTR " persistent=%d", MAC2STR(sa), s->id);
+		wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
+			       "sa=" MACSTR " persistent=%d",
+			       MAC2STR(sa), s->id);
 	}
 }
 
@@ -2649,12 +2666,12 @@
 	struct wpa_ssid *ssid;
 
 	if (bssid) {
-		wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
-			"status=%d " MACSTR,
-			status, MAC2STR(bssid));
+		wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
+			       "status=%d " MACSTR,
+			       status, MAC2STR(bssid));
 	} else {
-		wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
-			"status=%d ", status);
+		wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
+			       "status=%d ", status);
 	}
 	wpas_notify_p2p_invitation_result(wpa_s, status, bssid);
 
@@ -2995,6 +3012,13 @@
 }
 
 
+static void wpas_p2p_debug_print(void *ctx, int level, const char *msg)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+	wpa_msg_global(wpa_s, level, "P2P: %s", msg);
+}
+
+
 /**
  * wpas_p2p_init - Initialize P2P module for %wpa_supplicant
  * @global: Pointer to global data from wpa_supplicant_init()
@@ -3033,8 +3057,8 @@
 	}
 
 	os_memset(&p2p, 0, sizeof(p2p));
-	p2p.msg_ctx = wpa_s;
 	p2p.cb_ctx = wpa_s;
+	p2p.debug_print = wpas_p2p_debug_print;
 	p2p.p2p_scan = wpas_p2p_scan;
 	p2p.send_action = wpas_send_action;
 	p2p.send_action_done = wpas_send_action_done;
@@ -3042,6 +3066,7 @@
 	p2p.go_neg_req_rx = wpas_go_neg_req_rx;
 	p2p.dev_found = wpas_dev_found;
 	p2p.dev_lost = wpas_dev_lost;
+	p2p.find_stopped = wpas_find_stopped;
 	p2p.start_listen = wpas_start_listen;
 	p2p.stop_listen = wpas_stop_listen;
 	p2p.send_probe_resp = wpas_send_probe_resp;
@@ -3338,13 +3363,14 @@
 		eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
 		if (wpa_s->p2p_auto_pd) {
 			wpa_s->p2p_auto_pd = 0;
-			wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
-				" p2p_dev_addr=" MACSTR " status=N/A",
-				MAC2STR(wpa_s->pending_join_dev_addr));
+			wpa_msg_global(wpa_s, MSG_INFO,
+				       P2P_EVENT_PROV_DISC_FAILURE
+				       " p2p_dev_addr=" MACSTR " status=N/A",
+				       MAC2STR(wpa_s->pending_join_dev_addr));
 			return;
 		}
-		wpa_msg(wpa_s->parent, MSG_INFO,
-			P2P_EVENT_GROUP_FORMATION_FAILURE);
+		wpa_msg_global(wpa_s->parent, MSG_INFO,
+			       P2P_EVENT_GROUP_FORMATION_FAILURE);
 	}
 }
 
@@ -3468,9 +3494,10 @@
 				      wpa_s->pending_pd_config_methods, join,
 				      0, wpa_s->user_initiated_pd) < 0) {
 			wpa_s->p2p_auto_pd = 0;
-			wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
-				" p2p_dev_addr=" MACSTR " status=N/A",
-				MAC2STR(wpa_s->pending_join_dev_addr));
+			wpa_msg_global(wpa_s, MSG_INFO,
+				       P2P_EVENT_PROV_DISC_FAILURE
+				       " p2p_dev_addr=" MACSTR " status=N/A",
+				       MAC2STR(wpa_s->pending_join_dev_addr));
 		}
 		return;
 	}
@@ -3532,9 +3559,9 @@
 		u16 method;
 
 		if (wpas_check_freq_conflict(wpa_s, freq) > 0) {
-			wpa_msg(wpa_s->parent, MSG_INFO,
-				P2P_EVENT_GROUP_FORMATION_FAILURE
-				"reason=FREQ_CONFLICT");
+			wpa_msg_global(wpa_s->parent, MSG_INFO,
+				       P2P_EVENT_GROUP_FORMATION_FAILURE
+				       "reason=FREQ_CONFLICT");
 			return;
 		}
 
@@ -4246,13 +4273,14 @@
 
 	if (wpas_p2p_add_group_interface(wpa_s, go ? WPA_IF_P2P_GO :
 					 WPA_IF_P2P_CLIENT) < 0) {
-		wpa_msg(wpa_s, MSG_ERROR, "P2P: Failed to add group interface");
+		wpa_msg_global(wpa_s, MSG_ERROR,
+			       "P2P: Failed to add group interface");
 		return NULL;
 	}
 	group_wpa_s = wpas_p2p_init_group_interface(wpa_s, go);
 	if (group_wpa_s == NULL) {
-		wpa_msg(wpa_s, MSG_ERROR, "P2P: Failed to initialize group "
-			"interface");
+		wpa_msg_global(wpa_s, MSG_ERROR,
+			       "P2P: Failed to initialize group interface");
 		wpas_p2p_remove_pending_group_interface(wpa_s);
 		return NULL;
 	}
@@ -5056,20 +5084,20 @@
 	if (ssid->passphrase == NULL && ssid->psk_set) {
 		char psk[65];
 		wpa_snprintf_hex(psk, sizeof(psk), ssid->psk, 32);
-		wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
-			"%s client ssid=\"%s\" freq=%d psk=%s go_dev_addr="
-			MACSTR "%s",
-			wpa_s->ifname, ssid_txt, freq, psk,
-			MAC2STR(go_dev_addr),
-			persistent ? " [PERSISTENT]" : "");
+		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",
+			       wpa_s->ifname, ssid_txt, freq, psk,
+			       MAC2STR(go_dev_addr),
+			       persistent ? " [PERSISTENT]" : "");
 	} else {
-		wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
-			"%s client ssid=\"%s\" freq=%d passphrase=\"%s\" "
-			"go_dev_addr=" MACSTR "%s",
-			wpa_s->ifname, ssid_txt, freq,
-			ssid->passphrase ? ssid->passphrase : "",
-			MAC2STR(go_dev_addr),
-			persistent ? " [PERSISTENT]" : "");
+		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",
+			       wpa_s->ifname, ssid_txt, freq,
+			       ssid->passphrase ? ssid->passphrase : "",
+			       MAC2STR(go_dev_addr),
+			       persistent ? " [PERSISTENT]" : "");
 	}
 
 	if (persistent)
@@ -5401,9 +5429,10 @@
 
 			iface->cross_connect_enabled = 0;
 			iface->cross_connect_in_use = 0;
-			wpa_msg(iface->parent, MSG_INFO,
-				P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
-				iface->ifname, iface->cross_connect_uplink);
+			wpa_msg_global(iface->parent, MSG_INFO,
+				       P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
+				       iface->ifname,
+				       iface->cross_connect_uplink);
 		}
 	}
 
@@ -5430,9 +5459,9 @@
 			continue;
 
 		iface->cross_connect_in_use = 1;
-		wpa_msg(iface->parent, MSG_INFO,
-			P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
-			iface->ifname, iface->cross_connect_uplink);
+		wpa_msg_global(iface->parent, MSG_INFO,
+			       P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
+			       iface->ifname, iface->cross_connect_uplink);
 	}
 }
 
@@ -5450,9 +5479,9 @@
 		if (!iface->cross_connect_in_use)
 			continue;
 
-		wpa_msg(iface->parent, MSG_INFO,
-			P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
-			iface->ifname, iface->cross_connect_uplink);
+		wpa_msg_global(iface->parent, MSG_INFO,
+			       P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
+			       iface->ifname, iface->cross_connect_uplink);
 		iface->cross_connect_in_use = 0;
 	}
 }
@@ -5512,9 +5541,9 @@
 			break;
 
 		wpa_s->cross_connect_in_use = 1;
-		wpa_msg(wpa_s->parent, MSG_INFO,
-			P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
-			wpa_s->ifname, wpa_s->cross_connect_uplink);
+		wpa_msg_global(wpa_s->parent, MSG_INFO,
+			       P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
+			       wpa_s->ifname, wpa_s->cross_connect_uplink);
 		break;
 	}
 }
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 04148a8..8cd0f1d 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -527,6 +527,63 @@
 }
 
 
+static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
+					  u16 num_modes,
+					  enum hostapd_hw_mode mode)
+{
+	u16 i;
+
+	for (i = 0; i < num_modes; i++) {
+		if (modes[i].mode == mode)
+			return &modes[i];
+	}
+
+	return NULL;
+}
+
+
+static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s,
+					enum hostapd_hw_mode band,
+					struct wpa_driver_scan_params *params)
+{
+	/* Include only supported channels for the specified band */
+	struct hostapd_hw_modes *mode;
+	int count, i;
+
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band);
+	if (mode == NULL) {
+		/* No channels supported in this band - use empty list */
+		params->freqs = os_zalloc(sizeof(int));
+		return;
+	}
+
+	params->freqs = os_zalloc((mode->num_channels + 1) * sizeof(int));
+	if (params->freqs == NULL)
+		return;
+	for (count = 0, i = 0; i < mode->num_channels; i++) {
+		if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
+			continue;
+		params->freqs[count++] = mode->channels[i].freq;
+	}
+}
+
+
+static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s,
+				   struct wpa_driver_scan_params *params)
+{
+	if (wpa_s->hw.modes == NULL)
+		return; /* unknown what channels the driver supports */
+	if (params->freqs)
+		return; /* already using a limited channel set */
+	if (wpa_s->setband == WPA_SETBAND_5G)
+		wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
+					    params);
+	else if (wpa_s->setband == WPA_SETBAND_2G)
+		wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
+					    params);
+}
+
+
 static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
@@ -760,6 +817,7 @@
 	} else
 		os_free(wpa_s->next_scan_freqs);
 	wpa_s->next_scan_freqs = NULL;
+	wpa_setband_scan_freqs(wpa_s, &params);
 
 	/* See if user specified frequencies. If so, scan only those. */
 	if (wpa_s->conf->freq_list && !params.freqs) {
@@ -1136,6 +1194,8 @@
 			wpa_s->sched_scan_interval);
 	}
 
+	wpa_setband_scan_freqs(wpa_s, scan_params);
+
 	ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params,
 					      wpa_s->sched_scan_interval);
 	wpabuf_free(extra_ie);
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 61d4b61..966ee83 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -3386,6 +3386,9 @@
 
 static void try_connection(void *eloop_ctx, void *timeout_ctx)
 {
+	if (ctrl_conn)
+		goto done;
+
 	if (ctrl_ifname == NULL)
 		ctrl_ifname = wpa_cli_get_default_ifname();
 
@@ -3404,6 +3407,7 @@
 	if (warning_displayed)
 		printf("Connection established.\n");
 
+done:
 	start_edit();
 }
 
@@ -3525,7 +3529,7 @@
 #endif /* CONFIG_CTRL_IFACE_UNIX */
 
 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
-	char buf[2048], *pos;
+	char buf[4096], *pos;
 	size_t len;
 	struct wpa_ctrl *ctrl;
 	int ret;
@@ -3619,6 +3623,23 @@
 				global, strerror(errno));
 			return -1;
 		}
+
+		if (interactive) {
+			mon_conn = wpa_ctrl_open(global);
+			if (mon_conn) {
+				if (wpa_ctrl_attach(mon_conn) == 0) {
+					wpa_cli_attached = 1;
+					eloop_register_read_sock(
+						wpa_ctrl_get_fd(mon_conn),
+						wpa_cli_mon_receive,
+						NULL, NULL);
+				} else {
+					printf("Failed to open monitor "
+					       "connection through global "
+					       "control interface\n");
+				}
+			}
+		}
 	}
 
 	eloop_register_signal_terminate(wpa_cli_terminate, NULL);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 1a7c0ff..58605de 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3309,6 +3309,9 @@
 	if (params->ctrl_interface)
 		global->params.ctrl_interface =
 			os_strdup(params->ctrl_interface);
+	if (params->ctrl_interface_group)
+		global->params.ctrl_interface_group =
+			os_strdup(params->ctrl_interface_group);
 	if (params->override_driver)
 		global->params.override_driver =
 			os_strdup(params->override_driver);
@@ -3451,6 +3454,7 @@
 		os_free(global->params.pid_file);
 	}
 	os_free(global->params.ctrl_interface);
+	os_free(global->params.ctrl_interface_group);
 	os_free(global->params.override_driver);
 	os_free(global->params.override_ctrl_interface);
 
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index a2a189b..c971ae4 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -155,6 +155,11 @@
 	char *ctrl_interface;
 
 	/**
+	 * ctrl_interface_group - Global ctrl_iface group
+	 */
+	char *ctrl_interface_group;
+
+	/**
 	 * dbus_ctrl_interface - Enable the DBus control interface
 	 */
 	int dbus_ctrl_interface;
@@ -348,6 +353,8 @@
 	struct wpa_ssid_value *disallow_aps_ssid;
 	size_t disallow_aps_ssid_count;
 
+	enum { WPA_SETBAND_AUTO, WPA_SETBAND_5G, WPA_SETBAND_2G } setband;
+
 	/* previous scan was wildcard when interleaving between
 	 * wildcard scans and specific SSID scan when max_ssids=1 */
 	int prev_scan_wildcard;
@@ -701,6 +708,11 @@
 	u8 wnm_bss_termination_duration[12];
 	struct neighbor_report *wnm_neighbor_report_elements;
 #endif /* CONFIG_WNM */
+
+#ifdef CONFIG_TESTING_GET_GTK
+	u8 last_gtk[32];
+	size_t last_gtk_len;
+#endif /* CONFIG_TESTING_GET_GTK */
 };
 
 
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 1a64df3..40720c5 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -437,6 +437,13 @@
 		/* Clear the MIC error counter when setting a new PTK. */
 		wpa_s->mic_errors_seen = 0;
 	}
+#ifdef CONFIG_TESTING_GET_GTK
+	if (key_idx > 0 && addr && is_broadcast_ether_addr(addr) &&
+	    alg != WPA_ALG_NONE && key_len <= sizeof(wpa_s->last_gtk)) {
+		os_memcpy(wpa_s->last_gtk, key, key_len);
+		wpa_s->last_gtk_len = key_len;
+	}
+#endif /* CONFIG_TESTING_GET_GTK */
 	return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
 			       key, key_len);
 }