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