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 1388338050 Lines: 275 493 55.8 %
Date: 2013-12-29 Functions: 13 17 76.5 %
Branches: 118 274 43.1 %

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

Generated by: LCOV version 1.9