LCOV - code coverage report
Current view: top level - wpa_supplicant - ctrl_iface_unix.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1422976643 Lines: 308 498 61.8 %
Date: 2015-02-03 Functions: 14 17 82.4 %

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

Generated by: LCOV version 1.10