LCOV - code coverage report
Current view: top level - hostapd - ctrl_iface.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1422976643 Lines: 1194 1495 79.9 %
Date: 2015-02-03 Functions: 56 56 100.0 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / UNIX domain socket -based control interface
       3             :  * Copyright (c) 2004-2015, 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             : #ifdef CONFIG_TESTING_OPTIONS
      14             : #include <net/ethernet.h>
      15             : #include <netinet/ip.h>
      16             : #endif /* CONFIG_TESTING_OPTIONS */
      17             : 
      18             : #include <sys/un.h>
      19             : #include <sys/stat.h>
      20             : #include <stddef.h>
      21             : 
      22             : #include "utils/common.h"
      23             : #include "utils/eloop.h"
      24             : #include "common/version.h"
      25             : #include "common/ieee802_11_defs.h"
      26             : #include "crypto/tls.h"
      27             : #include "drivers/driver.h"
      28             : #include "radius/radius_client.h"
      29             : #include "radius/radius_server.h"
      30             : #include "l2_packet/l2_packet.h"
      31             : #include "ap/hostapd.h"
      32             : #include "ap/ap_config.h"
      33             : #include "ap/ieee802_1x.h"
      34             : #include "ap/wpa_auth.h"
      35             : #include "ap/ieee802_11.h"
      36             : #include "ap/sta_info.h"
      37             : #include "ap/wps_hostapd.h"
      38             : #include "ap/ctrl_iface_ap.h"
      39             : #include "ap/ap_drv_ops.h"
      40             : #include "ap/hs20.h"
      41             : #include "ap/wnm_ap.h"
      42             : #include "ap/wpa_auth.h"
      43             : #include "wps/wps_defs.h"
      44             : #include "wps/wps.h"
      45             : #include "config_file.h"
      46             : #include "ctrl_iface.h"
      47             : 
      48             : 
      49             : struct wpa_ctrl_dst {
      50             :         struct wpa_ctrl_dst *next;
      51             :         struct sockaddr_un addr;
      52             :         socklen_t addrlen;
      53             :         int debug_level;
      54             :         int errors;
      55             : };
      56             : 
      57             : 
      58             : static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
      59             :                                     const char *buf, size_t len);
      60             : 
      61             : 
      62        1329 : static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
      63             :                                      struct sockaddr_un *from,
      64             :                                      socklen_t fromlen)
      65             : {
      66             :         struct wpa_ctrl_dst *dst;
      67             : 
      68        1329 :         dst = os_zalloc(sizeof(*dst));
      69        1329 :         if (dst == NULL)
      70           3 :                 return -1;
      71        1326 :         os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
      72        1326 :         dst->addrlen = fromlen;
      73        1326 :         dst->debug_level = MSG_INFO;
      74        1326 :         dst->next = hapd->ctrl_dst;
      75        1326 :         hapd->ctrl_dst = dst;
      76        2652 :         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
      77        1326 :                     (u8 *) from->sun_path,
      78             :                     fromlen - offsetof(struct sockaddr_un, sun_path));
      79        1326 :         return 0;
      80             : }
      81             : 
      82             : 
      83        1237 : static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
      84             :                                      struct sockaddr_un *from,
      85             :                                      socklen_t fromlen)
      86             : {
      87        1237 :         struct wpa_ctrl_dst *dst, *prev = NULL;
      88             : 
      89        1237 :         dst = hapd->ctrl_dst;
      90        2476 :         while (dst) {
      91        2476 :                 if (fromlen == dst->addrlen &&
      92        1238 :                     os_memcmp(from->sun_path, dst->addr.sun_path,
      93             :                               fromlen - offsetof(struct sockaddr_un, sun_path))
      94             :                     == 0) {
      95        2472 :                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
      96        1236 :                                     (u8 *) from->sun_path,
      97             :                                     fromlen -
      98             :                                     offsetof(struct sockaddr_un, sun_path));
      99        1236 :                         if (prev == NULL)
     100        1234 :                                 hapd->ctrl_dst = dst->next;
     101             :                         else
     102           2 :                                 prev->next = dst->next;
     103        1236 :                         os_free(dst);
     104        1236 :                         return 0;
     105             :                 }
     106           2 :                 prev = dst;
     107           2 :                 dst = dst->next;
     108             :         }
     109           1 :         return -1;
     110             : }
     111             : 
     112             : 
     113           1 : static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
     114             :                                     struct sockaddr_un *from,
     115             :                                     socklen_t fromlen,
     116             :                                     char *level)
     117             : {
     118             :         struct wpa_ctrl_dst *dst;
     119             : 
     120           1 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
     121             : 
     122           1 :         dst = hapd->ctrl_dst;
     123           3 :         while (dst) {
     124           2 :                 if (fromlen == dst->addrlen &&
     125           1 :                     os_memcmp(from->sun_path, dst->addr.sun_path,
     126             :                               fromlen - offsetof(struct sockaddr_un, sun_path))
     127             :                     == 0) {
     128           0 :                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
     129           0 :                                     "level", (u8 *) from->sun_path, fromlen -
     130             :                                     offsetof(struct sockaddr_un, sun_path));
     131           0 :                         dst->debug_level = atoi(level);
     132           0 :                         return 0;
     133             :                 }
     134           1 :                 dst = dst->next;
     135             :         }
     136             : 
     137           1 :         return -1;
     138             : }
     139             : 
     140             : 
     141           2 : static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
     142             :                                       const char *txtaddr)
     143             : {
     144             :         u8 addr[ETH_ALEN];
     145             :         struct sta_info *sta;
     146             : 
     147           2 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
     148             : 
     149           2 :         if (hwaddr_aton(txtaddr, addr))
     150           1 :                 return -1;
     151             : 
     152           1 :         sta = ap_get_sta(hapd, addr);
     153           1 :         if (sta)
     154           0 :                 return 0;
     155             : 
     156           6 :         wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
     157           6 :                    "notification", MAC2STR(addr));
     158           1 :         sta = ap_sta_add(hapd, addr);
     159           1 :         if (sta == NULL)
     160           0 :                 return -1;
     161             : 
     162           1 :         hostapd_new_assoc_sta(hapd, sta, 0);
     163           1 :         return 0;
     164             : }
     165             : 
     166             : 
     167             : #ifdef CONFIG_IEEE80211W
     168             : #ifdef NEED_AP_MLME
     169           2 : static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
     170             :                                        const char *txtaddr)
     171             : {
     172             :         u8 addr[ETH_ALEN];
     173             :         u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
     174             : 
     175           2 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
     176             : 
     177           4 :         if (hwaddr_aton(txtaddr, addr) ||
     178           2 :             os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
     179           0 :                 return -1;
     180             : 
     181           2 :         ieee802_11_send_sa_query_req(hapd, addr, trans_id);
     182             : 
     183           2 :         return 0;
     184             : }
     185             : #endif /* NEED_AP_MLME */
     186             : #endif /* CONFIG_IEEE80211W */
     187             : 
     188             : 
     189             : #ifdef CONFIG_WPS
     190          20 : static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
     191             : {
     192          20 :         char *pin = os_strchr(txt, ' ');
     193             :         char *timeout_txt;
     194             :         int timeout;
     195          20 :         u8 addr_buf[ETH_ALEN], *addr = NULL;
     196             :         char *pos;
     197             : 
     198          20 :         if (pin == NULL)
     199           1 :                 return -1;
     200          19 :         *pin++ = '\0';
     201             : 
     202          19 :         timeout_txt = os_strchr(pin, ' ');
     203          19 :         if (timeout_txt) {
     204           2 :                 *timeout_txt++ = '\0';
     205           2 :                 timeout = atoi(timeout_txt);
     206           2 :                 pos = os_strchr(timeout_txt, ' ');
     207           2 :                 if (pos) {
     208           1 :                         *pos++ = '\0';
     209           1 :                         if (hwaddr_aton(pos, addr_buf) == 0)
     210           1 :                                 addr = addr_buf;
     211             :                 }
     212             :         } else
     213          17 :                 timeout = 0;
     214             : 
     215          19 :         return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
     216             : }
     217             : 
     218             : 
     219           9 : static int hostapd_ctrl_iface_wps_check_pin(
     220             :         struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
     221             : {
     222             :         char pin[9];
     223             :         size_t len;
     224             :         char *pos;
     225             :         int ret;
     226             : 
     227           9 :         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
     228             :                               (u8 *) cmd, os_strlen(cmd));
     229          81 :         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
     230          74 :                 if (*pos < '0' || *pos > '9')
     231           6 :                         continue;
     232          68 :                 pin[len++] = *pos;
     233          68 :                 if (len == 9) {
     234           2 :                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
     235           2 :                         return -1;
     236             :                 }
     237             :         }
     238           7 :         if (len != 4 && len != 8) {
     239           2 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
     240           2 :                 return -1;
     241             :         }
     242           5 :         pin[len] = '\0';
     243             : 
     244           5 :         if (len == 8) {
     245             :                 unsigned int pin_val;
     246           5 :                 pin_val = atoi(pin);
     247           5 :                 if (!wps_pin_valid(pin_val)) {
     248           1 :                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
     249           1 :                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
     250           1 :                         if (os_snprintf_error(buflen, ret))
     251           0 :                                 return -1;
     252           1 :                         return ret;
     253             :                 }
     254             :         }
     255             : 
     256           4 :         ret = os_snprintf(buf, buflen, "%s", pin);
     257           4 :         if (os_snprintf_error(buflen, ret))
     258           0 :                 return -1;
     259             : 
     260           4 :         return ret;
     261             : }
     262             : 
     263             : 
     264             : #ifdef CONFIG_WPS_NFC
     265           2 : static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
     266             :                                                char *pos)
     267             : {
     268             :         size_t len;
     269             :         struct wpabuf *buf;
     270             :         int ret;
     271             : 
     272           2 :         len = os_strlen(pos);
     273           2 :         if (len & 0x01)
     274           0 :                 return -1;
     275           2 :         len /= 2;
     276             : 
     277           2 :         buf = wpabuf_alloc(len);
     278           2 :         if (buf == NULL)
     279           0 :                 return -1;
     280           2 :         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
     281           0 :                 wpabuf_free(buf);
     282           0 :                 return -1;
     283             :         }
     284             : 
     285           2 :         ret = hostapd_wps_nfc_tag_read(hapd, buf);
     286           2 :         wpabuf_free(buf);
     287             : 
     288           2 :         return ret;
     289             : }
     290             : 
     291             : 
     292           2 : static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
     293             :                                                    char *cmd, char *reply,
     294             :                                                    size_t max_len)
     295             : {
     296             :         int ndef;
     297             :         struct wpabuf *buf;
     298             :         int res;
     299             : 
     300           2 :         if (os_strcmp(cmd, "WPS") == 0)
     301           0 :                 ndef = 0;
     302           2 :         else if (os_strcmp(cmd, "NDEF") == 0)
     303           2 :                 ndef = 1;
     304             :         else
     305           0 :                 return -1;
     306             : 
     307           2 :         buf = hostapd_wps_nfc_config_token(hapd, ndef);
     308           2 :         if (buf == NULL)
     309           0 :                 return -1;
     310             : 
     311           2 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
     312             :                                          wpabuf_len(buf));
     313           2 :         reply[res++] = '\n';
     314           2 :         reply[res] = '\0';
     315             : 
     316           2 :         wpabuf_free(buf);
     317             : 
     318           2 :         return res;
     319             : }
     320             : 
     321             : 
     322           3 : static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
     323             :                                                 char *reply, size_t max_len,
     324             :                                                 int ndef)
     325             : {
     326             :         struct wpabuf *buf;
     327             :         int res;
     328             : 
     329           3 :         buf = hostapd_wps_nfc_token_gen(hapd, ndef);
     330           3 :         if (buf == NULL)
     331           0 :                 return -1;
     332             : 
     333           3 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
     334             :                                          wpabuf_len(buf));
     335           3 :         reply[res++] = '\n';
     336           3 :         reply[res] = '\0';
     337             : 
     338           3 :         wpabuf_free(buf);
     339             : 
     340           3 :         return res;
     341             : }
     342             : 
     343             : 
     344           6 : static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
     345             :                                             char *cmd, char *reply,
     346             :                                             size_t max_len)
     347             : {
     348           6 :         if (os_strcmp(cmd, "WPS") == 0)
     349           1 :                 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
     350             :                                                             max_len, 0);
     351             : 
     352           5 :         if (os_strcmp(cmd, "NDEF") == 0)
     353           2 :                 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
     354             :                                                             max_len, 1);
     355             : 
     356           3 :         if (os_strcmp(cmd, "enable") == 0)
     357           2 :                 return hostapd_wps_nfc_token_enable(hapd);
     358             : 
     359           1 :         if (os_strcmp(cmd, "disable") == 0) {
     360           1 :                 hostapd_wps_nfc_token_disable(hapd);
     361           1 :                 return 0;
     362             :         }
     363             : 
     364           0 :         return -1;
     365             : }
     366             : 
     367             : 
     368           8 : static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
     369             :                                                    char *cmd, char *reply,
     370             :                                                    size_t max_len)
     371             : {
     372             :         struct wpabuf *buf;
     373             :         int res;
     374             :         char *pos;
     375             :         int ndef;
     376             : 
     377           8 :         pos = os_strchr(cmd, ' ');
     378           8 :         if (pos == NULL)
     379           0 :                 return -1;
     380           8 :         *pos++ = '\0';
     381             : 
     382           8 :         if (os_strcmp(cmd, "WPS") == 0)
     383           0 :                 ndef = 0;
     384           8 :         else if (os_strcmp(cmd, "NDEF") == 0)
     385           8 :                 ndef = 1;
     386             :         else
     387           0 :                 return -1;
     388             : 
     389           8 :         if (os_strcmp(pos, "WPS-CR") == 0)
     390           8 :                 buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
     391             :         else
     392           0 :                 buf = NULL;
     393           8 :         if (buf == NULL)
     394           0 :                 return -1;
     395             : 
     396           8 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
     397             :                                          wpabuf_len(buf));
     398           8 :         reply[res++] = '\n';
     399           8 :         reply[res] = '\0';
     400             : 
     401           8 :         wpabuf_free(buf);
     402             : 
     403           8 :         return res;
     404             : }
     405             : 
     406             : 
     407          17 : static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
     408             :                                                   char *cmd)
     409             : {
     410             :         size_t len;
     411             :         struct wpabuf *req, *sel;
     412             :         int ret;
     413             :         char *pos, *role, *type, *pos2;
     414             : 
     415          17 :         role = cmd;
     416          17 :         pos = os_strchr(role, ' ');
     417          17 :         if (pos == NULL)
     418           2 :                 return -1;
     419          15 :         *pos++ = '\0';
     420             : 
     421          15 :         type = pos;
     422          15 :         pos = os_strchr(type, ' ');
     423          15 :         if (pos == NULL)
     424           1 :                 return -1;
     425          14 :         *pos++ = '\0';
     426             : 
     427          14 :         pos2 = os_strchr(pos, ' ');
     428          14 :         if (pos2 == NULL)
     429           1 :                 return -1;
     430          13 :         *pos2++ = '\0';
     431             : 
     432          13 :         len = os_strlen(pos);
     433          13 :         if (len & 0x01)
     434           1 :                 return -1;
     435          12 :         len /= 2;
     436             : 
     437          12 :         req = wpabuf_alloc(len);
     438          12 :         if (req == NULL)
     439           0 :                 return -1;
     440          12 :         if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
     441           1 :                 wpabuf_free(req);
     442           1 :                 return -1;
     443             :         }
     444             : 
     445          11 :         len = os_strlen(pos2);
     446          11 :         if (len & 0x01) {
     447           1 :                 wpabuf_free(req);
     448           1 :                 return -1;
     449             :         }
     450          10 :         len /= 2;
     451             : 
     452          10 :         sel = wpabuf_alloc(len);
     453          10 :         if (sel == NULL) {
     454           0 :                 wpabuf_free(req);
     455           0 :                 return -1;
     456             :         }
     457          10 :         if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
     458           1 :                 wpabuf_free(req);
     459           1 :                 wpabuf_free(sel);
     460           1 :                 return -1;
     461             :         }
     462             : 
     463           9 :         if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
     464           8 :                 ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
     465             :         } else {
     466           1 :                 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
     467             :                            "reported: role=%s type=%s", role, type);
     468           1 :                 ret = -1;
     469             :         }
     470           9 :         wpabuf_free(req);
     471           9 :         wpabuf_free(sel);
     472             : 
     473           9 :         return ret;
     474             : }
     475             : 
     476             : #endif /* CONFIG_WPS_NFC */
     477             : 
     478             : 
     479          11 : static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
     480             :                                          char *buf, size_t buflen)
     481             : {
     482          11 :         int timeout = 300;
     483             :         char *pos;
     484             :         const char *pin_txt;
     485             : 
     486          11 :         pos = os_strchr(txt, ' ');
     487          11 :         if (pos)
     488           3 :                 *pos++ = '\0';
     489             : 
     490          11 :         if (os_strcmp(txt, "disable") == 0) {
     491           3 :                 hostapd_wps_ap_pin_disable(hapd);
     492           3 :                 return os_snprintf(buf, buflen, "OK\n");
     493             :         }
     494             : 
     495           8 :         if (os_strcmp(txt, "random") == 0) {
     496           3 :                 if (pos)
     497           1 :                         timeout = atoi(pos);
     498           3 :                 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
     499           3 :                 if (pin_txt == NULL)
     500           0 :                         return -1;
     501           3 :                 return os_snprintf(buf, buflen, "%s", pin_txt);
     502             :         }
     503             : 
     504           5 :         if (os_strcmp(txt, "get") == 0) {
     505           3 :                 pin_txt = hostapd_wps_ap_pin_get(hapd);
     506           3 :                 if (pin_txt == NULL)
     507           2 :                         return -1;
     508           1 :                 return os_snprintf(buf, buflen, "%s", pin_txt);
     509             :         }
     510             : 
     511           2 :         if (os_strcmp(txt, "set") == 0) {
     512             :                 char *pin;
     513           2 :                 if (pos == NULL)
     514           0 :                         return -1;
     515           2 :                 pin = pos;
     516           2 :                 pos = os_strchr(pos, ' ');
     517           2 :                 if (pos) {
     518           1 :                         *pos++ = '\0';
     519           1 :                         timeout = atoi(pos);
     520             :                 }
     521           2 :                 if (os_strlen(pin) > buflen)
     522           0 :                         return -1;
     523           2 :                 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
     524           0 :                         return -1;
     525           2 :                 return os_snprintf(buf, buflen, "%s", pin);
     526             :         }
     527             : 
     528           0 :         return -1;
     529             : }
     530             : 
     531             : 
     532           2 : static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
     533             : {
     534             :         char *pos;
     535           2 :         char *ssid, *auth, *encr = NULL, *key = NULL;
     536             : 
     537           2 :         ssid = txt;
     538           2 :         pos = os_strchr(txt, ' ');
     539           2 :         if (!pos)
     540           0 :                 return -1;
     541           2 :         *pos++ = '\0';
     542             : 
     543           2 :         auth = pos;
     544           2 :         pos = os_strchr(pos, ' ');
     545           2 :         if (pos) {
     546           2 :                 *pos++ = '\0';
     547           2 :                 encr = pos;
     548           2 :                 pos = os_strchr(pos, ' ');
     549           2 :                 if (pos) {
     550           2 :                         *pos++ = '\0';
     551           2 :                         key = pos;
     552             :                 }
     553             :         }
     554             : 
     555           2 :         return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
     556             : }
     557             : 
     558             : 
     559           5 : static const char * pbc_status_str(enum pbc_status status)
     560             : {
     561           5 :         switch (status) {
     562             :         case WPS_PBC_STATUS_DISABLE:
     563           4 :                 return "Disabled";
     564             :         case WPS_PBC_STATUS_ACTIVE:
     565           1 :                 return "Active";
     566             :         case WPS_PBC_STATUS_TIMEOUT:
     567           0 :                 return "Timed-out";
     568             :         case WPS_PBC_STATUS_OVERLAP:
     569           0 :                 return "Overlap";
     570             :         default:
     571           0 :                 return "Unknown";
     572             :         }
     573             : }
     574             : 
     575             : 
     576           5 : static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
     577             :                                              char *buf, size_t buflen)
     578             : {
     579             :         int ret;
     580             :         char *pos, *end;
     581             : 
     582           5 :         pos = buf;
     583           5 :         end = buf + buflen;
     584             : 
     585           5 :         ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
     586             :                           pbc_status_str(hapd->wps_stats.pbc_status));
     587             : 
     588           5 :         if (os_snprintf_error(end - pos, ret))
     589           0 :                 return pos - buf;
     590           5 :         pos += ret;
     591             : 
     592           9 :         ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
     593           5 :                           (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
     594             :                            "Success":
     595           4 :                            (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
     596           4 :                             "Failed" : "None")));
     597             : 
     598           5 :         if (os_snprintf_error(end - pos, ret))
     599           0 :                 return pos - buf;
     600           5 :         pos += ret;
     601             : 
     602             :         /* If status == Failure - Add possible Reasons */
     603           8 :         if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
     604           3 :            hapd->wps_stats.failure_reason > 0) {
     605           1 :                 ret = os_snprintf(pos, end - pos,
     606             :                                   "Failure Reason: %s\n",
     607             :                                   wps_ei_str(hapd->wps_stats.failure_reason));
     608             : 
     609           1 :                 if (os_snprintf_error(end - pos, ret))
     610           0 :                         return pos - buf;
     611           1 :                 pos += ret;
     612             :         }
     613             : 
     614           5 :         if (hapd->wps_stats.status) {
     615          24 :                 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
     616          24 :                                   MAC2STR(hapd->wps_stats.peer_addr));
     617             : 
     618           4 :                 if (os_snprintf_error(end - pos, ret))
     619           0 :                         return pos - buf;
     620           4 :                 pos += ret;
     621             :         }
     622             : 
     623           5 :         return pos - buf;
     624             : }
     625             : 
     626             : #endif /* CONFIG_WPS */
     627             : 
     628             : #ifdef CONFIG_HS20
     629             : 
     630           7 : static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
     631             :                                              const char *cmd)
     632             : {
     633             :         u8 addr[ETH_ALEN];
     634             :         const char *url;
     635             : 
     636           7 :         if (hwaddr_aton(cmd, addr))
     637           3 :                 return -1;
     638           4 :         url = cmd + 17;
     639           4 :         if (*url == '\0') {
     640           1 :                 url = NULL;
     641             :         } else {
     642           3 :                 if (*url != ' ')
     643           1 :                         return -1;
     644           2 :                 url++;
     645           2 :                 if (*url == '\0')
     646           0 :                         url = NULL;
     647             :         }
     648             : 
     649           3 :         return hs20_send_wnm_notification(hapd, addr, 1, url);
     650             : }
     651             : 
     652             : 
     653           5 : static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
     654             :                                               const char *cmd)
     655             : {
     656             :         u8 addr[ETH_ALEN];
     657             :         int code, reauth_delay, ret;
     658             :         const char *pos;
     659             :         size_t url_len;
     660             :         struct wpabuf *req;
     661             : 
     662             :         /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
     663           5 :         if (hwaddr_aton(cmd, addr))
     664           1 :                 return -1;
     665             : 
     666           4 :         pos = os_strchr(cmd, ' ');
     667           4 :         if (pos == NULL)
     668           1 :                 return -1;
     669           3 :         pos++;
     670           3 :         code = atoi(pos);
     671             : 
     672           3 :         pos = os_strchr(pos, ' ');
     673           3 :         if (pos == NULL)
     674           1 :                 return -1;
     675           2 :         pos++;
     676           2 :         reauth_delay = atoi(pos);
     677             : 
     678           2 :         url_len = 0;
     679           2 :         pos = os_strchr(pos, ' ');
     680           2 :         if (pos) {
     681           2 :                 pos++;
     682           2 :                 url_len = os_strlen(pos);
     683             :         }
     684             : 
     685           2 :         req = wpabuf_alloc(4 + url_len);
     686           2 :         if (req == NULL)
     687           0 :                 return -1;
     688           2 :         wpabuf_put_u8(req, code);
     689           2 :         wpabuf_put_le16(req, reauth_delay);
     690           2 :         wpabuf_put_u8(req, url_len);
     691           2 :         if (pos)
     692           2 :                 wpabuf_put_data(req, pos, url_len);
     693             : 
     694          12 :         wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
     695             :                    " to indicate imminent deauthentication (code=%d "
     696          12 :                    "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
     697           2 :         ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
     698           2 :         wpabuf_free(req);
     699           2 :         return ret;
     700             : }
     701             : 
     702             : #endif /* CONFIG_HS20 */
     703             : 
     704             : 
     705             : #ifdef CONFIG_INTERWORKING
     706             : 
     707           7 : static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
     708             :                                               const char *cmd)
     709             : {
     710           7 :         u8 qos_map_set[16 + 2 * 21], count = 0;
     711           7 :         const char *pos = cmd;
     712             :         int val, ret;
     713             : 
     714             :         for (;;) {
     715         122 :                 if (count == sizeof(qos_map_set)) {
     716           1 :                         wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
     717           1 :                         return -1;
     718             :                 }
     719             : 
     720         121 :                 val = atoi(pos);
     721         121 :                 if (val < 0 || val > 255) {
     722           1 :                         wpa_printf(MSG_INFO, "Invalid QoS Map Set");
     723           1 :                         return -1;
     724             :                 }
     725             : 
     726         120 :                 qos_map_set[count++] = val;
     727         120 :                 pos = os_strchr(pos, ',');
     728         120 :                 if (!pos)
     729           5 :                         break;
     730         115 :                 pos++;
     731         115 :         }
     732             : 
     733           5 :         if (count < 16 || count & 1) {
     734           3 :                 wpa_printf(MSG_INFO, "Invalid QoS Map Set");
     735           3 :                 return -1;
     736             :         }
     737             : 
     738           2 :         ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
     739           2 :         if (ret) {
     740           0 :                 wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
     741           0 :                 return -1;
     742             :         }
     743             : 
     744           2 :         os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
     745           2 :         hapd->conf->qos_map_set_len = count;
     746             : 
     747           2 :         return 0;
     748             : }
     749             : 
     750             : 
     751           4 : static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
     752             :                                                 const char *cmd)
     753             : {
     754             :         u8 addr[ETH_ALEN];
     755             :         struct sta_info *sta;
     756             :         struct wpabuf *buf;
     757           4 :         u8 *qos_map_set = hapd->conf->qos_map_set;
     758           4 :         u8 qos_map_set_len = hapd->conf->qos_map_set_len;
     759             :         int ret;
     760             : 
     761           4 :         if (!qos_map_set_len) {
     762           1 :                 wpa_printf(MSG_INFO, "QoS Map Set is not set");
     763           1 :                 return -1;
     764             :         }
     765             : 
     766           3 :         if (hwaddr_aton(cmd, addr))
     767           1 :                 return -1;
     768             : 
     769           2 :         sta = ap_get_sta(hapd, addr);
     770           2 :         if (sta == NULL) {
     771           6 :                 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
     772             :                            "for QoS Map Configuration message",
     773           6 :                            MAC2STR(addr));
     774           1 :                 return -1;
     775             :         }
     776             : 
     777           1 :         if (!sta->qos_map_enabled) {
     778           0 :                 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
     779           0 :                            "support for QoS Map", MAC2STR(addr));
     780           0 :                 return -1;
     781             :         }
     782             : 
     783           1 :         buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
     784           1 :         if (buf == NULL)
     785           0 :                 return -1;
     786             : 
     787           1 :         wpabuf_put_u8(buf, WLAN_ACTION_QOS);
     788           1 :         wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
     789             : 
     790             :         /* QoS Map Set Element */
     791           1 :         wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
     792           1 :         wpabuf_put_u8(buf, qos_map_set_len);
     793           1 :         wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
     794             : 
     795           2 :         ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
     796           1 :                                       wpabuf_head(buf), wpabuf_len(buf));
     797           1 :         wpabuf_free(buf);
     798             : 
     799           1 :         return ret;
     800             : }
     801             : 
     802             : #endif /* CONFIG_INTERWORKING */
     803             : 
     804             : 
     805             : #ifdef CONFIG_WNM
     806             : 
     807           5 : static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
     808             :                                                 const char *cmd)
     809             : {
     810             :         u8 addr[ETH_ALEN];
     811             :         int disassoc_timer;
     812             :         struct sta_info *sta;
     813             : 
     814           5 :         if (hwaddr_aton(cmd, addr))
     815           1 :                 return -1;
     816           4 :         if (cmd[17] != ' ')
     817           1 :                 return -1;
     818           3 :         disassoc_timer = atoi(cmd + 17);
     819             : 
     820           3 :         sta = ap_get_sta(hapd, addr);
     821           3 :         if (sta == NULL) {
     822           6 :                 wpa_printf(MSG_DEBUG, "Station " MACSTR
     823             :                            " not found for disassociation imminent message",
     824           6 :                            MAC2STR(addr));
     825           1 :                 return -1;
     826             :         }
     827             : 
     828           2 :         return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
     829             : }
     830             : 
     831             : 
     832           8 : static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
     833             :                                            const char *cmd)
     834             : {
     835             :         u8 addr[ETH_ALEN];
     836             :         const char *url, *timerstr;
     837             :         int disassoc_timer;
     838             :         struct sta_info *sta;
     839             : 
     840           8 :         if (hwaddr_aton(cmd, addr))
     841           1 :                 return -1;
     842             : 
     843           7 :         sta = ap_get_sta(hapd, addr);
     844           7 :         if (sta == NULL) {
     845           6 :                 wpa_printf(MSG_DEBUG, "Station " MACSTR
     846             :                            " not found for ESS disassociation imminent message",
     847           6 :                            MAC2STR(addr));
     848           1 :                 return -1;
     849             :         }
     850             : 
     851           6 :         timerstr = cmd + 17;
     852           6 :         if (*timerstr != ' ')
     853           1 :                 return -1;
     854           5 :         timerstr++;
     855           5 :         disassoc_timer = atoi(timerstr);
     856           5 :         if (disassoc_timer < 0 || disassoc_timer > 65535)
     857           1 :                 return -1;
     858             : 
     859           4 :         url = os_strchr(timerstr, ' ');
     860           4 :         if (url == NULL)
     861           1 :                 return -1;
     862           3 :         url++;
     863             : 
     864           3 :         return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
     865             : }
     866             : 
     867             : 
     868           5 : static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
     869             :                                          const char *cmd)
     870             : {
     871             :         u8 addr[ETH_ALEN];
     872             :         const char *pos, *end;
     873           5 :         int disassoc_timer = 0;
     874             :         struct sta_info *sta;
     875           5 :         u8 req_mode = 0, valid_int = 0x01;
     876             :         u8 bss_term_dur[12];
     877           5 :         char *url = NULL;
     878             :         int ret;
     879             :         u8 nei_rep[1000];
     880           5 :         u8 *nei_pos = nei_rep;
     881             : 
     882           5 :         if (hwaddr_aton(cmd, addr)) {
     883           0 :                 wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
     884           0 :                 return -1;
     885             :         }
     886             : 
     887           5 :         sta = ap_get_sta(hapd, addr);
     888           5 :         if (sta == NULL) {
     889           0 :                 wpa_printf(MSG_DEBUG, "Station " MACSTR
     890             :                            " not found for BSS TM Request message",
     891           0 :                            MAC2STR(addr));
     892           0 :                 return -1;
     893             :         }
     894             : 
     895           5 :         pos = os_strstr(cmd, " disassoc_timer=");
     896           5 :         if (pos) {
     897           0 :                 pos += 16;
     898           0 :                 disassoc_timer = atoi(pos);
     899           0 :                 if (disassoc_timer < 0 || disassoc_timer > 65535) {
     900           0 :                         wpa_printf(MSG_DEBUG, "Invalid disassoc_timer");
     901           0 :                         return -1;
     902             :                 }
     903             :         }
     904             : 
     905           5 :         pos = os_strstr(cmd, " valid_int=");
     906           5 :         if (pos) {
     907           2 :                 pos += 11;
     908           2 :                 valid_int = atoi(pos);
     909             :         }
     910             : 
     911           5 :         pos = os_strstr(cmd, " bss_term=");
     912           5 :         if (pos) {
     913           0 :                 pos += 10;
     914           0 :                 req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED;
     915             :                 /* TODO: TSF configurable/learnable */
     916           0 :                 bss_term_dur[0] = 4; /* Subelement ID */
     917           0 :                 bss_term_dur[1] = 10; /* Length */
     918           0 :                 os_memset(bss_term_dur, 2, 8);
     919           0 :                 end = os_strchr(pos, ',');
     920           0 :                 if (end == NULL) {
     921           0 :                         wpa_printf(MSG_DEBUG, "Invalid bss_term data");
     922           0 :                         return -1;
     923             :                 }
     924           0 :                 end++;
     925           0 :                 WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
     926             :         }
     927             : 
     928             : 
     929             :         /*
     930             :          * BSS Transition Candidate List Entries - Neighbor Report elements
     931             :          * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
     932             :          * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
     933             :          */
     934           5 :         pos = cmd;
     935          17 :         while (pos) {
     936             :                 u8 *nei_start;
     937             :                 long int val;
     938             :                 char *endptr, *tmp;
     939             : 
     940           9 :                 pos = os_strstr(pos, " neighbor=");
     941           9 :                 if (!pos)
     942           2 :                         break;
     943           7 :                 if (nei_pos + 15 > nei_rep + sizeof(nei_rep)) {
     944           0 :                         wpa_printf(MSG_DEBUG,
     945             :                                    "Not enough room for additional neighbor");
     946           0 :                         return -1;
     947             :                 }
     948           7 :                 pos += 10;
     949             : 
     950           7 :                 nei_start = nei_pos;
     951           7 :                 *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
     952           7 :                 nei_pos++; /* length to be filled in */
     953             : 
     954           7 :                 if (hwaddr_aton(pos, nei_pos)) {
     955           0 :                         wpa_printf(MSG_DEBUG, "Invalid BSSID");
     956           0 :                         return -1;
     957             :                 }
     958           7 :                 nei_pos += ETH_ALEN;
     959           7 :                 pos += 17;
     960           7 :                 if (*pos != ',') {
     961           0 :                         wpa_printf(MSG_DEBUG, "Missing BSSID Information");
     962           0 :                         return -1;
     963             :                 }
     964           7 :                 pos++;
     965             : 
     966           7 :                 val = strtol(pos, &endptr, 0);
     967           7 :                 WPA_PUT_LE32(nei_pos, val);
     968           7 :                 nei_pos += 4;
     969           7 :                 if (*endptr != ',') {
     970           0 :                         wpa_printf(MSG_DEBUG, "Missing Operating Class");
     971           0 :                         return -1;
     972             :                 }
     973           7 :                 pos = endptr + 1;
     974             : 
     975           7 :                 *nei_pos++ = atoi(pos); /* Operating Class */
     976           7 :                 pos = os_strchr(pos, ',');
     977           7 :                 if (pos == NULL) {
     978           0 :                         wpa_printf(MSG_DEBUG, "Missing Channel Number");
     979           0 :                         return -1;
     980             :                 }
     981           7 :                 pos++;
     982             : 
     983           7 :                 *nei_pos++ = atoi(pos); /* Channel Number */
     984           7 :                 pos = os_strchr(pos, ',');
     985           7 :                 if (pos == NULL) {
     986           0 :                         wpa_printf(MSG_DEBUG, "Missing PHY Type");
     987           0 :                         return -1;
     988             :                 }
     989           7 :                 pos++;
     990             : 
     991           7 :                 *nei_pos++ = atoi(pos); /* PHY Type */
     992           7 :                 end = os_strchr(pos, ' ');
     993           7 :                 tmp = os_strchr(pos, ',');
     994           7 :                 if (tmp && (!end || tmp < end)) {
     995             :                         /* Optional Subelements (hexdump) */
     996             :                         size_t len;
     997             : 
     998           5 :                         pos = tmp + 1;
     999           5 :                         end = os_strchr(pos, ' ');
    1000           5 :                         if (end)
    1001           2 :                                 len = end - pos;
    1002             :                         else
    1003           3 :                                 len = os_strlen(pos);
    1004           5 :                         if (nei_pos + len / 2 > nei_rep + sizeof(nei_rep)) {
    1005           0 :                                 wpa_printf(MSG_DEBUG,
    1006             :                                            "Not enough room for neighbor subelements");
    1007           0 :                                 return -1;
    1008             :                         }
    1009          10 :                         if (len & 0x01 ||
    1010           5 :                             hexstr2bin(pos, nei_pos, len / 2) < 0) {
    1011           0 :                                 wpa_printf(MSG_DEBUG,
    1012             :                                            "Invalid neighbor subelement info");
    1013           0 :                                 return -1;
    1014             :                         }
    1015           5 :                         nei_pos += len / 2;
    1016           5 :                         pos = end;
    1017             :                 }
    1018             : 
    1019           7 :                 nei_start[1] = nei_pos - nei_start - 2;
    1020             :         }
    1021             : 
    1022           5 :         pos = os_strstr(cmd, " url=");
    1023           5 :         if (pos) {
    1024             :                 size_t len;
    1025           0 :                 pos += 5;
    1026           0 :                 end = os_strchr(pos, ' ');
    1027           0 :                 if (end)
    1028           0 :                         len = end - pos;
    1029             :                 else
    1030           0 :                         len = os_strlen(pos);
    1031           0 :                 url = os_malloc(len + 1);
    1032           0 :                 if (url == NULL)
    1033           0 :                         return -1;
    1034           0 :                 os_memcpy(url, pos, len);
    1035           0 :                 url[len] = '\0';
    1036           0 :                 req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
    1037             :         }
    1038             : 
    1039           5 :         if (os_strstr(cmd, " pref=1"))
    1040           3 :                 req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
    1041           5 :         if (os_strstr(cmd, " abridged=1"))
    1042           2 :                 req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
    1043           5 :         if (os_strstr(cmd, " disassoc_imminent=1"))
    1044           0 :                 req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
    1045             : 
    1046           5 :         ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
    1047             :                                   valid_int, bss_term_dur, url,
    1048             :                                   nei_pos > nei_rep ? nei_rep : NULL,
    1049           5 :                                   nei_pos - nei_rep);
    1050           5 :         os_free(url);
    1051           5 :         return ret;
    1052             : }
    1053             : 
    1054             : #endif /* CONFIG_WNM */
    1055             : 
    1056             : 
    1057          11 : static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
    1058             :                                          char *buf, size_t buflen)
    1059             : {
    1060             :         int ret;
    1061             :         char *pos, *end;
    1062             : 
    1063          11 :         pos = buf;
    1064          11 :         end = buf + buflen;
    1065             : 
    1066          88 :         ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
    1067             :                           "ssid=%s\n",
    1068          66 :                           MAC2STR(hapd->own_addr),
    1069          11 :                           wpa_ssid_txt(hapd->conf->ssid.ssid,
    1070          11 :                                        hapd->conf->ssid.ssid_len));
    1071          11 :         if (os_snprintf_error(end - pos, ret))
    1072           0 :                 return pos - buf;
    1073          11 :         pos += ret;
    1074             : 
    1075             : #ifdef CONFIG_WPS
    1076          12 :         ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
    1077          11 :                           hapd->conf->wps_state == 0 ? "disabled" :
    1078           1 :                           (hapd->conf->wps_state == 1 ? "not configured" :
    1079             :                            "configured"));
    1080          11 :         if (os_snprintf_error(end - pos, ret))
    1081           0 :                 return pos - buf;
    1082          11 :         pos += ret;
    1083             : 
    1084          12 :         if (hapd->conf->wps_state && hapd->conf->wpa &&
    1085           1 :             hapd->conf->ssid.wpa_passphrase) {
    1086           1 :                 ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
    1087           1 :                                   hapd->conf->ssid.wpa_passphrase);
    1088           1 :                 if (os_snprintf_error(end - pos, ret))
    1089           0 :                         return pos - buf;
    1090           1 :                 pos += ret;
    1091             :         }
    1092             : 
    1093          12 :         if (hapd->conf->wps_state && hapd->conf->wpa &&
    1094           2 :             hapd->conf->ssid.wpa_psk &&
    1095           1 :             hapd->conf->ssid.wpa_psk->group) {
    1096             :                 char hex[PMK_LEN * 2 + 1];
    1097           1 :                 wpa_snprintf_hex(hex, sizeof(hex),
    1098           1 :                                  hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
    1099           1 :                 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
    1100           1 :                 if (os_snprintf_error(end - pos, ret))
    1101           0 :                         return pos - buf;
    1102           1 :                 pos += ret;
    1103             :         }
    1104             : #endif /* CONFIG_WPS */
    1105             : 
    1106          11 :         if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
    1107          11 :                 ret = os_snprintf(pos, end - pos, "key_mgmt=");
    1108          11 :                 if (os_snprintf_error(end - pos, ret))
    1109           0 :                         return pos - buf;
    1110          11 :                 pos += ret;
    1111             : 
    1112          11 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
    1113           4 :                         ret = os_snprintf(pos, end - pos, "WPA-PSK ");
    1114           4 :                         if (os_snprintf_error(end - pos, ret))
    1115           0 :                                 return pos - buf;
    1116           4 :                         pos += ret;
    1117             :                 }
    1118          11 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
    1119           1 :                         ret = os_snprintf(pos, end - pos, "WPA-EAP ");
    1120           1 :                         if (os_snprintf_error(end - pos, ret))
    1121           0 :                                 return pos - buf;
    1122           1 :                         pos += ret;
    1123             :                 }
    1124             : #ifdef CONFIG_IEEE80211R
    1125          11 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
    1126           1 :                         ret = os_snprintf(pos, end - pos, "FT-PSK ");
    1127           1 :                         if (os_snprintf_error(end - pos, ret))
    1128           0 :                                 return pos - buf;
    1129           1 :                         pos += ret;
    1130             :                 }
    1131          11 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
    1132           2 :                         ret = os_snprintf(pos, end - pos, "FT-EAP ");
    1133           2 :                         if (os_snprintf_error(end - pos, ret))
    1134           0 :                                 return pos - buf;
    1135           2 :                         pos += ret;
    1136             :                 }
    1137             : #ifdef CONFIG_SAE
    1138          11 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
    1139           1 :                         ret = os_snprintf(pos, end - pos, "FT-SAE ");
    1140           1 :                         if (os_snprintf_error(end - pos, ret))
    1141           0 :                                 return pos - buf;
    1142           1 :                         pos += ret;
    1143             :                 }
    1144             : #endif /* CONFIG_SAE */
    1145             : #endif /* CONFIG_IEEE80211R */
    1146             : #ifdef CONFIG_IEEE80211W
    1147          11 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
    1148           1 :                         ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
    1149           1 :                         if (os_snprintf_error(end - pos, ret))
    1150           0 :                                 return pos - buf;
    1151           1 :                         pos += ret;
    1152             :                 }
    1153          11 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
    1154           1 :                         ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
    1155           1 :                         if (os_snprintf_error(end - pos, ret))
    1156           0 :                                 return pos - buf;
    1157           1 :                         pos += ret;
    1158             :                 }
    1159             : #endif /* CONFIG_IEEE80211W */
    1160             : #ifdef CONFIG_SAE
    1161          11 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
    1162           1 :                         ret = os_snprintf(pos, end - pos, "SAE ");
    1163           1 :                         if (os_snprintf_error(end - pos, ret))
    1164           0 :                                 return pos - buf;
    1165           1 :                         pos += ret;
    1166             :                 }
    1167             : #endif /* CONFIG_SAE */
    1168          11 :                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
    1169           0 :                         ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
    1170           0 :                         if (os_snprintf_error(end - pos, ret))
    1171           0 :                                 return pos - buf;
    1172           0 :                         pos += ret;
    1173             :                 }
    1174          11 :                 if (hapd->conf->wpa_key_mgmt &
    1175             :                     WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
    1176           0 :                         ret = os_snprintf(pos, end - pos,
    1177             :                                           "WPA-EAP-SUITE-B-192 ");
    1178           0 :                         if (os_snprintf_error(end - pos, ret))
    1179           0 :                                 return pos - buf;
    1180           0 :                         pos += ret;
    1181             :                 }
    1182             : 
    1183          11 :                 ret = os_snprintf(pos, end - pos, "\n");
    1184          11 :                 if (os_snprintf_error(end - pos, ret))
    1185           0 :                         return pos - buf;
    1186          11 :                 pos += ret;
    1187             :         }
    1188             : 
    1189          11 :         if (hapd->conf->wpa) {
    1190          11 :                 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
    1191          11 :                                   wpa_cipher_txt(hapd->conf->wpa_group));
    1192          11 :                 if (os_snprintf_error(end - pos, ret))
    1193           0 :                         return pos - buf;
    1194          11 :                 pos += ret;
    1195             :         }
    1196             : 
    1197          11 :         if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
    1198          11 :                 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
    1199          11 :                 if (os_snprintf_error(end - pos, ret))
    1200           0 :                         return pos - buf;
    1201          11 :                 pos += ret;
    1202             : 
    1203          11 :                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
    1204             :                                         " ");
    1205          11 :                 if (ret < 0)
    1206           0 :                         return pos - buf;
    1207          11 :                 pos += ret;
    1208             : 
    1209          11 :                 ret = os_snprintf(pos, end - pos, "\n");
    1210          11 :                 if (os_snprintf_error(end - pos, ret))
    1211           0 :                         return pos - buf;
    1212          11 :                 pos += ret;
    1213             :         }
    1214             : 
    1215          11 :         if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
    1216           2 :                 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
    1217           2 :                 if (os_snprintf_error(end - pos, ret))
    1218           0 :                         return pos - buf;
    1219           2 :                 pos += ret;
    1220             : 
    1221           2 :                 ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
    1222             :                                         " ");
    1223           2 :                 if (ret < 0)
    1224           0 :                         return pos - buf;
    1225           2 :                 pos += ret;
    1226             : 
    1227           2 :                 ret = os_snprintf(pos, end - pos, "\n");
    1228           2 :                 if (os_snprintf_error(end - pos, ret))
    1229           0 :                         return pos - buf;
    1230           2 :                 pos += ret;
    1231             :         }
    1232             : 
    1233          11 :         return pos - buf;
    1234             : }
    1235             : 
    1236             : 
    1237       16039 : static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
    1238             : {
    1239             :         char *value;
    1240       16039 :         int ret = 0;
    1241             : 
    1242       16039 :         value = os_strchr(cmd, ' ');
    1243       16039 :         if (value == NULL)
    1244           0 :                 return -1;
    1245       16039 :         *value++ = '\0';
    1246             : 
    1247       16039 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
    1248             :         if (0) {
    1249             : #ifdef CONFIG_WPS_TESTING
    1250       16039 :         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
    1251             :                 long int val;
    1252           4 :                 val = strtol(value, NULL, 0);
    1253           4 :                 if (val < 0 || val > 0xff) {
    1254           0 :                         ret = -1;
    1255           0 :                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
    1256             :                                    "wps_version_number %ld", val);
    1257             :                 } else {
    1258           4 :                         wps_version_number = val;
    1259           8 :                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
    1260             :                                    "version %u.%u",
    1261           4 :                                    (wps_version_number & 0xf0) >> 4,
    1262             :                                    wps_version_number & 0x0f);
    1263           4 :                         hostapd_wps_update_ie(hapd);
    1264             :                 }
    1265       16035 :         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
    1266           0 :                 wps_testing_dummy_cred = atoi(value);
    1267           0 :                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
    1268             :                            wps_testing_dummy_cred);
    1269       16035 :         } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
    1270           1 :                 wps_corrupt_pkhash = atoi(value);
    1271           1 :                 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
    1272             :                            wps_corrupt_pkhash);
    1273             : #endif /* CONFIG_WPS_TESTING */
    1274             : #ifdef CONFIG_INTERWORKING
    1275       16034 :         } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
    1276           3 :                 int val = atoi(value);
    1277           3 :                 if (val <= 0)
    1278           0 :                         ret = -1;
    1279             :                 else
    1280           3 :                         hapd->gas_frag_limit = val;
    1281             : #endif /* CONFIG_INTERWORKING */
    1282             : #ifdef CONFIG_TESTING_OPTIONS
    1283       16031 :         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
    1284          30 :                 hapd->ext_mgmt_frame_handling = atoi(value);
    1285       16001 :         } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
    1286          10 :                 hapd->ext_eapol_frame_io = atoi(value);
    1287             : #endif /* CONFIG_TESTING_OPTIONS */
    1288             :         } else {
    1289             :                 struct sta_info *sta;
    1290             :                 int vlan_id;
    1291             : 
    1292       15991 :                 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
    1293       15991 :                 if (ret)
    1294         175 :                         return ret;
    1295             : 
    1296       15816 :                 if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
    1297           4 :                         for (sta = hapd->sta_list; sta; sta = sta->next) {
    1298           4 :                                 if (hostapd_maclist_found(
    1299           2 :                                             hapd->conf->deny_mac,
    1300           2 :                                             hapd->conf->num_deny_mac, sta->addr,
    1301           1 :                                             &vlan_id) &&
    1302           1 :                                     (!vlan_id || vlan_id == sta->vlan_id))
    1303           1 :                                         ap_sta_disconnect(
    1304           1 :                                                 hapd, sta, sta->addr,
    1305             :                                                 WLAN_REASON_UNSPECIFIED);
    1306             :                         }
    1307       15817 :                 } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
    1308           3 :                            os_strcasecmp(cmd, "accept_mac_file") == 0) {
    1309           3 :                         for (sta = hapd->sta_list; sta; sta = sta->next) {
    1310           4 :                                 if (!hostapd_maclist_found(
    1311           2 :                                             hapd->conf->accept_mac,
    1312           2 :                                             hapd->conf->num_accept_mac,
    1313           3 :                                             sta->addr, &vlan_id) ||
    1314           1 :                                     (vlan_id && vlan_id != sta->vlan_id))
    1315           1 :                                         ap_sta_disconnect(
    1316           1 :                                                 hapd, sta, sta->addr,
    1317             :                                                 WLAN_REASON_UNSPECIFIED);
    1318             :                         }
    1319             :                 }
    1320             :         }
    1321             : 
    1322       15864 :         return ret;
    1323             : }
    1324             : 
    1325             : 
    1326           3 : static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
    1327             :                                   char *buf, size_t buflen)
    1328             : {
    1329             :         int res;
    1330             : 
    1331           3 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
    1332             : 
    1333           3 :         if (os_strcmp(cmd, "version") == 0) {
    1334           1 :                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
    1335           1 :                 if (os_snprintf_error(buflen, res))
    1336           0 :                         return -1;
    1337           1 :                 return res;
    1338           2 :         } else if (os_strcmp(cmd, "tls_library") == 0) {
    1339           1 :                 res = tls_get_library_version(buf, buflen);
    1340           1 :                 if (os_snprintf_error(buflen, res))
    1341           0 :                         return -1;
    1342           1 :                 return res;
    1343             :         }
    1344             : 
    1345           1 :         return -1;
    1346             : }
    1347             : 
    1348             : 
    1349         961 : static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
    1350             : {
    1351         961 :         if (hostapd_enable_iface(iface) < 0) {
    1352          36 :                 wpa_printf(MSG_ERROR, "Enabling of interface failed");
    1353          36 :                 return -1;
    1354             :         }
    1355         925 :         return 0;
    1356             : }
    1357             : 
    1358             : 
    1359           1 : static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
    1360             : {
    1361           1 :         if (hostapd_reload_iface(iface) < 0) {
    1362           0 :                 wpa_printf(MSG_ERROR, "Reloading of interface failed");
    1363           0 :                 return -1;
    1364             :         }
    1365           1 :         return 0;
    1366             : }
    1367             : 
    1368             : 
    1369          75 : static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
    1370             : {
    1371          75 :         if (hostapd_disable_iface(iface) < 0) {
    1372           9 :                 wpa_printf(MSG_ERROR, "Disabling of interface failed");
    1373           9 :                 return -1;
    1374             :         }
    1375          66 :         return 0;
    1376             : }
    1377             : 
    1378             : 
    1379             : #ifdef CONFIG_TESTING_OPTIONS
    1380             : 
    1381           3 : static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
    1382             : {
    1383             :         union wpa_event_data data;
    1384             :         char *pos, *param;
    1385             :         enum wpa_event_type event;
    1386             : 
    1387           3 :         wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
    1388             : 
    1389           3 :         os_memset(&data, 0, sizeof(data));
    1390             : 
    1391           3 :         param = os_strchr(cmd, ' ');
    1392           3 :         if (param == NULL)
    1393           0 :                 return -1;
    1394           3 :         *param++ = '\0';
    1395             : 
    1396           3 :         if (os_strcmp(cmd, "DETECTED") == 0)
    1397           3 :                 event = EVENT_DFS_RADAR_DETECTED;
    1398           0 :         else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
    1399           0 :                 event = EVENT_DFS_CAC_FINISHED;
    1400           0 :         else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
    1401           0 :                 event = EVENT_DFS_CAC_ABORTED;
    1402           0 :         else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
    1403           0 :                 event = EVENT_DFS_NOP_FINISHED;
    1404             :         else {
    1405           0 :                 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
    1406             :                            cmd);
    1407           0 :                 return -1;
    1408             :         }
    1409             : 
    1410           3 :         pos = os_strstr(param, "freq=");
    1411           3 :         if (pos)
    1412           3 :                 data.dfs_event.freq = atoi(pos + 5);
    1413             : 
    1414           3 :         pos = os_strstr(param, "ht_enabled=1");
    1415           3 :         if (pos)
    1416           3 :                 data.dfs_event.ht_enabled = 1;
    1417             : 
    1418           3 :         pos = os_strstr(param, "chan_offset=");
    1419           3 :         if (pos)
    1420           0 :                 data.dfs_event.chan_offset = atoi(pos + 12);
    1421             : 
    1422           3 :         pos = os_strstr(param, "chan_width=");
    1423           3 :         if (pos)
    1424           3 :                 data.dfs_event.chan_width = atoi(pos + 11);
    1425             : 
    1426           3 :         pos = os_strstr(param, "cf1=");
    1427           3 :         if (pos)
    1428           0 :                 data.dfs_event.cf1 = atoi(pos + 4);
    1429             : 
    1430           3 :         pos = os_strstr(param, "cf2=");
    1431           3 :         if (pos)
    1432           0 :                 data.dfs_event.cf2 = atoi(pos + 4);
    1433             : 
    1434           3 :         wpa_supplicant_event(hapd, event, &data);
    1435             : 
    1436           3 :         return 0;
    1437             : }
    1438             : 
    1439             : 
    1440         259 : static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
    1441             : {
    1442             :         size_t len;
    1443             :         u8 *buf;
    1444             :         int res;
    1445             : 
    1446         259 :         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
    1447             : 
    1448         259 :         len = os_strlen(cmd);
    1449         259 :         if (len & 1)
    1450           0 :                 return -1;
    1451         259 :         len /= 2;
    1452             : 
    1453         259 :         buf = os_malloc(len);
    1454         259 :         if (buf == NULL)
    1455           0 :                 return -1;
    1456             : 
    1457         259 :         if (hexstr2bin(cmd, buf, len) < 0) {
    1458           0 :                 os_free(buf);
    1459           0 :                 return -1;
    1460             :         }
    1461             : 
    1462         259 :         res = hostapd_drv_send_mlme(hapd, buf, len, 0);
    1463         259 :         os_free(buf);
    1464         259 :         return res;
    1465             : }
    1466             : 
    1467             : 
    1468          38 : static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
    1469             : {
    1470             :         char *pos;
    1471             :         u8 src[ETH_ALEN], *buf;
    1472             :         int used;
    1473             :         size_t len;
    1474             : 
    1475          38 :         wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
    1476             : 
    1477          38 :         pos = cmd;
    1478          38 :         used = hwaddr_aton2(pos, src);
    1479          38 :         if (used < 0)
    1480           0 :                 return -1;
    1481          38 :         pos += used;
    1482         114 :         while (*pos == ' ')
    1483          38 :                 pos++;
    1484             : 
    1485          38 :         len = os_strlen(pos);
    1486          38 :         if (len & 1)
    1487           0 :                 return -1;
    1488          38 :         len /= 2;
    1489             : 
    1490          38 :         buf = os_malloc(len);
    1491          38 :         if (buf == NULL)
    1492           0 :                 return -1;
    1493             : 
    1494          38 :         if (hexstr2bin(pos, buf, len) < 0) {
    1495           0 :                 os_free(buf);
    1496           0 :                 return -1;
    1497             :         }
    1498             : 
    1499          38 :         ieee802_1x_receive(hapd, src, buf, len);
    1500          38 :         os_free(buf);
    1501             : 
    1502          38 :         return 0;
    1503             : }
    1504             : 
    1505             : 
    1506        1012 : static u16 ipv4_hdr_checksum(const void *buf, size_t len)
    1507             : {
    1508             :         size_t i;
    1509        1012 :         u32 sum = 0;
    1510        1012 :         const u16 *pos = buf;
    1511             : 
    1512       11132 :         for (i = 0; i < len / 2; i++)
    1513       10120 :                 sum += *pos++;
    1514             : 
    1515        3036 :         while (sum >> 16)
    1516        1012 :                 sum = (sum & 0xffff) + (sum >> 16);
    1517             : 
    1518        1012 :         return sum ^ 0xffff;
    1519             : }
    1520             : 
    1521             : 
    1522             : #define HWSIM_PACKETLEN 1500
    1523             : #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
    1524             : 
    1525        1012 : void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
    1526             :                           size_t len)
    1527             : {
    1528        1012 :         struct hostapd_data *hapd = ctx;
    1529             :         const struct ether_header *eth;
    1530             :         const struct iphdr *ip;
    1531             :         const u8 *pos;
    1532             :         unsigned int i;
    1533             : 
    1534        1012 :         if (len != HWSIM_PACKETLEN)
    1535           0 :                 return;
    1536             : 
    1537        1012 :         eth = (const struct ether_header *) buf;
    1538        1012 :         ip = (const struct iphdr *) (eth + 1);
    1539        1012 :         pos = (const u8 *) (ip + 1);
    1540             : 
    1541        2024 :         if (ip->ihl != 5 || ip->version != 4 ||
    1542        1012 :             ntohs(ip->tot_len) != HWSIM_IP_LEN)
    1543           0 :                 return;
    1544             : 
    1545     1484604 :         for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) {
    1546     1483592 :                 if (*pos != (u8) i)
    1547           0 :                         return;
    1548     1483592 :                 pos++;
    1549             :         }
    1550             : 
    1551       12144 :         wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
    1552       12144 :                 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
    1553             : }
    1554             : 
    1555             : 
    1556         920 : static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
    1557             :                                                char *cmd)
    1558             : {
    1559         920 :         int enabled = atoi(cmd);
    1560             :         char *pos;
    1561             :         const char *ifname;
    1562             : 
    1563         920 :         if (!enabled) {
    1564         460 :                 if (hapd->l2_test) {
    1565         460 :                         l2_packet_deinit(hapd->l2_test);
    1566         460 :                         hapd->l2_test = NULL;
    1567         460 :                         wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
    1568             :                                 "test data: Disabled");
    1569             :                 }
    1570         460 :                 return 0;
    1571             :         }
    1572             : 
    1573         460 :         if (hapd->l2_test)
    1574           0 :                 return 0;
    1575             : 
    1576         460 :         pos = os_strstr(cmd, " ifname=");
    1577         460 :         if (pos)
    1578          21 :                 ifname = pos + 8;
    1579             :         else
    1580         439 :                 ifname = hapd->conf->iface;
    1581             : 
    1582         460 :         hapd->l2_test = l2_packet_init(ifname, hapd->own_addr,
    1583             :                                         ETHERTYPE_IP, hostapd_data_test_rx,
    1584             :                                         hapd, 1);
    1585         460 :         if (hapd->l2_test == NULL)
    1586           0 :                 return -1;
    1587             : 
    1588         460 :         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
    1589             : 
    1590         460 :         return 0;
    1591             : }
    1592             : 
    1593             : 
    1594        1012 : static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
    1595             : {
    1596             :         u8 dst[ETH_ALEN], src[ETH_ALEN];
    1597             :         char *pos;
    1598             :         int used;
    1599             :         long int val;
    1600             :         u8 tos;
    1601             :         u8 buf[HWSIM_PACKETLEN];
    1602             :         struct ether_header *eth;
    1603             :         struct iphdr *ip;
    1604             :         u8 *dpos;
    1605             :         unsigned int i;
    1606             : 
    1607        1012 :         if (hapd->l2_test == NULL)
    1608           0 :                 return -1;
    1609             : 
    1610             :         /* format: <dst> <src> <tos> */
    1611             : 
    1612        1012 :         pos = cmd;
    1613        1012 :         used = hwaddr_aton2(pos, dst);
    1614        1012 :         if (used < 0)
    1615           0 :                 return -1;
    1616        1012 :         pos += used;
    1617        3036 :         while (*pos == ' ')
    1618        1012 :                 pos++;
    1619        1012 :         used = hwaddr_aton2(pos, src);
    1620        1012 :         if (used < 0)
    1621           0 :                 return -1;
    1622        1012 :         pos += used;
    1623             : 
    1624        1012 :         val = strtol(pos, NULL, 0);
    1625        1012 :         if (val < 0 || val > 0xff)
    1626           0 :                 return -1;
    1627        1012 :         tos = val;
    1628             : 
    1629        1012 :         eth = (struct ether_header *) buf;
    1630        1012 :         os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
    1631        1012 :         os_memcpy(eth->ether_shost, src, ETH_ALEN);
    1632        1012 :         eth->ether_type = htons(ETHERTYPE_IP);
    1633        1012 :         ip = (struct iphdr *) (eth + 1);
    1634        1012 :         os_memset(ip, 0, sizeof(*ip));
    1635        1012 :         ip->ihl = 5;
    1636        1012 :         ip->version = 4;
    1637        1012 :         ip->ttl = 64;
    1638        1012 :         ip->tos = tos;
    1639        1012 :         ip->tot_len = htons(HWSIM_IP_LEN);
    1640        1012 :         ip->protocol = 1;
    1641        1012 :         ip->saddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 1);
    1642        1012 :         ip->daddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 2);
    1643        1012 :         ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
    1644        1012 :         dpos = (u8 *) (ip + 1);
    1645     1484604 :         for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
    1646     1483592 :                 *dpos++ = i;
    1647             : 
    1648        1012 :         if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, buf,
    1649             :                            HWSIM_PACKETLEN) < 0)
    1650           0 :                 return -1;
    1651             : 
    1652        1012 :         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
    1653             :                 " src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
    1654             : 
    1655        1012 :         return 0;
    1656             : }
    1657             : 
    1658             : 
    1659          52 : static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
    1660             :                                               char *cmd)
    1661             : {
    1662             :         u8 *buf;
    1663             :         struct ether_header *eth;
    1664          52 :         struct l2_packet_data *l2 = NULL;
    1665             :         size_t len;
    1666             :         u16 ethertype;
    1667          52 :         int res = -1;
    1668          52 :         const char *ifname = hapd->conf->iface;
    1669             : 
    1670          52 :         if (os_strncmp(cmd, "ifname=", 7) == 0) {
    1671          52 :                 cmd += 7;
    1672          52 :                 ifname = cmd;
    1673          52 :                 cmd = os_strchr(cmd, ' ');
    1674          52 :                 if (cmd == NULL)
    1675           0 :                         return -1;
    1676          52 :                 *cmd++ = '\0';
    1677             :         }
    1678             : 
    1679          52 :         len = os_strlen(cmd);
    1680          52 :         if (len & 1 || len < ETH_HLEN * 2)
    1681           0 :                 return -1;
    1682          52 :         len /= 2;
    1683             : 
    1684          52 :         buf = os_malloc(len);
    1685          52 :         if (buf == NULL)
    1686           0 :                 return -1;
    1687             : 
    1688          52 :         if (hexstr2bin(cmd, buf, len) < 0)
    1689           0 :                 goto done;
    1690             : 
    1691          52 :         eth = (struct ether_header *) buf;
    1692          52 :         ethertype = ntohs(eth->ether_type);
    1693             : 
    1694          52 :         l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
    1695             :                             hostapd_data_test_rx, hapd, 1);
    1696          52 :         if (l2 == NULL)
    1697           0 :                 goto done;
    1698             : 
    1699          52 :         res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
    1700          52 :         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
    1701             : done:
    1702          52 :         if (l2)
    1703          52 :                 l2_packet_deinit(l2);
    1704          52 :         os_free(buf);
    1705             : 
    1706          52 :         return res < 0 ? -1 : 0;
    1707             : }
    1708             : 
    1709             : 
    1710         670 : static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
    1711             : {
    1712             : #ifdef WPA_TRACE_BFD
    1713             :         extern char wpa_trace_fail_func[256];
    1714             :         extern unsigned int wpa_trace_fail_after;
    1715             :         char *pos;
    1716             : 
    1717         670 :         wpa_trace_fail_after = atoi(cmd);
    1718         670 :         pos = os_strchr(cmd, ':');
    1719         670 :         if (pos) {
    1720         670 :                 pos++;
    1721         670 :                 os_strlcpy(wpa_trace_fail_func, pos,
    1722             :                            sizeof(wpa_trace_fail_func));
    1723             :         } else {
    1724           0 :                 wpa_trace_fail_after = 0;
    1725             :         }
    1726             : 
    1727         670 :         return 0;
    1728             : #else /* WPA_TRACE_BFD */
    1729             :         return -1;
    1730             : #endif /* WPA_TRACE_BFD */
    1731             : }
    1732             : 
    1733             : 
    1734         372 : static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
    1735             :                                        char *buf, size_t buflen)
    1736             : {
    1737             : #ifdef WPA_TRACE_BFD
    1738             :         extern char wpa_trace_fail_func[256];
    1739             :         extern unsigned int wpa_trace_fail_after;
    1740             : 
    1741         372 :         return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
    1742             :                            wpa_trace_fail_func);
    1743             : #else /* WPA_TRACE_BFD */
    1744             :         return -1;
    1745             : #endif /* WPA_TRACE_BFD */
    1746             : }
    1747             : 
    1748             : #endif /* CONFIG_TESTING_OPTIONS */
    1749             : 
    1750             : 
    1751          23 : static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
    1752             :                                           char *pos)
    1753             : {
    1754             : #ifdef NEED_AP_MLME
    1755             :         struct csa_settings settings;
    1756             :         int ret;
    1757             :         unsigned int i;
    1758             : 
    1759          23 :         ret = hostapd_parse_csa_settings(pos, &settings);
    1760          23 :         if (ret)
    1761           3 :                 return ret;
    1762             : 
    1763          38 :         for (i = 0; i < iface->num_bss; i++) {
    1764          20 :                 ret = hostapd_switch_channel(iface->bss[i], &settings);
    1765          20 :                 if (ret) {
    1766             :                         /* FIX: What do we do if CSA fails in the middle of
    1767             :                          * submitting multi-BSS CSA requests? */
    1768           2 :                         return ret;
    1769             :                 }
    1770             :         }
    1771             : 
    1772          18 :         return 0;
    1773             : #else /* NEED_AP_MLME */
    1774             :         return -1;
    1775             : #endif /* NEED_AP_MLME */
    1776             : }
    1777             : 
    1778             : 
    1779           8 : static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
    1780             :                                   int reply_size, const char *param)
    1781             : {
    1782             : #ifdef RADIUS_SERVER
    1783           8 :         if (os_strcmp(param, "radius_server") == 0) {
    1784           8 :                 return radius_server_get_mib(hapd->radius_srv, reply,
    1785             :                                              reply_size);
    1786             :         }
    1787             : #endif /* RADIUS_SERVER */
    1788           0 :         return -1;
    1789             : }
    1790             : 
    1791             : 
    1792           1 : static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
    1793             :                                      char *buf, size_t buflen)
    1794             : {
    1795             :         int ret;
    1796             :         char *pos;
    1797           1 :         u8 *data = NULL;
    1798             :         unsigned int vendor_id, subcmd;
    1799             :         struct wpabuf *reply;
    1800           1 :         size_t data_len = 0;
    1801             : 
    1802             :         /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
    1803           1 :         vendor_id = strtoul(cmd, &pos, 16);
    1804           1 :         if (!isblank(*pos))
    1805           0 :                 return -EINVAL;
    1806             : 
    1807           1 :         subcmd = strtoul(pos, &pos, 10);
    1808             : 
    1809           1 :         if (*pos != '\0') {
    1810           1 :                 if (!isblank(*pos++))
    1811           0 :                         return -EINVAL;
    1812           1 :                 data_len = os_strlen(pos);
    1813             :         }
    1814             : 
    1815           1 :         if (data_len) {
    1816           1 :                 data_len /= 2;
    1817           1 :                 data = os_malloc(data_len);
    1818           1 :                 if (!data)
    1819           0 :                         return -ENOBUFS;
    1820             : 
    1821           1 :                 if (hexstr2bin(pos, data, data_len)) {
    1822           0 :                         wpa_printf(MSG_DEBUG,
    1823             :                                    "Vendor command: wrong parameter format");
    1824           0 :                         os_free(data);
    1825           0 :                         return -EINVAL;
    1826             :                 }
    1827             :         }
    1828             : 
    1829           1 :         reply = wpabuf_alloc((buflen - 1) / 2);
    1830           1 :         if (!reply) {
    1831           0 :                 os_free(data);
    1832           0 :                 return -ENOBUFS;
    1833             :         }
    1834             : 
    1835           1 :         ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
    1836             :                                      reply);
    1837             : 
    1838           1 :         if (ret == 0)
    1839           1 :                 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
    1840             :                                        wpabuf_len(reply));
    1841             : 
    1842           1 :         wpabuf_free(reply);
    1843           1 :         os_free(data);
    1844             : 
    1845           1 :         return ret;
    1846             : }
    1847             : 
    1848             : 
    1849       24752 : static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
    1850             :                                        void *sock_ctx)
    1851             : {
    1852       24752 :         struct hostapd_data *hapd = eloop_ctx;
    1853             :         char buf[4096];
    1854             :         int res;
    1855             :         struct sockaddr_un from;
    1856       24752 :         socklen_t fromlen = sizeof(from);
    1857             :         char *reply;
    1858       24752 :         const int reply_size = 4096;
    1859             :         int reply_len;
    1860       24752 :         int level = MSG_DEBUG;
    1861             : 
    1862       24752 :         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
    1863             :                        (struct sockaddr *) &from, &fromlen);
    1864       24752 :         if (res < 0) {
    1865           0 :                 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
    1866           0 :                            strerror(errno));
    1867           0 :                 return;
    1868             :         }
    1869       24752 :         buf[res] = '\0';
    1870       24752 :         if (os_strcmp(buf, "PING") == 0)
    1871        1048 :                 level = MSG_EXCESSIVE;
    1872       24752 :         wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
    1873             : 
    1874       24752 :         reply = os_malloc(reply_size);
    1875       24752 :         if (reply == NULL) {
    1876          55 :                 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
    1877             :                            fromlen) < 0) {
    1878           0 :                         wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
    1879           0 :                                    strerror(errno));
    1880             :                 }
    1881          55 :                 return;
    1882             :         }
    1883             : 
    1884       24697 :         os_memcpy(reply, "OK\n", 3);
    1885       24697 :         reply_len = 3;
    1886             : 
    1887       24697 :         if (os_strcmp(buf, "PING") == 0) {
    1888        1045 :                 os_memcpy(reply, "PONG\n", 5);
    1889        1045 :                 reply_len = 5;
    1890       23652 :         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
    1891           0 :                 if (wpa_debug_reopen_file() < 0)
    1892           0 :                         reply_len = -1;
    1893       23652 :         } else if (os_strcmp(buf, "STATUS") == 0) {
    1894         370 :                 reply_len = hostapd_ctrl_iface_status(hapd, reply,
    1895             :                                                       reply_size);
    1896       23282 :         } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
    1897          17 :                 reply_len = hostapd_drv_status(hapd, reply, reply_size);
    1898       23265 :         } else if (os_strcmp(buf, "MIB") == 0) {
    1899           8 :                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
    1900           8 :                 if (reply_len >= 0) {
    1901           8 :                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
    1902           8 :                                           reply_size - reply_len);
    1903           8 :                         if (res < 0)
    1904           0 :                                 reply_len = -1;
    1905             :                         else
    1906           8 :                                 reply_len += res;
    1907             :                 }
    1908           8 :                 if (reply_len >= 0) {
    1909           8 :                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
    1910           8 :                                                  reply_size - reply_len);
    1911           8 :                         if (res < 0)
    1912           0 :                                 reply_len = -1;
    1913             :                         else
    1914           8 :                                 reply_len += res;
    1915             :                 }
    1916             : #ifndef CONFIG_NO_RADIUS
    1917           8 :                 if (reply_len >= 0) {
    1918           8 :                         res = radius_client_get_mib(hapd->radius,
    1919             :                                                     reply + reply_len,
    1920           8 :                                                     reply_size - reply_len);
    1921           8 :                         if (res < 0)
    1922           0 :                                 reply_len = -1;
    1923             :                         else
    1924           8 :                                 reply_len += res;
    1925             :                 }
    1926             : #endif /* CONFIG_NO_RADIUS */
    1927       23257 :         } else if (os_strncmp(buf, "MIB ", 4) == 0) {
    1928           8 :                 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
    1929             :                                                    buf + 4);
    1930       23249 :         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
    1931           1 :                 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
    1932             :                                                          reply_size);
    1933       23248 :         } else if (os_strncmp(buf, "STA ", 4) == 0) {
    1934          53 :                 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
    1935             :                                                    reply_size);
    1936       23195 :         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
    1937           4 :                 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
    1938             :                                                         reply_size);
    1939       23191 :         } else if (os_strcmp(buf, "ATTACH") == 0) {
    1940        1329 :                 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
    1941           3 :                         reply_len = -1;
    1942       21862 :         } else if (os_strcmp(buf, "DETACH") == 0) {
    1943        1236 :                 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
    1944           1 :                         reply_len = -1;
    1945       20626 :         } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
    1946           1 :                 if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
    1947             :                                                     buf + 6))
    1948           1 :                         reply_len = -1;
    1949       20625 :         } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
    1950           2 :                 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
    1951           1 :                         reply_len = -1;
    1952       20623 :         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
    1953          14 :                 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
    1954           1 :                         reply_len = -1;
    1955       20609 :         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
    1956           3 :                 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
    1957           1 :                         reply_len = -1;
    1958             : #ifdef CONFIG_IEEE80211W
    1959             : #ifdef NEED_AP_MLME
    1960       20606 :         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
    1961           2 :                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
    1962           0 :                         reply_len = -1;
    1963             : #endif /* NEED_AP_MLME */
    1964             : #endif /* CONFIG_IEEE80211W */
    1965             : #ifdef CONFIG_WPS
    1966       20604 :         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
    1967          20 :                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
    1968           1 :                         reply_len = -1;
    1969       20584 :         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
    1970           9 :                 reply_len = hostapd_ctrl_iface_wps_check_pin(
    1971             :                         hapd, buf + 14, reply, reply_size);
    1972       20575 :         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
    1973          35 :                 if (hostapd_wps_button_pushed(hapd, NULL))
    1974           4 :                         reply_len = -1;
    1975       20540 :         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
    1976           4 :                 if (hostapd_wps_cancel(hapd))
    1977           1 :                         reply_len = -1;
    1978       20536 :         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
    1979          11 :                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
    1980             :                                                           reply, reply_size);
    1981       20525 :         } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
    1982           2 :                 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
    1983           0 :                         reply_len = -1;
    1984       20523 :         } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
    1985           5 :                 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
    1986             :                                                               reply_size);
    1987             : #ifdef CONFIG_WPS_NFC
    1988       20518 :         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
    1989           2 :                 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
    1990           0 :                         reply_len = -1;
    1991       20516 :         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
    1992           2 :                 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
    1993             :                         hapd, buf + 21, reply, reply_size);
    1994       20514 :         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
    1995           6 :                 reply_len = hostapd_ctrl_iface_wps_nfc_token(
    1996             :                         hapd, buf + 14, reply, reply_size);
    1997       20508 :         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
    1998           8 :                 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
    1999             :                         hapd, buf + 21, reply, reply_size);
    2000       20500 :         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
    2001          17 :                 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
    2002          10 :                         reply_len = -1;
    2003             : #endif /* CONFIG_WPS_NFC */
    2004             : #endif /* CONFIG_WPS */
    2005             : #ifdef CONFIG_INTERWORKING
    2006       20483 :         } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
    2007           7 :                 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
    2008           5 :                         reply_len = -1;
    2009       20476 :         } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
    2010           4 :                 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
    2011           3 :                         reply_len = -1;
    2012             : #endif /* CONFIG_INTERWORKING */
    2013             : #ifdef CONFIG_HS20
    2014       20472 :         } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
    2015           7 :                 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
    2016           5 :                         reply_len = -1;
    2017       20465 :         } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
    2018           5 :                 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
    2019           3 :                         reply_len = -1;
    2020             : #endif /* CONFIG_HS20 */
    2021             : #ifdef CONFIG_WNM
    2022       20460 :         } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
    2023           5 :                 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
    2024           3 :                         reply_len = -1;
    2025       20455 :         } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
    2026           8 :                 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
    2027           5 :                         reply_len = -1;
    2028       20447 :         } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
    2029           5 :                 if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
    2030           0 :                         reply_len = -1;
    2031             : #endif /* CONFIG_WNM */
    2032       20442 :         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
    2033          11 :                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
    2034             :                                                           reply_size);
    2035       20431 :         } else if (os_strncmp(buf, "SET ", 4) == 0) {
    2036       16039 :                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
    2037         175 :                         reply_len = -1;
    2038        4392 :         } else if (os_strncmp(buf, "GET ", 4) == 0) {
    2039           3 :                 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
    2040             :                                                    reply_size);
    2041        4389 :         } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
    2042         961 :                 if (hostapd_ctrl_iface_enable(hapd->iface))
    2043          36 :                         reply_len = -1;
    2044        3428 :         } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
    2045           1 :                 if (hostapd_ctrl_iface_reload(hapd->iface))
    2046           0 :                         reply_len = -1;
    2047        3427 :         } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
    2048          75 :                 if (hostapd_ctrl_iface_disable(hapd->iface))
    2049           9 :                         reply_len = -1;
    2050             : #ifdef CONFIG_TESTING_OPTIONS
    2051        3352 :         } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
    2052           3 :                 if (hostapd_ctrl_iface_radar(hapd, buf + 6))
    2053           0 :                         reply_len = -1;
    2054        3349 :         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
    2055         259 :                 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
    2056           0 :                         reply_len = -1;
    2057        3090 :         } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
    2058          38 :                 if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
    2059           0 :                         reply_len = -1;
    2060        3052 :         } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
    2061         920 :                 if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
    2062           0 :                         reply_len = -1;
    2063        2132 :         } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
    2064        1012 :                 if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
    2065           0 :                         reply_len = -1;
    2066        1120 :         } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
    2067          52 :                 if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
    2068           0 :                         reply_len = -1;
    2069        1068 :         } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
    2070         670 :                 if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
    2071           0 :                         reply_len = -1;
    2072         398 :         } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
    2073         372 :                 reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
    2074             :                                                         reply_size);
    2075             : #endif /* CONFIG_TESTING_OPTIONS */
    2076          26 :         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
    2077          23 :                 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
    2078           5 :                         reply_len = -1;
    2079           3 :         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
    2080           1 :                 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
    2081             :                                                       reply_size);
    2082           2 :         } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
    2083           1 :                 ieee802_1x_erp_flush(hapd);
    2084             : #ifdef RADIUS_SERVER
    2085           1 :                 radius_server_erp_flush(hapd->radius_srv);
    2086             : #endif /* RADIUS_SERVER */
    2087             :         } else {
    2088           1 :                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
    2089           1 :                 reply_len = 16;
    2090             :         }
    2091             : 
    2092       24697 :         if (reply_len < 0) {
    2093         285 :                 os_memcpy(reply, "FAIL\n", 5);
    2094         285 :                 reply_len = 5;
    2095             :         }
    2096       24697 :         if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
    2097             :                    fromlen) < 0) {
    2098           6 :                 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
    2099           6 :                            strerror(errno));
    2100             :         }
    2101       24697 :         os_free(reply);
    2102             : }
    2103             : 
    2104             : 
    2105        2149 : static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
    2106             : {
    2107             :         char *buf;
    2108             :         size_t len;
    2109             : 
    2110        2149 :         if (hapd->conf->ctrl_interface == NULL)
    2111           0 :                 return NULL;
    2112             : 
    2113        4298 :         len = os_strlen(hapd->conf->ctrl_interface) +
    2114        2149 :                 os_strlen(hapd->conf->iface) + 2;
    2115        2149 :         buf = os_malloc(len);
    2116        2149 :         if (buf == NULL)
    2117           7 :                 return NULL;
    2118             : 
    2119        2142 :         os_snprintf(buf, len, "%s/%s",
    2120        2142 :                     hapd->conf->ctrl_interface, hapd->conf->iface);
    2121        2142 :         buf[len - 1] = '\0';
    2122        2142 :         return buf;
    2123             : }
    2124             : 
    2125             : 
    2126       57724 : static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global,
    2127             :                                       const char *txt, size_t len)
    2128             : {
    2129       57724 :         struct hostapd_data *hapd = ctx;
    2130       57724 :         if (hapd == NULL)
    2131       57724 :                 return;
    2132       57724 :         hostapd_ctrl_iface_send(hapd, level, txt, len);
    2133             : }
    2134             : 
    2135             : 
    2136        2019 : int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
    2137             : {
    2138             :         struct sockaddr_un addr;
    2139        2019 :         int s = -1;
    2140        2019 :         char *fname = NULL;
    2141             : 
    2142        2019 :         if (hapd->ctrl_sock > -1) {
    2143         943 :                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
    2144         943 :                 return 0;
    2145             :         }
    2146             : 
    2147        1076 :         if (hapd->conf->ctrl_interface == NULL)
    2148           0 :                 return 0;
    2149             : 
    2150        1076 :         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
    2151        1071 :                 if (errno == EEXIST) {
    2152        1071 :                         wpa_printf(MSG_DEBUG, "Using existing control "
    2153             :                                    "interface directory.");
    2154             :                 } else {
    2155           0 :                         wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
    2156           0 :                                    strerror(errno));
    2157           0 :                         goto fail;
    2158             :                 }
    2159             :         }
    2160             : 
    2161        1086 :         if (hapd->conf->ctrl_interface_gid_set &&
    2162          10 :             chown(hapd->conf->ctrl_interface, -1,
    2163          10 :                   hapd->conf->ctrl_interface_gid) < 0) {
    2164           0 :                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
    2165           0 :                            strerror(errno));
    2166           0 :                 return -1;
    2167             :         }
    2168             : 
    2169        2142 :         if (!hapd->conf->ctrl_interface_gid_set &&
    2170        1066 :             hapd->iface->interfaces->ctrl_iface_group &&
    2171           0 :             chown(hapd->conf->ctrl_interface, -1,
    2172           0 :                   hapd->iface->interfaces->ctrl_iface_group) < 0) {
    2173           0 :                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
    2174           0 :                            strerror(errno));
    2175           0 :                 return -1;
    2176             :         }
    2177             : 
    2178             : #ifdef ANDROID
    2179             :         /*
    2180             :          * Android is using umask 0077 which would leave the control interface
    2181             :          * directory without group access. This breaks things since Wi-Fi
    2182             :          * framework assumes that this directory can be accessed by other
    2183             :          * applications in the wifi group. Fix this by adding group access even
    2184             :          * if umask value would prevent this.
    2185             :          */
    2186             :         if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
    2187             :                 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
    2188             :                            strerror(errno));
    2189             :                 /* Try to continue anyway */
    2190             :         }
    2191             : #endif /* ANDROID */
    2192             : 
    2193        2152 :         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
    2194        1076 :             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
    2195           0 :                 goto fail;
    2196             : 
    2197        1076 :         s = socket(PF_UNIX, SOCK_DGRAM, 0);
    2198        1076 :         if (s < 0) {
    2199           0 :                 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
    2200           0 :                 goto fail;
    2201             :         }
    2202             : 
    2203        1076 :         os_memset(&addr, 0, sizeof(addr));
    2204             : #ifdef __FreeBSD__
    2205             :         addr.sun_len = sizeof(addr);
    2206             : #endif /* __FreeBSD__ */
    2207        1076 :         addr.sun_family = AF_UNIX;
    2208        1076 :         fname = hostapd_ctrl_iface_path(hapd);
    2209        1076 :         if (fname == NULL)
    2210           3 :                 goto fail;
    2211        1073 :         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
    2212        1073 :         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    2213           4 :                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
    2214           4 :                            strerror(errno));
    2215           4 :                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    2216           4 :                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
    2217             :                                    " allow connections - assuming it was left"
    2218             :                                    "over from forced program termination");
    2219           4 :                         if (unlink(fname) < 0) {
    2220           0 :                                 wpa_printf(MSG_ERROR,
    2221             :                                            "Could not unlink existing ctrl_iface socket '%s': %s",
    2222           0 :                                            fname, strerror(errno));
    2223           0 :                                 goto fail;
    2224             :                         }
    2225           4 :                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
    2226             :                             0) {
    2227           0 :                                 wpa_printf(MSG_ERROR,
    2228             :                                            "hostapd-ctrl-iface: bind(PF_UNIX): %s",
    2229           0 :                                            strerror(errno));
    2230           0 :                                 goto fail;
    2231             :                         }
    2232           4 :                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
    2233             :                                    "ctrl_iface socket '%s'", fname);
    2234             :                 } else {
    2235           0 :                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
    2236             :                                    "be in use - cannot override it");
    2237           0 :                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
    2238             :                                    "not used anymore", fname);
    2239           0 :                         os_free(fname);
    2240           0 :                         fname = NULL;
    2241           0 :                         goto fail;
    2242             :                 }
    2243             :         }
    2244             : 
    2245        1083 :         if (hapd->conf->ctrl_interface_gid_set &&
    2246          10 :             chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
    2247           0 :                 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
    2248           0 :                            strerror(errno));
    2249           0 :                 goto fail;
    2250             :         }
    2251             : 
    2252        2136 :         if (!hapd->conf->ctrl_interface_gid_set &&
    2253        1063 :             hapd->iface->interfaces->ctrl_iface_group &&
    2254           0 :             chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
    2255           0 :                 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
    2256           0 :                            strerror(errno));
    2257           0 :                 goto fail;
    2258             :         }
    2259             : 
    2260        1073 :         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
    2261           0 :                 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
    2262           0 :                            strerror(errno));
    2263           0 :                 goto fail;
    2264             :         }
    2265        1073 :         os_free(fname);
    2266             : 
    2267        1073 :         hapd->ctrl_sock = s;
    2268        1073 :         if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
    2269             :                                      NULL) < 0) {
    2270           0 :                 hostapd_ctrl_iface_deinit(hapd);
    2271           0 :                 return -1;
    2272             :         }
    2273        1073 :         hapd->msg_ctx = hapd;
    2274        1073 :         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
    2275             : 
    2276        1073 :         return 0;
    2277             : 
    2278             : fail:
    2279           3 :         if (s >= 0)
    2280           3 :                 close(s);
    2281           3 :         if (fname) {
    2282           0 :                 unlink(fname);
    2283           0 :                 os_free(fname);
    2284             :         }
    2285           3 :         return -1;
    2286             : }
    2287             : 
    2288             : 
    2289        1080 : void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
    2290             : {
    2291             :         struct wpa_ctrl_dst *dst, *prev;
    2292             : 
    2293        1080 :         if (hapd->ctrl_sock > -1) {
    2294             :                 char *fname;
    2295        1073 :                 eloop_unregister_read_sock(hapd->ctrl_sock);
    2296        1073 :                 close(hapd->ctrl_sock);
    2297        1073 :                 hapd->ctrl_sock = -1;
    2298        1073 :                 fname = hostapd_ctrl_iface_path(hapd);
    2299        1073 :                 if (fname)
    2300        1069 :                         unlink(fname);
    2301        1073 :                 os_free(fname);
    2302             : 
    2303        2146 :                 if (hapd->conf->ctrl_interface &&
    2304        1073 :                     rmdir(hapd->conf->ctrl_interface) < 0) {
    2305        1068 :                         if (errno == ENOTEMPTY) {
    2306        1068 :                                 wpa_printf(MSG_DEBUG, "Control interface "
    2307             :                                            "directory not empty - leaving it "
    2308             :                                            "behind");
    2309             :                         } else {
    2310           0 :                                 wpa_printf(MSG_ERROR,
    2311             :                                            "rmdir[ctrl_interface=%s]: %s",
    2312           0 :                                            hapd->conf->ctrl_interface,
    2313           0 :                                            strerror(errno));
    2314             :                         }
    2315             :                 }
    2316             :         }
    2317             : 
    2318        1080 :         dst = hapd->ctrl_dst;
    2319        1080 :         hapd->ctrl_dst = NULL;
    2320        2250 :         while (dst) {
    2321          90 :                 prev = dst;
    2322          90 :                 dst = dst->next;
    2323          90 :                 os_free(prev);
    2324             :         }
    2325             : 
    2326             : #ifdef CONFIG_TESTING_OPTIONS
    2327        1080 :         l2_packet_deinit(hapd->l2_test);
    2328        1080 :         hapd->l2_test = NULL;
    2329             : #endif /* CONFIG_TESTING_OPTIONS */
    2330        1080 : }
    2331             : 
    2332             : 
    2333        1100 : static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
    2334             :                                   char *buf)
    2335             : {
    2336        1100 :         if (hostapd_add_iface(interfaces, buf) < 0) {
    2337          45 :                 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
    2338          45 :                 return -1;
    2339             :         }
    2340        1055 :         return 0;
    2341             : }
    2342             : 
    2343             : 
    2344        5405 : static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
    2345             :                                      char *buf)
    2346             : {
    2347        5405 :         if (hostapd_remove_iface(interfaces, buf) < 0) {
    2348        4347 :                 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
    2349        4347 :                 return -1;
    2350             :         }
    2351        1058 :         return 0;
    2352             : }
    2353             : 
    2354             : 
    2355        1088 : static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
    2356             : {
    2357             : #ifdef CONFIG_WPS_TESTING
    2358        1088 :         wps_version_number = 0x20;
    2359        1088 :         wps_testing_dummy_cred = 0;
    2360        1088 :         wps_corrupt_pkhash = 0;
    2361             : #endif /* CONFIG_WPS_TESTING */
    2362        1088 : }
    2363             : 
    2364             : 
    2365        8644 : static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
    2366             :                                               void *sock_ctx)
    2367             : {
    2368        8644 :         void *interfaces = eloop_ctx;
    2369             :         char buf[256];
    2370             :         int res;
    2371             :         struct sockaddr_un from;
    2372        8644 :         socklen_t fromlen = sizeof(from);
    2373             :         char reply[24];
    2374             :         int reply_len;
    2375             : 
    2376        8644 :         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
    2377             :                        (struct sockaddr *) &from, &fromlen);
    2378        8644 :         if (res < 0) {
    2379           0 :                 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
    2380           0 :                            strerror(errno));
    2381        8644 :                 return;
    2382             :         }
    2383        8644 :         buf[res] = '\0';
    2384        8644 :         wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
    2385             : 
    2386        8644 :         os_memcpy(reply, "OK\n", 3);
    2387        8644 :         reply_len = 3;
    2388             : 
    2389        8644 :         if (os_strcmp(buf, "PING") == 0) {
    2390           5 :                 os_memcpy(reply, "PONG\n", 5);
    2391           5 :                 reply_len = 5;
    2392        8639 :         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
    2393        1045 :                 if (wpa_debug_reopen_file() < 0)
    2394           0 :                         reply_len = -1;
    2395        7594 :         } else if (os_strcmp(buf, "FLUSH") == 0) {
    2396        1088 :                 hostapd_ctrl_iface_flush(interfaces);
    2397        6506 :         } else if (os_strncmp(buf, "ADD ", 4) == 0) {
    2398        1100 :                 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
    2399          45 :                         reply_len = -1;
    2400        5406 :         } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
    2401        5405 :                 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
    2402        4347 :                         reply_len = -1;
    2403             : #ifdef CONFIG_MODULE_TESTS
    2404           1 :         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
    2405             :                 int hapd_module_tests(void);
    2406           1 :                 if (hapd_module_tests() < 0)
    2407           0 :                         reply_len = -1;
    2408             : #endif /* CONFIG_MODULE_TESTS */
    2409             :         } else {
    2410           0 :                 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
    2411             :                            "ignored");
    2412           0 :                 reply_len = -1;
    2413             :         }
    2414             : 
    2415        8644 :         if (reply_len < 0) {
    2416        4392 :                 os_memcpy(reply, "FAIL\n", 5);
    2417        4392 :                 reply_len = 5;
    2418             :         }
    2419             : 
    2420        8644 :         if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
    2421             :                    fromlen) < 0) {
    2422           0 :                 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
    2423           0 :                            strerror(errno));
    2424             :         }
    2425             : }
    2426             : 
    2427             : 
    2428          10 : static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
    2429             : {
    2430             :         char *buf;
    2431             :         size_t len;
    2432             : 
    2433          10 :         if (interface->global_iface_path == NULL)
    2434           0 :                 return NULL;
    2435             : 
    2436          20 :         len = os_strlen(interface->global_iface_path) +
    2437          10 :                 os_strlen(interface->global_iface_name) + 2;
    2438          10 :         buf = os_malloc(len);
    2439          10 :         if (buf == NULL)
    2440           0 :                 return NULL;
    2441             : 
    2442          10 :         os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
    2443             :                     interface->global_iface_name);
    2444          10 :         buf[len - 1] = '\0';
    2445          10 :         return buf;
    2446             : }
    2447             : 
    2448             : 
    2449          10 : int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
    2450             : {
    2451             :         struct sockaddr_un addr;
    2452          10 :         int s = -1;
    2453          10 :         char *fname = NULL;
    2454             : 
    2455          10 :         if (interface->global_iface_path == NULL) {
    2456           5 :                 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
    2457           5 :                 return 0;
    2458             :         }
    2459             : 
    2460           5 :         if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
    2461           5 :                 if (errno == EEXIST) {
    2462           5 :                         wpa_printf(MSG_DEBUG, "Using existing control "
    2463             :                                    "interface directory.");
    2464             :                 } else {
    2465           0 :                         wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
    2466           0 :                                    strerror(errno));
    2467           0 :                         goto fail;
    2468             :                 }
    2469           0 :         } else if (interface->ctrl_iface_group &&
    2470           0 :                    chown(interface->global_iface_path, -1,
    2471             :                          interface->ctrl_iface_group) < 0) {
    2472           0 :                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
    2473           0 :                            strerror(errno));
    2474           0 :                 goto fail;
    2475             :         }
    2476             : 
    2477          10 :         if (os_strlen(interface->global_iface_path) + 1 +
    2478           5 :             os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
    2479           0 :                 goto fail;
    2480             : 
    2481           5 :         s = socket(PF_UNIX, SOCK_DGRAM, 0);
    2482           5 :         if (s < 0) {
    2483           0 :                 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
    2484           0 :                 goto fail;
    2485             :         }
    2486             : 
    2487           5 :         os_memset(&addr, 0, sizeof(addr));
    2488             : #ifdef __FreeBSD__
    2489             :         addr.sun_len = sizeof(addr);
    2490             : #endif /* __FreeBSD__ */
    2491           5 :         addr.sun_family = AF_UNIX;
    2492           5 :         fname = hostapd_global_ctrl_iface_path(interface);
    2493           5 :         if (fname == NULL)
    2494           0 :                 goto fail;
    2495           5 :         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
    2496           5 :         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    2497           0 :                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
    2498           0 :                            strerror(errno));
    2499           0 :                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    2500           0 :                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
    2501             :                                    " allow connections - assuming it was left"
    2502             :                                    "over from forced program termination");
    2503           0 :                         if (unlink(fname) < 0) {
    2504           0 :                                 wpa_printf(MSG_ERROR,
    2505             :                                            "Could not unlink existing ctrl_iface socket '%s': %s",
    2506           0 :                                            fname, strerror(errno));
    2507           0 :                                 goto fail;
    2508             :                         }
    2509           0 :                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
    2510             :                             0) {
    2511           0 :                                 wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
    2512           0 :                                            strerror(errno));
    2513           0 :                                 goto fail;
    2514             :                         }
    2515           0 :                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
    2516             :                                    "ctrl_iface socket '%s'", fname);
    2517             :                 } else {
    2518           0 :                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
    2519             :                                    "be in use - cannot override it");
    2520           0 :                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
    2521             :                                    "not used anymore", fname);
    2522           0 :                         os_free(fname);
    2523           0 :                         fname = NULL;
    2524           0 :                         goto fail;
    2525             :                 }
    2526             :         }
    2527             : 
    2528           5 :         if (interface->ctrl_iface_group &&
    2529           0 :             chown(fname, -1, interface->ctrl_iface_group) < 0) {
    2530           0 :                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
    2531           0 :                            strerror(errno));
    2532           0 :                 goto fail;
    2533             :         }
    2534             : 
    2535           5 :         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
    2536           0 :                 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
    2537           0 :                            strerror(errno));
    2538           0 :                 goto fail;
    2539             :         }
    2540           5 :         os_free(fname);
    2541             : 
    2542           5 :         interface->global_ctrl_sock = s;
    2543           5 :         eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
    2544             :                                  interface, NULL);
    2545             : 
    2546           5 :         return 0;
    2547             : 
    2548             : fail:
    2549           0 :         if (s >= 0)
    2550           0 :                 close(s);
    2551           0 :         if (fname) {
    2552           0 :                 unlink(fname);
    2553           0 :                 os_free(fname);
    2554             :         }
    2555           0 :         return -1;
    2556             : }
    2557             : 
    2558             : 
    2559          10 : void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
    2560             : {
    2561          10 :         char *fname = NULL;
    2562             : 
    2563          10 :         if (interfaces->global_ctrl_sock > -1) {
    2564           5 :                 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
    2565           5 :                 close(interfaces->global_ctrl_sock);
    2566           5 :                 interfaces->global_ctrl_sock = -1;
    2567           5 :                 fname = hostapd_global_ctrl_iface_path(interfaces);
    2568           5 :                 if (fname) {
    2569           5 :                         unlink(fname);
    2570           5 :                         os_free(fname);
    2571             :                 }
    2572             : 
    2573          10 :                 if (interfaces->global_iface_path &&
    2574           5 :                     rmdir(interfaces->global_iface_path) < 0) {
    2575           5 :                         if (errno == ENOTEMPTY) {
    2576           0 :                                 wpa_printf(MSG_DEBUG, "Control interface "
    2577             :                                            "directory not empty - leaving it "
    2578             :                                            "behind");
    2579             :                         } else {
    2580           5 :                                 wpa_printf(MSG_ERROR,
    2581             :                                            "rmdir[ctrl_interface=%s]: %s",
    2582             :                                            interfaces->global_iface_path,
    2583           5 :                                            strerror(errno));
    2584             :                         }
    2585             :                 }
    2586           5 :                 os_free(interfaces->global_iface_path);
    2587           5 :                 interfaces->global_iface_path = NULL;
    2588             :         }
    2589          10 : }
    2590             : 
    2591             : 
    2592       57724 : static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
    2593             :                                     const char *buf, size_t len)
    2594             : {
    2595             :         struct wpa_ctrl_dst *dst, *next;
    2596             :         struct msghdr msg;
    2597             :         int idx;
    2598             :         struct iovec io[2];
    2599             :         char levelstr[10];
    2600             : 
    2601       57724 :         dst = hapd->ctrl_dst;
    2602       57724 :         if (hapd->ctrl_sock < 0 || dst == NULL)
    2603       76317 :                 return;
    2604             : 
    2605       39131 :         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
    2606       39131 :         io[0].iov_base = levelstr;
    2607       39131 :         io[0].iov_len = os_strlen(levelstr);
    2608       39131 :         io[1].iov_base = (char *) buf;
    2609       39131 :         io[1].iov_len = len;
    2610       39131 :         os_memset(&msg, 0, sizeof(msg));
    2611       39131 :         msg.msg_iov = io;
    2612       39131 :         msg.msg_iovlen = 2;
    2613             : 
    2614       39131 :         idx = 0;
    2615      119863 :         while (dst) {
    2616       41601 :                 next = dst->next;
    2617       41601 :                 if (level >= dst->debug_level) {
    2618       14626 :                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
    2619       14626 :                                     (u8 *) dst->addr.sun_path, dst->addrlen -
    2620             :                                     offsetof(struct sockaddr_un, sun_path));
    2621        7313 :                         msg.msg_name = &dst->addr;
    2622        7313 :                         msg.msg_namelen = dst->addrlen;
    2623        7313 :                         if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
    2624           1 :                                 int _errno = errno;
    2625           2 :                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
    2626             :                                            "%d - %s",
    2627           2 :                                            idx, errno, strerror(errno));
    2628           1 :                                 dst->errors++;
    2629           1 :                                 if (dst->errors > 10 || _errno == ENOENT) {
    2630           1 :                                         hostapd_ctrl_iface_detach(
    2631             :                                                 hapd, &dst->addr,
    2632             :                                                 dst->addrlen);
    2633             :                                 }
    2634             :                         } else
    2635        7312 :                                 dst->errors = 0;
    2636             :                 }
    2637       41601 :                 idx++;
    2638       41601 :                 dst = next;
    2639             :         }
    2640             : }
    2641             : 
    2642             : #endif /* CONFIG_NATIVE_WINDOWS */

Generated by: LCOV version 1.10