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 1475438200 Lines: 398 592 67.2 %
Date: 2016-10-02 Functions: 22 24 91.7 %

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

Generated by: LCOV version 1.10