1189251Ssam/*
2189251Ssam * WPA Supplicant / UNIX domain socket -based control interface
3281806Srpaulo * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
4189251Ssam *
5252726Srpaulo * This software may be distributed under the terms of the BSD license.
6252726Srpaulo * See README for more details.
7189251Ssam */
8189251Ssam
9189251Ssam#include "includes.h"
10189251Ssam#include <sys/un.h>
11189251Ssam#include <sys/stat.h>
12189251Ssam#include <grp.h>
13189775Ssam#include <stddef.h>
14252726Srpaulo#include <unistd.h>
15252726Srpaulo#include <fcntl.h>
16289549Srpaulo#ifdef __linux__
17289549Srpaulo#include <sys/ioctl.h>
18289549Srpaulo#include <linux/sockios.h>
19289549Srpaulo#endif /* __linux__ */
20252726Srpaulo#ifdef ANDROID
21252726Srpaulo#include <cutils/sockets.h>
22252726Srpaulo#endif /* ANDROID */
23189251Ssam
24214734Srpaulo#include "utils/common.h"
25214734Srpaulo#include "utils/eloop.h"
26214734Srpaulo#include "utils/list.h"
27214734Srpaulo#include "eapol_supp/eapol_supp_sm.h"
28189251Ssam#include "config.h"
29189251Ssam#include "wpa_supplicant_i.h"
30189251Ssam#include "ctrl_iface.h"
31189251Ssam
32189251Ssam/* Per-interface ctrl_iface */
33189251Ssam
34189251Ssam/**
35189251Ssam * struct wpa_ctrl_dst - Internal data structure of control interface monitors
36189251Ssam *
37189251Ssam * This structure is used to store information about registered control
38189251Ssam * interface monitors into struct wpa_supplicant. This data is private to
39189251Ssam * ctrl_iface_unix.c and should not be touched directly from other files.
40189251Ssam */
41189251Ssamstruct wpa_ctrl_dst {
42214734Srpaulo	struct dl_list list;
43189251Ssam	struct sockaddr_un addr;
44189251Ssam	socklen_t addrlen;
45189251Ssam	int debug_level;
46189251Ssam	int errors;
47189251Ssam};
48189251Ssam
49189251Ssam
50189251Ssamstruct ctrl_iface_priv {
51189251Ssam	struct wpa_supplicant *wpa_s;
52189251Ssam	int sock;
53214734Srpaulo	struct dl_list ctrl_dst;
54281806Srpaulo	int android_control_socket;
55189251Ssam};
56189251Ssam
57189251Ssam
58281806Srpaulostruct ctrl_iface_global_priv {
59281806Srpaulo	struct wpa_global *global;
60281806Srpaulo	int sock;
61281806Srpaulo	struct dl_list ctrl_dst;
62281806Srpaulo	int android_control_socket;
63281806Srpaulo};
64281806Srpaulo
65281806Srpaulo
66281806Srpaulostatic void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
67281806Srpaulo					   const char *ifname, int sock,
68281806Srpaulo					   struct dl_list *ctrl_dst,
69189251Ssam					   int level, const char *buf,
70281806Srpaulo					   size_t len,
71281806Srpaulo					   struct ctrl_iface_priv *priv,
72281806Srpaulo					   struct ctrl_iface_global_priv *gp);
73281806Srpaulostatic int wpas_ctrl_iface_reinit(struct wpa_supplicant *wpa_s,
74281806Srpaulo				  struct ctrl_iface_priv *priv);
75281806Srpaulostatic int wpas_ctrl_iface_global_reinit(struct wpa_global *global,
76281806Srpaulo					 struct ctrl_iface_global_priv *priv);
77189251Ssam
78189251Ssam
79289549Srpaulostatic void wpas_ctrl_sock_debug(const char *title, int sock, const char *buf,
80289549Srpaulo				 size_t len)
81289549Srpaulo{
82289549Srpaulo#ifdef __linux__
83289549Srpaulo	socklen_t optlen;
84289549Srpaulo	int sndbuf, outq;
85289549Srpaulo	int level = MSG_MSGDUMP;
86289549Srpaulo
87289549Srpaulo	if (len >= 5 && os_strncmp(buf, "PONG\n", 5) == 0)
88289549Srpaulo		level = MSG_EXCESSIVE;
89289549Srpaulo
90289549Srpaulo	optlen = sizeof(sndbuf);
91289549Srpaulo	sndbuf = 0;
92289549Srpaulo	if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, &optlen) < 0)
93289549Srpaulo		sndbuf = -1;
94289549Srpaulo
95289549Srpaulo	if (ioctl(sock, SIOCOUTQ, &outq) < 0)
96289549Srpaulo		outq = -1;
97289549Srpaulo
98289549Srpaulo	wpa_printf(level,
99289549Srpaulo		   "CTRL-DEBUG: %s: sock=%d sndbuf=%d outq=%d send_len=%d",
100289549Srpaulo		   title, sock, sndbuf, outq, (int) len);
101289549Srpaulo#endif /* __linux__ */
102289549Srpaulo}
103289549Srpaulo
104289549Srpaulo
105281806Srpaulostatic int wpa_supplicant_ctrl_iface_attach(struct dl_list *ctrl_dst,
106189251Ssam					    struct sockaddr_un *from,
107281806Srpaulo					    socklen_t fromlen, int global)
108189251Ssam{
109189251Ssam	struct wpa_ctrl_dst *dst;
110281806Srpaulo	char addr_txt[200];
111189251Ssam
112189251Ssam	dst = os_zalloc(sizeof(*dst));
113189251Ssam	if (dst == NULL)
114189251Ssam		return -1;
115189251Ssam	os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
116189251Ssam	dst->addrlen = fromlen;
117189251Ssam	dst->debug_level = MSG_INFO;
118281806Srpaulo	dl_list_add(ctrl_dst, &dst->list);
119281806Srpaulo	printf_encode(addr_txt, sizeof(addr_txt),
120281806Srpaulo		      (u8 *) from->sun_path,
121281806Srpaulo		      fromlen - offsetof(struct sockaddr_un, sun_path));
122281806Srpaulo	wpa_printf(MSG_DEBUG, "CTRL_IFACE %smonitor attached %s",
123281806Srpaulo		   global ? "global " : "", addr_txt);
124189251Ssam	return 0;
125189251Ssam}
126189251Ssam
127189251Ssam
128281806Srpaulostatic int wpa_supplicant_ctrl_iface_detach(struct dl_list *ctrl_dst,
129189251Ssam					    struct sockaddr_un *from,
130189251Ssam					    socklen_t fromlen)
131189251Ssam{
132214734Srpaulo	struct wpa_ctrl_dst *dst;
133189251Ssam
134281806Srpaulo	dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
135189251Ssam		if (fromlen == dst->addrlen &&
136189251Ssam		    os_memcmp(from->sun_path, dst->addr.sun_path,
137209158Srpaulo			      fromlen - offsetof(struct sockaddr_un, sun_path))
138209158Srpaulo		    == 0) {
139281806Srpaulo			char addr_txt[200];
140281806Srpaulo			printf_encode(addr_txt, sizeof(addr_txt),
141281806Srpaulo				      (u8 *) from->sun_path,
142281806Srpaulo				      fromlen -
143281806Srpaulo				      offsetof(struct sockaddr_un, sun_path));
144281806Srpaulo			wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached %s",
145281806Srpaulo				   addr_txt);
146214734Srpaulo			dl_list_del(&dst->list);
147189251Ssam			os_free(dst);
148189251Ssam			return 0;
149189251Ssam		}
150189251Ssam	}
151189251Ssam	return -1;
152189251Ssam}
153189251Ssam
154189251Ssam
155189251Ssamstatic int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
156189251Ssam					   struct sockaddr_un *from,
157189251Ssam					   socklen_t fromlen,
158189251Ssam					   char *level)
159189251Ssam{
160189251Ssam	struct wpa_ctrl_dst *dst;
161189251Ssam
162189251Ssam	wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
163189251Ssam
164214734Srpaulo	dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) {
165189251Ssam		if (fromlen == dst->addrlen &&
166189251Ssam		    os_memcmp(from->sun_path, dst->addr.sun_path,
167209158Srpaulo			      fromlen - offsetof(struct sockaddr_un, sun_path))
168209158Srpaulo		    == 0) {
169281806Srpaulo			char addr_txt[200];
170189251Ssam			dst->debug_level = atoi(level);
171281806Srpaulo			printf_encode(addr_txt, sizeof(addr_txt),
172281806Srpaulo				      (u8 *) from->sun_path, fromlen -
173281806Srpaulo				      offsetof(struct sockaddr_un, sun_path));
174281806Srpaulo			wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor level to %d for %s",
175281806Srpaulo				   dst->debug_level, addr_txt);
176189251Ssam			return 0;
177189251Ssam		}
178189251Ssam	}
179189251Ssam
180189251Ssam	return -1;
181189251Ssam}
182189251Ssam
183189251Ssam
184189251Ssamstatic void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
185189251Ssam					      void *sock_ctx)
186189251Ssam{
187189251Ssam	struct wpa_supplicant *wpa_s = eloop_ctx;
188189251Ssam	struct ctrl_iface_priv *priv = sock_ctx;
189252726Srpaulo	char buf[4096];
190189251Ssam	int res;
191189251Ssam	struct sockaddr_un from;
192189251Ssam	socklen_t fromlen = sizeof(from);
193281806Srpaulo	char *reply = NULL, *reply_buf = NULL;
194189251Ssam	size_t reply_len = 0;
195189251Ssam	int new_attached = 0;
196189251Ssam
197189251Ssam	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
198189251Ssam		       (struct sockaddr *) &from, &fromlen);
199189251Ssam	if (res < 0) {
200281806Srpaulo		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
201281806Srpaulo			   strerror(errno));
202189251Ssam		return;
203189251Ssam	}
204189251Ssam	buf[res] = '\0';
205189251Ssam
206189251Ssam	if (os_strcmp(buf, "ATTACH") == 0) {
207281806Srpaulo		if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, &from,
208281806Srpaulo						     fromlen, 0))
209189251Ssam			reply_len = 1;
210189251Ssam		else {
211189251Ssam			new_attached = 1;
212189251Ssam			reply_len = 2;
213189251Ssam		}
214189251Ssam	} else if (os_strcmp(buf, "DETACH") == 0) {
215281806Srpaulo		if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, &from,
216281806Srpaulo						     fromlen))
217189251Ssam			reply_len = 1;
218189251Ssam		else
219189251Ssam			reply_len = 2;
220189251Ssam	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
221189251Ssam		if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen,
222189251Ssam						    buf + 6))
223189251Ssam			reply_len = 1;
224189251Ssam		else
225189251Ssam			reply_len = 2;
226189251Ssam	} else {
227281806Srpaulo		reply_buf = wpa_supplicant_ctrl_iface_process(wpa_s, buf,
228281806Srpaulo							      &reply_len);
229281806Srpaulo		reply = reply_buf;
230289549Srpaulo
231289549Srpaulo		/*
232289549Srpaulo		 * There could be some password/key material in the command, so
233289549Srpaulo		 * clear the buffer explicitly now that it is not needed
234289549Srpaulo		 * anymore.
235289549Srpaulo		 */
236289549Srpaulo		os_memset(buf, 0, res);
237189251Ssam	}
238189251Ssam
239281806Srpaulo	if (!reply && reply_len == 1) {
240281806Srpaulo		reply = "FAIL\n";
241281806Srpaulo		reply_len = 5;
242281806Srpaulo	} else if (!reply && reply_len == 2) {
243281806Srpaulo		reply = "OK\n";
244281806Srpaulo		reply_len = 3;
245281806Srpaulo	}
246281806Srpaulo
247189251Ssam	if (reply) {
248289549Srpaulo		wpas_ctrl_sock_debug("ctrl_sock-sendto", sock, reply,
249289549Srpaulo				     reply_len);
250281806Srpaulo		if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
251281806Srpaulo			   fromlen) < 0) {
252281806Srpaulo			int _errno = errno;
253281806Srpaulo			wpa_dbg(wpa_s, MSG_DEBUG,
254281806Srpaulo				"ctrl_iface sendto failed: %d - %s",
255281806Srpaulo				_errno, strerror(_errno));
256281806Srpaulo			if (_errno == ENOBUFS || _errno == EAGAIN) {
257281806Srpaulo				/*
258281806Srpaulo				 * The socket send buffer could be full. This
259281806Srpaulo				 * may happen if client programs are not
260281806Srpaulo				 * receiving their pending messages. Close and
261281806Srpaulo				 * reopen the socket as a workaround to avoid
262281806Srpaulo				 * getting stuck being unable to send any new
263281806Srpaulo				 * responses.
264281806Srpaulo				 */
265281806Srpaulo				sock = wpas_ctrl_iface_reinit(wpa_s, priv);
266281806Srpaulo				if (sock < 0) {
267281806Srpaulo					wpa_dbg(wpa_s, MSG_DEBUG, "Failed to reinitialize ctrl_iface socket");
268281806Srpaulo				}
269281806Srpaulo			}
270281806Srpaulo			if (new_attached) {
271281806Srpaulo				wpa_dbg(wpa_s, MSG_DEBUG, "Failed to send response to ATTACH - detaching");
272281806Srpaulo				new_attached = 0;
273281806Srpaulo				wpa_supplicant_ctrl_iface_detach(
274281806Srpaulo					&priv->ctrl_dst, &from, fromlen);
275281806Srpaulo			}
276281806Srpaulo		}
277189251Ssam	}
278281806Srpaulo	os_free(reply_buf);
279189251Ssam
280189251Ssam	if (new_attached)
281189251Ssam		eapol_sm_notify_ctrl_attached(wpa_s->eapol);
282189251Ssam}
283189251Ssam
284189251Ssam
285189251Ssamstatic char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
286189251Ssam{
287189251Ssam	char *buf;
288189251Ssam	size_t len;
289281806Srpaulo	char *pbuf, *dir = NULL;
290189251Ssam	int res;
291189251Ssam
292189251Ssam	if (wpa_s->conf->ctrl_interface == NULL)
293189251Ssam		return NULL;
294189251Ssam
295189251Ssam	pbuf = os_strdup(wpa_s->conf->ctrl_interface);
296189251Ssam	if (pbuf == NULL)
297189251Ssam		return NULL;
298189251Ssam	if (os_strncmp(pbuf, "DIR=", 4) == 0) {
299281806Srpaulo		char *gid_str;
300189251Ssam		dir = pbuf + 4;
301189251Ssam		gid_str = os_strstr(dir, " GROUP=");
302281806Srpaulo		if (gid_str)
303189251Ssam			*gid_str = '\0';
304189251Ssam	} else
305189251Ssam		dir = pbuf;
306189251Ssam
307189251Ssam	len = os_strlen(dir) + os_strlen(wpa_s->ifname) + 2;
308189251Ssam	buf = os_malloc(len);
309189251Ssam	if (buf == NULL) {
310189251Ssam		os_free(pbuf);
311189251Ssam		return NULL;
312189251Ssam	}
313189251Ssam
314189251Ssam	res = os_snprintf(buf, len, "%s/%s", dir, wpa_s->ifname);
315281806Srpaulo	if (os_snprintf_error(len, res)) {
316189251Ssam		os_free(pbuf);
317189251Ssam		os_free(buf);
318189251Ssam		return NULL;
319189251Ssam	}
320189251Ssam#ifdef __CYGWIN__
321189251Ssam	{
322189251Ssam		/* Windows/WinPcap uses interface names that are not suitable
323189251Ssam		 * as a file name - convert invalid chars to underscores */
324189251Ssam		char *pos = buf;
325189251Ssam		while (*pos) {
326189251Ssam			if (*pos == '\\')
327189251Ssam				*pos = '_';
328189251Ssam			pos++;
329189251Ssam		}
330189251Ssam	}
331189251Ssam#endif /* __CYGWIN__ */
332189251Ssam	os_free(pbuf);
333189251Ssam	return buf;
334189251Ssam}
335189251Ssam
336189251Ssam
337289549Srpaulostatic void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
338289549Srpaulo					     enum wpa_msg_type type,
339189251Ssam					     const char *txt, size_t len)
340189251Ssam{
341189251Ssam	struct wpa_supplicant *wpa_s = ctx;
342281806Srpaulo
343281806Srpaulo	if (wpa_s == NULL)
344189251Ssam		return;
345281806Srpaulo
346289549Srpaulo	if (type != WPA_MSG_NO_GLOBAL && wpa_s->global->ctrl_iface) {
347281806Srpaulo		struct ctrl_iface_global_priv *priv = wpa_s->global->ctrl_iface;
348281806Srpaulo		if (!dl_list_empty(&priv->ctrl_dst)) {
349289549Srpaulo			wpa_supplicant_ctrl_iface_send(
350289549Srpaulo				wpa_s,
351289549Srpaulo				type != WPA_MSG_PER_INTERFACE ?
352289549Srpaulo				NULL : wpa_s->ifname,
353289549Srpaulo				priv->sock, &priv->ctrl_dst, level, txt, len,
354289549Srpaulo				NULL, priv);
355281806Srpaulo		}
356281806Srpaulo	}
357281806Srpaulo
358289549Srpaulo	if (type == WPA_MSG_ONLY_GLOBAL || wpa_s->ctrl_iface == NULL)
359281806Srpaulo		return;
360281806Srpaulo	wpa_supplicant_ctrl_iface_send(wpa_s, NULL, wpa_s->ctrl_iface->sock,
361281806Srpaulo				       &wpa_s->ctrl_iface->ctrl_dst,
362281806Srpaulo				       level, txt, len, wpa_s->ctrl_iface,
363281806Srpaulo				       NULL);
364189251Ssam}
365189251Ssam
366189251Ssam
367281806Srpaulostatic int wpas_ctrl_iface_open_sock(struct wpa_supplicant *wpa_s,
368281806Srpaulo				     struct ctrl_iface_priv *priv)
369189251Ssam{
370189251Ssam	struct sockaddr_un addr;
371189251Ssam	char *fname = NULL;
372189251Ssam	gid_t gid = 0;
373189251Ssam	int gid_set = 0;
374189251Ssam	char *buf, *dir = NULL, *gid_str = NULL;
375189251Ssam	struct group *grp;
376189251Ssam	char *endp;
377252726Srpaulo	int flags;
378189251Ssam
379189251Ssam	buf = os_strdup(wpa_s->conf->ctrl_interface);
380189251Ssam	if (buf == NULL)
381189251Ssam		goto fail;
382252726Srpaulo#ifdef ANDROID
383252726Srpaulo	os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s",
384252726Srpaulo		    wpa_s->conf->ctrl_interface);
385252726Srpaulo	priv->sock = android_get_control_socket(addr.sun_path);
386281806Srpaulo	if (priv->sock >= 0) {
387281806Srpaulo		priv->android_control_socket = 1;
388252726Srpaulo		goto havesock;
389281806Srpaulo	}
390252726Srpaulo#endif /* ANDROID */
391189251Ssam	if (os_strncmp(buf, "DIR=", 4) == 0) {
392189251Ssam		dir = buf + 4;
393189251Ssam		gid_str = os_strstr(dir, " GROUP=");
394189251Ssam		if (gid_str) {
395189251Ssam			*gid_str = '\0';
396189251Ssam			gid_str += 7;
397189251Ssam		}
398189251Ssam	} else {
399189251Ssam		dir = buf;
400189251Ssam		gid_str = wpa_s->conf->ctrl_interface_group;
401189251Ssam	}
402189251Ssam
403189251Ssam	if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) {
404189251Ssam		if (errno == EEXIST) {
405189251Ssam			wpa_printf(MSG_DEBUG, "Using existing control "
406189251Ssam				   "interface directory.");
407189251Ssam		} else {
408281806Srpaulo			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface=%s]: %s",
409281806Srpaulo				   dir, strerror(errno));
410189251Ssam			goto fail;
411189251Ssam		}
412189251Ssam	}
413189251Ssam
414252726Srpaulo#ifdef ANDROID
415252726Srpaulo	/*
416252726Srpaulo	 * wpa_supplicant is started from /init.*.rc on Android and that seems
417252726Srpaulo	 * to be using umask 0077 which would leave the control interface
418252726Srpaulo	 * directory without group access. This breaks things since Wi-Fi
419252726Srpaulo	 * framework assumes that this directory can be accessed by other
420252726Srpaulo	 * applications in the wifi group. Fix this by adding group access even
421252726Srpaulo	 * if umask value would prevent this.
422252726Srpaulo	 */
423252726Srpaulo	if (chmod(dir, S_IRWXU | S_IRWXG) < 0) {
424252726Srpaulo		wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
425252726Srpaulo			   strerror(errno));
426252726Srpaulo		/* Try to continue anyway */
427252726Srpaulo	}
428252726Srpaulo#endif /* ANDROID */
429252726Srpaulo
430189251Ssam	if (gid_str) {
431189251Ssam		grp = getgrnam(gid_str);
432189251Ssam		if (grp) {
433189251Ssam			gid = grp->gr_gid;
434189251Ssam			gid_set = 1;
435189251Ssam			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
436189251Ssam				   " (from group name '%s')",
437189251Ssam				   (int) gid, gid_str);
438189251Ssam		} else {
439189251Ssam			/* Group name not found - try to parse this as gid */
440189251Ssam			gid = strtol(gid_str, &endp, 10);
441189251Ssam			if (*gid_str == '\0' || *endp != '\0') {
442189251Ssam				wpa_printf(MSG_ERROR, "CTRL: Invalid group "
443189251Ssam					   "'%s'", gid_str);
444189251Ssam				goto fail;
445189251Ssam			}
446189251Ssam			gid_set = 1;
447189251Ssam			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
448189251Ssam				   (int) gid);
449189251Ssam		}
450189251Ssam	}
451189251Ssam
452189251Ssam	if (gid_set && chown(dir, -1, gid) < 0) {
453281806Srpaulo		wpa_printf(MSG_ERROR, "chown[ctrl_interface=%s,gid=%d]: %s",
454281806Srpaulo			   dir, (int) gid, strerror(errno));
455189251Ssam		goto fail;
456189251Ssam	}
457189251Ssam
458209158Srpaulo	/* Make sure the group can enter and read the directory */
459209158Srpaulo	if (gid_set &&
460209158Srpaulo	    chmod(dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP) < 0) {
461209158Srpaulo		wpa_printf(MSG_ERROR, "CTRL: chmod[ctrl_interface]: %s",
462209158Srpaulo			   strerror(errno));
463209158Srpaulo		goto fail;
464209158Srpaulo	}
465209158Srpaulo
466189251Ssam	if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >=
467189251Ssam	    sizeof(addr.sun_path)) {
468189251Ssam		wpa_printf(MSG_ERROR, "ctrl_iface path limit exceeded");
469189251Ssam		goto fail;
470189251Ssam	}
471189251Ssam
472189251Ssam	priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
473189251Ssam	if (priv->sock < 0) {
474281806Srpaulo		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
475189251Ssam		goto fail;
476189251Ssam	}
477189251Ssam
478189251Ssam	os_memset(&addr, 0, sizeof(addr));
479214734Srpaulo#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
480189775Ssam	addr.sun_len = sizeof(addr);
481209158Srpaulo#endif /* __FreeBSD__ */
482189251Ssam	addr.sun_family = AF_UNIX;
483189251Ssam	fname = wpa_supplicant_ctrl_iface_path(wpa_s);
484189251Ssam	if (fname == NULL)
485189251Ssam		goto fail;
486189251Ssam	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
487189251Ssam	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
488189251Ssam		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
489189251Ssam			   strerror(errno));
490189251Ssam		if (connect(priv->sock, (struct sockaddr *) &addr,
491189251Ssam			    sizeof(addr)) < 0) {
492189251Ssam			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
493189251Ssam				   " allow connections - assuming it was left"
494189251Ssam				   "over from forced program termination");
495189251Ssam			if (unlink(fname) < 0) {
496281806Srpaulo				wpa_printf(MSG_ERROR,
497281806Srpaulo					   "Could not unlink existing ctrl_iface socket '%s': %s",
498281806Srpaulo					   fname, strerror(errno));
499189251Ssam				goto fail;
500189251Ssam			}
501189251Ssam			if (bind(priv->sock, (struct sockaddr *) &addr,
502189251Ssam				 sizeof(addr)) < 0) {
503281806Srpaulo				wpa_printf(MSG_ERROR, "supp-ctrl-iface-init: bind(PF_UNIX): %s",
504281806Srpaulo					   strerror(errno));
505189251Ssam				goto fail;
506189251Ssam			}
507189251Ssam			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
508189251Ssam				   "ctrl_iface socket '%s'", fname);
509189251Ssam		} else {
510189251Ssam			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
511189251Ssam				   "be in use - cannot override it");
512189251Ssam			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
513189251Ssam				   "not used anymore", fname);
514189251Ssam			os_free(fname);
515189251Ssam			fname = NULL;
516189251Ssam			goto fail;
517189251Ssam		}
518189251Ssam	}
519189251Ssam
520189251Ssam	if (gid_set && chown(fname, -1, gid) < 0) {
521281806Srpaulo		wpa_printf(MSG_ERROR, "chown[ctrl_interface=%s,gid=%d]: %s",
522281806Srpaulo			   fname, (int) gid, strerror(errno));
523189251Ssam		goto fail;
524189251Ssam	}
525189251Ssam
526189251Ssam	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
527281806Srpaulo		wpa_printf(MSG_ERROR, "chmod[ctrl_interface=%s]: %s",
528281806Srpaulo			   fname, strerror(errno));
529189251Ssam		goto fail;
530189251Ssam	}
531189251Ssam	os_free(fname);
532189251Ssam
533252726Srpaulo#ifdef ANDROID
534252726Srpaulohavesock:
535252726Srpaulo#endif /* ANDROID */
536252726Srpaulo
537252726Srpaulo	/*
538252726Srpaulo	 * Make socket non-blocking so that we don't hang forever if
539252726Srpaulo	 * target dies unexpectedly.
540252726Srpaulo	 */
541252726Srpaulo	flags = fcntl(priv->sock, F_GETFL);
542252726Srpaulo	if (flags >= 0) {
543252726Srpaulo		flags |= O_NONBLOCK;
544252726Srpaulo		if (fcntl(priv->sock, F_SETFL, flags) < 0) {
545281806Srpaulo			wpa_printf(MSG_INFO, "fcntl(ctrl, O_NONBLOCK): %s",
546281806Srpaulo				   strerror(errno));
547252726Srpaulo			/* Not fatal, continue on.*/
548252726Srpaulo		}
549252726Srpaulo	}
550252726Srpaulo
551189251Ssam	eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
552189251Ssam				 wpa_s, priv);
553189251Ssam	wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
554189251Ssam
555189251Ssam	os_free(buf);
556281806Srpaulo	return 0;
557189251Ssam
558189251Ssamfail:
559281806Srpaulo	if (priv->sock >= 0) {
560189251Ssam		close(priv->sock);
561281806Srpaulo		priv->sock = -1;
562281806Srpaulo	}
563189251Ssam	if (fname) {
564189251Ssam		unlink(fname);
565189251Ssam		os_free(fname);
566189251Ssam	}
567189251Ssam	os_free(buf);
568281806Srpaulo	return -1;
569189251Ssam}
570189251Ssam
571189251Ssam
572281806Srpaulostruct ctrl_iface_priv *
573281806Srpaulowpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
574281806Srpaulo{
575281806Srpaulo	struct ctrl_iface_priv *priv;
576281806Srpaulo
577281806Srpaulo	priv = os_zalloc(sizeof(*priv));
578281806Srpaulo	if (priv == NULL)
579281806Srpaulo		return NULL;
580281806Srpaulo	dl_list_init(&priv->ctrl_dst);
581281806Srpaulo	priv->wpa_s = wpa_s;
582281806Srpaulo	priv->sock = -1;
583281806Srpaulo
584281806Srpaulo	if (wpa_s->conf->ctrl_interface == NULL)
585281806Srpaulo		return priv;
586281806Srpaulo
587289549Srpaulo#ifdef ANDROID
588289549Srpaulo	if (wpa_s->global->params.ctrl_interface) {
589289549Srpaulo		int same = 0;
590289549Srpaulo
591289549Srpaulo		if (wpa_s->global->params.ctrl_interface[0] == '/') {
592289549Srpaulo			if (os_strcmp(wpa_s->global->params.ctrl_interface,
593289549Srpaulo				      wpa_s->conf->ctrl_interface) == 0)
594289549Srpaulo				same = 1;
595289549Srpaulo		} else if (os_strncmp(wpa_s->global->params.ctrl_interface,
596289549Srpaulo				      "@android:", 9) == 0 ||
597289549Srpaulo			   os_strncmp(wpa_s->global->params.ctrl_interface,
598289549Srpaulo				      "@abstract:", 10) == 0) {
599289549Srpaulo			char *pos;
600289549Srpaulo
601289549Srpaulo			/*
602289549Srpaulo			 * Currently, Android uses @android:wpa_* as the naming
603289549Srpaulo			 * convention for the global ctrl interface. This logic
604289549Srpaulo			 * needs to be revisited if the above naming convention
605289549Srpaulo			 * is modified.
606289549Srpaulo			 */
607289549Srpaulo			pos = os_strchr(wpa_s->global->params.ctrl_interface,
608289549Srpaulo					'_');
609289549Srpaulo			if (pos &&
610289549Srpaulo			    os_strcmp(pos + 1,
611289549Srpaulo				      wpa_s->conf->ctrl_interface) == 0)
612289549Srpaulo				same = 1;
613289549Srpaulo		}
614289549Srpaulo
615289549Srpaulo		if (same) {
616289549Srpaulo			/*
617289549Srpaulo			 * The invalid configuration combination might be
618289549Srpaulo			 * possible to hit in an Android OTA upgrade case, so
619289549Srpaulo			 * instead of refusing to start the wpa_supplicant
620289549Srpaulo			 * process, do not open the per-interface ctrl_iface
621289549Srpaulo			 * and continue with the global control interface that
622289549Srpaulo			 * was set from the command line since the Wi-Fi
623289549Srpaulo			 * framework will use it for operations.
624289549Srpaulo			 */
625289549Srpaulo			wpa_printf(MSG_ERROR,
626289549Srpaulo				   "global ctrl interface %s matches ctrl interface %s - do not open per-interface ctrl interface",
627289549Srpaulo				   wpa_s->global->params.ctrl_interface,
628289549Srpaulo				   wpa_s->conf->ctrl_interface);
629289549Srpaulo			return priv;
630289549Srpaulo		}
631289549Srpaulo	}
632289549Srpaulo#endif /* ANDROID */
633289549Srpaulo
634281806Srpaulo	if (wpas_ctrl_iface_open_sock(wpa_s, priv) < 0) {
635281806Srpaulo		os_free(priv);
636281806Srpaulo		return NULL;
637281806Srpaulo	}
638281806Srpaulo
639281806Srpaulo	return priv;
640281806Srpaulo}
641281806Srpaulo
642281806Srpaulo
643281806Srpaulostatic int wpas_ctrl_iface_reinit(struct wpa_supplicant *wpa_s,
644281806Srpaulo				  struct ctrl_iface_priv *priv)
645281806Srpaulo{
646281806Srpaulo	int res;
647281806Srpaulo
648281806Srpaulo	if (priv->sock <= 0)
649281806Srpaulo		return -1;
650281806Srpaulo
651281806Srpaulo	/*
652281806Srpaulo	 * On Android, the control socket being used may be the socket
653281806Srpaulo	 * that is created when wpa_supplicant is started as a /init.*.rc
654281806Srpaulo	 * service. Such a socket is maintained as a key-value pair in
655281806Srpaulo	 * Android's environment. Closing this control socket would leave us
656281806Srpaulo	 * in a bad state with an invalid socket descriptor.
657281806Srpaulo	 */
658281806Srpaulo	if (priv->android_control_socket)
659281806Srpaulo		return priv->sock;
660281806Srpaulo
661281806Srpaulo	eloop_unregister_read_sock(priv->sock);
662281806Srpaulo	close(priv->sock);
663281806Srpaulo	priv->sock = -1;
664281806Srpaulo	res = wpas_ctrl_iface_open_sock(wpa_s, priv);
665281806Srpaulo	if (res < 0)
666281806Srpaulo		return -1;
667281806Srpaulo	return priv->sock;
668281806Srpaulo}
669281806Srpaulo
670281806Srpaulo
671189251Ssamvoid wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
672189251Ssam{
673189251Ssam	struct wpa_ctrl_dst *dst, *prev;
674189251Ssam
675189251Ssam	if (priv->sock > -1) {
676189251Ssam		char *fname;
677281806Srpaulo		char *buf, *dir = NULL;
678189251Ssam		eloop_unregister_read_sock(priv->sock);
679214734Srpaulo		if (!dl_list_empty(&priv->ctrl_dst)) {
680189251Ssam			/*
681281806Srpaulo			 * Wait before closing the control socket if
682189251Ssam			 * there are any attached monitors in order to allow
683189251Ssam			 * them to receive any pending messages.
684189251Ssam			 */
685189251Ssam			wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
686189251Ssam				   "monitors to receive messages");
687281806Srpaulo			os_sleep(0, 100000);
688189251Ssam		}
689189251Ssam		close(priv->sock);
690189251Ssam		priv->sock = -1;
691189251Ssam		fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s);
692189251Ssam		if (fname) {
693189251Ssam			unlink(fname);
694189251Ssam			os_free(fname);
695189251Ssam		}
696189251Ssam
697281806Srpaulo		if (priv->wpa_s->conf->ctrl_interface == NULL)
698281806Srpaulo			goto free_dst;
699189251Ssam		buf = os_strdup(priv->wpa_s->conf->ctrl_interface);
700189251Ssam		if (buf == NULL)
701189251Ssam			goto free_dst;
702189251Ssam		if (os_strncmp(buf, "DIR=", 4) == 0) {
703281806Srpaulo			char *gid_str;
704189251Ssam			dir = buf + 4;
705189251Ssam			gid_str = os_strstr(dir, " GROUP=");
706281806Srpaulo			if (gid_str)
707189251Ssam				*gid_str = '\0';
708189251Ssam		} else
709189251Ssam			dir = buf;
710189251Ssam
711189251Ssam		if (rmdir(dir) < 0) {
712189251Ssam			if (errno == ENOTEMPTY) {
713189251Ssam				wpa_printf(MSG_DEBUG, "Control interface "
714189251Ssam					   "directory not empty - leaving it "
715189251Ssam					   "behind");
716189251Ssam			} else {
717281806Srpaulo				wpa_printf(MSG_ERROR,
718281806Srpaulo					   "rmdir[ctrl_interface=%s]: %s",
719281806Srpaulo					   dir, strerror(errno));
720189251Ssam			}
721189251Ssam		}
722189251Ssam		os_free(buf);
723189251Ssam	}
724189251Ssam
725189251Ssamfree_dst:
726214734Srpaulo	dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
727214734Srpaulo			      list)
728214734Srpaulo		os_free(dst);
729189251Ssam	os_free(priv);
730189251Ssam}
731189251Ssam
732189251Ssam
733189251Ssam/**
734189251Ssam * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors
735281806Srpaulo * @ifname: Interface name for global control socket or %NULL
736281806Srpaulo * @sock: Local socket fd
737281806Srpaulo * @ctrl_dst: List of attached listeners
738189251Ssam * @level: Priority level of the message
739189251Ssam * @buf: Message data
740189251Ssam * @len: Message length
741189251Ssam *
742189251Ssam * Send a packet to all monitor programs attached to the control interface.
743189251Ssam */
744281806Srpaulostatic void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
745281806Srpaulo					   const char *ifname, int sock,
746281806Srpaulo					   struct dl_list *ctrl_dst,
747189251Ssam					   int level, const char *buf,
748281806Srpaulo					   size_t len,
749281806Srpaulo					   struct ctrl_iface_priv *priv,
750281806Srpaulo					   struct ctrl_iface_global_priv *gp)
751189251Ssam{
752189251Ssam	struct wpa_ctrl_dst *dst, *next;
753189251Ssam	char levelstr[10];
754189251Ssam	int idx, res;
755189251Ssam	struct msghdr msg;
756281806Srpaulo	struct iovec io[5];
757189251Ssam
758281806Srpaulo	if (sock < 0 || dl_list_empty(ctrl_dst))
759189251Ssam		return;
760189251Ssam
761189251Ssam	res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
762281806Srpaulo	if (os_snprintf_error(sizeof(levelstr), res))
763189251Ssam		return;
764281806Srpaulo	idx = 0;
765281806Srpaulo	if (ifname) {
766281806Srpaulo		io[idx].iov_base = "IFNAME=";
767281806Srpaulo		io[idx].iov_len = 7;
768281806Srpaulo		idx++;
769281806Srpaulo		io[idx].iov_base = (char *) ifname;
770281806Srpaulo		io[idx].iov_len = os_strlen(ifname);
771281806Srpaulo		idx++;
772281806Srpaulo		io[idx].iov_base = " ";
773281806Srpaulo		io[idx].iov_len = 1;
774281806Srpaulo		idx++;
775281806Srpaulo	}
776281806Srpaulo	io[idx].iov_base = levelstr;
777281806Srpaulo	io[idx].iov_len = os_strlen(levelstr);
778281806Srpaulo	idx++;
779281806Srpaulo	io[idx].iov_base = (char *) buf;
780281806Srpaulo	io[idx].iov_len = len;
781281806Srpaulo	idx++;
782189251Ssam	os_memset(&msg, 0, sizeof(msg));
783189251Ssam	msg.msg_iov = io;
784281806Srpaulo	msg.msg_iovlen = idx;
785189251Ssam
786281806Srpaulo	dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
787281806Srpaulo		int _errno;
788281806Srpaulo		char addr_txt[200];
789281806Srpaulo
790281806Srpaulo		if (level < dst->debug_level)
791281806Srpaulo			continue;
792281806Srpaulo
793281806Srpaulo		printf_encode(addr_txt, sizeof(addr_txt),
794281806Srpaulo			      (u8 *) dst->addr.sun_path, dst->addrlen -
795281806Srpaulo			      offsetof(struct sockaddr_un, sun_path));
796281806Srpaulo		msg.msg_name = (void *) &dst->addr;
797281806Srpaulo		msg.msg_namelen = dst->addrlen;
798289549Srpaulo		wpas_ctrl_sock_debug("ctrl_sock-sendmsg", sock, buf, len);
799281806Srpaulo		if (sendmsg(sock, &msg, MSG_DONTWAIT) >= 0) {
800289549Srpaulo			wpa_printf(MSG_MSGDUMP,
801289549Srpaulo				   "CTRL_IFACE monitor sent successfully to %s",
802281806Srpaulo				   addr_txt);
803281806Srpaulo			dst->errors = 0;
804281806Srpaulo			continue;
805189251Ssam		}
806281806Srpaulo
807281806Srpaulo		_errno = errno;
808281806Srpaulo		wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor[%s]: %d - %s",
809281806Srpaulo			   addr_txt, errno, strerror(errno));
810281806Srpaulo		dst->errors++;
811281806Srpaulo
812281806Srpaulo		if (dst->errors > 10 || _errno == ENOENT || _errno == EPERM) {
813281806Srpaulo			wpa_printf(MSG_INFO, "CTRL_IFACE: Detach monitor %s that cannot receive messages",
814281806Srpaulo				addr_txt);
815281806Srpaulo			wpa_supplicant_ctrl_iface_detach(ctrl_dst, &dst->addr,
816281806Srpaulo							 dst->addrlen);
817281806Srpaulo		}
818281806Srpaulo
819281806Srpaulo		if (_errno == ENOBUFS || _errno == EAGAIN) {
820281806Srpaulo			/*
821281806Srpaulo			 * The socket send buffer could be full. This may happen
822281806Srpaulo			 * if client programs are not receiving their pending
823281806Srpaulo			 * messages. Close and reopen the socket as a workaround
824281806Srpaulo			 * to avoid getting stuck being unable to send any new
825281806Srpaulo			 * responses.
826281806Srpaulo			 */
827281806Srpaulo			if (priv)
828281806Srpaulo				sock = wpas_ctrl_iface_reinit(wpa_s, priv);
829281806Srpaulo			else if (gp)
830281806Srpaulo				sock = wpas_ctrl_iface_global_reinit(
831281806Srpaulo					wpa_s->global, gp);
832281806Srpaulo			else
833281806Srpaulo				break;
834281806Srpaulo			if (sock < 0) {
835281806Srpaulo				wpa_dbg(wpa_s, MSG_DEBUG,
836281806Srpaulo					"Failed to reinitialize ctrl_iface socket");
837281806Srpaulo				break;
838281806Srpaulo			}
839281806Srpaulo		}
840189251Ssam	}
841189251Ssam}
842189251Ssam
843189251Ssam
844189251Ssamvoid wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
845189251Ssam{
846189251Ssam	char buf[256];
847189251Ssam	int res;
848189251Ssam	struct sockaddr_un from;
849189251Ssam	socklen_t fromlen = sizeof(from);
850189251Ssam
851189251Ssam	for (;;) {
852189251Ssam		wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to "
853189251Ssam			   "attach", priv->wpa_s->ifname);
854189251Ssam		eloop_wait_for_read_sock(priv->sock);
855189251Ssam
856189251Ssam		res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0,
857189251Ssam			       (struct sockaddr *) &from, &fromlen);
858189251Ssam		if (res < 0) {
859281806Srpaulo			wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
860281806Srpaulo				   strerror(errno));
861189251Ssam			continue;
862189251Ssam		}
863189251Ssam		buf[res] = '\0';
864189251Ssam
865189251Ssam		if (os_strcmp(buf, "ATTACH") == 0) {
866189251Ssam			/* handle ATTACH signal of first monitor interface */
867281806Srpaulo			if (!wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst,
868281806Srpaulo							      &from, fromlen,
869281806Srpaulo							      0)) {
870281806Srpaulo				if (sendto(priv->sock, "OK\n", 3, 0,
871281806Srpaulo					   (struct sockaddr *) &from, fromlen) <
872281806Srpaulo				    0) {
873281806Srpaulo					wpa_printf(MSG_DEBUG, "ctrl_iface sendto failed: %s",
874281806Srpaulo						   strerror(errno));
875281806Srpaulo				}
876189251Ssam				/* OK to continue */
877189251Ssam				return;
878189251Ssam			} else {
879281806Srpaulo				if (sendto(priv->sock, "FAIL\n", 5, 0,
880281806Srpaulo					   (struct sockaddr *) &from, fromlen) <
881281806Srpaulo				    0) {
882281806Srpaulo					wpa_printf(MSG_DEBUG, "ctrl_iface sendto failed: %s",
883281806Srpaulo						   strerror(errno));
884281806Srpaulo				}
885189251Ssam			}
886189251Ssam		} else {
887189251Ssam			/* return FAIL for all other signals */
888281806Srpaulo			if (sendto(priv->sock, "FAIL\n", 5, 0,
889281806Srpaulo				   (struct sockaddr *) &from, fromlen) < 0) {
890281806Srpaulo				wpa_printf(MSG_DEBUG,
891281806Srpaulo					   "ctrl_iface sendto failed: %s",
892281806Srpaulo					   strerror(errno));
893281806Srpaulo			}
894189251Ssam		}
895189251Ssam	}
896189251Ssam}
897189251Ssam
898189251Ssam
899189251Ssam/* Global ctrl_iface */
900189251Ssam
901189251Ssamstatic void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
902189251Ssam						     void *sock_ctx)
903189251Ssam{
904189251Ssam	struct wpa_global *global = eloop_ctx;
905281806Srpaulo	struct ctrl_iface_global_priv *priv = sock_ctx;
906281806Srpaulo	char buf[4096];
907189251Ssam	int res;
908189251Ssam	struct sockaddr_un from;
909189251Ssam	socklen_t fromlen = sizeof(from);
910281806Srpaulo	char *reply = NULL, *reply_buf = NULL;
911189251Ssam	size_t reply_len;
912189251Ssam
913189251Ssam	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
914189251Ssam		       (struct sockaddr *) &from, &fromlen);
915189251Ssam	if (res < 0) {
916281806Srpaulo		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
917281806Srpaulo			   strerror(errno));
918189251Ssam		return;
919189251Ssam	}
920189251Ssam	buf[res] = '\0';
921189251Ssam
922281806Srpaulo	if (os_strcmp(buf, "ATTACH") == 0) {
923281806Srpaulo		if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, &from,
924281806Srpaulo						     fromlen, 1))
925281806Srpaulo			reply_len = 1;
926281806Srpaulo		else
927281806Srpaulo			reply_len = 2;
928281806Srpaulo	} else if (os_strcmp(buf, "DETACH") == 0) {
929281806Srpaulo		if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, &from,
930281806Srpaulo						     fromlen))
931281806Srpaulo			reply_len = 1;
932281806Srpaulo		else
933281806Srpaulo			reply_len = 2;
934281806Srpaulo	} else {
935281806Srpaulo		reply_buf = wpa_supplicant_global_ctrl_iface_process(
936281806Srpaulo			global, buf, &reply_len);
937281806Srpaulo		reply = reply_buf;
938289549Srpaulo
939289549Srpaulo		/*
940289549Srpaulo		 * There could be some password/key material in the command, so
941289549Srpaulo		 * clear the buffer explicitly now that it is not needed
942289549Srpaulo		 * anymore.
943289549Srpaulo		 */
944289549Srpaulo		os_memset(buf, 0, res);
945281806Srpaulo	}
946189251Ssam
947281806Srpaulo	if (!reply && reply_len == 1) {
948281806Srpaulo		reply = "FAIL\n";
949281806Srpaulo		reply_len = 5;
950281806Srpaulo	} else if (!reply && reply_len == 2) {
951281806Srpaulo		reply = "OK\n";
952281806Srpaulo		reply_len = 3;
953281806Srpaulo	}
954281806Srpaulo
955189251Ssam	if (reply) {
956289549Srpaulo		wpas_ctrl_sock_debug("global_ctrl_sock-sendto",
957289549Srpaulo				     sock, reply, reply_len);
958281806Srpaulo		if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
959281806Srpaulo			   fromlen) < 0) {
960281806Srpaulo			wpa_printf(MSG_DEBUG, "ctrl_iface sendto failed: %s",
961281806Srpaulo				strerror(errno));
962281806Srpaulo		}
963189251Ssam	}
964281806Srpaulo	os_free(reply_buf);
965189251Ssam}
966189251Ssam
967189251Ssam
968281806Srpaulostatic int wpas_global_ctrl_iface_open_sock(struct wpa_global *global,
969281806Srpaulo					    struct ctrl_iface_global_priv *priv)
970189251Ssam{
971189251Ssam	struct sockaddr_un addr;
972281806Srpaulo	const char *ctrl = global->params.ctrl_interface;
973281806Srpaulo	int flags;
974189251Ssam
975281806Srpaulo	wpa_printf(MSG_DEBUG, "Global control interface '%s'", ctrl);
976189251Ssam
977252726Srpaulo#ifdef ANDROID
978281806Srpaulo	if (os_strncmp(ctrl, "@android:", 9) == 0) {
979281806Srpaulo		priv->sock = android_get_control_socket(ctrl + 9);
980281806Srpaulo		if (priv->sock < 0) {
981281806Srpaulo			wpa_printf(MSG_ERROR, "Failed to open Android control "
982281806Srpaulo				   "socket '%s'", ctrl + 9);
983281806Srpaulo			goto fail;
984281806Srpaulo		}
985281806Srpaulo		wpa_printf(MSG_DEBUG, "Using Android control socket '%s'",
986281806Srpaulo			   ctrl + 9);
987281806Srpaulo		priv->android_control_socket = 1;
988252726Srpaulo		goto havesock;
989281806Srpaulo	}
990281806Srpaulo
991281806Srpaulo	if (os_strncmp(ctrl, "@abstract:", 10) != 0) {
992281806Srpaulo		/*
993281806Srpaulo		 * Backwards compatibility - try to open an Android control
994281806Srpaulo		 * socket and if that fails, assume this was a UNIX domain
995281806Srpaulo		 * socket instead.
996281806Srpaulo		 */
997281806Srpaulo		priv->sock = android_get_control_socket(ctrl);
998281806Srpaulo		if (priv->sock >= 0) {
999281806Srpaulo			wpa_printf(MSG_DEBUG,
1000281806Srpaulo				   "Using Android control socket '%s'",
1001281806Srpaulo				   ctrl);
1002281806Srpaulo			priv->android_control_socket = 1;
1003281806Srpaulo			goto havesock;
1004281806Srpaulo		}
1005281806Srpaulo	}
1006252726Srpaulo#endif /* ANDROID */
1007252726Srpaulo
1008189251Ssam	priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
1009189251Ssam	if (priv->sock < 0) {
1010281806Srpaulo		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
1011189251Ssam		goto fail;
1012189251Ssam	}
1013189251Ssam
1014189251Ssam	os_memset(&addr, 0, sizeof(addr));
1015214734Srpaulo#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1016189775Ssam	addr.sun_len = sizeof(addr);
1017209158Srpaulo#endif /* __FreeBSD__ */
1018189251Ssam	addr.sun_family = AF_UNIX;
1019281806Srpaulo
1020281806Srpaulo	if (os_strncmp(ctrl, "@abstract:", 10) == 0) {
1021281806Srpaulo		addr.sun_path[0] = '\0';
1022281806Srpaulo		os_strlcpy(addr.sun_path + 1, ctrl + 10,
1023281806Srpaulo			   sizeof(addr.sun_path) - 1);
1024281806Srpaulo		if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) <
1025281806Srpaulo		    0) {
1026281806Srpaulo			wpa_printf(MSG_ERROR, "supp-global-ctrl-iface-init: "
1027281806Srpaulo				   "bind(PF_UNIX;%s) failed: %s",
1028281806Srpaulo				   ctrl, strerror(errno));
1029281806Srpaulo			goto fail;
1030281806Srpaulo		}
1031281806Srpaulo		wpa_printf(MSG_DEBUG, "Using Abstract control socket '%s'",
1032281806Srpaulo			   ctrl + 10);
1033281806Srpaulo		goto havesock;
1034281806Srpaulo	}
1035281806Srpaulo
1036281806Srpaulo	os_strlcpy(addr.sun_path, ctrl, sizeof(addr.sun_path));
1037189251Ssam	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1038281806Srpaulo		wpa_printf(MSG_INFO, "supp-global-ctrl-iface-init(%s) (will try fixup): bind(PF_UNIX): %s",
1039281806Srpaulo			   ctrl, strerror(errno));
1040189251Ssam		if (connect(priv->sock, (struct sockaddr *) &addr,
1041189251Ssam			    sizeof(addr)) < 0) {
1042189251Ssam			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1043189251Ssam				   " allow connections - assuming it was left"
1044189251Ssam				   "over from forced program termination");
1045281806Srpaulo			if (unlink(ctrl) < 0) {
1046281806Srpaulo				wpa_printf(MSG_ERROR,
1047281806Srpaulo					   "Could not unlink existing ctrl_iface socket '%s': %s",
1048281806Srpaulo					   ctrl, strerror(errno));
1049189251Ssam				goto fail;
1050189251Ssam			}
1051189251Ssam			if (bind(priv->sock, (struct sockaddr *) &addr,
1052189251Ssam				 sizeof(addr)) < 0) {
1053281806Srpaulo				wpa_printf(MSG_ERROR, "supp-glb-iface-init: bind(PF_UNIX;%s): %s",
1054281806Srpaulo					   ctrl, strerror(errno));
1055189251Ssam				goto fail;
1056189251Ssam			}
1057189251Ssam			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1058189251Ssam				   "ctrl_iface socket '%s'",
1059281806Srpaulo				   ctrl);
1060189251Ssam		} else {
1061189251Ssam			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1062189251Ssam				   "be in use - cannot override it");
1063189251Ssam			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1064189251Ssam				   "not used anymore",
1065281806Srpaulo				   ctrl);
1066189251Ssam			goto fail;
1067189251Ssam		}
1068189251Ssam	}
1069189251Ssam
1070281806Srpaulo	wpa_printf(MSG_DEBUG, "Using UNIX control socket '%s'", ctrl);
1071281806Srpaulo
1072281806Srpaulo	if (global->params.ctrl_interface_group) {
1073281806Srpaulo		char *gid_str = global->params.ctrl_interface_group;
1074281806Srpaulo		gid_t gid = 0;
1075281806Srpaulo		struct group *grp;
1076281806Srpaulo		char *endp;
1077281806Srpaulo
1078281806Srpaulo		grp = getgrnam(gid_str);
1079281806Srpaulo		if (grp) {
1080281806Srpaulo			gid = grp->gr_gid;
1081281806Srpaulo			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
1082281806Srpaulo				   " (from group name '%s')",
1083281806Srpaulo				   (int) gid, gid_str);
1084281806Srpaulo		} else {
1085281806Srpaulo			/* Group name not found - try to parse this as gid */
1086281806Srpaulo			gid = strtol(gid_str, &endp, 10);
1087281806Srpaulo			if (*gid_str == '\0' || *endp != '\0') {
1088281806Srpaulo				wpa_printf(MSG_ERROR, "CTRL: Invalid group "
1089281806Srpaulo					   "'%s'", gid_str);
1090281806Srpaulo				goto fail;
1091281806Srpaulo			}
1092281806Srpaulo			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
1093281806Srpaulo				   (int) gid);
1094281806Srpaulo		}
1095281806Srpaulo		if (chown(ctrl, -1, gid) < 0) {
1096281806Srpaulo			wpa_printf(MSG_ERROR,
1097281806Srpaulo				   "chown[global_ctrl_interface=%s,gid=%d]: %s",
1098281806Srpaulo				   ctrl, (int) gid, strerror(errno));
1099281806Srpaulo			goto fail;
1100281806Srpaulo		}
1101281806Srpaulo
1102281806Srpaulo		if (chmod(ctrl, S_IRWXU | S_IRWXG) < 0) {
1103281806Srpaulo			wpa_printf(MSG_ERROR,
1104281806Srpaulo				   "chmod[global_ctrl_interface=%s]: %s",
1105281806Srpaulo				   ctrl, strerror(errno));
1106281806Srpaulo			goto fail;
1107281806Srpaulo		}
1108281806Srpaulo	} else {
1109281806Srpaulo		if (chmod(ctrl, S_IRWXU) < 0) {
1110281806Srpaulo			wpa_printf(MSG_DEBUG,
1111281806Srpaulo				   "chmod[global_ctrl_interface=%s](S_IRWXU): %s",
1112281806Srpaulo				   ctrl, strerror(errno));
1113281806Srpaulo			/* continue anyway since group change was not required
1114281806Srpaulo			 */
1115281806Srpaulo		}
1116281806Srpaulo	}
1117281806Srpaulo
1118252726Srpaulohavesock:
1119281806Srpaulo
1120281806Srpaulo	/*
1121281806Srpaulo	 * Make socket non-blocking so that we don't hang forever if
1122281806Srpaulo	 * target dies unexpectedly.
1123281806Srpaulo	 */
1124281806Srpaulo	flags = fcntl(priv->sock, F_GETFL);
1125281806Srpaulo	if (flags >= 0) {
1126281806Srpaulo		flags |= O_NONBLOCK;
1127281806Srpaulo		if (fcntl(priv->sock, F_SETFL, flags) < 0) {
1128281806Srpaulo			wpa_printf(MSG_INFO, "fcntl(ctrl, O_NONBLOCK): %s",
1129281806Srpaulo				   strerror(errno));
1130281806Srpaulo			/* Not fatal, continue on.*/
1131281806Srpaulo		}
1132281806Srpaulo	}
1133281806Srpaulo
1134189251Ssam	eloop_register_read_sock(priv->sock,
1135189251Ssam				 wpa_supplicant_global_ctrl_iface_receive,
1136281806Srpaulo				 global, priv);
1137189251Ssam
1138281806Srpaulo	return 0;
1139189251Ssam
1140189251Ssamfail:
1141281806Srpaulo	if (priv->sock >= 0) {
1142189251Ssam		close(priv->sock);
1143281806Srpaulo		priv->sock = -1;
1144281806Srpaulo	}
1145281806Srpaulo	return -1;
1146189251Ssam}
1147189251Ssam
1148189251Ssam
1149281806Srpaulostruct ctrl_iface_global_priv *
1150281806Srpaulowpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
1151281806Srpaulo{
1152281806Srpaulo	struct ctrl_iface_global_priv *priv;
1153281806Srpaulo
1154281806Srpaulo	priv = os_zalloc(sizeof(*priv));
1155281806Srpaulo	if (priv == NULL)
1156281806Srpaulo		return NULL;
1157281806Srpaulo	dl_list_init(&priv->ctrl_dst);
1158281806Srpaulo	priv->global = global;
1159281806Srpaulo	priv->sock = -1;
1160281806Srpaulo
1161281806Srpaulo	if (global->params.ctrl_interface == NULL)
1162281806Srpaulo		return priv;
1163281806Srpaulo
1164281806Srpaulo	if (wpas_global_ctrl_iface_open_sock(global, priv) < 0) {
1165281806Srpaulo		os_free(priv);
1166281806Srpaulo		return NULL;
1167281806Srpaulo	}
1168281806Srpaulo
1169281806Srpaulo	wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
1170281806Srpaulo
1171281806Srpaulo	return priv;
1172281806Srpaulo}
1173281806Srpaulo
1174281806Srpaulo
1175281806Srpaulostatic int wpas_ctrl_iface_global_reinit(struct wpa_global *global,
1176281806Srpaulo					 struct ctrl_iface_global_priv *priv)
1177281806Srpaulo{
1178281806Srpaulo	int res;
1179281806Srpaulo
1180281806Srpaulo	if (priv->sock <= 0)
1181281806Srpaulo		return -1;
1182281806Srpaulo
1183281806Srpaulo	/*
1184281806Srpaulo	 * On Android, the control socket being used may be the socket
1185281806Srpaulo	 * that is created when wpa_supplicant is started as a /init.*.rc
1186281806Srpaulo	 * service. Such a socket is maintained as a key-value pair in
1187281806Srpaulo	 * Android's environment. Closing this control socket would leave us
1188281806Srpaulo	 * in a bad state with an invalid socket descriptor.
1189281806Srpaulo	 */
1190281806Srpaulo	if (priv->android_control_socket)
1191281806Srpaulo		return priv->sock;
1192281806Srpaulo
1193281806Srpaulo	eloop_unregister_read_sock(priv->sock);
1194281806Srpaulo	close(priv->sock);
1195281806Srpaulo	priv->sock = -1;
1196281806Srpaulo	res = wpas_global_ctrl_iface_open_sock(global, priv);
1197281806Srpaulo	if (res < 0)
1198281806Srpaulo		return -1;
1199281806Srpaulo	return priv->sock;
1200281806Srpaulo}
1201281806Srpaulo
1202281806Srpaulo
1203189251Ssamvoid
1204189251Ssamwpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
1205189251Ssam{
1206281806Srpaulo	struct wpa_ctrl_dst *dst, *prev;
1207281806Srpaulo
1208189251Ssam	if (priv->sock >= 0) {
1209189251Ssam		eloop_unregister_read_sock(priv->sock);
1210189251Ssam		close(priv->sock);
1211189251Ssam	}
1212189251Ssam	if (priv->global->params.ctrl_interface)
1213189251Ssam		unlink(priv->global->params.ctrl_interface);
1214281806Srpaulo	dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
1215281806Srpaulo			      list)
1216281806Srpaulo		os_free(dst);
1217189251Ssam	os_free(priv);
1218189251Ssam}
1219