LCOV - code coverage report
Current view: top level - wpa_supplicant - ctrl_iface_unix.c (source / functions) Hit Total Coverage
Test: wpa_supplicant hwsim test run 1388943092 Lines: 275 494 55.7 %
Date: 2014-01-05 Functions: 13 17 76.5 %
Branches: 123 274 44.9 %

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

Generated by: LCOV version 1.9