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 753 : 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 753 : dst = os_zalloc(sizeof(*dst));
81 753 : if (dst == NULL)
82 0 : return -1;
83 753 : os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
84 753 : dst->addrlen = fromlen;
85 753 : dst->debug_level = MSG_INFO;
86 753 : dl_list_add(ctrl_dst, &dst->list);
87 1506 : printf_encode(addr_txt, sizeof(addr_txt),
88 753 : (u8 *) from->sun_path,
89 : fromlen - offsetof(struct sockaddr_un, sun_path));
90 753 : wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s", addr_txt);
91 753 : return 0;
92 : }
93 :
94 :
95 753 : 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 780 : dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
102 1559 : if (fromlen == dst->addrlen &&
103 779 : 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 1506 : printf_encode(addr_txt, sizeof(addr_txt),
108 753 : (u8 *) from->sun_path,
109 : fromlen -
110 : offsetof(struct sockaddr_un, sun_path));
111 753 : wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached %s",
112 : addr_txt);
113 753 : dl_list_del(&dst->list);
114 753 : os_free(dst);
115 753 : 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 41104 : static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
152 : void *sock_ctx)
153 : {
154 41104 : struct wpa_supplicant *wpa_s = eloop_ctx;
155 41104 : struct ctrl_iface_priv *priv = sock_ctx;
156 : char buf[4096];
157 : int res;
158 : struct sockaddr_un from;
159 41104 : socklen_t fromlen = sizeof(from);
160 41104 : char *reply = NULL, *reply_buf = NULL;
161 41104 : size_t reply_len = 0;
162 41104 : int new_attached = 0;
163 :
164 41104 : res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
165 : (struct sockaddr *) &from, &fromlen);
166 41104 : if (res < 0) {
167 0 : wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
168 0 : strerror(errno));
169 41104 : return;
170 : }
171 41104 : buf[res] = '\0';
172 :
173 41104 : if (os_strcmp(buf, "ATTACH") == 0) {
174 63 : if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, &from,
175 : fromlen))
176 0 : reply_len = 1;
177 : else {
178 63 : new_attached = 1;
179 63 : reply_len = 2;
180 : }
181 41041 : } else if (os_strcmp(buf, "DETACH") == 0) {
182 62 : if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, &from,
183 : fromlen))
184 0 : reply_len = 1;
185 : else
186 62 : reply_len = 2;
187 40979 : } 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 40976 : reply_buf = wpa_supplicant_ctrl_iface_process(wpa_s, buf,
195 : &reply_len);
196 40976 : reply = reply_buf;
197 : }
198 :
199 41104 : if (!reply && reply_len == 1) {
200 1 : reply = "FAIL\n";
201 1 : reply_len = 5;
202 41103 : } else if (!reply && reply_len == 2) {
203 127 : reply = "OK\n";
204 127 : reply_len = 3;
205 : }
206 :
207 41104 : if (reply) {
208 41104 : if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
209 : fromlen) < 0) {
210 4 : int _errno = errno;
211 4 : wpa_dbg(wpa_s, MSG_DEBUG,
212 : "ctrl_iface sendto failed: %d - %s",
213 : _errno, strerror(_errno));
214 4 : 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 4 : 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 41104 : os_free(reply_buf);
237 :
238 41104 : if (new_attached)
239 63 : eapol_sm_notify_ctrl_attached(wpa_s->eapol);
240 : }
241 :
242 :
243 138 : static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
244 : {
245 : char *buf;
246 : size_t len;
247 138 : char *pbuf, *dir = NULL;
248 : int res;
249 :
250 138 : if (wpa_s->conf->ctrl_interface == NULL)
251 0 : return NULL;
252 :
253 138 : pbuf = os_strdup(wpa_s->conf->ctrl_interface);
254 138 : if (pbuf == NULL)
255 0 : return NULL;
256 138 : if (os_strncmp(pbuf, "DIR=", 4) == 0) {
257 : char *gid_str;
258 138 : dir = pbuf + 4;
259 138 : gid_str = os_strstr(dir, " GROUP=");
260 138 : if (gid_str)
261 138 : *gid_str = '\0';
262 : } else
263 0 : dir = pbuf;
264 :
265 138 : len = os_strlen(dir) + os_strlen(wpa_s->ifname) + 2;
266 138 : buf = os_malloc(len);
267 138 : if (buf == NULL) {
268 0 : os_free(pbuf);
269 0 : return NULL;
270 : }
271 :
272 138 : res = os_snprintf(buf, len, "%s/%s", dir, wpa_s->ifname);
273 138 : 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 138 : os_free(pbuf);
291 138 : return buf;
292 : }
293 :
294 :
295 252324 : static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, int global,
296 : const char *txt, size_t len)
297 : {
298 252324 : struct wpa_supplicant *wpa_s = ctx;
299 :
300 252324 : if (wpa_s == NULL)
301 1 : return;
302 :
303 252323 : if (global != 2 && wpa_s->global->ctrl_iface) {
304 252297 : struct ctrl_iface_global_priv *priv = wpa_s->global->ctrl_iface;
305 252297 : if (!dl_list_empty(&priv->ctrl_dst)) {
306 252240 : 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 252323 : if (wpa_s->ctrl_iface == NULL)
316 297 : return;
317 504052 : wpa_supplicant_ctrl_iface_send(wpa_s, NULL, wpa_s->ctrl_iface->sock,
318 252026 : &wpa_s->ctrl_iface->ctrl_dst,
319 : level, txt, len, wpa_s->ctrl_iface,
320 : NULL);
321 : }
322 :
323 :
324 69 : 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 69 : char *fname = NULL;
329 69 : gid_t gid = 0;
330 69 : int gid_set = 0;
331 69 : char *buf, *dir = NULL, *gid_str = NULL;
332 : struct group *grp;
333 : char *endp;
334 : int flags;
335 :
336 69 : buf = os_strdup(wpa_s->conf->ctrl_interface);
337 69 : 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 69 : if (os_strncmp(buf, "DIR=", 4) == 0) {
347 69 : dir = buf + 4;
348 69 : gid_str = os_strstr(dir, " GROUP=");
349 69 : if (gid_str) {
350 69 : *gid_str = '\0';
351 69 : gid_str += 7;
352 : }
353 : } else {
354 0 : dir = buf;
355 0 : gid_str = wpa_s->conf->ctrl_interface_group;
356 : }
357 :
358 69 : if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) {
359 68 : if (errno == EEXIST) {
360 68 : 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 69 : if (gid_str) {
386 69 : grp = getgrnam(gid_str);
387 69 : if (grp) {
388 69 : gid = grp->gr_gid;
389 69 : gid_set = 1;
390 69 : 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 69 : 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 138 : if (gid_set &&
415 69 : 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 69 : 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 69 : priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
428 69 : if (priv->sock < 0) {
429 0 : wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
430 0 : goto fail;
431 : }
432 :
433 69 : os_memset(&addr, 0, sizeof(addr));
434 : #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
435 : addr.sun_len = sizeof(addr);
436 : #endif /* __FreeBSD__ */
437 69 : addr.sun_family = AF_UNIX;
438 69 : fname = wpa_supplicant_ctrl_iface_path(wpa_s);
439 69 : if (fname == NULL)
440 0 : goto fail;
441 69 : os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
442 69 : 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 69 : 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 69 : 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 69 : 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 69 : flags = fcntl(priv->sock, F_GETFL);
497 69 : if (flags >= 0) {
498 69 : flags |= O_NONBLOCK;
499 69 : 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 69 : eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
507 : wpa_s, priv);
508 69 : wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
509 :
510 69 : os_free(buf);
511 69 : 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 69 : wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
529 : {
530 : struct ctrl_iface_priv *priv;
531 :
532 69 : priv = os_zalloc(sizeof(*priv));
533 69 : if (priv == NULL)
534 0 : return NULL;
535 69 : dl_list_init(&priv->ctrl_dst);
536 69 : priv->wpa_s = wpa_s;
537 69 : priv->sock = -1;
538 :
539 69 : if (wpa_s->conf->ctrl_interface == NULL)
540 0 : return priv;
541 :
542 69 : if (wpas_ctrl_iface_open_sock(wpa_s, priv) < 0) {
543 0 : os_free(priv);
544 0 : return NULL;
545 : }
546 :
547 69 : 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 69 : void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
570 : {
571 : struct wpa_ctrl_dst *dst, *prev;
572 :
573 69 : if (priv->sock > -1) {
574 : char *fname;
575 69 : char *buf, *dir = NULL;
576 69 : eloop_unregister_read_sock(priv->sock);
577 69 : 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 69 : close(priv->sock);
588 69 : priv->sock = -1;
589 69 : fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s);
590 69 : if (fname) {
591 69 : unlink(fname);
592 69 : os_free(fname);
593 : }
594 :
595 69 : if (priv->wpa_s->conf->ctrl_interface == NULL)
596 0 : goto free_dst;
597 69 : buf = os_strdup(priv->wpa_s->conf->ctrl_interface);
598 69 : if (buf == NULL)
599 0 : goto free_dst;
600 69 : if (os_strncmp(buf, "DIR=", 4) == 0) {
601 : char *gid_str;
602 69 : dir = buf + 4;
603 69 : gid_str = os_strstr(dir, " GROUP=");
604 69 : if (gid_str)
605 69 : *gid_str = '\0';
606 : } else
607 0 : dir = buf;
608 :
609 69 : if (rmdir(dir) < 0) {
610 68 : if (errno == ENOTEMPTY) {
611 67 : 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 69 : os_free(buf);
621 : }
622 :
623 : free_dst:
624 69 : dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
625 : list)
626 0 : os_free(dst);
627 69 : os_free(priv);
628 69 : }
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 504266 : 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 504266 : if (sock < 0 || dl_list_empty(ctrl_dst))
657 10546 : return;
658 :
659 498993 : res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
660 498993 : if (res < 0 || (size_t) res >= sizeof(levelstr))
661 0 : return;
662 498993 : idx = 0;
663 498993 : if (ifname) {
664 200816 : io[idx].iov_base = "IFNAME=";
665 200816 : io[idx].iov_len = 7;
666 200816 : idx++;
667 200816 : io[idx].iov_base = (char *) ifname;
668 200816 : io[idx].iov_len = os_strlen(ifname);
669 200816 : idx++;
670 200816 : io[idx].iov_base = " ";
671 200816 : io[idx].iov_len = 1;
672 200816 : idx++;
673 : }
674 498993 : io[idx].iov_base = levelstr;
675 498993 : io[idx].iov_len = os_strlen(levelstr);
676 498993 : idx++;
677 498993 : io[idx].iov_base = (char *) buf;
678 498993 : io[idx].iov_len = len;
679 498993 : idx++;
680 498993 : os_memset(&msg, 0, sizeof(msg));
681 498993 : msg.msg_iov = io;
682 498993 : msg.msg_iovlen = idx;
683 :
684 1002525 : dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
685 : int _errno;
686 : char addr_txt[200];
687 :
688 503532 : if (level < dst->debug_level)
689 957523 : continue;
690 :
691 99080 : printf_encode(addr_txt, sizeof(addr_txt),
692 99080 : (u8 *) dst->addr.sun_path, dst->addrlen -
693 : offsetof(struct sockaddr_un, sun_path));
694 49540 : msg.msg_name = (void *) &dst->addr;
695 49540 : msg.msg_namelen = dst->addrlen;
696 49540 : if (sendmsg(sock, &msg, MSG_DONTWAIT) >= 0) {
697 49539 : wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor sent successfully to %s",
698 : addr_txt);
699 49539 : dst->errors = 0;
700 49539 : continue;
701 : }
702 :
703 1 : _errno = errno;
704 2 : wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor[%s]: %d - %s",
705 2 : addr_txt, errno, strerror(errno));
706 1 : dst->errors++;
707 :
708 1 : if (dst->errors > 10 || _errno == ENOENT || _errno == EPERM) {
709 1 : wpa_printf(MSG_INFO, "CTRL_IFACE: Detach monitor %s that cannot receive messages",
710 : addr_txt);
711 1 : wpa_supplicant_ctrl_iface_detach(ctrl_dst, &dst->addr,
712 : dst->addrlen);
713 : }
714 :
715 1 : 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 5281 : static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
797 : void *sock_ctx)
798 : {
799 5281 : struct wpa_global *global = eloop_ctx;
800 5281 : struct ctrl_iface_global_priv *priv = sock_ctx;
801 : char buf[4096];
802 : int res;
803 : struct sockaddr_un from;
804 5281 : socklen_t fromlen = sizeof(from);
805 5281 : char *reply = NULL, *reply_buf = NULL;
806 : size_t reply_len;
807 :
808 5281 : res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
809 : (struct sockaddr *) &from, &fromlen);
810 5281 : if (res < 0) {
811 0 : wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
812 0 : strerror(errno));
813 5281 : return;
814 : }
815 5281 : buf[res] = '\0';
816 :
817 5281 : if (os_strcmp(buf, "ATTACH") == 0) {
818 690 : if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, &from,
819 : fromlen))
820 0 : reply_len = 1;
821 : else
822 690 : reply_len = 2;
823 4591 : } else if (os_strcmp(buf, "DETACH") == 0) {
824 690 : if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, &from,
825 : fromlen))
826 0 : reply_len = 1;
827 : else
828 690 : reply_len = 2;
829 : } else {
830 3901 : reply_buf = wpa_supplicant_global_ctrl_iface_process(
831 : global, buf, &reply_len);
832 3901 : reply = reply_buf;
833 : }
834 :
835 5281 : if (!reply && reply_len == 1) {
836 0 : reply = "FAIL\n";
837 0 : reply_len = 5;
838 5281 : } else if (!reply && reply_len == 2) {
839 1380 : reply = "OK\n";
840 1380 : reply_len = 3;
841 : }
842 :
843 5281 : if (reply) {
844 5281 : if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
845 : fromlen) < 0) {
846 1 : wpa_printf(MSG_DEBUG, "ctrl_iface sendto failed: %s",
847 1 : strerror(errno));
848 : }
849 : }
850 5281 : 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 : chmod(ctrl, S_IRWXU);
994 : }
995 :
996 : havesock:
997 :
998 : /*
999 : * Make socket non-blocking so that we don't hang forever if
1000 : * target dies unexpectedly.
1001 : */
1002 4 : flags = fcntl(priv->sock, F_GETFL);
1003 4 : if (flags >= 0) {
1004 4 : flags |= O_NONBLOCK;
1005 4 : if (fcntl(priv->sock, F_SETFL, flags) < 0) {
1006 0 : wpa_printf(MSG_INFO, "fcntl(ctrl, O_NONBLOCK): %s",
1007 0 : strerror(errno));
1008 : /* Not fatal, continue on.*/
1009 : }
1010 : }
1011 :
1012 4 : eloop_register_read_sock(priv->sock,
1013 : wpa_supplicant_global_ctrl_iface_receive,
1014 : global, priv);
1015 :
1016 4 : return 0;
1017 :
1018 : fail:
1019 0 : if (priv->sock >= 0) {
1020 0 : close(priv->sock);
1021 0 : priv->sock = -1;
1022 : }
1023 0 : return -1;
1024 : }
1025 :
1026 :
1027 : struct ctrl_iface_global_priv *
1028 4 : wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
1029 : {
1030 : struct ctrl_iface_global_priv *priv;
1031 :
1032 4 : priv = os_zalloc(sizeof(*priv));
1033 4 : if (priv == NULL)
1034 0 : return NULL;
1035 4 : dl_list_init(&priv->ctrl_dst);
1036 4 : priv->global = global;
1037 4 : priv->sock = -1;
1038 :
1039 4 : if (global->params.ctrl_interface == NULL)
1040 0 : return priv;
1041 :
1042 4 : if (wpas_global_ctrl_iface_open_sock(global, priv) < 0) {
1043 0 : os_free(priv);
1044 0 : return NULL;
1045 : }
1046 :
1047 4 : wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
1048 :
1049 4 : return priv;
1050 : }
1051 :
1052 :
1053 0 : static int wpas_ctrl_iface_global_reinit(struct wpa_global *global,
1054 : struct ctrl_iface_global_priv *priv)
1055 : {
1056 : int res;
1057 :
1058 0 : if (priv->sock <= 0)
1059 0 : return -1;
1060 :
1061 0 : eloop_unregister_read_sock(priv->sock);
1062 0 : close(priv->sock);
1063 0 : priv->sock = -1;
1064 0 : res = wpas_global_ctrl_iface_open_sock(global, priv);
1065 0 : if (res < 0)
1066 0 : return -1;
1067 0 : return priv->sock;
1068 : }
1069 :
1070 :
1071 : void
1072 4 : wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
1073 : {
1074 : struct wpa_ctrl_dst *dst, *prev;
1075 :
1076 4 : if (priv->sock >= 0) {
1077 4 : eloop_unregister_read_sock(priv->sock);
1078 4 : close(priv->sock);
1079 : }
1080 4 : if (priv->global->params.ctrl_interface)
1081 4 : unlink(priv->global->params.ctrl_interface);
1082 4 : dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
1083 : list)
1084 0 : os_free(dst);
1085 4 : os_free(priv);
1086 4 : }
|