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 1475438200 Lines: 1552 1920 80.8 %
Date: 2016-10-02 Functions: 77 78 98.7 %

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

Generated by: LCOV version 1.10