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