LCOV - code coverage report
Current view: top level - hostapd - ctrl_iface.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1401264779 Lines: 914 1161 78.7 %
Date: 2014-05-28 Functions: 46 47 97.9 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / 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 "utils/includes.h"
      10             : 
      11             : #ifndef CONFIG_NATIVE_WINDOWS
      12             : 
      13             : #include <sys/un.h>
      14             : #include <sys/stat.h>
      15             : #include <stddef.h>
      16             : 
      17             : #include "utils/common.h"
      18             : #include "utils/eloop.h"
      19             : #include "common/version.h"
      20             : #include "common/ieee802_11_defs.h"
      21             : #include "drivers/driver.h"
      22             : #include "radius/radius_client.h"
      23             : #include "radius/radius_server.h"
      24             : #include "ap/hostapd.h"
      25             : #include "ap/ap_config.h"
      26             : #include "ap/ieee802_1x.h"
      27             : #include "ap/wpa_auth.h"
      28             : #include "ap/ieee802_11.h"
      29             : #include "ap/sta_info.h"
      30             : #include "ap/wps_hostapd.h"
      31             : #include "ap/ctrl_iface_ap.h"
      32             : #include "ap/ap_drv_ops.h"
      33             : #include "ap/hs20.h"
      34             : #include "ap/wnm_ap.h"
      35             : #include "ap/wpa_auth.h"
      36             : #include "wps/wps_defs.h"
      37             : #include "wps/wps.h"
      38             : #include "config_file.h"
      39             : #include "ctrl_iface.h"
      40             : 
      41             : 
      42             : struct wpa_ctrl_dst {
      43             :         struct wpa_ctrl_dst *next;
      44             :         struct sockaddr_un addr;
      45             :         socklen_t addrlen;
      46             :         int debug_level;
      47             :         int errors;
      48             : };
      49             : 
      50             : 
      51             : static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
      52             :                                     const char *buf, size_t len);
      53             : 
      54             : 
      55         753 : static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
      56             :                                      struct sockaddr_un *from,
      57             :                                      socklen_t fromlen)
      58             : {
      59             :         struct wpa_ctrl_dst *dst;
      60             : 
      61         753 :         dst = os_zalloc(sizeof(*dst));
      62         753 :         if (dst == NULL)
      63           0 :                 return -1;
      64         753 :         os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
      65         753 :         dst->addrlen = fromlen;
      66         753 :         dst->debug_level = MSG_INFO;
      67         753 :         dst->next = hapd->ctrl_dst;
      68         753 :         hapd->ctrl_dst = dst;
      69        1506 :         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
      70         753 :                     (u8 *) from->sun_path,
      71             :                     fromlen - offsetof(struct sockaddr_un, sun_path));
      72         753 :         return 0;
      73             : }
      74             : 
      75             : 
      76         737 : static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
      77             :                                      struct sockaddr_un *from,
      78             :                                      socklen_t fromlen)
      79             : {
      80         737 :         struct wpa_ctrl_dst *dst, *prev = NULL;
      81             : 
      82         737 :         dst = hapd->ctrl_dst;
      83        1476 :         while (dst) {
      84        1478 :                 if (fromlen == dst->addrlen &&
      85         739 :                     os_memcmp(from->sun_path, dst->addr.sun_path,
      86             :                               fromlen - offsetof(struct sockaddr_un, sun_path))
      87             :                     == 0) {
      88        1474 :                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
      89         737 :                                     (u8 *) from->sun_path,
      90             :                                     fromlen -
      91             :                                     offsetof(struct sockaddr_un, sun_path));
      92         737 :                         if (prev == NULL)
      93         735 :                                 hapd->ctrl_dst = dst->next;
      94             :                         else
      95           2 :                                 prev->next = dst->next;
      96         737 :                         os_free(dst);
      97         737 :                         return 0;
      98             :                 }
      99           2 :                 prev = dst;
     100           2 :                 dst = dst->next;
     101             :         }
     102           0 :         return -1;
     103             : }
     104             : 
     105             : 
     106           1 : static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
     107             :                                     struct sockaddr_un *from,
     108             :                                     socklen_t fromlen,
     109             :                                     char *level)
     110             : {
     111             :         struct wpa_ctrl_dst *dst;
     112             : 
     113           1 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
     114             : 
     115           1 :         dst = hapd->ctrl_dst;
     116           3 :         while (dst) {
     117           2 :                 if (fromlen == dst->addrlen &&
     118           1 :                     os_memcmp(from->sun_path, dst->addr.sun_path,
     119             :                               fromlen - offsetof(struct sockaddr_un, sun_path))
     120             :                     == 0) {
     121           0 :                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
     122           0 :                                     "level", (u8 *) from->sun_path, fromlen -
     123             :                                     offsetof(struct sockaddr_un, sun_path));
     124           0 :                         dst->debug_level = atoi(level);
     125           0 :                         return 0;
     126             :                 }
     127           1 :                 dst = dst->next;
     128             :         }
     129             : 
     130           1 :         return -1;
     131             : }
     132             : 
     133             : 
     134           2 : static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
     135             :                                       const char *txtaddr)
     136             : {
     137             :         u8 addr[ETH_ALEN];
     138             :         struct sta_info *sta;
     139             : 
     140           2 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
     141             : 
     142           2 :         if (hwaddr_aton(txtaddr, addr))
     143           1 :                 return -1;
     144             : 
     145           1 :         sta = ap_get_sta(hapd, addr);
     146           1 :         if (sta)
     147           0 :                 return 0;
     148             : 
     149           6 :         wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
     150           6 :                    "notification", MAC2STR(addr));
     151           1 :         sta = ap_sta_add(hapd, addr);
     152           1 :         if (sta == NULL)
     153           0 :                 return -1;
     154             : 
     155           1 :         hostapd_new_assoc_sta(hapd, sta, 0);
     156           1 :         return 0;
     157             : }
     158             : 
     159             : 
     160             : #ifdef CONFIG_IEEE80211W
     161             : #ifdef NEED_AP_MLME
     162           2 : static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
     163             :                                        const char *txtaddr)
     164             : {
     165             :         u8 addr[ETH_ALEN];
     166             :         u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
     167             : 
     168           2 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
     169             : 
     170           4 :         if (hwaddr_aton(txtaddr, addr) ||
     171           2 :             os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
     172           0 :                 return -1;
     173             : 
     174           2 :         ieee802_11_send_sa_query_req(hapd, addr, trans_id);
     175             : 
     176           2 :         return 0;
     177             : }
     178             : #endif /* NEED_AP_MLME */
     179             : #endif /* CONFIG_IEEE80211W */
     180             : 
     181             : 
     182             : #ifdef CONFIG_WPS
     183          14 : static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
     184             : {
     185          14 :         char *pin = os_strchr(txt, ' ');
     186             :         char *timeout_txt;
     187             :         int timeout;
     188          14 :         u8 addr_buf[ETH_ALEN], *addr = NULL;
     189             :         char *pos;
     190             : 
     191          14 :         if (pin == NULL)
     192           1 :                 return -1;
     193          13 :         *pin++ = '\0';
     194             : 
     195          13 :         timeout_txt = os_strchr(pin, ' ');
     196          13 :         if (timeout_txt) {
     197           2 :                 *timeout_txt++ = '\0';
     198           2 :                 timeout = atoi(timeout_txt);
     199           2 :                 pos = os_strchr(timeout_txt, ' ');
     200           2 :                 if (pos) {
     201           1 :                         *pos++ = '\0';
     202           1 :                         if (hwaddr_aton(pos, addr_buf) == 0)
     203           1 :                                 addr = addr_buf;
     204             :                 }
     205             :         } else
     206          11 :                 timeout = 0;
     207             : 
     208          13 :         return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
     209             : }
     210             : 
     211             : 
     212           9 : static int hostapd_ctrl_iface_wps_check_pin(
     213             :         struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
     214             : {
     215             :         char pin[9];
     216             :         size_t len;
     217             :         char *pos;
     218             :         int ret;
     219             : 
     220           9 :         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
     221             :                               (u8 *) cmd, os_strlen(cmd));
     222          81 :         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
     223          74 :                 if (*pos < '0' || *pos > '9')
     224           6 :                         continue;
     225          68 :                 pin[len++] = *pos;
     226          68 :                 if (len == 9) {
     227           2 :                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
     228           2 :                         return -1;
     229             :                 }
     230             :         }
     231           7 :         if (len != 4 && len != 8) {
     232           2 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
     233           2 :                 return -1;
     234             :         }
     235           5 :         pin[len] = '\0';
     236             : 
     237           5 :         if (len == 8) {
     238             :                 unsigned int pin_val;
     239           5 :                 pin_val = atoi(pin);
     240           5 :                 if (!wps_pin_valid(pin_val)) {
     241           1 :                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
     242           1 :                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
     243           1 :                         if (ret < 0 || (size_t) ret >= buflen)
     244           0 :                                 return -1;
     245           1 :                         return ret;
     246             :                 }
     247             :         }
     248             : 
     249           4 :         ret = os_snprintf(buf, buflen, "%s", pin);
     250           4 :         if (ret < 0 || (size_t) ret >= buflen)
     251           0 :                 return -1;
     252             : 
     253           4 :         return ret;
     254             : }
     255             : 
     256             : 
     257             : #ifdef CONFIG_WPS_NFC
     258           2 : static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
     259             :                                                char *pos)
     260             : {
     261             :         size_t len;
     262             :         struct wpabuf *buf;
     263             :         int ret;
     264             : 
     265           2 :         len = os_strlen(pos);
     266           2 :         if (len & 0x01)
     267           0 :                 return -1;
     268           2 :         len /= 2;
     269             : 
     270           2 :         buf = wpabuf_alloc(len);
     271           2 :         if (buf == NULL)
     272           0 :                 return -1;
     273           2 :         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
     274           0 :                 wpabuf_free(buf);
     275           0 :                 return -1;
     276             :         }
     277             : 
     278           2 :         ret = hostapd_wps_nfc_tag_read(hapd, buf);
     279           2 :         wpabuf_free(buf);
     280             : 
     281           2 :         return ret;
     282             : }
     283             : 
     284             : 
     285           2 : static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
     286             :                                                    char *cmd, char *reply,
     287             :                                                    size_t max_len)
     288             : {
     289             :         int ndef;
     290             :         struct wpabuf *buf;
     291             :         int res;
     292             : 
     293           2 :         if (os_strcmp(cmd, "WPS") == 0)
     294           0 :                 ndef = 0;
     295           2 :         else if (os_strcmp(cmd, "NDEF") == 0)
     296           2 :                 ndef = 1;
     297             :         else
     298           0 :                 return -1;
     299             : 
     300           2 :         buf = hostapd_wps_nfc_config_token(hapd, ndef);
     301           2 :         if (buf == NULL)
     302           0 :                 return -1;
     303             : 
     304           2 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
     305             :                                          wpabuf_len(buf));
     306           2 :         reply[res++] = '\n';
     307           2 :         reply[res] = '\0';
     308             : 
     309           2 :         wpabuf_free(buf);
     310             : 
     311           2 :         return res;
     312             : }
     313             : 
     314             : 
     315           3 : static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
     316             :                                                 char *reply, size_t max_len,
     317             :                                                 int ndef)
     318             : {
     319             :         struct wpabuf *buf;
     320             :         int res;
     321             : 
     322           3 :         buf = hostapd_wps_nfc_token_gen(hapd, ndef);
     323           3 :         if (buf == NULL)
     324           0 :                 return -1;
     325             : 
     326           3 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
     327             :                                          wpabuf_len(buf));
     328           3 :         reply[res++] = '\n';
     329           3 :         reply[res] = '\0';
     330             : 
     331           3 :         wpabuf_free(buf);
     332             : 
     333           3 :         return res;
     334             : }
     335             : 
     336             : 
     337           6 : static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
     338             :                                             char *cmd, char *reply,
     339             :                                             size_t max_len)
     340             : {
     341           6 :         if (os_strcmp(cmd, "WPS") == 0)
     342           1 :                 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
     343             :                                                             max_len, 0);
     344             : 
     345           5 :         if (os_strcmp(cmd, "NDEF") == 0)
     346           2 :                 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
     347             :                                                             max_len, 1);
     348             : 
     349           3 :         if (os_strcmp(cmd, "enable") == 0)
     350           2 :                 return hostapd_wps_nfc_token_enable(hapd);
     351             : 
     352           1 :         if (os_strcmp(cmd, "disable") == 0) {
     353           1 :                 hostapd_wps_nfc_token_disable(hapd);
     354           1 :                 return 0;
     355             :         }
     356             : 
     357           0 :         return -1;
     358             : }
     359             : 
     360             : 
     361           8 : static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
     362             :                                                    char *cmd, char *reply,
     363             :                                                    size_t max_len)
     364             : {
     365             :         struct wpabuf *buf;
     366             :         int res;
     367             :         char *pos;
     368             :         int ndef;
     369             : 
     370           8 :         pos = os_strchr(cmd, ' ');
     371           8 :         if (pos == NULL)
     372           0 :                 return -1;
     373           8 :         *pos++ = '\0';
     374             : 
     375           8 :         if (os_strcmp(cmd, "WPS") == 0)
     376           0 :                 ndef = 0;
     377           8 :         else if (os_strcmp(cmd, "NDEF") == 0)
     378           8 :                 ndef = 1;
     379             :         else
     380           0 :                 return -1;
     381             : 
     382           8 :         if (os_strcmp(pos, "WPS-CR") == 0)
     383           8 :                 buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
     384             :         else
     385           0 :                 buf = NULL;
     386           8 :         if (buf == NULL)
     387           0 :                 return -1;
     388             : 
     389           8 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
     390             :                                          wpabuf_len(buf));
     391           8 :         reply[res++] = '\n';
     392           8 :         reply[res] = '\0';
     393             : 
     394           8 :         wpabuf_free(buf);
     395             : 
     396           8 :         return res;
     397             : }
     398             : 
     399             : 
     400          17 : static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
     401             :                                                   char *cmd)
     402             : {
     403             :         size_t len;
     404             :         struct wpabuf *req, *sel;
     405             :         int ret;
     406             :         char *pos, *role, *type, *pos2;
     407             : 
     408          17 :         role = cmd;
     409          17 :         pos = os_strchr(role, ' ');
     410          17 :         if (pos == NULL)
     411           2 :                 return -1;
     412          15 :         *pos++ = '\0';
     413             : 
     414          15 :         type = pos;
     415          15 :         pos = os_strchr(type, ' ');
     416          15 :         if (pos == NULL)
     417           1 :                 return -1;
     418          14 :         *pos++ = '\0';
     419             : 
     420          14 :         pos2 = os_strchr(pos, ' ');
     421          14 :         if (pos2 == NULL)
     422           1 :                 return -1;
     423          13 :         *pos2++ = '\0';
     424             : 
     425          13 :         len = os_strlen(pos);
     426          13 :         if (len & 0x01)
     427           1 :                 return -1;
     428          12 :         len /= 2;
     429             : 
     430          12 :         req = wpabuf_alloc(len);
     431          12 :         if (req == NULL)
     432           0 :                 return -1;
     433          12 :         if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
     434           1 :                 wpabuf_free(req);
     435           1 :                 return -1;
     436             :         }
     437             : 
     438          11 :         len = os_strlen(pos2);
     439          11 :         if (len & 0x01) {
     440           1 :                 wpabuf_free(req);
     441           1 :                 return -1;
     442             :         }
     443          10 :         len /= 2;
     444             : 
     445          10 :         sel = wpabuf_alloc(len);
     446          10 :         if (sel == NULL) {
     447           0 :                 wpabuf_free(req);
     448           0 :                 return -1;
     449             :         }
     450          10 :         if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
     451           1 :                 wpabuf_free(req);
     452           1 :                 wpabuf_free(sel);
     453           1 :                 return -1;
     454             :         }
     455             : 
     456           9 :         if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
     457           8 :                 ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
     458             :         } else {
     459           1 :                 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
     460             :                            "reported: role=%s type=%s", role, type);
     461           1 :                 ret = -1;
     462             :         }
     463           9 :         wpabuf_free(req);
     464           9 :         wpabuf_free(sel);
     465             : 
     466           9 :         return ret;
     467             : }
     468             : 
     469             : #endif /* CONFIG_WPS_NFC */
     470             : 
     471             : 
     472          11 : static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
     473             :                                          char *buf, size_t buflen)
     474             : {
     475          11 :         int timeout = 300;
     476             :         char *pos;
     477             :         const char *pin_txt;
     478             : 
     479          11 :         pos = os_strchr(txt, ' ');
     480          11 :         if (pos)
     481           3 :                 *pos++ = '\0';
     482             : 
     483          11 :         if (os_strcmp(txt, "disable") == 0) {
     484           3 :                 hostapd_wps_ap_pin_disable(hapd);
     485           3 :                 return os_snprintf(buf, buflen, "OK\n");
     486             :         }
     487             : 
     488           8 :         if (os_strcmp(txt, "random") == 0) {
     489           3 :                 if (pos)
     490           1 :                         timeout = atoi(pos);
     491           3 :                 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
     492           3 :                 if (pin_txt == NULL)
     493           0 :                         return -1;
     494           3 :                 return os_snprintf(buf, buflen, "%s", pin_txt);
     495             :         }
     496             : 
     497           5 :         if (os_strcmp(txt, "get") == 0) {
     498           3 :                 pin_txt = hostapd_wps_ap_pin_get(hapd);
     499           3 :                 if (pin_txt == NULL)
     500           2 :                         return -1;
     501           1 :                 return os_snprintf(buf, buflen, "%s", pin_txt);
     502             :         }
     503             : 
     504           2 :         if (os_strcmp(txt, "set") == 0) {
     505             :                 char *pin;
     506           2 :                 if (pos == NULL)
     507           0 :                         return -1;
     508           2 :                 pin = pos;
     509           2 :                 pos = os_strchr(pos, ' ');
     510           2 :                 if (pos) {
     511           1 :                         *pos++ = '\0';
     512           1 :                         timeout = atoi(pos);
     513             :                 }
     514           2 :                 if (os_strlen(pin) > buflen)
     515           0 :                         return -1;
     516           2 :                 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
     517           0 :                         return -1;
     518           2 :                 return os_snprintf(buf, buflen, "%s", pin);
     519             :         }
     520             : 
     521           0 :         return -1;
     522             : }
     523             : 
     524             : 
     525           2 : static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
     526             : {
     527             :         char *pos;
     528           2 :         char *ssid, *auth, *encr = NULL, *key = NULL;
     529             : 
     530           2 :         ssid = txt;
     531           2 :         pos = os_strchr(txt, ' ');
     532           2 :         if (!pos)
     533           0 :                 return -1;
     534           2 :         *pos++ = '\0';
     535             : 
     536           2 :         auth = pos;
     537           2 :         pos = os_strchr(pos, ' ');
     538           2 :         if (pos) {
     539           2 :                 *pos++ = '\0';
     540           2 :                 encr = pos;
     541           2 :                 pos = os_strchr(pos, ' ');
     542           2 :                 if (pos) {
     543           2 :                         *pos++ = '\0';
     544           2 :                         key = pos;
     545             :                 }
     546             :         }
     547             : 
     548           2 :         return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
     549             : }
     550             : 
     551             : 
     552           5 : static const char * pbc_status_str(enum pbc_status status)
     553             : {
     554           5 :         switch (status) {
     555             :         case WPS_PBC_STATUS_DISABLE:
     556           4 :                 return "Disabled";
     557             :         case WPS_PBC_STATUS_ACTIVE:
     558           1 :                 return "Active";
     559             :         case WPS_PBC_STATUS_TIMEOUT:
     560           0 :                 return "Timed-out";
     561             :         case WPS_PBC_STATUS_OVERLAP:
     562           0 :                 return "Overlap";
     563             :         default:
     564           0 :                 return "Unknown";
     565             :         }
     566             : }
     567             : 
     568             : 
     569           5 : static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
     570             :                                              char *buf, size_t buflen)
     571             : {
     572             :         int ret;
     573             :         char *pos, *end;
     574             : 
     575           5 :         pos = buf;
     576           5 :         end = buf + buflen;
     577             : 
     578           5 :         ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
     579             :                           pbc_status_str(hapd->wps_stats.pbc_status));
     580             : 
     581           5 :         if (ret < 0 || ret >= end - pos)
     582           0 :                 return pos - buf;
     583           5 :         pos += ret;
     584             : 
     585           9 :         ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
     586           5 :                           (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
     587             :                            "Success":
     588           4 :                            (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
     589           4 :                             "Failed" : "None")));
     590             : 
     591           5 :         if (ret < 0 || ret >= end - pos)
     592           0 :                 return pos - buf;
     593           5 :         pos += ret;
     594             : 
     595             :         /* If status == Failure - Add possible Reasons */
     596           8 :         if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
     597           3 :            hapd->wps_stats.failure_reason > 0) {
     598           1 :                 ret = os_snprintf(pos, end - pos,
     599             :                                   "Failure Reason: %s\n",
     600             :                                   wps_ei_str(hapd->wps_stats.failure_reason));
     601             : 
     602           1 :                 if (ret < 0 || ret >= end - pos)
     603           0 :                         return pos - buf;
     604           1 :                 pos += ret;
     605             :         }
     606             : 
     607           5 :         if (hapd->wps_stats.status) {
     608          24 :                 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
     609          24 :                                   MAC2STR(hapd->wps_stats.peer_addr));
     610             : 
     611           4 :                 if (ret < 0 || ret >= end - pos)
     612           0 :                         return pos - buf;
     613           4 :                 pos += ret;
     614             :         }
     615             : 
     616           5 :         return pos - buf;
     617             : }
     618             : 
     619             : #endif /* CONFIG_WPS */
     620             : 
     621             : #ifdef CONFIG_HS20
     622             : 
     623           7 : static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
     624             :                                              const char *cmd)
     625             : {
     626             :         u8 addr[ETH_ALEN];
     627             :         const char *url;
     628             : 
     629           7 :         if (hwaddr_aton(cmd, addr))
     630           3 :                 return -1;
     631           4 :         url = cmd + 17;
     632           4 :         if (*url == '\0') {
     633           1 :                 url = NULL;
     634             :         } else {
     635           3 :                 if (*url != ' ')
     636           1 :                         return -1;
     637           2 :                 url++;
     638           2 :                 if (*url == '\0')
     639           0 :                         url = NULL;
     640             :         }
     641             : 
     642           3 :         return hs20_send_wnm_notification(hapd, addr, 1, url);
     643             : }
     644             : 
     645             : 
     646           5 : static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
     647             :                                               const char *cmd)
     648             : {
     649             :         u8 addr[ETH_ALEN];
     650             :         int code, reauth_delay, ret;
     651             :         const char *pos;
     652             :         size_t url_len;
     653             :         struct wpabuf *req;
     654             : 
     655             :         /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
     656           5 :         if (hwaddr_aton(cmd, addr))
     657           1 :                 return -1;
     658             : 
     659           4 :         pos = os_strchr(cmd, ' ');
     660           4 :         if (pos == NULL)
     661           1 :                 return -1;
     662           3 :         pos++;
     663           3 :         code = atoi(pos);
     664             : 
     665           3 :         pos = os_strchr(pos, ' ');
     666           3 :         if (pos == NULL)
     667           1 :                 return -1;
     668           2 :         pos++;
     669           2 :         reauth_delay = atoi(pos);
     670             : 
     671           2 :         url_len = 0;
     672           2 :         pos = os_strchr(pos, ' ');
     673           2 :         if (pos) {
     674           2 :                 pos++;
     675           2 :                 url_len = os_strlen(pos);
     676             :         }
     677             : 
     678           2 :         req = wpabuf_alloc(4 + url_len);
     679           2 :         if (req == NULL)
     680           0 :                 return -1;
     681           2 :         wpabuf_put_u8(req, code);
     682           2 :         wpabuf_put_le16(req, reauth_delay);
     683           2 :         wpabuf_put_u8(req, url_len);
     684           2 :         if (pos)
     685           2 :                 wpabuf_put_data(req, pos, url_len);
     686             : 
     687          12 :         wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
     688             :                    " to indicate imminent deauthentication (code=%d "
     689          12 :                    "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
     690           2 :         ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
     691           2 :         wpabuf_free(req);
     692           2 :         return ret;
     693             : }
     694             : 
     695             : #endif /* CONFIG_HS20 */
     696             : 
     697             : 
     698             : #ifdef CONFIG_INTERWORKING
     699             : 
     700           7 : static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
     701             :                                               const char *cmd)
     702             : {
     703           7 :         u8 qos_map_set[16 + 2 * 21], count = 0;
     704           7 :         const char *pos = cmd;
     705             :         int val, ret;
     706             : 
     707             :         for (;;) {
     708         122 :                 if (count == sizeof(qos_map_set)) {
     709           1 :                         wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
     710           1 :                         return -1;
     711             :                 }
     712             : 
     713         121 :                 val = atoi(pos);
     714         121 :                 if (val < 0 || val > 255) {
     715           1 :                         wpa_printf(MSG_INFO, "Invalid QoS Map Set");
     716           1 :                         return -1;
     717             :                 }
     718             : 
     719         120 :                 qos_map_set[count++] = val;
     720         120 :                 pos = os_strchr(pos, ',');
     721         120 :                 if (!pos)
     722           5 :                         break;
     723         115 :                 pos++;
     724         115 :         }
     725             : 
     726           5 :         if (count < 16 || count & 1) {
     727           3 :                 wpa_printf(MSG_INFO, "Invalid QoS Map Set");
     728           3 :                 return -1;
     729             :         }
     730             : 
     731           2 :         ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
     732           2 :         if (ret) {
     733           0 :                 wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
     734           0 :                 return -1;
     735             :         }
     736             : 
     737           2 :         os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
     738           2 :         hapd->conf->qos_map_set_len = count;
     739             : 
     740           2 :         return 0;
     741             : }
     742             : 
     743             : 
     744           4 : static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
     745             :                                                 const char *cmd)
     746             : {
     747             :         u8 addr[ETH_ALEN];
     748             :         struct sta_info *sta;
     749             :         struct wpabuf *buf;
     750           4 :         u8 *qos_map_set = hapd->conf->qos_map_set;
     751           4 :         u8 qos_map_set_len = hapd->conf->qos_map_set_len;
     752             :         int ret;
     753             : 
     754           4 :         if (!qos_map_set_len) {
     755           1 :                 wpa_printf(MSG_INFO, "QoS Map Set is not set");
     756           1 :                 return -1;
     757             :         }
     758             : 
     759           3 :         if (hwaddr_aton(cmd, addr))
     760           1 :                 return -1;
     761             : 
     762           2 :         sta = ap_get_sta(hapd, addr);
     763           2 :         if (sta == NULL) {
     764           6 :                 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
     765             :                            "for QoS Map Configuration message",
     766           6 :                            MAC2STR(addr));
     767           1 :                 return -1;
     768             :         }
     769             : 
     770           1 :         if (!sta->qos_map_enabled) {
     771           0 :                 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
     772           0 :                            "support for QoS Map", MAC2STR(addr));
     773           0 :                 return -1;
     774             :         }
     775             : 
     776           1 :         buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
     777           1 :         if (buf == NULL)
     778           0 :                 return -1;
     779             : 
     780           1 :         wpabuf_put_u8(buf, WLAN_ACTION_QOS);
     781           1 :         wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
     782             : 
     783             :         /* QoS Map Set Element */
     784           1 :         wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
     785           1 :         wpabuf_put_u8(buf, qos_map_set_len);
     786           1 :         wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
     787             : 
     788           2 :         ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
     789           1 :                                       wpabuf_head(buf), wpabuf_len(buf));
     790           1 :         wpabuf_free(buf);
     791             : 
     792           1 :         return ret;
     793             : }
     794             : 
     795             : #endif /* CONFIG_INTERWORKING */
     796             : 
     797             : 
     798             : #ifdef CONFIG_WNM
     799             : 
     800           5 : static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
     801             :                                                 const char *cmd)
     802             : {
     803             :         u8 addr[ETH_ALEN];
     804             :         int disassoc_timer;
     805             :         struct sta_info *sta;
     806             : 
     807           5 :         if (hwaddr_aton(cmd, addr))
     808           1 :                 return -1;
     809           4 :         if (cmd[17] != ' ')
     810           1 :                 return -1;
     811           3 :         disassoc_timer = atoi(cmd + 17);
     812             : 
     813           3 :         sta = ap_get_sta(hapd, addr);
     814           3 :         if (sta == NULL) {
     815           6 :                 wpa_printf(MSG_DEBUG, "Station " MACSTR
     816             :                            " not found for disassociation imminent message",
     817           6 :                            MAC2STR(addr));
     818           1 :                 return -1;
     819             :         }
     820             : 
     821           2 :         return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
     822             : }
     823             : 
     824             : 
     825           8 : static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
     826             :                                            const char *cmd)
     827             : {
     828             :         u8 addr[ETH_ALEN];
     829             :         const char *url, *timerstr;
     830             :         int disassoc_timer;
     831             :         struct sta_info *sta;
     832             : 
     833           8 :         if (hwaddr_aton(cmd, addr))
     834           1 :                 return -1;
     835             : 
     836           7 :         sta = ap_get_sta(hapd, addr);
     837           7 :         if (sta == NULL) {
     838           6 :                 wpa_printf(MSG_DEBUG, "Station " MACSTR
     839             :                            " not found for ESS disassociation imminent message",
     840           6 :                            MAC2STR(addr));
     841           1 :                 return -1;
     842             :         }
     843             : 
     844           6 :         timerstr = cmd + 17;
     845           6 :         if (*timerstr != ' ')
     846           1 :                 return -1;
     847           5 :         timerstr++;
     848           5 :         disassoc_timer = atoi(timerstr);
     849           5 :         if (disassoc_timer < 0 || disassoc_timer > 65535)
     850           1 :                 return -1;
     851             : 
     852           4 :         url = os_strchr(timerstr, ' ');
     853           4 :         if (url == NULL)
     854           1 :                 return -1;
     855           3 :         url++;
     856             : 
     857           3 :         return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
     858             : }
     859             : 
     860             : #endif /* CONFIG_WNM */
     861             : 
     862             : 
     863          10 : static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
     864             :                                          char *buf, size_t buflen)
     865             : {
     866             :         int ret;
     867             :         char *pos, *end;
     868             : 
     869          10 :         pos = buf;
     870          10 :         end = buf + buflen;
     871             : 
     872          80 :         ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
     873             :                           "ssid=%s\n",
     874          60 :                           MAC2STR(hapd->own_addr),
     875          10 :                           wpa_ssid_txt(hapd->conf->ssid.ssid,
     876          10 :                                        hapd->conf->ssid.ssid_len));
     877          10 :         if (ret < 0 || ret >= end - pos)
     878           0 :                 return pos - buf;
     879          10 :         pos += ret;
     880             : 
     881             : #ifdef CONFIG_WPS
     882          11 :         ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
     883          10 :                           hapd->conf->wps_state == 0 ? "disabled" :
     884           1 :                           (hapd->conf->wps_state == 1 ? "not configured" :
     885             :                            "configured"));
     886          10 :         if (ret < 0 || ret >= end - pos)
     887           0 :                 return pos - buf;
     888          10 :         pos += ret;
     889             : 
     890          11 :         if (hapd->conf->wps_state && hapd->conf->wpa &&
     891           1 :             hapd->conf->ssid.wpa_passphrase) {
     892           1 :                 ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
     893           1 :                                   hapd->conf->ssid.wpa_passphrase);
     894           1 :                 if (ret < 0 || ret >= end - pos)
     895           0 :                         return pos - buf;
     896           1 :                 pos += ret;
     897             :         }
     898             : 
     899          11 :         if (hapd->conf->wps_state && hapd->conf->wpa &&
     900           2 :             hapd->conf->ssid.wpa_psk &&
     901           1 :             hapd->conf->ssid.wpa_psk->group) {
     902             :                 char hex[PMK_LEN * 2 + 1];
     903           1 :                 wpa_snprintf_hex(hex, sizeof(hex),
     904           1 :                                  hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
     905           1 :                 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
     906           1 :                 if (ret < 0 || ret >= end - pos)
     907           0 :                         return pos - buf;
     908           1 :                 pos += ret;
     909             :         }
     910             : #endif /* CONFIG_WPS */
     911             : 
     912          10 :         if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
     913          10 :                 ret = os_snprintf(pos, end - pos, "key_mgmt=");
     914          10 :                 if (ret < 0 || ret >= end - pos)
     915           0 :                         return pos - buf;
     916          10 :                 pos += ret;
     917             : 
     918          10 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
     919           3 :                         ret = os_snprintf(pos, end - pos, "WPA-PSK ");
     920           3 :                         if (ret < 0 || ret >= end - pos)
     921           0 :                                 return pos - buf;
     922           3 :                         pos += ret;
     923             :                 }
     924          10 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
     925           1 :                         ret = os_snprintf(pos, end - pos, "WPA-EAP ");
     926           1 :                         if (ret < 0 || ret >= end - pos)
     927           0 :                                 return pos - buf;
     928           1 :                         pos += ret;
     929             :                 }
     930             : #ifdef CONFIG_IEEE80211R
     931          10 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
     932           1 :                         ret = os_snprintf(pos, end - pos, "FT-PSK ");
     933           1 :                         if (ret < 0 || ret >= end - pos)
     934           0 :                                 return pos - buf;
     935           1 :                         pos += ret;
     936             :                 }
     937          10 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
     938           2 :                         ret = os_snprintf(pos, end - pos, "FT-EAP ");
     939           2 :                         if (ret < 0 || ret >= end - pos)
     940           0 :                                 return pos - buf;
     941           2 :                         pos += ret;
     942             :                 }
     943             : #ifdef CONFIG_SAE
     944          10 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
     945           1 :                         ret = os_snprintf(pos, end - pos, "FT-SAE ");
     946           1 :                         if (ret < 0 || ret >= end - pos)
     947           0 :                                 return pos - buf;
     948           1 :                         pos += ret;
     949             :                 }
     950             : #endif /* CONFIG_SAE */
     951             : #endif /* CONFIG_IEEE80211R */
     952             : #ifdef CONFIG_IEEE80211W
     953          10 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
     954           1 :                         ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
     955           1 :                         if (ret < 0 || ret >= end - pos)
     956           0 :                                 return pos - buf;
     957           1 :                         pos += ret;
     958             :                 }
     959          10 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
     960           1 :                         ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
     961           1 :                         if (ret < 0 || ret >= end - pos)
     962           0 :                                 return pos - buf;
     963           1 :                         pos += ret;
     964             :                 }
     965             : #endif /* CONFIG_IEEE80211W */
     966             : #ifdef CONFIG_SAE
     967          10 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
     968           1 :                         ret = os_snprintf(pos, end - pos, "SAE ");
     969           1 :                         if (ret < 0 || ret >= end - pos)
     970           0 :                                 return pos - buf;
     971           1 :                         pos += ret;
     972             :                 }
     973             : #endif /* CONFIG_SAE */
     974             : 
     975          10 :                 ret = os_snprintf(pos, end - pos, "\n");
     976          10 :                 if (ret < 0 || ret >= end - pos)
     977           0 :                         return pos - buf;
     978          10 :                 pos += ret;
     979             :         }
     980             : 
     981          10 :         if (hapd->conf->wpa) {
     982          10 :                 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
     983          10 :                                   wpa_cipher_txt(hapd->conf->wpa_group));
     984          10 :                 if (ret < 0 || ret >= end - pos)
     985           0 :                         return pos - buf;
     986          10 :                 pos += ret;
     987             :         }
     988             : 
     989          10 :         if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
     990          10 :                 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
     991          10 :                 if (ret < 0 || ret >= end - pos)
     992           0 :                         return pos - buf;
     993          10 :                 pos += ret;
     994             : 
     995          10 :                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
     996             :                                         " ");
     997          10 :                 if (ret < 0)
     998           0 :                         return pos - buf;
     999          10 :                 pos += ret;
    1000             : 
    1001          10 :                 ret = os_snprintf(pos, end - pos, "\n");
    1002          10 :                 if (ret < 0 || ret >= end - pos)
    1003           0 :                         return pos - buf;
    1004          10 :                 pos += ret;
    1005             :         }
    1006             : 
    1007          10 :         if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
    1008           2 :                 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
    1009           2 :                 if (ret < 0 || ret >= end - pos)
    1010           0 :                         return pos - buf;
    1011           2 :                 pos += ret;
    1012             : 
    1013           2 :                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
    1014             :                                         " ");
    1015           2 :                 if (ret < 0)
    1016           0 :                         return pos - buf;
    1017           2 :                 pos += ret;
    1018             : 
    1019           2 :                 ret = os_snprintf(pos, end - pos, "\n");
    1020           2 :                 if (ret < 0 || ret >= end - pos)
    1021           0 :                         return pos - buf;
    1022           2 :                 pos += ret;
    1023             :         }
    1024             : 
    1025          10 :         return pos - buf;
    1026             : }
    1027             : 
    1028             : 
    1029       10024 : static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
    1030             : {
    1031             :         char *value;
    1032       10024 :         int ret = 0;
    1033             : 
    1034       10024 :         value = os_strchr(cmd, ' ');
    1035       10024 :         if (value == NULL)
    1036           0 :                 return -1;
    1037       10024 :         *value++ = '\0';
    1038             : 
    1039       10024 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
    1040             :         if (0) {
    1041             : #ifdef CONFIG_WPS_TESTING
    1042       10024 :         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
    1043             :                 long int val;
    1044           4 :                 val = strtol(value, NULL, 0);
    1045           4 :                 if (val < 0 || val > 0xff) {
    1046           0 :                         ret = -1;
    1047           0 :                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
    1048             :                                    "wps_version_number %ld", val);
    1049             :                 } else {
    1050           4 :                         wps_version_number = val;
    1051           8 :                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
    1052             :                                    "version %u.%u",
    1053           4 :                                    (wps_version_number & 0xf0) >> 4,
    1054             :                                    wps_version_number & 0x0f);
    1055           4 :                         hostapd_wps_update_ie(hapd);
    1056             :                 }
    1057       10020 :         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
    1058           0 :                 wps_testing_dummy_cred = atoi(value);
    1059           0 :                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
    1060             :                            wps_testing_dummy_cred);
    1061       10020 :         } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
    1062           1 :                 wps_corrupt_pkhash = atoi(value);
    1063           1 :                 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
    1064             :                            wps_corrupt_pkhash);
    1065             : #endif /* CONFIG_WPS_TESTING */
    1066             : #ifdef CONFIG_INTERWORKING
    1067       10019 :         } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
    1068           3 :                 int val = atoi(value);
    1069           3 :                 if (val <= 0)
    1070           0 :                         ret = -1;
    1071             :                 else
    1072           3 :                         hapd->gas_frag_limit = val;
    1073             : #endif /* CONFIG_INTERWORKING */
    1074             : #ifdef CONFIG_TESTING_OPTIONS
    1075       10016 :         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
    1076          24 :                 hapd->ext_mgmt_frame_handling = atoi(value);
    1077             : #endif /* CONFIG_TESTING_OPTIONS */
    1078             :         } else {
    1079             :                 struct sta_info *sta;
    1080             :                 int vlan_id;
    1081             : 
    1082        9992 :                 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
    1083        9992 :                 if (ret)
    1084         165 :                         return ret;
    1085             : 
    1086        9827 :                 if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
    1087           4 :                         for (sta = hapd->sta_list; sta; sta = sta->next) {
    1088           4 :                                 if (hostapd_maclist_found(
    1089           2 :                                             hapd->conf->deny_mac,
    1090           2 :                                             hapd->conf->num_deny_mac, sta->addr,
    1091           1 :                                             &vlan_id) &&
    1092           1 :                                     (!vlan_id || vlan_id == sta->vlan_id))
    1093           1 :                                         ap_sta_disconnect(
    1094           1 :                                                 hapd, sta, sta->addr,
    1095             :                                                 WLAN_REASON_UNSPECIFIED);
    1096             :                         }
    1097        9828 :                 } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
    1098           3 :                            os_strcasecmp(cmd, "accept_mac_file") == 0) {
    1099           3 :                         for (sta = hapd->sta_list; sta; sta = sta->next) {
    1100           4 :                                 if (!hostapd_maclist_found(
    1101           2 :                                             hapd->conf->accept_mac,
    1102           2 :                                             hapd->conf->num_accept_mac,
    1103           3 :                                             sta->addr, &vlan_id) ||
    1104           1 :                                     (vlan_id && vlan_id != sta->vlan_id))
    1105           1 :                                         ap_sta_disconnect(
    1106           1 :                                                 hapd, sta, sta->addr,
    1107             :                                                 WLAN_REASON_UNSPECIFIED);
    1108             :                         }
    1109             :                 }
    1110             :         }
    1111             : 
    1112        9859 :         return ret;
    1113             : }
    1114             : 
    1115             : 
    1116           2 : static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
    1117             :                                   char *buf, size_t buflen)
    1118             : {
    1119             :         int res;
    1120             : 
    1121           2 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
    1122             : 
    1123           2 :         if (os_strcmp(cmd, "version") == 0) {
    1124           1 :                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
    1125           1 :                 if (res < 0 || (unsigned int) res >= buflen)
    1126           0 :                         return -1;
    1127           1 :                 return res;
    1128             :         }
    1129             : 
    1130           1 :         return -1;
    1131             : }
    1132             : 
    1133             : 
    1134         551 : static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
    1135             : {
    1136         551 :         if (hostapd_enable_iface(iface) < 0) {
    1137          15 :                 wpa_printf(MSG_ERROR, "Enabling of interface failed");
    1138          15 :                 return -1;
    1139             :         }
    1140         536 :         return 0;
    1141             : }
    1142             : 
    1143             : 
    1144           1 : static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
    1145             : {
    1146           1 :         if (hostapd_reload_iface(iface) < 0) {
    1147           0 :                 wpa_printf(MSG_ERROR, "Reloading of interface failed");
    1148           0 :                 return -1;
    1149             :         }
    1150           1 :         return 0;
    1151             : }
    1152             : 
    1153             : 
    1154           8 : static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
    1155             : {
    1156           8 :         if (hostapd_disable_iface(iface) < 0) {
    1157           0 :                 wpa_printf(MSG_ERROR, "Disabling of interface failed");
    1158           0 :                 return -1;
    1159             :         }
    1160           8 :         return 0;
    1161             : }
    1162             : 
    1163             : 
    1164             : #ifdef CONFIG_TESTING_OPTIONS
    1165             : 
    1166           2 : static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
    1167             : {
    1168             :         union wpa_event_data data;
    1169             :         char *pos, *param;
    1170             :         enum wpa_event_type event;
    1171             : 
    1172           2 :         wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
    1173             : 
    1174           2 :         os_memset(&data, 0, sizeof(data));
    1175             : 
    1176           2 :         param = os_strchr(cmd, ' ');
    1177           2 :         if (param == NULL)
    1178           0 :                 return -1;
    1179           2 :         *param++ = '\0';
    1180             : 
    1181           2 :         if (os_strcmp(cmd, "DETECTED") == 0)
    1182           2 :                 event = EVENT_DFS_RADAR_DETECTED;
    1183           0 :         else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
    1184           0 :                 event = EVENT_DFS_CAC_FINISHED;
    1185           0 :         else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
    1186           0 :                 event = EVENT_DFS_CAC_ABORTED;
    1187           0 :         else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
    1188           0 :                 event = EVENT_DFS_NOP_FINISHED;
    1189             :         else {
    1190           0 :                 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
    1191             :                            cmd);
    1192           0 :                 return -1;
    1193             :         }
    1194             : 
    1195           2 :         pos = os_strstr(param, "freq=");
    1196           2 :         if (pos)
    1197           2 :                 data.dfs_event.freq = atoi(pos + 5);
    1198             : 
    1199           2 :         pos = os_strstr(param, "ht_enabled=1");
    1200           2 :         if (pos)
    1201           2 :                 data.dfs_event.ht_enabled = 1;
    1202             : 
    1203           2 :         pos = os_strstr(param, "chan_offset=");
    1204           2 :         if (pos)
    1205           0 :                 data.dfs_event.chan_offset = atoi(pos + 12);
    1206             : 
    1207           2 :         pos = os_strstr(param, "chan_width=");
    1208           2 :         if (pos)
    1209           2 :                 data.dfs_event.chan_width = atoi(pos + 11);
    1210             : 
    1211           2 :         pos = os_strstr(param, "cf1=");
    1212           2 :         if (pos)
    1213           0 :                 data.dfs_event.cf1 = atoi(pos + 4);
    1214             : 
    1215           2 :         pos = os_strstr(param, "cf2=");
    1216           2 :         if (pos)
    1217           0 :                 data.dfs_event.cf2 = atoi(pos + 4);
    1218             : 
    1219           2 :         wpa_supplicant_event(hapd, event, &data);
    1220             : 
    1221           2 :         return 0;
    1222             : }
    1223             : 
    1224             : 
    1225         246 : static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
    1226             : {
    1227             :         size_t len;
    1228             :         u8 *buf;
    1229             :         int res;
    1230             : 
    1231         246 :         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
    1232             : 
    1233         246 :         len = os_strlen(cmd);
    1234         246 :         if (len & 1)
    1235           0 :                 return -1;
    1236         246 :         len /= 2;
    1237             : 
    1238         246 :         buf = os_malloc(len);
    1239         246 :         if (buf == NULL)
    1240           0 :                 return -1;
    1241             : 
    1242         246 :         if (hexstr2bin(cmd, buf, len) < 0) {
    1243           0 :                 os_free(buf);
    1244           0 :                 return -1;
    1245             :         }
    1246             : 
    1247         246 :         res = hostapd_drv_send_mlme(hapd, buf, len, 0);
    1248         246 :         os_free(buf);
    1249         246 :         return res;
    1250             : }
    1251             : 
    1252             : #endif /* CONFIG_TESTING_OPTIONS */
    1253             : 
    1254             : 
    1255           4 : static int hostapd_ctrl_iface_chan_switch(struct hostapd_data *hapd, char *pos)
    1256             : {
    1257             : #ifdef NEED_AP_MLME
    1258             :         struct csa_settings settings;
    1259           4 :         int ret = hostapd_parse_csa_settings(pos, &settings);
    1260             : 
    1261           4 :         if (ret)
    1262           3 :                 return ret;
    1263             : 
    1264           1 :         return hostapd_switch_channel(hapd, &settings);
    1265             : #else /* NEED_AP_MLME */
    1266             :         return -1;
    1267             : #endif /* NEED_AP_MLME */
    1268             : }
    1269             : 
    1270             : 
    1271           4 : static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
    1272             :                                   int reply_size, const char *param)
    1273             : {
    1274             : #ifdef RADIUS_SERVER
    1275           4 :         if (os_strcmp(param, "radius_server") == 0) {
    1276           4 :                 return radius_server_get_mib(hapd->radius_srv, reply,
    1277             :                                              reply_size);
    1278             :         }
    1279             : #endif /* RADIUS_SERVER */
    1280           0 :         return -1;
    1281             : }
    1282             : 
    1283             : 
    1284           0 : static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
    1285             :                                      char *buf, size_t buflen)
    1286             : {
    1287             :         int ret;
    1288             :         char *pos;
    1289           0 :         u8 *data = NULL;
    1290             :         unsigned int vendor_id, subcmd;
    1291             :         struct wpabuf *reply;
    1292           0 :         size_t data_len = 0;
    1293             : 
    1294             :         /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
    1295           0 :         vendor_id = strtoul(cmd, &pos, 16);
    1296           0 :         if (!isblank(*pos))
    1297           0 :                 return -EINVAL;
    1298             : 
    1299           0 :         subcmd = strtoul(pos, &pos, 10);
    1300             : 
    1301           0 :         if (*pos != '\0') {
    1302           0 :                 if (!isblank(*pos++))
    1303           0 :                         return -EINVAL;
    1304           0 :                 data_len = os_strlen(pos);
    1305             :         }
    1306             : 
    1307           0 :         if (data_len) {
    1308           0 :                 data_len /= 2;
    1309           0 :                 data = os_malloc(data_len);
    1310           0 :                 if (!data)
    1311           0 :                         return -ENOBUFS;
    1312             : 
    1313           0 :                 if (hexstr2bin(pos, data, data_len)) {
    1314           0 :                         wpa_printf(MSG_DEBUG,
    1315             :                                    "Vendor command: wrong parameter format");
    1316           0 :                         os_free(data);
    1317           0 :                         return -EINVAL;
    1318             :                 }
    1319             :         }
    1320             : 
    1321           0 :         reply = wpabuf_alloc((buflen - 1) / 2);
    1322           0 :         if (!reply) {
    1323           0 :                 os_free(data);
    1324           0 :                 return -ENOBUFS;
    1325             :         }
    1326             : 
    1327           0 :         ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
    1328             :                                      reply);
    1329             : 
    1330           0 :         if (ret == 0)
    1331           0 :                 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
    1332             :                                        wpabuf_len(reply));
    1333             : 
    1334           0 :         wpabuf_free(reply);
    1335           0 :         os_free(data);
    1336             : 
    1337           0 :         return ret;
    1338             : }
    1339             : 
    1340             : 
    1341       13217 : static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
    1342             :                                        void *sock_ctx)
    1343             : {
    1344       13217 :         struct hostapd_data *hapd = eloop_ctx;
    1345             :         char buf[4096];
    1346             :         int res;
    1347             :         struct sockaddr_un from;
    1348       13217 :         socklen_t fromlen = sizeof(from);
    1349             :         char *reply;
    1350       13217 :         const int reply_size = 4096;
    1351             :         int reply_len;
    1352       13217 :         int level = MSG_DEBUG;
    1353             : 
    1354       13217 :         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
    1355             :                        (struct sockaddr *) &from, &fromlen);
    1356       13217 :         if (res < 0) {
    1357           0 :                 perror("recvfrom(ctrl_iface)");
    1358           0 :                 return;
    1359             :         }
    1360       13217 :         buf[res] = '\0';
    1361       13217 :         if (os_strcmp(buf, "PING") == 0)
    1362         562 :                 level = MSG_EXCESSIVE;
    1363       13217 :         wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
    1364             : 
    1365       13217 :         reply = os_malloc(reply_size);
    1366       13217 :         if (reply == NULL) {
    1367           0 :                 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
    1368             :                        fromlen);
    1369           0 :                 return;
    1370             :         }
    1371             : 
    1372       13217 :         os_memcpy(reply, "OK\n", 3);
    1373       13217 :         reply_len = 3;
    1374             : 
    1375       13217 :         if (os_strcmp(buf, "PING") == 0) {
    1376         562 :                 os_memcpy(reply, "PONG\n", 5);
    1377         562 :                 reply_len = 5;
    1378       12655 :         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
    1379           0 :                 if (wpa_debug_reopen_file() < 0)
    1380           0 :                         reply_len = -1;
    1381       12655 :         } else if (os_strcmp(buf, "STATUS") == 0) {
    1382         118 :                 reply_len = hostapd_ctrl_iface_status(hapd, reply,
    1383             :                                                       reply_size);
    1384       12537 :         } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
    1385           2 :                 reply_len = hostapd_drv_status(hapd, reply, reply_size);
    1386       12535 :         } else if (os_strcmp(buf, "MIB") == 0) {
    1387           3 :                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
    1388           3 :                 if (reply_len >= 0) {
    1389           3 :                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
    1390           3 :                                           reply_size - reply_len);
    1391           3 :                         if (res < 0)
    1392           0 :                                 reply_len = -1;
    1393             :                         else
    1394           3 :                                 reply_len += res;
    1395             :                 }
    1396           3 :                 if (reply_len >= 0) {
    1397           3 :                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
    1398           3 :                                                  reply_size - reply_len);
    1399           3 :                         if (res < 0)
    1400           0 :                                 reply_len = -1;
    1401             :                         else
    1402           3 :                                 reply_len += res;
    1403             :                 }
    1404             : #ifndef CONFIG_NO_RADIUS
    1405           3 :                 if (reply_len >= 0) {
    1406           3 :                         res = radius_client_get_mib(hapd->radius,
    1407             :                                                     reply + reply_len,
    1408           3 :                                                     reply_size - reply_len);
    1409           3 :                         if (res < 0)
    1410           0 :                                 reply_len = -1;
    1411             :                         else
    1412           3 :                                 reply_len += res;
    1413             :                 }
    1414             : #endif /* CONFIG_NO_RADIUS */
    1415       12532 :         } else if (os_strncmp(buf, "MIB ", 4) == 0) {
    1416           4 :                 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
    1417             :                                                    buf + 4);
    1418       12528 :         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
    1419           1 :                 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
    1420             :                                                          reply_size);
    1421       12527 :         } else if (os_strncmp(buf, "STA ", 4) == 0) {
    1422          29 :                 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
    1423             :                                                    reply_size);
    1424       12498 :         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
    1425           4 :                 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
    1426             :                                                         reply_size);
    1427       12494 :         } else if (os_strcmp(buf, "ATTACH") == 0) {
    1428         753 :                 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
    1429           0 :                         reply_len = -1;
    1430       11741 :         } else if (os_strcmp(buf, "DETACH") == 0) {
    1431         737 :                 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
    1432           0 :                         reply_len = -1;
    1433       11004 :         } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
    1434           1 :                 if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
    1435             :                                                     buf + 6))
    1436           1 :                         reply_len = -1;
    1437       11003 :         } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
    1438           2 :                 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
    1439           1 :                         reply_len = -1;
    1440       11001 :         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
    1441           6 :                 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
    1442           1 :                         reply_len = -1;
    1443       10995 :         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
    1444           3 :                 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
    1445           1 :                         reply_len = -1;
    1446             : #ifdef CONFIG_IEEE80211W
    1447             : #ifdef NEED_AP_MLME
    1448       10992 :         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
    1449           2 :                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
    1450           0 :                         reply_len = -1;
    1451             : #endif /* NEED_AP_MLME */
    1452             : #endif /* CONFIG_IEEE80211W */
    1453             : #ifdef CONFIG_WPS
    1454       10990 :         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
    1455          14 :                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
    1456           1 :                         reply_len = -1;
    1457       10976 :         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
    1458           9 :                 reply_len = hostapd_ctrl_iface_wps_check_pin(
    1459             :                         hapd, buf + 14, reply, reply_size);
    1460       10967 :         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
    1461          25 :                 if (hostapd_wps_button_pushed(hapd, NULL))
    1462           2 :                         reply_len = -1;
    1463       10942 :         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
    1464           4 :                 if (hostapd_wps_cancel(hapd))
    1465           1 :                         reply_len = -1;
    1466       10938 :         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
    1467          11 :                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
    1468             :                                                           reply, reply_size);
    1469       10927 :         } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
    1470           2 :                 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
    1471           0 :                         reply_len = -1;
    1472       10925 :         } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
    1473           5 :                 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
    1474             :                                                               reply_size);
    1475             : #ifdef CONFIG_WPS_NFC
    1476       10920 :         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
    1477           2 :                 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
    1478           0 :                         reply_len = -1;
    1479       10918 :         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
    1480           2 :                 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
    1481             :                         hapd, buf + 21, reply, reply_size);
    1482       10916 :         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
    1483           6 :                 reply_len = hostapd_ctrl_iface_wps_nfc_token(
    1484             :                         hapd, buf + 14, reply, reply_size);
    1485       10910 :         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
    1486           8 :                 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
    1487             :                         hapd, buf + 21, reply, reply_size);
    1488       10902 :         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
    1489          17 :                 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
    1490          10 :                         reply_len = -1;
    1491             : #endif /* CONFIG_WPS_NFC */
    1492             : #endif /* CONFIG_WPS */
    1493             : #ifdef CONFIG_INTERWORKING
    1494       10885 :         } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
    1495           7 :                 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
    1496           5 :                         reply_len = -1;
    1497       10878 :         } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
    1498           4 :                 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
    1499           3 :                         reply_len = -1;
    1500             : #endif /* CONFIG_INTERWORKING */
    1501             : #ifdef CONFIG_HS20
    1502       10874 :         } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
    1503           7 :                 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
    1504           5 :                         reply_len = -1;
    1505       10867 :         } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
    1506           5 :                 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
    1507           3 :                         reply_len = -1;
    1508             : #endif /* CONFIG_HS20 */
    1509             : #ifdef CONFIG_WNM
    1510       10862 :         } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
    1511           5 :                 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
    1512           3 :                         reply_len = -1;
    1513       10857 :         } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
    1514           8 :                 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
    1515           5 :                         reply_len = -1;
    1516             : #endif /* CONFIG_WNM */
    1517       10849 :         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
    1518          10 :                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
    1519             :                                                           reply_size);
    1520       10839 :         } else if (os_strncmp(buf, "SET ", 4) == 0) {
    1521       10024 :                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
    1522         165 :                         reply_len = -1;
    1523         815 :         } else if (os_strncmp(buf, "GET ", 4) == 0) {
    1524           2 :                 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
    1525             :                                                    reply_size);
    1526         813 :         } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
    1527         551 :                 if (hostapd_ctrl_iface_enable(hapd->iface))
    1528          15 :                         reply_len = -1;
    1529         262 :         } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
    1530           1 :                 if (hostapd_ctrl_iface_reload(hapd->iface))
    1531           0 :                         reply_len = -1;
    1532         261 :         } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
    1533           8 :                 if (hostapd_ctrl_iface_disable(hapd->iface))
    1534           0 :                         reply_len = -1;
    1535             : #ifdef CONFIG_TESTING_OPTIONS
    1536         253 :         } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
    1537           2 :                 if (hostapd_ctrl_iface_radar(hapd, buf + 6))
    1538           0 :                         reply_len = -1;
    1539         251 :         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
    1540         246 :                 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
    1541           0 :                         reply_len = -1;
    1542             : #endif /* CONFIG_TESTING_OPTIONS */
    1543           5 :         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
    1544           4 :                 if (hostapd_ctrl_iface_chan_switch(hapd, buf + 12))
    1545           4 :                         reply_len = -1;
    1546           1 :         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
    1547           0 :                 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
    1548             :                                                       reply_size);
    1549             : 
    1550             :         } else {
    1551           1 :                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
    1552           1 :                 reply_len = 16;
    1553             :         }
    1554             : 
    1555       13217 :         if (reply_len < 0) {
    1556         235 :                 os_memcpy(reply, "FAIL\n", 5);
    1557         235 :                 reply_len = 5;
    1558             :         }
    1559       13217 :         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
    1560       13217 :         os_free(reply);
    1561             : }
    1562             : 
    1563             : 
    1564        1146 : static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
    1565             : {
    1566             :         char *buf;
    1567             :         size_t len;
    1568             : 
    1569        1146 :         if (hapd->conf->ctrl_interface == NULL)
    1570           0 :                 return NULL;
    1571             : 
    1572        2292 :         len = os_strlen(hapd->conf->ctrl_interface) +
    1573        1146 :                 os_strlen(hapd->conf->iface) + 2;
    1574        1146 :         buf = os_malloc(len);
    1575        1146 :         if (buf == NULL)
    1576           0 :                 return NULL;
    1577             : 
    1578        1146 :         os_snprintf(buf, len, "%s/%s",
    1579        1146 :                     hapd->conf->ctrl_interface, hapd->conf->iface);
    1580        1146 :         buf[len - 1] = '\0';
    1581        1146 :         return buf;
    1582             : }
    1583             : 
    1584             : 
    1585       24740 : static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global,
    1586             :                                       const char *txt, size_t len)
    1587             : {
    1588       24740 :         struct hostapd_data *hapd = ctx;
    1589       24740 :         if (hapd == NULL)
    1590       24740 :                 return;
    1591       24740 :         hostapd_ctrl_iface_send(hapd, level, txt, len);
    1592             : }
    1593             : 
    1594             : 
    1595        1122 : int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
    1596             : {
    1597             :         struct sockaddr_un addr;
    1598        1122 :         int s = -1;
    1599        1122 :         char *fname = NULL;
    1600             : 
    1601        1122 :         if (hapd->ctrl_sock > -1) {
    1602         549 :                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
    1603         549 :                 return 0;
    1604             :         }
    1605             : 
    1606         573 :         if (hapd->conf->ctrl_interface == NULL)
    1607           0 :                 return 0;
    1608             : 
    1609         573 :         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
    1610         572 :                 if (errno == EEXIST) {
    1611         572 :                         wpa_printf(MSG_DEBUG, "Using existing control "
    1612             :                                    "interface directory.");
    1613             :                 } else {
    1614           0 :                         perror("mkdir[ctrl_interface]");
    1615           0 :                         goto fail;
    1616             :                 }
    1617             :         }
    1618             : 
    1619         575 :         if (hapd->conf->ctrl_interface_gid_set &&
    1620           2 :             chown(hapd->conf->ctrl_interface, -1,
    1621           2 :                   hapd->conf->ctrl_interface_gid) < 0) {
    1622           0 :                 perror("chown[ctrl_interface]");
    1623           0 :                 return -1;
    1624             :         }
    1625             : 
    1626        1144 :         if (!hapd->conf->ctrl_interface_gid_set &&
    1627         571 :             hapd->iface->interfaces->ctrl_iface_group &&
    1628           0 :             chown(hapd->conf->ctrl_interface, -1,
    1629           0 :                   hapd->iface->interfaces->ctrl_iface_group) < 0) {
    1630           0 :                 perror("chown[ctrl_interface]");
    1631           0 :                 return -1;
    1632             :         }
    1633             : 
    1634             : #ifdef ANDROID
    1635             :         /*
    1636             :          * Android is using umask 0077 which would leave the control interface
    1637             :          * directory without group access. This breaks things since Wi-Fi
    1638             :          * framework assumes that this directory can be accessed by other
    1639             :          * applications in the wifi group. Fix this by adding group access even
    1640             :          * if umask value would prevent this.
    1641             :          */
    1642             :         if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
    1643             :                 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
    1644             :                            strerror(errno));
    1645             :                 /* Try to continue anyway */
    1646             :         }
    1647             : #endif /* ANDROID */
    1648             : 
    1649        1146 :         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
    1650         573 :             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
    1651           0 :                 goto fail;
    1652             : 
    1653         573 :         s = socket(PF_UNIX, SOCK_DGRAM, 0);
    1654         573 :         if (s < 0) {
    1655           0 :                 perror("socket(PF_UNIX)");
    1656           0 :                 goto fail;
    1657             :         }
    1658             : 
    1659         573 :         os_memset(&addr, 0, sizeof(addr));
    1660             : #ifdef __FreeBSD__
    1661             :         addr.sun_len = sizeof(addr);
    1662             : #endif /* __FreeBSD__ */
    1663         573 :         addr.sun_family = AF_UNIX;
    1664         573 :         fname = hostapd_ctrl_iface_path(hapd);
    1665         573 :         if (fname == NULL)
    1666           0 :                 goto fail;
    1667         573 :         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
    1668         573 :         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    1669           0 :                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
    1670           0 :                            strerror(errno));
    1671           0 :                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    1672           0 :                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
    1673             :                                    " allow connections - assuming it was left"
    1674             :                                    "over from forced program termination");
    1675           0 :                         if (unlink(fname) < 0) {
    1676           0 :                                 perror("unlink[ctrl_iface]");
    1677           0 :                                 wpa_printf(MSG_ERROR, "Could not unlink "
    1678             :                                            "existing ctrl_iface socket '%s'",
    1679             :                                            fname);
    1680           0 :                                 goto fail;
    1681             :                         }
    1682           0 :                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
    1683             :                             0) {
    1684           0 :                                 perror("hostapd-ctrl-iface: bind(PF_UNIX)");
    1685           0 :                                 goto fail;
    1686             :                         }
    1687           0 :                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
    1688             :                                    "ctrl_iface socket '%s'", fname);
    1689             :                 } else {
    1690           0 :                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
    1691             :                                    "be in use - cannot override it");
    1692           0 :                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
    1693             :                                    "not used anymore", fname);
    1694           0 :                         os_free(fname);
    1695           0 :                         fname = NULL;
    1696           0 :                         goto fail;
    1697             :                 }
    1698             :         }
    1699             : 
    1700         575 :         if (hapd->conf->ctrl_interface_gid_set &&
    1701           2 :             chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
    1702           0 :                 perror("chown[ctrl_interface/ifname]");
    1703           0 :                 goto fail;
    1704             :         }
    1705             : 
    1706        1144 :         if (!hapd->conf->ctrl_interface_gid_set &&
    1707         571 :             hapd->iface->interfaces->ctrl_iface_group &&
    1708           0 :             chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
    1709           0 :                 perror("chown[ctrl_interface/ifname]");
    1710           0 :                 goto fail;
    1711             :         }
    1712             : 
    1713         573 :         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
    1714           0 :                 perror("chmod[ctrl_interface/ifname]");
    1715           0 :                 goto fail;
    1716             :         }
    1717         573 :         os_free(fname);
    1718             : 
    1719         573 :         hapd->ctrl_sock = s;
    1720         573 :         eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
    1721             :                                  NULL);
    1722         573 :         hapd->msg_ctx = hapd;
    1723         573 :         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
    1724             : 
    1725         573 :         return 0;
    1726             : 
    1727             : fail:
    1728           0 :         if (s >= 0)
    1729           0 :                 close(s);
    1730           0 :         if (fname) {
    1731           0 :                 unlink(fname);
    1732           0 :                 os_free(fname);
    1733             :         }
    1734           0 :         return -1;
    1735             : }
    1736             : 
    1737             : 
    1738         573 : void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
    1739             : {
    1740             :         struct wpa_ctrl_dst *dst, *prev;
    1741             : 
    1742         573 :         if (hapd->ctrl_sock > -1) {
    1743             :                 char *fname;
    1744         573 :                 eloop_unregister_read_sock(hapd->ctrl_sock);
    1745         573 :                 close(hapd->ctrl_sock);
    1746         573 :                 hapd->ctrl_sock = -1;
    1747         573 :                 fname = hostapd_ctrl_iface_path(hapd);
    1748         573 :                 if (fname)
    1749         573 :                         unlink(fname);
    1750         573 :                 os_free(fname);
    1751             : 
    1752        1146 :                 if (hapd->conf->ctrl_interface &&
    1753         573 :                     rmdir(hapd->conf->ctrl_interface) < 0) {
    1754         572 :                         if (errno == ENOTEMPTY) {
    1755         572 :                                 wpa_printf(MSG_DEBUG, "Control interface "
    1756             :                                            "directory not empty - leaving it "
    1757             :                                            "behind");
    1758             :                         } else {
    1759           0 :                                 wpa_printf(MSG_ERROR,
    1760             :                                            "rmdir[ctrl_interface=%s]: %s",
    1761           0 :                                            hapd->conf->ctrl_interface,
    1762           0 :                                            strerror(errno));
    1763             :                         }
    1764             :                 }
    1765             :         }
    1766             : 
    1767         573 :         dst = hapd->ctrl_dst;
    1768        1162 :         while (dst) {
    1769          16 :                 prev = dst;
    1770          16 :                 dst = dst->next;
    1771          16 :                 os_free(prev);
    1772             :         }
    1773         573 : }
    1774             : 
    1775             : 
    1776         566 : static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
    1777             :                                   char *buf)
    1778             : {
    1779         566 :         if (hostapd_add_iface(interfaces, buf) < 0) {
    1780           1 :                 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
    1781           1 :                 return -1;
    1782             :         }
    1783         565 :         return 0;
    1784             : }
    1785             : 
    1786             : 
    1787        3098 : static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
    1788             :                                      char *buf)
    1789             : {
    1790        3098 :         if (hostapd_remove_iface(interfaces, buf) < 0) {
    1791        2530 :                 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
    1792        2530 :                 return -1;
    1793             :         }
    1794         568 :         return 0;
    1795             : }
    1796             : 
    1797             : 
    1798         631 : static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
    1799             : {
    1800             : #ifdef CONFIG_WPS_TESTING
    1801         631 :         wps_version_number = 0x20;
    1802         631 :         wps_testing_dummy_cred = 0;
    1803         631 :         wps_corrupt_pkhash = 0;
    1804             : #endif /* CONFIG_WPS_TESTING */
    1805         631 : }
    1806             : 
    1807             : 
    1808        4927 : static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
    1809             :                                               void *sock_ctx)
    1810             : {
    1811        4927 :         void *interfaces = eloop_ctx;
    1812             :         char buf[256];
    1813             :         int res;
    1814             :         struct sockaddr_un from;
    1815        4927 :         socklen_t fromlen = sizeof(from);
    1816             :         char reply[24];
    1817             :         int reply_len;
    1818             : 
    1819        4927 :         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
    1820             :                        (struct sockaddr *) &from, &fromlen);
    1821        4927 :         if (res < 0) {
    1822           0 :                 perror("recvfrom(ctrl_iface)");
    1823        4927 :                 return;
    1824             :         }
    1825        4927 :         buf[res] = '\0';
    1826        4927 :         wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
    1827             : 
    1828        4927 :         os_memcpy(reply, "OK\n", 3);
    1829        4927 :         reply_len = 3;
    1830             : 
    1831        4927 :         if (os_strcmp(buf, "PING") == 0) {
    1832           1 :                 os_memcpy(reply, "PONG\n", 5);
    1833           1 :                 reply_len = 5;
    1834        4926 :         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
    1835         630 :                 if (wpa_debug_reopen_file() < 0)
    1836           0 :                         reply_len = -1;
    1837        4296 :         } else if (os_strcmp(buf, "FLUSH") == 0) {
    1838         631 :                 hostapd_ctrl_iface_flush(interfaces);
    1839        3665 :         } else if (os_strncmp(buf, "ADD ", 4) == 0) {
    1840         566 :                 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
    1841           1 :                         reply_len = -1;
    1842        3099 :         } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
    1843        3098 :                 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
    1844        2530 :                         reply_len = -1;
    1845             : #ifdef CONFIG_MODULE_TESTS
    1846           1 :         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
    1847             :                 int hapd_module_tests(void);
    1848           1 :                 if (hapd_module_tests() < 0)
    1849           0 :                         reply_len = -1;
    1850             : #endif /* CONFIG_MODULE_TESTS */
    1851             :         } else {
    1852           0 :                 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
    1853             :                            "ignored");
    1854           0 :                 reply_len = -1;
    1855             :         }
    1856             : 
    1857        4927 :         if (reply_len < 0) {
    1858        2531 :                 os_memcpy(reply, "FAIL\n", 5);
    1859        2531 :                 reply_len = 5;
    1860             :         }
    1861             : 
    1862        4927 :         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
    1863             : }
    1864             : 
    1865             : 
    1866           2 : static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
    1867             : {
    1868             :         char *buf;
    1869             :         size_t len;
    1870             : 
    1871           2 :         if (interface->global_iface_path == NULL)
    1872           0 :                 return NULL;
    1873             : 
    1874           4 :         len = os_strlen(interface->global_iface_path) +
    1875           2 :                 os_strlen(interface->global_iface_name) + 2;
    1876           2 :         buf = os_malloc(len);
    1877           2 :         if (buf == NULL)
    1878           0 :                 return NULL;
    1879             : 
    1880           2 :         os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
    1881             :                     interface->global_iface_name);
    1882           2 :         buf[len - 1] = '\0';
    1883           2 :         return buf;
    1884             : }
    1885             : 
    1886             : 
    1887           2 : int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
    1888             : {
    1889             :         struct sockaddr_un addr;
    1890           2 :         int s = -1;
    1891           2 :         char *fname = NULL;
    1892             : 
    1893           2 :         if (interface->global_iface_path == NULL) {
    1894           1 :                 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
    1895           1 :                 return 0;
    1896             :         }
    1897             : 
    1898           1 :         if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
    1899           1 :                 if (errno == EEXIST) {
    1900           1 :                         wpa_printf(MSG_DEBUG, "Using existing control "
    1901             :                                    "interface directory.");
    1902             :                 } else {
    1903           0 :                         perror("mkdir[ctrl_interface]");
    1904           0 :                         goto fail;
    1905             :                 }
    1906           0 :         } else if (interface->ctrl_iface_group &&
    1907           0 :                    chown(interface->global_iface_path, -1,
    1908             :                          interface->ctrl_iface_group) < 0) {
    1909           0 :                 perror("chown[ctrl_interface]");
    1910           0 :                 goto fail;
    1911             :         }
    1912             : 
    1913           2 :         if (os_strlen(interface->global_iface_path) + 1 +
    1914           1 :             os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
    1915           0 :                 goto fail;
    1916             : 
    1917           1 :         s = socket(PF_UNIX, SOCK_DGRAM, 0);
    1918           1 :         if (s < 0) {
    1919           0 :                 perror("socket(PF_UNIX)");
    1920           0 :                 goto fail;
    1921             :         }
    1922             : 
    1923           1 :         os_memset(&addr, 0, sizeof(addr));
    1924             : #ifdef __FreeBSD__
    1925             :         addr.sun_len = sizeof(addr);
    1926             : #endif /* __FreeBSD__ */
    1927           1 :         addr.sun_family = AF_UNIX;
    1928           1 :         fname = hostapd_global_ctrl_iface_path(interface);
    1929           1 :         if (fname == NULL)
    1930           0 :                 goto fail;
    1931           1 :         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
    1932           1 :         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    1933           0 :                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
    1934           0 :                            strerror(errno));
    1935           0 :                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    1936           0 :                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
    1937             :                                    " allow connections - assuming it was left"
    1938             :                                    "over from forced program termination");
    1939           0 :                         if (unlink(fname) < 0) {
    1940           0 :                                 perror("unlink[ctrl_iface]");
    1941           0 :                                 wpa_printf(MSG_ERROR, "Could not unlink "
    1942             :                                            "existing ctrl_iface socket '%s'",
    1943             :                                            fname);
    1944           0 :                                 goto fail;
    1945             :                         }
    1946           0 :                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
    1947             :                             0) {
    1948           0 :                                 perror("bind(PF_UNIX)");
    1949           0 :                                 goto fail;
    1950             :                         }
    1951           0 :                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
    1952             :                                    "ctrl_iface socket '%s'", fname);
    1953             :                 } else {
    1954           0 :                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
    1955             :                                    "be in use - cannot override it");
    1956           0 :                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
    1957             :                                    "not used anymore", fname);
    1958           0 :                         os_free(fname);
    1959           0 :                         fname = NULL;
    1960           0 :                         goto fail;
    1961             :                 }
    1962             :         }
    1963             : 
    1964           1 :         if (interface->ctrl_iface_group &&
    1965           0 :             chown(fname, -1, interface->ctrl_iface_group) < 0) {
    1966           0 :                 perror("chown[ctrl_interface]");
    1967           0 :                 goto fail;
    1968             :         }
    1969             : 
    1970           1 :         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
    1971           0 :                 perror("chmod[ctrl_interface/ifname]");
    1972           0 :                 goto fail;
    1973             :         }
    1974           1 :         os_free(fname);
    1975             : 
    1976           1 :         interface->global_ctrl_sock = s;
    1977           1 :         eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
    1978             :                                  interface, NULL);
    1979             : 
    1980           1 :         return 0;
    1981             : 
    1982             : fail:
    1983           0 :         if (s >= 0)
    1984           0 :                 close(s);
    1985           0 :         if (fname) {
    1986           0 :                 unlink(fname);
    1987           0 :                 os_free(fname);
    1988             :         }
    1989           0 :         return -1;
    1990             : }
    1991             : 
    1992             : 
    1993           2 : void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
    1994             : {
    1995           2 :         char *fname = NULL;
    1996             : 
    1997           2 :         if (interfaces->global_ctrl_sock > -1) {
    1998           1 :                 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
    1999           1 :                 close(interfaces->global_ctrl_sock);
    2000           1 :                 interfaces->global_ctrl_sock = -1;
    2001           1 :                 fname = hostapd_global_ctrl_iface_path(interfaces);
    2002           1 :                 if (fname) {
    2003           1 :                         unlink(fname);
    2004           1 :                         os_free(fname);
    2005             :                 }
    2006             : 
    2007           2 :                 if (interfaces->global_iface_path &&
    2008           1 :                     rmdir(interfaces->global_iface_path) < 0) {
    2009           1 :                         if (errno == ENOTEMPTY) {
    2010           0 :                                 wpa_printf(MSG_DEBUG, "Control interface "
    2011             :                                            "directory not empty - leaving it "
    2012             :                                            "behind");
    2013             :                         } else {
    2014           1 :                                 wpa_printf(MSG_ERROR,
    2015             :                                            "rmdir[ctrl_interface=%s]: %s",
    2016             :                                            interfaces->global_iface_path,
    2017           1 :                                            strerror(errno));
    2018             :                         }
    2019             :                 }
    2020           1 :                 os_free(interfaces->global_iface_path);
    2021           1 :                 interfaces->global_iface_path = NULL;
    2022             :         }
    2023           2 : }
    2024             : 
    2025             : 
    2026       24740 : static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
    2027             :                                     const char *buf, size_t len)
    2028             : {
    2029             :         struct wpa_ctrl_dst *dst, *next;
    2030             :         struct msghdr msg;
    2031             :         int idx;
    2032             :         struct iovec io[2];
    2033             :         char levelstr[10];
    2034             : 
    2035       24740 :         dst = hapd->ctrl_dst;
    2036       24740 :         if (hapd->ctrl_sock < 0 || dst == NULL)
    2037       39485 :                 return;
    2038             : 
    2039        9995 :         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
    2040        9995 :         io[0].iov_base = levelstr;
    2041        9995 :         io[0].iov_len = os_strlen(levelstr);
    2042        9995 :         io[1].iov_base = (char *) buf;
    2043        9995 :         io[1].iov_len = len;
    2044        9995 :         os_memset(&msg, 0, sizeof(msg));
    2045        9995 :         msg.msg_iov = io;
    2046        9995 :         msg.msg_iovlen = 2;
    2047             : 
    2048        9995 :         idx = 0;
    2049       30300 :         while (dst) {
    2050       10310 :                 next = dst->next;
    2051       10310 :                 if (level >= dst->debug_level) {
    2052        4288 :                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
    2053        4288 :                                     (u8 *) dst->addr.sun_path, dst->addrlen -
    2054             :                                     offsetof(struct sockaddr_un, sun_path));
    2055        2144 :                         msg.msg_name = &dst->addr;
    2056        2144 :                         msg.msg_namelen = dst->addrlen;
    2057        2144 :                         if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
    2058           0 :                                 int _errno = errno;
    2059           0 :                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
    2060             :                                            "%d - %s",
    2061           0 :                                            idx, errno, strerror(errno));
    2062           0 :                                 dst->errors++;
    2063           0 :                                 if (dst->errors > 10 || _errno == ENOENT) {
    2064           0 :                                         hostapd_ctrl_iface_detach(
    2065             :                                                 hapd, &dst->addr,
    2066             :                                                 dst->addrlen);
    2067             :                                 }
    2068             :                         } else
    2069        2144 :                                 dst->errors = 0;
    2070             :                 }
    2071       10310 :                 idx++;
    2072       10310 :                 dst = next;
    2073             :         }
    2074             : }
    2075             : 
    2076             : #endif /* CONFIG_NATIVE_WINDOWS */

Generated by: LCOV version 1.10