LCOV - code coverage report
Current view: top level - wpa_supplicant - ctrl_iface_unix.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1393793999 Lines: 284 492 57.7 %
Date: 2014-03-02 Functions: 13 17 76.5 %
Branches: 131 274 47.8 %

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

Generated by: LCOV version 1.9