LCOV - code coverage report
Current view: top level - tmp/logs/alt-hostapd/hostapd - ctrl_iface.c (source / functions) Hit Total Coverage
Test: hostapd hwsim test run 1412854115 Lines: 919 1165 78.9 %
Date: 2014-10-09 Functions: 45 47 95.7 %

          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         849 : 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         849 :         dst = os_zalloc(sizeof(*dst));
      62         849 :         if (dst == NULL)
      63           0 :                 return -1;
      64         849 :         os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
      65         849 :         dst->addrlen = fromlen;
      66         849 :         dst->debug_level = MSG_INFO;
      67         849 :         dst->next = hapd->ctrl_dst;
      68         849 :         hapd->ctrl_dst = dst;
      69        1698 :         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
      70         849 :                     (u8 *) from->sun_path,
      71             :                     fromlen - offsetof(struct sockaddr_un, sun_path));
      72         849 :         return 0;
      73             : }
      74             : 
      75             : 
      76         834 : static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
      77             :                                      struct sockaddr_un *from,
      78             :                                      socklen_t fromlen)
      79             : {
      80         834 :         struct wpa_ctrl_dst *dst, *prev = NULL;
      81             : 
      82         834 :         dst = hapd->ctrl_dst;
      83        1670 :         while (dst) {
      84        1670 :                 if (fromlen == dst->addrlen &&
      85         835 :                     os_memcmp(from->sun_path, dst->addr.sun_path,
      86             :                               fromlen - offsetof(struct sockaddr_un, sun_path))
      87             :                     == 0) {
      88        1666 :                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
      89         833 :                                     (u8 *) from->sun_path,
      90             :                                     fromlen -
      91             :                                     offsetof(struct sockaddr_un, sun_path));
      92         833 :                         if (prev == NULL)
      93         831 :                                 hapd->ctrl_dst = dst->next;
      94             :                         else
      95           2 :                                 prev->next = dst->next;
      96         833 :                         os_free(dst);
      97         833 :                         return 0;
      98             :                 }
      99           2 :                 prev = dst;
     100           2 :                 dst = dst->next;
     101             :         }
     102           1 :         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->wpa_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       11162 : static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
    1030             : {
    1031             :         char *value;
    1032       11162 :         int ret = 0;
    1033             : 
    1034       11162 :         value = os_strchr(cmd, ' ');
    1035       11162 :         if (value == NULL)
    1036           0 :                 return -1;
    1037       11162 :         *value++ = '\0';
    1038             : 
    1039       11162 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
    1040             :         if (0) {
    1041             : #ifdef CONFIG_WPS_TESTING
    1042       11162 :         } 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       11158 :         } 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       11158 :         } 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       11157 :         } 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       11154 :         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
    1076          25 :                 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       11129 :                 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
    1083       11129 :                 if (ret)
    1084         165 :                         return ret;
    1085             : 
    1086       10964 :                 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       10965 :                 } 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       10997 :         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         631 : static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
    1135             : {
    1136         631 :         if (hostapd_enable_iface(iface) < 0) {
    1137          15 :                 wpa_printf(MSG_ERROR, "Enabling of interface failed");
    1138          15 :                 return -1;
    1139             :         }
    1140         616 :         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          12 : static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
    1155             : {
    1156          12 :         if (hostapd_disable_iface(iface) < 0) {
    1157           6 :                 wpa_printf(MSG_ERROR, "Disabling of interface failed");
    1158           6 :                 return -1;
    1159             :         }
    1160           6 :         return 0;
    1161             : }
    1162             : 
    1163             : 
    1164             : #ifdef CONFIG_TESTING_OPTIONS
    1165             : 
    1166           3 : 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           3 :         wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
    1173             : 
    1174           3 :         os_memset(&data, 0, sizeof(data));
    1175             : 
    1176           3 :         param = os_strchr(cmd, ' ');
    1177           3 :         if (param == NULL)
    1178           0 :                 return -1;
    1179           3 :         *param++ = '\0';
    1180             : 
    1181           3 :         if (os_strcmp(cmd, "DETECTED") == 0)
    1182           3 :                 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           3 :         pos = os_strstr(param, "freq=");
    1196           3 :         if (pos)
    1197           3 :                 data.dfs_event.freq = atoi(pos + 5);
    1198             : 
    1199           3 :         pos = os_strstr(param, "ht_enabled=1");
    1200           3 :         if (pos)
    1201           3 :                 data.dfs_event.ht_enabled = 1;
    1202             : 
    1203           3 :         pos = os_strstr(param, "chan_offset=");
    1204           3 :         if (pos)
    1205           0 :                 data.dfs_event.chan_offset = atoi(pos + 12);
    1206             : 
    1207           3 :         pos = os_strstr(param, "chan_width=");
    1208           3 :         if (pos)
    1209           3 :                 data.dfs_event.chan_width = atoi(pos + 11);
    1210             : 
    1211           3 :         pos = os_strstr(param, "cf1=");
    1212           3 :         if (pos)
    1213           0 :                 data.dfs_event.cf1 = atoi(pos + 4);
    1214             : 
    1215           3 :         pos = os_strstr(param, "cf2=");
    1216           3 :         if (pos)
    1217           0 :                 data.dfs_event.cf2 = atoi(pos + 4);
    1218             : 
    1219           3 :         wpa_supplicant_event(hapd, event, &data);
    1220             : 
    1221           3 :         return 0;
    1222             : }
    1223             : 
    1224             : 
    1225         248 : 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         248 :         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
    1232             : 
    1233         248 :         len = os_strlen(cmd);
    1234         248 :         if (len & 1)
    1235           0 :                 return -1;
    1236         248 :         len /= 2;
    1237             : 
    1238         248 :         buf = os_malloc(len);
    1239         248 :         if (buf == NULL)
    1240           0 :                 return -1;
    1241             : 
    1242         248 :         if (hexstr2bin(cmd, buf, len) < 0) {
    1243           0 :                 os_free(buf);
    1244           0 :                 return -1;
    1245             :         }
    1246             : 
    1247         248 :         res = hostapd_drv_send_mlme(hapd, buf, len, 0);
    1248         248 :         os_free(buf);
    1249         248 :         return res;
    1250             : }
    1251             : 
    1252             : #endif /* CONFIG_TESTING_OPTIONS */
    1253             : 
    1254             : 
    1255           4 : static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
    1256             :                                           char *pos)
    1257             : {
    1258             : #ifdef NEED_AP_MLME
    1259             :         struct csa_settings settings;
    1260             :         int ret;
    1261             :         unsigned int i;
    1262             : 
    1263           4 :         ret = hostapd_parse_csa_settings(pos, &settings);
    1264           4 :         if (ret)
    1265           3 :                 return ret;
    1266             : 
    1267           1 :         for (i = 0; i < iface->num_bss; i++) {
    1268           1 :                 ret = hostapd_switch_channel(iface->bss[i], &settings);
    1269           1 :                 if (ret) {
    1270             :                         /* FIX: What do we do if CSA fails in the middle of
    1271             :                          * submitting multi-BSS CSA requests? */
    1272           1 :                         return ret;
    1273             :                 }
    1274             :         }
    1275             : 
    1276           0 :         return 0;
    1277             : #else /* NEED_AP_MLME */
    1278             :         return -1;
    1279             : #endif /* NEED_AP_MLME */
    1280             : }
    1281             : 
    1282             : 
    1283           0 : static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
    1284             :                                   int reply_size, const char *param)
    1285             : {
    1286             : #ifdef RADIUS_SERVER
    1287           0 :         if (os_strcmp(param, "radius_server") == 0) {
    1288           0 :                 return radius_server_get_mib(hapd->radius_srv, reply,
    1289             :                                              reply_size);
    1290             :         }
    1291             : #endif /* RADIUS_SERVER */
    1292           0 :         return -1;
    1293             : }
    1294             : 
    1295             : 
    1296           0 : static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
    1297             :                                      char *buf, size_t buflen)
    1298             : {
    1299             :         int ret;
    1300             :         char *pos;
    1301           0 :         u8 *data = NULL;
    1302             :         unsigned int vendor_id, subcmd;
    1303             :         struct wpabuf *reply;
    1304           0 :         size_t data_len = 0;
    1305             : 
    1306             :         /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
    1307           0 :         vendor_id = strtoul(cmd, &pos, 16);
    1308           0 :         if (!isblank(*pos))
    1309           0 :                 return -EINVAL;
    1310             : 
    1311           0 :         subcmd = strtoul(pos, &pos, 10);
    1312             : 
    1313           0 :         if (*pos != '\0') {
    1314           0 :                 if (!isblank(*pos++))
    1315           0 :                         return -EINVAL;
    1316           0 :                 data_len = os_strlen(pos);
    1317             :         }
    1318             : 
    1319           0 :         if (data_len) {
    1320           0 :                 data_len /= 2;
    1321           0 :                 data = os_malloc(data_len);
    1322           0 :                 if (!data)
    1323           0 :                         return -ENOBUFS;
    1324             : 
    1325           0 :                 if (hexstr2bin(pos, data, data_len)) {
    1326           0 :                         wpa_printf(MSG_DEBUG,
    1327             :                                    "Vendor command: wrong parameter format");
    1328           0 :                         os_free(data);
    1329           0 :                         return -EINVAL;
    1330             :                 }
    1331             :         }
    1332             : 
    1333           0 :         reply = wpabuf_alloc((buflen - 1) / 2);
    1334           0 :         if (!reply) {
    1335           0 :                 os_free(data);
    1336           0 :                 return -ENOBUFS;
    1337             :         }
    1338             : 
    1339           0 :         ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
    1340             :                                      reply);
    1341             : 
    1342           0 :         if (ret == 0)
    1343           0 :                 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
    1344             :                                        wpabuf_len(reply));
    1345             : 
    1346           0 :         wpabuf_free(reply);
    1347           0 :         os_free(data);
    1348             : 
    1349           0 :         return ret;
    1350             : }
    1351             : 
    1352             : 
    1353       14738 : static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
    1354             :                                        void *sock_ctx)
    1355             : {
    1356       14738 :         struct hostapd_data *hapd = eloop_ctx;
    1357             :         char buf[4096];
    1358             :         int res;
    1359             :         struct sockaddr_un from;
    1360       14738 :         socklen_t fromlen = sizeof(from);
    1361             :         char *reply;
    1362       14738 :         const int reply_size = 4096;
    1363             :         int reply_len;
    1364       14738 :         int level = MSG_DEBUG;
    1365             : 
    1366       14738 :         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
    1367             :                        (struct sockaddr *) &from, &fromlen);
    1368       14738 :         if (res < 0) {
    1369           0 :                 perror("recvfrom(ctrl_iface)");
    1370           0 :                 return;
    1371             :         }
    1372       14738 :         buf[res] = '\0';
    1373       14738 :         if (os_strcmp(buf, "PING") == 0)
    1374         643 :                 level = MSG_EXCESSIVE;
    1375       14738 :         wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
    1376             : 
    1377       14738 :         reply = os_malloc(reply_size);
    1378       14738 :         if (reply == NULL) {
    1379           0 :                 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
    1380             :                        fromlen);
    1381           0 :                 return;
    1382             :         }
    1383             : 
    1384       14738 :         os_memcpy(reply, "OK\n", 3);
    1385       14738 :         reply_len = 3;
    1386             : 
    1387       14738 :         if (os_strcmp(buf, "PING") == 0) {
    1388         643 :                 os_memcpy(reply, "PONG\n", 5);
    1389         643 :                 reply_len = 5;
    1390       14095 :         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
    1391           0 :                 if (wpa_debug_reopen_file() < 0)
    1392           0 :                         reply_len = -1;
    1393       14095 :         } else if (os_strcmp(buf, "STATUS") == 0) {
    1394         129 :                 reply_len = hostapd_ctrl_iface_status(hapd, reply,
    1395             :                                                       reply_size);
    1396       13966 :         } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
    1397           3 :                 reply_len = hostapd_drv_status(hapd, reply, reply_size);
    1398       13963 :         } else if (os_strcmp(buf, "MIB") == 0) {
    1399           7 :                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
    1400           7 :                 if (reply_len >= 0) {
    1401           7 :                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
    1402           7 :                                           reply_size - reply_len);
    1403           7 :                         if (res < 0)
    1404           0 :                                 reply_len = -1;
    1405             :                         else
    1406           7 :                                 reply_len += res;
    1407             :                 }
    1408           7 :                 if (reply_len >= 0) {
    1409           7 :                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
    1410           7 :                                                  reply_size - reply_len);
    1411           7 :                         if (res < 0)
    1412           0 :                                 reply_len = -1;
    1413             :                         else
    1414           7 :                                 reply_len += res;
    1415             :                 }
    1416             : #ifndef CONFIG_NO_RADIUS
    1417           7 :                 if (reply_len >= 0) {
    1418           7 :                         res = radius_client_get_mib(hapd->radius,
    1419             :                                                     reply + reply_len,
    1420           7 :                                                     reply_size - reply_len);
    1421           7 :                         if (res < 0)
    1422           0 :                                 reply_len = -1;
    1423             :                         else
    1424           7 :                                 reply_len += res;
    1425             :                 }
    1426             : #endif /* CONFIG_NO_RADIUS */
    1427       13956 :         } else if (os_strncmp(buf, "MIB ", 4) == 0) {
    1428           0 :                 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
    1429             :                                                    buf + 4);
    1430       13956 :         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
    1431           1 :                 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
    1432             :                                                          reply_size);
    1433       13955 :         } else if (os_strncmp(buf, "STA ", 4) == 0) {
    1434          36 :                 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
    1435             :                                                    reply_size);
    1436       13919 :         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
    1437           4 :                 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
    1438             :                                                         reply_size);
    1439       13915 :         } else if (os_strcmp(buf, "ATTACH") == 0) {
    1440         849 :                 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
    1441           0 :                         reply_len = -1;
    1442       13066 :         } else if (os_strcmp(buf, "DETACH") == 0) {
    1443         833 :                 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
    1444           1 :                         reply_len = -1;
    1445       12233 :         } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
    1446           1 :                 if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
    1447             :                                                     buf + 6))
    1448           1 :                         reply_len = -1;
    1449       12232 :         } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
    1450           2 :                 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
    1451           1 :                         reply_len = -1;
    1452       12230 :         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
    1453           7 :                 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
    1454           1 :                         reply_len = -1;
    1455       12223 :         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
    1456           3 :                 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
    1457           1 :                         reply_len = -1;
    1458             : #ifdef CONFIG_IEEE80211W
    1459             : #ifdef NEED_AP_MLME
    1460       12220 :         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
    1461           2 :                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
    1462           0 :                         reply_len = -1;
    1463             : #endif /* NEED_AP_MLME */
    1464             : #endif /* CONFIG_IEEE80211W */
    1465             : #ifdef CONFIG_WPS
    1466       12218 :         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
    1467          14 :                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
    1468           1 :                         reply_len = -1;
    1469       12204 :         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
    1470           9 :                 reply_len = hostapd_ctrl_iface_wps_check_pin(
    1471             :                         hapd, buf + 14, reply, reply_size);
    1472       12195 :         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
    1473          28 :                 if (hostapd_wps_button_pushed(hapd, NULL))
    1474           4 :                         reply_len = -1;
    1475       12167 :         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
    1476           4 :                 if (hostapd_wps_cancel(hapd))
    1477           1 :                         reply_len = -1;
    1478       12163 :         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
    1479          11 :                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
    1480             :                                                           reply, reply_size);
    1481       12152 :         } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
    1482           2 :                 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
    1483           0 :                         reply_len = -1;
    1484       12150 :         } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
    1485           5 :                 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
    1486             :                                                               reply_size);
    1487             : #ifdef CONFIG_WPS_NFC
    1488       12145 :         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
    1489           2 :                 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
    1490           0 :                         reply_len = -1;
    1491       12143 :         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
    1492           2 :                 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
    1493             :                         hapd, buf + 21, reply, reply_size);
    1494       12141 :         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
    1495           6 :                 reply_len = hostapd_ctrl_iface_wps_nfc_token(
    1496             :                         hapd, buf + 14, reply, reply_size);
    1497       12135 :         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
    1498           8 :                 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
    1499             :                         hapd, buf + 21, reply, reply_size);
    1500       12127 :         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
    1501          17 :                 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
    1502          10 :                         reply_len = -1;
    1503             : #endif /* CONFIG_WPS_NFC */
    1504             : #endif /* CONFIG_WPS */
    1505             : #ifdef CONFIG_INTERWORKING
    1506       12110 :         } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
    1507           7 :                 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
    1508           5 :                         reply_len = -1;
    1509       12103 :         } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
    1510           4 :                 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
    1511           3 :                         reply_len = -1;
    1512             : #endif /* CONFIG_INTERWORKING */
    1513             : #ifdef CONFIG_HS20
    1514       12099 :         } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
    1515           7 :                 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
    1516           5 :                         reply_len = -1;
    1517       12092 :         } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
    1518           5 :                 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
    1519           3 :                         reply_len = -1;
    1520             : #endif /* CONFIG_HS20 */
    1521             : #ifdef CONFIG_WNM
    1522       12087 :         } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
    1523           5 :                 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
    1524           3 :                         reply_len = -1;
    1525       12082 :         } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
    1526           8 :                 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
    1527           5 :                         reply_len = -1;
    1528             : #endif /* CONFIG_WNM */
    1529       12074 :         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
    1530          10 :                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
    1531             :                                                           reply_size);
    1532       12064 :         } else if (os_strncmp(buf, "SET ", 4) == 0) {
    1533       11162 :                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
    1534         165 :                         reply_len = -1;
    1535         902 :         } else if (os_strncmp(buf, "GET ", 4) == 0) {
    1536           2 :                 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
    1537             :                                                    reply_size);
    1538         900 :         } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
    1539         631 :                 if (hostapd_ctrl_iface_enable(hapd->iface))
    1540          15 :                         reply_len = -1;
    1541         269 :         } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
    1542           1 :                 if (hostapd_ctrl_iface_reload(hapd->iface))
    1543           0 :                         reply_len = -1;
    1544         268 :         } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
    1545          12 :                 if (hostapd_ctrl_iface_disable(hapd->iface))
    1546           6 :                         reply_len = -1;
    1547             : #ifdef CONFIG_TESTING_OPTIONS
    1548         256 :         } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
    1549           3 :                 if (hostapd_ctrl_iface_radar(hapd, buf + 6))
    1550           0 :                         reply_len = -1;
    1551         253 :         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
    1552         248 :                 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
    1553           0 :                         reply_len = -1;
    1554             : #endif /* CONFIG_TESTING_OPTIONS */
    1555           5 :         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
    1556           4 :                 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
    1557           4 :                         reply_len = -1;
    1558           1 :         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
    1559           0 :                 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
    1560             :                                                       reply_size);
    1561             : 
    1562             :         } else {
    1563           1 :                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
    1564           1 :                 reply_len = 16;
    1565             :         }
    1566             : 
    1567       14738 :         if (reply_len < 0) {
    1568         247 :                 os_memcpy(reply, "FAIL\n", 5);
    1569         247 :                 reply_len = 5;
    1570             :         }
    1571       14738 :         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
    1572       14738 :         os_free(reply);
    1573             : }
    1574             : 
    1575             : 
    1576        1304 : static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
    1577             : {
    1578             :         char *buf;
    1579             :         size_t len;
    1580             : 
    1581        1304 :         if (hapd->conf->ctrl_interface == NULL)
    1582           0 :                 return NULL;
    1583             : 
    1584        2608 :         len = os_strlen(hapd->conf->ctrl_interface) +
    1585        1304 :                 os_strlen(hapd->conf->iface) + 2;
    1586        1304 :         buf = os_malloc(len);
    1587        1304 :         if (buf == NULL)
    1588           0 :                 return NULL;
    1589             : 
    1590        1304 :         os_snprintf(buf, len, "%s/%s",
    1591        1304 :                     hapd->conf->ctrl_interface, hapd->conf->iface);
    1592        1304 :         buf[len - 1] = '\0';
    1593        1304 :         return buf;
    1594             : }
    1595             : 
    1596             : 
    1597       31378 : static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global,
    1598             :                                       const char *txt, size_t len)
    1599             : {
    1600       31378 :         struct hostapd_data *hapd = ctx;
    1601       31378 :         if (hapd == NULL)
    1602       31378 :                 return;
    1603       31378 :         hostapd_ctrl_iface_send(hapd, level, txt, len);
    1604             : }
    1605             : 
    1606             : 
    1607        1282 : int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
    1608             : {
    1609             :         struct sockaddr_un addr;
    1610        1282 :         int s = -1;
    1611        1282 :         char *fname = NULL;
    1612             : 
    1613        1282 :         if (hapd->ctrl_sock > -1) {
    1614         630 :                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
    1615         630 :                 return 0;
    1616             :         }
    1617             : 
    1618         652 :         if (hapd->conf->ctrl_interface == NULL)
    1619           0 :                 return 0;
    1620             : 
    1621         652 :         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
    1622         652 :                 if (errno == EEXIST) {
    1623         652 :                         wpa_printf(MSG_DEBUG, "Using existing control "
    1624             :                                    "interface directory.");
    1625             :                 } else {
    1626           0 :                         perror("mkdir[ctrl_interface]");
    1627           0 :                         goto fail;
    1628             :                 }
    1629             :         }
    1630             : 
    1631         652 :         if (hapd->conf->ctrl_interface_gid_set &&
    1632           0 :             chown(hapd->conf->ctrl_interface, -1,
    1633           0 :                   hapd->conf->ctrl_interface_gid) < 0) {
    1634           0 :                 perror("chown[ctrl_interface]");
    1635           0 :                 return -1;
    1636             :         }
    1637             : 
    1638        1304 :         if (!hapd->conf->ctrl_interface_gid_set &&
    1639         652 :             hapd->iface->interfaces->ctrl_iface_group &&
    1640           0 :             chown(hapd->conf->ctrl_interface, -1,
    1641           0 :                   hapd->iface->interfaces->ctrl_iface_group) < 0) {
    1642           0 :                 perror("chown[ctrl_interface]");
    1643           0 :                 return -1;
    1644             :         }
    1645             : 
    1646             : #ifdef ANDROID
    1647             :         /*
    1648             :          * Android is using umask 0077 which would leave the control interface
    1649             :          * directory without group access. This breaks things since Wi-Fi
    1650             :          * framework assumes that this directory can be accessed by other
    1651             :          * applications in the wifi group. Fix this by adding group access even
    1652             :          * if umask value would prevent this.
    1653             :          */
    1654             :         if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
    1655             :                 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
    1656             :                            strerror(errno));
    1657             :                 /* Try to continue anyway */
    1658             :         }
    1659             : #endif /* ANDROID */
    1660             : 
    1661        1304 :         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
    1662         652 :             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
    1663           0 :                 goto fail;
    1664             : 
    1665         652 :         s = socket(PF_UNIX, SOCK_DGRAM, 0);
    1666         652 :         if (s < 0) {
    1667           0 :                 perror("socket(PF_UNIX)");
    1668           0 :                 goto fail;
    1669             :         }
    1670             : 
    1671         652 :         os_memset(&addr, 0, sizeof(addr));
    1672             : #ifdef __FreeBSD__
    1673             :         addr.sun_len = sizeof(addr);
    1674             : #endif /* __FreeBSD__ */
    1675         652 :         addr.sun_family = AF_UNIX;
    1676         652 :         fname = hostapd_ctrl_iface_path(hapd);
    1677         652 :         if (fname == NULL)
    1678           0 :                 goto fail;
    1679         652 :         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
    1680         652 :         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    1681           0 :                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
    1682           0 :                            strerror(errno));
    1683           0 :                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    1684           0 :                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
    1685             :                                    " allow connections - assuming it was left"
    1686             :                                    "over from forced program termination");
    1687           0 :                         if (unlink(fname) < 0) {
    1688           0 :                                 perror("unlink[ctrl_iface]");
    1689           0 :                                 wpa_printf(MSG_ERROR, "Could not unlink "
    1690             :                                            "existing ctrl_iface socket '%s'",
    1691             :                                            fname);
    1692           0 :                                 goto fail;
    1693             :                         }
    1694           0 :                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
    1695             :                             0) {
    1696           0 :                                 perror("hostapd-ctrl-iface: bind(PF_UNIX)");
    1697           0 :                                 goto fail;
    1698             :                         }
    1699           0 :                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
    1700             :                                    "ctrl_iface socket '%s'", fname);
    1701             :                 } else {
    1702           0 :                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
    1703             :                                    "be in use - cannot override it");
    1704           0 :                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
    1705             :                                    "not used anymore", fname);
    1706           0 :                         os_free(fname);
    1707           0 :                         fname = NULL;
    1708           0 :                         goto fail;
    1709             :                 }
    1710             :         }
    1711             : 
    1712         652 :         if (hapd->conf->ctrl_interface_gid_set &&
    1713           0 :             chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
    1714           0 :                 perror("chown[ctrl_interface/ifname]");
    1715           0 :                 goto fail;
    1716             :         }
    1717             : 
    1718        1304 :         if (!hapd->conf->ctrl_interface_gid_set &&
    1719         652 :             hapd->iface->interfaces->ctrl_iface_group &&
    1720           0 :             chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
    1721           0 :                 perror("chown[ctrl_interface/ifname]");
    1722           0 :                 goto fail;
    1723             :         }
    1724             : 
    1725         652 :         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
    1726           0 :                 perror("chmod[ctrl_interface/ifname]");
    1727           0 :                 goto fail;
    1728             :         }
    1729         652 :         os_free(fname);
    1730             : 
    1731         652 :         hapd->ctrl_sock = s;
    1732         652 :         eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
    1733             :                                  NULL);
    1734         652 :         hapd->msg_ctx = hapd;
    1735         652 :         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
    1736             : 
    1737         652 :         return 0;
    1738             : 
    1739             : fail:
    1740           0 :         if (s >= 0)
    1741           0 :                 close(s);
    1742           0 :         if (fname) {
    1743           0 :                 unlink(fname);
    1744           0 :                 os_free(fname);
    1745             :         }
    1746           0 :         return -1;
    1747             : }
    1748             : 
    1749             : 
    1750         652 : void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
    1751             : {
    1752             :         struct wpa_ctrl_dst *dst, *prev;
    1753             : 
    1754         652 :         if (hapd->ctrl_sock > -1) {
    1755             :                 char *fname;
    1756         652 :                 eloop_unregister_read_sock(hapd->ctrl_sock);
    1757         652 :                 close(hapd->ctrl_sock);
    1758         652 :                 hapd->ctrl_sock = -1;
    1759         652 :                 fname = hostapd_ctrl_iface_path(hapd);
    1760         652 :                 if (fname)
    1761         652 :                         unlink(fname);
    1762         652 :                 os_free(fname);
    1763             : 
    1764        1304 :                 if (hapd->conf->ctrl_interface &&
    1765         652 :                     rmdir(hapd->conf->ctrl_interface) < 0) {
    1766         652 :                         if (errno == ENOTEMPTY) {
    1767         652 :                                 wpa_printf(MSG_DEBUG, "Control interface "
    1768             :                                            "directory not empty - leaving it "
    1769             :                                            "behind");
    1770             :                         } else {
    1771           0 :                                 wpa_printf(MSG_ERROR,
    1772             :                                            "rmdir[ctrl_interface=%s]: %s",
    1773           0 :                                            hapd->conf->ctrl_interface,
    1774           0 :                                            strerror(errno));
    1775             :                         }
    1776             :                 }
    1777             :         }
    1778             : 
    1779         652 :         dst = hapd->ctrl_dst;
    1780        1320 :         while (dst) {
    1781          16 :                 prev = dst;
    1782          16 :                 dst = dst->next;
    1783          16 :                 os_free(prev);
    1784             :         }
    1785         652 : }
    1786             : 
    1787             : 
    1788         647 : static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
    1789             :                                   char *buf)
    1790             : {
    1791         647 :         if (hostapd_add_iface(interfaces, buf) < 0) {
    1792           1 :                 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
    1793           1 :                 return -1;
    1794             :         }
    1795         646 :         return 0;
    1796             : }
    1797             : 
    1798             : 
    1799        3561 : static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
    1800             :                                      char *buf)
    1801             : {
    1802        3561 :         if (hostapd_remove_iface(interfaces, buf) < 0) {
    1803        2912 :                 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
    1804        2912 :                 return -1;
    1805             :         }
    1806         649 :         return 0;
    1807             : }
    1808             : 
    1809             : 
    1810         727 : static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
    1811             : {
    1812             : #ifdef CONFIG_WPS_TESTING
    1813         727 :         wps_version_number = 0x20;
    1814         727 :         wps_testing_dummy_cred = 0;
    1815         727 :         wps_corrupt_pkhash = 0;
    1816             : #endif /* CONFIG_WPS_TESTING */
    1817         727 : }
    1818             : 
    1819             : 
    1820        5663 : static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
    1821             :                                               void *sock_ctx)
    1822             : {
    1823        5663 :         void *interfaces = eloop_ctx;
    1824             :         char buf[256];
    1825             :         int res;
    1826             :         struct sockaddr_un from;
    1827        5663 :         socklen_t fromlen = sizeof(from);
    1828             :         char reply[24];
    1829             :         int reply_len;
    1830             : 
    1831        5663 :         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
    1832             :                        (struct sockaddr *) &from, &fromlen);
    1833        5663 :         if (res < 0) {
    1834           0 :                 perror("recvfrom(ctrl_iface)");
    1835        5663 :                 return;
    1836             :         }
    1837        5663 :         buf[res] = '\0';
    1838        5663 :         wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
    1839             : 
    1840        5663 :         os_memcpy(reply, "OK\n", 3);
    1841        5663 :         reply_len = 3;
    1842             : 
    1843        5663 :         if (os_strcmp(buf, "PING") == 0) {
    1844           1 :                 os_memcpy(reply, "PONG\n", 5);
    1845           1 :                 reply_len = 5;
    1846        5662 :         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
    1847         726 :                 if (wpa_debug_reopen_file() < 0)
    1848           0 :                         reply_len = -1;
    1849        4936 :         } else if (os_strcmp(buf, "FLUSH") == 0) {
    1850         727 :                 hostapd_ctrl_iface_flush(interfaces);
    1851        4209 :         } else if (os_strncmp(buf, "ADD ", 4) == 0) {
    1852         647 :                 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
    1853           1 :                         reply_len = -1;
    1854        3562 :         } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
    1855        3561 :                 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
    1856        2912 :                         reply_len = -1;
    1857             : #ifdef CONFIG_MODULE_TESTS
    1858           1 :         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
    1859             :                 int hapd_module_tests(void);
    1860           1 :                 if (hapd_module_tests() < 0)
    1861           0 :                         reply_len = -1;
    1862             : #endif /* CONFIG_MODULE_TESTS */
    1863             :         } else {
    1864           0 :                 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
    1865             :                            "ignored");
    1866           0 :                 reply_len = -1;
    1867             :         }
    1868             : 
    1869        5663 :         if (reply_len < 0) {
    1870        2913 :                 os_memcpy(reply, "FAIL\n", 5);
    1871        2913 :                 reply_len = 5;
    1872             :         }
    1873             : 
    1874        5663 :         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
    1875             : }
    1876             : 
    1877             : 
    1878           2 : static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
    1879             : {
    1880             :         char *buf;
    1881             :         size_t len;
    1882             : 
    1883           2 :         if (interface->global_iface_path == NULL)
    1884           0 :                 return NULL;
    1885             : 
    1886           4 :         len = os_strlen(interface->global_iface_path) +
    1887           2 :                 os_strlen(interface->global_iface_name) + 2;
    1888           2 :         buf = os_malloc(len);
    1889           2 :         if (buf == NULL)
    1890           0 :                 return NULL;
    1891             : 
    1892           2 :         os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
    1893             :                     interface->global_iface_name);
    1894           2 :         buf[len - 1] = '\0';
    1895           2 :         return buf;
    1896             : }
    1897             : 
    1898             : 
    1899           1 : int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
    1900             : {
    1901             :         struct sockaddr_un addr;
    1902           1 :         int s = -1;
    1903           1 :         char *fname = NULL;
    1904             : 
    1905           1 :         if (interface->global_iface_path == NULL) {
    1906           0 :                 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
    1907           0 :                 return 0;
    1908             :         }
    1909             : 
    1910           1 :         if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
    1911           1 :                 if (errno == EEXIST) {
    1912           1 :                         wpa_printf(MSG_DEBUG, "Using existing control "
    1913             :                                    "interface directory.");
    1914             :                 } else {
    1915           0 :                         perror("mkdir[ctrl_interface]");
    1916           0 :                         goto fail;
    1917             :                 }
    1918           0 :         } else if (interface->ctrl_iface_group &&
    1919           0 :                    chown(interface->global_iface_path, -1,
    1920             :                          interface->ctrl_iface_group) < 0) {
    1921           0 :                 perror("chown[ctrl_interface]");
    1922           0 :                 goto fail;
    1923             :         }
    1924             : 
    1925           2 :         if (os_strlen(interface->global_iface_path) + 1 +
    1926           1 :             os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
    1927           0 :                 goto fail;
    1928             : 
    1929           1 :         s = socket(PF_UNIX, SOCK_DGRAM, 0);
    1930           1 :         if (s < 0) {
    1931           0 :                 perror("socket(PF_UNIX)");
    1932           0 :                 goto fail;
    1933             :         }
    1934             : 
    1935           1 :         os_memset(&addr, 0, sizeof(addr));
    1936             : #ifdef __FreeBSD__
    1937             :         addr.sun_len = sizeof(addr);
    1938             : #endif /* __FreeBSD__ */
    1939           1 :         addr.sun_family = AF_UNIX;
    1940           1 :         fname = hostapd_global_ctrl_iface_path(interface);
    1941           1 :         if (fname == NULL)
    1942           0 :                 goto fail;
    1943           1 :         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
    1944           1 :         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    1945           0 :                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
    1946           0 :                            strerror(errno));
    1947           0 :                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    1948           0 :                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
    1949             :                                    " allow connections - assuming it was left"
    1950             :                                    "over from forced program termination");
    1951           0 :                         if (unlink(fname) < 0) {
    1952           0 :                                 perror("unlink[ctrl_iface]");
    1953           0 :                                 wpa_printf(MSG_ERROR, "Could not unlink "
    1954             :                                            "existing ctrl_iface socket '%s'",
    1955             :                                            fname);
    1956           0 :                                 goto fail;
    1957             :                         }
    1958           0 :                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
    1959             :                             0) {
    1960           0 :                                 perror("bind(PF_UNIX)");
    1961           0 :                                 goto fail;
    1962             :                         }
    1963           0 :                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
    1964             :                                    "ctrl_iface socket '%s'", fname);
    1965             :                 } else {
    1966           0 :                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
    1967             :                                    "be in use - cannot override it");
    1968           0 :                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
    1969             :                                    "not used anymore", fname);
    1970           0 :                         os_free(fname);
    1971           0 :                         fname = NULL;
    1972           0 :                         goto fail;
    1973             :                 }
    1974             :         }
    1975             : 
    1976           1 :         if (interface->ctrl_iface_group &&
    1977           0 :             chown(fname, -1, interface->ctrl_iface_group) < 0) {
    1978           0 :                 perror("chown[ctrl_interface]");
    1979           0 :                 goto fail;
    1980             :         }
    1981             : 
    1982           1 :         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
    1983           0 :                 perror("chmod[ctrl_interface/ifname]");
    1984           0 :                 goto fail;
    1985             :         }
    1986           1 :         os_free(fname);
    1987             : 
    1988           1 :         interface->global_ctrl_sock = s;
    1989           1 :         eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
    1990             :                                  interface, NULL);
    1991             : 
    1992           1 :         return 0;
    1993             : 
    1994             : fail:
    1995           0 :         if (s >= 0)
    1996           0 :                 close(s);
    1997           0 :         if (fname) {
    1998           0 :                 unlink(fname);
    1999           0 :                 os_free(fname);
    2000             :         }
    2001           0 :         return -1;
    2002             : }
    2003             : 
    2004             : 
    2005           1 : void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
    2006             : {
    2007           1 :         char *fname = NULL;
    2008             : 
    2009           1 :         if (interfaces->global_ctrl_sock > -1) {
    2010           1 :                 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
    2011           1 :                 close(interfaces->global_ctrl_sock);
    2012           1 :                 interfaces->global_ctrl_sock = -1;
    2013           1 :                 fname = hostapd_global_ctrl_iface_path(interfaces);
    2014           1 :                 if (fname) {
    2015           1 :                         unlink(fname);
    2016           1 :                         os_free(fname);
    2017             :                 }
    2018             : 
    2019           2 :                 if (interfaces->global_iface_path &&
    2020           1 :                     rmdir(interfaces->global_iface_path) < 0) {
    2021           1 :                         if (errno == ENOTEMPTY) {
    2022           0 :                                 wpa_printf(MSG_DEBUG, "Control interface "
    2023             :                                            "directory not empty - leaving it "
    2024             :                                            "behind");
    2025             :                         } else {
    2026           1 :                                 wpa_printf(MSG_ERROR,
    2027             :                                            "rmdir[ctrl_interface=%s]: %s",
    2028             :                                            interfaces->global_iface_path,
    2029           1 :                                            strerror(errno));
    2030             :                         }
    2031             :                 }
    2032           1 :                 os_free(interfaces->global_iface_path);
    2033           1 :                 interfaces->global_iface_path = NULL;
    2034             :         }
    2035           1 : }
    2036             : 
    2037             : 
    2038       31378 : static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
    2039             :                                     const char *buf, size_t len)
    2040             : {
    2041             :         struct wpa_ctrl_dst *dst, *next;
    2042             :         struct msghdr msg;
    2043             :         int idx;
    2044             :         struct iovec io[2];
    2045             :         char levelstr[10];
    2046             : 
    2047       31378 :         dst = hapd->ctrl_dst;
    2048       31378 :         if (hapd->ctrl_sock < 0 || dst == NULL)
    2049       48607 :                 return;
    2050             : 
    2051       14149 :         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
    2052       14149 :         io[0].iov_base = levelstr;
    2053       14149 :         io[0].iov_len = os_strlen(levelstr);
    2054       14149 :         io[1].iov_base = (char *) buf;
    2055       14149 :         io[1].iov_len = len;
    2056       14149 :         os_memset(&msg, 0, sizeof(msg));
    2057       14149 :         msg.msg_iov = io;
    2058       14149 :         msg.msg_iovlen = 2;
    2059             : 
    2060       14149 :         idx = 0;
    2061       42762 :         while (dst) {
    2062       14464 :                 next = dst->next;
    2063       14464 :                 if (level >= dst->debug_level) {
    2064        5412 :                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
    2065        5412 :                                     (u8 *) dst->addr.sun_path, dst->addrlen -
    2066             :                                     offsetof(struct sockaddr_un, sun_path));
    2067        2706 :                         msg.msg_name = &dst->addr;
    2068        2706 :                         msg.msg_namelen = dst->addrlen;
    2069        2706 :                         if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
    2070           1 :                                 int _errno = errno;
    2071           2 :                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
    2072             :                                            "%d - %s",
    2073           2 :                                            idx, errno, strerror(errno));
    2074           1 :                                 dst->errors++;
    2075           1 :                                 if (dst->errors > 10 || _errno == ENOENT) {
    2076           1 :                                         hostapd_ctrl_iface_detach(
    2077             :                                                 hapd, &dst->addr,
    2078             :                                                 dst->addrlen);
    2079             :                                 }
    2080             :                         } else
    2081        2705 :                                 dst->errors = 0;
    2082             :                 }
    2083       14464 :                 idx++;
    2084       14464 :                 dst = next;
    2085             :         }
    2086             : }
    2087             : 
    2088             : #endif /* CONFIG_NATIVE_WINDOWS */

Generated by: LCOV version 1.10