source: rtems-libbsd/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c @ 8f2267b

55-freebsd-126-freebsd-12
Last change on this file since 8f2267b was 9c9d11b, checked in by Sichen Zhao <1473996754@…>, on 08/01/17 at 12:43:41

Import wpa from FreeBSD

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