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