• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * WPA Supplicant / UNIX domain socket -based control interface
3  * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 #include <sys/un.h>
11 #include <sys/stat.h>
12 #include <grp.h>
13 #include <stddef.h>
14 #include <unistd.h>
15 #include <fcntl.h>
16 #ifdef ANDROID
17 #include <cutils/sockets.h>
18 #endif /* ANDROID */
19 
20 #include "utils/common.h"
21 #include "utils/eloop.h"
22 #include "utils/list.h"
23 #include "eapol_supp/eapol_supp_sm.h"
24 #include "config.h"
25 #include "wpa_supplicant_i.h"
26 #include "ctrl_iface.h"
27 
28 /* Per-interface ctrl_iface */
29 
30 /**
31  * struct wpa_ctrl_dst - Internal data structure of control interface monitors
32  *
33  * This structure is used to store information about registered control
34  * interface monitors into struct wpa_supplicant. This data is private to
35  * ctrl_iface_unix.c and should not be touched directly from other files.
36  */
37 struct wpa_ctrl_dst {
38 	struct dl_list list;
39 	struct sockaddr_un addr;
40 	socklen_t addrlen;
41 	int debug_level;
42 	int errors;
43 };
44 
45 
46 struct ctrl_iface_priv {
47 	struct wpa_supplicant *wpa_s;
48 	int sock;
49 	struct dl_list ctrl_dst;
50 };
51 
52 
53 static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
54 					   int level, const char *buf,
55 					   size_t len);
56 
57 
wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv * priv,struct sockaddr_un * from,socklen_t fromlen)58 static int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv,
59 					    struct sockaddr_un *from,
60 					    socklen_t fromlen)
61 {
62 	struct wpa_ctrl_dst *dst;
63 
64 	dst = os_zalloc(sizeof(*dst));
65 	if (dst == NULL)
66 		return -1;
67 	os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
68 	dst->addrlen = fromlen;
69 	dst->debug_level = MSG_INFO;
70 	dl_list_add(&priv->ctrl_dst, &dst->list);
71 	wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
72 		    (u8 *) from->sun_path,
73 		    fromlen - offsetof(struct sockaddr_un, sun_path));
74 	return 0;
75 }
76 
77 
wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv * priv,struct sockaddr_un * from,socklen_t fromlen)78 static int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv,
79 					    struct sockaddr_un *from,
80 					    socklen_t fromlen)
81 {
82 	struct wpa_ctrl_dst *dst;
83 
84 	dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) {
85 		if (fromlen == dst->addrlen &&
86 		    os_memcmp(from->sun_path, dst->addr.sun_path,
87 			      fromlen - offsetof(struct sockaddr_un, sun_path))
88 		    == 0) {
89 			dl_list_del(&dst->list);
90 			os_free(dst);
91 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
92 				    (u8 *) from->sun_path,
93 				    fromlen -
94 				    offsetof(struct sockaddr_un, sun_path));
95 			return 0;
96 		}
97 	}
98 	return -1;
99 }
100 
101 
wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv * priv,struct sockaddr_un * from,socklen_t fromlen,char * level)102 static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
103 					   struct sockaddr_un *from,
104 					   socklen_t fromlen,
105 					   char *level)
106 {
107 	struct wpa_ctrl_dst *dst;
108 
109 	wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
110 
111 	dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) {
112 		if (fromlen == dst->addrlen &&
113 		    os_memcmp(from->sun_path, dst->addr.sun_path,
114 			      fromlen - offsetof(struct sockaddr_un, sun_path))
115 		    == 0) {
116 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
117 				    "level", (u8 *) from->sun_path,
118 				    fromlen -
119 				    offsetof(struct sockaddr_un, sun_path));
120 			dst->debug_level = atoi(level);
121 			return 0;
122 		}
123 	}
124 
125 	return -1;
126 }
127 
128 
wpa_supplicant_ctrl_iface_receive(int sock,void * eloop_ctx,void * sock_ctx)129 static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
130 					      void *sock_ctx)
131 {
132 	struct wpa_supplicant *wpa_s = eloop_ctx;
133 	struct ctrl_iface_priv *priv = sock_ctx;
134 	char buf[4096];
135 	int res;
136 	struct sockaddr_un from;
137 	socklen_t fromlen = sizeof(from);
138 	char *reply = NULL;
139 	size_t reply_len = 0;
140 	int new_attached = 0;
141 
142 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
143 		       (struct sockaddr *) &from, &fromlen);
144 	if (res < 0) {
145 		perror("recvfrom(ctrl_iface)");
146 		return;
147 	}
148 	buf[res] = '\0';
149 
150 	if (os_strcmp(buf, "ATTACH") == 0) {
151 		if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen))
152 			reply_len = 1;
153 		else {
154 			new_attached = 1;
155 			reply_len = 2;
156 		}
157 	} else if (os_strcmp(buf, "DETACH") == 0) {
158 		if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen))
159 			reply_len = 1;
160 		else
161 			reply_len = 2;
162 	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
163 		if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen,
164 						    buf + 6))
165 			reply_len = 1;
166 		else
167 			reply_len = 2;
168 	} else {
169 #if defined(CONFIG_P2P) && defined(ANDROID_P2P)
170 		char *ifname, *ifend;
171 
172 		ifname = os_strstr(buf, "interface=");
173 		if (ifname != NULL) {
174 			ifend = os_strchr(ifname + 10, ' ');
175 			if (ifend != NULL)
176 				*ifend++ = '\0';
177 			else
178 				*(ifname - 1) = '\0';
179 			wpa_printf(MSG_DEBUG, "Found %s", ifname);
180 			for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
181 				if (os_strcmp(wpa_s->ifname, ifname + 10) == 0)
182 					break;
183 			}
184 			if (wpa_s == NULL) {
185 				wpa_printf(MSG_ERROR, "P2P: %s does not exist", ifname);
186 				wpa_s = eloop_ctx;
187 			}
188 			if (ifend != NULL)
189 				os_memmove(ifname, ifend, strlen(ifend) + 1);
190 			wpa_printf(MSG_INFO, "wpa_s->ifname %s cmd %s", wpa_s ? wpa_s->ifname : "NULL", buf);
191 		}
192 #endif /* defined CONFIG_P2P && defined ANDROID_P2P */
193 		reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf,
194 							  &reply_len);
195 	}
196 
197 	if (reply) {
198 		sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
199 		       fromlen);
200 		os_free(reply);
201 	} else if (reply_len == 1) {
202 		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
203 		       fromlen);
204 	} else if (reply_len == 2) {
205 		sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
206 		       fromlen);
207 	}
208 
209 	if (new_attached)
210 		eapol_sm_notify_ctrl_attached(wpa_s->eapol);
211 }
212 
213 
wpa_supplicant_ctrl_iface_path(struct wpa_supplicant * wpa_s)214 static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
215 {
216 	char *buf;
217 	size_t len;
218 	char *pbuf, *dir = NULL, *gid_str = NULL;
219 	int res;
220 
221 	if (wpa_s->conf->ctrl_interface == NULL)
222 		return NULL;
223 
224 	pbuf = os_strdup(wpa_s->conf->ctrl_interface);
225 	if (pbuf == NULL)
226 		return NULL;
227 	if (os_strncmp(pbuf, "DIR=", 4) == 0) {
228 		dir = pbuf + 4;
229 		gid_str = os_strstr(dir, " GROUP=");
230 		if (gid_str) {
231 			*gid_str = '\0';
232 			gid_str += 7;
233 		}
234 	} else
235 		dir = pbuf;
236 
237 	len = os_strlen(dir) + os_strlen(wpa_s->ifname) + 2;
238 	buf = os_malloc(len);
239 	if (buf == NULL) {
240 		os_free(pbuf);
241 		return NULL;
242 	}
243 
244 	res = os_snprintf(buf, len, "%s/%s", dir, wpa_s->ifname);
245 	if (res < 0 || (size_t) res >= len) {
246 		os_free(pbuf);
247 		os_free(buf);
248 		return NULL;
249 	}
250 #ifdef __CYGWIN__
251 	{
252 		/* Windows/WinPcap uses interface names that are not suitable
253 		 * as a file name - convert invalid chars to underscores */
254 		char *pos = buf;
255 		while (*pos) {
256 			if (*pos == '\\')
257 				*pos = '_';
258 			pos++;
259 		}
260 	}
261 #endif /* __CYGWIN__ */
262 	os_free(pbuf);
263 	return buf;
264 }
265 
266 
wpa_supplicant_ctrl_iface_msg_cb(void * ctx,int level,const char * txt,size_t len)267 static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
268 					     const char *txt, size_t len)
269 {
270 	struct wpa_supplicant *wpa_s = ctx;
271 	if (wpa_s == NULL || wpa_s->ctrl_iface == NULL)
272 		return;
273 	wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len);
274 }
275 
276 
277 struct ctrl_iface_priv *
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant * wpa_s)278 wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
279 {
280 	struct ctrl_iface_priv *priv;
281 	struct sockaddr_un addr;
282 	char *fname = NULL;
283 	gid_t gid = 0;
284 	int gid_set = 0;
285 	char *buf, *dir = NULL, *gid_str = NULL;
286 	struct group *grp;
287 	char *endp;
288 	int flags;
289 
290 	priv = os_zalloc(sizeof(*priv));
291 	if (priv == NULL)
292 		return NULL;
293 	dl_list_init(&priv->ctrl_dst);
294 	priv->wpa_s = wpa_s;
295 	priv->sock = -1;
296 
297 	if (wpa_s->conf->ctrl_interface == NULL)
298 		return priv;
299 
300 	buf = os_strdup(wpa_s->conf->ctrl_interface);
301 	if (buf == NULL)
302 		goto fail;
303 #ifdef ANDROID
304 	os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s",
305 		    wpa_s->conf->ctrl_interface);
306 	priv->sock = android_get_control_socket(addr.sun_path);
307 	if (priv->sock >= 0)
308 		goto havesock;
309 #endif /* ANDROID */
310 	if (os_strncmp(buf, "DIR=", 4) == 0) {
311 		dir = buf + 4;
312 		gid_str = os_strstr(dir, " GROUP=");
313 		if (gid_str) {
314 			*gid_str = '\0';
315 			gid_str += 7;
316 		}
317 	} else {
318 		dir = buf;
319 		gid_str = wpa_s->conf->ctrl_interface_group;
320 	}
321 
322 	if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) {
323 		if (errno == EEXIST) {
324 			wpa_printf(MSG_DEBUG, "Using existing control "
325 				   "interface directory.");
326 		} else {
327 			perror("mkdir[ctrl_interface]");
328 			goto fail;
329 		}
330 	}
331 
332 #ifdef ANDROID
333 	/*
334 	 * wpa_supplicant is started from /init.*.rc on Android and that seems
335 	 * to be using umask 0077 which would leave the control interface
336 	 * directory without group access. This breaks things since Wi-Fi
337 	 * framework assumes that this directory can be accessed by other
338 	 * applications in the wifi group. Fix this by adding group access even
339 	 * if umask value would prevent this.
340 	 */
341 	if (chmod(dir, S_IRWXU | S_IRWXG) < 0) {
342 		wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
343 			   strerror(errno));
344 		/* Try to continue anyway */
345 	}
346 #endif /* ANDROID */
347 
348 	if (gid_str) {
349 		grp = getgrnam(gid_str);
350 		if (grp) {
351 			gid = grp->gr_gid;
352 			gid_set = 1;
353 			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
354 				   " (from group name '%s')",
355 				   (int) gid, gid_str);
356 		} else {
357 			/* Group name not found - try to parse this as gid */
358 			gid = strtol(gid_str, &endp, 10);
359 			if (*gid_str == '\0' || *endp != '\0') {
360 				wpa_printf(MSG_ERROR, "CTRL: Invalid group "
361 					   "'%s'", gid_str);
362 				goto fail;
363 			}
364 			gid_set = 1;
365 			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
366 				   (int) gid);
367 		}
368 	}
369 
370 	if (gid_set && chown(dir, -1, gid) < 0) {
371 		perror("chown[ctrl_interface]");
372 		goto fail;
373 	}
374 
375 	/* Make sure the group can enter and read the directory */
376 	if (gid_set &&
377 	    chmod(dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP) < 0) {
378 		wpa_printf(MSG_ERROR, "CTRL: chmod[ctrl_interface]: %s",
379 			   strerror(errno));
380 		goto fail;
381 	}
382 
383 	if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >=
384 	    sizeof(addr.sun_path)) {
385 		wpa_printf(MSG_ERROR, "ctrl_iface path limit exceeded");
386 		goto fail;
387 	}
388 
389 	priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
390 	if (priv->sock < 0) {
391 		perror("socket(PF_UNIX)");
392 		goto fail;
393 	}
394 
395 	os_memset(&addr, 0, sizeof(addr));
396 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
397 	addr.sun_len = sizeof(addr);
398 #endif /* __FreeBSD__ */
399 	addr.sun_family = AF_UNIX;
400 	fname = wpa_supplicant_ctrl_iface_path(wpa_s);
401 	if (fname == NULL)
402 		goto fail;
403 	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
404 	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
405 		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
406 			   strerror(errno));
407 		if (connect(priv->sock, (struct sockaddr *) &addr,
408 			    sizeof(addr)) < 0) {
409 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
410 				   " allow connections - assuming it was left"
411 				   "over from forced program termination");
412 			if (unlink(fname) < 0) {
413 				perror("unlink[ctrl_iface]");
414 				wpa_printf(MSG_ERROR, "Could not unlink "
415 					   "existing ctrl_iface socket '%s'",
416 					   fname);
417 				goto fail;
418 			}
419 			if (bind(priv->sock, (struct sockaddr *) &addr,
420 				 sizeof(addr)) < 0) {
421 				perror("supp-ctrl-iface-init: bind(PF_UNIX)");
422 				goto fail;
423 			}
424 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
425 				   "ctrl_iface socket '%s'", fname);
426 		} else {
427 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
428 				   "be in use - cannot override it");
429 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
430 				   "not used anymore", fname);
431 			os_free(fname);
432 			fname = NULL;
433 			goto fail;
434 		}
435 	}
436 
437 	if (gid_set && chown(fname, -1, gid) < 0) {
438 		perror("chown[ctrl_interface/ifname]");
439 		goto fail;
440 	}
441 
442 	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
443 		perror("chmod[ctrl_interface/ifname]");
444 		goto fail;
445 	}
446 	os_free(fname);
447 
448 #ifdef ANDROID
449 havesock:
450 #endif /* ANDROID */
451 
452 	/*
453 	 * Make socket non-blocking so that we don't hang forever if
454 	 * target dies unexpectedly.
455 	 */
456 	flags = fcntl(priv->sock, F_GETFL);
457 	if (flags >= 0) {
458 		flags |= O_NONBLOCK;
459 		if (fcntl(priv->sock, F_SETFL, flags) < 0) {
460 			perror("fcntl(ctrl, O_NONBLOCK)");
461 			/* Not fatal, continue on.*/
462 		}
463 	}
464 
465 	eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
466 				 wpa_s, priv);
467 	wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
468 
469 	os_free(buf);
470 	return priv;
471 
472 fail:
473 	if (priv->sock >= 0)
474 		close(priv->sock);
475 	os_free(priv);
476 	if (fname) {
477 		unlink(fname);
478 		os_free(fname);
479 	}
480 	os_free(buf);
481 	return NULL;
482 }
483 
484 
wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv * priv)485 void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
486 {
487 	struct wpa_ctrl_dst *dst, *prev;
488 
489 	if (priv->sock > -1) {
490 		char *fname;
491 		char *buf, *dir = NULL, *gid_str = NULL;
492 		eloop_unregister_read_sock(priv->sock);
493 		if (!dl_list_empty(&priv->ctrl_dst)) {
494 			/*
495 			 * Wait a second before closing the control socket if
496 			 * there are any attached monitors in order to allow
497 			 * them to receive any pending messages.
498 			 */
499 			wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
500 				   "monitors to receive messages");
501 			os_sleep(1, 0);
502 		}
503 		close(priv->sock);
504 		priv->sock = -1;
505 		fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s);
506 		if (fname) {
507 			unlink(fname);
508 			os_free(fname);
509 		}
510 
511 		buf = os_strdup(priv->wpa_s->conf->ctrl_interface);
512 		if (buf == NULL)
513 			goto free_dst;
514 		if (os_strncmp(buf, "DIR=", 4) == 0) {
515 			dir = buf + 4;
516 			gid_str = os_strstr(dir, " GROUP=");
517 			if (gid_str) {
518 				*gid_str = '\0';
519 				gid_str += 7;
520 			}
521 		} else
522 			dir = buf;
523 
524 		if (rmdir(dir) < 0) {
525 			if (errno == ENOTEMPTY) {
526 				wpa_printf(MSG_DEBUG, "Control interface "
527 					   "directory not empty - leaving it "
528 					   "behind");
529 			} else {
530 				perror("rmdir[ctrl_interface]");
531 			}
532 		}
533 		os_free(buf);
534 	}
535 
536 free_dst:
537 	dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
538 			      list)
539 		os_free(dst);
540 	os_free(priv);
541 }
542 
543 
544 /**
545  * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors
546  * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
547  * @level: Priority level of the message
548  * @buf: Message data
549  * @len: Message length
550  *
551  * Send a packet to all monitor programs attached to the control interface.
552  */
wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv * priv,int level,const char * buf,size_t len)553 static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
554 					   int level, const char *buf,
555 					   size_t len)
556 {
557 	struct wpa_ctrl_dst *dst, *next;
558 	char levelstr[10];
559 	int idx, res;
560 	struct msghdr msg;
561 	struct iovec io[2];
562 
563 	if (priv->sock < 0 || dl_list_empty(&priv->ctrl_dst))
564 		return;
565 
566 	res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
567 	if (res < 0 || (size_t) res >= sizeof(levelstr))
568 		return;
569 	io[0].iov_base = levelstr;
570 	io[0].iov_len = os_strlen(levelstr);
571 	io[1].iov_base = (char *) buf;
572 	io[1].iov_len = len;
573 	os_memset(&msg, 0, sizeof(msg));
574 	msg.msg_iov = io;
575 	msg.msg_iovlen = 2;
576 
577 	idx = 0;
578 	dl_list_for_each_safe(dst, next, &priv->ctrl_dst, struct wpa_ctrl_dst,
579 			      list) {
580 		if (level >= dst->debug_level) {
581 			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
582 				    (u8 *) dst->addr.sun_path, dst->addrlen -
583 				    offsetof(struct sockaddr_un, sun_path));
584 			msg.msg_name = (void *) &dst->addr;
585 			msg.msg_namelen = dst->addrlen;
586 			if (sendmsg(priv->sock, &msg, 0) < 0) {
587 				int _errno = errno;
588 				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
589 					   "%d - %s",
590 					   idx, errno, strerror(errno));
591 				dst->errors++;
592 				if (dst->errors > 1000 ||
593 				    (_errno != ENOBUFS && dst->errors > 10) ||
594 				    _errno == ENOENT) {
595 					wpa_supplicant_ctrl_iface_detach(
596 						priv, &dst->addr,
597 						dst->addrlen);
598 				}
599 			} else
600 				dst->errors = 0;
601 		}
602 		idx++;
603 	}
604 }
605 
606 
wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv * priv)607 void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
608 {
609 	char buf[256];
610 	int res;
611 	struct sockaddr_un from;
612 	socklen_t fromlen = sizeof(from);
613 
614 	for (;;) {
615 		wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to "
616 			   "attach", priv->wpa_s->ifname);
617 		eloop_wait_for_read_sock(priv->sock);
618 
619 		res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0,
620 			       (struct sockaddr *) &from, &fromlen);
621 		if (res < 0) {
622 			perror("recvfrom(ctrl_iface)");
623 			continue;
624 		}
625 		buf[res] = '\0';
626 
627 		if (os_strcmp(buf, "ATTACH") == 0) {
628 			/* handle ATTACH signal of first monitor interface */
629 			if (!wpa_supplicant_ctrl_iface_attach(priv, &from,
630 							      fromlen)) {
631 				sendto(priv->sock, "OK\n", 3, 0,
632 				       (struct sockaddr *) &from, fromlen);
633 				/* OK to continue */
634 				return;
635 			} else {
636 				sendto(priv->sock, "FAIL\n", 5, 0,
637 				       (struct sockaddr *) &from, fromlen);
638 			}
639 		} else {
640 			/* return FAIL for all other signals */
641 			sendto(priv->sock, "FAIL\n", 5, 0,
642 			       (struct sockaddr *) &from, fromlen);
643 		}
644 	}
645 }
646 
647 
648 /* Global ctrl_iface */
649 
650 struct ctrl_iface_global_priv {
651 	struct wpa_global *global;
652 	int sock;
653 };
654 
655 
wpa_supplicant_global_ctrl_iface_receive(int sock,void * eloop_ctx,void * sock_ctx)656 static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
657 						     void *sock_ctx)
658 {
659 	struct wpa_global *global = eloop_ctx;
660 	char buf[256];
661 	int res;
662 	struct sockaddr_un from;
663 	socklen_t fromlen = sizeof(from);
664 	char *reply;
665 	size_t reply_len;
666 
667 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
668 		       (struct sockaddr *) &from, &fromlen);
669 	if (res < 0) {
670 		perror("recvfrom(ctrl_iface)");
671 		return;
672 	}
673 	buf[res] = '\0';
674 
675 	reply = wpa_supplicant_global_ctrl_iface_process(global, buf,
676 							 &reply_len);
677 
678 	if (reply) {
679 		sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
680 		       fromlen);
681 		os_free(reply);
682 	} else if (reply_len) {
683 		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
684 		       fromlen);
685 	}
686 }
687 
688 
689 struct ctrl_iface_global_priv *
wpa_supplicant_global_ctrl_iface_init(struct wpa_global * global)690 wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
691 {
692 	struct ctrl_iface_global_priv *priv;
693 	struct sockaddr_un addr;
694 
695 	priv = os_zalloc(sizeof(*priv));
696 	if (priv == NULL)
697 		return NULL;
698 	priv->global = global;
699 	priv->sock = -1;
700 
701 	if (global->params.ctrl_interface == NULL)
702 		return priv;
703 
704 #ifdef ANDROID
705 	priv->sock = android_get_control_socket(global->params.ctrl_interface);
706 	if (priv->sock >= 0)
707 		goto havesock;
708 #endif /* ANDROID */
709 
710 	wpa_printf(MSG_DEBUG, "Global control interface '%s'",
711 		   global->params.ctrl_interface);
712 
713 	priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
714 	if (priv->sock < 0) {
715 		perror("socket(PF_UNIX)");
716 		goto fail;
717 	}
718 
719 	os_memset(&addr, 0, sizeof(addr));
720 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
721 	addr.sun_len = sizeof(addr);
722 #endif /* __FreeBSD__ */
723 	addr.sun_family = AF_UNIX;
724 	os_strlcpy(addr.sun_path, global->params.ctrl_interface,
725 		   sizeof(addr.sun_path));
726 	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
727 		perror("supp-global-ctrl-iface-init (will try fixup): "
728 		       "bind(PF_UNIX)");
729 		if (connect(priv->sock, (struct sockaddr *) &addr,
730 			    sizeof(addr)) < 0) {
731 			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
732 				   " allow connections - assuming it was left"
733 				   "over from forced program termination");
734 			if (unlink(global->params.ctrl_interface) < 0) {
735 				perror("unlink[ctrl_iface]");
736 				wpa_printf(MSG_ERROR, "Could not unlink "
737 					   "existing ctrl_iface socket '%s'",
738 					   global->params.ctrl_interface);
739 				goto fail;
740 			}
741 			if (bind(priv->sock, (struct sockaddr *) &addr,
742 				 sizeof(addr)) < 0) {
743 				perror("supp-glb-iface-init: bind(PF_UNIX)");
744 				goto fail;
745 			}
746 			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
747 				   "ctrl_iface socket '%s'",
748 				   global->params.ctrl_interface);
749 		} else {
750 			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
751 				   "be in use - cannot override it");
752 			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
753 				   "not used anymore",
754 				   global->params.ctrl_interface);
755 			goto fail;
756 		}
757 	}
758 
759 #ifdef ANDROID
760 havesock:
761 #endif /* ANDROID */
762 	eloop_register_read_sock(priv->sock,
763 				 wpa_supplicant_global_ctrl_iface_receive,
764 				 global, NULL);
765 
766 	return priv;
767 
768 fail:
769 	if (priv->sock >= 0)
770 		close(priv->sock);
771 	os_free(priv);
772 	return NULL;
773 }
774 
775 
776 void
wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv * priv)777 wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
778 {
779 	if (priv->sock >= 0) {
780 		eloop_unregister_read_sock(priv->sock);
781 		close(priv->sock);
782 	}
783 	if (priv->global->params.ctrl_interface)
784 		unlink(priv->global->params.ctrl_interface);
785 	os_free(priv);
786 }
787