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

Generated by: LCOV version 1.10