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 1426431149 Lines: 1197 1501 79.7 %
Date: 2015-03-15 Functions: 56 56 100.0 %

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

Generated by: LCOV version 1.10