LCOV - code coverage report
Current view: top level - wpa_supplicant - ctrl_iface.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1426431149 Lines: 4528 5048 89.7 %
Date: 2015-03-15 Functions: 188 188 100.0 %

          Line data    Source code
       1             : /*
       2             :  * WPA Supplicant / Control interface (shared code for all backends)
       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             : #ifdef CONFIG_TESTING_OPTIONS
      11             : #include <net/ethernet.h>
      12             : #include <netinet/ip.h>
      13             : #endif /* CONFIG_TESTING_OPTIONS */
      14             : 
      15             : #include "utils/common.h"
      16             : #include "utils/eloop.h"
      17             : #include "utils/uuid.h"
      18             : #include "common/version.h"
      19             : #include "common/ieee802_11_defs.h"
      20             : #include "common/ieee802_11_common.h"
      21             : #include "common/wpa_ctrl.h"
      22             : #include "crypto/tls.h"
      23             : #include "ap/hostapd.h"
      24             : #include "eap_peer/eap.h"
      25             : #include "eapol_supp/eapol_supp_sm.h"
      26             : #include "rsn_supp/wpa.h"
      27             : #include "rsn_supp/preauth.h"
      28             : #include "rsn_supp/pmksa_cache.h"
      29             : #include "l2_packet/l2_packet.h"
      30             : #include "wps/wps.h"
      31             : #include "config.h"
      32             : #include "wpa_supplicant_i.h"
      33             : #include "driver_i.h"
      34             : #include "wps_supplicant.h"
      35             : #include "ibss_rsn.h"
      36             : #include "ap.h"
      37             : #include "p2p_supplicant.h"
      38             : #include "p2p/p2p.h"
      39             : #include "hs20_supplicant.h"
      40             : #include "wifi_display.h"
      41             : #include "notify.h"
      42             : #include "bss.h"
      43             : #include "scan.h"
      44             : #include "ctrl_iface.h"
      45             : #include "interworking.h"
      46             : #include "blacklist.h"
      47             : #include "autoscan.h"
      48             : #include "wnm_sta.h"
      49             : #include "offchannel.h"
      50             : #include "drivers/driver.h"
      51             : #include "mesh.h"
      52             : 
      53             : static int wpa_supplicant_global_iface_list(struct wpa_global *global,
      54             :                                             char *buf, int len);
      55             : static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
      56             :                                                   char *buf, int len);
      57             : static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
      58             :                                         char *val);
      59             : 
      60           4 : static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
      61             : {
      62             :         char *pos;
      63           4 :         u8 addr[ETH_ALEN], *filter = NULL, *n;
      64           4 :         size_t count = 0;
      65             : 
      66           4 :         pos = val;
      67          10 :         while (pos) {
      68           5 :                 if (*pos == '\0')
      69           2 :                         break;
      70           3 :                 if (hwaddr_aton(pos, addr)) {
      71           1 :                         os_free(filter);
      72           1 :                         return -1;
      73             :                 }
      74           2 :                 n = os_realloc_array(filter, count + 1, ETH_ALEN);
      75           2 :                 if (n == NULL) {
      76           0 :                         os_free(filter);
      77           0 :                         return -1;
      78             :                 }
      79           2 :                 filter = n;
      80           2 :                 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
      81           2 :                 count++;
      82             : 
      83           2 :                 pos = os_strchr(pos, ' ');
      84           2 :                 if (pos)
      85           1 :                         pos++;
      86             :         }
      87             : 
      88           3 :         wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
      89           3 :         os_free(wpa_s->bssid_filter);
      90           3 :         wpa_s->bssid_filter = filter;
      91           3 :         wpa_s->bssid_filter_count = count;
      92             : 
      93           3 :         return 0;
      94             : }
      95             : 
      96             : 
      97          16 : static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
      98             : {
      99             :         char *pos;
     100          16 :         u8 addr[ETH_ALEN], *bssid = NULL, *n;
     101          16 :         struct wpa_ssid_value *ssid = NULL, *ns;
     102          16 :         size_t count = 0, ssid_count = 0;
     103             :         struct wpa_ssid *c;
     104             : 
     105             :         /*
     106             :          * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
     107             :          * SSID_SPEC ::= ssid <SSID_HEX>
     108             :          * BSSID_SPEC ::= bssid <BSSID_HEX>
     109             :          */
     110             : 
     111          16 :         pos = val;
     112          42 :         while (pos) {
     113          19 :                 if (*pos == '\0')
     114           2 :                         break;
     115          17 :                 if (os_strncmp(pos, "bssid ", 6) == 0) {
     116             :                         int res;
     117           9 :                         pos += 6;
     118           9 :                         res = hwaddr_aton2(pos, addr);
     119           9 :                         if (res < 0) {
     120           2 :                                 os_free(ssid);
     121           2 :                                 os_free(bssid);
     122           2 :                                 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
     123             :                                            "BSSID value '%s'", pos);
     124           2 :                                 return -1;
     125             :                         }
     126           7 :                         pos += res;
     127           7 :                         n = os_realloc_array(bssid, count + 1, ETH_ALEN);
     128           7 :                         if (n == NULL) {
     129           0 :                                 os_free(ssid);
     130           0 :                                 os_free(bssid);
     131           0 :                                 return -1;
     132             :                         }
     133           7 :                         bssid = n;
     134           7 :                         os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
     135           7 :                         count++;
     136           8 :                 } else if (os_strncmp(pos, "ssid ", 5) == 0) {
     137             :                         char *end;
     138           7 :                         pos += 5;
     139             : 
     140           7 :                         end = pos;
     141         118 :                         while (*end) {
     142         105 :                                 if (*end == '\0' || *end == ' ')
     143             :                                         break;
     144         104 :                                 end++;
     145             :                         }
     146             : 
     147           7 :                         ns = os_realloc_array(ssid, ssid_count + 1,
     148             :                                               sizeof(struct wpa_ssid_value));
     149           7 :                         if (ns == NULL) {
     150           0 :                                 os_free(ssid);
     151           0 :                                 os_free(bssid);
     152           0 :                                 return -1;
     153             :                         }
     154           7 :                         ssid = ns;
     155             : 
     156          11 :                         if ((end - pos) & 0x01 || end - pos > 2 * 32 ||
     157           4 :                             hexstr2bin(pos, ssid[ssid_count].ssid,
     158           4 :                                        (end - pos) / 2) < 0) {
     159           4 :                                 os_free(ssid);
     160           4 :                                 os_free(bssid);
     161           4 :                                 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
     162             :                                            "SSID value '%s'", pos);
     163           4 :                                 return -1;
     164             :                         }
     165           3 :                         ssid[ssid_count].ssid_len = (end - pos) / 2;
     166           6 :                         wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
     167           3 :                                           ssid[ssid_count].ssid,
     168           3 :                                           ssid[ssid_count].ssid_len);
     169           3 :                         ssid_count++;
     170           3 :                         pos = end;
     171             :                 } else {
     172           1 :                         wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
     173             :                                    "'%s'", pos);
     174           1 :                         os_free(ssid);
     175           1 :                         os_free(bssid);
     176           1 :                         return -1;
     177             :                 }
     178             : 
     179          10 :                 pos = os_strchr(pos, ' ');
     180          10 :                 if (pos)
     181           3 :                         pos++;
     182             :         }
     183             : 
     184           9 :         wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
     185           9 :         os_free(wpa_s->disallow_aps_bssid);
     186           9 :         wpa_s->disallow_aps_bssid = bssid;
     187           9 :         wpa_s->disallow_aps_bssid_count = count;
     188             : 
     189           9 :         wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
     190           9 :         os_free(wpa_s->disallow_aps_ssid);
     191           9 :         wpa_s->disallow_aps_ssid = ssid;
     192           9 :         wpa_s->disallow_aps_ssid_count = ssid_count;
     193             : 
     194           9 :         if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
     195           4 :                 return 0;
     196             : 
     197           5 :         c = wpa_s->current_ssid;
     198           5 :         if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
     199           1 :                 return 0;
     200             : 
     201           6 :         if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
     202           2 :             !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
     203           1 :                 return 0;
     204             : 
     205           3 :         wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
     206             :                    "because current AP was marked disallowed");
     207             : 
     208             : #ifdef CONFIG_SME
     209           3 :         wpa_s->sme.prev_bssid_set = 0;
     210             : #endif /* CONFIG_SME */
     211           3 :         wpa_s->reassociate = 1;
     212           3 :         wpa_s->own_disconnect_req = 1;
     213           3 :         wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
     214           3 :         wpa_supplicant_req_scan(wpa_s, 0, 0);
     215             : 
     216           3 :         return 0;
     217             : }
     218             : 
     219             : 
     220             : #ifndef CONFIG_NO_CONFIG_BLOBS
     221          13 : static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
     222             : {
     223          13 :         char *name = pos;
     224             :         struct wpa_config_blob *blob;
     225             :         size_t len;
     226             : 
     227          13 :         pos = os_strchr(pos, ' ');
     228          13 :         if (pos == NULL)
     229           1 :                 return -1;
     230          12 :         *pos++ = '\0';
     231          12 :         len = os_strlen(pos);
     232          12 :         if (len & 1)
     233           1 :                 return -1;
     234             : 
     235          11 :         wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
     236          11 :         blob = os_zalloc(sizeof(*blob));
     237          11 :         if (blob == NULL)
     238           0 :                 return -1;
     239          11 :         blob->name = os_strdup(name);
     240          11 :         blob->data = os_malloc(len / 2);
     241          11 :         if (blob->name == NULL || blob->data == NULL) {
     242           0 :                 wpa_config_free_blob(blob);
     243           0 :                 return -1;
     244             :         }
     245             : 
     246          11 :         if (hexstr2bin(pos, blob->data, len / 2) < 0) {
     247           1 :                 wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
     248           1 :                 wpa_config_free_blob(blob);
     249           1 :                 return -1;
     250             :         }
     251          10 :         blob->len = len / 2;
     252             : 
     253          10 :         wpa_config_set_blob(wpa_s->conf, blob);
     254             : 
     255          10 :         return 0;
     256             : }
     257             : #endif /* CONFIG_NO_CONFIG_BLOBS */
     258             : 
     259             : 
     260           5 : static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
     261             : {
     262             :         char *params;
     263             :         char *pos;
     264           5 :         int *freqs = NULL;
     265             :         int ret;
     266             : 
     267           5 :         if (atoi(cmd)) {
     268           4 :                 params = os_strchr(cmd, ' ');
     269           4 :                 os_free(wpa_s->manual_sched_scan_freqs);
     270           4 :                 if (params) {
     271           2 :                         params++;
     272           2 :                         pos = os_strstr(params, "freq=");
     273           2 :                         if (pos)
     274           2 :                                 freqs = freq_range_to_channel_list(wpa_s,
     275             :                                                                    pos + 5);
     276             :                 }
     277           4 :                 wpa_s->manual_sched_scan_freqs = freqs;
     278           4 :                 ret = wpas_start_pno(wpa_s);
     279             :         } else {
     280           1 :                 ret = wpas_stop_pno(wpa_s);
     281             :         }
     282           5 :         return ret;
     283             : }
     284             : 
     285             : 
     286       20785 : static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
     287             :                                          char *cmd)
     288             : {
     289             :         char *value;
     290       20785 :         int ret = 0;
     291             : 
     292       20785 :         value = os_strchr(cmd, ' ');
     293       20785 :         if (value == NULL)
     294           2 :                 return -1;
     295       20783 :         *value++ = '\0';
     296             : 
     297       20783 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
     298       20783 :         if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
     299           1 :                 eapol_sm_configure(wpa_s->eapol,
     300             :                                    atoi(value), -1, -1, -1);
     301       20782 :         } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
     302           5 :                 eapol_sm_configure(wpa_s->eapol,
     303             :                                    -1, atoi(value), -1, -1);
     304       20777 :         } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
     305           1 :                 eapol_sm_configure(wpa_s->eapol,
     306             :                                    -1, -1, atoi(value), -1);
     307       20776 :         } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
     308           1 :                 eapol_sm_configure(wpa_s->eapol,
     309             :                                    -1, -1, -1, atoi(value));
     310       20775 :         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
     311           3 :                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
     312           3 :                                      atoi(value)))
     313           1 :                         ret = -1;
     314       20772 :         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
     315             :                    0) {
     316           2 :                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
     317           2 :                                      atoi(value)))
     318           1 :                         ret = -1;
     319       20770 :         } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
     320           4 :                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
     321           1 :                         ret = -1;
     322       20766 :         } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
     323           3 :                 wpa_s->wps_fragment_size = atoi(value);
     324             : #ifdef CONFIG_WPS_TESTING
     325       20763 :         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
     326             :                 long int val;
     327           5 :                 val = strtol(value, NULL, 0);
     328           5 :                 if (val < 0 || val > 0xff) {
     329           2 :                         ret = -1;
     330           2 :                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
     331             :                                    "wps_version_number %ld", val);
     332             :                 } else {
     333           3 :                         wps_version_number = val;
     334           6 :                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
     335             :                                    "version %u.%u",
     336           3 :                                    (wps_version_number & 0xf0) >> 4,
     337             :                                    wps_version_number & 0x0f);
     338             :                 }
     339       20758 :         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
     340           1 :                 wps_testing_dummy_cred = atoi(value);
     341           1 :                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
     342             :                            wps_testing_dummy_cred);
     343       20757 :         } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
     344           3 :                 wps_corrupt_pkhash = atoi(value);
     345           3 :                 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
     346             :                            wps_corrupt_pkhash);
     347             : #endif /* CONFIG_WPS_TESTING */
     348       20754 :         } else if (os_strcasecmp(cmd, "ampdu") == 0) {
     349           1 :                 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
     350           1 :                         ret = -1;
     351             : #ifdef CONFIG_TDLS
     352             : #ifdef CONFIG_TDLS_TESTING
     353       20753 :         } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
     354             :                 extern unsigned int tdls_testing;
     355          10 :                 tdls_testing = strtol(value, NULL, 0);
     356          10 :                 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
     357             : #endif /* CONFIG_TDLS_TESTING */
     358       20743 :         } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
     359           2 :                 int disabled = atoi(value);
     360           2 :                 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
     361           2 :                 if (disabled) {
     362           1 :                         if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
     363           0 :                                 ret = -1;
     364           1 :                 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
     365           0 :                         ret = -1;
     366           2 :                 wpa_tdls_enable(wpa_s->wpa, !disabled);
     367             : #endif /* CONFIG_TDLS */
     368       20741 :         } else if (os_strcasecmp(cmd, "pno") == 0) {
     369           5 :                 ret = wpas_ctrl_pno(wpa_s, value);
     370       20736 :         } else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
     371           0 :                 int disabled = atoi(value);
     372           0 :                 if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
     373           0 :                         ret = -1;
     374           0 :                 else if (disabled)
     375           0 :                         wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
     376       20736 :         } else if (os_strcasecmp(cmd, "uapsd") == 0) {
     377           7 :                 if (os_strcmp(value, "disable") == 0)
     378           1 :                         wpa_s->set_sta_uapsd = 0;
     379             :                 else {
     380             :                         int be, bk, vi, vo;
     381             :                         char *pos;
     382             :                         /* format: BE,BK,VI,VO;max SP Length */
     383           6 :                         be = atoi(value);
     384           6 :                         pos = os_strchr(value, ',');
     385           6 :                         if (pos == NULL)
     386           2 :                                 return -1;
     387           4 :                         pos++;
     388           4 :                         bk = atoi(pos);
     389           4 :                         pos = os_strchr(pos, ',');
     390           4 :                         if (pos == NULL)
     391           1 :                                 return -1;
     392           3 :                         pos++;
     393           3 :                         vi = atoi(pos);
     394           3 :                         pos = os_strchr(pos, ',');
     395           3 :                         if (pos == NULL)
     396           1 :                                 return -1;
     397           2 :                         pos++;
     398           2 :                         vo = atoi(pos);
     399             :                         /* ignore max SP Length for now */
     400             : 
     401           2 :                         wpa_s->set_sta_uapsd = 1;
     402           2 :                         wpa_s->sta_uapsd = 0;
     403           2 :                         if (be)
     404           1 :                                 wpa_s->sta_uapsd |= BIT(0);
     405           2 :                         if (bk)
     406           1 :                                 wpa_s->sta_uapsd |= BIT(1);
     407           2 :                         if (vi)
     408           1 :                                 wpa_s->sta_uapsd |= BIT(2);
     409           2 :                         if (vo)
     410           1 :                                 wpa_s->sta_uapsd |= BIT(3);
     411             :                 }
     412       20729 :         } else if (os_strcasecmp(cmd, "ps") == 0) {
     413           4 :                 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
     414             : #ifdef CONFIG_WIFI_DISPLAY
     415       20725 :         } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
     416          23 :                 int enabled = !!atoi(value);
     417          23 :                 if (enabled && !wpa_s->global->p2p)
     418           0 :                         ret = -1;
     419             :                 else
     420          23 :                         wifi_display_enable(wpa_s->global, enabled);
     421             : #endif /* CONFIG_WIFI_DISPLAY */
     422       20702 :         } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
     423           4 :                 ret = set_bssid_filter(wpa_s, value);
     424       20698 :         } else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
     425          16 :                 ret = set_disallow_aps(wpa_s, value);
     426       20682 :         } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
     427           3 :                 wpa_s->no_keep_alive = !!atoi(value);
     428             : #ifdef CONFIG_TESTING_OPTIONS
     429       20679 :         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
     430          16 :                 wpa_s->ext_mgmt_frame_handling = !!atoi(value);
     431       20663 :         } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
     432          37 :                 wpa_s->ext_eapol_frame_io = !!atoi(value);
     433             : #ifdef CONFIG_AP
     434          37 :                 if (wpa_s->ap_iface) {
     435           4 :                         wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
     436           2 :                                 wpa_s->ext_eapol_frame_io;
     437             :                 }
     438             : #endif /* CONFIG_AP */
     439       20626 :         } else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
     440           2 :                 wpa_s->extra_roc_dur = atoi(value);
     441       20624 :         } else if (os_strcasecmp(cmd, "test_failure") == 0) {
     442           4 :                 wpa_s->test_failure = atoi(value);
     443             : #endif /* CONFIG_TESTING_OPTIONS */
     444             : #ifndef CONFIG_NO_CONFIG_BLOBS
     445       20620 :         } else if (os_strcmp(cmd, "blob") == 0) {
     446          13 :                 ret = wpas_ctrl_set_blob(wpa_s, value);
     447             : #endif /* CONFIG_NO_CONFIG_BLOBS */
     448       20607 :         } else if (os_strcasecmp(cmd, "setband") == 0) {
     449           7 :                 if (os_strcmp(value, "AUTO") == 0)
     450           4 :                         wpa_s->setband = WPA_SETBAND_AUTO;
     451           3 :                 else if (os_strcmp(value, "5G") == 0)
     452           1 :                         wpa_s->setband = WPA_SETBAND_5G;
     453           2 :                 else if (os_strcmp(value, "2G") == 0)
     454           1 :                         wpa_s->setband = WPA_SETBAND_2G;
     455             :                 else
     456           1 :                         ret = -1;
     457             :         } else {
     458       20600 :                 value[-1] = '=';
     459       20600 :                 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
     460       20600 :                 if (ret == 0)
     461       20594 :                         wpa_supplicant_update_config(wpa_s);
     462             :         }
     463             : 
     464       20779 :         return ret;
     465             : }
     466             : 
     467             : 
     468          95 : static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
     469             :                                          char *cmd, char *buf, size_t buflen)
     470             : {
     471          95 :         int res = -1;
     472             : 
     473          95 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
     474             : 
     475          95 :         if (os_strcmp(cmd, "version") == 0) {
     476           1 :                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
     477          94 :         } else if (os_strcasecmp(cmd, "country") == 0) {
     478           2 :                 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
     479           4 :                         res = os_snprintf(buf, buflen, "%c%c",
     480           2 :                                           wpa_s->conf->country[0],
     481           2 :                                           wpa_s->conf->country[1]);
     482             : #ifdef CONFIG_WIFI_DISPLAY
     483          92 :         } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
     484             :                 int enabled;
     485           2 :                 if (wpa_s->global->p2p == NULL ||
     486           1 :                     wpa_s->global->p2p_disabled)
     487           0 :                         enabled = 0;
     488             :                 else
     489           1 :                         enabled = wpa_s->global->wifi_display;
     490           1 :                 res = os_snprintf(buf, buflen, "%d", enabled);
     491             : #endif /* CONFIG_WIFI_DISPLAY */
     492             : #ifdef CONFIG_TESTING_GET_GTK
     493             :         } else if (os_strcmp(cmd, "gtk") == 0) {
     494             :                 if (wpa_s->last_gtk_len == 0)
     495             :                         return -1;
     496             :                 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
     497             :                                        wpa_s->last_gtk_len);
     498             :                 return res;
     499             : #endif /* CONFIG_TESTING_GET_GTK */
     500          91 :         } else if (os_strcmp(cmd, "tls_library") == 0) {
     501          11 :                 res = tls_get_library_version(buf, buflen);
     502             :         } else {
     503          80 :                 res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
     504             :         }
     505             : 
     506          95 :         if (os_snprintf_error(buflen, res))
     507          18 :                 return -1;
     508          77 :         return res;
     509             : }
     510             : 
     511             : 
     512             : #ifdef IEEE8021X_EAPOL
     513          16 : static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
     514             :                                              char *addr)
     515             : {
     516             :         u8 bssid[ETH_ALEN];
     517          16 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
     518             : 
     519          16 :         if (hwaddr_aton(addr, bssid)) {
     520           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
     521             :                            "'%s'", addr);
     522           1 :                 return -1;
     523             :         }
     524             : 
     525          15 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
     526          15 :         rsn_preauth_deinit(wpa_s->wpa);
     527          15 :         if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
     528           5 :                 return -1;
     529             : 
     530          10 :         return 0;
     531             : }
     532             : #endif /* IEEE8021X_EAPOL */
     533             : 
     534             : 
     535             : #ifdef CONFIG_PEERKEY
     536             : /* MLME-STKSTART.request(peer) */
     537           6 : static int wpa_supplicant_ctrl_iface_stkstart(
     538             :         struct wpa_supplicant *wpa_s, char *addr)
     539             : {
     540             :         u8 peer[ETH_ALEN];
     541             : 
     542           6 :         if (hwaddr_aton(addr, peer)) {
     543           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
     544             :                            "address '%s'", addr);
     545           1 :                 return -1;
     546             :         }
     547             : 
     548          30 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
     549          30 :                    MAC2STR(peer));
     550             : 
     551           5 :         return wpa_sm_stkstart(wpa_s->wpa, peer);
     552             : }
     553             : #endif /* CONFIG_PEERKEY */
     554             : 
     555             : 
     556             : #ifdef CONFIG_TDLS
     557             : 
     558           3 : static int wpa_supplicant_ctrl_iface_tdls_discover(
     559             :         struct wpa_supplicant *wpa_s, char *addr)
     560             : {
     561             :         u8 peer[ETH_ALEN];
     562             :         int ret;
     563             : 
     564           3 :         if (hwaddr_aton(addr, peer)) {
     565           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
     566             :                            "address '%s'", addr);
     567           1 :                 return -1;
     568             :         }
     569             : 
     570          12 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
     571          12 :                    MAC2STR(peer));
     572             : 
     573           2 :         if (wpa_tdls_is_external_setup(wpa_s->wpa))
     574           2 :                 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
     575             :         else
     576           0 :                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
     577             : 
     578           2 :         return ret;
     579             : }
     580             : 
     581             : 
     582          29 : static int wpa_supplicant_ctrl_iface_tdls_setup(
     583             :         struct wpa_supplicant *wpa_s, char *addr)
     584             : {
     585             :         u8 peer[ETH_ALEN];
     586             :         int ret;
     587             : 
     588          29 :         if (hwaddr_aton(addr, peer)) {
     589           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
     590             :                            "address '%s'", addr);
     591           1 :                 return -1;
     592             :         }
     593             : 
     594         168 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
     595         168 :                    MAC2STR(peer));
     596             : 
     597          28 :         if ((wpa_s->conf->tdls_external_control) &&
     598           0 :             wpa_tdls_is_external_setup(wpa_s->wpa))
     599           0 :                 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
     600             : 
     601          28 :         wpa_tdls_remove(wpa_s->wpa, peer);
     602             : 
     603          28 :         if (wpa_tdls_is_external_setup(wpa_s->wpa))
     604          28 :                 ret = wpa_tdls_start(wpa_s->wpa, peer);
     605             :         else
     606           0 :                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
     607             : 
     608          28 :         return ret;
     609             : }
     610             : 
     611             : 
     612          13 : static int wpa_supplicant_ctrl_iface_tdls_teardown(
     613             :         struct wpa_supplicant *wpa_s, char *addr)
     614             : {
     615             :         u8 peer[ETH_ALEN];
     616             :         int ret;
     617             : 
     618          13 :         if (os_strcmp(addr, "*") == 0) {
     619             :                 /* remove everyone */
     620           2 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
     621           2 :                 wpa_tdls_teardown_peers(wpa_s->wpa);
     622           2 :                 return 0;
     623             :         }
     624             : 
     625          11 :         if (hwaddr_aton(addr, peer)) {
     626           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
     627             :                            "address '%s'", addr);
     628           1 :                 return -1;
     629             :         }
     630             : 
     631          60 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
     632          60 :                    MAC2STR(peer));
     633             : 
     634          10 :         if ((wpa_s->conf->tdls_external_control) &&
     635           0 :             wpa_tdls_is_external_setup(wpa_s->wpa))
     636           0 :                 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
     637             : 
     638          10 :         if (wpa_tdls_is_external_setup(wpa_s->wpa))
     639          10 :                 ret = wpa_tdls_teardown_link(
     640             :                         wpa_s->wpa, peer,
     641             :                         WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
     642             :         else
     643           0 :                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
     644             : 
     645          10 :         return ret;
     646             : }
     647             : 
     648             : 
     649           1 : static int ctrl_iface_get_capability_tdls(
     650             :         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
     651             : {
     652             :         int ret;
     653             : 
     654           2 :         ret = os_snprintf(buf, buflen, "%s\n",
     655           1 :                           wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
     656           1 :                           (wpa_s->drv_flags &
     657             :                            WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
     658           1 :                            "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
     659           1 :         if (os_snprintf_error(buflen, ret))
     660           0 :                 return -1;
     661           1 :         return ret;
     662             : }
     663             : 
     664             : 
     665           8 : static int wpa_supplicant_ctrl_iface_tdls_chan_switch(
     666             :         struct wpa_supplicant *wpa_s, char *cmd)
     667             : {
     668             :         u8 peer[ETH_ALEN];
     669             :         struct hostapd_freq_params freq_params;
     670             :         u8 oper_class;
     671             :         char *pos, *end;
     672             : 
     673           8 :         if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
     674           0 :                 wpa_printf(MSG_INFO,
     675             :                            "tdls_chanswitch: Only supported with external setup");
     676           0 :                 return -1;
     677             :         }
     678             : 
     679           8 :         os_memset(&freq_params, 0, sizeof(freq_params));
     680             : 
     681           8 :         pos = os_strchr(cmd, ' ');
     682           8 :         if (pos == NULL)
     683           1 :                 return -1;
     684           7 :         *pos++ = '\0';
     685             : 
     686           7 :         oper_class = strtol(pos, &end, 10);
     687           7 :         if (pos == end) {
     688           3 :                 wpa_printf(MSG_INFO,
     689             :                            "tdls_chanswitch: Invalid op class provided");
     690           3 :                 return -1;
     691             :         }
     692             : 
     693           4 :         pos = end;
     694           4 :         freq_params.freq = atoi(pos);
     695           4 :         if (freq_params.freq == 0) {
     696           1 :                 wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided");
     697           1 :                 return -1;
     698             :         }
     699             : 
     700             : #define SET_FREQ_SETTING(str) \
     701             :         do { \
     702             :                 const char *pos2 = os_strstr(pos, " " #str "="); \
     703             :                 if (pos2) { \
     704             :                         pos2 += sizeof(" " #str "=") - 1; \
     705             :                         freq_params.str = atoi(pos2); \
     706             :                 } \
     707             :         } while (0)
     708             : 
     709           3 :         SET_FREQ_SETTING(center_freq1);
     710           3 :         SET_FREQ_SETTING(center_freq2);
     711           3 :         SET_FREQ_SETTING(bandwidth);
     712           3 :         SET_FREQ_SETTING(sec_channel_offset);
     713             : #undef SET_FREQ_SETTING
     714             : 
     715           3 :         freq_params.ht_enabled = !!os_strstr(pos, " ht");
     716           3 :         freq_params.vht_enabled = !!os_strstr(pos, " vht");
     717             : 
     718           3 :         if (hwaddr_aton(cmd, peer)) {
     719           0 :                 wpa_printf(MSG_DEBUG,
     720             :                            "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'",
     721             :                            cmd);
     722           0 :                 return -1;
     723             :         }
     724             : 
     725          24 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR
     726             :                    " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
     727          18 :                    MAC2STR(peer), oper_class, freq_params.freq,
     728             :                    freq_params.center_freq1, freq_params.center_freq2,
     729             :                    freq_params.bandwidth, freq_params.sec_channel_offset,
     730           3 :                    freq_params.ht_enabled ? " HT" : "",
     731           3 :                    freq_params.vht_enabled ? " VHT" : "");
     732             : 
     733           3 :         return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
     734             :                                            &freq_params);
     735             : }
     736             : 
     737             : 
     738           4 : static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(
     739             :         struct wpa_supplicant *wpa_s, char *cmd)
     740             : {
     741             :         u8 peer[ETH_ALEN];
     742             : 
     743           4 :         if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
     744           0 :                 wpa_printf(MSG_INFO,
     745             :                            "tdls_chanswitch: Only supported with external setup");
     746           0 :                 return -1;
     747             :         }
     748             : 
     749           4 :         if (hwaddr_aton(cmd, peer)) {
     750           1 :                 wpa_printf(MSG_DEBUG,
     751             :                            "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'",
     752             :                            cmd);
     753           1 :                 return -1;
     754             :         }
     755             : 
     756          18 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR,
     757          18 :                    MAC2STR(peer));
     758             : 
     759           3 :         return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
     760             : }
     761             : 
     762             : #endif /* CONFIG_TDLS */
     763             : 
     764             : 
     765          16 : static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
     766             : {
     767          16 :         char *token, *context = NULL;
     768          16 :         struct wmm_ac_ts_setup_params params = {
     769             :                 .tsid = 0xff,
     770             :                 .direction = 0xff,
     771             :         };
     772             : 
     773         128 :         while ((token = str_token(cmd, " ", &context))) {
     774         177 :                 if (sscanf(token, "tsid=%i", &params.tsid) == 1 ||
     775         149 :                     sscanf(token, "up=%i", &params.user_priority) == 1 ||
     776          68 :                     sscanf(token, "nominal_msdu_size=%i",
     777          55 :                            &params.nominal_msdu_size) == 1 ||
     778          55 :                     sscanf(token, "mean_data_rate=%i",
     779          42 :                            &params.mean_data_rate) == 1 ||
     780          42 :                     sscanf(token, "min_phy_rate=%i",
     781          29 :                            &params.minimum_phy_rate) == 1 ||
     782          29 :                     sscanf(token, "sba=%i",
     783             :                            &params.surplus_bandwidth_allowance) == 1)
     784          80 :                         continue;
     785             : 
     786          16 :                 if (os_strcasecmp(token, "downlink") == 0) {
     787          13 :                         params.direction = WMM_TSPEC_DIRECTION_DOWNLINK;
     788           3 :                 } else if (os_strcasecmp(token, "uplink") == 0) {
     789           1 :                         params.direction = WMM_TSPEC_DIRECTION_UPLINK;
     790           2 :                 } else if (os_strcasecmp(token, "bidi") == 0) {
     791           1 :                         params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL;
     792           1 :                 } else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) {
     793           1 :                         params.fixed_nominal_msdu = 1;
     794             :                 } else {
     795           0 :                         wpa_printf(MSG_DEBUG,
     796             :                                    "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'",
     797             :                                    token);
     798           0 :                         return -1;
     799             :                 }
     800             : 
     801             :         }
     802             : 
     803          16 :         return wpas_wmm_ac_addts(wpa_s, &params);
     804             : }
     805             : 
     806             : 
     807           3 : static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd)
     808             : {
     809           3 :         u8 tsid = atoi(cmd);
     810             : 
     811           3 :         return wpas_wmm_ac_delts(wpa_s, tsid);
     812             : }
     813             : 
     814             : 
     815             : #ifdef CONFIG_IEEE80211R
     816         116 : static int wpa_supplicant_ctrl_iface_ft_ds(
     817             :         struct wpa_supplicant *wpa_s, char *addr)
     818             : {
     819             :         u8 target_ap[ETH_ALEN];
     820             :         struct wpa_bss *bss;
     821             :         const u8 *mdie;
     822             : 
     823         116 :         if (hwaddr_aton(addr, target_ap)) {
     824           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
     825             :                            "address '%s'", addr);
     826           1 :                 return -1;
     827             :         }
     828             : 
     829         115 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
     830             : 
     831         115 :         bss = wpa_bss_get_bssid(wpa_s, target_ap);
     832         115 :         if (bss)
     833         114 :                 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
     834             :         else
     835           1 :                 mdie = NULL;
     836             : 
     837         115 :         return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
     838             : }
     839             : #endif /* CONFIG_IEEE80211R */
     840             : 
     841             : 
     842             : #ifdef CONFIG_WPS
     843          44 : static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
     844             :                                              char *cmd)
     845             : {
     846          44 :         u8 bssid[ETH_ALEN], *_bssid = bssid;
     847             : #ifdef CONFIG_P2P
     848             :         u8 p2p_dev_addr[ETH_ALEN];
     849             : #endif /* CONFIG_P2P */
     850             : #ifdef CONFIG_AP
     851          44 :         u8 *_p2p_dev_addr = NULL;
     852             : #endif /* CONFIG_AP */
     853             : 
     854          44 :         if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
     855          16 :                 _bssid = NULL;
     856             : #ifdef CONFIG_P2P
     857          28 :         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
     858           2 :                 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
     859           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
     860             :                                    "P2P Device Address '%s'",
     861             :                                    cmd + 13);
     862           1 :                         return -1;
     863             :                 }
     864           1 :                 _p2p_dev_addr = p2p_dev_addr;
     865             : #endif /* CONFIG_P2P */
     866          26 :         } else if (hwaddr_aton(cmd, bssid)) {
     867           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
     868             :                            cmd);
     869           1 :                 return -1;
     870             :         }
     871             : 
     872             : #ifdef CONFIG_AP
     873          42 :         if (wpa_s->ap_iface)
     874           8 :                 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
     875             : #endif /* CONFIG_AP */
     876             : 
     877          34 :         return wpas_wps_start_pbc(wpa_s, _bssid, 0);
     878             : }
     879             : 
     880             : 
     881         207 : static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
     882             :                                              char *cmd, char *buf,
     883             :                                              size_t buflen)
     884             : {
     885         207 :         u8 bssid[ETH_ALEN], *_bssid = bssid;
     886             :         char *pin;
     887             :         int ret;
     888             : 
     889         207 :         pin = os_strchr(cmd, ' ');
     890         207 :         if (pin)
     891          71 :                 *pin++ = '\0';
     892             : 
     893         207 :         if (os_strcmp(cmd, "any") == 0)
     894          57 :                 _bssid = NULL;
     895         150 :         else if (os_strcmp(cmd, "get") == 0) {
     896         133 :                 ret = wps_generate_pin();
     897         133 :                 goto done;
     898          17 :         } else if (hwaddr_aton(cmd, bssid)) {
     899           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
     900             :                            cmd);
     901           1 :                 return -1;
     902             :         }
     903             : 
     904             : #ifdef CONFIG_AP
     905          73 :         if (wpa_s->ap_iface) {
     906          51 :                 int timeout = 0;
     907             :                 char *pos;
     908             : 
     909          51 :                 if (pin) {
     910          51 :                         pos = os_strchr(pin, ' ');
     911          51 :                         if (pos) {
     912           1 :                                 *pos++ = '\0';
     913           1 :                                 timeout = atoi(pos);
     914             :                         }
     915             :                 }
     916             : 
     917          51 :                 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
     918             :                                                  buf, buflen, timeout);
     919             :         }
     920             : #endif /* CONFIG_AP */
     921             : 
     922          22 :         if (pin) {
     923          20 :                 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
     924             :                                          DEV_PW_DEFAULT);
     925          20 :                 if (ret < 0)
     926           0 :                         return -1;
     927          20 :                 ret = os_snprintf(buf, buflen, "%s", pin);
     928          20 :                 if (os_snprintf_error(buflen, ret))
     929           0 :                         return -1;
     930          20 :                 return ret;
     931             :         }
     932             : 
     933           2 :         ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
     934           2 :         if (ret < 0)
     935           0 :                 return -1;
     936             : 
     937             : done:
     938             :         /* Return the generated PIN */
     939         135 :         ret = os_snprintf(buf, buflen, "%08d", ret);
     940         135 :         if (os_snprintf_error(buflen, ret))
     941           0 :                 return -1;
     942         135 :         return ret;
     943             : }
     944             : 
     945             : 
     946          17 : static int wpa_supplicant_ctrl_iface_wps_check_pin(
     947             :         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
     948             : {
     949             :         char pin[9];
     950             :         size_t len;
     951             :         char *pos;
     952             :         int ret;
     953             : 
     954          17 :         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
     955             :                               (u8 *) cmd, os_strlen(cmd));
     956         156 :         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
     957         140 :                 if (*pos < '0' || *pos > '9')
     958           6 :                         continue;
     959         134 :                 pin[len++] = *pos;
     960         134 :                 if (len == 9) {
     961           1 :                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
     962           1 :                         return -1;
     963             :                 }
     964             :         }
     965          16 :         if (len != 4 && len != 8) {
     966           1 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
     967           1 :                 return -1;
     968             :         }
     969          15 :         pin[len] = '\0';
     970             : 
     971          15 :         if (len == 8) {
     972             :                 unsigned int pin_val;
     973          15 :                 pin_val = atoi(pin);
     974          15 :                 if (!wps_pin_valid(pin_val)) {
     975           1 :                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
     976           1 :                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
     977           1 :                         if (os_snprintf_error(buflen, ret))
     978           0 :                                 return -1;
     979           1 :                         return ret;
     980             :                 }
     981             :         }
     982             : 
     983          14 :         ret = os_snprintf(buf, buflen, "%s", pin);
     984          14 :         if (os_snprintf_error(buflen, ret))
     985           0 :                 return -1;
     986             : 
     987          14 :         return ret;
     988             : }
     989             : 
     990             : 
     991             : #ifdef CONFIG_WPS_NFC
     992             : 
     993           4 : static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
     994             :                                              char *cmd)
     995             : {
     996           4 :         u8 bssid[ETH_ALEN], *_bssid = bssid;
     997             : 
     998           4 :         if (cmd == NULL || cmd[0] == '\0')
     999           3 :                 _bssid = NULL;
    1000           1 :         else if (hwaddr_aton(cmd, bssid))
    1001           1 :                 return -1;
    1002             : 
    1003           3 :         return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
    1004             :                                   0, 0);
    1005             : }
    1006             : 
    1007             : 
    1008           3 : static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
    1009             :         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
    1010             : {
    1011             :         int ndef;
    1012             :         struct wpabuf *buf;
    1013             :         int res;
    1014             :         char *pos;
    1015             : 
    1016           3 :         pos = os_strchr(cmd, ' ');
    1017           3 :         if (pos)
    1018           1 :                 *pos++ = '\0';
    1019           3 :         if (os_strcmp(cmd, "WPS") == 0)
    1020           1 :                 ndef = 0;
    1021           2 :         else if (os_strcmp(cmd, "NDEF") == 0)
    1022           1 :                 ndef = 1;
    1023             :         else
    1024           1 :                 return -1;
    1025             : 
    1026           2 :         buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
    1027           2 :         if (buf == NULL)
    1028           1 :                 return -1;
    1029             : 
    1030           1 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    1031             :                                          wpabuf_len(buf));
    1032           1 :         reply[res++] = '\n';
    1033           1 :         reply[res] = '\0';
    1034             : 
    1035           1 :         wpabuf_free(buf);
    1036             : 
    1037           1 :         return res;
    1038             : }
    1039             : 
    1040             : 
    1041          14 : static int wpa_supplicant_ctrl_iface_wps_nfc_token(
    1042             :         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
    1043             : {
    1044             :         int ndef;
    1045             :         struct wpabuf *buf;
    1046             :         int res;
    1047             : 
    1048          14 :         if (os_strcmp(cmd, "WPS") == 0)
    1049           1 :                 ndef = 0;
    1050          13 :         else if (os_strcmp(cmd, "NDEF") == 0)
    1051          12 :                 ndef = 1;
    1052             :         else
    1053           1 :                 return -1;
    1054             : 
    1055          13 :         buf = wpas_wps_nfc_token(wpa_s, ndef);
    1056          13 :         if (buf == NULL)
    1057           0 :                 return -1;
    1058             : 
    1059          13 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    1060             :                                          wpabuf_len(buf));
    1061          13 :         reply[res++] = '\n';
    1062          13 :         reply[res] = '\0';
    1063             : 
    1064          13 :         wpabuf_free(buf);
    1065             : 
    1066          13 :         return res;
    1067             : }
    1068             : 
    1069             : 
    1070          37 : static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
    1071             :         struct wpa_supplicant *wpa_s, char *pos)
    1072             : {
    1073             :         size_t len;
    1074             :         struct wpabuf *buf;
    1075             :         int ret;
    1076             :         char *freq;
    1077          37 :         int forced_freq = 0;
    1078             : 
    1079          37 :         freq = strstr(pos, " freq=");
    1080          37 :         if (freq) {
    1081           1 :                 *freq = '\0';
    1082           1 :                 freq += 6;
    1083           1 :                 forced_freq = atoi(freq);
    1084             :         }
    1085             : 
    1086          37 :         len = os_strlen(pos);
    1087          37 :         if (len & 0x01)
    1088           1 :                 return -1;
    1089          36 :         len /= 2;
    1090             : 
    1091          36 :         buf = wpabuf_alloc(len);
    1092          36 :         if (buf == NULL)
    1093           0 :                 return -1;
    1094          36 :         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
    1095           1 :                 wpabuf_free(buf);
    1096           1 :                 return -1;
    1097             :         }
    1098             : 
    1099          35 :         ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
    1100          35 :         wpabuf_free(buf);
    1101             : 
    1102          35 :         return ret;
    1103             : }
    1104             : 
    1105             : 
    1106          12 : static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
    1107             :                                               char *reply, size_t max_len,
    1108             :                                               int ndef)
    1109             : {
    1110             :         struct wpabuf *buf;
    1111             :         int res;
    1112             : 
    1113          12 :         buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
    1114          12 :         if (buf == NULL)
    1115           0 :                 return -1;
    1116             : 
    1117          12 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    1118             :                                          wpabuf_len(buf));
    1119          12 :         reply[res++] = '\n';
    1120          12 :         reply[res] = '\0';
    1121             : 
    1122          12 :         wpabuf_free(buf);
    1123             : 
    1124          12 :         return res;
    1125             : }
    1126             : 
    1127             : 
    1128             : #ifdef CONFIG_P2P
    1129          10 : static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
    1130             :                                               char *reply, size_t max_len,
    1131             :                                               int ndef)
    1132             : {
    1133             :         struct wpabuf *buf;
    1134             :         int res;
    1135             : 
    1136          10 :         buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
    1137          10 :         if (buf == NULL) {
    1138           0 :                 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
    1139           0 :                 return -1;
    1140             :         }
    1141             : 
    1142          10 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    1143             :                                          wpabuf_len(buf));
    1144          10 :         reply[res++] = '\n';
    1145          10 :         reply[res] = '\0';
    1146             : 
    1147          10 :         wpabuf_free(buf);
    1148             : 
    1149          10 :         return res;
    1150             : }
    1151             : #endif /* CONFIG_P2P */
    1152             : 
    1153             : 
    1154          28 : static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
    1155             :                                           char *cmd, char *reply,
    1156             :                                           size_t max_len)
    1157             : {
    1158             :         char *pos;
    1159             :         int ndef;
    1160             : 
    1161          28 :         pos = os_strchr(cmd, ' ');
    1162          28 :         if (pos == NULL)
    1163           1 :                 return -1;
    1164          27 :         *pos++ = '\0';
    1165             : 
    1166          27 :         if (os_strcmp(cmd, "WPS") == 0)
    1167           4 :                 ndef = 0;
    1168          23 :         else if (os_strcmp(cmd, "NDEF") == 0)
    1169          22 :                 ndef = 1;
    1170             :         else
    1171           1 :                 return -1;
    1172             : 
    1173          26 :         if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
    1174          14 :                 if (!ndef)
    1175           2 :                         return -1;
    1176          12 :                 return wpas_ctrl_nfc_get_handover_req_wps(
    1177             :                         wpa_s, reply, max_len, ndef);
    1178             :         }
    1179             : 
    1180             : #ifdef CONFIG_P2P
    1181          12 :         if (os_strcmp(pos, "P2P-CR") == 0) {
    1182          10 :                 return wpas_ctrl_nfc_get_handover_req_p2p(
    1183             :                         wpa_s, reply, max_len, ndef);
    1184             :         }
    1185             : #endif /* CONFIG_P2P */
    1186             : 
    1187           2 :         return -1;
    1188             : }
    1189             : 
    1190             : 
    1191           6 : static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
    1192             :                                               char *reply, size_t max_len,
    1193             :                                               int ndef, int cr, char *uuid)
    1194             : {
    1195             :         struct wpabuf *buf;
    1196             :         int res;
    1197             : 
    1198           6 :         buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
    1199           6 :         if (buf == NULL)
    1200           2 :                 return -1;
    1201             : 
    1202           4 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    1203             :                                          wpabuf_len(buf));
    1204           4 :         reply[res++] = '\n';
    1205           4 :         reply[res] = '\0';
    1206             : 
    1207           4 :         wpabuf_free(buf);
    1208             : 
    1209           4 :         return res;
    1210             : }
    1211             : 
    1212             : 
    1213             : #ifdef CONFIG_P2P
    1214          20 : static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
    1215             :                                               char *reply, size_t max_len,
    1216             :                                               int ndef, int tag)
    1217             : {
    1218             :         struct wpabuf *buf;
    1219             :         int res;
    1220             : 
    1221          20 :         buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
    1222          20 :         if (buf == NULL)
    1223           0 :                 return -1;
    1224             : 
    1225          20 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    1226             :                                          wpabuf_len(buf));
    1227          20 :         reply[res++] = '\n';
    1228          20 :         reply[res] = '\0';
    1229             : 
    1230          20 :         wpabuf_free(buf);
    1231             : 
    1232          20 :         return res;
    1233             : }
    1234             : #endif /* CONFIG_P2P */
    1235             : 
    1236             : 
    1237          32 : static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
    1238             :                                           char *cmd, char *reply,
    1239             :                                           size_t max_len)
    1240             : {
    1241             :         char *pos, *pos2;
    1242             :         int ndef;
    1243             : 
    1244          32 :         pos = os_strchr(cmd, ' ');
    1245          32 :         if (pos == NULL)
    1246           1 :                 return -1;
    1247          31 :         *pos++ = '\0';
    1248             : 
    1249          31 :         if (os_strcmp(cmd, "WPS") == 0)
    1250           5 :                 ndef = 0;
    1251          26 :         else if (os_strcmp(cmd, "NDEF") == 0)
    1252          25 :                 ndef = 1;
    1253             :         else
    1254           1 :                 return -1;
    1255             : 
    1256          30 :         pos2 = os_strchr(pos, ' ');
    1257          30 :         if (pos2)
    1258           4 :                 *pos2++ = '\0';
    1259          30 :         if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
    1260           8 :                 if (!ndef)
    1261           2 :                         return -1;
    1262           6 :                 return wpas_ctrl_nfc_get_handover_sel_wps(
    1263             :                         wpa_s, reply, max_len, ndef,
    1264           6 :                         os_strcmp(pos, "WPS-CR") == 0, pos2);
    1265             :         }
    1266             : 
    1267             : #ifdef CONFIG_P2P
    1268          22 :         if (os_strcmp(pos, "P2P-CR") == 0) {
    1269          10 :                 return wpas_ctrl_nfc_get_handover_sel_p2p(
    1270             :                         wpa_s, reply, max_len, ndef, 0);
    1271             :         }
    1272             : 
    1273          12 :         if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
    1274          10 :                 return wpas_ctrl_nfc_get_handover_sel_p2p(
    1275             :                         wpa_s, reply, max_len, ndef, 1);
    1276             :         }
    1277             : #endif /* CONFIG_P2P */
    1278             : 
    1279           2 :         return -1;
    1280             : }
    1281             : 
    1282             : 
    1283          40 : static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
    1284             :                                          char *cmd)
    1285             : {
    1286             :         size_t len;
    1287             :         struct wpabuf *req, *sel;
    1288             :         int ret;
    1289             :         char *pos, *role, *type, *pos2;
    1290             : #ifdef CONFIG_P2P
    1291             :         char *freq;
    1292          40 :         int forced_freq = 0;
    1293             : 
    1294          40 :         freq = strstr(cmd, " freq=");
    1295          40 :         if (freq) {
    1296           1 :                 *freq = '\0';
    1297           1 :                 freq += 6;
    1298           1 :                 forced_freq = atoi(freq);
    1299             :         }
    1300             : #endif /* CONFIG_P2P */
    1301             : 
    1302          40 :         role = cmd;
    1303          40 :         pos = os_strchr(role, ' ');
    1304          40 :         if (pos == NULL) {
    1305           2 :                 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
    1306           2 :                 return -1;
    1307             :         }
    1308          38 :         *pos++ = '\0';
    1309             : 
    1310          38 :         type = pos;
    1311          38 :         pos = os_strchr(type, ' ');
    1312          38 :         if (pos == NULL) {
    1313           1 :                 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
    1314           1 :                 return -1;
    1315             :         }
    1316          37 :         *pos++ = '\0';
    1317             : 
    1318          37 :         pos2 = os_strchr(pos, ' ');
    1319          37 :         if (pos2 == NULL) {
    1320           1 :                 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
    1321           1 :                 return -1;
    1322             :         }
    1323          36 :         *pos2++ = '\0';
    1324             : 
    1325          36 :         len = os_strlen(pos);
    1326          36 :         if (len & 0x01) {
    1327           1 :                 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
    1328           1 :                 return -1;
    1329             :         }
    1330          35 :         len /= 2;
    1331             : 
    1332          35 :         req = wpabuf_alloc(len);
    1333          35 :         if (req == NULL) {
    1334           0 :                 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
    1335           0 :                 return -1;
    1336             :         }
    1337          35 :         if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
    1338           1 :                 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
    1339           1 :                 wpabuf_free(req);
    1340           1 :                 return -1;
    1341             :         }
    1342             : 
    1343          34 :         len = os_strlen(pos2);
    1344          34 :         if (len & 0x01) {
    1345           1 :                 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
    1346           1 :                 wpabuf_free(req);
    1347           1 :                 return -1;
    1348             :         }
    1349          33 :         len /= 2;
    1350             : 
    1351          33 :         sel = wpabuf_alloc(len);
    1352          33 :         if (sel == NULL) {
    1353           0 :                 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
    1354           0 :                 wpabuf_free(req);
    1355           0 :                 return -1;
    1356             :         }
    1357          33 :         if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
    1358           1 :                 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
    1359           1 :                 wpabuf_free(req);
    1360           1 :                 wpabuf_free(sel);
    1361           1 :                 return -1;
    1362             :         }
    1363             : 
    1364          64 :         wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
    1365          64 :                    role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
    1366             : 
    1367          32 :         if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
    1368          11 :                 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
    1369             : #ifdef CONFIG_AP
    1370          21 :         } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
    1371             :         {
    1372           4 :                 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
    1373           8 :                 if (ret < 0)
    1374           3 :                         ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
    1375             : #endif /* CONFIG_AP */
    1376             : #ifdef CONFIG_P2P
    1377          17 :         } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
    1378             :         {
    1379           8 :                 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
    1380           9 :         } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
    1381             :         {
    1382           8 :                 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
    1383             :                                                    forced_freq);
    1384             : #endif /* CONFIG_P2P */
    1385             :         } else {
    1386           1 :                 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
    1387             :                            "reported: role=%s type=%s", role, type);
    1388           1 :                 ret = -1;
    1389             :         }
    1390          32 :         wpabuf_free(req);
    1391          32 :         wpabuf_free(sel);
    1392             : 
    1393          32 :         if (ret)
    1394           1 :                 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
    1395             : 
    1396          32 :         return ret;
    1397             : }
    1398             : 
    1399             : #endif /* CONFIG_WPS_NFC */
    1400             : 
    1401             : 
    1402          45 : static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
    1403             :                                              char *cmd)
    1404             : {
    1405             :         u8 bssid[ETH_ALEN];
    1406             :         char *pin;
    1407             :         char *new_ssid;
    1408             :         char *new_auth;
    1409             :         char *new_encr;
    1410             :         char *new_key;
    1411             :         struct wps_new_ap_settings ap;
    1412             : 
    1413          45 :         pin = os_strchr(cmd, ' ');
    1414          45 :         if (pin == NULL)
    1415           1 :                 return -1;
    1416          44 :         *pin++ = '\0';
    1417             : 
    1418          44 :         if (hwaddr_aton(cmd, bssid)) {
    1419           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
    1420             :                            cmd);
    1421           1 :                 return -1;
    1422             :         }
    1423             : 
    1424          43 :         new_ssid = os_strchr(pin, ' ');
    1425          43 :         if (new_ssid == NULL)
    1426          24 :                 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
    1427          19 :         *new_ssid++ = '\0';
    1428             : 
    1429          19 :         new_auth = os_strchr(new_ssid, ' ');
    1430          19 :         if (new_auth == NULL)
    1431           1 :                 return -1;
    1432          18 :         *new_auth++ = '\0';
    1433             : 
    1434          18 :         new_encr = os_strchr(new_auth, ' ');
    1435          18 :         if (new_encr == NULL)
    1436           1 :                 return -1;
    1437          17 :         *new_encr++ = '\0';
    1438             : 
    1439          17 :         new_key = os_strchr(new_encr, ' ');
    1440          17 :         if (new_key == NULL)
    1441           1 :                 return -1;
    1442          16 :         *new_key++ = '\0';
    1443             : 
    1444          16 :         os_memset(&ap, 0, sizeof(ap));
    1445          16 :         ap.ssid_hex = new_ssid;
    1446          16 :         ap.auth = new_auth;
    1447          16 :         ap.encr = new_encr;
    1448          16 :         ap.key_hex = new_key;
    1449          16 :         return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
    1450             : }
    1451             : 
    1452             : 
    1453             : #ifdef CONFIG_AP
    1454          16 : static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
    1455             :                                                 char *cmd, char *buf,
    1456             :                                                 size_t buflen)
    1457             : {
    1458          16 :         int timeout = 300;
    1459             :         char *pos;
    1460             :         const char *pin_txt;
    1461             : 
    1462          16 :         if (!wpa_s->ap_iface)
    1463           1 :                 return -1;
    1464             : 
    1465          15 :         pos = os_strchr(cmd, ' ');
    1466          15 :         if (pos)
    1467           3 :                 *pos++ = '\0';
    1468             : 
    1469          15 :         if (os_strcmp(cmd, "disable") == 0) {
    1470           1 :                 wpas_wps_ap_pin_disable(wpa_s);
    1471           1 :                 return os_snprintf(buf, buflen, "OK\n");
    1472             :         }
    1473             : 
    1474          14 :         if (os_strcmp(cmd, "random") == 0) {
    1475           2 :                 if (pos)
    1476           1 :                         timeout = atoi(pos);
    1477           2 :                 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
    1478           2 :                 if (pin_txt == NULL)
    1479           0 :                         return -1;
    1480           2 :                 return os_snprintf(buf, buflen, "%s", pin_txt);
    1481             :         }
    1482             : 
    1483          12 :         if (os_strcmp(cmd, "get") == 0) {
    1484           8 :                 pin_txt = wpas_wps_ap_pin_get(wpa_s);
    1485           8 :                 if (pin_txt == NULL)
    1486           2 :                         return -1;
    1487           6 :                 return os_snprintf(buf, buflen, "%s", pin_txt);
    1488             :         }
    1489             : 
    1490           4 :         if (os_strcmp(cmd, "set") == 0) {
    1491             :                 char *pin;
    1492           3 :                 if (pos == NULL)
    1493           1 :                         return -1;
    1494           2 :                 pin = pos;
    1495           2 :                 pos = os_strchr(pos, ' ');
    1496           2 :                 if (pos) {
    1497           1 :                         *pos++ = '\0';
    1498           1 :                         timeout = atoi(pos);
    1499             :                 }
    1500           2 :                 if (os_strlen(pin) > buflen)
    1501           0 :                         return -1;
    1502           2 :                 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
    1503           0 :                         return -1;
    1504           2 :                 return os_snprintf(buf, buflen, "%s", pin);
    1505             :         }
    1506             : 
    1507           1 :         return -1;
    1508             : }
    1509             : #endif /* CONFIG_AP */
    1510             : 
    1511             : 
    1512             : #ifdef CONFIG_WPS_ER
    1513           5 : static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
    1514             :                                                 char *cmd)
    1515             : {
    1516           5 :         char *uuid = cmd, *pin, *pos;
    1517           5 :         u8 addr_buf[ETH_ALEN], *addr = NULL;
    1518           5 :         pin = os_strchr(uuid, ' ');
    1519           5 :         if (pin == NULL)
    1520           1 :                 return -1;
    1521           4 :         *pin++ = '\0';
    1522           4 :         pos = os_strchr(pin, ' ');
    1523           4 :         if (pos) {
    1524           4 :                 *pos++ = '\0';
    1525           4 :                 if (hwaddr_aton(pos, addr_buf) == 0)
    1526           4 :                         addr = addr_buf;
    1527             :         }
    1528           4 :         return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
    1529             : }
    1530             : 
    1531             : 
    1532           2 : static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
    1533             :                                                   char *cmd)
    1534             : {
    1535           2 :         char *uuid = cmd, *pin;
    1536           2 :         pin = os_strchr(uuid, ' ');
    1537           2 :         if (pin == NULL)
    1538           1 :                 return -1;
    1539           1 :         *pin++ = '\0';
    1540           1 :         return wpas_wps_er_learn(wpa_s, uuid, pin);
    1541             : }
    1542             : 
    1543             : 
    1544           9 : static int wpa_supplicant_ctrl_iface_wps_er_set_config(
    1545             :         struct wpa_supplicant *wpa_s, char *cmd)
    1546             : {
    1547           9 :         char *uuid = cmd, *id;
    1548           9 :         id = os_strchr(uuid, ' ');
    1549           9 :         if (id == NULL)
    1550           1 :                 return -1;
    1551           8 :         *id++ = '\0';
    1552           8 :         return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
    1553             : }
    1554             : 
    1555             : 
    1556           6 : static int wpa_supplicant_ctrl_iface_wps_er_config(
    1557             :         struct wpa_supplicant *wpa_s, char *cmd)
    1558             : {
    1559             :         char *pin;
    1560             :         char *new_ssid;
    1561             :         char *new_auth;
    1562             :         char *new_encr;
    1563             :         char *new_key;
    1564             :         struct wps_new_ap_settings ap;
    1565             : 
    1566           6 :         pin = os_strchr(cmd, ' ');
    1567           6 :         if (pin == NULL)
    1568           1 :                 return -1;
    1569           5 :         *pin++ = '\0';
    1570             : 
    1571           5 :         new_ssid = os_strchr(pin, ' ');
    1572           5 :         if (new_ssid == NULL)
    1573           1 :                 return -1;
    1574           4 :         *new_ssid++ = '\0';
    1575             : 
    1576           4 :         new_auth = os_strchr(new_ssid, ' ');
    1577           4 :         if (new_auth == NULL)
    1578           1 :                 return -1;
    1579           3 :         *new_auth++ = '\0';
    1580             : 
    1581           3 :         new_encr = os_strchr(new_auth, ' ');
    1582           3 :         if (new_encr == NULL)
    1583           1 :                 return -1;
    1584           2 :         *new_encr++ = '\0';
    1585             : 
    1586           2 :         new_key = os_strchr(new_encr, ' ');
    1587           2 :         if (new_key == NULL)
    1588           1 :                 return -1;
    1589           1 :         *new_key++ = '\0';
    1590             : 
    1591           1 :         os_memset(&ap, 0, sizeof(ap));
    1592           1 :         ap.ssid_hex = new_ssid;
    1593           1 :         ap.auth = new_auth;
    1594           1 :         ap.encr = new_encr;
    1595           1 :         ap.key_hex = new_key;
    1596           1 :         return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
    1597             : }
    1598             : 
    1599             : 
    1600             : #ifdef CONFIG_WPS_NFC
    1601           5 : static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
    1602             :         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
    1603             : {
    1604             :         int ndef;
    1605             :         struct wpabuf *buf;
    1606             :         int res;
    1607             :         char *uuid;
    1608             : 
    1609           5 :         uuid = os_strchr(cmd, ' ');
    1610           5 :         if (uuid == NULL)
    1611           1 :                 return -1;
    1612           4 :         *uuid++ = '\0';
    1613             : 
    1614           4 :         if (os_strcmp(cmd, "WPS") == 0)
    1615           1 :                 ndef = 0;
    1616           3 :         else if (os_strcmp(cmd, "NDEF") == 0)
    1617           2 :                 ndef = 1;
    1618             :         else
    1619           1 :                 return -1;
    1620             : 
    1621           3 :         buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
    1622           3 :         if (buf == NULL)
    1623           1 :                 return -1;
    1624             : 
    1625           2 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    1626             :                                          wpabuf_len(buf));
    1627           2 :         reply[res++] = '\n';
    1628           2 :         reply[res] = '\0';
    1629             : 
    1630           2 :         wpabuf_free(buf);
    1631             : 
    1632           2 :         return res;
    1633             : }
    1634             : #endif /* CONFIG_WPS_NFC */
    1635             : #endif /* CONFIG_WPS_ER */
    1636             : 
    1637             : #endif /* CONFIG_WPS */
    1638             : 
    1639             : 
    1640             : #ifdef CONFIG_IBSS_RSN
    1641           2 : static int wpa_supplicant_ctrl_iface_ibss_rsn(
    1642             :         struct wpa_supplicant *wpa_s, char *addr)
    1643             : {
    1644             :         u8 peer[ETH_ALEN];
    1645             : 
    1646           2 :         if (hwaddr_aton(addr, peer)) {
    1647           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
    1648             :                            "address '%s'", addr);
    1649           1 :                 return -1;
    1650             :         }
    1651             : 
    1652           6 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
    1653           6 :                    MAC2STR(peer));
    1654             : 
    1655           1 :         return ibss_rsn_start(wpa_s->ibss_rsn, peer);
    1656             : }
    1657             : #endif /* CONFIG_IBSS_RSN */
    1658             : 
    1659             : 
    1660          49 : static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
    1661             :                                               char *rsp)
    1662             : {
    1663             : #ifdef IEEE8021X_EAPOL
    1664             :         char *pos, *id_pos;
    1665             :         int id;
    1666             :         struct wpa_ssid *ssid;
    1667             : 
    1668          49 :         pos = os_strchr(rsp, '-');
    1669          49 :         if (pos == NULL)
    1670           1 :                 return -1;
    1671          48 :         *pos++ = '\0';
    1672          48 :         id_pos = pos;
    1673          48 :         pos = os_strchr(pos, ':');
    1674          48 :         if (pos == NULL)
    1675           2 :                 return -1;
    1676          46 :         *pos++ = '\0';
    1677          46 :         id = atoi(id_pos);
    1678          46 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
    1679          46 :         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
    1680             :                               (u8 *) pos, os_strlen(pos));
    1681             : 
    1682          46 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    1683          46 :         if (ssid == NULL) {
    1684           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
    1685             :                            "to update", id);
    1686           1 :                 return -1;
    1687             :         }
    1688             : 
    1689          45 :         return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
    1690             :                                                          pos);
    1691             : #else /* IEEE8021X_EAPOL */
    1692             :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
    1693             :         return -1;
    1694             : #endif /* IEEE8021X_EAPOL */
    1695             : }
    1696             : 
    1697             : 
    1698        6840 : static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
    1699             :                                             const char *params,
    1700             :                                             char *buf, size_t buflen)
    1701             : {
    1702             :         char *pos, *end, tmp[30];
    1703             :         int res, verbose, wps, ret;
    1704             : #ifdef CONFIG_HS20
    1705             :         const u8 *hs20;
    1706             : #endif /* CONFIG_HS20 */
    1707             :         const u8 *sess_id;
    1708             :         size_t sess_id_len;
    1709             : 
    1710        6840 :         if (os_strcmp(params, "-DRIVER") == 0)
    1711        4242 :                 return wpa_drv_status(wpa_s, buf, buflen);
    1712        2598 :         verbose = os_strcmp(params, "-VERBOSE") == 0;
    1713        2598 :         wps = os_strcmp(params, "-WPS") == 0;
    1714        2598 :         pos = buf;
    1715        2598 :         end = buf + buflen;
    1716        2598 :         if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
    1717        2010 :                 struct wpa_ssid *ssid = wpa_s->current_ssid;
    1718       12060 :                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
    1719       12060 :                                   MAC2STR(wpa_s->bssid));
    1720        2010 :                 if (os_snprintf_error(end - pos, ret))
    1721           0 :                         return pos - buf;
    1722        2010 :                 pos += ret;
    1723        2010 :                 ret = os_snprintf(pos, end - pos, "freq=%u\n",
    1724             :                                   wpa_s->assoc_freq);
    1725        2010 :                 if (os_snprintf_error(end - pos, ret))
    1726           0 :                         return pos - buf;
    1727        2010 :                 pos += ret;
    1728        2010 :                 if (ssid) {
    1729        2010 :                         u8 *_ssid = ssid->ssid;
    1730        2010 :                         size_t ssid_len = ssid->ssid_len;
    1731             :                         u8 ssid_buf[MAX_SSID_LEN];
    1732        2010 :                         if (ssid_len == 0) {
    1733           1 :                                 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
    1734           1 :                                 if (_res < 0)
    1735           0 :                                         ssid_len = 0;
    1736             :                                 else
    1737           1 :                                         ssid_len = _res;
    1738           1 :                                 _ssid = ssid_buf;
    1739             :                         }
    1740        2010 :                         ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
    1741             :                                           wpa_ssid_txt(_ssid, ssid_len),
    1742             :                                           ssid->id);
    1743        2010 :                         if (os_snprintf_error(end - pos, ret))
    1744           0 :                                 return pos - buf;
    1745        2010 :                         pos += ret;
    1746             : 
    1747        2012 :                         if (wps && ssid->passphrase &&
    1748           4 :                             wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
    1749           4 :                             (ssid->mode == WPAS_MODE_AP ||
    1750           2 :                              ssid->mode == WPAS_MODE_P2P_GO)) {
    1751           2 :                                 ret = os_snprintf(pos, end - pos,
    1752             :                                                   "passphrase=%s\n",
    1753             :                                                   ssid->passphrase);
    1754           2 :                                 if (os_snprintf_error(end - pos, ret))
    1755           0 :                                         return pos - buf;
    1756           2 :                                 pos += ret;
    1757             :                         }
    1758        2010 :                         if (ssid->id_str) {
    1759           1 :                                 ret = os_snprintf(pos, end - pos,
    1760             :                                                   "id_str=%s\n",
    1761             :                                                   ssid->id_str);
    1762           1 :                                 if (os_snprintf_error(end - pos, ret))
    1763           0 :                                         return pos - buf;
    1764           1 :                                 pos += ret;
    1765             :                         }
    1766             : 
    1767        2010 :                         switch (ssid->mode) {
    1768             :                         case WPAS_MODE_INFRA:
    1769        1778 :                                 ret = os_snprintf(pos, end - pos,
    1770             :                                                   "mode=station\n");
    1771        1778 :                                 break;
    1772             :                         case WPAS_MODE_IBSS:
    1773          37 :                                 ret = os_snprintf(pos, end - pos,
    1774             :                                                   "mode=IBSS\n");
    1775          37 :                                 break;
    1776             :                         case WPAS_MODE_AP:
    1777           9 :                                 ret = os_snprintf(pos, end - pos,
    1778             :                                                   "mode=AP\n");
    1779           9 :                                 break;
    1780             :                         case WPAS_MODE_P2P_GO:
    1781         184 :                                 ret = os_snprintf(pos, end - pos,
    1782             :                                                   "mode=P2P GO\n");
    1783         184 :                                 break;
    1784             :                         case WPAS_MODE_P2P_GROUP_FORMATION:
    1785           2 :                                 ret = os_snprintf(pos, end - pos,
    1786             :                                                   "mode=P2P GO - group "
    1787             :                                                   "formation\n");
    1788           2 :                                 break;
    1789             :                         default:
    1790           0 :                                 ret = 0;
    1791           0 :                                 break;
    1792             :                         }
    1793        2010 :                         if (os_snprintf_error(end - pos, ret))
    1794           0 :                                 return pos - buf;
    1795        2010 :                         pos += ret;
    1796             :                 }
    1797             : 
    1798             : #ifdef CONFIG_AP
    1799        2010 :                 if (wpa_s->ap_iface) {
    1800         195 :                         pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
    1801         195 :                                                             end - pos,
    1802             :                                                             verbose);
    1803             :                 } else
    1804             : #endif /* CONFIG_AP */
    1805        1815 :                 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
    1806             :         }
    1807             : #ifdef CONFIG_SAE
    1808        4608 :         if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
    1809             : #ifdef CONFIG_AP
    1810        3825 :             !wpa_s->ap_iface &&
    1811             : #endif /* CONFIG_AP */
    1812        1815 :             wpa_s->sme.sae.state == SAE_ACCEPTED) {
    1813          27 :                 ret = os_snprintf(pos, end - pos, "sae_group=%d\n",
    1814             :                                   wpa_s->sme.sae.group);
    1815          27 :                 if (os_snprintf_error(end - pos, ret))
    1816           0 :                         return pos - buf;
    1817          27 :                 pos += ret;
    1818             :         }
    1819             : #endif /* CONFIG_SAE */
    1820        2598 :         ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
    1821             :                           wpa_supplicant_state_txt(wpa_s->wpa_state));
    1822        2598 :         if (os_snprintf_error(end - pos, ret))
    1823           0 :                 return pos - buf;
    1824        2598 :         pos += ret;
    1825             : 
    1826        5196 :         if (wpa_s->l2 &&
    1827        2598 :             l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
    1828           1 :                 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
    1829           1 :                 if (os_snprintf_error(end - pos, ret))
    1830           0 :                         return pos - buf;
    1831           1 :                 pos += ret;
    1832             :         }
    1833             : 
    1834             : #ifdef CONFIG_P2P
    1835        2598 :         if (wpa_s->global->p2p) {
    1836       15528 :                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
    1837       15528 :                                   "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
    1838        2588 :                 if (os_snprintf_error(end - pos, ret))
    1839           0 :                         return pos - buf;
    1840        2588 :                 pos += ret;
    1841             :         }
    1842             : #endif /* CONFIG_P2P */
    1843             : 
    1844       15588 :         ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
    1845       15588 :                           MAC2STR(wpa_s->own_addr));
    1846        2598 :         if (os_snprintf_error(end - pos, ret))
    1847           0 :                 return pos - buf;
    1848        2598 :         pos += ret;
    1849             : 
    1850             : #ifdef CONFIG_HS20
    1851        4413 :         if (wpa_s->current_bss &&
    1852        1815 :             (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
    1853          47 :                                           HS20_IE_VENDOR_TYPE)) &&
    1854          94 :             wpa_s->wpa_proto == WPA_PROTO_RSN &&
    1855          47 :             wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
    1856          47 :                 int release = 1;
    1857          47 :                 if (hs20[1] >= 5) {
    1858          47 :                         u8 rel_num = (hs20[6] & 0xf0) >> 4;
    1859          47 :                         release = rel_num + 1;
    1860             :                 }
    1861          47 :                 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
    1862          47 :                 if (os_snprintf_error(end - pos, ret))
    1863           0 :                         return pos - buf;
    1864          47 :                 pos += ret;
    1865             :         }
    1866             : 
    1867        2598 :         if (wpa_s->current_ssid) {
    1868             :                 struct wpa_cred *cred;
    1869             :                 char *type;
    1870             : 
    1871        4128 :                 for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
    1872             :                         size_t i;
    1873             : 
    1874          48 :                         if (wpa_s->current_ssid->parent_cred != cred)
    1875           3 :                                 continue;
    1876             : 
    1877          45 :                         if (cred->provisioning_sp) {
    1878           6 :                                 ret = os_snprintf(pos, end - pos,
    1879             :                                                   "provisioning_sp=%s\n",
    1880             :                                                   cred->provisioning_sp);
    1881           6 :                                 if (os_snprintf_error(end - pos, ret))
    1882           0 :                                         return pos - buf;
    1883           6 :                                 pos += ret;
    1884             :                         }
    1885             : 
    1886          45 :                         if (!cred->domain)
    1887          21 :                                 goto no_domain;
    1888             : 
    1889          24 :                         i = 0;
    1890          24 :                         if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
    1891          24 :                                 struct wpabuf *names =
    1892          24 :                                         wpa_s->current_bss->anqp->domain_name;
    1893          25 :                                 for (i = 0; names && i < cred->num_domain; i++)
    1894             :                                 {
    1895          20 :                                         if (domain_name_list_contains(
    1896          20 :                                                     names, cred->domain[i], 1))
    1897          19 :                                                 break;
    1898             :                                 }
    1899          24 :                                 if (i == cred->num_domain)
    1900           1 :                                         i = 0; /* show first entry by default */
    1901             :                         }
    1902          24 :                         ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
    1903          24 :                                           cred->domain[i]);
    1904          24 :                         if (os_snprintf_error(end - pos, ret))
    1905           0 :                                 return pos - buf;
    1906          24 :                         pos += ret;
    1907             : 
    1908             :                 no_domain:
    1909          90 :                         if (wpa_s->current_bss == NULL ||
    1910          45 :                             wpa_s->current_bss->anqp == NULL)
    1911           0 :                                 res = -1;
    1912             :                         else
    1913          45 :                                 res = interworking_home_sp_cred(
    1914             :                                         wpa_s, cred,
    1915          45 :                                         wpa_s->current_bss->anqp->domain_name);
    1916          45 :                         if (res > 0)
    1917          23 :                                 type = "home";
    1918          22 :                         else if (res == 0)
    1919           3 :                                 type = "roaming";
    1920             :                         else
    1921          19 :                                 type = "unknown";
    1922             : 
    1923          45 :                         ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
    1924          45 :                         if (os_snprintf_error(end - pos, ret))
    1925           0 :                                 return pos - buf;
    1926          45 :                         pos += ret;
    1927             : 
    1928          45 :                         break;
    1929             :                 }
    1930             :         }
    1931             : #endif /* CONFIG_HS20 */
    1932             : 
    1933        4938 :         if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
    1934        2340 :             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
    1935         263 :                 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
    1936             :                                           verbose);
    1937         263 :                 if (res >= 0)
    1938         263 :                         pos += res;
    1939             :         }
    1940             : 
    1941        2598 :         sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
    1942        2598 :         if (sess_id) {
    1943         248 :                 char *start = pos;
    1944             : 
    1945         248 :                 ret = os_snprintf(pos, end - pos, "eap_session_id=");
    1946         248 :                 if (os_snprintf_error(end - pos, ret))
    1947           0 :                         return start - buf;
    1948         248 :                 pos += ret;
    1949         248 :                 ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len);
    1950         248 :                 if (ret <= 0)
    1951           0 :                         return start - buf;
    1952         248 :                 pos += ret;
    1953         248 :                 ret = os_snprintf(pos, end - pos, "\n");
    1954         248 :                 if (os_snprintf_error(end - pos, ret))
    1955           0 :                         return start - buf;
    1956         248 :                 pos += ret;
    1957             :         }
    1958             : 
    1959        2598 :         res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
    1960        2598 :         if (res >= 0)
    1961        2598 :                 pos += res;
    1962             : 
    1963             : #ifdef CONFIG_WPS
    1964             :         {
    1965             :                 char uuid_str[100];
    1966        2598 :                 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
    1967        2598 :                 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
    1968        2598 :                 if (os_snprintf_error(end - pos, ret))
    1969           0 :                         return pos - buf;
    1970        2598 :                 pos += ret;
    1971             :         }
    1972             : #endif /* CONFIG_WPS */
    1973             : 
    1974             : #ifdef ANDROID
    1975             :         /*
    1976             :          * Allow using the STATUS command with default behavior, say for debug,
    1977             :          * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
    1978             :          * events with STATUS-NO_EVENTS.
    1979             :          */
    1980             :         if (os_strcmp(params, "-NO_EVENTS")) {
    1981             :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
    1982             :                              "id=%d state=%d BSSID=" MACSTR " SSID=%s",
    1983             :                              wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
    1984             :                              wpa_s->wpa_state,
    1985             :                              MAC2STR(wpa_s->bssid),
    1986             :                              wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
    1987             :                              wpa_ssid_txt(wpa_s->current_ssid->ssid,
    1988             :                                           wpa_s->current_ssid->ssid_len) : "");
    1989             :                 if (wpa_s->wpa_state == WPA_COMPLETED) {
    1990             :                         struct wpa_ssid *ssid = wpa_s->current_ssid;
    1991             :                         wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
    1992             :                                      "- connection to " MACSTR
    1993             :                                      " completed %s [id=%d id_str=%s]",
    1994             :                                      MAC2STR(wpa_s->bssid), "(auth)",
    1995             :                                      ssid ? ssid->id : -1,
    1996             :                                      ssid && ssid->id_str ? ssid->id_str : "");
    1997             :                 }
    1998             :         }
    1999             : #endif /* ANDROID */
    2000             : 
    2001        2598 :         return pos - buf;
    2002             : }
    2003             : 
    2004             : 
    2005           5 : static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
    2006             :                                            char *cmd)
    2007             : {
    2008             :         char *pos;
    2009             :         int id;
    2010             :         struct wpa_ssid *ssid;
    2011             :         u8 bssid[ETH_ALEN];
    2012             : 
    2013             :         /* cmd: "<network id> <BSSID>" */
    2014           5 :         pos = os_strchr(cmd, ' ');
    2015           5 :         if (pos == NULL)
    2016           1 :                 return -1;
    2017           4 :         *pos++ = '\0';
    2018           4 :         id = atoi(cmd);
    2019           4 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
    2020           4 :         if (hwaddr_aton(pos, bssid)) {
    2021           1 :                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
    2022           1 :                 return -1;
    2023             :         }
    2024             : 
    2025           3 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    2026           3 :         if (ssid == NULL) {
    2027           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
    2028             :                            "to update", id);
    2029           1 :                 return -1;
    2030             :         }
    2031             : 
    2032           2 :         os_memcpy(ssid->bssid, bssid, ETH_ALEN);
    2033           2 :         ssid->bssid_set = !is_zero_ether_addr(bssid);
    2034             : 
    2035           2 :         return 0;
    2036             : }
    2037             : 
    2038             : 
    2039          14 : static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
    2040             :                                                char *cmd, char *buf,
    2041             :                                                size_t buflen)
    2042             : {
    2043             :         u8 bssid[ETH_ALEN];
    2044             :         struct wpa_blacklist *e;
    2045             :         char *pos, *end;
    2046             :         int ret;
    2047             : 
    2048             :         /* cmd: "BLACKLIST [<BSSID>]" */
    2049          14 :         if (*cmd == '\0') {
    2050           7 :                 pos = buf;
    2051           7 :                 end = buf + buflen;
    2052           7 :                 e = wpa_s->blacklist;
    2053          19 :                 while (e) {
    2054          30 :                         ret = os_snprintf(pos, end - pos, MACSTR "\n",
    2055          30 :                                           MAC2STR(e->bssid));
    2056           5 :                         if (os_snprintf_error(end - pos, ret))
    2057           0 :                                 return pos - buf;
    2058           5 :                         pos += ret;
    2059           5 :                         e = e->next;
    2060             :                 }
    2061           7 :                 return pos - buf;
    2062             :         }
    2063             : 
    2064           7 :         cmd++;
    2065           7 :         if (os_strncmp(cmd, "clear", 5) == 0) {
    2066           2 :                 wpa_blacklist_clear(wpa_s);
    2067           2 :                 os_memcpy(buf, "OK\n", 3);
    2068           2 :                 return 3;
    2069             :         }
    2070             : 
    2071           5 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
    2072           5 :         if (hwaddr_aton(cmd, bssid)) {
    2073           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
    2074           1 :                 return -1;
    2075             :         }
    2076             : 
    2077             :         /*
    2078             :          * Add the BSSID twice, so its count will be 2, causing it to be
    2079             :          * skipped when processing scan results.
    2080             :          */
    2081           4 :         ret = wpa_blacklist_add(wpa_s, bssid);
    2082           4 :         if (ret < 0)
    2083           1 :                 return -1;
    2084           3 :         ret = wpa_blacklist_add(wpa_s, bssid);
    2085           3 :         if (ret < 0)
    2086           0 :                 return -1;
    2087           3 :         os_memcpy(buf, "OK\n", 3);
    2088           3 :         return 3;
    2089             : }
    2090             : 
    2091             : 
    2092          10 : static const char * debug_level_str(int level)
    2093             : {
    2094          10 :         switch (level) {
    2095             :         case MSG_EXCESSIVE:
    2096           1 :                 return "EXCESSIVE";
    2097             :         case MSG_MSGDUMP:
    2098           5 :                 return "MSGDUMP";
    2099             :         case MSG_DEBUG:
    2100           1 :                 return "DEBUG";
    2101             :         case MSG_INFO:
    2102           1 :                 return "INFO";
    2103             :         case MSG_WARNING:
    2104           1 :                 return "WARNING";
    2105             :         case MSG_ERROR:
    2106           1 :                 return "ERROR";
    2107             :         default:
    2108           0 :                 return "?";
    2109             :         }
    2110             : }
    2111             : 
    2112             : 
    2113          11 : static int str_to_debug_level(const char *s)
    2114             : {
    2115          11 :         if (os_strcasecmp(s, "EXCESSIVE") == 0)
    2116           1 :                 return MSG_EXCESSIVE;
    2117          10 :         if (os_strcasecmp(s, "MSGDUMP") == 0)
    2118           5 :                 return MSG_MSGDUMP;
    2119           5 :         if (os_strcasecmp(s, "DEBUG") == 0)
    2120           1 :                 return MSG_DEBUG;
    2121           4 :         if (os_strcasecmp(s, "INFO") == 0)
    2122           1 :                 return MSG_INFO;
    2123           3 :         if (os_strcasecmp(s, "WARNING") == 0)
    2124           1 :                 return MSG_WARNING;
    2125           2 :         if (os_strcasecmp(s, "ERROR") == 0)
    2126           1 :                 return MSG_ERROR;
    2127           1 :         return -1;
    2128             : }
    2129             : 
    2130             : 
    2131          21 : static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
    2132             :                                                char *cmd, char *buf,
    2133             :                                                size_t buflen)
    2134             : {
    2135             :         char *pos, *end, *stamp;
    2136             :         int ret;
    2137             : 
    2138             :         /* cmd: "LOG_LEVEL [<level>]" */
    2139          21 :         if (*cmd == '\0') {
    2140          10 :                 pos = buf;
    2141          10 :                 end = buf + buflen;
    2142          10 :                 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
    2143             :                                   "Timestamp: %d\n",
    2144             :                                   debug_level_str(wpa_debug_level),
    2145             :                                   wpa_debug_timestamp);
    2146          10 :                 if (os_snprintf_error(end - pos, ret))
    2147           0 :                         ret = 0;
    2148             : 
    2149          10 :                 return ret;
    2150             :         }
    2151             : 
    2152          36 :         while (*cmd == ' ')
    2153          14 :                 cmd++;
    2154             : 
    2155          11 :         stamp = os_strchr(cmd, ' ');
    2156          11 :         if (stamp) {
    2157           3 :                 *stamp++ = '\0';
    2158           9 :                 while (*stamp == ' ') {
    2159           3 :                         stamp++;
    2160             :                 }
    2161             :         }
    2162             : 
    2163          11 :         if (cmd && os_strlen(cmd)) {
    2164          11 :                 int level = str_to_debug_level(cmd);
    2165          11 :                 if (level < 0)
    2166           1 :                         return -1;
    2167          10 :                 wpa_debug_level = level;
    2168             :         }
    2169             : 
    2170          10 :         if (stamp && os_strlen(stamp))
    2171           3 :                 wpa_debug_timestamp = atoi(stamp);
    2172             : 
    2173          10 :         os_memcpy(buf, "OK\n", 3);
    2174          10 :         return 3;
    2175             : }
    2176             : 
    2177             : 
    2178          25 : static int wpa_supplicant_ctrl_iface_list_networks(
    2179             :         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
    2180             : {
    2181             :         char *pos, *end, *prev;
    2182             :         struct wpa_ssid *ssid;
    2183             :         int ret;
    2184             : 
    2185          25 :         pos = buf;
    2186          25 :         end = buf + buflen;
    2187          25 :         ret = os_snprintf(pos, end - pos,
    2188             :                           "network id / ssid / bssid / flags\n");
    2189          25 :         if (os_snprintf_error(end - pos, ret))
    2190           0 :                 return pos - buf;
    2191          25 :         pos += ret;
    2192             : 
    2193          25 :         ssid = wpa_s->conf->ssid;
    2194             : 
    2195             :         /* skip over ssids until we find next one */
    2196          25 :         if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
    2197           1 :                 int last_id = atoi(cmd + 8);
    2198           1 :                 if (last_id != -1) {
    2199        1000 :                         while (ssid != NULL && ssid->id <= last_id) {
    2200         998 :                                 ssid = ssid->next;
    2201             :                         }
    2202             :                 }
    2203             :         }
    2204             : 
    2205         289 :         while (ssid) {
    2206         240 :                 prev = pos;
    2207         480 :                 ret = os_snprintf(pos, end - pos, "%d\t%s",
    2208             :                                   ssid->id,
    2209         240 :                                   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
    2210         240 :                 if (os_snprintf_error(end - pos, ret))
    2211           0 :                         return prev - buf;
    2212         240 :                 pos += ret;
    2213         240 :                 if (ssid->bssid_set) {
    2214          78 :                         ret = os_snprintf(pos, end - pos, "\t" MACSTR,
    2215          78 :                                           MAC2STR(ssid->bssid));
    2216             :                 } else {
    2217         227 :                         ret = os_snprintf(pos, end - pos, "\tany");
    2218             :                 }
    2219         240 :                 if (os_snprintf_error(end - pos, ret))
    2220           0 :                         return prev - buf;
    2221         240 :                 pos += ret;
    2222         960 :                 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
    2223         240 :                                   ssid == wpa_s->current_ssid ?
    2224             :                                   "[CURRENT]" : "",
    2225         240 :                                   ssid->disabled ? "[DISABLED]" : "",
    2226         240 :                                   ssid->disabled_until.sec ?
    2227             :                                   "[TEMP-DISABLED]" : "",
    2228         240 :                                   ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
    2229             :                                   "");
    2230         240 :                 if (os_snprintf_error(end - pos, ret))
    2231           1 :                         return prev - buf;
    2232         239 :                 pos += ret;
    2233         239 :                 ret = os_snprintf(pos, end - pos, "\n");
    2234         239 :                 if (os_snprintf_error(end - pos, ret))
    2235           0 :                         return prev - buf;
    2236         239 :                 pos += ret;
    2237             : 
    2238         239 :                 ssid = ssid->next;
    2239             :         }
    2240             : 
    2241          24 :         return pos - buf;
    2242             : }
    2243             : 
    2244             : 
    2245         334 : static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
    2246             : {
    2247             :         int ret;
    2248         334 :         ret = os_snprintf(pos, end - pos, "-");
    2249         334 :         if (os_snprintf_error(end - pos, ret))
    2250           0 :                 return pos;
    2251         334 :         pos += ret;
    2252         334 :         ret = wpa_write_ciphers(pos, end, cipher, "+");
    2253         334 :         if (ret < 0)
    2254           0 :                 return pos;
    2255         334 :         pos += ret;
    2256         334 :         return pos;
    2257             : }
    2258             : 
    2259             : 
    2260         334 : static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
    2261             :                                     const u8 *ie, size_t ie_len)
    2262             : {
    2263             :         struct wpa_ie_data data;
    2264             :         char *start;
    2265             :         int ret;
    2266             : 
    2267         334 :         ret = os_snprintf(pos, end - pos, "[%s-", proto);
    2268         334 :         if (os_snprintf_error(end - pos, ret))
    2269           0 :                 return pos;
    2270         334 :         pos += ret;
    2271             : 
    2272         334 :         if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
    2273           0 :                 ret = os_snprintf(pos, end - pos, "?]");
    2274           0 :                 if (os_snprintf_error(end - pos, ret))
    2275           0 :                         return pos;
    2276           0 :                 pos += ret;
    2277           0 :                 return pos;
    2278             :         }
    2279             : 
    2280         334 :         start = pos;
    2281         334 :         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
    2282         194 :                 ret = os_snprintf(pos, end - pos, "%sEAP",
    2283             :                                   pos == start ? "" : "+");
    2284         194 :                 if (os_snprintf_error(end - pos, ret))
    2285           0 :                         return pos;
    2286         194 :                 pos += ret;
    2287             :         }
    2288         334 :         if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
    2289         119 :                 ret = os_snprintf(pos, end - pos, "%sPSK",
    2290             :                                   pos == start ? "" : "+");
    2291         119 :                 if (os_snprintf_error(end - pos, ret))
    2292           0 :                         return pos;
    2293         119 :                 pos += ret;
    2294             :         }
    2295         334 :         if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
    2296           1 :                 ret = os_snprintf(pos, end - pos, "%sNone",
    2297             :                                   pos == start ? "" : "+");
    2298           1 :                 if (os_snprintf_error(end - pos, ret))
    2299           0 :                         return pos;
    2300           1 :                 pos += ret;
    2301             :         }
    2302         334 :         if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
    2303           3 :                 ret = os_snprintf(pos, end - pos, "%sSAE",
    2304             :                                   pos == start ? "" : "+");
    2305           3 :                 if (os_snprintf_error(end - pos, ret))
    2306           0 :                         return pos;
    2307           3 :                 pos += ret;
    2308             :         }
    2309             : #ifdef CONFIG_IEEE80211R
    2310         334 :         if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
    2311           7 :                 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
    2312             :                                   pos == start ? "" : "+");
    2313           7 :                 if (os_snprintf_error(end - pos, ret))
    2314           0 :                         return pos;
    2315           7 :                 pos += ret;
    2316             :         }
    2317         334 :         if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
    2318          19 :                 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
    2319             :                                   pos == start ? "" : "+");
    2320          19 :                 if (os_snprintf_error(end - pos, ret))
    2321           0 :                         return pos;
    2322          19 :                 pos += ret;
    2323             :         }
    2324         334 :         if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
    2325           4 :                 ret = os_snprintf(pos, end - pos, "%sFT/SAE",
    2326             :                                   pos == start ? "" : "+");
    2327           4 :                 if (os_snprintf_error(end - pos, ret))
    2328           0 :                         return pos;
    2329           4 :                 pos += ret;
    2330             :         }
    2331             : #endif /* CONFIG_IEEE80211R */
    2332             : #ifdef CONFIG_IEEE80211W
    2333         334 :         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
    2334           3 :                 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
    2335             :                                   pos == start ? "" : "+");
    2336           3 :                 if (os_snprintf_error(end - pos, ret))
    2337           0 :                         return pos;
    2338           3 :                 pos += ret;
    2339             :         }
    2340         334 :         if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
    2341           3 :                 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
    2342             :                                   pos == start ? "" : "+");
    2343           3 :                 if (os_snprintf_error(end - pos, ret))
    2344           0 :                         return pos;
    2345           3 :                 pos += ret;
    2346             :         }
    2347             : #endif /* CONFIG_IEEE80211W */
    2348             : 
    2349             : #ifdef CONFIG_SUITEB
    2350         334 :         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
    2351           1 :                 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
    2352             :                                   pos == start ? "" : "+");
    2353           1 :                 if (os_snprintf_error(end - pos, ret))
    2354           0 :                         return pos;
    2355           1 :                 pos += ret;
    2356             :         }
    2357             : #endif /* CONFIG_SUITEB */
    2358             : 
    2359             : #ifdef CONFIG_SUITEB192
    2360         334 :         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
    2361           1 :                 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
    2362             :                                   pos == start ? "" : "+");
    2363           1 :                 if (os_snprintf_error(end - pos, ret))
    2364           0 :                         return pos;
    2365           1 :                 pos += ret;
    2366             :         }
    2367             : #endif /* CONFIG_SUITEB192 */
    2368             : 
    2369         334 :         pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
    2370             : 
    2371         334 :         if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
    2372           4 :                 ret = os_snprintf(pos, end - pos, "-preauth");
    2373           4 :                 if (os_snprintf_error(end - pos, ret))
    2374           0 :                         return pos;
    2375           4 :                 pos += ret;
    2376             :         }
    2377             : 
    2378         334 :         ret = os_snprintf(pos, end - pos, "]");
    2379         334 :         if (os_snprintf_error(end - pos, ret))
    2380           0 :                 return pos;
    2381         334 :         pos += ret;
    2382             : 
    2383         334 :         return pos;
    2384             : }
    2385             : 
    2386             : 
    2387             : #ifdef CONFIG_WPS
    2388         463 : static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
    2389             :                                             char *pos, char *end,
    2390             :                                             struct wpabuf *wps_ie)
    2391             : {
    2392             :         int ret;
    2393             :         const char *txt;
    2394             : 
    2395         463 :         if (wps_ie == NULL)
    2396         350 :                 return pos;
    2397         113 :         if (wps_is_selected_pbc_registrar(wps_ie))
    2398          30 :                 txt = "[WPS-PBC]";
    2399          83 :         else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
    2400          27 :                 txt = "[WPS-AUTH]";
    2401          56 :         else if (wps_is_selected_pin_registrar(wps_ie))
    2402           1 :                 txt = "[WPS-PIN]";
    2403             :         else
    2404          55 :                 txt = "[WPS]";
    2405             : 
    2406         113 :         ret = os_snprintf(pos, end - pos, "%s", txt);
    2407         113 :         if (!os_snprintf_error(end - pos, ret))
    2408         113 :                 pos += ret;
    2409         113 :         wpabuf_free(wps_ie);
    2410         113 :         return pos;
    2411             : }
    2412             : #endif /* CONFIG_WPS */
    2413             : 
    2414             : 
    2415         463 : static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
    2416             :                                         char *pos, char *end,
    2417             :                                         const struct wpa_bss *bss)
    2418             : {
    2419             : #ifdef CONFIG_WPS
    2420             :         struct wpabuf *wps_ie;
    2421         463 :         wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    2422         463 :         return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
    2423             : #else /* CONFIG_WPS */
    2424             :         return pos;
    2425             : #endif /* CONFIG_WPS */
    2426             : }
    2427             : 
    2428             : 
    2429             : /* Format one result on one text line into a buffer. */
    2430          40 : static int wpa_supplicant_ctrl_iface_scan_result(
    2431             :         struct wpa_supplicant *wpa_s,
    2432             :         const struct wpa_bss *bss, char *buf, size_t buflen)
    2433             : {
    2434             :         char *pos, *end;
    2435             :         int ret;
    2436             :         const u8 *ie, *ie2, *p2p, *mesh;
    2437             : 
    2438          40 :         mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
    2439          40 :         p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
    2440          40 :         if (!p2p)
    2441          34 :                 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
    2442          40 :         if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
    2443           0 :             os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
    2444             :             0)
    2445           0 :                 return 0; /* Do not show P2P listen discovery results here */
    2446             : 
    2447          40 :         pos = buf;
    2448          40 :         end = buf + buflen;
    2449             : 
    2450         280 :         ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
    2451         240 :                           MAC2STR(bss->bssid), bss->freq, bss->level);
    2452          40 :         if (os_snprintf_error(end - pos, ret))
    2453           0 :                 return -1;
    2454          40 :         pos += ret;
    2455          40 :         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
    2456          40 :         if (ie)
    2457           2 :                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
    2458          40 :         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
    2459          40 :         if (ie2) {
    2460          17 :                 pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
    2461          17 :                                             ie2, 2 + ie2[1]);
    2462             :         }
    2463          40 :         pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
    2464          40 :         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
    2465           2 :                 ret = os_snprintf(pos, end - pos, "[WEP]");
    2466           2 :                 if (os_snprintf_error(end - pos, ret))
    2467           0 :                         return -1;
    2468           2 :                 pos += ret;
    2469             :         }
    2470          40 :         if (mesh) {
    2471           1 :                 ret = os_snprintf(pos, end - pos, "[MESH]");
    2472           1 :                 if (os_snprintf_error(end - pos, ret))
    2473           0 :                         return -1;
    2474           1 :                 pos += ret;
    2475             :         }
    2476          40 :         if (bss_is_dmg(bss)) {
    2477             :                 const char *s;
    2478           0 :                 ret = os_snprintf(pos, end - pos, "[DMG]");
    2479           0 :                 if (os_snprintf_error(end - pos, ret))
    2480           0 :                         return -1;
    2481           0 :                 pos += ret;
    2482           0 :                 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
    2483             :                 case IEEE80211_CAP_DMG_IBSS:
    2484           0 :                         s = "[IBSS]";
    2485           0 :                         break;
    2486             :                 case IEEE80211_CAP_DMG_AP:
    2487           0 :                         s = "[ESS]";
    2488           0 :                         break;
    2489             :                 case IEEE80211_CAP_DMG_PBSS:
    2490           0 :                         s = "[PBSS]";
    2491           0 :                         break;
    2492             :                 default:
    2493           0 :                         s = "";
    2494           0 :                         break;
    2495             :                 }
    2496           0 :                 ret = os_snprintf(pos, end - pos, "%s", s);
    2497           0 :                 if (os_snprintf_error(end - pos, ret))
    2498           0 :                         return -1;
    2499           0 :                 pos += ret;
    2500             :         } else {
    2501          40 :                 if (bss->caps & IEEE80211_CAP_IBSS) {
    2502           1 :                         ret = os_snprintf(pos, end - pos, "[IBSS]");
    2503           1 :                         if (os_snprintf_error(end - pos, ret))
    2504           0 :                                 return -1;
    2505           1 :                         pos += ret;
    2506             :                 }
    2507          40 :                 if (bss->caps & IEEE80211_CAP_ESS) {
    2508          38 :                         ret = os_snprintf(pos, end - pos, "[ESS]");
    2509          38 :                         if (os_snprintf_error(end - pos, ret))
    2510           0 :                                 return -1;
    2511          38 :                         pos += ret;
    2512             :                 }
    2513             :         }
    2514          40 :         if (p2p) {
    2515           6 :                 ret = os_snprintf(pos, end - pos, "[P2P]");
    2516           6 :                 if (os_snprintf_error(end - pos, ret))
    2517           0 :                         return -1;
    2518           6 :                 pos += ret;
    2519             :         }
    2520             : #ifdef CONFIG_HS20
    2521          40 :         if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
    2522           1 :                 ret = os_snprintf(pos, end - pos, "[HS20]");
    2523           1 :                 if (os_snprintf_error(end - pos, ret))
    2524           0 :                         return -1;
    2525           1 :                 pos += ret;
    2526             :         }
    2527             : #endif /* CONFIG_HS20 */
    2528             : 
    2529          80 :         ret = os_snprintf(pos, end - pos, "\t%s",
    2530          40 :                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
    2531          40 :         if (os_snprintf_error(end - pos, ret))
    2532           0 :                 return -1;
    2533          40 :         pos += ret;
    2534             : 
    2535          40 :         ret = os_snprintf(pos, end - pos, "\n");
    2536          40 :         if (os_snprintf_error(end - pos, ret))
    2537           0 :                 return -1;
    2538          40 :         pos += ret;
    2539             : 
    2540          40 :         return pos - buf;
    2541             : }
    2542             : 
    2543             : 
    2544          31 : static int wpa_supplicant_ctrl_iface_scan_results(
    2545             :         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
    2546             : {
    2547             :         char *pos, *end;
    2548             :         struct wpa_bss *bss;
    2549             :         int ret;
    2550             : 
    2551          31 :         pos = buf;
    2552          31 :         end = buf + buflen;
    2553          31 :         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
    2554             :                           "flags / ssid\n");
    2555          31 :         if (os_snprintf_error(end - pos, ret))
    2556           0 :                 return pos - buf;
    2557          31 :         pos += ret;
    2558             : 
    2559          71 :         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
    2560          40 :                 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
    2561          40 :                                                             end - pos);
    2562          40 :                 if (ret < 0 || ret >= end - pos)
    2563           0 :                         return pos - buf;
    2564          40 :                 pos += ret;
    2565             :         }
    2566             : 
    2567          31 :         return pos - buf;
    2568             : }
    2569             : 
    2570             : 
    2571             : #ifdef CONFIG_MESH
    2572             : 
    2573           4 : static int wpa_supplicant_ctrl_iface_mesh_interface_add(
    2574             :         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
    2575             : {
    2576             :         char *pos, ifname[IFNAMSIZ + 1];
    2577             : 
    2578           4 :         ifname[0] = '\0';
    2579             : 
    2580           4 :         pos = os_strstr(cmd, "ifname=");
    2581           4 :         if (pos) {
    2582           2 :                 pos += 7;
    2583           2 :                 os_strlcpy(ifname, pos, sizeof(ifname));
    2584             :         }
    2585             : 
    2586           4 :         if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0)
    2587           0 :                 return -1;
    2588             : 
    2589           4 :         os_strlcpy(reply, ifname, max_len);
    2590           4 :         return os_strlen(ifname);
    2591             : }
    2592             : 
    2593             : 
    2594          37 : static int wpa_supplicant_ctrl_iface_mesh_group_add(
    2595             :         struct wpa_supplicant *wpa_s, char *cmd)
    2596             : {
    2597             :         int id;
    2598             :         struct wpa_ssid *ssid;
    2599             : 
    2600          37 :         id = atoi(cmd);
    2601          37 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
    2602             : 
    2603          37 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    2604          37 :         if (ssid == NULL) {
    2605           1 :                 wpa_printf(MSG_DEBUG,
    2606             :                            "CTRL_IFACE: Could not find network id=%d", id);
    2607           1 :                 return -1;
    2608             :         }
    2609          36 :         if (ssid->mode != WPAS_MODE_MESH) {
    2610           1 :                 wpa_printf(MSG_DEBUG,
    2611             :                            "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
    2612           1 :                 return -1;
    2613             :         }
    2614          49 :         if (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
    2615          14 :             ssid->key_mgmt != WPA_KEY_MGMT_SAE) {
    2616           1 :                 wpa_printf(MSG_ERROR,
    2617             :                            "CTRL_IFACE: key_mgmt for mesh network should be open or SAE");
    2618           1 :                 return -1;
    2619             :         }
    2620             : 
    2621             :         /*
    2622             :          * TODO: If necessary write our own group_add function,
    2623             :          * for now we can reuse select_network
    2624             :          */
    2625          34 :         wpa_supplicant_select_network(wpa_s, ssid);
    2626             : 
    2627          34 :         return 0;
    2628             : }
    2629             : 
    2630             : 
    2631          17 : static int wpa_supplicant_ctrl_iface_mesh_group_remove(
    2632             :         struct wpa_supplicant *wpa_s, char *cmd)
    2633             : {
    2634             :         struct wpa_supplicant *orig;
    2635             :         struct wpa_global *global;
    2636          17 :         int found = 0;
    2637             : 
    2638          17 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
    2639             : 
    2640          17 :         global = wpa_s->global;
    2641          17 :         orig = wpa_s;
    2642             : 
    2643          24 :         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
    2644          19 :                 if (os_strcmp(wpa_s->ifname, cmd) == 0) {
    2645          12 :                         found = 1;
    2646          12 :                         break;
    2647             :                 }
    2648             :         }
    2649          17 :         if (!found) {
    2650           5 :                 wpa_printf(MSG_ERROR,
    2651             :                            "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found",
    2652             :                            cmd);
    2653           5 :                 return -1;
    2654             :         }
    2655          12 :         if (wpa_s->mesh_if_created && wpa_s == orig) {
    2656           2 :                 wpa_printf(MSG_ERROR,
    2657             :                            "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself");
    2658           2 :                 return -1;
    2659             :         }
    2660             : 
    2661          10 :         wpa_s->reassociate = 0;
    2662          10 :         wpa_s->disconnected = 1;
    2663          10 :         wpa_supplicant_cancel_sched_scan(wpa_s);
    2664          10 :         wpa_supplicant_cancel_scan(wpa_s);
    2665             : 
    2666             :         /*
    2667             :          * TODO: If necessary write our own group_remove function,
    2668             :          * for now we can reuse deauthenticate
    2669             :          */
    2670          10 :         wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
    2671             : 
    2672          10 :         if (wpa_s->mesh_if_created)
    2673           4 :                 wpa_supplicant_remove_iface(global, wpa_s, 0);
    2674             : 
    2675          10 :         return 0;
    2676             : }
    2677             : 
    2678             : #endif /* CONFIG_MESH */
    2679             : 
    2680             : 
    2681        1455 : static int wpa_supplicant_ctrl_iface_select_network(
    2682             :         struct wpa_supplicant *wpa_s, char *cmd)
    2683             : {
    2684             :         int id;
    2685             :         struct wpa_ssid *ssid;
    2686             :         char *pos;
    2687             : 
    2688             :         /* cmd: "<network id>" or "any" */
    2689        1455 :         if (os_strncmp(cmd, "any", 3) == 0) {
    2690           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
    2691           1 :                 ssid = NULL;
    2692             :         } else {
    2693        1454 :                 id = atoi(cmd);
    2694        1454 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
    2695             : 
    2696        1454 :                 ssid = wpa_config_get_network(wpa_s->conf, id);
    2697        1454 :                 if (ssid == NULL) {
    2698           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
    2699             :                                    "network id=%d", id);
    2700           1 :                         return -1;
    2701             :                 }
    2702        1453 :                 if (ssid->disabled == 2) {
    2703           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
    2704             :                                    "SELECT_NETWORK with persistent P2P group");
    2705           1 :                         return -1;
    2706             :                 }
    2707             :         }
    2708             : 
    2709        1453 :         pos = os_strstr(cmd, " freq=");
    2710        1453 :         if (pos) {
    2711          33 :                 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
    2712          33 :                 if (freqs) {
    2713          33 :                         wpa_s->scan_req = MANUAL_SCAN_REQ;
    2714          33 :                         os_free(wpa_s->manual_scan_freqs);
    2715          33 :                         wpa_s->manual_scan_freqs = freqs;
    2716             :                 }
    2717             :         }
    2718             : 
    2719        1453 :         wpa_supplicant_select_network(wpa_s, ssid);
    2720             : 
    2721        1453 :         return 0;
    2722             : }
    2723             : 
    2724             : 
    2725          33 : static int wpa_supplicant_ctrl_iface_enable_network(
    2726             :         struct wpa_supplicant *wpa_s, char *cmd)
    2727             : {
    2728             :         int id;
    2729             :         struct wpa_ssid *ssid;
    2730             : 
    2731             :         /* cmd: "<network id>" or "all" */
    2732          33 :         if (os_strcmp(cmd, "all") == 0) {
    2733           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
    2734           1 :                 ssid = NULL;
    2735             :         } else {
    2736          32 :                 id = atoi(cmd);
    2737          32 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
    2738             : 
    2739          32 :                 ssid = wpa_config_get_network(wpa_s->conf, id);
    2740          32 :                 if (ssid == NULL) {
    2741           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
    2742             :                                    "network id=%d", id);
    2743           1 :                         return -1;
    2744             :                 }
    2745          31 :                 if (ssid->disabled == 2) {
    2746           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
    2747             :                                    "ENABLE_NETWORK with persistent P2P group");
    2748           1 :                         return -1;
    2749             :                 }
    2750             : 
    2751          30 :                 if (os_strstr(cmd, " no-connect")) {
    2752          27 :                         ssid->disabled = 0;
    2753          27 :                         return 0;
    2754             :                 }
    2755             :         }
    2756           4 :         wpa_supplicant_enable_network(wpa_s, ssid);
    2757             : 
    2758           4 :         return 0;
    2759             : }
    2760             : 
    2761             : 
    2762           7 : static int wpa_supplicant_ctrl_iface_disable_network(
    2763             :         struct wpa_supplicant *wpa_s, char *cmd)
    2764             : {
    2765             :         int id;
    2766             :         struct wpa_ssid *ssid;
    2767             : 
    2768             :         /* cmd: "<network id>" or "all" */
    2769           7 :         if (os_strcmp(cmd, "all") == 0) {
    2770           2 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
    2771           2 :                 ssid = NULL;
    2772             :         } else {
    2773           5 :                 id = atoi(cmd);
    2774           5 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
    2775             : 
    2776           5 :                 ssid = wpa_config_get_network(wpa_s->conf, id);
    2777           5 :                 if (ssid == NULL) {
    2778           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
    2779             :                                    "network id=%d", id);
    2780           1 :                         return -1;
    2781             :                 }
    2782           4 :                 if (ssid->disabled == 2) {
    2783           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
    2784             :                                    "DISABLE_NETWORK with persistent P2P "
    2785             :                                    "group");
    2786           1 :                         return -1;
    2787             :                 }
    2788             :         }
    2789           5 :         wpa_supplicant_disable_network(wpa_s, ssid);
    2790             : 
    2791           5 :         return 0;
    2792             : }
    2793             : 
    2794             : 
    2795        2475 : static int wpa_supplicant_ctrl_iface_add_network(
    2796             :         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
    2797             : {
    2798             :         struct wpa_ssid *ssid;
    2799             :         int ret;
    2800             : 
    2801        2475 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
    2802             : 
    2803        2475 :         ssid = wpa_config_add_network(wpa_s->conf);
    2804        2475 :         if (ssid == NULL)
    2805           0 :                 return -1;
    2806             : 
    2807        2475 :         wpas_notify_network_added(wpa_s, ssid);
    2808             : 
    2809        2475 :         ssid->disabled = 1;
    2810        2475 :         wpa_config_set_network_defaults(ssid);
    2811             : 
    2812        2475 :         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
    2813        2475 :         if (os_snprintf_error(buflen, ret))
    2814           0 :                 return -1;
    2815        2475 :         return ret;
    2816             : }
    2817             : 
    2818             : 
    2819        4067 : static int wpa_supplicant_ctrl_iface_remove_network(
    2820             :         struct wpa_supplicant *wpa_s, char *cmd)
    2821             : {
    2822             :         int id;
    2823             :         struct wpa_ssid *ssid;
    2824             :         int was_disabled;
    2825             : 
    2826             :         /* cmd: "<network id>" or "all" */
    2827        4067 :         if (os_strcmp(cmd, "all") == 0) {
    2828        3947 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
    2829        3947 :                 if (wpa_s->sched_scanning)
    2830           0 :                         wpa_supplicant_cancel_sched_scan(wpa_s);
    2831             : 
    2832        3947 :                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
    2833        3947 :                 if (wpa_s->current_ssid) {
    2834             : #ifdef CONFIG_SME
    2835         622 :                         wpa_s->sme.prev_bssid_set = 0;
    2836             : #endif /* CONFIG_SME */
    2837         622 :                         wpa_sm_set_config(wpa_s->wpa, NULL);
    2838         622 :                         eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
    2839         622 :                         wpa_s->own_disconnect_req = 1;
    2840         622 :                         wpa_supplicant_deauthenticate(
    2841             :                                 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
    2842             :                 }
    2843        3947 :                 ssid = wpa_s->conf->ssid;
    2844       10457 :                 while (ssid) {
    2845        2563 :                         struct wpa_ssid *remove_ssid = ssid;
    2846        2563 :                         id = ssid->id;
    2847        2563 :                         ssid = ssid->next;
    2848        2563 :                         if (wpa_s->last_ssid == remove_ssid)
    2849        1383 :                                 wpa_s->last_ssid = NULL;
    2850        2563 :                         wpas_notify_network_removed(wpa_s, remove_ssid);
    2851        2563 :                         wpa_config_remove_network(wpa_s->conf, id);
    2852             :                 }
    2853        3947 :                 return 0;
    2854             :         }
    2855             : 
    2856         120 :         id = atoi(cmd);
    2857         120 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
    2858             : 
    2859         120 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    2860         120 :         if (ssid)
    2861         119 :                 wpas_notify_network_removed(wpa_s, ssid);
    2862         120 :         if (ssid == NULL) {
    2863           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
    2864             :                            "id=%d", id);
    2865           1 :                 return -1;
    2866             :         }
    2867             : 
    2868         119 :         if (wpa_s->last_ssid == ssid)
    2869          83 :                 wpa_s->last_ssid = NULL;
    2870             : 
    2871         119 :         if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
    2872             : #ifdef CONFIG_SME
    2873         118 :                 wpa_s->sme.prev_bssid_set = 0;
    2874             : #endif /* CONFIG_SME */
    2875             :                 /*
    2876             :                  * Invalidate the EAP session cache if the current or
    2877             :                  * previously used network is removed.
    2878             :                  */
    2879         118 :                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
    2880             :         }
    2881             : 
    2882         119 :         if (ssid == wpa_s->current_ssid) {
    2883          95 :                 wpa_sm_set_config(wpa_s->wpa, NULL);
    2884          95 :                 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
    2885             : 
    2886          95 :                 wpa_s->own_disconnect_req = 1;
    2887          95 :                 wpa_supplicant_deauthenticate(wpa_s,
    2888             :                                               WLAN_REASON_DEAUTH_LEAVING);
    2889             :         }
    2890             : 
    2891         119 :         was_disabled = ssid->disabled;
    2892             : 
    2893         119 :         if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
    2894           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
    2895             :                            "network id=%d", id);
    2896           0 :                 return -1;
    2897             :         }
    2898             : 
    2899         119 :         if (!was_disabled && wpa_s->sched_scanning) {
    2900           0 :                 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
    2901             :                            "network from filters");
    2902           0 :                 wpa_supplicant_cancel_sched_scan(wpa_s);
    2903           0 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
    2904             :         }
    2905             : 
    2906         119 :         return 0;
    2907             : }
    2908             : 
    2909             : 
    2910        7926 : static int wpa_supplicant_ctrl_iface_update_network(
    2911             :         struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
    2912             :         char *name, char *value)
    2913             : {
    2914        7926 :         if (wpa_config_set(ssid, name, value, 0) < 0) {
    2915          33 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
    2916             :                            "variable '%s'", name);
    2917          33 :                 return -1;
    2918             :         }
    2919             : 
    2920       15764 :         if (os_strcmp(name, "bssid") != 0 &&
    2921        7871 :             os_strcmp(name, "priority") != 0)
    2922        7870 :                 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
    2923             : 
    2924        7893 :         if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
    2925             :                 /*
    2926             :                  * Invalidate the EAP session cache if anything in the current
    2927             :                  * or previously used configuration changes.
    2928             :                  */
    2929        7869 :                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
    2930             :         }
    2931             : 
    2932        8183 :         if ((os_strcmp(name, "psk") == 0 &&
    2933        8186 :              value[0] == '"' && ssid->ssid_len) ||
    2934        9107 :             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
    2935         254 :                 wpa_config_update_psk(ssid);
    2936        7639 :         else if (os_strcmp(name, "priority") == 0)
    2937           1 :                 wpa_config_update_prio_list(wpa_s->conf);
    2938             : 
    2939        7893 :         return 0;
    2940             : }
    2941             : 
    2942             : 
    2943        7925 : static int wpa_supplicant_ctrl_iface_set_network(
    2944             :         struct wpa_supplicant *wpa_s, char *cmd)
    2945             : {
    2946             :         int id, ret, prev_bssid_set, prev_disabled;
    2947             :         struct wpa_ssid *ssid;
    2948             :         char *name, *value;
    2949             :         u8 prev_bssid[ETH_ALEN];
    2950             : 
    2951             :         /* cmd: "<network id> <variable name> <value>" */
    2952        7925 :         name = os_strchr(cmd, ' ');
    2953        7925 :         if (name == NULL)
    2954           1 :                 return -1;
    2955        7924 :         *name++ = '\0';
    2956             : 
    2957        7924 :         value = os_strchr(name, ' ');
    2958        7924 :         if (value == NULL)
    2959           1 :                 return -1;
    2960        7923 :         *value++ = '\0';
    2961             : 
    2962        7923 :         id = atoi(cmd);
    2963        7923 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
    2964             :                    id, name);
    2965        7923 :         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
    2966             :                               (u8 *) value, os_strlen(value));
    2967             : 
    2968        7923 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    2969        7923 :         if (ssid == NULL) {
    2970           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
    2971             :                            "id=%d", id);
    2972           1 :                 return -1;
    2973             :         }
    2974             : 
    2975        7922 :         prev_bssid_set = ssid->bssid_set;
    2976        7922 :         prev_disabled = ssid->disabled;
    2977        7922 :         os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
    2978        7922 :         ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
    2979             :                                                        value);
    2980       15811 :         if (ret == 0 &&
    2981       15757 :             (ssid->bssid_set != prev_bssid_set ||
    2982        7868 :              os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0))
    2983          22 :                 wpas_notify_network_bssid_set_changed(wpa_s, ssid);
    2984             : 
    2985        7922 :         if (prev_disabled != ssid->disabled &&
    2986          17 :             (prev_disabled == 2 || ssid->disabled == 2))
    2987           1 :                 wpas_notify_network_type_changed(wpa_s, ssid);
    2988             : 
    2989        7922 :         return ret;
    2990             : }
    2991             : 
    2992             : 
    2993          56 : static int wpa_supplicant_ctrl_iface_get_network(
    2994             :         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
    2995             : {
    2996             :         int id;
    2997             :         size_t res;
    2998             :         struct wpa_ssid *ssid;
    2999             :         char *name, *value;
    3000             : 
    3001             :         /* cmd: "<network id> <variable name>" */
    3002          56 :         name = os_strchr(cmd, ' ');
    3003          56 :         if (name == NULL || buflen == 0)
    3004           1 :                 return -1;
    3005          55 :         *name++ = '\0';
    3006             : 
    3007          55 :         id = atoi(cmd);
    3008          55 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
    3009             :                    id, name);
    3010             : 
    3011          55 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    3012          55 :         if (ssid == NULL) {
    3013           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
    3014             :                            "id=%d", id);
    3015           1 :                 return -1;
    3016             :         }
    3017             : 
    3018          54 :         value = wpa_config_get_no_key(ssid, name);
    3019          54 :         if (value == NULL) {
    3020           7 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
    3021             :                            "variable '%s'", name);
    3022           7 :                 return -1;
    3023             :         }
    3024             : 
    3025          47 :         res = os_strlcpy(buf, value, buflen);
    3026          47 :         if (res >= buflen) {
    3027           0 :                 os_free(value);
    3028           0 :                 return -1;
    3029             :         }
    3030             : 
    3031          47 :         os_free(value);
    3032             : 
    3033          47 :         return res;
    3034             : }
    3035             : 
    3036             : 
    3037          10 : static int wpa_supplicant_ctrl_iface_dup_network(
    3038             :         struct wpa_supplicant *wpa_s, char *cmd)
    3039             : {
    3040             :         struct wpa_ssid *ssid_s, *ssid_d;
    3041             :         char *name, *id, *value;
    3042             :         int id_s, id_d, ret;
    3043             : 
    3044             :         /* cmd: "<src network id> <dst network id> <variable name>" */
    3045          10 :         id = os_strchr(cmd, ' ');
    3046          10 :         if (id == NULL)
    3047           1 :                 return -1;
    3048           9 :         *id++ = '\0';
    3049             : 
    3050           9 :         name = os_strchr(id, ' ');
    3051           9 :         if (name == NULL)
    3052           2 :                 return -1;
    3053           7 :         *name++ = '\0';
    3054             : 
    3055           7 :         id_s = atoi(cmd);
    3056           7 :         id_d = atoi(id);
    3057           7 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: DUP_NETWORK id=%d -> %d name='%s'",
    3058             :                    id_s, id_d, name);
    3059             : 
    3060           7 :         ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
    3061           7 :         if (ssid_s == NULL) {
    3062           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
    3063             :                            "network id=%d", id_s);
    3064           1 :                 return -1;
    3065             :         }
    3066             : 
    3067           6 :         ssid_d = wpa_config_get_network(wpa_s->conf, id_d);
    3068           6 :         if (ssid_d == NULL) {
    3069           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
    3070             :                            "network id=%d", id_d);
    3071           1 :                 return -1;
    3072             :         }
    3073             : 
    3074           5 :         value = wpa_config_get(ssid_s, name);
    3075           5 :         if (value == NULL) {
    3076           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
    3077             :                            "variable '%s'", name);
    3078           1 :                 return -1;
    3079             :         }
    3080             : 
    3081           4 :         ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid_d, name,
    3082             :                                                        value);
    3083             : 
    3084           4 :         os_free(value);
    3085             : 
    3086           4 :         return ret;
    3087             : }
    3088             : 
    3089             : 
    3090           8 : static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
    3091             :                                                 char *buf, size_t buflen)
    3092             : {
    3093             :         char *pos, *end;
    3094             :         struct wpa_cred *cred;
    3095             :         int ret;
    3096             : 
    3097           8 :         pos = buf;
    3098           8 :         end = buf + buflen;
    3099           8 :         ret = os_snprintf(pos, end - pos,
    3100             :                           "cred id / realm / username / domain / imsi\n");
    3101           8 :         if (os_snprintf_error(end - pos, ret))
    3102           0 :                 return pos - buf;
    3103           8 :         pos += ret;
    3104             : 
    3105           8 :         cred = wpa_s->conf->cred;
    3106         111 :         while (cred) {
    3107         388 :                 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
    3108          96 :                                   cred->id, cred->realm ? cred->realm : "",
    3109          96 :                                   cred->username ? cred->username : "",
    3110         100 :                                   cred->domain ? cred->domain[0] : "",
    3111          96 :                                   cred->imsi ? cred->imsi : "");
    3112          96 :                 if (os_snprintf_error(end - pos, ret))
    3113           1 :                         return pos - buf;
    3114          95 :                 pos += ret;
    3115             : 
    3116          95 :                 cred = cred->next;
    3117             :         }
    3118             : 
    3119           7 :         return pos - buf;
    3120             : }
    3121             : 
    3122             : 
    3123         224 : static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
    3124             :                                               char *buf, size_t buflen)
    3125             : {
    3126             :         struct wpa_cred *cred;
    3127             :         int ret;
    3128             : 
    3129         224 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
    3130             : 
    3131         224 :         cred = wpa_config_add_cred(wpa_s->conf);
    3132         224 :         if (cred == NULL)
    3133           0 :                 return -1;
    3134             : 
    3135         224 :         wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
    3136             : 
    3137         224 :         ret = os_snprintf(buf, buflen, "%d\n", cred->id);
    3138         224 :         if (os_snprintf_error(buflen, ret))
    3139           0 :                 return -1;
    3140         224 :         return ret;
    3141             : }
    3142             : 
    3143             : 
    3144         222 : static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
    3145             :                                  struct wpa_cred *cred)
    3146             : {
    3147             :         struct wpa_ssid *ssid;
    3148             :         char str[20];
    3149             :         int id;
    3150             : 
    3151         222 :         if (cred == NULL) {
    3152           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
    3153           1 :                 return -1;
    3154             :         }
    3155             : 
    3156         221 :         id = cred->id;
    3157         221 :         if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
    3158           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
    3159           0 :                 return -1;
    3160             :         }
    3161             : 
    3162         221 :         wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
    3163             : 
    3164             :         /* Remove any network entry created based on the removed credential */
    3165         221 :         ssid = wpa_s->conf->ssid;
    3166         466 :         while (ssid) {
    3167          24 :                 if (ssid->parent_cred == cred) {
    3168             :                         int res;
    3169             : 
    3170          21 :                         wpa_printf(MSG_DEBUG, "Remove network id %d since it "
    3171             :                                    "used the removed credential", ssid->id);
    3172          21 :                         res = os_snprintf(str, sizeof(str), "%d", ssid->id);
    3173          21 :                         if (os_snprintf_error(sizeof(str), res))
    3174           0 :                                 str[sizeof(str) - 1] = '\0';
    3175          21 :                         ssid = ssid->next;
    3176          21 :                         wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
    3177             :                 } else
    3178           3 :                         ssid = ssid->next;
    3179             :         }
    3180             : 
    3181         221 :         return 0;
    3182             : }
    3183             : 
    3184             : 
    3185        3488 : static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
    3186             :                                                  char *cmd)
    3187             : {
    3188             :         int id;
    3189             :         struct wpa_cred *cred, *prev;
    3190             : 
    3191             :         /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
    3192             :          * "provisioning_sp=<FQDN> */
    3193        3488 :         if (os_strcmp(cmd, "all") == 0) {
    3194        3343 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
    3195        3343 :                 cred = wpa_s->conf->cred;
    3196        6761 :                 while (cred) {
    3197          75 :                         prev = cred;
    3198          75 :                         cred = cred->next;
    3199          75 :                         wpas_ctrl_remove_cred(wpa_s, prev);
    3200             :                 }
    3201        3343 :                 return 0;
    3202             :         }
    3203             : 
    3204         145 :         if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
    3205           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
    3206             :                            cmd + 8);
    3207           1 :                 cred = wpa_s->conf->cred;
    3208           5 :                 while (cred) {
    3209           3 :                         prev = cred;
    3210           3 :                         cred = cred->next;
    3211           3 :                         if (prev->domain) {
    3212             :                                 size_t i;
    3213           8 :                                 for (i = 0; i < prev->num_domain; i++) {
    3214           3 :                                         if (os_strcmp(prev->domain[i], cmd + 8)
    3215             :                                             != 0)
    3216           1 :                                                 continue;
    3217           2 :                                         wpas_ctrl_remove_cred(wpa_s, prev);
    3218           2 :                                         break;
    3219             :                                 }
    3220             :                         }
    3221             :                 }
    3222           1 :                 return 0;
    3223             :         }
    3224             : 
    3225         144 :         if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
    3226           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
    3227             :                            cmd + 16);
    3228           1 :                 cred = wpa_s->conf->cred;
    3229           5 :                 while (cred) {
    3230           3 :                         prev = cred;
    3231           3 :                         cred = cred->next;
    3232           6 :                         if (prev->provisioning_sp &&
    3233           3 :                             os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
    3234           2 :                                 wpas_ctrl_remove_cred(wpa_s, prev);
    3235             :                 }
    3236           1 :                 return 0;
    3237             :         }
    3238             : 
    3239         143 :         id = atoi(cmd);
    3240         143 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
    3241             : 
    3242         143 :         cred = wpa_config_get_cred(wpa_s->conf, id);
    3243         143 :         return wpas_ctrl_remove_cred(wpa_s, cred);
    3244             : }
    3245             : 
    3246             : 
    3247         750 : static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
    3248             :                                               char *cmd)
    3249             : {
    3250             :         int id;
    3251             :         struct wpa_cred *cred;
    3252             :         char *name, *value;
    3253             : 
    3254             :         /* cmd: "<cred id> <variable name> <value>" */
    3255         750 :         name = os_strchr(cmd, ' ');
    3256         750 :         if (name == NULL)
    3257           1 :                 return -1;
    3258         749 :         *name++ = '\0';
    3259             : 
    3260         749 :         value = os_strchr(name, ' ');
    3261         749 :         if (value == NULL)
    3262           1 :                 return -1;
    3263         748 :         *value++ = '\0';
    3264             : 
    3265         748 :         id = atoi(cmd);
    3266         748 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
    3267             :                    id, name);
    3268         748 :         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
    3269             :                               (u8 *) value, os_strlen(value));
    3270             : 
    3271         748 :         cred = wpa_config_get_cred(wpa_s->conf, id);
    3272         748 :         if (cred == NULL) {
    3273           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
    3274             :                            id);
    3275           1 :                 return -1;
    3276             :         }
    3277             : 
    3278         747 :         if (wpa_config_set_cred(cred, name, value, 0) < 0) {
    3279          13 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
    3280             :                            "variable '%s'", name);
    3281          13 :                 return -1;
    3282             :         }
    3283             : 
    3284         734 :         wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
    3285             : 
    3286         734 :         return 0;
    3287             : }
    3288             : 
    3289             : 
    3290          39 : static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
    3291             :                                               char *cmd, char *buf,
    3292             :                                               size_t buflen)
    3293             : {
    3294             :         int id;
    3295             :         size_t res;
    3296             :         struct wpa_cred *cred;
    3297             :         char *name, *value;
    3298             : 
    3299             :         /* cmd: "<cred id> <variable name>" */
    3300          39 :         name = os_strchr(cmd, ' ');
    3301          39 :         if (name == NULL)
    3302           1 :                 return -1;
    3303          38 :         *name++ = '\0';
    3304             : 
    3305          38 :         id = atoi(cmd);
    3306          38 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
    3307             :                    id, name);
    3308             : 
    3309          38 :         cred = wpa_config_get_cred(wpa_s->conf, id);
    3310          38 :         if (cred == NULL) {
    3311           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
    3312             :                            id);
    3313           1 :                 return -1;
    3314             :         }
    3315             : 
    3316          37 :         value = wpa_config_get_cred_no_key(cred, name);
    3317          37 :         if (value == NULL) {
    3318           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
    3319             :                            name);
    3320           1 :                 return -1;
    3321             :         }
    3322             : 
    3323          36 :         res = os_strlcpy(buf, value, buflen);
    3324          36 :         if (res >= buflen) {
    3325           0 :                 os_free(value);
    3326           0 :                 return -1;
    3327             :         }
    3328             : 
    3329          36 :         os_free(value);
    3330             : 
    3331          36 :         return res;
    3332             : }
    3333             : 
    3334             : 
    3335             : #ifndef CONFIG_NO_CONFIG_WRITE
    3336           4 : static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
    3337             : {
    3338             :         int ret;
    3339             : 
    3340           4 :         if (!wpa_s->conf->update_config) {
    3341           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
    3342             :                            "to update configuration (update_config=0)");
    3343           1 :                 return -1;
    3344             :         }
    3345             : 
    3346           3 :         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
    3347           3 :         if (ret) {
    3348           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
    3349             :                            "update configuration");
    3350             :         } else {
    3351           2 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
    3352             :                            " updated");
    3353             :         }
    3354             : 
    3355           3 :         return ret;
    3356             : }
    3357             : #endif /* CONFIG_NO_CONFIG_WRITE */
    3358             : 
    3359             : 
    3360             : struct cipher_info {
    3361             :         unsigned int capa;
    3362             :         const char *name;
    3363             :         int group_only;
    3364             : };
    3365             : 
    3366             : static const struct cipher_info ciphers[] = {
    3367             :         { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
    3368             :         { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
    3369             :         { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
    3370             :         { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
    3371             :         { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
    3372             :         { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
    3373             :         { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
    3374             :         { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
    3375             : };
    3376             : 
    3377             : static const struct cipher_info ciphers_group_mgmt[] = {
    3378             :         { WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 },
    3379             :         { WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 },
    3380             :         { WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 },
    3381             :         { WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 },
    3382             : };
    3383             : 
    3384             : 
    3385           8 : static int ctrl_iface_get_capability_pairwise(int res, char *strict,
    3386             :                                               struct wpa_driver_capa *capa,
    3387             :                                               char *buf, size_t buflen)
    3388             : {
    3389             :         int ret;
    3390             :         char *pos, *end;
    3391             :         size_t len;
    3392             :         unsigned int i;
    3393             : 
    3394           8 :         pos = buf;
    3395           8 :         end = pos + buflen;
    3396             : 
    3397           8 :         if (res < 0) {
    3398           0 :                 if (strict)
    3399           0 :                         return 0;
    3400           0 :                 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
    3401           0 :                 if (len >= buflen)
    3402           0 :                         return -1;
    3403           0 :                 return len;
    3404             :         }
    3405             : 
    3406          72 :         for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
    3407          64 :                 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
    3408          40 :                         ret = os_snprintf(pos, end - pos, "%s%s",
    3409             :                                           pos == buf ? "" : " ",
    3410             :                                           ciphers[i].name);
    3411          40 :                         if (os_snprintf_error(end - pos, ret))
    3412           0 :                                 return pos - buf;
    3413          40 :                         pos += ret;
    3414             :                 }
    3415             :         }
    3416             : 
    3417           8 :         return pos - buf;
    3418             : }
    3419             : 
    3420             : 
    3421           1 : static int ctrl_iface_get_capability_group(int res, char *strict,
    3422             :                                            struct wpa_driver_capa *capa,
    3423             :                                            char *buf, size_t buflen)
    3424             : {
    3425             :         int ret;
    3426             :         char *pos, *end;
    3427             :         size_t len;
    3428             :         unsigned int i;
    3429             : 
    3430           1 :         pos = buf;
    3431           1 :         end = pos + buflen;
    3432             : 
    3433           1 :         if (res < 0) {
    3434           0 :                 if (strict)
    3435           0 :                         return 0;
    3436           0 :                 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
    3437           0 :                 if (len >= buflen)
    3438           0 :                         return -1;
    3439           0 :                 return len;
    3440             :         }
    3441             : 
    3442           9 :         for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
    3443           8 :                 if (capa->enc & ciphers[i].capa) {
    3444           7 :                         ret = os_snprintf(pos, end - pos, "%s%s",
    3445             :                                           pos == buf ? "" : " ",
    3446             :                                           ciphers[i].name);
    3447           7 :                         if (os_snprintf_error(end - pos, ret))
    3448           0 :                                 return pos - buf;
    3449           7 :                         pos += ret;
    3450             :                 }
    3451             :         }
    3452             : 
    3453           1 :         return pos - buf;
    3454             : }
    3455             : 
    3456             : 
    3457           6 : static int ctrl_iface_get_capability_group_mgmt(int res, char *strict,
    3458             :                                                 struct wpa_driver_capa *capa,
    3459             :                                                 char *buf, size_t buflen)
    3460             : {
    3461             :         int ret;
    3462             :         char *pos, *end;
    3463             :         unsigned int i;
    3464             : 
    3465           6 :         pos = buf;
    3466           6 :         end = pos + buflen;
    3467             : 
    3468           6 :         if (res < 0)
    3469           0 :                 return 0;
    3470             : 
    3471          30 :         for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) {
    3472          24 :                 if (capa->enc & ciphers_group_mgmt[i].capa) {
    3473          24 :                         ret = os_snprintf(pos, end - pos, "%s%s",
    3474             :                                           pos == buf ? "" : " ",
    3475             :                                           ciphers_group_mgmt[i].name);
    3476          24 :                         if (os_snprintf_error(end - pos, ret))
    3477           0 :                                 return pos - buf;
    3478          24 :                         pos += ret;
    3479             :                 }
    3480             :         }
    3481             : 
    3482           6 :         return pos - buf;
    3483             : }
    3484             : 
    3485             : 
    3486           3 : static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
    3487             :                                               struct wpa_driver_capa *capa,
    3488             :                                               char *buf, size_t buflen)
    3489             : {
    3490             :         int ret;
    3491             :         char *pos, *end;
    3492             :         size_t len;
    3493             : 
    3494           3 :         pos = buf;
    3495           3 :         end = pos + buflen;
    3496             : 
    3497           3 :         if (res < 0) {
    3498           0 :                 if (strict)
    3499           0 :                         return 0;
    3500           0 :                 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
    3501             :                                  "NONE", buflen);
    3502           0 :                 if (len >= buflen)
    3503           0 :                         return -1;
    3504           0 :                 return len;
    3505             :         }
    3506             : 
    3507           3 :         ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
    3508           3 :         if (os_snprintf_error(end - pos, ret))
    3509           0 :                 return pos - buf;
    3510           3 :         pos += ret;
    3511             : 
    3512           3 :         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
    3513             :                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
    3514           3 :                 ret = os_snprintf(pos, end - pos, " WPA-EAP");
    3515           3 :                 if (os_snprintf_error(end - pos, ret))
    3516           0 :                         return pos - buf;
    3517           3 :                 pos += ret;
    3518             :         }
    3519             : 
    3520           3 :         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
    3521             :                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
    3522           3 :                 ret = os_snprintf(pos, end - pos, " WPA-PSK");
    3523           3 :                 if (os_snprintf_error(end - pos, ret))
    3524           0 :                         return pos - buf;
    3525           3 :                 pos += ret;
    3526             :         }
    3527             : 
    3528           3 :         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
    3529           0 :                 ret = os_snprintf(pos, end - pos, " WPA-NONE");
    3530           0 :                 if (os_snprintf_error(end - pos, ret))
    3531           0 :                         return pos - buf;
    3532           0 :                 pos += ret;
    3533             :         }
    3534             : 
    3535             : #ifdef CONFIG_SUITEB
    3536           3 :         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) {
    3537           3 :                 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B");
    3538           3 :                 if (os_snprintf_error(end - pos, ret))
    3539           0 :                         return pos - buf;
    3540           3 :                 pos += ret;
    3541             :         }
    3542             : #endif /* CONFIG_SUITEB */
    3543             : #ifdef CONFIG_SUITEB192
    3544           3 :         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
    3545           3 :                 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192");
    3546           3 :                 if (os_snprintf_error(end - pos, ret))
    3547           0 :                         return pos - buf;
    3548           3 :                 pos += ret;
    3549             :         }
    3550             : #endif /* CONFIG_SUITEB192 */
    3551             : 
    3552           3 :         return pos - buf;
    3553             : }
    3554             : 
    3555             : 
    3556           1 : static int ctrl_iface_get_capability_proto(int res, char *strict,
    3557             :                                            struct wpa_driver_capa *capa,
    3558             :                                            char *buf, size_t buflen)
    3559             : {
    3560             :         int ret;
    3561             :         char *pos, *end;
    3562             :         size_t len;
    3563             : 
    3564           1 :         pos = buf;
    3565           1 :         end = pos + buflen;
    3566             : 
    3567           1 :         if (res < 0) {
    3568           0 :                 if (strict)
    3569           0 :                         return 0;
    3570           0 :                 len = os_strlcpy(buf, "RSN WPA", buflen);
    3571           0 :                 if (len >= buflen)
    3572           0 :                         return -1;
    3573           0 :                 return len;
    3574             :         }
    3575             : 
    3576           1 :         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
    3577             :                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
    3578           1 :                 ret = os_snprintf(pos, end - pos, "%sRSN",
    3579             :                                   pos == buf ? "" : " ");
    3580           1 :                 if (os_snprintf_error(end - pos, ret))
    3581           0 :                         return pos - buf;
    3582           1 :                 pos += ret;
    3583             :         }
    3584             : 
    3585           1 :         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
    3586             :                               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
    3587           1 :                 ret = os_snprintf(pos, end - pos, "%sWPA",
    3588             :                                   pos == buf ? "" : " ");
    3589           1 :                 if (os_snprintf_error(end - pos, ret))
    3590           0 :                         return pos - buf;
    3591           1 :                 pos += ret;
    3592             :         }
    3593             : 
    3594           1 :         return pos - buf;
    3595             : }
    3596             : 
    3597             : 
    3598          20 : static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
    3599             :                                               int res, char *strict,
    3600             :                                               struct wpa_driver_capa *capa,
    3601             :                                               char *buf, size_t buflen)
    3602             : {
    3603             :         int ret;
    3604             :         char *pos, *end;
    3605             :         size_t len;
    3606             : 
    3607          20 :         pos = buf;
    3608          20 :         end = pos + buflen;
    3609             : 
    3610          20 :         if (res < 0) {
    3611           0 :                 if (strict)
    3612           0 :                         return 0;
    3613           0 :                 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
    3614           0 :                 if (len >= buflen)
    3615           0 :                         return -1;
    3616           0 :                 return len;
    3617             :         }
    3618             : 
    3619          20 :         if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
    3620          20 :                 ret = os_snprintf(pos, end - pos, "%sOPEN",
    3621             :                                   pos == buf ? "" : " ");
    3622          20 :                 if (os_snprintf_error(end - pos, ret))
    3623           0 :                         return pos - buf;
    3624          20 :                 pos += ret;
    3625             :         }
    3626             : 
    3627          20 :         if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
    3628          20 :                 ret = os_snprintf(pos, end - pos, "%sSHARED",
    3629             :                                   pos == buf ? "" : " ");
    3630          20 :                 if (os_snprintf_error(end - pos, ret))
    3631           0 :                         return pos - buf;
    3632          20 :                 pos += ret;
    3633             :         }
    3634             : 
    3635          20 :         if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
    3636          20 :                 ret = os_snprintf(pos, end - pos, "%sLEAP",
    3637             :                                   pos == buf ? "" : " ");
    3638          20 :                 if (os_snprintf_error(end - pos, ret))
    3639           0 :                         return pos - buf;
    3640          20 :                 pos += ret;
    3641             :         }
    3642             : 
    3643             : #ifdef CONFIG_SAE
    3644          20 :         if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
    3645          20 :                 ret = os_snprintf(pos, end - pos, "%sSAE",
    3646             :                                   pos == buf ? "" : " ");
    3647          20 :                 if (os_snprintf_error(end - pos, ret))
    3648           0 :                         return pos - buf;
    3649          20 :                 pos += ret;
    3650             :         }
    3651             : #endif /* CONFIG_SAE */
    3652             : 
    3653          20 :         return pos - buf;
    3654             : }
    3655             : 
    3656             : 
    3657          20 : static int ctrl_iface_get_capability_modes(int res, char *strict,
    3658             :                                            struct wpa_driver_capa *capa,
    3659             :                                            char *buf, size_t buflen)
    3660             : {
    3661             :         int ret;
    3662             :         char *pos, *end;
    3663             :         size_t len;
    3664             : 
    3665          20 :         pos = buf;
    3666          20 :         end = pos + buflen;
    3667             : 
    3668          20 :         if (res < 0) {
    3669           0 :                 if (strict)
    3670           0 :                         return 0;
    3671           0 :                 len = os_strlcpy(buf, "IBSS AP", buflen);
    3672           0 :                 if (len >= buflen)
    3673           0 :                         return -1;
    3674           0 :                 return len;
    3675             :         }
    3676             : 
    3677          20 :         if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
    3678          20 :                 ret = os_snprintf(pos, end - pos, "%sIBSS",
    3679             :                                   pos == buf ? "" : " ");
    3680          20 :                 if (os_snprintf_error(end - pos, ret))
    3681           0 :                         return pos - buf;
    3682          20 :                 pos += ret;
    3683             :         }
    3684             : 
    3685          20 :         if (capa->flags & WPA_DRIVER_FLAGS_AP) {
    3686          20 :                 ret = os_snprintf(pos, end - pos, "%sAP",
    3687             :                                   pos == buf ? "" : " ");
    3688          20 :                 if (os_snprintf_error(end - pos, ret))
    3689           0 :                         return pos - buf;
    3690          20 :                 pos += ret;
    3691             :         }
    3692             : 
    3693             : #ifdef CONFIG_MESH
    3694          20 :         if (capa->flags & WPA_DRIVER_FLAGS_MESH) {
    3695          20 :                 ret = os_snprintf(pos, end - pos, "%sMESH",
    3696             :                                   pos == buf ? "" : " ");
    3697          20 :                 if (os_snprintf_error(end - pos, ret))
    3698           0 :                         return pos - buf;
    3699          20 :                 pos += ret;
    3700             :         }
    3701             : #endif /* CONFIG_MESH */
    3702             : 
    3703          20 :         return pos - buf;
    3704             : }
    3705             : 
    3706             : 
    3707           1 : static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
    3708             :                                               char *buf, size_t buflen)
    3709             : {
    3710             :         struct hostapd_channel_data *chnl;
    3711             :         int ret, i, j;
    3712             :         char *pos, *end, *hmode;
    3713             : 
    3714           1 :         pos = buf;
    3715           1 :         end = pos + buflen;
    3716             : 
    3717           4 :         for (j = 0; j < wpa_s->hw.num_modes; j++) {
    3718           3 :                 switch (wpa_s->hw.modes[j].mode) {
    3719             :                 case HOSTAPD_MODE_IEEE80211B:
    3720           1 :                         hmode = "B";
    3721           1 :                         break;
    3722             :                 case HOSTAPD_MODE_IEEE80211G:
    3723           1 :                         hmode = "G";
    3724           1 :                         break;
    3725             :                 case HOSTAPD_MODE_IEEE80211A:
    3726           1 :                         hmode = "A";
    3727           1 :                         break;
    3728             :                 case HOSTAPD_MODE_IEEE80211AD:
    3729           0 :                         hmode = "AD";
    3730           0 :                         break;
    3731             :                 default:
    3732           0 :                         continue;
    3733             :                 }
    3734           3 :                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
    3735           3 :                 if (os_snprintf_error(end - pos, ret))
    3736           0 :                         return pos - buf;
    3737           3 :                 pos += ret;
    3738           3 :                 chnl = wpa_s->hw.modes[j].channels;
    3739          55 :                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
    3740          52 :                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
    3741           0 :                                 continue;
    3742          52 :                         ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
    3743          52 :                         if (os_snprintf_error(end - pos, ret))
    3744           0 :                                 return pos - buf;
    3745          52 :                         pos += ret;
    3746             :                 }
    3747           3 :                 ret = os_snprintf(pos, end - pos, "\n");
    3748           3 :                 if (os_snprintf_error(end - pos, ret))
    3749           0 :                         return pos - buf;
    3750           3 :                 pos += ret;
    3751             :         }
    3752             : 
    3753           1 :         return pos - buf;
    3754             : }
    3755             : 
    3756             : 
    3757           1 : static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
    3758             :                                           char *buf, size_t buflen)
    3759             : {
    3760             :         struct hostapd_channel_data *chnl;
    3761             :         int ret, i, j;
    3762             :         char *pos, *end, *hmode;
    3763             : 
    3764           1 :         pos = buf;
    3765           1 :         end = pos + buflen;
    3766             : 
    3767           4 :         for (j = 0; j < wpa_s->hw.num_modes; j++) {
    3768           3 :                 switch (wpa_s->hw.modes[j].mode) {
    3769             :                 case HOSTAPD_MODE_IEEE80211B:
    3770           1 :                         hmode = "B";
    3771           1 :                         break;
    3772             :                 case HOSTAPD_MODE_IEEE80211G:
    3773           1 :                         hmode = "G";
    3774           1 :                         break;
    3775             :                 case HOSTAPD_MODE_IEEE80211A:
    3776           1 :                         hmode = "A";
    3777           1 :                         break;
    3778             :                 case HOSTAPD_MODE_IEEE80211AD:
    3779           0 :                         hmode = "AD";
    3780           0 :                         break;
    3781             :                 default:
    3782           0 :                         continue;
    3783             :                 }
    3784           3 :                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
    3785             :                                   hmode);
    3786           3 :                 if (os_snprintf_error(end - pos, ret))
    3787           0 :                         return pos - buf;
    3788           3 :                 pos += ret;
    3789           3 :                 chnl = wpa_s->hw.modes[j].channels;
    3790          55 :                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
    3791          52 :                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
    3792           0 :                                 continue;
    3793         208 :                         ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
    3794         104 :                                           chnl[i].chan, chnl[i].freq,
    3795          52 :                                           chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
    3796             :                                           " (NO_IR)" : "",
    3797          52 :                                           chnl[i].flag & HOSTAPD_CHAN_RADAR ?
    3798             :                                           " (DFS)" : "");
    3799             : 
    3800          52 :                         if (os_snprintf_error(end - pos, ret))
    3801           0 :                                 return pos - buf;
    3802          52 :                         pos += ret;
    3803             :                 }
    3804           3 :                 ret = os_snprintf(pos, end - pos, "\n");
    3805           3 :                 if (os_snprintf_error(end - pos, ret))
    3806           0 :                         return pos - buf;
    3807           3 :                 pos += ret;
    3808             :         }
    3809             : 
    3810           1 :         return pos - buf;
    3811             : }
    3812             : 
    3813             : 
    3814          88 : static int wpa_supplicant_ctrl_iface_get_capability(
    3815             :         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
    3816             :         size_t buflen)
    3817             : {
    3818             :         struct wpa_driver_capa capa;
    3819             :         int res;
    3820             :         char *strict;
    3821             :         char field[30];
    3822             :         size_t len;
    3823             : 
    3824             :         /* Determine whether or not strict checking was requested */
    3825          88 :         len = os_strlcpy(field, _field, sizeof(field));
    3826          88 :         if (len >= sizeof(field))
    3827           1 :                 return -1;
    3828          87 :         strict = os_strchr(field, ' ');
    3829          87 :         if (strict != NULL) {
    3830           2 :                 *strict++ = '\0';
    3831           2 :                 if (os_strcmp(strict, "strict") != 0)
    3832           1 :                         return -1;
    3833             :         }
    3834             : 
    3835          86 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
    3836             :                 field, strict ? strict : "");
    3837             : 
    3838          86 :         if (os_strcmp(field, "eap") == 0) {
    3839          17 :                 return eap_get_names(buf, buflen);
    3840             :         }
    3841             : 
    3842          69 :         res = wpa_drv_get_capa(wpa_s, &capa);
    3843             : 
    3844          69 :         if (os_strcmp(field, "pairwise") == 0)
    3845           8 :                 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
    3846             :                                                           buf, buflen);
    3847             : 
    3848          61 :         if (os_strcmp(field, "group") == 0)
    3849           1 :                 return ctrl_iface_get_capability_group(res, strict, &capa,
    3850             :                                                        buf, buflen);
    3851             : 
    3852          60 :         if (os_strcmp(field, "group_mgmt") == 0)
    3853           6 :                 return ctrl_iface_get_capability_group_mgmt(res, strict, &capa,
    3854             :                                                             buf, buflen);
    3855             : 
    3856          54 :         if (os_strcmp(field, "key_mgmt") == 0)
    3857           3 :                 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
    3858             :                                                           buf, buflen);
    3859             : 
    3860          51 :         if (os_strcmp(field, "proto") == 0)
    3861           1 :                 return ctrl_iface_get_capability_proto(res, strict, &capa,
    3862             :                                                        buf, buflen);
    3863             : 
    3864          50 :         if (os_strcmp(field, "auth_alg") == 0)
    3865          20 :                 return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict,
    3866             :                                                           &capa, buf, buflen);
    3867             : 
    3868          30 :         if (os_strcmp(field, "modes") == 0)
    3869          20 :                 return ctrl_iface_get_capability_modes(res, strict, &capa,
    3870             :                                                        buf, buflen);
    3871             : 
    3872          10 :         if (os_strcmp(field, "channels") == 0)
    3873           1 :                 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
    3874             : 
    3875           9 :         if (os_strcmp(field, "freq") == 0)
    3876           1 :                 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
    3877             : 
    3878             : #ifdef CONFIG_TDLS
    3879           8 :         if (os_strcmp(field, "tdls") == 0)
    3880           1 :                 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
    3881             : #endif /* CONFIG_TDLS */
    3882             : 
    3883             : #ifdef CONFIG_ERP
    3884           7 :         if (os_strcmp(field, "erp") == 0) {
    3885           6 :                 res = os_snprintf(buf, buflen, "ERP");
    3886           6 :                 if (os_snprintf_error(buflen, res))
    3887           0 :                         return -1;
    3888           6 :                 return res;
    3889             :         }
    3890             : #endif /* CONFIG_EPR */
    3891             : 
    3892           1 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
    3893             :                    field);
    3894             : 
    3895           1 :         return -1;
    3896             : }
    3897             : 
    3898             : 
    3899             : #ifdef CONFIG_INTERWORKING
    3900         588 : static char * anqp_add_hex(char *pos, char *end, const char *title,
    3901             :                            struct wpabuf *data)
    3902             : {
    3903         588 :         char *start = pos;
    3904             :         size_t i;
    3905             :         int ret;
    3906             :         const u8 *d;
    3907             : 
    3908         588 :         if (data == NULL)
    3909         413 :                 return start;
    3910             : 
    3911         175 :         ret = os_snprintf(pos, end - pos, "%s=", title);
    3912         175 :         if (os_snprintf_error(end - pos, ret))
    3913           0 :                 return start;
    3914         175 :         pos += ret;
    3915             : 
    3916         175 :         d = wpabuf_head_u8(data);
    3917        4914 :         for (i = 0; i < wpabuf_len(data); i++) {
    3918        4739 :                 ret = os_snprintf(pos, end - pos, "%02x", *d++);
    3919        4739 :                 if (os_snprintf_error(end - pos, ret))
    3920           0 :                         return start;
    3921        4739 :                 pos += ret;
    3922             :         }
    3923             : 
    3924         175 :         ret = os_snprintf(pos, end - pos, "\n");
    3925         175 :         if (os_snprintf_error(end - pos, ret))
    3926           0 :                 return start;
    3927         175 :         pos += ret;
    3928             : 
    3929         175 :         return pos;
    3930             : }
    3931             : #endif /* CONFIG_INTERWORKING */
    3932             : 
    3933             : 
    3934         587 : static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
    3935             :                           unsigned long mask, char *buf, size_t buflen)
    3936             : {
    3937             :         size_t i;
    3938             :         int ret;
    3939             :         char *pos, *end;
    3940             :         const u8 *ie, *ie2;
    3941             : 
    3942         587 :         pos = buf;
    3943         587 :         end = buf + buflen;
    3944             : 
    3945         587 :         if (mask & WPA_BSS_MASK_ID) {
    3946         446 :                 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
    3947         446 :                 if (os_snprintf_error(end - pos, ret))
    3948           0 :                         return 0;
    3949         446 :                 pos += ret;
    3950             :         }
    3951             : 
    3952         587 :         if (mask & WPA_BSS_MASK_BSSID) {
    3953        3384 :                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
    3954        3384 :                                   MAC2STR(bss->bssid));
    3955         564 :                 if (os_snprintf_error(end - pos, ret))
    3956           0 :                         return 0;
    3957         564 :                 pos += ret;
    3958             :         }
    3959             : 
    3960         587 :         if (mask & WPA_BSS_MASK_FREQ) {
    3961         423 :                 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
    3962         423 :                 if (os_snprintf_error(end - pos, ret))
    3963           0 :                         return 0;
    3964         423 :                 pos += ret;
    3965             :         }
    3966             : 
    3967         587 :         if (mask & WPA_BSS_MASK_BEACON_INT) {
    3968         423 :                 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
    3969         423 :                                   bss->beacon_int);
    3970         423 :                 if (os_snprintf_error(end - pos, ret))
    3971           0 :                         return 0;
    3972         423 :                 pos += ret;
    3973             :         }
    3974             : 
    3975         587 :         if (mask & WPA_BSS_MASK_CAPABILITIES) {
    3976         423 :                 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
    3977         423 :                                   bss->caps);
    3978         423 :                 if (os_snprintf_error(end - pos, ret))
    3979           0 :                         return 0;
    3980         423 :                 pos += ret;
    3981             :         }
    3982             : 
    3983         587 :         if (mask & WPA_BSS_MASK_QUAL) {
    3984         423 :                 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
    3985         423 :                 if (os_snprintf_error(end - pos, ret))
    3986           0 :                         return 0;
    3987         423 :                 pos += ret;
    3988             :         }
    3989             : 
    3990         587 :         if (mask & WPA_BSS_MASK_NOISE) {
    3991         423 :                 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
    3992         423 :                 if (os_snprintf_error(end - pos, ret))
    3993           0 :                         return 0;
    3994         423 :                 pos += ret;
    3995             :         }
    3996             : 
    3997         587 :         if (mask & WPA_BSS_MASK_LEVEL) {
    3998         423 :                 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
    3999         423 :                 if (os_snprintf_error(end - pos, ret))
    4000           0 :                         return 0;
    4001         423 :                 pos += ret;
    4002             :         }
    4003             : 
    4004         587 :         if (mask & WPA_BSS_MASK_TSF) {
    4005         423 :                 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
    4006         423 :                                   (unsigned long long) bss->tsf);
    4007         423 :                 if (os_snprintf_error(end - pos, ret))
    4008           0 :                         return 0;
    4009         423 :                 pos += ret;
    4010             :         }
    4011             : 
    4012         587 :         if (mask & WPA_BSS_MASK_AGE) {
    4013             :                 struct os_reltime now;
    4014             : 
    4015         423 :                 os_get_reltime(&now);
    4016         846 :                 ret = os_snprintf(pos, end - pos, "age=%d\n",
    4017         846 :                                   (int) (now.sec - bss->last_update.sec));
    4018         423 :                 if (os_snprintf_error(end - pos, ret))
    4019           0 :                         return 0;
    4020         423 :                 pos += ret;
    4021             :         }
    4022             : 
    4023         587 :         if (mask & WPA_BSS_MASK_IE) {
    4024         423 :                 ret = os_snprintf(pos, end - pos, "ie=");
    4025         423 :                 if (os_snprintf_error(end - pos, ret))
    4026           0 :                         return 0;
    4027         423 :                 pos += ret;
    4028             : 
    4029         423 :                 ie = (const u8 *) (bss + 1);
    4030       77301 :                 for (i = 0; i < bss->ie_len; i++) {
    4031       76878 :                         ret = os_snprintf(pos, end - pos, "%02x", *ie++);
    4032       76878 :                         if (os_snprintf_error(end - pos, ret))
    4033           0 :                                 return 0;
    4034       76878 :                         pos += ret;
    4035             :                 }
    4036             : 
    4037         423 :                 ret = os_snprintf(pos, end - pos, "\n");
    4038         423 :                 if (os_snprintf_error(end - pos, ret))
    4039           0 :                         return 0;
    4040         423 :                 pos += ret;
    4041             :         }
    4042             : 
    4043         587 :         if (mask & WPA_BSS_MASK_FLAGS) {
    4044         423 :                 ret = os_snprintf(pos, end - pos, "flags=");
    4045         423 :                 if (os_snprintf_error(end - pos, ret))
    4046           0 :                         return 0;
    4047         423 :                 pos += ret;
    4048             : 
    4049         423 :                 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
    4050         423 :                 if (ie)
    4051          18 :                         pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
    4052          18 :                                                     2 + ie[1]);
    4053         423 :                 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
    4054         423 :                 if (ie2)
    4055         297 :                         pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
    4056         297 :                                                     2 + ie2[1]);
    4057         423 :                 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
    4058         423 :                 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
    4059           2 :                         ret = os_snprintf(pos, end - pos, "[WEP]");
    4060           2 :                         if (os_snprintf_error(end - pos, ret))
    4061           0 :                                 return 0;
    4062           2 :                         pos += ret;
    4063             :                 }
    4064         423 :                 if (bss_is_dmg(bss)) {
    4065             :                         const char *s;
    4066           0 :                         ret = os_snprintf(pos, end - pos, "[DMG]");
    4067           0 :                         if (os_snprintf_error(end - pos, ret))
    4068           0 :                                 return 0;
    4069           0 :                         pos += ret;
    4070           0 :                         switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
    4071             :                         case IEEE80211_CAP_DMG_IBSS:
    4072           0 :                                 s = "[IBSS]";
    4073           0 :                                 break;
    4074             :                         case IEEE80211_CAP_DMG_AP:
    4075           0 :                                 s = "[ESS]";
    4076           0 :                                 break;
    4077             :                         case IEEE80211_CAP_DMG_PBSS:
    4078           0 :                                 s = "[PBSS]";
    4079           0 :                                 break;
    4080             :                         default:
    4081           0 :                                 s = "";
    4082           0 :                                 break;
    4083             :                         }
    4084           0 :                         ret = os_snprintf(pos, end - pos, "%s", s);
    4085           0 :                         if (os_snprintf_error(end - pos, ret))
    4086           0 :                                 return 0;
    4087           0 :                         pos += ret;
    4088             :                 } else {
    4089         423 :                         if (bss->caps & IEEE80211_CAP_IBSS) {
    4090           2 :                                 ret = os_snprintf(pos, end - pos, "[IBSS]");
    4091           2 :                                 if (os_snprintf_error(end - pos, ret))
    4092           0 :                                         return 0;
    4093           2 :                                 pos += ret;
    4094             :                         }
    4095         423 :                         if (bss->caps & IEEE80211_CAP_ESS) {
    4096         420 :                                 ret = os_snprintf(pos, end - pos, "[ESS]");
    4097         420 :                                 if (os_snprintf_error(end - pos, ret))
    4098           0 :                                         return 0;
    4099         420 :                                 pos += ret;
    4100             :                         }
    4101             :                 }
    4102         836 :                 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
    4103         413 :                     wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
    4104          10 :                         ret = os_snprintf(pos, end - pos, "[P2P]");
    4105          10 :                         if (os_snprintf_error(end - pos, ret))
    4106           0 :                                 return 0;
    4107          10 :                         pos += ret;
    4108             :                 }
    4109             : #ifdef CONFIG_HS20
    4110         423 :                 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
    4111         132 :                         ret = os_snprintf(pos, end - pos, "[HS20]");
    4112         132 :                         if (os_snprintf_error(end - pos, ret))
    4113           0 :                                 return 0;
    4114         132 :                         pos += ret;
    4115             :                 }
    4116             : #endif /* CONFIG_HS20 */
    4117             : 
    4118         423 :                 ret = os_snprintf(pos, end - pos, "\n");
    4119         423 :                 if (os_snprintf_error(end - pos, ret))
    4120           0 :                         return 0;
    4121         423 :                 pos += ret;
    4122             :         }
    4123             : 
    4124         587 :         if (mask & WPA_BSS_MASK_SSID) {
    4125         846 :                 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
    4126         423 :                                   wpa_ssid_txt(bss->ssid, bss->ssid_len));
    4127         423 :                 if (os_snprintf_error(end - pos, ret))
    4128           0 :                         return 0;
    4129         423 :                 pos += ret;
    4130             :         }
    4131             : 
    4132             : #ifdef CONFIG_WPS
    4133         587 :         if (mask & WPA_BSS_MASK_WPS_SCAN) {
    4134         423 :                 ie = (const u8 *) (bss + 1);
    4135         423 :                 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
    4136         423 :                 if (ret < 0 || ret >= end - pos)
    4137           0 :                         return 0;
    4138         423 :                 pos += ret;
    4139             :         }
    4140             : #endif /* CONFIG_WPS */
    4141             : 
    4142             : #ifdef CONFIG_P2P
    4143         587 :         if (mask & WPA_BSS_MASK_P2P_SCAN) {
    4144         423 :                 ie = (const u8 *) (bss + 1);
    4145         423 :                 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
    4146         423 :                 if (ret < 0 || ret >= end - pos)
    4147           0 :                         return 0;
    4148         423 :                 pos += ret;
    4149             :         }
    4150             : #endif /* CONFIG_P2P */
    4151             : 
    4152             : #ifdef CONFIG_WIFI_DISPLAY
    4153         587 :         if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
    4154             :                 struct wpabuf *wfd;
    4155         423 :                 ie = (const u8 *) (bss + 1);
    4156         423 :                 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
    4157             :                                                   WFD_IE_VENDOR_TYPE);
    4158         423 :                 if (wfd) {
    4159           2 :                         ret = os_snprintf(pos, end - pos, "wfd_subelems=");
    4160           2 :                         if (os_snprintf_error(end - pos, ret)) {
    4161           0 :                                 wpabuf_free(wfd);
    4162           0 :                                 return 0;
    4163             :                         }
    4164           2 :                         pos += ret;
    4165             : 
    4166           4 :                         pos += wpa_snprintf_hex(pos, end - pos,
    4167           2 :                                                 wpabuf_head(wfd),
    4168             :                                                 wpabuf_len(wfd));
    4169           2 :                         wpabuf_free(wfd);
    4170             : 
    4171           2 :                         ret = os_snprintf(pos, end - pos, "\n");
    4172           2 :                         if (os_snprintf_error(end - pos, ret))
    4173           0 :                                 return 0;
    4174           2 :                         pos += ret;
    4175             :                 }
    4176             :         }
    4177             : #endif /* CONFIG_WIFI_DISPLAY */
    4178             : 
    4179             : #ifdef CONFIG_INTERWORKING
    4180         587 :         if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
    4181          42 :                 struct wpa_bss_anqp *anqp = bss->anqp;
    4182          42 :                 pos = anqp_add_hex(pos, end, "anqp_capability_list",
    4183             :                                    anqp->capability_list);
    4184          42 :                 pos = anqp_add_hex(pos, end, "anqp_venue_name",
    4185             :                                    anqp->venue_name);
    4186          42 :                 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
    4187             :                                    anqp->network_auth_type);
    4188          42 :                 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
    4189             :                                    anqp->roaming_consortium);
    4190          42 :                 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
    4191             :                                    anqp->ip_addr_type_availability);
    4192          42 :                 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
    4193             :                                    anqp->nai_realm);
    4194          42 :                 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
    4195          42 :                 pos = anqp_add_hex(pos, end, "anqp_domain_name",
    4196             :                                    anqp->domain_name);
    4197             : #ifdef CONFIG_HS20
    4198          42 :                 pos = anqp_add_hex(pos, end, "hs20_capability_list",
    4199             :                                    anqp->hs20_capability_list);
    4200          42 :                 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
    4201             :                                    anqp->hs20_operator_friendly_name);
    4202          42 :                 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
    4203             :                                    anqp->hs20_wan_metrics);
    4204          42 :                 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
    4205             :                                    anqp->hs20_connection_capability);
    4206          42 :                 pos = anqp_add_hex(pos, end, "hs20_operating_class",
    4207             :                                    anqp->hs20_operating_class);
    4208          42 :                 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
    4209             :                                    anqp->hs20_osu_providers_list);
    4210             : #endif /* CONFIG_HS20 */
    4211             :         }
    4212             : #endif /* CONFIG_INTERWORKING */
    4213             : 
    4214             : #ifdef CONFIG_MESH
    4215         587 :         if (mask & WPA_BSS_MASK_MESH_SCAN) {
    4216         423 :                 ie = (const u8 *) (bss + 1);
    4217         423 :                 ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
    4218         423 :                 if (ret < 0 || ret >= end - pos)
    4219           0 :                         return 0;
    4220         423 :                 pos += ret;
    4221             :         }
    4222             : #endif /* CONFIG_MESH */
    4223             : 
    4224         587 :         if (mask & WPA_BSS_MASK_SNR) {
    4225         423 :                 ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
    4226         423 :                 if (os_snprintf_error(end - pos, ret))
    4227           0 :                         return 0;
    4228         423 :                 pos += ret;
    4229             :         }
    4230             : 
    4231         587 :         if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
    4232         423 :                 ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
    4233             :                                   bss->est_throughput);
    4234         423 :                 if (os_snprintf_error(end - pos, ret))
    4235           0 :                         return 0;
    4236         423 :                 pos += ret;
    4237             :         }
    4238             : 
    4239         587 :         if (mask & WPA_BSS_MASK_DELIM) {
    4240           2 :                 ret = os_snprintf(pos, end - pos, "====\n");
    4241           2 :                 if (os_snprintf_error(end - pos, ret))
    4242           0 :                         return 0;
    4243           2 :                 pos += ret;
    4244             :         }
    4245             : 
    4246         587 :         return pos - buf;
    4247             : }
    4248             : 
    4249             : 
    4250         777 : static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
    4251             :                                          const char *cmd, char *buf,
    4252             :                                          size_t buflen)
    4253             : {
    4254             :         u8 bssid[ETH_ALEN];
    4255             :         size_t i;
    4256             :         struct wpa_bss *bss;
    4257         777 :         struct wpa_bss *bsslast = NULL;
    4258             :         struct dl_list *next;
    4259         777 :         int ret = 0;
    4260             :         int len;
    4261         777 :         char *ctmp, *end = buf + buflen;
    4262         777 :         unsigned long mask = WPA_BSS_MASK_ALL;
    4263             : 
    4264         777 :         if (os_strncmp(cmd, "RANGE=", 6) == 0) {
    4265         109 :                 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
    4266         100 :                         bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
    4267             :                                             list_id);
    4268         100 :                         bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
    4269             :                                                list_id);
    4270             :                 } else { /* N1-N2 */
    4271             :                         unsigned int id1, id2;
    4272             : 
    4273           9 :                         if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
    4274           1 :                                 wpa_printf(MSG_INFO, "Wrong BSS range "
    4275             :                                            "format");
    4276           1 :                                 return 0;
    4277             :                         }
    4278             : 
    4279           8 :                         if (*(cmd + 6) == '-')
    4280           1 :                                 id1 = 0;
    4281             :                         else
    4282           7 :                                 id1 = atoi(cmd + 6);
    4283           8 :                         ctmp++;
    4284           8 :                         if (*ctmp >= '0' && *ctmp <= '9')
    4285           6 :                                 id2 = atoi(ctmp);
    4286             :                         else
    4287           2 :                                 id2 = (unsigned int) -1;
    4288           8 :                         bss = wpa_bss_get_id_range(wpa_s, id1, id2);
    4289           8 :                         if (id2 == (unsigned int) -1)
    4290           2 :                                 bsslast = dl_list_last(&wpa_s->bss_id,
    4291             :                                                        struct wpa_bss,
    4292             :                                                        list_id);
    4293             :                         else {
    4294           6 :                                 bsslast = wpa_bss_get_id(wpa_s, id2);
    4295           6 :                                 if (bsslast == NULL && bss && id2 > id1) {
    4296           1 :                                         struct wpa_bss *tmp = bss;
    4297             :                                         for (;;) {
    4298           2 :                                                 next = tmp->list_id.next;
    4299           2 :                                                 if (next == &wpa_s->bss_id)
    4300           1 :                                                         break;
    4301           1 :                                                 tmp = dl_list_entry(
    4302             :                                                         next, struct wpa_bss,
    4303             :                                                         list_id);
    4304           1 :                                                 if (tmp->id > id2)
    4305           0 :                                                         break;
    4306           1 :                                                 bsslast = tmp;
    4307           1 :                                         }
    4308             :                                 }
    4309             :                         }
    4310             :                 }
    4311         668 :         } else if (os_strncmp(cmd, "FIRST", 5) == 0)
    4312           2 :                 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
    4313         666 :         else if (os_strncmp(cmd, "LAST", 4) == 0)
    4314           2 :                 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
    4315         664 :         else if (os_strncmp(cmd, "ID-", 3) == 0) {
    4316           2 :                 i = atoi(cmd + 3);
    4317           2 :                 bss = wpa_bss_get_id(wpa_s, i);
    4318         662 :         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
    4319           2 :                 i = atoi(cmd + 5);
    4320           2 :                 bss = wpa_bss_get_id(wpa_s, i);
    4321           2 :                 if (bss) {
    4322           2 :                         next = bss->list_id.next;
    4323           2 :                         if (next == &wpa_s->bss_id)
    4324           1 :                                 bss = NULL;
    4325             :                         else
    4326           1 :                                 bss = dl_list_entry(next, struct wpa_bss,
    4327             :                                                     list_id);
    4328             :                 }
    4329             : #ifdef CONFIG_P2P
    4330         660 :         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
    4331           5 :                 if (hwaddr_aton(cmd + 13, bssid) == 0)
    4332           4 :                         bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
    4333             :                 else
    4334           1 :                         bss = NULL;
    4335             : #endif /* CONFIG_P2P */
    4336         655 :         } else if (hwaddr_aton(cmd, bssid) == 0)
    4337         645 :                 bss = wpa_bss_get_bssid(wpa_s, bssid);
    4338             :         else {
    4339             :                 struct wpa_bss *tmp;
    4340          10 :                 i = atoi(cmd);
    4341          10 :                 bss = NULL;
    4342          10 :                 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
    4343             :                 {
    4344           5 :                         if (i-- == 0) {
    4345           5 :                                 bss = tmp;
    4346           5 :                                 break;
    4347             :                         }
    4348             :                 }
    4349             :         }
    4350             : 
    4351         776 :         if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
    4352         101 :                 mask = strtoul(ctmp + 5, NULL, 0x10);
    4353         101 :                 if (mask == 0)
    4354           1 :                         mask = WPA_BSS_MASK_ALL;
    4355             :         }
    4356             : 
    4357         776 :         if (bss == NULL)
    4358         276 :                 return 0;
    4359             : 
    4360         500 :         if (bsslast == NULL)
    4361         408 :                 bsslast = bss;
    4362             :         do {
    4363         587 :                 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
    4364         587 :                 ret += len;
    4365         587 :                 buf += len;
    4366         587 :                 buflen -= len;
    4367         587 :                 if (bss == bsslast) {
    4368         501 :                         if ((mask & WPA_BSS_MASK_DELIM) && len &&
    4369           1 :                             (bss == dl_list_last(&wpa_s->bss_id,
    4370             :                                                  struct wpa_bss, list_id))) {
    4371             :                                 int res;
    4372             : 
    4373           1 :                                 res = os_snprintf(buf - 5, end - buf + 5,
    4374             :                                                   "####\n");
    4375           1 :                                 if (os_snprintf_error(end - buf + 5, res)) {
    4376           0 :                                         wpa_printf(MSG_DEBUG,
    4377             :                                                    "Could not add end delim");
    4378             :                                 }
    4379             :                         }
    4380         500 :                         break;
    4381             :                 }
    4382          87 :                 next = bss->list_id.next;
    4383          87 :                 if (next == &wpa_s->bss_id)
    4384           0 :                         break;
    4385          87 :                 bss = dl_list_entry(next, struct wpa_bss, list_id);
    4386          87 :         } while (bss && len);
    4387             : 
    4388         500 :         return ret;
    4389             : }
    4390             : 
    4391             : 
    4392          13 : static int wpa_supplicant_ctrl_iface_ap_scan(
    4393             :         struct wpa_supplicant *wpa_s, char *cmd)
    4394             : {
    4395          13 :         int ap_scan = atoi(cmd);
    4396          13 :         return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
    4397             : }
    4398             : 
    4399             : 
    4400          18 : static int wpa_supplicant_ctrl_iface_scan_interval(
    4401             :         struct wpa_supplicant *wpa_s, char *cmd)
    4402             : {
    4403          18 :         int scan_int = atoi(cmd);
    4404          18 :         return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
    4405             : }
    4406             : 
    4407             : 
    4408           3 : static int wpa_supplicant_ctrl_iface_bss_expire_age(
    4409             :         struct wpa_supplicant *wpa_s, char *cmd)
    4410             : {
    4411           3 :         int expire_age = atoi(cmd);
    4412           3 :         return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
    4413             : }
    4414             : 
    4415             : 
    4416           2 : static int wpa_supplicant_ctrl_iface_bss_expire_count(
    4417             :         struct wpa_supplicant *wpa_s, char *cmd)
    4418             : {
    4419           2 :         int expire_count = atoi(cmd);
    4420           2 :         return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
    4421             : }
    4422             : 
    4423             : 
    4424         234 : static void wpa_supplicant_ctrl_iface_bss_flush(
    4425             :         struct wpa_supplicant *wpa_s, char *cmd)
    4426             : {
    4427         234 :         int flush_age = atoi(cmd);
    4428             : 
    4429         234 :         if (flush_age == 0)
    4430         233 :                 wpa_bss_flush(wpa_s);
    4431             :         else
    4432           1 :                 wpa_bss_flush_by_age(wpa_s, flush_age);
    4433         234 : }
    4434             : 
    4435             : 
    4436             : #ifdef CONFIG_TESTING_OPTIONS
    4437           2 : static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
    4438             : {
    4439           2 :         wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
    4440             :         /* MLME-DELETEKEYS.request */
    4441           2 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
    4442           2 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
    4443           2 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
    4444           2 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
    4445             : #ifdef CONFIG_IEEE80211W
    4446           2 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
    4447           2 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
    4448             : #endif /* CONFIG_IEEE80211W */
    4449             : 
    4450           2 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
    4451             :                         0);
    4452             :         /* MLME-SETPROTECTION.request(None) */
    4453           2 :         wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
    4454             :                                    MLME_SETPROTECTION_PROTECT_TYPE_NONE,
    4455             :                                    MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
    4456           2 :         wpa_sm_drop_sa(wpa_s->wpa);
    4457           2 : }
    4458             : #endif /* CONFIG_TESTING_OPTIONS */
    4459             : 
    4460             : 
    4461         155 : static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
    4462             :                                           char *addr)
    4463             : {
    4464             : #ifdef CONFIG_NO_SCAN_PROCESSING
    4465             :         return -1;
    4466             : #else /* CONFIG_NO_SCAN_PROCESSING */
    4467             :         u8 bssid[ETH_ALEN];
    4468             :         struct wpa_bss *bss;
    4469         155 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
    4470             : 
    4471         155 :         if (hwaddr_aton(addr, bssid)) {
    4472           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
    4473             :                            "address '%s'", addr);
    4474           1 :                 return -1;
    4475             :         }
    4476             : 
    4477         154 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
    4478             : 
    4479         154 :         if (!ssid) {
    4480           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
    4481             :                            "configuration known for the target AP");
    4482           1 :                 return -1;
    4483             :         }
    4484             : 
    4485         153 :         bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
    4486         153 :         if (!bss) {
    4487           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
    4488             :                            "from BSS table");
    4489           1 :                 return -1;
    4490             :         }
    4491             : 
    4492             :         /*
    4493             :          * TODO: Find best network configuration block from configuration to
    4494             :          * allow roaming to other networks
    4495             :          */
    4496             : 
    4497         152 :         wpa_s->reassociate = 1;
    4498         152 :         wpa_supplicant_connect(wpa_s, bss, ssid);
    4499             : 
    4500         152 :         return 0;
    4501             : #endif /* CONFIG_NO_SCAN_PROCESSING */
    4502             : }
    4503             : 
    4504             : 
    4505             : #ifdef CONFIG_P2P
    4506         353 : static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
    4507             : {
    4508         353 :         unsigned int timeout = atoi(cmd);
    4509         353 :         enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
    4510         353 :         u8 dev_id[ETH_ALEN], *_dev_id = NULL;
    4511         353 :         u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
    4512             :         char *pos;
    4513             :         unsigned int search_delay;
    4514         353 :         const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
    4515         353 :         u8 seek_count = 0;
    4516         353 :         int freq = 0;
    4517             : 
    4518         353 :         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
    4519           1 :                 wpa_dbg(wpa_s, MSG_INFO,
    4520             :                         "Reject P2P_FIND since interface is disabled");
    4521           1 :                 return -1;
    4522             :         }
    4523         352 :         if (os_strstr(cmd, "type=social"))
    4524         328 :                 type = P2P_FIND_ONLY_SOCIAL;
    4525          24 :         else if (os_strstr(cmd, "type=progressive"))
    4526           1 :                 type = P2P_FIND_PROGRESSIVE;
    4527             : 
    4528         352 :         pos = os_strstr(cmd, "dev_id=");
    4529         352 :         if (pos) {
    4530           5 :                 pos += 7;
    4531           5 :                 if (hwaddr_aton(pos, dev_id))
    4532           1 :                         return -1;
    4533           4 :                 _dev_id = dev_id;
    4534             :         }
    4535             : 
    4536         351 :         pos = os_strstr(cmd, "dev_type=");
    4537         351 :         if (pos) {
    4538           5 :                 pos += 9;
    4539           5 :                 if (wps_dev_type_str2bin(pos, dev_type) < 0)
    4540           1 :                         return -1;
    4541           4 :                 _dev_type = dev_type;
    4542             :         }
    4543             : 
    4544         350 :         pos = os_strstr(cmd, "delay=");
    4545         350 :         if (pos) {
    4546           1 :                 pos += 6;
    4547           1 :                 search_delay = atoi(pos);
    4548             :         } else
    4549         349 :                 search_delay = wpas_p2p_search_delay(wpa_s);
    4550             : 
    4551             :         /* Must be searched for last, because it adds nul termination */
    4552         350 :         pos = os_strstr(cmd, " seek=");
    4553         734 :         while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) {
    4554             :                 char *term;
    4555             : 
    4556          34 :                 term = os_strchr(pos + 1, ' ');
    4557          34 :                 _seek[seek_count++] = pos + 6;
    4558          34 :                 seek = _seek;
    4559          34 :                 pos = os_strstr(pos + 6, " seek=");
    4560             : 
    4561          34 :                 if (term)
    4562           8 :                         *term = '\0';
    4563             :         }
    4564         350 :         if (seek_count > P2P_MAX_QUERY_HASH) {
    4565           1 :                 seek[0] = NULL;
    4566           1 :                 seek_count = 1;
    4567             :         }
    4568             : 
    4569         350 :         pos = os_strstr(cmd, "freq=");
    4570         350 :         if (pos) {
    4571           2 :                 pos += 5;
    4572           2 :                 freq = atoi(pos);
    4573           2 :                 if (freq <= 0)
    4574           0 :                         return -1;
    4575             :         }
    4576             : 
    4577         350 :         return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
    4578             :                              _dev_id, search_delay, seek_count, seek, freq);
    4579             : }
    4580             : 
    4581             : 
    4582          18 : static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
    4583             : {
    4584             :         struct p2ps_provision *p2ps_prov;
    4585             :         char *pos;
    4586          18 :         size_t info_len = 0;
    4587          18 :         char *info = NULL;
    4588          18 :         u8 role = P2PS_SETUP_NONE;
    4589             :         long long unsigned val;
    4590             : 
    4591          18 :         pos = os_strstr(cmd, "info=");
    4592          18 :         if (pos) {
    4593          15 :                 pos += 5;
    4594          15 :                 info_len = os_strlen(pos);
    4595             : 
    4596          15 :                 if (info_len) {
    4597          15 :                         info = os_malloc(info_len + 1);
    4598          15 :                         if (info) {
    4599          15 :                                 info_len = utf8_unescape(pos, info_len,
    4600             :                                                          info, info_len + 1);
    4601             :                         } else
    4602           0 :                                 info_len = 0;
    4603             :                 }
    4604             :         }
    4605             : 
    4606          18 :         p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
    4607          18 :         if (p2ps_prov == NULL) {
    4608           0 :                 os_free(info);
    4609           0 :                 return NULL;
    4610             :         }
    4611             : 
    4612          18 :         if (info) {
    4613          15 :                 os_memcpy(p2ps_prov->info, info, info_len);
    4614          15 :                 p2ps_prov->info[info_len] = '\0';
    4615          15 :                 os_free(info);
    4616             :         }
    4617             : 
    4618          18 :         pos = os_strstr(cmd, "status=");
    4619          18 :         if (pos)
    4620           3 :                 p2ps_prov->status = atoi(pos + 7);
    4621             :         else
    4622          15 :                 p2ps_prov->status = -1;
    4623             : 
    4624          18 :         pos = os_strstr(cmd, "adv_id=");
    4625          18 :         if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
    4626             :                 goto invalid_args;
    4627          18 :         p2ps_prov->adv_id = val;
    4628             : 
    4629          18 :         pos = os_strstr(cmd, "method=");
    4630          18 :         if (pos)
    4631          15 :                 p2ps_prov->method = strtol(pos + 7, NULL, 16);
    4632             :         else
    4633           3 :                 p2ps_prov->method = 0;
    4634             : 
    4635          18 :         pos = os_strstr(cmd, "session=");
    4636          18 :         if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
    4637             :                 goto invalid_args;
    4638          18 :         p2ps_prov->session_id = val;
    4639             : 
    4640          18 :         pos = os_strstr(cmd, "adv_mac=");
    4641          18 :         if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
    4642             :                 goto invalid_args;
    4643             : 
    4644          18 :         pos = os_strstr(cmd, "session_mac=");
    4645          18 :         if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
    4646             :                 goto invalid_args;
    4647             : 
    4648             :         /* force conncap with tstCap (no sanity checks) */
    4649          18 :         pos = os_strstr(cmd, "tstCap=");
    4650          18 :         if (pos) {
    4651           0 :                 role = strtol(pos + 7, NULL, 16);
    4652             :         } else {
    4653          18 :                 pos = os_strstr(cmd, "role=");
    4654          18 :                 if (pos) {
    4655           0 :                         role = strtol(pos + 5, NULL, 16);
    4656           0 :                         if (role != P2PS_SETUP_CLIENT &&
    4657             :                             role != P2PS_SETUP_GROUP_OWNER)
    4658           0 :                                 role = P2PS_SETUP_NONE;
    4659             :                 }
    4660             :         }
    4661          18 :         p2ps_prov->role = role;
    4662             : 
    4663          18 :         return p2ps_prov;
    4664             : 
    4665             : invalid_args:
    4666           0 :         os_free(p2ps_prov);
    4667           0 :         return NULL;
    4668             : }
    4669             : 
    4670             : 
    4671           3 : static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
    4672             : {
    4673             :         u8 addr[ETH_ALEN];
    4674             :         struct p2ps_provision *p2ps_prov;
    4675             :         char *pos;
    4676             : 
    4677             :         /* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
    4678             : 
    4679           3 :         wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
    4680             : 
    4681           3 :         if (hwaddr_aton(cmd, addr))
    4682           0 :                 return -1;
    4683             : 
    4684           3 :         pos = cmd + 17;
    4685           3 :         if (*pos != ' ')
    4686           0 :                 return -1;
    4687             : 
    4688           3 :         p2ps_prov = p2p_parse_asp_provision_cmd(pos);
    4689           3 :         if (!p2ps_prov)
    4690           0 :                 return -1;
    4691             : 
    4692           3 :         if (p2ps_prov->status < 0) {
    4693           0 :                 os_free(p2ps_prov);
    4694           0 :                 return -1;
    4695             :         }
    4696             : 
    4697           3 :         return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
    4698             :                                   p2ps_prov);
    4699             : }
    4700             : 
    4701             : 
    4702          15 : static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
    4703             : {
    4704             :         u8 addr[ETH_ALEN];
    4705             :         struct p2ps_provision *p2ps_prov;
    4706             :         char *pos;
    4707             : 
    4708             :         /* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
    4709             :          *        session=<ses_id> mac=<ses_mac> [info=<infodata>]
    4710             :          */
    4711             : 
    4712          15 :         wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
    4713          15 :         if (hwaddr_aton(cmd, addr))
    4714           0 :                 return -1;
    4715             : 
    4716          15 :         pos = cmd + 17;
    4717          15 :         if (*pos != ' ')
    4718           0 :                 return -1;
    4719             : 
    4720          15 :         p2ps_prov = p2p_parse_asp_provision_cmd(pos);
    4721          15 :         if (!p2ps_prov)
    4722           0 :                 return -1;
    4723             : 
    4724          15 :         return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
    4725             :                                   p2ps_prov);
    4726             : }
    4727             : 
    4728             : 
    4729         298 : static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
    4730             :                             char *buf, size_t buflen)
    4731             : {
    4732             :         u8 addr[ETH_ALEN];
    4733             :         char *pos, *pos2;
    4734         298 :         char *pin = NULL;
    4735             :         enum p2p_wps_method wps_method;
    4736             :         int new_pin;
    4737             :         int ret;
    4738         298 :         int persistent_group, persistent_id = -1;
    4739             :         int join;
    4740             :         int auth;
    4741             :         int automatic;
    4742         298 :         int go_intent = -1;
    4743         298 :         int freq = 0;
    4744             :         int pd;
    4745             :         int ht40, vht;
    4746             : 
    4747         298 :         if (!wpa_s->global->p2p_init_wpa_s)
    4748           0 :                 return -1;
    4749         298 :         if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
    4750           1 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
    4751             :                         wpa_s->global->p2p_init_wpa_s->ifname);
    4752           1 :                 wpa_s = wpa_s->global->p2p_init_wpa_s;
    4753             :         }
    4754             : 
    4755             :         /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
    4756             :          * [persistent|persistent=<network id>]
    4757             :          * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
    4758             :          * [ht40] [vht] [auto] */
    4759             : 
    4760         298 :         if (hwaddr_aton(cmd, addr))
    4761           1 :                 return -1;
    4762             : 
    4763         297 :         pos = cmd + 17;
    4764         297 :         if (*pos != ' ')
    4765           1 :                 return -1;
    4766         296 :         pos++;
    4767             : 
    4768         296 :         persistent_group = os_strstr(pos, " persistent") != NULL;
    4769         296 :         pos2 = os_strstr(pos, " persistent=");
    4770         296 :         if (pos2) {
    4771             :                 struct wpa_ssid *ssid;
    4772           3 :                 persistent_id = atoi(pos2 + 12);
    4773           3 :                 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
    4774           4 :                 if (ssid == NULL || ssid->disabled != 2 ||
    4775           1 :                     ssid->mode != WPAS_MODE_P2P_GO) {
    4776           2 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
    4777             :                                    "SSID id=%d for persistent P2P group (GO)",
    4778             :                                    persistent_id);
    4779           2 :                         return -1;
    4780             :                 }
    4781             :         }
    4782         294 :         join = os_strstr(pos, " join") != NULL;
    4783         294 :         auth = os_strstr(pos, " auth") != NULL;
    4784         294 :         automatic = os_strstr(pos, " auto") != NULL;
    4785         294 :         pd = os_strstr(pos, " provdisc") != NULL;
    4786         294 :         vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
    4787         294 :         ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
    4788             :                 vht;
    4789             : 
    4790         294 :         pos2 = os_strstr(pos, " go_intent=");
    4791         294 :         if (pos2) {
    4792         107 :                 pos2 += 11;
    4793         107 :                 go_intent = atoi(pos2);
    4794         107 :                 if (go_intent < 0 || go_intent > 15)
    4795           2 :                         return -1;
    4796             :         }
    4797             : 
    4798         292 :         pos2 = os_strstr(pos, " freq=");
    4799         292 :         if (pos2) {
    4800          57 :                 pos2 += 6;
    4801          57 :                 freq = atoi(pos2);
    4802          57 :                 if (freq <= 0)
    4803           1 :                         return -1;
    4804             :         }
    4805             : 
    4806         291 :         if (os_strncmp(pos, "pin", 3) == 0) {
    4807             :                 /* Request random PIN (to be displayed) and enable the PIN */
    4808           3 :                 wps_method = WPS_PIN_DISPLAY;
    4809         288 :         } else if (os_strncmp(pos, "pbc", 3) == 0) {
    4810          74 :                 wps_method = WPS_PBC;
    4811             :         } else {
    4812         214 :                 pin = pos;
    4813         214 :                 pos = os_strchr(pin, ' ');
    4814         214 :                 wps_method = WPS_PIN_KEYPAD;
    4815         214 :                 if (pos) {
    4816         213 :                         *pos++ = '\0';
    4817         213 :                         if (os_strncmp(pos, "display", 7) == 0)
    4818          81 :                                 wps_method = WPS_PIN_DISPLAY;
    4819         132 :                         else if (os_strncmp(pos, "p2ps", 4) == 0)
    4820          10 :                                 wps_method = WPS_P2PS;
    4821             :                 }
    4822         214 :                 if (!wps_pin_str_valid(pin)) {
    4823           1 :                         os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
    4824           1 :                         return 17;
    4825             :                 }
    4826             :         }
    4827             : 
    4828         290 :         new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
    4829             :                                    persistent_group, automatic, join,
    4830             :                                    auth, go_intent, freq, persistent_id, pd,
    4831             :                                    ht40, vht);
    4832         290 :         if (new_pin == -2) {
    4833           0 :                 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
    4834           0 :                 return 25;
    4835             :         }
    4836         290 :         if (new_pin == -3) {
    4837           2 :                 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
    4838           2 :                 return 25;
    4839             :         }
    4840         288 :         if (new_pin < 0)
    4841           1 :                 return -1;
    4842         287 :         if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
    4843           1 :                 ret = os_snprintf(buf, buflen, "%08d", new_pin);
    4844           1 :                 if (os_snprintf_error(buflen, ret))
    4845           0 :                         return -1;
    4846           1 :                 return ret;
    4847             :         }
    4848             : 
    4849         286 :         os_memcpy(buf, "OK\n", 3);
    4850         286 :         return 3;
    4851             : }
    4852             : 
    4853             : 
    4854         355 : static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
    4855             : {
    4856         355 :         unsigned int timeout = atoi(cmd);
    4857         355 :         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
    4858           2 :                 wpa_dbg(wpa_s, MSG_INFO,
    4859             :                         "Reject P2P_LISTEN since interface is disabled");
    4860           2 :                 return -1;
    4861             :         }
    4862         353 :         return wpas_p2p_listen(wpa_s, timeout);
    4863             : }
    4864             : 
    4865             : 
    4866          16 : static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
    4867             : {
    4868             :         u8 addr[ETH_ALEN];
    4869             :         char *pos;
    4870          16 :         enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
    4871             : 
    4872             :         /* <addr> <config method> [join|auto] */
    4873             : 
    4874          16 :         if (hwaddr_aton(cmd, addr))
    4875           1 :                 return -1;
    4876             : 
    4877          15 :         pos = cmd + 17;
    4878          15 :         if (*pos != ' ')
    4879           1 :                 return -1;
    4880          14 :         pos++;
    4881             : 
    4882          14 :         if (os_strstr(pos, " join") != NULL)
    4883           2 :                 use = WPAS_P2P_PD_FOR_JOIN;
    4884          12 :         else if (os_strstr(pos, " auto") != NULL)
    4885           2 :                 use = WPAS_P2P_PD_AUTO;
    4886             : 
    4887          14 :         return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL);
    4888             : }
    4889             : 
    4890             : 
    4891           2 : static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
    4892             :                               size_t buflen)
    4893             : {
    4894           2 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
    4895             : 
    4896           3 :         if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
    4897           1 :             ssid->passphrase == NULL)
    4898           1 :                 return -1;
    4899             : 
    4900           1 :         os_strlcpy(buf, ssid->passphrase, buflen);
    4901           1 :         return os_strlen(buf);
    4902             : }
    4903             : 
    4904             : 
    4905          68 : static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
    4906             :                                   char *buf, size_t buflen)
    4907             : {
    4908             :         u64 ref;
    4909             :         int res;
    4910             :         u8 dst_buf[ETH_ALEN], *dst;
    4911             :         struct wpabuf *tlvs;
    4912             :         char *pos;
    4913             :         size_t len;
    4914             : 
    4915          68 :         if (hwaddr_aton(cmd, dst_buf))
    4916           1 :                 return -1;
    4917          67 :         dst = dst_buf;
    4918         106 :         if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
    4919          78 :             dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
    4920          39 :                 dst = NULL;
    4921          67 :         pos = cmd + 17;
    4922          67 :         if (*pos != ' ')
    4923           1 :                 return -1;
    4924          66 :         pos++;
    4925             : 
    4926          66 :         if (os_strncmp(pos, "upnp ", 5) == 0) {
    4927             :                 u8 version;
    4928           4 :                 pos += 5;
    4929           4 :                 if (hexstr2bin(pos, &version, 1) < 0)
    4930           3 :                         return -1;
    4931           3 :                 pos += 2;
    4932           3 :                 if (*pos != ' ')
    4933           1 :                         return -1;
    4934           2 :                 pos++;
    4935           2 :                 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
    4936             : #ifdef CONFIG_WIFI_DISPLAY
    4937          62 :         } else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
    4938           1 :                 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
    4939             : #endif /* CONFIG_WIFI_DISPLAY */
    4940          61 :         } else if (os_strncmp(pos, "asp ", 4) == 0) {
    4941             :                 char *svc_str;
    4942          20 :                 char *svc_info = NULL;
    4943             :                 u32 id;
    4944             : 
    4945          20 :                 pos += 4;
    4946          20 :                 if (sscanf(pos, "%x", &id) != 1 || id > 0xff)
    4947           0 :                         return -1;
    4948             : 
    4949          20 :                 pos = os_strchr(pos, ' ');
    4950          20 :                 if (pos == NULL || pos[1] == '\0' || pos[1] == ' ')
    4951           0 :                         return -1;
    4952             : 
    4953          20 :                 svc_str = pos + 1;
    4954             : 
    4955          20 :                 pos = os_strchr(svc_str, ' ');
    4956             : 
    4957          20 :                 if (pos)
    4958          20 :                         *pos++ = '\0';
    4959             : 
    4960             :                 /* All remaining data is the svc_info string */
    4961          20 :                 if (pos && pos[0] && pos[0] != ' ') {
    4962          20 :                         len = os_strlen(pos);
    4963             : 
    4964             :                         /* Unescape in place */
    4965          20 :                         len = utf8_unescape(pos, len, pos, len);
    4966          20 :                         if (len > 0xff)
    4967           0 :                                 return -1;
    4968             : 
    4969          20 :                         svc_info = pos;
    4970             :                 }
    4971             : 
    4972          20 :                 ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id,
    4973             :                                               svc_str, svc_info);
    4974             :         } else {
    4975          41 :                 len = os_strlen(pos);
    4976          41 :                 if (len & 1)
    4977           1 :                         return -1;
    4978          40 :                 len /= 2;
    4979          40 :                 tlvs = wpabuf_alloc(len);
    4980          40 :                 if (tlvs == NULL)
    4981           0 :                         return -1;
    4982          40 :                 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
    4983           1 :                         wpabuf_free(tlvs);
    4984           1 :                         return -1;
    4985             :                 }
    4986             : 
    4987          39 :                 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
    4988          39 :                 wpabuf_free(tlvs);
    4989             :         }
    4990          62 :         if (ref == 0)
    4991           0 :                 return -1;
    4992          62 :         res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
    4993          62 :         if (os_snprintf_error(buflen, res))
    4994           0 :                 return -1;
    4995          62 :         return res;
    4996             : }
    4997             : 
    4998             : 
    4999           9 : static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
    5000             :                                          char *cmd)
    5001             : {
    5002             :         long long unsigned val;
    5003             :         u64 req;
    5004           9 :         if (sscanf(cmd, "%llx", &val) != 1)
    5005           1 :                 return -1;
    5006           8 :         req = val;
    5007           8 :         return wpas_p2p_sd_cancel_request(wpa_s, req);
    5008             : }
    5009             : 
    5010             : 
    5011           9 : static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
    5012             : {
    5013             :         int freq;
    5014             :         u8 dst[ETH_ALEN];
    5015             :         u8 dialog_token;
    5016             :         struct wpabuf *resp_tlvs;
    5017             :         char *pos, *pos2;
    5018             :         size_t len;
    5019             : 
    5020           9 :         pos = os_strchr(cmd, ' ');
    5021           9 :         if (pos == NULL)
    5022           1 :                 return -1;
    5023           8 :         *pos++ = '\0';
    5024           8 :         freq = atoi(cmd);
    5025           8 :         if (freq == 0)
    5026           1 :                 return -1;
    5027             : 
    5028           7 :         if (hwaddr_aton(pos, dst))
    5029           1 :                 return -1;
    5030           6 :         pos += 17;
    5031           6 :         if (*pos != ' ')
    5032           1 :                 return -1;
    5033           5 :         pos++;
    5034             : 
    5035           5 :         pos2 = os_strchr(pos, ' ');
    5036           5 :         if (pos2 == NULL)
    5037           1 :                 return -1;
    5038           4 :         *pos2++ = '\0';
    5039           4 :         dialog_token = atoi(pos);
    5040             : 
    5041           4 :         len = os_strlen(pos2);
    5042           4 :         if (len & 1)
    5043           1 :                 return -1;
    5044           3 :         len /= 2;
    5045           3 :         resp_tlvs = wpabuf_alloc(len);
    5046           3 :         if (resp_tlvs == NULL)
    5047           0 :                 return -1;
    5048           3 :         if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
    5049           1 :                 wpabuf_free(resp_tlvs);
    5050           1 :                 return -1;
    5051             :         }
    5052             : 
    5053           2 :         wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
    5054           2 :         wpabuf_free(resp_tlvs);
    5055           2 :         return 0;
    5056             : }
    5057             : 
    5058             : 
    5059           4 : static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
    5060             :                                        char *cmd)
    5061             : {
    5062           4 :         if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
    5063           1 :                 return -1;
    5064           3 :         wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
    5065           3 :         return 0;
    5066             : }
    5067             : 
    5068             : 
    5069         118 : static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
    5070             :                                         char *cmd)
    5071             : {
    5072             :         char *pos;
    5073             :         size_t len;
    5074             :         struct wpabuf *query, *resp;
    5075             : 
    5076         118 :         pos = os_strchr(cmd, ' ');
    5077         118 :         if (pos == NULL)
    5078           1 :                 return -1;
    5079         117 :         *pos++ = '\0';
    5080             : 
    5081         117 :         len = os_strlen(cmd);
    5082         117 :         if (len & 1)
    5083           1 :                 return -1;
    5084         116 :         len /= 2;
    5085         116 :         query = wpabuf_alloc(len);
    5086         116 :         if (query == NULL)
    5087           0 :                 return -1;
    5088         116 :         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
    5089           1 :                 wpabuf_free(query);
    5090           1 :                 return -1;
    5091             :         }
    5092             : 
    5093         115 :         len = os_strlen(pos);
    5094         115 :         if (len & 1) {
    5095           1 :                 wpabuf_free(query);
    5096           1 :                 return -1;
    5097             :         }
    5098         114 :         len /= 2;
    5099         114 :         resp = wpabuf_alloc(len);
    5100         114 :         if (resp == NULL) {
    5101           0 :                 wpabuf_free(query);
    5102           0 :                 return -1;
    5103             :         }
    5104         114 :         if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
    5105           1 :                 wpabuf_free(query);
    5106           1 :                 wpabuf_free(resp);
    5107           1 :                 return -1;
    5108             :         }
    5109             : 
    5110         113 :         if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
    5111           0 :                 wpabuf_free(query);
    5112           0 :                 wpabuf_free(resp);
    5113           0 :                 return -1;
    5114             :         }
    5115         113 :         return 0;
    5116             : }
    5117             : 
    5118             : 
    5119         542 : static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
    5120             : {
    5121             :         char *pos;
    5122             :         u8 version;
    5123             : 
    5124         542 :         pos = os_strchr(cmd, ' ');
    5125         542 :         if (pos == NULL)
    5126           1 :                 return -1;
    5127         541 :         *pos++ = '\0';
    5128             : 
    5129         541 :         if (hexstr2bin(cmd, &version, 1) < 0)
    5130           1 :                 return -1;
    5131             : 
    5132         540 :         return wpas_p2p_service_add_upnp(wpa_s, version, pos);
    5133             : }
    5134             : 
    5135             : 
    5136          28 : static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
    5137             :                                     u8 replace, char *cmd)
    5138             : {
    5139             :         char *pos;
    5140             :         char *adv_str;
    5141             :         u32 auto_accept, adv_id, svc_state, config_methods;
    5142          28 :         char *svc_info = NULL;
    5143             : 
    5144          28 :         pos = os_strchr(cmd, ' ');
    5145          28 :         if (pos == NULL)
    5146           0 :                 return -1;
    5147          28 :         *pos++ = '\0';
    5148             : 
    5149             :         /* Auto-Accept value is mandatory, and must be one of the
    5150             :          * single values (0, 1, 2, 4) */
    5151          28 :         auto_accept = atoi(cmd);
    5152          28 :         switch (auto_accept) {
    5153             :         case P2PS_SETUP_NONE: /* No auto-accept */
    5154             :         case P2PS_SETUP_NEW:
    5155             :         case P2PS_SETUP_CLIENT:
    5156             :         case P2PS_SETUP_GROUP_OWNER:
    5157          28 :                 break;
    5158             :         default:
    5159           0 :                 return -1;
    5160             :         }
    5161             : 
    5162             :         /* Advertisement ID is mandatory */
    5163          28 :         cmd = pos;
    5164          28 :         pos = os_strchr(cmd, ' ');
    5165          28 :         if (pos == NULL)
    5166           0 :                 return -1;
    5167          28 :         *pos++ = '\0';
    5168             : 
    5169             :         /* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
    5170          28 :         if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
    5171           0 :                 return -1;
    5172             : 
    5173             :         /* Only allow replacements if exist, and adds if not */
    5174          28 :         if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
    5175           2 :                 if (!replace)
    5176           0 :                         return -1;
    5177             :         } else {
    5178          26 :                 if (replace)
    5179           0 :                         return -1;
    5180             :         }
    5181             : 
    5182             :         /* svc_state between 0 - 0xff is mandatory */
    5183          28 :         if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
    5184           0 :                 return -1;
    5185             : 
    5186          28 :         pos = os_strchr(pos, ' ');
    5187          28 :         if (pos == NULL)
    5188           0 :                 return -1;
    5189             : 
    5190             :         /* config_methods is mandatory */
    5191          28 :         pos++;
    5192          28 :         if (sscanf(pos, "%x", &config_methods) != 1)
    5193           0 :                 return -1;
    5194             : 
    5195          28 :         if (!(config_methods &
    5196             :               (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
    5197           0 :                 return -1;
    5198             : 
    5199          28 :         pos = os_strchr(pos, ' ');
    5200          28 :         if (pos == NULL)
    5201           0 :                 return -1;
    5202             : 
    5203          28 :         pos++;
    5204          28 :         adv_str = pos;
    5205             : 
    5206             :         /* Advertisement string is mandatory */
    5207          28 :         if (!pos[0] || pos[0] == ' ')
    5208           0 :                 return -1;
    5209             : 
    5210             :         /* Terminate svc string */
    5211          28 :         pos = os_strchr(pos, ' ');
    5212          28 :         if (pos != NULL)
    5213          28 :                 *pos++ = '\0';
    5214             : 
    5215             :         /* Service and Response Information are optional */
    5216          28 :         if (pos && pos[0]) {
    5217             :                 size_t len;
    5218             : 
    5219             :                 /* Note the bare ' included, which cannot exist legally
    5220             :                  * in unescaped string. */
    5221          28 :                 svc_info = os_strstr(pos, "svc_info='");
    5222             : 
    5223          28 :                 if (svc_info) {
    5224          28 :                         svc_info += 9;
    5225          28 :                         len = os_strlen(svc_info);
    5226          28 :                         utf8_unescape(svc_info, len, svc_info, len);
    5227             :                 }
    5228             :         }
    5229             : 
    5230          56 :         return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
    5231          56 :                                         (u8) svc_state, (u16) config_methods,
    5232             :                                         svc_info);
    5233             : }
    5234             : 
    5235             : 
    5236         688 : static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
    5237             : {
    5238             :         char *pos;
    5239             : 
    5240         688 :         pos = os_strchr(cmd, ' ');
    5241         688 :         if (pos == NULL)
    5242           1 :                 return -1;
    5243         687 :         *pos++ = '\0';
    5244             : 
    5245         687 :         if (os_strcmp(cmd, "bonjour") == 0)
    5246         118 :                 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
    5247         569 :         if (os_strcmp(cmd, "upnp") == 0)
    5248         542 :                 return p2p_ctrl_service_add_upnp(wpa_s, pos);
    5249          27 :         if (os_strcmp(cmd, "asp") == 0)
    5250          26 :                 return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
    5251           1 :         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
    5252           1 :         return -1;
    5253             : }
    5254             : 
    5255             : 
    5256          40 : static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
    5257             :                                         char *cmd)
    5258             : {
    5259             :         size_t len;
    5260             :         struct wpabuf *query;
    5261             :         int ret;
    5262             : 
    5263          40 :         len = os_strlen(cmd);
    5264          40 :         if (len & 1)
    5265           1 :                 return -1;
    5266          39 :         len /= 2;
    5267          39 :         query = wpabuf_alloc(len);
    5268          39 :         if (query == NULL)
    5269           0 :                 return -1;
    5270          39 :         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
    5271           1 :                 wpabuf_free(query);
    5272           1 :                 return -1;
    5273             :         }
    5274             : 
    5275          38 :         ret = wpas_p2p_service_del_bonjour(wpa_s, query);
    5276          38 :         wpabuf_free(query);
    5277          38 :         return ret;
    5278             : }
    5279             : 
    5280             : 
    5281          41 : static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
    5282             : {
    5283             :         char *pos;
    5284             :         u8 version;
    5285             : 
    5286          41 :         pos = os_strchr(cmd, ' ');
    5287          41 :         if (pos == NULL)
    5288           1 :                 return -1;
    5289          40 :         *pos++ = '\0';
    5290             : 
    5291          40 :         if (hexstr2bin(cmd, &version, 1) < 0)
    5292           2 :                 return -1;
    5293             : 
    5294          38 :         return wpas_p2p_service_del_upnp(wpa_s, version, pos);
    5295             : }
    5296             : 
    5297             : 
    5298          23 : static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
    5299             : {
    5300             :         u32 adv_id;
    5301             : 
    5302          23 :         if (sscanf(cmd, "%x", &adv_id) != 1)
    5303           0 :                 return -1;
    5304             : 
    5305          23 :         return wpas_p2p_service_del_asp(wpa_s, adv_id);
    5306             : }
    5307             : 
    5308             : 
    5309         106 : static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
    5310             : {
    5311             :         char *pos;
    5312             : 
    5313         106 :         pos = os_strchr(cmd, ' ');
    5314         106 :         if (pos == NULL)
    5315           1 :                 return -1;
    5316         105 :         *pos++ = '\0';
    5317             : 
    5318         105 :         if (os_strcmp(cmd, "bonjour") == 0)
    5319          40 :                 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
    5320          65 :         if (os_strcmp(cmd, "upnp") == 0)
    5321          41 :                 return p2p_ctrl_service_del_upnp(wpa_s, pos);
    5322          24 :         if (os_strcmp(cmd, "asp") == 0)
    5323          23 :                 return p2p_ctrl_service_del_asp(wpa_s, pos);
    5324           1 :         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
    5325           1 :         return -1;
    5326             : }
    5327             : 
    5328             : 
    5329           2 : static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
    5330             : {
    5331             :         char *pos;
    5332             : 
    5333           2 :         pos = os_strchr(cmd, ' ');
    5334           2 :         if (pos == NULL)
    5335           0 :                 return -1;
    5336           2 :         *pos++ = '\0';
    5337             : 
    5338           2 :         if (os_strcmp(cmd, "asp") == 0)
    5339           2 :                 return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
    5340             : 
    5341           0 :         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
    5342           0 :         return -1;
    5343             : }
    5344             : 
    5345             : 
    5346           3 : static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
    5347             : {
    5348             :         u8 addr[ETH_ALEN];
    5349             : 
    5350             :         /* <addr> */
    5351             : 
    5352           3 :         if (hwaddr_aton(cmd, addr))
    5353           1 :                 return -1;
    5354             : 
    5355           2 :         return wpas_p2p_reject(wpa_s, addr);
    5356             : }
    5357             : 
    5358             : 
    5359          38 : static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
    5360             : {
    5361             :         char *pos;
    5362             :         int id;
    5363             :         struct wpa_ssid *ssid;
    5364          38 :         u8 *_peer = NULL, peer[ETH_ALEN];
    5365          38 :         int freq = 0, pref_freq = 0;
    5366             :         int ht40, vht;
    5367             : 
    5368          38 :         id = atoi(cmd);
    5369          38 :         pos = os_strstr(cmd, " peer=");
    5370          38 :         if (pos) {
    5371          36 :                 pos += 6;
    5372          36 :                 if (hwaddr_aton(pos, peer))
    5373           1 :                         return -1;
    5374          35 :                 _peer = peer;
    5375             :         }
    5376          37 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    5377          37 :         if (ssid == NULL || ssid->disabled != 2) {
    5378           2 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
    5379             :                            "for persistent P2P group",
    5380             :                            id);
    5381           2 :                 return -1;
    5382             :         }
    5383             : 
    5384          35 :         pos = os_strstr(cmd, " freq=");
    5385          35 :         if (pos) {
    5386           7 :                 pos += 6;
    5387           7 :                 freq = atoi(pos);
    5388           7 :                 if (freq <= 0)
    5389           1 :                         return -1;
    5390             :         }
    5391             : 
    5392          34 :         pos = os_strstr(cmd, " pref=");
    5393          34 :         if (pos) {
    5394           4 :                 pos += 6;
    5395           4 :                 pref_freq = atoi(pos);
    5396           4 :                 if (pref_freq <= 0)
    5397           1 :                         return -1;
    5398             :         }
    5399             : 
    5400          33 :         vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
    5401          33 :         ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
    5402             :                 vht;
    5403             : 
    5404          33 :         return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, vht,
    5405             :                                pref_freq);
    5406             : }
    5407             : 
    5408             : 
    5409          11 : static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
    5410             : {
    5411             :         char *pos;
    5412          11 :         u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
    5413             : 
    5414          11 :         pos = os_strstr(cmd, " peer=");
    5415          11 :         if (!pos)
    5416           1 :                 return -1;
    5417             : 
    5418          10 :         *pos = '\0';
    5419          10 :         pos += 6;
    5420          10 :         if (hwaddr_aton(pos, peer)) {
    5421           1 :                 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
    5422           1 :                 return -1;
    5423             :         }
    5424             : 
    5425           9 :         pos = os_strstr(pos, " go_dev_addr=");
    5426           9 :         if (pos) {
    5427           1 :                 pos += 13;
    5428           1 :                 if (hwaddr_aton(pos, go_dev_addr)) {
    5429           1 :                         wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
    5430             :                                    pos);
    5431           1 :                         return -1;
    5432             :                 }
    5433           0 :                 go_dev = go_dev_addr;
    5434             :         }
    5435             : 
    5436           8 :         return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
    5437             : }
    5438             : 
    5439             : 
    5440          50 : static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
    5441             : {
    5442          50 :         if (os_strncmp(cmd, "persistent=", 11) == 0)
    5443          38 :                 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
    5444          12 :         if (os_strncmp(cmd, "group=", 6) == 0)
    5445          11 :                 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
    5446             : 
    5447           1 :         return -1;
    5448             : }
    5449             : 
    5450             : 
    5451          17 : static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
    5452             :                                          char *cmd, int freq, int ht40,
    5453             :                                          int vht)
    5454             : {
    5455             :         int id;
    5456             :         struct wpa_ssid *ssid;
    5457             : 
    5458          17 :         id = atoi(cmd);
    5459          17 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    5460          17 :         if (ssid == NULL || ssid->disabled != 2) {
    5461           2 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
    5462             :                            "for persistent P2P group",
    5463             :                            id);
    5464           2 :                 return -1;
    5465             :         }
    5466             : 
    5467          15 :         return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, ht40, vht,
    5468             :                                              NULL, 0);
    5469             : }
    5470             : 
    5471             : 
    5472         132 : static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
    5473             : {
    5474         132 :         int freq = 0, ht40, vht;
    5475             :         char *pos;
    5476             : 
    5477         132 :         pos = os_strstr(cmd, "freq=");
    5478         132 :         if (pos)
    5479         122 :                 freq = atoi(pos + 5);
    5480             : 
    5481         132 :         vht = (os_strstr(cmd, "vht") != NULL) || wpa_s->conf->p2p_go_vht;
    5482         132 :         ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
    5483             :                 vht;
    5484             : 
    5485         132 :         if (os_strncmp(cmd, "persistent=", 11) == 0)
    5486          17 :                 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
    5487             :                                                      ht40, vht);
    5488         228 :         if (os_strcmp(cmd, "persistent") == 0 ||
    5489         113 :             os_strncmp(cmd, "persistent ", 11) == 0)
    5490           2 :                 return wpas_p2p_group_add(wpa_s, 1, freq, ht40, vht);
    5491         113 :         if (os_strncmp(cmd, "freq=", 5) == 0)
    5492         110 :                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
    5493           3 :         if (ht40)
    5494           2 :                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
    5495             : 
    5496           1 :         wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
    5497             :                    cmd);
    5498           1 :         return -1;
    5499             : }
    5500             : 
    5501             : 
    5502         952 : static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
    5503             :                          char *buf, size_t buflen)
    5504             : {
    5505             :         u8 addr[ETH_ALEN], *addr_ptr;
    5506             :         int next, res;
    5507             :         const struct p2p_peer_info *info;
    5508             :         char *pos, *end;
    5509             :         char devtype[WPS_DEV_TYPE_BUFSIZE];
    5510             :         struct wpa_ssid *ssid;
    5511             :         size_t i;
    5512             : 
    5513         952 :         if (!wpa_s->global->p2p)
    5514           0 :                 return -1;
    5515             : 
    5516         952 :         if (os_strcmp(cmd, "FIRST") == 0) {
    5517           1 :                 addr_ptr = NULL;
    5518           1 :                 next = 0;
    5519         951 :         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
    5520           2 :                 if (hwaddr_aton(cmd + 5, addr) < 0)
    5521           1 :                         return -1;
    5522           1 :                 addr_ptr = addr;
    5523           1 :                 next = 1;
    5524             :         } else {
    5525         949 :                 if (hwaddr_aton(cmd, addr) < 0)
    5526           1 :                         return -1;
    5527         948 :                 addr_ptr = addr;
    5528         948 :                 next = 0;
    5529             :         }
    5530             : 
    5531         950 :         info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
    5532         950 :         if (info == NULL)
    5533         437 :                 return -1;
    5534             : 
    5535         513 :         pos = buf;
    5536         513 :         end = buf + buflen;
    5537             : 
    5538        5643 :         res = os_snprintf(pos, end - pos, MACSTR "\n"
    5539             :                           "pri_dev_type=%s\n"
    5540             :                           "device_name=%s\n"
    5541             :                           "manufacturer=%s\n"
    5542             :                           "model_name=%s\n"
    5543             :                           "model_number=%s\n"
    5544             :                           "serial_number=%s\n"
    5545             :                           "config_methods=0x%x\n"
    5546             :                           "dev_capab=0x%x\n"
    5547             :                           "group_capab=0x%x\n"
    5548             :                           "level=%d\n",
    5549        3078 :                           MAC2STR(info->p2p_device_addr),
    5550         513 :                           wps_dev_type_bin2str(info->pri_dev_type,
    5551             :                                                devtype, sizeof(devtype)),
    5552         513 :                           info->device_name,
    5553         513 :                           info->manufacturer,
    5554         513 :                           info->model_name,
    5555         513 :                           info->model_number,
    5556         513 :                           info->serial_number,
    5557         513 :                           info->config_methods,
    5558         513 :                           info->dev_capab,
    5559         513 :                           info->group_capab,
    5560             :                           info->level);
    5561         513 :         if (os_snprintf_error(end - pos, res))
    5562           0 :                 return pos - buf;
    5563         513 :         pos += res;
    5564             : 
    5565         519 :         for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
    5566             :         {
    5567             :                 const u8 *t;
    5568           6 :                 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
    5569           6 :                 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
    5570             :                                   wps_dev_type_bin2str(t, devtype,
    5571             :                                                        sizeof(devtype)));
    5572           6 :                 if (os_snprintf_error(end - pos, res))
    5573           0 :                         return pos - buf;
    5574           6 :                 pos += res;
    5575             :         }
    5576             : 
    5577         513 :         ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
    5578         513 :         if (ssid) {
    5579          82 :                 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
    5580          82 :                 if (os_snprintf_error(end - pos, res))
    5581           0 :                         return pos - buf;
    5582          82 :                 pos += res;
    5583             :         }
    5584             : 
    5585         513 :         res = p2p_get_peer_info_txt(info, pos, end - pos);
    5586         513 :         if (res < 0)
    5587           0 :                 return pos - buf;
    5588         513 :         pos += res;
    5589             : 
    5590         513 :         if (info->vendor_elems) {
    5591           4 :                 res = os_snprintf(pos, end - pos, "vendor_elems=");
    5592           4 :                 if (os_snprintf_error(end - pos, res))
    5593           0 :                         return pos - buf;
    5594           4 :                 pos += res;
    5595             : 
    5596           8 :                 pos += wpa_snprintf_hex(pos, end - pos,
    5597           4 :                                         wpabuf_head(info->vendor_elems),
    5598           4 :                                         wpabuf_len(info->vendor_elems));
    5599             : 
    5600           4 :                 res = os_snprintf(pos, end - pos, "\n");
    5601           4 :                 if (os_snprintf_error(end - pos, res))
    5602           0 :                         return pos - buf;
    5603           4 :                 pos += res;
    5604             :         }
    5605             : 
    5606         513 :         return pos - buf;
    5607             : }
    5608             : 
    5609             : 
    5610          18 : static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
    5611             :                                   const char *param)
    5612             : {
    5613             :         unsigned int i;
    5614             : 
    5615          18 :         if (wpa_s->global->p2p == NULL)
    5616           0 :                 return -1;
    5617             : 
    5618          18 :         if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
    5619           0 :                 return -1;
    5620             : 
    5621          35 :         for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
    5622             :                 struct wpa_freq_range *freq;
    5623          17 :                 freq = &wpa_s->global->p2p_disallow_freq.range[i];
    5624          17 :                 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
    5625             :                            freq->min, freq->max);
    5626             :         }
    5627             : 
    5628          18 :         wpas_p2p_update_channel_list(wpa_s);
    5629          18 :         return 0;
    5630             : }
    5631             : 
    5632             : 
    5633         106 : static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
    5634             : {
    5635             :         char *param;
    5636             : 
    5637         106 :         if (wpa_s->global->p2p == NULL)
    5638           0 :                 return -1;
    5639             : 
    5640         106 :         param = os_strchr(cmd, ' ');
    5641         106 :         if (param == NULL)
    5642           1 :                 return -1;
    5643         105 :         *param++ = '\0';
    5644             : 
    5645         105 :         if (os_strcmp(cmd, "discoverability") == 0) {
    5646           2 :                 p2p_set_client_discoverability(wpa_s->global->p2p,
    5647             :                                                atoi(param));
    5648           2 :                 return 0;
    5649             :         }
    5650             : 
    5651         103 :         if (os_strcmp(cmd, "managed") == 0) {
    5652           2 :                 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
    5653           2 :                 return 0;
    5654             :         }
    5655             : 
    5656         101 :         if (os_strcmp(cmd, "listen_channel") == 0) {
    5657           4 :                 return p2p_set_listen_channel(wpa_s->global->p2p, 81,
    5658           4 :                                               atoi(param), 1);
    5659             :         }
    5660             : 
    5661          97 :         if (os_strcmp(cmd, "ssid_postfix") == 0) {
    5662           4 :                 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
    5663             :                                             os_strlen(param));
    5664             :         }
    5665             : 
    5666          93 :         if (os_strcmp(cmd, "noa") == 0) {
    5667             :                 char *pos;
    5668             :                 int count, start, duration;
    5669             :                 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
    5670           9 :                 count = atoi(param);
    5671           9 :                 pos = os_strchr(param, ',');
    5672           9 :                 if (pos == NULL)
    5673           1 :                         return -1;
    5674           8 :                 pos++;
    5675           8 :                 start = atoi(pos);
    5676           8 :                 pos = os_strchr(pos, ',');
    5677           8 :                 if (pos == NULL)
    5678           1 :                         return -1;
    5679           7 :                 pos++;
    5680           7 :                 duration = atoi(pos);
    5681           7 :                 if (count < 0 || count > 255 || start < 0 || duration < 0)
    5682           4 :                         return -1;
    5683           3 :                 if (count == 0 && duration > 0)
    5684           1 :                         return -1;
    5685           2 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
    5686             :                            "start=%d duration=%d", count, start, duration);
    5687           2 :                 return wpas_p2p_set_noa(wpa_s, count, start, duration);
    5688             :         }
    5689             : 
    5690          84 :         if (os_strcmp(cmd, "ps") == 0)
    5691           2 :                 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
    5692             : 
    5693          82 :         if (os_strcmp(cmd, "oppps") == 0)
    5694           1 :                 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
    5695             : 
    5696          81 :         if (os_strcmp(cmd, "ctwindow") == 0)
    5697           1 :                 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
    5698             : 
    5699          80 :         if (os_strcmp(cmd, "disabled") == 0) {
    5700          24 :                 wpa_s->global->p2p_disabled = atoi(param);
    5701          24 :                 wpa_printf(MSG_DEBUG, "P2P functionality %s",
    5702          24 :                            wpa_s->global->p2p_disabled ?
    5703             :                            "disabled" : "enabled");
    5704          24 :                 if (wpa_s->global->p2p_disabled) {
    5705          14 :                         wpas_p2p_stop_find(wpa_s);
    5706          14 :                         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
    5707          14 :                         p2p_flush(wpa_s->global->p2p);
    5708             :                 }
    5709          24 :                 return 0;
    5710             :         }
    5711             : 
    5712          56 :         if (os_strcmp(cmd, "conc_pref") == 0) {
    5713           1 :                 if (os_strcmp(param, "sta") == 0)
    5714           0 :                         wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
    5715           1 :                 else if (os_strcmp(param, "p2p") == 0)
    5716           0 :                         wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
    5717             :                 else {
    5718           1 :                         wpa_printf(MSG_INFO, "Invalid conc_pref value");
    5719           1 :                         return -1;
    5720             :                 }
    5721           0 :                 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
    5722             :                            "%s", param);
    5723           0 :                 return 0;
    5724             :         }
    5725             : 
    5726          55 :         if (os_strcmp(cmd, "force_long_sd") == 0) {
    5727           0 :                 wpa_s->force_long_sd = atoi(param);
    5728           0 :                 return 0;
    5729             :         }
    5730             : 
    5731          55 :         if (os_strcmp(cmd, "peer_filter") == 0) {
    5732             :                 u8 addr[ETH_ALEN];
    5733           3 :                 if (hwaddr_aton(param, addr))
    5734           1 :                         return -1;
    5735           2 :                 p2p_set_peer_filter(wpa_s->global->p2p, addr);
    5736           2 :                 return 0;
    5737             :         }
    5738             : 
    5739          52 :         if (os_strcmp(cmd, "cross_connect") == 0)
    5740           5 :                 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
    5741             : 
    5742          47 :         if (os_strcmp(cmd, "go_apsd") == 0) {
    5743           0 :                 if (os_strcmp(param, "disable") == 0)
    5744           0 :                         wpa_s->set_ap_uapsd = 0;
    5745             :                 else {
    5746           0 :                         wpa_s->set_ap_uapsd = 1;
    5747           0 :                         wpa_s->ap_uapsd = atoi(param);
    5748             :                 }
    5749           0 :                 return 0;
    5750             :         }
    5751             : 
    5752          47 :         if (os_strcmp(cmd, "client_apsd") == 0) {
    5753           3 :                 if (os_strcmp(param, "disable") == 0)
    5754           0 :                         wpa_s->set_sta_uapsd = 0;
    5755             :                 else {
    5756             :                         int be, bk, vi, vo;
    5757             :                         char *pos;
    5758             :                         /* format: BE,BK,VI,VO;max SP Length */
    5759           3 :                         be = atoi(param);
    5760           3 :                         pos = os_strchr(param, ',');
    5761           3 :                         if (pos == NULL)
    5762           1 :                                 return -1;
    5763           2 :                         pos++;
    5764           2 :                         bk = atoi(pos);
    5765           2 :                         pos = os_strchr(pos, ',');
    5766           2 :                         if (pos == NULL)
    5767           1 :                                 return -1;
    5768           1 :                         pos++;
    5769           1 :                         vi = atoi(pos);
    5770           1 :                         pos = os_strchr(pos, ',');
    5771           1 :                         if (pos == NULL)
    5772           1 :                                 return -1;
    5773           0 :                         pos++;
    5774           0 :                         vo = atoi(pos);
    5775             :                         /* ignore max SP Length for now */
    5776             : 
    5777           0 :                         wpa_s->set_sta_uapsd = 1;
    5778           0 :                         wpa_s->sta_uapsd = 0;
    5779           0 :                         if (be)
    5780           0 :                                 wpa_s->sta_uapsd |= BIT(0);
    5781           0 :                         if (bk)
    5782           0 :                                 wpa_s->sta_uapsd |= BIT(1);
    5783           0 :                         if (vi)
    5784           0 :                                 wpa_s->sta_uapsd |= BIT(2);
    5785           0 :                         if (vo)
    5786           0 :                                 wpa_s->sta_uapsd |= BIT(3);
    5787             :                 }
    5788           0 :                 return 0;
    5789             :         }
    5790             : 
    5791          44 :         if (os_strcmp(cmd, "disallow_freq") == 0)
    5792          18 :                 return p2p_ctrl_disallow_freq(wpa_s, param);
    5793             : 
    5794          26 :         if (os_strcmp(cmd, "disc_int") == 0) {
    5795             :                 int min_disc_int, max_disc_int, max_disc_tu;
    5796             :                 char *pos;
    5797             : 
    5798           5 :                 pos = param;
    5799             : 
    5800           5 :                 min_disc_int = atoi(pos);
    5801           5 :                 pos = os_strchr(pos, ' ');
    5802           5 :                 if (pos == NULL)
    5803           1 :                         return -1;
    5804           4 :                 *pos++ = '\0';
    5805             : 
    5806           4 :                 max_disc_int = atoi(pos);
    5807           4 :                 pos = os_strchr(pos, ' ');
    5808           4 :                 if (pos == NULL)
    5809           1 :                         return -1;
    5810           3 :                 *pos++ = '\0';
    5811             : 
    5812           3 :                 max_disc_tu = atoi(pos);
    5813             : 
    5814           3 :                 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
    5815             :                                         max_disc_int, max_disc_tu);
    5816             :         }
    5817             : 
    5818          21 :         if (os_strcmp(cmd, "per_sta_psk") == 0) {
    5819           4 :                 wpa_s->global->p2p_per_sta_psk = !!atoi(param);
    5820           4 :                 return 0;
    5821             :         }
    5822             : 
    5823             : #ifdef CONFIG_WPS_NFC
    5824          17 :         if (os_strcmp(cmd, "nfc_tag") == 0)
    5825          14 :                 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
    5826             : #endif /* CONFIG_WPS_NFC */
    5827             : 
    5828           3 :         if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
    5829           2 :                 wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
    5830           2 :                 return 0;
    5831             :         }
    5832             : 
    5833           1 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
    5834             :                    cmd);
    5835             : 
    5836           1 :         return -1;
    5837             : }
    5838             : 
    5839             : 
    5840        3382 : static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
    5841             : {
    5842        3382 :         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
    5843        3382 :         wpa_s->force_long_sd = 0;
    5844        3382 :         wpas_p2p_stop_find(wpa_s);
    5845        3382 :         if (wpa_s->global->p2p)
    5846        3382 :                 p2p_flush(wpa_s->global->p2p);
    5847        3382 : }
    5848             : 
    5849             : 
    5850           6 : static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
    5851             : {
    5852             :         char *pos, *pos2;
    5853           6 :         unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
    5854             : 
    5855           6 :         if (cmd[0]) {
    5856           5 :                 pos = os_strchr(cmd, ' ');
    5857           5 :                 if (pos == NULL)
    5858           1 :                         return -1;
    5859           4 :                 *pos++ = '\0';
    5860           4 :                 dur1 = atoi(cmd);
    5861             : 
    5862           4 :                 pos2 = os_strchr(pos, ' ');
    5863           4 :                 if (pos2)
    5864           2 :                         *pos2++ = '\0';
    5865           4 :                 int1 = atoi(pos);
    5866             :         } else
    5867           1 :                 pos2 = NULL;
    5868             : 
    5869           5 :         if (pos2) {
    5870           2 :                 pos = os_strchr(pos2, ' ');
    5871           2 :                 if (pos == NULL)
    5872           1 :                         return -1;
    5873           1 :                 *pos++ = '\0';
    5874           1 :                 dur2 = atoi(pos2);
    5875           1 :                 int2 = atoi(pos);
    5876             :         }
    5877             : 
    5878           4 :         return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
    5879             : }
    5880             : 
    5881             : 
    5882           6 : static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
    5883             : {
    5884             :         char *pos;
    5885           6 :         unsigned int period = 0, interval = 0;
    5886             : 
    5887           6 :         if (cmd[0]) {
    5888           3 :                 pos = os_strchr(cmd, ' ');
    5889           3 :                 if (pos == NULL)
    5890           1 :                         return -1;
    5891           2 :                 *pos++ = '\0';
    5892           2 :                 period = atoi(cmd);
    5893           2 :                 interval = atoi(pos);
    5894             :         }
    5895             : 
    5896           5 :         return wpas_p2p_ext_listen(wpa_s, period, interval);
    5897             : }
    5898             : 
    5899             : 
    5900           7 : static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
    5901             : {
    5902             :         const char *pos;
    5903             :         u8 peer[ETH_ALEN];
    5904           7 :         int iface_addr = 0;
    5905             : 
    5906           7 :         pos = cmd;
    5907           7 :         if (os_strncmp(pos, "iface=", 6) == 0) {
    5908           2 :                 iface_addr = 1;
    5909           2 :                 pos += 6;
    5910             :         }
    5911           7 :         if (hwaddr_aton(pos, peer))
    5912           1 :                 return -1;
    5913             : 
    5914           6 :         wpas_p2p_remove_client(wpa_s, peer, iface_addr);
    5915           6 :         return 0;
    5916             : }
    5917             : 
    5918             : #endif /* CONFIG_P2P */
    5919             : 
    5920             : 
    5921         633 : static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
    5922             : {
    5923             :         struct wpa_freq_range_list ranges;
    5924         633 :         int *freqs = NULL;
    5925             :         struct hostapd_hw_modes *mode;
    5926             :         u16 i;
    5927             : 
    5928         633 :         if (wpa_s->hw.modes == NULL)
    5929           0 :                 return NULL;
    5930             : 
    5931         633 :         os_memset(&ranges, 0, sizeof(ranges));
    5932         633 :         if (freq_range_list_parse(&ranges, val) < 0)
    5933           0 :                 return NULL;
    5934             : 
    5935        2532 :         for (i = 0; i < wpa_s->hw.num_modes; i++) {
    5936             :                 int j;
    5937             : 
    5938        1899 :                 mode = &wpa_s->hw.modes[i];
    5939       34815 :                 for (j = 0; j < mode->num_channels; j++) {
    5940             :                         unsigned int freq;
    5941             : 
    5942       32916 :                         if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
    5943         454 :                                 continue;
    5944             : 
    5945       32462 :                         freq = mode->channels[j].freq;
    5946       32462 :                         if (!freq_range_list_includes(&ranges, freq))
    5947       30997 :                                 continue;
    5948             : 
    5949        1465 :                         int_array_add_unique(&freqs, freq);
    5950             :                 }
    5951             :         }
    5952             : 
    5953         633 :         os_free(ranges.range);
    5954         633 :         return freqs;
    5955             : }
    5956             : 
    5957             : 
    5958             : #ifdef CONFIG_INTERWORKING
    5959             : 
    5960         133 : static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
    5961             : {
    5962         133 :         int auto_sel = 0;
    5963         133 :         int *freqs = NULL;
    5964             : 
    5965         133 :         if (param) {
    5966             :                 char *pos;
    5967             : 
    5968         132 :                 auto_sel = os_strstr(param, "auto") != NULL;
    5969             : 
    5970         132 :                 pos = os_strstr(param, "freq=");
    5971         132 :                 if (pos) {
    5972         131 :                         freqs = freq_range_to_channel_list(wpa_s, pos + 5);
    5973         131 :                         if (freqs == NULL)
    5974           0 :                                 return -1;
    5975             :                 }
    5976             : 
    5977             :         }
    5978             : 
    5979         133 :         return interworking_select(wpa_s, auto_sel, freqs);
    5980             : }
    5981             : 
    5982             : 
    5983          51 : static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
    5984             :                                      int only_add)
    5985             : {
    5986             :         u8 bssid[ETH_ALEN];
    5987             :         struct wpa_bss *bss;
    5988             : 
    5989          51 :         if (hwaddr_aton(dst, bssid)) {
    5990           1 :                 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
    5991           1 :                 return -1;
    5992             :         }
    5993             : 
    5994          50 :         bss = wpa_bss_get_bssid(wpa_s, bssid);
    5995          50 :         if (bss == NULL) {
    5996           6 :                 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
    5997           6 :                            MAC2STR(bssid));
    5998           1 :                 return -1;
    5999             :         }
    6000             : 
    6001          49 :         if (bss->ssid_len == 0) {
    6002           2 :                 int found = 0;
    6003             : 
    6004          12 :                 wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR
    6005          12 :                            " does not have SSID information", MAC2STR(bssid));
    6006             : 
    6007           4 :                 dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
    6008             :                                          list) {
    6009           8 :                         if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
    6010           4 :                             bss->ssid_len > 0) {
    6011           2 :                                 found = 1;
    6012           2 :                                 break;
    6013             :                         }
    6014             :                 }
    6015             : 
    6016           2 :                 if (!found)
    6017           0 :                         return -1;
    6018           2 :                 wpa_printf(MSG_DEBUG,
    6019             :                            "Found another matching BSS entry with SSID");
    6020             :         }
    6021             : 
    6022          49 :         return interworking_connect(wpa_s, bss, only_add);
    6023             : }
    6024             : 
    6025             : 
    6026          30 : static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
    6027             : {
    6028             :         u8 dst_addr[ETH_ALEN];
    6029             :         int used;
    6030             :         char *pos;
    6031             : #define MAX_ANQP_INFO_ID 100
    6032             :         u16 id[MAX_ANQP_INFO_ID];
    6033          30 :         size_t num_id = 0;
    6034          30 :         u32 subtypes = 0;
    6035             : 
    6036          30 :         used = hwaddr_aton2(dst, dst_addr);
    6037          30 :         if (used < 0)
    6038           2 :                 return -1;
    6039          28 :         pos = dst + used;
    6040          28 :         if (*pos == ' ')
    6041          27 :                 pos++;
    6042          62 :         while (num_id < MAX_ANQP_INFO_ID) {
    6043          34 :                 if (os_strncmp(pos, "hs20:", 5) == 0) {
    6044             : #ifdef CONFIG_HS20
    6045           8 :                         int num = atoi(pos + 5);
    6046           8 :                         if (num <= 0 || num > 31)
    6047           6 :                                 return -1;
    6048           2 :                         subtypes |= BIT(num);
    6049             : #else /* CONFIG_HS20 */
    6050             :                         return -1;
    6051             : #endif /* CONFIG_HS20 */
    6052             :                 } else {
    6053          26 :                         id[num_id] = atoi(pos);
    6054          26 :                         if (id[num_id])
    6055          23 :                                 num_id++;
    6056             :                 }
    6057          28 :                 pos = os_strchr(pos + 1, ',');
    6058          28 :                 if (pos == NULL)
    6059          22 :                         break;
    6060           6 :                 pos++;
    6061             :         }
    6062             : 
    6063          22 :         if (num_id == 0)
    6064           3 :                 return -1;
    6065             : 
    6066          19 :         return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes);
    6067             : }
    6068             : 
    6069             : 
    6070          20 : static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
    6071             : {
    6072             :         u8 dst_addr[ETH_ALEN];
    6073          20 :         struct wpabuf *advproto, *query = NULL;
    6074          20 :         int used, ret = -1;
    6075             :         char *pos, *end;
    6076             :         size_t len;
    6077             : 
    6078          20 :         used = hwaddr_aton2(cmd, dst_addr);
    6079          20 :         if (used < 0)
    6080           1 :                 return -1;
    6081             : 
    6082          19 :         pos = cmd + used;
    6083          57 :         while (*pos == ' ')
    6084          19 :                 pos++;
    6085             : 
    6086             :         /* Advertisement Protocol ID */
    6087          19 :         end = os_strchr(pos, ' ');
    6088          19 :         if (end)
    6089          14 :                 len = end - pos;
    6090             :         else
    6091           5 :                 len = os_strlen(pos);
    6092          19 :         if (len & 0x01)
    6093           2 :                 return -1;
    6094          17 :         len /= 2;
    6095          17 :         if (len == 0)
    6096           3 :                 return -1;
    6097          14 :         advproto = wpabuf_alloc(len);
    6098          14 :         if (advproto == NULL)
    6099           0 :                 return -1;
    6100          14 :         if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
    6101           2 :                 goto fail;
    6102             : 
    6103          12 :         if (end) {
    6104             :                 /* Optional Query Request */
    6105          12 :                 pos = end + 1;
    6106          29 :                 while (*pos == ' ')
    6107           5 :                         pos++;
    6108             : 
    6109          12 :                 len = os_strlen(pos);
    6110          12 :                 if (len) {
    6111          11 :                         if (len & 0x01)
    6112           2 :                                 goto fail;
    6113           9 :                         len /= 2;
    6114           9 :                         if (len == 0)
    6115           0 :                                 goto fail;
    6116           9 :                         query = wpabuf_alloc(len);
    6117           9 :                         if (query == NULL)
    6118           0 :                                 goto fail;
    6119           9 :                         if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
    6120           1 :                                 goto fail;
    6121             :                 }
    6122             :         }
    6123             : 
    6124           9 :         ret = gas_send_request(wpa_s, dst_addr, advproto, query);
    6125             : 
    6126             : fail:
    6127          14 :         wpabuf_free(advproto);
    6128          14 :         wpabuf_free(query);
    6129             : 
    6130          14 :         return ret;
    6131             : }
    6132             : 
    6133             : 
    6134          14 : static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
    6135             :                             size_t buflen)
    6136             : {
    6137             :         u8 addr[ETH_ALEN];
    6138             :         int dialog_token;
    6139             :         int used;
    6140             :         char *pos;
    6141             :         size_t resp_len, start, requested_len;
    6142             :         struct wpabuf *resp;
    6143             :         int ret;
    6144             : 
    6145          14 :         used = hwaddr_aton2(cmd, addr);
    6146          14 :         if (used < 0)
    6147           1 :                 return -1;
    6148             : 
    6149          13 :         pos = cmd + used;
    6150          39 :         while (*pos == ' ')
    6151          13 :                 pos++;
    6152          13 :         dialog_token = atoi(pos);
    6153             : 
    6154          26 :         if (wpa_s->last_gas_resp &&
    6155          26 :             os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
    6156          13 :             dialog_token == wpa_s->last_gas_dialog_token)
    6157          11 :                 resp = wpa_s->last_gas_resp;
    6158           3 :         else if (wpa_s->prev_gas_resp &&
    6159           2 :                  os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
    6160           1 :                  dialog_token == wpa_s->prev_gas_dialog_token)
    6161           1 :                 resp = wpa_s->prev_gas_resp;
    6162             :         else
    6163           1 :                 return -1;
    6164             : 
    6165          12 :         resp_len = wpabuf_len(resp);
    6166          12 :         start = 0;
    6167          12 :         requested_len = resp_len;
    6168             : 
    6169          12 :         pos = os_strchr(pos, ' ');
    6170          12 :         if (pos) {
    6171           5 :                 start = atoi(pos);
    6172           5 :                 if (start > resp_len)
    6173           1 :                         return os_snprintf(buf, buflen, "FAIL-Invalid range");
    6174           4 :                 pos = os_strchr(pos, ',');
    6175           4 :                 if (pos == NULL)
    6176           1 :                         return -1;
    6177           3 :                 pos++;
    6178           3 :                 requested_len = atoi(pos);
    6179           3 :                 if (start + requested_len > resp_len)
    6180           1 :                         return os_snprintf(buf, buflen, "FAIL-Invalid range");
    6181             :         }
    6182             : 
    6183           9 :         if (requested_len * 2 + 1 > buflen)
    6184           0 :                 return os_snprintf(buf, buflen, "FAIL-Too long response");
    6185             : 
    6186           9 :         ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
    6187             :                                requested_len);
    6188             : 
    6189           9 :         if (start + requested_len == resp_len) {
    6190             :                 /*
    6191             :                  * Free memory by dropping the response after it has been
    6192             :                  * fetched.
    6193             :                  */
    6194           7 :                 if (resp == wpa_s->prev_gas_resp) {
    6195           1 :                         wpabuf_free(wpa_s->prev_gas_resp);
    6196           1 :                         wpa_s->prev_gas_resp = NULL;
    6197             :                 } else {
    6198           6 :                         wpabuf_free(wpa_s->last_gas_resp);
    6199           6 :                         wpa_s->last_gas_resp = NULL;
    6200             :                 }
    6201             :         }
    6202             : 
    6203           9 :         return ret;
    6204             : }
    6205             : #endif /* CONFIG_INTERWORKING */
    6206             : 
    6207             : 
    6208             : #ifdef CONFIG_HS20
    6209             : 
    6210           9 : static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
    6211             : {
    6212             :         u8 dst_addr[ETH_ALEN];
    6213             :         int used;
    6214             :         char *pos;
    6215           9 :         u32 subtypes = 0;
    6216             : 
    6217           9 :         used = hwaddr_aton2(dst, dst_addr);
    6218           9 :         if (used < 0)
    6219           2 :                 return -1;
    6220           7 :         pos = dst + used;
    6221           7 :         if (*pos == ' ')
    6222           6 :                 pos++;
    6223             :         for (;;) {
    6224           8 :                 int num = atoi(pos);
    6225           8 :                 if (num <= 0 || num > 31)
    6226           6 :                         return -1;
    6227           2 :                 subtypes |= BIT(num);
    6228           2 :                 pos = os_strchr(pos + 1, ',');
    6229           2 :                 if (pos == NULL)
    6230           1 :                         break;
    6231           1 :                 pos++;
    6232           1 :         }
    6233             : 
    6234           1 :         if (subtypes == 0)
    6235           0 :                 return -1;
    6236             : 
    6237           1 :         return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
    6238             : }
    6239             : 
    6240             : 
    6241           2 : static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
    6242             :                                     const u8 *addr, const char *realm)
    6243             : {
    6244             :         u8 *buf;
    6245             :         size_t rlen, len;
    6246             :         int ret;
    6247             : 
    6248           2 :         rlen = os_strlen(realm);
    6249           2 :         len = 3 + rlen;
    6250           2 :         buf = os_malloc(len);
    6251           2 :         if (buf == NULL)
    6252           0 :                 return -1;
    6253           2 :         buf[0] = 1; /* NAI Home Realm Count */
    6254           2 :         buf[1] = 0; /* Formatted in accordance with RFC 4282 */
    6255           2 :         buf[2] = rlen;
    6256           2 :         os_memcpy(buf + 3, realm, rlen);
    6257             : 
    6258           2 :         ret = hs20_anqp_send_req(wpa_s, addr,
    6259             :                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
    6260             :                                  buf, len);
    6261             : 
    6262           2 :         os_free(buf);
    6263             : 
    6264           2 :         return ret;
    6265             : }
    6266             : 
    6267             : 
    6268           7 : static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
    6269             :                                         char *dst)
    6270             : {
    6271           7 :         struct wpa_cred *cred = wpa_s->conf->cred;
    6272             :         u8 dst_addr[ETH_ALEN];
    6273             :         int used;
    6274             :         u8 *buf;
    6275             :         size_t len;
    6276             :         int ret;
    6277             : 
    6278           7 :         used = hwaddr_aton2(dst, dst_addr);
    6279           7 :         if (used < 0)
    6280           1 :                 return -1;
    6281             : 
    6282          16 :         while (dst[used] == ' ')
    6283           4 :                 used++;
    6284           6 :         if (os_strncmp(dst + used, "realm=", 6) == 0)
    6285           1 :                 return hs20_nai_home_realm_list(wpa_s, dst_addr,
    6286           1 :                                                 dst + used + 6);
    6287             : 
    6288           5 :         len = os_strlen(dst + used);
    6289             : 
    6290           5 :         if (len == 0 && cred && cred->realm)
    6291           1 :                 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
    6292             : 
    6293           4 :         if (len & 1)
    6294           1 :                 return -1;
    6295           3 :         len /= 2;
    6296           3 :         buf = os_malloc(len);
    6297           3 :         if (buf == NULL)
    6298           0 :                 return -1;
    6299           3 :         if (hexstr2bin(dst + used, buf, len) < 0) {
    6300           1 :                 os_free(buf);
    6301           1 :                 return -1;
    6302             :         }
    6303             : 
    6304           2 :         ret = hs20_anqp_send_req(wpa_s, dst_addr,
    6305             :                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
    6306             :                                  buf, len);
    6307           2 :         os_free(buf);
    6308             : 
    6309           2 :         return ret;
    6310             : }
    6311             : 
    6312             : 
    6313           2 : static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd)
    6314             : {
    6315             :         u8 dst_addr[ETH_ALEN];
    6316             :         int used;
    6317             :         char *icon;
    6318             : 
    6319           2 :         used = hwaddr_aton2(cmd, dst_addr);
    6320           2 :         if (used < 0)
    6321           1 :                 return -1;
    6322             : 
    6323           3 :         while (cmd[used] == ' ')
    6324           1 :                 used++;
    6325           1 :         icon = &cmd[used];
    6326             : 
    6327           1 :         wpa_s->fetch_osu_icon_in_progress = 0;
    6328           1 :         return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
    6329             :                                   (u8 *) icon, os_strlen(icon));
    6330             : }
    6331             : 
    6332             : #endif /* CONFIG_HS20 */
    6333             : 
    6334             : 
    6335             : #ifdef CONFIG_AUTOSCAN
    6336             : 
    6337          11 : static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
    6338             :                                               char *cmd)
    6339             : {
    6340          11 :         enum wpa_states state = wpa_s->wpa_state;
    6341          11 :         char *new_params = NULL;
    6342             : 
    6343          11 :         if (os_strlen(cmd) > 0) {
    6344           5 :                 new_params = os_strdup(cmd);
    6345           5 :                 if (new_params == NULL)
    6346           0 :                         return -1;
    6347             :         }
    6348             : 
    6349          11 :         os_free(wpa_s->conf->autoscan);
    6350          11 :         wpa_s->conf->autoscan = new_params;
    6351             : 
    6352          11 :         if (wpa_s->conf->autoscan == NULL)
    6353           6 :                 autoscan_deinit(wpa_s);
    6354           5 :         else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
    6355           4 :                 autoscan_init(wpa_s, 1);
    6356           1 :         else if (state == WPA_SCANNING)
    6357           1 :                 wpa_supplicant_reinit_autoscan(wpa_s);
    6358             : 
    6359          11 :         return 0;
    6360             : }
    6361             : 
    6362             : #endif /* CONFIG_AUTOSCAN */
    6363             : 
    6364             : 
    6365             : #ifdef CONFIG_WNM
    6366             : 
    6367          13 : static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
    6368             : {
    6369             :         int enter;
    6370          13 :         int intval = 0;
    6371             :         char *pos;
    6372             :         int ret;
    6373          13 :         struct wpabuf *tfs_req = NULL;
    6374             : 
    6375          13 :         if (os_strncmp(cmd, "enter", 5) == 0)
    6376           6 :                 enter = 1;
    6377           7 :         else if (os_strncmp(cmd, "exit", 4) == 0)
    6378           6 :                 enter = 0;
    6379             :         else
    6380           1 :                 return -1;
    6381             : 
    6382          12 :         pos = os_strstr(cmd, " interval=");
    6383          12 :         if (pos)
    6384           3 :                 intval = atoi(pos + 10);
    6385             : 
    6386          12 :         pos = os_strstr(cmd, " tfs_req=");
    6387          12 :         if (pos) {
    6388             :                 char *end;
    6389             :                 size_t len;
    6390           3 :                 pos += 9;
    6391           3 :                 end = os_strchr(pos, ' ');
    6392           3 :                 if (end)
    6393           2 :                         len = end - pos;
    6394             :                 else
    6395           1 :                         len = os_strlen(pos);
    6396           3 :                 if (len & 1)
    6397           1 :                         return -1;
    6398           2 :                 len /= 2;
    6399           2 :                 tfs_req = wpabuf_alloc(len);
    6400           2 :                 if (tfs_req == NULL)
    6401           0 :                         return -1;
    6402           2 :                 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
    6403           1 :                         wpabuf_free(tfs_req);
    6404           1 :                         return -1;
    6405             :                 }
    6406             :         }
    6407             : 
    6408          10 :         ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
    6409             :                                            WNM_SLEEP_MODE_EXIT, intval,
    6410             :                                            tfs_req);
    6411          10 :         wpabuf_free(tfs_req);
    6412             : 
    6413          10 :         return ret;
    6414             : }
    6415             : 
    6416             : 
    6417           1 : static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
    6418             : {
    6419             :         int query_reason;
    6420             : 
    6421           1 :         query_reason = atoi(cmd);
    6422             : 
    6423           1 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d",
    6424             :                    query_reason);
    6425             : 
    6426           1 :         return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason);
    6427             : }
    6428             : 
    6429             : #endif /* CONFIG_WNM */
    6430             : 
    6431             : 
    6432           5 : static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
    6433             :                                       size_t buflen)
    6434             : {
    6435             :         struct wpa_signal_info si;
    6436             :         int ret;
    6437             :         char *pos, *end;
    6438             : 
    6439           5 :         ret = wpa_drv_signal_poll(wpa_s, &si);
    6440           5 :         if (ret)
    6441           0 :                 return -1;
    6442             : 
    6443           5 :         pos = buf;
    6444           5 :         end = buf + buflen;
    6445             : 
    6446          10 :         ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
    6447             :                           "NOISE=%d\nFREQUENCY=%u\n",
    6448           5 :                           si.current_signal, si.current_txrate / 1000,
    6449             :                           si.current_noise, si.frequency);
    6450           5 :         if (os_snprintf_error(end - pos, ret))
    6451           0 :                 return -1;
    6452           5 :         pos += ret;
    6453             : 
    6454           5 :         if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
    6455           4 :                 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
    6456             :                                   channel_width_to_string(si.chanwidth));
    6457           4 :                 if (os_snprintf_error(end - pos, ret))
    6458           0 :                         return -1;
    6459           4 :                 pos += ret;
    6460             :         }
    6461             : 
    6462           5 :         if (si.center_frq1 > 0 && si.center_frq2 > 0) {
    6463           1 :                 ret = os_snprintf(pos, end - pos,
    6464             :                                   "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
    6465             :                                   si.center_frq1, si.center_frq2);
    6466           1 :                 if (os_snprintf_error(end - pos, ret))
    6467           0 :                         return -1;
    6468           1 :                 pos += ret;
    6469             :         }
    6470             : 
    6471           5 :         if (si.avg_signal) {
    6472           4 :                 ret = os_snprintf(pos, end - pos,
    6473             :                                   "AVG_RSSI=%d\n", si.avg_signal);
    6474           4 :                 if (os_snprintf_error(end - pos, ret))
    6475           0 :                         return -1;
    6476           4 :                 pos += ret;
    6477             :         }
    6478             : 
    6479           5 :         return pos - buf;
    6480             : }
    6481             : 
    6482             : 
    6483           1 : static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
    6484             :                                       size_t buflen)
    6485             : {
    6486             :         struct hostap_sta_driver_data sta;
    6487             :         int ret;
    6488             : 
    6489           1 :         ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
    6490           1 :         if (ret)
    6491           0 :                 return -1;
    6492             : 
    6493           1 :         ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
    6494             :                           sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
    6495           1 :         if (os_snprintf_error(buflen, ret))
    6496           0 :                 return -1;
    6497           1 :         return ret;
    6498             : }
    6499             : 
    6500             : 
    6501             : #ifdef ANDROID
    6502             : static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
    6503             :                                      char *buf, size_t buflen)
    6504             : {
    6505             :         int ret;
    6506             : 
    6507             :         ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
    6508             :         if (ret == 0) {
    6509             :                 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
    6510             :                         struct p2p_data *p2p = wpa_s->global->p2p;
    6511             :                         if (p2p) {
    6512             :                                 char country[3];
    6513             :                                 country[0] = cmd[8];
    6514             :                                 country[1] = cmd[9];
    6515             :                                 country[2] = 0x04;
    6516             :                                 p2p_set_country(p2p, country);
    6517             :                         }
    6518             :                 }
    6519             :                 ret = os_snprintf(buf, buflen, "%s\n", "OK");
    6520             :                 if (os_snprintf_error(buflen, ret))
    6521             :                         ret = -1;
    6522             :         }
    6523             :         return ret;
    6524             : }
    6525             : #endif /* ANDROID */
    6526             : 
    6527             : 
    6528           9 : static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
    6529             :                                      char *buf, size_t buflen)
    6530             : {
    6531             :         int ret;
    6532             :         char *pos;
    6533           9 :         u8 *data = NULL;
    6534             :         unsigned int vendor_id, subcmd;
    6535             :         struct wpabuf *reply;
    6536           9 :         size_t data_len = 0;
    6537             : 
    6538             :         /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
    6539           9 :         vendor_id = strtoul(cmd, &pos, 16);
    6540           9 :         if (!isblank(*pos))
    6541           2 :                 return -EINVAL;
    6542             : 
    6543           7 :         subcmd = strtoul(pos, &pos, 10);
    6544             : 
    6545           7 :         if (*pos != '\0') {
    6546           7 :                 if (!isblank(*pos++))
    6547           1 :                         return -EINVAL;
    6548           6 :                 data_len = os_strlen(pos);
    6549             :         }
    6550             : 
    6551           6 :         if (data_len) {
    6552           6 :                 data_len /= 2;
    6553           6 :                 data = os_malloc(data_len);
    6554           6 :                 if (!data)
    6555           0 :                         return -1;
    6556             : 
    6557           6 :                 if (hexstr2bin(pos, data, data_len)) {
    6558           2 :                         wpa_printf(MSG_DEBUG,
    6559             :                                    "Vendor command: wrong parameter format");
    6560           2 :                         os_free(data);
    6561           2 :                         return -EINVAL;
    6562             :                 }
    6563             :         }
    6564             : 
    6565           4 :         reply = wpabuf_alloc((buflen - 1) / 2);
    6566           4 :         if (!reply) {
    6567           0 :                 os_free(data);
    6568           0 :                 return -1;
    6569             :         }
    6570             : 
    6571           4 :         ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
    6572             :                                  reply);
    6573             : 
    6574           4 :         if (ret == 0)
    6575           4 :                 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
    6576             :                                        wpabuf_len(reply));
    6577             : 
    6578           4 :         wpabuf_free(reply);
    6579           4 :         os_free(data);
    6580             : 
    6581           4 :         return ret;
    6582             : }
    6583             : 
    6584             : 
    6585        3341 : static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
    6586             : {
    6587             : #ifdef CONFIG_P2P
    6588        6682 :         struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ?
    6589        3341 :                 wpa_s->global->p2p_init_wpa_s : wpa_s;
    6590             : #endif /* CONFIG_P2P */
    6591             : 
    6592        3341 :         wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
    6593             : 
    6594             : #ifdef CONFIG_P2P
    6595        3341 :         wpas_p2p_cancel(p2p_wpa_s);
    6596        3341 :         p2p_ctrl_flush(p2p_wpa_s);
    6597        3341 :         wpas_p2p_group_remove(p2p_wpa_s, "*");
    6598        3341 :         wpas_p2p_service_flush(p2p_wpa_s);
    6599        3341 :         p2p_wpa_s->global->p2p_disabled = 0;
    6600        3341 :         p2p_wpa_s->global->p2p_per_sta_psk = 0;
    6601        3341 :         p2p_wpa_s->conf->num_sec_device_types = 0;
    6602        3341 :         p2p_wpa_s->p2p_disable_ip_addr_req = 0;
    6603        3341 :         os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
    6604        3341 :         p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
    6605        3341 :         p2p_wpa_s->global->pending_p2ps_group = 0;
    6606             : #endif /* CONFIG_P2P */
    6607             : 
    6608             : #ifdef CONFIG_WPS_TESTING
    6609        3341 :         wps_version_number = 0x20;
    6610        3341 :         wps_testing_dummy_cred = 0;
    6611        3341 :         wps_corrupt_pkhash = 0;
    6612             : #endif /* CONFIG_WPS_TESTING */
    6613             : #ifdef CONFIG_WPS
    6614        3341 :         wpa_s->wps_fragment_size = 0;
    6615        3341 :         wpas_wps_cancel(wpa_s);
    6616        3341 :         wps_registrar_flush(wpa_s->wps->registrar);
    6617             : #endif /* CONFIG_WPS */
    6618        3341 :         wpa_s->after_wps = 0;
    6619        3341 :         wpa_s->known_wps_freq = 0;
    6620             : 
    6621             : #ifdef CONFIG_TDLS
    6622             : #ifdef CONFIG_TDLS_TESTING
    6623             :         extern unsigned int tdls_testing;
    6624        3341 :         tdls_testing = 0;
    6625             : #endif /* CONFIG_TDLS_TESTING */
    6626        3341 :         wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
    6627        3341 :         wpa_tdls_enable(wpa_s->wpa, 1);
    6628             : #endif /* CONFIG_TDLS */
    6629             : 
    6630        3341 :         eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
    6631        3341 :         wpa_supplicant_stop_countermeasures(wpa_s, NULL);
    6632             : 
    6633        3341 :         wpa_s->no_keep_alive = 0;
    6634        3341 :         wpa_s->own_disconnect_req = 0;
    6635             : 
    6636        3341 :         os_free(wpa_s->disallow_aps_bssid);
    6637        3341 :         wpa_s->disallow_aps_bssid = NULL;
    6638        3341 :         wpa_s->disallow_aps_bssid_count = 0;
    6639        3341 :         os_free(wpa_s->disallow_aps_ssid);
    6640        3341 :         wpa_s->disallow_aps_ssid = NULL;
    6641        3341 :         wpa_s->disallow_aps_ssid_count = 0;
    6642             : 
    6643        3341 :         wpa_s->set_sta_uapsd = 0;
    6644        3341 :         wpa_s->sta_uapsd = 0;
    6645             : 
    6646        3341 :         wpa_drv_radio_disable(wpa_s, 0);
    6647        3341 :         wpa_blacklist_clear(wpa_s);
    6648        3341 :         wpa_s->extra_blacklist_count = 0;
    6649        3341 :         wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
    6650        3341 :         wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
    6651        3341 :         wpa_config_flush_blobs(wpa_s->conf);
    6652        3341 :         wpa_s->conf->auto_interworking = 0;
    6653        3341 :         wpa_s->conf->okc = 0;
    6654             : 
    6655        3341 :         wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
    6656        3341 :         rsn_preauth_deinit(wpa_s->wpa);
    6657             : 
    6658        3341 :         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
    6659        3341 :         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
    6660        3341 :         wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
    6661        3341 :         eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
    6662             : 
    6663        3341 :         radio_remove_works(wpa_s, NULL, 1);
    6664        3341 :         wpa_s->ext_work_in_progress = 0;
    6665             : 
    6666        3341 :         wpa_s->next_ssid = NULL;
    6667             : 
    6668             : #ifdef CONFIG_INTERWORKING
    6669        3341 :         hs20_cancel_fetch_osu(wpa_s);
    6670             : #endif /* CONFIG_INTERWORKING */
    6671             : 
    6672        3341 :         wpa_s->ext_mgmt_frame_handling = 0;
    6673        3341 :         wpa_s->ext_eapol_frame_io = 0;
    6674             : #ifdef CONFIG_TESTING_OPTIONS
    6675        3341 :         wpa_s->extra_roc_dur = 0;
    6676        3341 :         wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
    6677             : #endif /* CONFIG_TESTING_OPTIONS */
    6678             : 
    6679        3341 :         wpa_s->disconnected = 0;
    6680        3341 :         os_free(wpa_s->next_scan_freqs);
    6681        3341 :         wpa_s->next_scan_freqs = NULL;
    6682             : 
    6683        3341 :         wpa_bss_flush(wpa_s);
    6684        3341 :         if (!dl_list_empty(&wpa_s->bss)) {
    6685           0 :                 wpa_printf(MSG_DEBUG,
    6686             :                            "BSS table not empty after flush: %u entries, current_bss=%p bssid="
    6687             :                            MACSTR " pending_bssid=" MACSTR,
    6688             :                            dl_list_len(&wpa_s->bss), wpa_s->current_bss,
    6689           0 :                            MAC2STR(wpa_s->bssid),
    6690           0 :                            MAC2STR(wpa_s->pending_bssid));
    6691             :         }
    6692        3341 : }
    6693             : 
    6694             : 
    6695           4 : static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
    6696             :                                      char *buf, size_t buflen)
    6697             : {
    6698             :         struct wpa_radio_work *work;
    6699             :         char *pos, *end;
    6700             :         struct os_reltime now, diff;
    6701             : 
    6702           4 :         pos = buf;
    6703           4 :         end = buf + buflen;
    6704             : 
    6705           4 :         os_get_reltime(&now);
    6706             : 
    6707           9 :         dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
    6708             :         {
    6709             :                 int ret;
    6710             : 
    6711           5 :                 os_reltime_sub(&now, &work->time, &diff);
    6712          15 :                 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
    6713           5 :                                   work->type, work->wpa_s->ifname, work->freq,
    6714           5 :                                   work->started, diff.sec, diff.usec);
    6715           5 :                 if (os_snprintf_error(end - pos, ret))
    6716           0 :                         break;
    6717           5 :                 pos += ret;
    6718             :         }
    6719             : 
    6720           4 :         return pos - buf;
    6721             : }
    6722             : 
    6723             : 
    6724           1 : static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
    6725             : {
    6726           1 :         struct wpa_radio_work *work = eloop_ctx;
    6727           1 :         struct wpa_external_work *ework = work->ctx;
    6728             : 
    6729           1 :         wpa_dbg(work->wpa_s, MSG_DEBUG,
    6730             :                 "Timing out external radio work %u (%s)",
    6731             :                 ework->id, work->type);
    6732           1 :         wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
    6733           1 :         work->wpa_s->ext_work_in_progress = 0;
    6734           1 :         radio_work_done(work);
    6735           1 :         os_free(ework);
    6736           1 : }
    6737             : 
    6738             : 
    6739          18 : static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
    6740             : {
    6741          18 :         struct wpa_external_work *ework = work->ctx;
    6742             : 
    6743          18 :         if (deinit) {
    6744           5 :                 if (work->started)
    6745           1 :                         eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
    6746             :                                              work, NULL);
    6747             : 
    6748           5 :                 os_free(ework);
    6749          23 :                 return;
    6750             :         }
    6751             : 
    6752          13 :         wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
    6753             :                 ework->id, ework->type);
    6754          13 :         wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
    6755          13 :         work->wpa_s->ext_work_in_progress = 1;
    6756          13 :         if (!ework->timeout)
    6757          12 :                 ework->timeout = 10;
    6758          13 :         eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
    6759             :                                work, NULL);
    6760             : }
    6761             : 
    6762             : 
    6763          18 : static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
    6764             :                                     char *buf, size_t buflen)
    6765             : {
    6766             :         struct wpa_external_work *ework;
    6767             :         char *pos, *pos2;
    6768             :         size_t type_len;
    6769             :         int ret;
    6770          18 :         unsigned int freq = 0;
    6771             : 
    6772             :         /* format: <name> [freq=<MHz>] [timeout=<seconds>] */
    6773             : 
    6774          18 :         ework = os_zalloc(sizeof(*ework));
    6775          18 :         if (ework == NULL)
    6776           0 :                 return -1;
    6777             : 
    6778          18 :         pos = os_strchr(cmd, ' ');
    6779          18 :         if (pos) {
    6780           2 :                 type_len = pos - cmd;
    6781           2 :                 pos++;
    6782             : 
    6783           2 :                 pos2 = os_strstr(pos, "freq=");
    6784           2 :                 if (pos2)
    6785           1 :                         freq = atoi(pos2 + 5);
    6786             : 
    6787           2 :                 pos2 = os_strstr(pos, "timeout=");
    6788           2 :                 if (pos2)
    6789           1 :                         ework->timeout = atoi(pos2 + 8);
    6790             :         } else {
    6791          16 :                 type_len = os_strlen(cmd);
    6792             :         }
    6793          18 :         if (4 + type_len >= sizeof(ework->type))
    6794           5 :                 type_len = sizeof(ework->type) - 4 - 1;
    6795          18 :         os_strlcpy(ework->type, "ext:", sizeof(ework->type));
    6796          18 :         os_memcpy(ework->type + 4, cmd, type_len);
    6797          18 :         ework->type[4 + type_len] = '\0';
    6798             : 
    6799          18 :         wpa_s->ext_work_id++;
    6800          18 :         if (wpa_s->ext_work_id == 0)
    6801           0 :                 wpa_s->ext_work_id++;
    6802          18 :         ework->id = wpa_s->ext_work_id;
    6803             : 
    6804          18 :         if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
    6805             :                            ework) < 0) {
    6806           0 :                 os_free(ework);
    6807           0 :                 return -1;
    6808             :         }
    6809             : 
    6810          18 :         ret = os_snprintf(buf, buflen, "%u", ework->id);
    6811          18 :         if (os_snprintf_error(buflen, ret))
    6812           0 :                 return -1;
    6813          18 :         return ret;
    6814             : }
    6815             : 
    6816             : 
    6817          12 : static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
    6818             : {
    6819             :         struct wpa_radio_work *work;
    6820          12 :         unsigned int id = atoi(cmd);
    6821             : 
    6822          25 :         dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
    6823             :         {
    6824             :                 struct wpa_external_work *ework;
    6825             : 
    6826          24 :                 if (os_strncmp(work->type, "ext:", 4) != 0)
    6827           7 :                         continue;
    6828          17 :                 ework = work->ctx;
    6829          17 :                 if (id && ework->id != id)
    6830           6 :                         continue;
    6831          11 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    6832             :                         "Completed external radio work %u (%s)",
    6833             :                         ework->id, ework->type);
    6834          11 :                 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
    6835          11 :                 wpa_s->ext_work_in_progress = 0;
    6836          11 :                 radio_work_done(work);
    6837          11 :                 os_free(ework);
    6838          11 :                 return 3; /* "OK\n" */
    6839             :         }
    6840             : 
    6841           1 :         return -1;
    6842             : }
    6843             : 
    6844             : 
    6845          35 : static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
    6846             :                                 char *buf, size_t buflen)
    6847             : {
    6848          35 :         if (os_strcmp(cmd, "show") == 0)
    6849           4 :                 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
    6850          31 :         if (os_strncmp(cmd, "add ", 4) == 0)
    6851          18 :                 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
    6852          13 :         if (os_strncmp(cmd, "done ", 5) == 0)
    6853          12 :                 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
    6854           1 :         return -1;
    6855             : }
    6856             : 
    6857             : 
    6858         288 : void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
    6859             : {
    6860             :         struct wpa_radio_work *work, *tmp;
    6861             : 
    6862         288 :         if (!wpa_s || !wpa_s->radio)
    6863         302 :                 return;
    6864             : 
    6865         280 :         dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
    6866             :                               struct wpa_radio_work, list) {
    6867             :                 struct wpa_external_work *ework;
    6868             : 
    6869           6 :                 if (os_strncmp(work->type, "ext:", 4) != 0)
    6870           5 :                         continue;
    6871           1 :                 ework = work->ctx;
    6872           1 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    6873             :                         "Flushing%s external radio work %u (%s)",
    6874             :                         work->started ? " started" : "", ework->id,
    6875             :                         ework->type);
    6876           1 :                 if (work->started)
    6877           1 :                         eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
    6878             :                                              work, NULL);
    6879           1 :                 radio_work_done(work);
    6880           1 :                 os_free(ework);
    6881             :         }
    6882             : }
    6883             : 
    6884             : 
    6885          44 : static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
    6886             : {
    6887          44 :         struct wpa_supplicant *wpa_s = eloop_ctx;
    6888          44 :         eapol_sm_notify_ctrl_response(wpa_s->eapol);
    6889          44 : }
    6890             : 
    6891             : 
    6892           3 : static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
    6893             :                               unsigned int *scan_id_count, int scan_id[])
    6894             : {
    6895           3 :         const char *pos = value;
    6896             : 
    6897          26 :         while (pos) {
    6898          21 :                 if (*pos == ' ' || *pos == '\0')
    6899             :                         break;
    6900          21 :                 if (*scan_id_count == MAX_SCAN_ID)
    6901           1 :                         return -1;
    6902          20 :                 scan_id[(*scan_id_count)++] = atoi(pos);
    6903          20 :                 pos = os_strchr(pos, ',');
    6904          20 :                 if (pos)
    6905          18 :                         pos++;
    6906             :         }
    6907             : 
    6908           2 :         return 0;
    6909             : }
    6910             : 
    6911             : 
    6912         497 : static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
    6913             :                            char *reply, int reply_size, int *reply_len)
    6914             : {
    6915             :         char *pos;
    6916         497 :         unsigned int manual_scan_passive = 0;
    6917         497 :         unsigned int manual_scan_use_id = 0;
    6918         497 :         unsigned int manual_scan_only_new = 0;
    6919         497 :         unsigned int scan_only = 0;
    6920         497 :         unsigned int scan_id_count = 0;
    6921             :         int scan_id[MAX_SCAN_ID];
    6922             :         void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
    6923             :                                  struct wpa_scan_results *scan_res);
    6924         497 :         int *manual_scan_freqs = NULL;
    6925             : 
    6926         497 :         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
    6927           1 :                 *reply_len = -1;
    6928           7 :                 return;
    6929             :         }
    6930             : 
    6931         496 :         if (radio_work_pending(wpa_s, "scan")) {
    6932           5 :                 wpa_printf(MSG_DEBUG,
    6933             :                            "Pending scan scheduled - reject new request");
    6934           5 :                 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
    6935           5 :                 return;
    6936             :         }
    6937             : 
    6938         491 :         if (params) {
    6939         478 :                 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
    6940         287 :                         scan_only = 1;
    6941             : 
    6942         478 :                 pos = os_strstr(params, "freq=");
    6943         478 :                 if (pos) {
    6944         467 :                         manual_scan_freqs = freq_range_to_channel_list(wpa_s,
    6945             :                                                                        pos + 5);
    6946         467 :                         if (manual_scan_freqs == NULL) {
    6947           0 :                                 *reply_len = -1;
    6948           0 :                                 goto done;
    6949             :                         }
    6950             :                 }
    6951             : 
    6952         478 :                 pos = os_strstr(params, "passive=");
    6953         478 :                 if (pos)
    6954           4 :                         manual_scan_passive = !!atoi(pos + 8);
    6955             : 
    6956         478 :                 pos = os_strstr(params, "use_id=");
    6957         478 :                 if (pos)
    6958          15 :                         manual_scan_use_id = atoi(pos + 7);
    6959             : 
    6960         478 :                 pos = os_strstr(params, "only_new=1");
    6961         478 :                 if (pos)
    6962         156 :                         manual_scan_only_new = 1;
    6963             : 
    6964         478 :                 pos = os_strstr(params, "scan_id=");
    6965         478 :                 if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
    6966             :                                               scan_id) < 0) {
    6967           1 :                         *reply_len = -1;
    6968           1 :                         goto done;
    6969             :                 }
    6970             :         }
    6971             : 
    6972         490 :         if (scan_only)
    6973         287 :                 scan_res_handler = scan_only_handler;
    6974         203 :         else if (wpa_s->scan_res_handler == scan_only_handler)
    6975           0 :                 scan_res_handler = NULL;
    6976             :         else
    6977         203 :                 scan_res_handler = wpa_s->scan_res_handler;
    6978             : 
    6979         980 :         if (!wpa_s->sched_scanning && !wpa_s->scanning &&
    6980         538 :             ((wpa_s->wpa_state <= WPA_SCANNING) ||
    6981          48 :              (wpa_s->wpa_state == WPA_COMPLETED))) {
    6982         490 :                 wpa_s->manual_scan_passive = manual_scan_passive;
    6983         490 :                 wpa_s->manual_scan_use_id = manual_scan_use_id;
    6984         490 :                 wpa_s->manual_scan_only_new = manual_scan_only_new;
    6985         490 :                 wpa_s->scan_id_count = scan_id_count;
    6986         490 :                 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
    6987         490 :                 wpa_s->scan_res_handler = scan_res_handler;
    6988         490 :                 os_free(wpa_s->manual_scan_freqs);
    6989         490 :                 wpa_s->manual_scan_freqs = manual_scan_freqs;
    6990         490 :                 manual_scan_freqs = NULL;
    6991             : 
    6992         490 :                 wpa_s->normal_scans = 0;
    6993         490 :                 wpa_s->scan_req = MANUAL_SCAN_REQ;
    6994         490 :                 wpa_s->after_wps = 0;
    6995         490 :                 wpa_s->known_wps_freq = 0;
    6996         490 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
    6997         980 :                 if (wpa_s->manual_scan_use_id) {
    6998          15 :                         wpa_s->manual_scan_id++;
    6999          15 :                         wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
    7000             :                                 wpa_s->manual_scan_id);
    7001          15 :                         *reply_len = os_snprintf(reply, reply_size, "%u\n",
    7002             :                                                  wpa_s->manual_scan_id);
    7003             :                 }
    7004           0 :         } else if (wpa_s->sched_scanning) {
    7005           0 :                 wpa_s->manual_scan_passive = manual_scan_passive;
    7006           0 :                 wpa_s->manual_scan_use_id = manual_scan_use_id;
    7007           0 :                 wpa_s->manual_scan_only_new = manual_scan_only_new;
    7008           0 :                 wpa_s->scan_id_count = scan_id_count;
    7009           0 :                 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
    7010           0 :                 wpa_s->scan_res_handler = scan_res_handler;
    7011           0 :                 os_free(wpa_s->manual_scan_freqs);
    7012           0 :                 wpa_s->manual_scan_freqs = manual_scan_freqs;
    7013           0 :                 manual_scan_freqs = NULL;
    7014             : 
    7015           0 :                 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
    7016           0 :                 wpa_supplicant_cancel_sched_scan(wpa_s);
    7017           0 :                 wpa_s->scan_req = MANUAL_SCAN_REQ;
    7018           0 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
    7019           0 :                 if (wpa_s->manual_scan_use_id) {
    7020           0 :                         wpa_s->manual_scan_id++;
    7021           0 :                         *reply_len = os_snprintf(reply, reply_size, "%u\n",
    7022             :                                                  wpa_s->manual_scan_id);
    7023           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
    7024             :                                 wpa_s->manual_scan_id);
    7025             :                 }
    7026             :         } else {
    7027           0 :                 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
    7028           0 :                 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
    7029             :         }
    7030             : 
    7031             : done:
    7032         491 :         os_free(manual_scan_freqs);
    7033             : }
    7034             : 
    7035             : 
    7036             : #ifdef CONFIG_TESTING_OPTIONS
    7037             : 
    7038          54 : static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
    7039             :                                        unsigned int freq, const u8 *dst,
    7040             :                                        const u8 *src, const u8 *bssid,
    7041             :                                        const u8 *data, size_t data_len,
    7042             :                                        enum offchannel_send_action_result
    7043             :                                        result)
    7044             : {
    7045        1028 :         wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
    7046             :                 " src=" MACSTR " bssid=" MACSTR " result=%s",
    7047         972 :                 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
    7048             :                 result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
    7049             :                 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
    7050           2 :                              "NO_ACK" : "FAILED"));
    7051          54 : }
    7052             : 
    7053             : 
    7054          59 : static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
    7055             : {
    7056             :         char *pos, *param;
    7057             :         size_t len;
    7058             :         u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
    7059             :         int res, used;
    7060          59 :         int freq = 0, no_cck = 0, wait_time = 0;
    7061             : 
    7062             :         /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
    7063             :          *    <action=Action frame payload> */
    7064             : 
    7065          59 :         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
    7066             : 
    7067          59 :         pos = cmd;
    7068          59 :         used = hwaddr_aton2(pos, da);
    7069          59 :         if (used < 0)
    7070           1 :                 return -1;
    7071          58 :         pos += used;
    7072         174 :         while (*pos == ' ')
    7073          58 :                 pos++;
    7074          58 :         used = hwaddr_aton2(pos, bssid);
    7075          58 :         if (used < 0)
    7076           1 :                 return -1;
    7077          57 :         pos += used;
    7078             : 
    7079          57 :         param = os_strstr(pos, " freq=");
    7080          57 :         if (param) {
    7081          55 :                 param += 6;
    7082          55 :                 freq = atoi(param);
    7083             :         }
    7084             : 
    7085          57 :         param = os_strstr(pos, " no_cck=");
    7086          57 :         if (param) {
    7087          30 :                 param += 8;
    7088          30 :                 no_cck = atoi(param);
    7089             :         }
    7090             : 
    7091          57 :         param = os_strstr(pos, " wait_time=");
    7092          57 :         if (param) {
    7093          40 :                 param += 11;
    7094          40 :                 wait_time = atoi(param);
    7095             :         }
    7096             : 
    7097          57 :         param = os_strstr(pos, " action=");
    7098          57 :         if (param == NULL)
    7099           1 :                 return -1;
    7100          56 :         param += 8;
    7101             : 
    7102          56 :         len = os_strlen(param);
    7103          56 :         if (len & 1)
    7104           1 :                 return -1;
    7105          55 :         len /= 2;
    7106             : 
    7107          55 :         buf = os_malloc(len);
    7108          55 :         if (buf == NULL)
    7109           0 :                 return -1;
    7110             : 
    7111          55 :         if (hexstr2bin(param, buf, len) < 0) {
    7112           1 :                 os_free(buf);
    7113           1 :                 return -1;
    7114             :         }
    7115             : 
    7116          54 :         res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
    7117             :                                      buf, len, wait_time,
    7118             :                                      wpas_ctrl_iface_mgmt_tx_cb, no_cck);
    7119          54 :         os_free(buf);
    7120          54 :         return res;
    7121             : }
    7122             : 
    7123             : 
    7124           1 : static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
    7125             : {
    7126           1 :         wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
    7127           1 :         offchannel_send_action_done(wpa_s);
    7128           1 : }
    7129             : 
    7130             : 
    7131          11 : static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
    7132             : {
    7133             :         char *pos, *param;
    7134             :         union wpa_event_data event;
    7135             :         enum wpa_event_type ev;
    7136             : 
    7137             :         /* <event name> [parameters..] */
    7138             : 
    7139          11 :         wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
    7140             : 
    7141          11 :         pos = cmd;
    7142          11 :         param = os_strchr(pos, ' ');
    7143          11 :         if (param)
    7144           2 :                 *param++ = '\0';
    7145             : 
    7146          11 :         os_memset(&event, 0, sizeof(event));
    7147             : 
    7148          11 :         if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
    7149           4 :                 ev = EVENT_INTERFACE_ENABLED;
    7150           7 :         } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
    7151           2 :                 ev = EVENT_INTERFACE_DISABLED;
    7152           5 :         } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
    7153           4 :                 ev = EVENT_AVOID_FREQUENCIES;
    7154           4 :                 if (param == NULL)
    7155           2 :                         param = "";
    7156           4 :                 if (freq_range_list_parse(&event.freq_range, param) < 0)
    7157           0 :                         return -1;
    7158           4 :                 wpa_supplicant_event(wpa_s, ev, &event);
    7159           4 :                 os_free(event.freq_range.range);
    7160           4 :                 return 0;
    7161             :         } else {
    7162           1 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
    7163             :                         cmd);
    7164           1 :                 return -1;
    7165             :         }
    7166             : 
    7167           6 :         wpa_supplicant_event(wpa_s, ev, &event);
    7168             : 
    7169           6 :         return 0;
    7170             : }
    7171             : 
    7172             : 
    7173         102 : static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
    7174             : {
    7175             :         char *pos;
    7176             :         u8 src[ETH_ALEN], *buf;
    7177             :         int used;
    7178             :         size_t len;
    7179             : 
    7180         102 :         wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
    7181             : 
    7182         102 :         pos = cmd;
    7183         102 :         used = hwaddr_aton2(pos, src);
    7184         102 :         if (used < 0)
    7185           1 :                 return -1;
    7186         101 :         pos += used;
    7187         303 :         while (*pos == ' ')
    7188         101 :                 pos++;
    7189             : 
    7190         101 :         len = os_strlen(pos);
    7191         101 :         if (len & 1)
    7192           1 :                 return -1;
    7193         100 :         len /= 2;
    7194             : 
    7195         100 :         buf = os_malloc(len);
    7196         100 :         if (buf == NULL)
    7197           0 :                 return -1;
    7198             : 
    7199         100 :         if (hexstr2bin(pos, buf, len) < 0) {
    7200           1 :                 os_free(buf);
    7201           1 :                 return -1;
    7202             :         }
    7203             : 
    7204          99 :         wpa_supplicant_rx_eapol(wpa_s, src, buf, len);
    7205          99 :         os_free(buf);
    7206             : 
    7207          99 :         return 0;
    7208             : }
    7209             : 
    7210             : 
    7211        2163 : static u16 ipv4_hdr_checksum(const void *buf, size_t len)
    7212             : {
    7213             :         size_t i;
    7214        2163 :         u32 sum = 0;
    7215        2163 :         const u16 *pos = buf;
    7216             : 
    7217       23793 :         for (i = 0; i < len / 2; i++)
    7218       21630 :                 sum += *pos++;
    7219             : 
    7220        6489 :         while (sum >> 16)
    7221        2163 :                 sum = (sum & 0xffff) + (sum >> 16);
    7222             : 
    7223        2163 :         return sum ^ 0xffff;
    7224             : }
    7225             : 
    7226             : 
    7227             : #define HWSIM_PACKETLEN 1500
    7228             : #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
    7229             : 
    7230        2154 : void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
    7231             : {
    7232        2154 :         struct wpa_supplicant *wpa_s = ctx;
    7233             :         const struct ether_header *eth;
    7234             :         const struct iphdr *ip;
    7235             :         const u8 *pos;
    7236             :         unsigned int i;
    7237             : 
    7238        2154 :         if (len != HWSIM_PACKETLEN)
    7239           0 :                 return;
    7240             : 
    7241        2154 :         eth = (const struct ether_header *) buf;
    7242        2154 :         ip = (const struct iphdr *) (eth + 1);
    7243        2154 :         pos = (const u8 *) (ip + 1);
    7244             : 
    7245        4308 :         if (ip->ihl != 5 || ip->version != 4 ||
    7246        2154 :             ntohs(ip->tot_len) != HWSIM_IP_LEN)
    7247           0 :                 return;
    7248             : 
    7249     3159918 :         for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) {
    7250     3157764 :                 if (*pos != (u8) i)
    7251           0 :                         return;
    7252     3157764 :                 pos++;
    7253             :         }
    7254             : 
    7255       25848 :         wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
    7256       25848 :                 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
    7257             : }
    7258             : 
    7259             : 
    7260        2088 : static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
    7261             :                                             char *cmd)
    7262             : {
    7263        2088 :         int enabled = atoi(cmd);
    7264             : 
    7265        2088 :         if (!enabled) {
    7266        1044 :                 if (wpa_s->l2_test) {
    7267        1043 :                         l2_packet_deinit(wpa_s->l2_test);
    7268        1043 :                         wpa_s->l2_test = NULL;
    7269        1043 :                         wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
    7270             :                 }
    7271        1044 :                 return 0;
    7272             :         }
    7273             : 
    7274        1044 :         if (wpa_s->l2_test)
    7275           1 :                 return 0;
    7276             : 
    7277        1043 :         wpa_s->l2_test = l2_packet_init(wpa_s->ifname, wpa_s->own_addr,
    7278             :                                         ETHERTYPE_IP, wpas_data_test_rx,
    7279             :                                         wpa_s, 1);
    7280        1043 :         if (wpa_s->l2_test == NULL)
    7281           0 :                 return -1;
    7282             : 
    7283        1043 :         wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
    7284             : 
    7285        1043 :         return 0;
    7286             : }
    7287             : 
    7288             : 
    7289        2168 : static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
    7290             : {
    7291             :         u8 dst[ETH_ALEN], src[ETH_ALEN];
    7292             :         char *pos;
    7293             :         int used;
    7294             :         long int val;
    7295             :         u8 tos;
    7296             :         u8 buf[HWSIM_PACKETLEN];
    7297             :         struct ether_header *eth;
    7298             :         struct iphdr *ip;
    7299             :         u8 *dpos;
    7300             :         unsigned int i;
    7301             : 
    7302        2168 :         if (wpa_s->l2_test == NULL)
    7303           1 :                 return -1;
    7304             : 
    7305             :         /* format: <dst> <src> <tos> */
    7306             : 
    7307        2167 :         pos = cmd;
    7308        2167 :         used = hwaddr_aton2(pos, dst);
    7309        2167 :         if (used < 0)
    7310           1 :                 return -1;
    7311        2166 :         pos += used;
    7312        6498 :         while (*pos == ' ')
    7313        2166 :                 pos++;
    7314        2166 :         used = hwaddr_aton2(pos, src);
    7315        2166 :         if (used < 0)
    7316           1 :                 return -1;
    7317        2165 :         pos += used;
    7318             : 
    7319        2165 :         val = strtol(pos, NULL, 0);
    7320        2165 :         if (val < 0 || val > 0xff)
    7321           2 :                 return -1;
    7322        2163 :         tos = val;
    7323             : 
    7324        2163 :         eth = (struct ether_header *) buf;
    7325        2163 :         os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
    7326        2163 :         os_memcpy(eth->ether_shost, src, ETH_ALEN);
    7327        2163 :         eth->ether_type = htons(ETHERTYPE_IP);
    7328        2163 :         ip = (struct iphdr *) (eth + 1);
    7329        2163 :         os_memset(ip, 0, sizeof(*ip));
    7330        2163 :         ip->ihl = 5;
    7331        2163 :         ip->version = 4;
    7332        2163 :         ip->ttl = 64;
    7333        2163 :         ip->tos = tos;
    7334        2163 :         ip->tot_len = htons(HWSIM_IP_LEN);
    7335        2163 :         ip->protocol = 1;
    7336        2163 :         ip->saddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 1);
    7337        2163 :         ip->daddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 2);
    7338        2163 :         ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
    7339        2163 :         dpos = (u8 *) (ip + 1);
    7340     3173121 :         for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
    7341     3170958 :                 *dpos++ = i;
    7342             : 
    7343        2163 :         if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, buf,
    7344             :                            HWSIM_PACKETLEN) < 0)
    7345           0 :                 return -1;
    7346             : 
    7347        2163 :         wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
    7348             :                 " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
    7349             : 
    7350        2163 :         return 0;
    7351             : }
    7352             : 
    7353             : 
    7354          98 : static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s,
    7355             :                                            char *cmd)
    7356             : {
    7357             :         u8 *buf;
    7358             :         struct ether_header *eth;
    7359          98 :         struct l2_packet_data *l2 = NULL;
    7360             :         size_t len;
    7361             :         u16 ethertype;
    7362          98 :         int res = -1;
    7363             : 
    7364          98 :         len = os_strlen(cmd);
    7365          98 :         if (len & 1 || len < ETH_HLEN * 2)
    7366           3 :                 return -1;
    7367          95 :         len /= 2;
    7368             : 
    7369          95 :         buf = os_malloc(len);
    7370          95 :         if (buf == NULL)
    7371           0 :                 return -1;
    7372             : 
    7373          95 :         if (hexstr2bin(cmd, buf, len) < 0)
    7374           1 :                 goto done;
    7375             : 
    7376          94 :         eth = (struct ether_header *) buf;
    7377          94 :         ethertype = ntohs(eth->ether_type);
    7378             : 
    7379          94 :         l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype,
    7380             :                             wpas_data_test_rx, wpa_s, 1);
    7381          94 :         if (l2 == NULL)
    7382           0 :                 goto done;
    7383             : 
    7384          94 :         res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
    7385          94 :         wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res);
    7386             : done:
    7387          95 :         if (l2)
    7388          94 :                 l2_packet_deinit(l2);
    7389          95 :         os_free(buf);
    7390             : 
    7391          95 :         return res < 0 ? -1 : 0;
    7392             : }
    7393             : 
    7394             : 
    7395         228 : static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
    7396             : {
    7397             : #ifdef WPA_TRACE_BFD
    7398             :         extern char wpa_trace_fail_func[256];
    7399             :         extern unsigned int wpa_trace_fail_after;
    7400             :         char *pos;
    7401             : 
    7402         228 :         wpa_trace_fail_after = atoi(cmd);
    7403         228 :         pos = os_strchr(cmd, ':');
    7404         228 :         if (pos) {
    7405         228 :                 pos++;
    7406         228 :                 os_strlcpy(wpa_trace_fail_func, pos,
    7407             :                            sizeof(wpa_trace_fail_func));
    7408             :         } else {
    7409           0 :                 wpa_trace_fail_after = 0;
    7410             :         }
    7411         228 :         return 0;
    7412             : #else /* WPA_TRACE_BFD */
    7413             :         return -1;
    7414             : #endif /* WPA_TRACE_BFD */
    7415             : }
    7416             : 
    7417             : 
    7418          87 : static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
    7419             :                                     char *buf, size_t buflen)
    7420             : {
    7421             : #ifdef WPA_TRACE_BFD
    7422             :         extern char wpa_trace_fail_func[256];
    7423             :         extern unsigned int wpa_trace_fail_after;
    7424             : 
    7425          87 :         return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
    7426             :                            wpa_trace_fail_func);
    7427             : #else /* WPA_TRACE_BFD */
    7428             :         return -1;
    7429             : #endif /* WPA_TRACE_BFD */
    7430             : }
    7431             : 
    7432             : #endif /* CONFIG_TESTING_OPTIONS */
    7433             : 
    7434             : 
    7435          20 : static void wpas_ctrl_vendor_elem_update(struct wpa_supplicant *wpa_s)
    7436             : {
    7437             :         unsigned int i;
    7438             :         char buf[30];
    7439             : 
    7440          20 :         wpa_printf(MSG_DEBUG, "Update vendor elements");
    7441             : 
    7442         300 :         for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
    7443         280 :                 if (wpa_s->vendor_elem[i]) {
    7444             :                         int res;
    7445             : 
    7446          17 :                         res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
    7447          17 :                         if (!os_snprintf_error(sizeof(buf), res)) {
    7448          17 :                                 wpa_hexdump_buf(MSG_DEBUG, buf,
    7449          17 :                                                 wpa_s->vendor_elem[i]);
    7450             :                         }
    7451             :                 }
    7452             :         }
    7453             : 
    7454             : #ifdef CONFIG_P2P
    7455          40 :         if (wpa_s->parent == wpa_s &&
    7456          40 :             wpa_s->global->p2p &&
    7457          20 :             !wpa_s->global->p2p_disabled)
    7458          20 :                 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
    7459             : #endif /* CONFIG_P2P */
    7460          20 : }
    7461             : 
    7462             : 
    7463             : static struct wpa_supplicant *
    7464          46 : wpas_ctrl_vendor_elem_iface(struct wpa_supplicant *wpa_s,
    7465             :                             enum wpa_vendor_elem_frame frame)
    7466             : {
    7467          46 :         switch (frame) {
    7468             : #ifdef CONFIG_P2P
    7469             :         case VENDOR_ELEM_PROBE_REQ_P2P:
    7470             :         case VENDOR_ELEM_PROBE_RESP_P2P:
    7471             :         case VENDOR_ELEM_PROBE_RESP_P2P_GO:
    7472             :         case VENDOR_ELEM_BEACON_P2P_GO:
    7473             :         case VENDOR_ELEM_P2P_PD_REQ:
    7474             :         case VENDOR_ELEM_P2P_PD_RESP:
    7475             :         case VENDOR_ELEM_P2P_GO_NEG_REQ:
    7476             :         case VENDOR_ELEM_P2P_GO_NEG_RESP:
    7477             :         case VENDOR_ELEM_P2P_GO_NEG_CONF:
    7478             :         case VENDOR_ELEM_P2P_INV_REQ:
    7479             :         case VENDOR_ELEM_P2P_INV_RESP:
    7480             :         case VENDOR_ELEM_P2P_ASSOC_REQ:
    7481          42 :                 return wpa_s->parent;
    7482             : #endif /* CONFIG_P2P */
    7483             :         default:
    7484           4 :                 return wpa_s;
    7485             :         }
    7486             : }
    7487             : 
    7488             : 
    7489          16 : static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
    7490             : {
    7491          16 :         char *pos = cmd;
    7492             :         int frame;
    7493             :         size_t len;
    7494             :         struct wpabuf *buf;
    7495             :         struct ieee802_11_elems elems;
    7496             : 
    7497          16 :         frame = atoi(pos);
    7498          16 :         if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
    7499           2 :                 return -1;
    7500          14 :         wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
    7501             : 
    7502          14 :         pos = os_strchr(pos, ' ');
    7503          14 :         if (pos == NULL)
    7504           1 :                 return -1;
    7505          13 :         pos++;
    7506             : 
    7507          13 :         len = os_strlen(pos);
    7508          13 :         if (len == 0)
    7509           1 :                 return 0;
    7510          12 :         if (len & 1)
    7511           1 :                 return -1;
    7512          11 :         len /= 2;
    7513             : 
    7514          11 :         buf = wpabuf_alloc(len);
    7515          11 :         if (buf == NULL)
    7516           0 :                 return -1;
    7517             : 
    7518          11 :         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
    7519           1 :                 wpabuf_free(buf);
    7520           1 :                 return -1;
    7521             :         }
    7522             : 
    7523          10 :         if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
    7524             :             ParseFailed) {
    7525           1 :                 wpabuf_free(buf);
    7526           1 :                 return -1;
    7527             :         }
    7528             : 
    7529           9 :         if (wpa_s->vendor_elem[frame] == NULL) {
    7530           8 :                 wpa_s->vendor_elem[frame] = buf;
    7531           8 :                 wpas_ctrl_vendor_elem_update(wpa_s);
    7532           8 :                 return 0;
    7533             :         }
    7534             : 
    7535           1 :         if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
    7536           0 :                 wpabuf_free(buf);
    7537           0 :                 return -1;
    7538             :         }
    7539             : 
    7540           1 :         wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
    7541           1 :         wpabuf_free(buf);
    7542           1 :         wpas_ctrl_vendor_elem_update(wpa_s);
    7543             : 
    7544           1 :         return 0;
    7545             : }
    7546             : 
    7547             : 
    7548           9 : static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
    7549             :                                      char *buf, size_t buflen)
    7550             : {
    7551           9 :         int frame = atoi(cmd);
    7552             : 
    7553           9 :         if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
    7554           2 :                 return -1;
    7555           7 :         wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
    7556             : 
    7557           7 :         if (wpa_s->vendor_elem[frame] == NULL)
    7558           2 :                 return 0;
    7559             : 
    7560          10 :         return wpa_snprintf_hex(buf, buflen,
    7561           5 :                                 wpabuf_head_u8(wpa_s->vendor_elem[frame]),
    7562           5 :                                 wpabuf_len(wpa_s->vendor_elem[frame]));
    7563             : }
    7564             : 
    7565             : 
    7566          29 : static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
    7567             : {
    7568          29 :         char *pos = cmd;
    7569             :         int frame;
    7570             :         size_t len;
    7571             :         u8 *buf;
    7572             :         struct ieee802_11_elems elems;
    7573             :         u8 *ie, *end;
    7574             : 
    7575          29 :         frame = atoi(pos);
    7576          29 :         if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
    7577           4 :                 return -1;
    7578          25 :         wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
    7579             : 
    7580          25 :         pos = os_strchr(pos, ' ');
    7581          25 :         if (pos == NULL)
    7582           3 :                 return -1;
    7583          22 :         pos++;
    7584             : 
    7585          22 :         if (*pos == '*') {
    7586           7 :                 wpabuf_free(wpa_s->vendor_elem[frame]);
    7587           7 :                 wpa_s->vendor_elem[frame] = NULL;
    7588           7 :                 wpas_ctrl_vendor_elem_update(wpa_s);
    7589           7 :                 return 0;
    7590             :         }
    7591             : 
    7592          15 :         if (wpa_s->vendor_elem[frame] == NULL)
    7593           4 :                 return -1;
    7594             : 
    7595          11 :         len = os_strlen(pos);
    7596          11 :         if (len == 0)
    7597           1 :                 return 0;
    7598          10 :         if (len & 1)
    7599           1 :                 return -1;
    7600           9 :         len /= 2;
    7601             : 
    7602           9 :         buf = os_malloc(len);
    7603           9 :         if (buf == NULL)
    7604           0 :                 return -1;
    7605             : 
    7606           9 :         if (hexstr2bin(pos, buf, len) < 0) {
    7607           1 :                 os_free(buf);
    7608           1 :                 return -1;
    7609             :         }
    7610             : 
    7611           8 :         if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
    7612           2 :                 os_free(buf);
    7613           2 :                 return -1;
    7614             :         }
    7615             : 
    7616           6 :         ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
    7617           6 :         end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
    7618             : 
    7619          20 :         for (; ie + 1 < end; ie += 2 + ie[1]) {
    7620           8 :                 if (ie + len > end)
    7621           0 :                         break;
    7622           8 :                 if (os_memcmp(ie, buf, len) != 0)
    7623           4 :                         continue;
    7624             : 
    7625           4 :                 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
    7626           2 :                         wpabuf_free(wpa_s->vendor_elem[frame]);
    7627           2 :                         wpa_s->vendor_elem[frame] = NULL;
    7628             :                 } else {
    7629           2 :                         os_memmove(ie, ie + len,
    7630             :                                    end - (ie + len));
    7631           2 :                         wpa_s->vendor_elem[frame]->used -= len;
    7632             :                 }
    7633           4 :                 os_free(buf);
    7634           4 :                 wpas_ctrl_vendor_elem_update(wpa_s);
    7635           4 :                 return 0;
    7636             :         }
    7637             : 
    7638           2 :         os_free(buf);
    7639             : 
    7640           2 :         return -1;
    7641             : }
    7642             : 
    7643             : 
    7644           2 : static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
    7645             : {
    7646           2 :         struct wpa_supplicant *wpa_s = ctx;
    7647             : 
    7648           2 :         if (neighbor_rep) {
    7649           0 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
    7650             :                              "length=%u",
    7651           0 :                              (unsigned int) wpabuf_len(neighbor_rep));
    7652           0 :                 wpabuf_free(neighbor_rep);
    7653             :         } else {
    7654           2 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
    7655             :         }
    7656           2 : }
    7657             : 
    7658             : 
    7659           4 : static int wpas_ctrl_iface_send_neigbor_rep(struct wpa_supplicant *wpa_s,
    7660             :                                             char *cmd)
    7661             : {
    7662             :         struct wpa_ssid ssid;
    7663           4 :         struct wpa_ssid *ssid_p = NULL;
    7664           4 :         int ret = 0;
    7665             : 
    7666           4 :         if (os_strncmp(cmd, " ssid=", 6) == 0) {
    7667           2 :                 ssid.ssid_len = os_strlen(cmd + 6);
    7668           2 :                 if (ssid.ssid_len > 32)
    7669           0 :                         return -1;
    7670           2 :                 ssid.ssid = (u8 *) (cmd + 6);
    7671           2 :                 ssid_p = &ssid;
    7672             :         }
    7673             : 
    7674           4 :         ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p,
    7675             :                                                  wpas_ctrl_neighbor_rep_cb,
    7676             :                                                  wpa_s);
    7677             : 
    7678           4 :         return ret;
    7679             : }
    7680             : 
    7681             : 
    7682          19 : static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
    7683             : {
    7684          19 :         eapol_sm_erp_flush(wpa_s->eapol);
    7685          19 :         return 0;
    7686             : }
    7687             : 
    7688             : 
    7689          16 : static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
    7690             :                                          char *cmd)
    7691             : {
    7692          16 :         char *token, *context = NULL;
    7693          16 :         unsigned int enable = ~0, type = 0;
    7694             :         u8 _addr[ETH_ALEN], _mask[ETH_ALEN];
    7695          16 :         u8 *addr = NULL, *mask = NULL;
    7696             : 
    7697          68 :         while ((token = str_token(cmd, " ", &context))) {
    7698          39 :                 if (os_strcasecmp(token, "scan") == 0) {
    7699           1 :                         type |= MAC_ADDR_RAND_SCAN;
    7700          38 :                 } else if (os_strcasecmp(token, "sched") == 0) {
    7701           1 :                         type |= MAC_ADDR_RAND_SCHED_SCAN;
    7702          37 :                 } else if (os_strcasecmp(token, "pno") == 0) {
    7703           2 :                         type |= MAC_ADDR_RAND_PNO;
    7704          35 :                 } else if (os_strcasecmp(token, "all") == 0) {
    7705          10 :                         type = wpa_s->mac_addr_rand_supported;
    7706          25 :                 } else if (os_strncasecmp(token, "enable=", 7) == 0) {
    7707          12 :                         enable = atoi(token + 7);
    7708          13 :                 } else if (os_strncasecmp(token, "addr=", 5) == 0) {
    7709           6 :                         addr = _addr;
    7710           6 :                         if (hwaddr_aton(token + 5, addr)) {
    7711           1 :                                 wpa_printf(MSG_INFO,
    7712             :                                            "CTRL: Invalid MAC address: %s",
    7713             :                                            token);
    7714           1 :                                 return -1;
    7715             :                         }
    7716           7 :                 } else if (os_strncasecmp(token, "mask=", 5) == 0) {
    7717           6 :                         mask = _mask;
    7718           6 :                         if (hwaddr_aton(token + 5, mask)) {
    7719           1 :                                 wpa_printf(MSG_INFO,
    7720             :                                            "CTRL: Invalid MAC address mask: %s",
    7721             :                                            token);
    7722           1 :                                 return -1;
    7723             :                         }
    7724             :                 } else {
    7725           1 :                         wpa_printf(MSG_INFO,
    7726             :                                    "CTRL: Invalid MAC_RAND_SCAN parameter: %s",
    7727             :                                    token);
    7728           1 :                         return -1;
    7729             :                 }
    7730             :         }
    7731             : 
    7732          13 :         if (!type) {
    7733           2 :                 wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified");
    7734           2 :                 return -1;
    7735             :         }
    7736             : 
    7737          11 :         if ((wpa_s->mac_addr_rand_supported & type) != type) {
    7738           1 :                 wpa_printf(MSG_INFO,
    7739             :                            "CTRL: MAC_RAND_SCAN types=%u != supported=%u",
    7740             :                            type, wpa_s->mac_addr_rand_supported);
    7741           1 :                 return -1;
    7742             :         }
    7743             : 
    7744          10 :         if (enable > 1) {
    7745           2 :                 wpa_printf(MSG_INFO,
    7746             :                            "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
    7747           2 :                 return -1;
    7748             :         }
    7749             : 
    7750           8 :         if (!enable) {
    7751           1 :                 wpas_mac_addr_rand_scan_clear(wpa_s, type);
    7752           1 :                 if (wpa_s->pno) {
    7753           0 :                         if (type & MAC_ADDR_RAND_PNO) {
    7754           0 :                                 wpas_stop_pno(wpa_s);
    7755           0 :                                 wpas_start_pno(wpa_s);
    7756             :                         }
    7757           1 :                 } else if (wpa_s->sched_scanning &&
    7758           0 :                            (type & MAC_ADDR_RAND_SCHED_SCAN)) {
    7759             :                         /* simulate timeout to restart the sched scan */
    7760           0 :                         wpa_s->sched_scan_timed_out = 1;
    7761           0 :                         wpa_s->prev_sched_ssid = NULL;
    7762           0 :                         wpa_supplicant_cancel_sched_scan(wpa_s);
    7763             :                 }
    7764           1 :                 return 0;
    7765             :         }
    7766             : 
    7767           7 :         if ((addr && !mask) || (!addr && mask)) {
    7768           2 :                 wpa_printf(MSG_INFO,
    7769             :                            "CTRL: MAC_RAND_SCAN invalid addr/mask combination");
    7770           2 :                 return -1;
    7771             :         }
    7772             : 
    7773           5 :         if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
    7774           2 :                 wpa_printf(MSG_INFO,
    7775             :                            "CTRL: MAC_RAND_SCAN cannot allow multicast address");
    7776           2 :                 return -1;
    7777             :         }
    7778             : 
    7779           3 :         if (type & MAC_ADDR_RAND_SCAN) {
    7780           3 :                 wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
    7781             :                                             addr, mask);
    7782             :         }
    7783             : 
    7784           3 :         if (type & MAC_ADDR_RAND_SCHED_SCAN) {
    7785           0 :                 wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
    7786             :                                             addr, mask);
    7787             : 
    7788           0 :                 if (wpa_s->sched_scanning && !wpa_s->pno) {
    7789             :                         /* simulate timeout to restart the sched scan */
    7790           0 :                         wpa_s->sched_scan_timed_out = 1;
    7791           0 :                         wpa_s->prev_sched_ssid = NULL;
    7792           0 :                         wpa_supplicant_cancel_sched_scan(wpa_s);
    7793             :                 }
    7794             :         }
    7795             : 
    7796           3 :         if (type & MAC_ADDR_RAND_PNO) {
    7797           0 :                 wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
    7798             :                                             addr, mask);
    7799           0 :                 if (wpa_s->pno) {
    7800           0 :                         wpas_stop_pno(wpa_s);
    7801           0 :                         wpas_start_pno(wpa_s);
    7802             :                 }
    7803             :         }
    7804             : 
    7805           3 :         return 0;
    7806             : }
    7807             : 
    7808             : 
    7809       70630 : char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
    7810             :                                          char *buf, size_t *resp_len)
    7811             : {
    7812             :         char *reply;
    7813       70630 :         const int reply_size = 4096;
    7814             :         int reply_len;
    7815             : 
    7816      141211 :         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
    7817       70581 :             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
    7818       15948 :                 if (wpa_debug_show_keys)
    7819        7974 :                         wpa_dbg(wpa_s, MSG_DEBUG,
    7820             :                                 "Control interface command '%s'", buf);
    7821             :                 else
    7822           0 :                         wpa_dbg(wpa_s, MSG_DEBUG,
    7823             :                                 "Control interface command '%s [REMOVED]'",
    7824             :                                 os_strncmp(buf, WPA_CTRL_RSP,
    7825             :                                            os_strlen(WPA_CTRL_RSP)) == 0 ?
    7826             :                                 WPA_CTRL_RSP : "SET_NETWORK");
    7827      125275 :         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
    7828       62619 :                    os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
    7829          77 :                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
    7830             :                                       (const u8 *) buf, os_strlen(buf));
    7831             :         } else {
    7832       62579 :                 int level = MSG_DEBUG;
    7833       62579 :                 if (os_strcmp(buf, "PING") == 0)
    7834        6662 :                         level = MSG_EXCESSIVE;
    7835       62579 :                 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
    7836             :         }
    7837             : 
    7838       70630 :         reply = os_malloc(reply_size);
    7839       70630 :         if (reply == NULL) {
    7840           0 :                 *resp_len = 1;
    7841           0 :                 return NULL;
    7842             :         }
    7843             : 
    7844       70630 :         os_memcpy(reply, "OK\n", 3);
    7845       70630 :         reply_len = 3;
    7846             : 
    7847       70630 :         if (os_strcmp(buf, "PING") == 0) {
    7848        6662 :                 os_memcpy(reply, "PONG\n", 5);
    7849        6662 :                 reply_len = 5;
    7850       63968 :         } else if (os_strcmp(buf, "IFNAME") == 0) {
    7851           1 :                 reply_len = os_strlen(wpa_s->ifname);
    7852           1 :                 os_memcpy(reply, wpa_s->ifname, reply_len);
    7853       63967 :         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
    7854           1 :                 if (wpa_debug_reopen_file() < 0)
    7855           0 :                         reply_len = -1;
    7856       63966 :         } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
    7857        6624 :                 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
    7858       57342 :         } else if (os_strcmp(buf, "MIB") == 0) {
    7859          11 :                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
    7860          11 :                 if (reply_len >= 0) {
    7861          11 :                         reply_len += eapol_sm_get_mib(wpa_s->eapol,
    7862             :                                                       reply + reply_len,
    7863          11 :                                                       reply_size - reply_len);
    7864             :                 }
    7865       57331 :         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
    7866        6840 :                 reply_len = wpa_supplicant_ctrl_iface_status(
    7867             :                         wpa_s, buf + 6, reply, reply_size);
    7868       50491 :         } else if (os_strcmp(buf, "PMKSA") == 0) {
    7869         149 :                 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
    7870             :                                                     reply_size);
    7871       50342 :         } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
    7872           7 :                 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
    7873       50335 :         } else if (os_strncmp(buf, "SET ", 4) == 0) {
    7874       20785 :                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
    7875          36 :                         reply_len = -1;
    7876       29550 :         } else if (os_strncmp(buf, "DUMP", 4) == 0) {
    7877           1 :                 reply_len = wpa_config_dump_values(wpa_s->conf,
    7878             :                                                    reply, reply_size);
    7879       29549 :         } else if (os_strncmp(buf, "GET ", 4) == 0) {
    7880          95 :                 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
    7881             :                                                           reply, reply_size);
    7882       29454 :         } else if (os_strcmp(buf, "LOGON") == 0) {
    7883           1 :                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
    7884       29453 :         } else if (os_strcmp(buf, "LOGOFF") == 0) {
    7885           1 :                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
    7886       29452 :         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
    7887          19 :                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
    7888           1 :                         reply_len = -1;
    7889             :                 else
    7890          18 :                         wpas_request_connection(wpa_s);
    7891       29433 :         } else if (os_strcmp(buf, "REATTACH") == 0) {
    7892           5 :                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
    7893           2 :                     !wpa_s->current_ssid)
    7894           2 :                         reply_len = -1;
    7895             :                 else {
    7896           1 :                         wpa_s->reattach = 1;
    7897           1 :                         wpas_request_connection(wpa_s);
    7898             :                 }
    7899       29430 :         } else if (os_strcmp(buf, "RECONNECT") == 0) {
    7900          35 :                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
    7901           1 :                         reply_len = -1;
    7902          34 :                 else if (wpa_s->disconnected)
    7903          34 :                         wpas_request_connection(wpa_s);
    7904             : #ifdef IEEE8021X_EAPOL
    7905       29395 :         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
    7906          16 :                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
    7907           6 :                         reply_len = -1;
    7908             : #endif /* IEEE8021X_EAPOL */
    7909             : #ifdef CONFIG_PEERKEY
    7910       29379 :         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
    7911           6 :                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
    7912           2 :                         reply_len = -1;
    7913             : #endif /* CONFIG_PEERKEY */
    7914             : #ifdef CONFIG_IEEE80211R
    7915       29373 :         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
    7916         116 :                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
    7917           1 :                         reply_len = -1;
    7918             : #endif /* CONFIG_IEEE80211R */
    7919             : #ifdef CONFIG_WPS
    7920       29257 :         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
    7921          15 :                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
    7922          15 :                 if (res == -2) {
    7923           1 :                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
    7924           1 :                         reply_len = 17;
    7925          14 :                 } else if (res)
    7926           0 :                         reply_len = -1;
    7927       29242 :         } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
    7928          29 :                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
    7929          29 :                 if (res == -2) {
    7930           1 :                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
    7931           1 :                         reply_len = 17;
    7932          28 :                 } else if (res)
    7933           2 :                         reply_len = -1;
    7934       29213 :         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
    7935         207 :                 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
    7936             :                                                               reply,
    7937             :                                                               reply_size);
    7938       29006 :         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
    7939          17 :                 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
    7940             :                         wpa_s, buf + 14, reply, reply_size);
    7941       28989 :         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
    7942          14 :                 if (wpas_wps_cancel(wpa_s))
    7943           1 :                         reply_len = -1;
    7944             : #ifdef CONFIG_WPS_NFC
    7945       28975 :         } else if (os_strcmp(buf, "WPS_NFC") == 0) {
    7946           3 :                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
    7947           0 :                         reply_len = -1;
    7948       28972 :         } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
    7949           1 :                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
    7950           1 :                         reply_len = -1;
    7951       28971 :         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
    7952           3 :                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
    7953             :                         wpa_s, buf + 21, reply, reply_size);
    7954       28968 :         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
    7955          14 :                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
    7956             :                         wpa_s, buf + 14, reply, reply_size);
    7957       28954 :         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
    7958          37 :                 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
    7959             :                                                                buf + 17))
    7960          22 :                         reply_len = -1;
    7961       28917 :         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
    7962          28 :                 reply_len = wpas_ctrl_nfc_get_handover_req(
    7963             :                         wpa_s, buf + 21, reply, reply_size);
    7964       28889 :         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
    7965          32 :                 reply_len = wpas_ctrl_nfc_get_handover_sel(
    7966             :                         wpa_s, buf + 21, reply, reply_size);
    7967       28857 :         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
    7968          40 :                 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
    7969           9 :                         reply_len = -1;
    7970             : #endif /* CONFIG_WPS_NFC */
    7971       28817 :         } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
    7972          45 :                 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
    7973           5 :                         reply_len = -1;
    7974             : #ifdef CONFIG_AP
    7975       28772 :         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
    7976          16 :                 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
    7977             :                         wpa_s, buf + 11, reply, reply_size);
    7978             : #endif /* CONFIG_AP */
    7979             : #ifdef CONFIG_WPS_ER
    7980       28756 :         } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
    7981           1 :                 if (wpas_wps_er_start(wpa_s, NULL))
    7982           0 :                         reply_len = -1;
    7983       28755 :         } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
    7984          10 :                 if (wpas_wps_er_start(wpa_s, buf + 13))
    7985           0 :                         reply_len = -1;
    7986       28745 :         } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
    7987          18 :                 wpas_wps_er_stop(wpa_s);
    7988       28727 :         } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
    7989           5 :                 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
    7990           1 :                         reply_len = -1;
    7991       28722 :         } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
    7992           5 :                 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
    7993           5 :                 if (ret == -2) {
    7994           1 :                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
    7995           1 :                         reply_len = 17;
    7996           4 :                 } else if (ret == -3) {
    7997           1 :                         os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
    7998           1 :                         reply_len = 18;
    7999           3 :                 } else if (ret == -4) {
    8000           1 :                         os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
    8001           1 :                         reply_len = 20;
    8002           2 :                 } else if (ret)
    8003           1 :                         reply_len = -1;
    8004       28717 :         } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
    8005           2 :                 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
    8006           1 :                         reply_len = -1;
    8007       28715 :         } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
    8008           9 :                 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
    8009             :                                                                 buf + 18))
    8010           1 :                         reply_len = -1;
    8011       28706 :         } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
    8012           6 :                 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
    8013           5 :                         reply_len = -1;
    8014             : #ifdef CONFIG_WPS_NFC
    8015       28700 :         } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
    8016           5 :                 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
    8017             :                         wpa_s, buf + 24, reply, reply_size);
    8018             : #endif /* CONFIG_WPS_NFC */
    8019             : #endif /* CONFIG_WPS_ER */
    8020             : #endif /* CONFIG_WPS */
    8021             : #ifdef CONFIG_IBSS_RSN
    8022       28695 :         } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
    8023           2 :                 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
    8024           1 :                         reply_len = -1;
    8025             : #endif /* CONFIG_IBSS_RSN */
    8026             : #ifdef CONFIG_MESH
    8027       28693 :         } else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
    8028           2 :                 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
    8029             :                         wpa_s, buf + 19, reply, reply_size);
    8030       28691 :         } else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) {
    8031           2 :                 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
    8032             :                         wpa_s, "", reply, reply_size);
    8033       28689 :         } else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
    8034          37 :                 if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
    8035           3 :                         reply_len = -1;
    8036       28652 :         } else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
    8037          17 :                 if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
    8038             :                                                                 buf + 18))
    8039           7 :                         reply_len = -1;
    8040             : #endif /* CONFIG_MESH */
    8041             : #ifdef CONFIG_P2P
    8042       28635 :         } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
    8043         333 :                 if (p2p_ctrl_find(wpa_s, buf + 8))
    8044           2 :                         reply_len = -1;
    8045       28302 :         } else if (os_strcmp(buf, "P2P_FIND") == 0) {
    8046          20 :                 if (p2p_ctrl_find(wpa_s, ""))
    8047           1 :                         reply_len = -1;
    8048       28282 :         } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
    8049         135 :                 wpas_p2p_stop_find(wpa_s);
    8050       28147 :         } else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
    8051          15 :                 if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
    8052           0 :                         reply_len = -1;
    8053       28132 :         } else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
    8054           3 :                 if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
    8055           0 :                         reply_len = -1;
    8056       28129 :         } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
    8057         298 :                 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
    8058             :                                              reply_size);
    8059       27831 :         } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
    8060           2 :                 if (p2p_ctrl_listen(wpa_s, buf + 11))
    8061           1 :                         reply_len = -1;
    8062       27829 :         } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
    8063         353 :                 if (p2p_ctrl_listen(wpa_s, ""))
    8064           1 :                         reply_len = -1;
    8065       27476 :         } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
    8066         306 :                 if (wpas_p2p_group_remove(wpa_s, buf + 17))
    8067          15 :                         reply_len = -1;
    8068       27170 :         } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
    8069          37 :                 if (wpas_p2p_group_add(wpa_s, 0, 0, 0, 0))
    8070           0 :                         reply_len = -1;
    8071       27133 :         } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
    8072         132 :                 if (p2p_ctrl_group_add(wpa_s, buf + 14))
    8073           4 :                         reply_len = -1;
    8074       27001 :         } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
    8075          16 :                 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
    8076           6 :                         reply_len = -1;
    8077       26985 :         } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
    8078           2 :                 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
    8079       26983 :         } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
    8080          68 :                 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
    8081             :                                                    reply_size);
    8082       26915 :         } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
    8083           9 :                 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
    8084           2 :                         reply_len = -1;
    8085       26906 :         } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
    8086           9 :                 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
    8087           7 :                         reply_len = -1;
    8088       26897 :         } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
    8089           1 :                 wpas_p2p_sd_service_update(wpa_s);
    8090       26896 :         } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
    8091           4 :                 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
    8092           1 :                         reply_len = -1;
    8093       26892 :         } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
    8094           1 :                 wpas_p2p_service_flush(wpa_s);
    8095       26891 :         } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
    8096         688 :                 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
    8097           9 :                         reply_len = -1;
    8098       26203 :         } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
    8099         106 :                 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
    8100          45 :                         reply_len = -1;
    8101       26097 :         } else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
    8102           2 :                 if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
    8103           1 :                         reply_len = -1;
    8104       26095 :         } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
    8105           3 :                 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
    8106           1 :                         reply_len = -1;
    8107       26092 :         } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
    8108          50 :                 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
    8109          10 :                         reply_len = -1;
    8110       26042 :         } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
    8111         952 :                 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
    8112             :                                               reply_size);
    8113       25090 :         } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
    8114         106 :                 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
    8115          26 :                         reply_len = -1;
    8116       24984 :         } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
    8117          41 :                 p2p_ctrl_flush(wpa_s);
    8118       24943 :         } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
    8119           3 :                 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
    8120           2 :                         reply_len = -1;
    8121       24940 :         } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
    8122           4 :                 if (wpas_p2p_cancel(wpa_s))
    8123           2 :                         reply_len = -1;
    8124       24936 :         } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
    8125           5 :                 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
    8126           2 :                         reply_len = -1;
    8127       24931 :         } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
    8128           1 :                 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
    8129           0 :                         reply_len = -1;
    8130       24930 :         } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
    8131           3 :                 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
    8132           1 :                         reply_len = -1;
    8133       24927 :         } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
    8134           3 :                 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
    8135           0 :                         reply_len = -1;
    8136       24924 :         } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
    8137           7 :                 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
    8138           1 :                         reply_len = -1;
    8139             : #endif /* CONFIG_P2P */
    8140             : #ifdef CONFIG_WIFI_DISPLAY
    8141       24917 :         } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
    8142          37 :                 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
    8143           8 :                         reply_len = -1;
    8144       24880 :         } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
    8145          16 :                 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
    8146             :                                                      reply, reply_size);
    8147             : #endif /* CONFIG_WIFI_DISPLAY */
    8148             : #ifdef CONFIG_INTERWORKING
    8149       24864 :         } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
    8150           7 :                 if (interworking_fetch_anqp(wpa_s) < 0)
    8151           0 :                         reply_len = -1;
    8152       24857 :         } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
    8153           2 :                 interworking_stop_fetch_anqp(wpa_s);
    8154       24855 :         } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
    8155           1 :                 if (ctrl_interworking_select(wpa_s, NULL) < 0)
    8156           0 :                         reply_len = -1;
    8157       24854 :         } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
    8158         132 :                 if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
    8159           0 :                         reply_len = -1;
    8160       24722 :         } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
    8161          50 :                 if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
    8162           3 :                         reply_len = -1;
    8163       24672 :         } else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
    8164             :                 int id;
    8165             : 
    8166           1 :                 id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
    8167           1 :                 if (id < 0)
    8168           0 :                         reply_len = -1;
    8169             :                 else {
    8170           1 :                         reply_len = os_snprintf(reply, reply_size, "%d\n", id);
    8171           1 :                         if (os_snprintf_error(reply_size, reply_len))
    8172           0 :                                 reply_len = -1;
    8173             :                 }
    8174       24671 :         } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
    8175          30 :                 if (get_anqp(wpa_s, buf + 9) < 0)
    8176          11 :                         reply_len = -1;
    8177       24641 :         } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
    8178          20 :                 if (gas_request(wpa_s, buf + 12) < 0)
    8179          12 :                         reply_len = -1;
    8180       24621 :         } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
    8181          14 :                 reply_len = gas_response_get(wpa_s, buf + 17, reply,
    8182             :                                              reply_size);
    8183             : #endif /* CONFIG_INTERWORKING */
    8184             : #ifdef CONFIG_HS20
    8185       24607 :         } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
    8186           9 :                 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
    8187           8 :                         reply_len = -1;
    8188       24598 :         } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
    8189           7 :                 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
    8190           3 :                         reply_len = -1;
    8191       24591 :         } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
    8192           2 :                 if (hs20_icon_request(wpa_s, buf + 18) < 0)
    8193           1 :                         reply_len = -1;
    8194       24589 :         } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
    8195           9 :                 if (hs20_fetch_osu(wpa_s) < 0)
    8196           6 :                         reply_len = -1;
    8197       24580 :         } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
    8198           2 :                 hs20_cancel_fetch_osu(wpa_s);
    8199             : #endif /* CONFIG_HS20 */
    8200       24578 :         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
    8201             :         {
    8202          49 :                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
    8203             :                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
    8204           5 :                         reply_len = -1;
    8205             :                 else {
    8206             :                         /*
    8207             :                          * Notify response from timeout to allow the control
    8208             :                          * interface response to be sent first.
    8209             :                          */
    8210          44 :                         eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
    8211             :                                                wpa_s, NULL);
    8212             :                 }
    8213       24529 :         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
    8214           1 :                 if (wpa_supplicant_reload_configuration(wpa_s))
    8215           0 :                         reply_len = -1;
    8216       24528 :         } else if (os_strcmp(buf, "TERMINATE") == 0) {
    8217           0 :                 wpa_supplicant_terminate_proc(wpa_s->global);
    8218       24528 :         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
    8219           5 :                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
    8220           3 :                         reply_len = -1;
    8221       24523 :         } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
    8222          14 :                 reply_len = wpa_supplicant_ctrl_iface_blacklist(
    8223             :                         wpa_s, buf + 9, reply, reply_size);
    8224       24509 :         } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
    8225          21 :                 reply_len = wpa_supplicant_ctrl_iface_log_level(
    8226             :                         wpa_s, buf + 9, reply, reply_size);
    8227       24488 :         } else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
    8228           1 :                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
    8229             :                         wpa_s, buf + 14, reply, reply_size);
    8230       24487 :         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
    8231          24 :                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
    8232             :                         wpa_s, NULL, reply, reply_size);
    8233       24463 :         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
    8234             : #ifdef CONFIG_SME
    8235         246 :                 wpa_s->sme.prev_bssid_set = 0;
    8236             : #endif /* CONFIG_SME */
    8237         246 :                 wpa_s->reassociate = 0;
    8238         246 :                 wpa_s->disconnected = 1;
    8239         246 :                 wpa_supplicant_cancel_sched_scan(wpa_s);
    8240         246 :                 wpa_supplicant_cancel_scan(wpa_s);
    8241         246 :                 wpa_supplicant_deauthenticate(wpa_s,
    8242             :                                               WLAN_REASON_DEAUTH_LEAVING);
    8243       24217 :         } else if (os_strcmp(buf, "SCAN") == 0) {
    8244          19 :                 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
    8245       24198 :         } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
    8246         478 :                 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
    8247       23720 :         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
    8248          31 :                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
    8249             :                         wpa_s, reply, reply_size);
    8250       23689 :         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
    8251        1455 :                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
    8252           2 :                         reply_len = -1;
    8253       22234 :         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
    8254          33 :                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
    8255           2 :                         reply_len = -1;
    8256       22201 :         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
    8257           7 :                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
    8258           2 :                         reply_len = -1;
    8259       22194 :         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
    8260        2475 :                 reply_len = wpa_supplicant_ctrl_iface_add_network(
    8261             :                         wpa_s, reply, reply_size);
    8262       19719 :         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
    8263         705 :                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
    8264           1 :                         reply_len = -1;
    8265       19014 :         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
    8266        7925 :                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
    8267          36 :                         reply_len = -1;
    8268       11089 :         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
    8269          56 :                 reply_len = wpa_supplicant_ctrl_iface_get_network(
    8270             :                         wpa_s, buf + 12, reply, reply_size);
    8271       11033 :         } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
    8272          10 :                 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12))
    8273           6 :                         reply_len = -1;
    8274       11023 :         } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
    8275           8 :                 reply_len = wpa_supplicant_ctrl_iface_list_creds(
    8276             :                         wpa_s, reply, reply_size);
    8277       11015 :         } else if (os_strcmp(buf, "ADD_CRED") == 0) {
    8278         224 :                 reply_len = wpa_supplicant_ctrl_iface_add_cred(
    8279             :                         wpa_s, reply, reply_size);
    8280       10791 :         } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
    8281         147 :                 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
    8282           1 :                         reply_len = -1;
    8283       10644 :         } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
    8284         750 :                 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
    8285          16 :                         reply_len = -1;
    8286        9894 :         } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
    8287          39 :                 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
    8288             :                                                                reply,
    8289             :                                                                reply_size);
    8290             : #ifndef CONFIG_NO_CONFIG_WRITE
    8291        9855 :         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
    8292           4 :                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
    8293           2 :                         reply_len = -1;
    8294             : #endif /* CONFIG_NO_CONFIG_WRITE */
    8295        9851 :         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
    8296          88 :                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
    8297             :                         wpa_s, buf + 15, reply, reply_size);
    8298        9763 :         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
    8299          13 :                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
    8300           2 :                         reply_len = -1;
    8301        9750 :         } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
    8302          18 :                 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
    8303           1 :                         reply_len = -1;
    8304        9732 :         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
    8305           1 :                 reply_len = wpa_supplicant_global_iface_list(
    8306             :                         wpa_s->global, reply, reply_size);
    8307        9731 :         } else if (os_strcmp(buf, "INTERFACES") == 0) {
    8308           1 :                 reply_len = wpa_supplicant_global_iface_interfaces(
    8309             :                         wpa_s->global, reply, reply_size);
    8310        9730 :         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
    8311         777 :                 reply_len = wpa_supplicant_ctrl_iface_bss(
    8312             :                         wpa_s, buf + 4, reply, reply_size);
    8313             : #ifdef CONFIG_AP
    8314        8953 :         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
    8315           1 :                 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
    8316        8952 :         } else if (os_strncmp(buf, "STA ", 4) == 0) {
    8317           1 :                 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
    8318             :                                               reply_size);
    8319        8951 :         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
    8320           2 :                 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
    8321             :                                                    reply_size);
    8322        8949 :         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
    8323          22 :                 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
    8324           2 :                         reply_len = -1;
    8325        8927 :         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
    8326          23 :                 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
    8327           2 :                         reply_len = -1;
    8328        8904 :         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
    8329           2 :                 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
    8330           1 :                         reply_len = -1;
    8331        8902 :         } else if (os_strcmp(buf, "STOP_AP") == 0) {
    8332           1 :                 if (wpas_ap_stop_ap(wpa_s))
    8333           0 :                         reply_len = -1;
    8334             : #endif /* CONFIG_AP */
    8335        8901 :         } else if (os_strcmp(buf, "SUSPEND") == 0) {
    8336           1 :                 wpas_notify_suspend(wpa_s->global);
    8337        8900 :         } else if (os_strcmp(buf, "RESUME") == 0) {
    8338           1 :                 wpas_notify_resume(wpa_s->global);
    8339             : #ifdef CONFIG_TESTING_OPTIONS
    8340        8899 :         } else if (os_strcmp(buf, "DROP_SA") == 0) {
    8341           2 :                 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
    8342             : #endif /* CONFIG_TESTING_OPTIONS */
    8343        8897 :         } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
    8344         155 :                 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
    8345           3 :                         reply_len = -1;
    8346        8742 :         } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
    8347           2 :                 wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0;
    8348        8740 :         } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
    8349           3 :                 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
    8350           1 :                         reply_len = -1;
    8351        8737 :         } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
    8352           2 :                 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
    8353             :                                                                buf + 17))
    8354           1 :                         reply_len = -1;
    8355        8735 :         } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
    8356         234 :                 wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10);
    8357             : #ifdef CONFIG_TDLS
    8358        8501 :         } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
    8359           3 :                 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
    8360           2 :                         reply_len = -1;
    8361        8498 :         } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
    8362          29 :                 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
    8363           1 :                         reply_len = -1;
    8364        8469 :         } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
    8365          13 :                 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
    8366           1 :                         reply_len = -1;
    8367        8456 :         } else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) {
    8368           8 :                 if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s,
    8369             :                                                                buf + 17))
    8370           7 :                         reply_len = -1;
    8371        8448 :         } else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) {
    8372           4 :                 if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s,
    8373             :                                                                       buf + 24))
    8374           3 :                         reply_len = -1;
    8375             : #endif /* CONFIG_TDLS */
    8376        8444 :         } else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
    8377          13 :                 reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
    8378        8431 :         } else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
    8379          16 :                 if (wmm_ac_ctrl_addts(wpa_s, buf + 13))
    8380           9 :                         reply_len = -1;
    8381        8415 :         } else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
    8382           3 :                 if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
    8383           2 :                         reply_len = -1;
    8384        8412 :         } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
    8385           5 :                 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
    8386             :                                                        reply_size);
    8387        8407 :         } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
    8388           1 :                 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
    8389             :                                                        reply_size);
    8390             : #ifdef CONFIG_AUTOSCAN
    8391        8406 :         } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
    8392          11 :                 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
    8393           0 :                         reply_len = -1;
    8394             : #endif /* CONFIG_AUTOSCAN */
    8395             : #ifdef ANDROID
    8396             :         } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
    8397             :                 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
    8398             :                                                       reply_size);
    8399             : #endif /* ANDROID */
    8400        8395 :         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
    8401           9 :                 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
    8402             :                                                       reply_size);
    8403        8386 :         } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
    8404          60 :                 pmksa_cache_clear_current(wpa_s->wpa);
    8405          60 :                 eapol_sm_request_reauth(wpa_s->eapol);
    8406             : #ifdef CONFIG_WNM
    8407        8326 :         } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
    8408          13 :                 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
    8409           3 :                         reply_len = -1;
    8410        8313 :         } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
    8411           1 :                 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
    8412           0 :                                 reply_len = -1;
    8413             : #endif /* CONFIG_WNM */
    8414        8312 :         } else if (os_strcmp(buf, "FLUSH") == 0) {
    8415        3341 :                 wpa_supplicant_ctrl_iface_flush(wpa_s);
    8416        4971 :         } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
    8417          35 :                 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
    8418             :                                                  reply_size);
    8419             : #ifdef CONFIG_TESTING_OPTIONS
    8420        4936 :         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
    8421          59 :                 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
    8422           5 :                         reply_len = -1;
    8423        4877 :         } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
    8424           1 :                 wpas_ctrl_iface_mgmt_tx_done(wpa_s);
    8425        4876 :         } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
    8426          11 :                 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
    8427           1 :                         reply_len = -1;
    8428        4865 :         } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
    8429         102 :                 if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
    8430           3 :                         reply_len = -1;
    8431        4763 :         } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
    8432        2088 :                 if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
    8433           0 :                         reply_len = -1;
    8434        2675 :         } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
    8435        2168 :                 if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
    8436           5 :                         reply_len = -1;
    8437         507 :         } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
    8438          98 :                 if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
    8439           4 :                         reply_len = -1;
    8440         409 :         } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
    8441         228 :                 if (wpas_ctrl_test_alloc_fail(wpa_s, buf + 16) < 0)
    8442           0 :                         reply_len = -1;
    8443         181 :         } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
    8444          87 :                 reply_len = wpas_ctrl_get_alloc_fail(wpa_s, reply, reply_size);
    8445             : #endif /* CONFIG_TESTING_OPTIONS */
    8446          94 :         } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
    8447          16 :                 if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
    8448           6 :                         reply_len = -1;
    8449          78 :         } else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
    8450           9 :                 reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
    8451             :                                                       reply_size);
    8452          69 :         } else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
    8453          29 :                 if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
    8454          17 :                         reply_len = -1;
    8455          40 :         } else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
    8456           4 :                 if (wpas_ctrl_iface_send_neigbor_rep(wpa_s, buf + 20))
    8457           2 :                         reply_len = -1;
    8458          36 :         } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
    8459          19 :                 wpas_ctrl_iface_erp_flush(wpa_s);
    8460          17 :         } else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
    8461          16 :                 if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14))
    8462          12 :                         reply_len = -1;
    8463             :         } else {
    8464           1 :                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
    8465           1 :                 reply_len = 16;
    8466             :         }
    8467             : 
    8468       70630 :         if (reply_len < 0) {
    8469        1007 :                 os_memcpy(reply, "FAIL\n", 5);
    8470        1007 :                 reply_len = 5;
    8471             :         }
    8472             : 
    8473       70630 :         *resp_len = reply_len;
    8474       70630 :         return reply;
    8475             : }
    8476             : 
    8477             : 
    8478          90 : static int wpa_supplicant_global_iface_add(struct wpa_global *global,
    8479             :                                            char *cmd)
    8480             : {
    8481             :         struct wpa_interface iface;
    8482             :         char *pos;
    8483             : 
    8484             :         /*
    8485             :          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
    8486             :          * TAB<bridge_ifname>
    8487             :          */
    8488          90 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
    8489             : 
    8490          90 :         os_memset(&iface, 0, sizeof(iface));
    8491             : 
    8492             :         do {
    8493          90 :                 iface.ifname = pos = cmd;
    8494          90 :                 pos = os_strchr(pos, '\t');
    8495          90 :                 if (pos)
    8496          88 :                         *pos++ = '\0';
    8497          90 :                 if (iface.ifname[0] == '\0')
    8498           1 :                         return -1;
    8499          89 :                 if (pos == NULL)
    8500           1 :                         break;
    8501             : 
    8502          88 :                 iface.confname = pos;
    8503          88 :                 pos = os_strchr(pos, '\t');
    8504          88 :                 if (pos)
    8505          87 :                         *pos++ = '\0';
    8506          88 :                 if (iface.confname[0] == '\0')
    8507          79 :                         iface.confname = NULL;
    8508          88 :                 if (pos == NULL)
    8509           1 :                         break;
    8510             : 
    8511          87 :                 iface.driver = pos;
    8512          87 :                 pos = os_strchr(pos, '\t');
    8513          87 :                 if (pos)
    8514          86 :                         *pos++ = '\0';
    8515          87 :                 if (iface.driver[0] == '\0')
    8516           1 :                         iface.driver = NULL;
    8517          87 :                 if (pos == NULL)
    8518           1 :                         break;
    8519             : 
    8520          86 :                 iface.ctrl_interface = pos;
    8521          86 :                 pos = os_strchr(pos, '\t');
    8522          86 :                 if (pos)
    8523          30 :                         *pos++ = '\0';
    8524          86 :                 if (iface.ctrl_interface[0] == '\0')
    8525           1 :                         iface.ctrl_interface = NULL;
    8526          86 :                 if (pos == NULL)
    8527          56 :                         break;
    8528             : 
    8529          30 :                 iface.driver_param = pos;
    8530          30 :                 pos = os_strchr(pos, '\t');
    8531          30 :                 if (pos)
    8532           7 :                         *pos++ = '\0';
    8533          30 :                 if (iface.driver_param[0] == '\0')
    8534           5 :                         iface.driver_param = NULL;
    8535          30 :                 if (pos == NULL)
    8536          23 :                         break;
    8537             : 
    8538           7 :                 iface.bridge_ifname = pos;
    8539           7 :                 pos = os_strchr(pos, '\t');
    8540           7 :                 if (pos)
    8541           1 :                         *pos++ = '\0';
    8542           7 :                 if (iface.bridge_ifname[0] == '\0')
    8543           1 :                         iface.bridge_ifname = NULL;
    8544           7 :                 if (pos == NULL)
    8545           6 :                         break;
    8546             :         } while (0);
    8547             : 
    8548          89 :         if (wpa_supplicant_get_iface(global, iface.ifname))
    8549           0 :                 return -1;
    8550             : 
    8551          89 :         return wpa_supplicant_add_iface(global, &iface, NULL) ? 0 : -1;
    8552             : }
    8553             : 
    8554             : 
    8555          80 : static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
    8556             :                                               char *cmd)
    8557             : {
    8558             :         struct wpa_supplicant *wpa_s;
    8559             : 
    8560          80 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
    8561             : 
    8562          80 :         wpa_s = wpa_supplicant_get_iface(global, cmd);
    8563          80 :         if (wpa_s == NULL)
    8564           1 :                 return -1;
    8565          79 :         return wpa_supplicant_remove_iface(global, wpa_s, 0);
    8566             : }
    8567             : 
    8568             : 
    8569           2 : static void wpa_free_iface_info(struct wpa_interface_info *iface)
    8570             : {
    8571             :         struct wpa_interface_info *prev;
    8572             : 
    8573           4 :         while (iface) {
    8574           0 :                 prev = iface;
    8575           0 :                 iface = iface->next;
    8576             : 
    8577           0 :                 os_free(prev->ifname);
    8578           0 :                 os_free(prev->desc);
    8579           0 :                 os_free(prev);
    8580             :         }
    8581           2 : }
    8582             : 
    8583             : 
    8584           2 : static int wpa_supplicant_global_iface_list(struct wpa_global *global,
    8585             :                                             char *buf, int len)
    8586             : {
    8587             :         int i, res;
    8588           2 :         struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
    8589             :         char *pos, *end;
    8590             : 
    8591           8 :         for (i = 0; wpa_drivers[i]; i++) {
    8592           6 :                 struct wpa_driver_ops *drv = wpa_drivers[i];
    8593           6 :                 if (drv->get_interfaces == NULL)
    8594           6 :                         continue;
    8595           0 :                 tmp = drv->get_interfaces(global->drv_priv[i]);
    8596           0 :                 if (tmp == NULL)
    8597           0 :                         continue;
    8598             : 
    8599           0 :                 if (last == NULL)
    8600           0 :                         iface = last = tmp;
    8601             :                 else
    8602           0 :                         last->next = tmp;
    8603           0 :                 while (last->next)
    8604           0 :                         last = last->next;
    8605             :         }
    8606             : 
    8607           2 :         pos = buf;
    8608           2 :         end = buf + len;
    8609           2 :         for (tmp = iface; tmp; tmp = tmp->next) {
    8610           0 :                 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
    8611             :                                   tmp->drv_name, tmp->ifname,
    8612           0 :                                   tmp->desc ? tmp->desc : "");
    8613           0 :                 if (os_snprintf_error(end - pos, res)) {
    8614           0 :                         *pos = '\0';
    8615           0 :                         break;
    8616             :                 }
    8617           0 :                 pos += res;
    8618             :         }
    8619             : 
    8620           2 :         wpa_free_iface_info(iface);
    8621             : 
    8622           2 :         return pos - buf;
    8623             : }
    8624             : 
    8625             : 
    8626        1112 : static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
    8627             :                                                   char *buf, int len)
    8628             : {
    8629             :         int res;
    8630             :         char *pos, *end;
    8631             :         struct wpa_supplicant *wpa_s;
    8632             : 
    8633        1112 :         wpa_s = global->ifaces;
    8634        1112 :         pos = buf;
    8635        1112 :         end = buf + len;
    8636             : 
    8637        2375 :         while (wpa_s) {
    8638         151 :                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
    8639         151 :                 if (os_snprintf_error(end - pos, res)) {
    8640           0 :                         *pos = '\0';
    8641           0 :                         break;
    8642             :                 }
    8643         151 :                 pos += res;
    8644         151 :                 wpa_s = wpa_s->next;
    8645             :         }
    8646        1112 :         return pos - buf;
    8647             : }
    8648             : 
    8649             : 
    8650           8 : static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
    8651             :                                             const char *ifname,
    8652             :                                             char *cmd, size_t *resp_len)
    8653             : {
    8654             :         struct wpa_supplicant *wpa_s;
    8655             : 
    8656           9 :         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
    8657           8 :                 if (os_strcmp(ifname, wpa_s->ifname) == 0)
    8658           7 :                         break;
    8659             :         }
    8660             : 
    8661           8 :         if (wpa_s == NULL) {
    8662           1 :                 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
    8663           1 :                 if (resp)
    8664           1 :                         *resp_len = os_strlen(resp);
    8665             :                 else
    8666           0 :                         *resp_len = 1;
    8667           1 :                 return resp;
    8668             :         }
    8669             : 
    8670           7 :         return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
    8671             : }
    8672             : 
    8673             : 
    8674       12676 : static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
    8675             :                                                char *buf, size_t *resp_len)
    8676             : {
    8677             : #ifdef CONFIG_P2P
    8678             :         static const char * cmd[] = {
    8679             :                 "LIST_NETWORKS",
    8680             :                 "P2P_FIND",
    8681             :                 "P2P_STOP_FIND",
    8682             :                 "P2P_LISTEN",
    8683             :                 "P2P_GROUP_ADD",
    8684             :                 "P2P_GET_PASSPHRASE",
    8685             :                 "P2P_SERVICE_UPDATE",
    8686             :                 "P2P_SERVICE_FLUSH",
    8687             :                 "P2P_FLUSH",
    8688             :                 "P2P_CANCEL",
    8689             :                 "P2P_PRESENCE_REQ",
    8690             :                 "P2P_EXT_LISTEN",
    8691             :                 NULL
    8692             :         };
    8693             :         static const char * prefix[] = {
    8694             : #ifdef ANDROID
    8695             :                 "DRIVER ",
    8696             : #endif /* ANDROID */
    8697             :                 "GET_NETWORK ",
    8698             :                 "REMOVE_NETWORK ",
    8699             :                 "P2P_FIND ",
    8700             :                 "P2P_CONNECT ",
    8701             :                 "P2P_LISTEN ",
    8702             :                 "P2P_GROUP_REMOVE ",
    8703             :                 "P2P_GROUP_ADD ",
    8704             :                 "P2P_PROV_DISC ",
    8705             :                 "P2P_SERV_DISC_REQ ",
    8706             :                 "P2P_SERV_DISC_CANCEL_REQ ",
    8707             :                 "P2P_SERV_DISC_RESP ",
    8708             :                 "P2P_SERV_DISC_EXTERNAL ",
    8709             :                 "P2P_SERVICE_ADD ",
    8710             :                 "P2P_SERVICE_DEL ",
    8711             :                 "P2P_SERVICE_REP ",
    8712             :                 "P2P_REJECT ",
    8713             :                 "P2P_INVITE ",
    8714             :                 "P2P_PEER ",
    8715             :                 "P2P_SET ",
    8716             :                 "P2P_UNAUTHORIZE ",
    8717             :                 "P2P_PRESENCE_REQ ",
    8718             :                 "P2P_EXT_LISTEN ",
    8719             :                 "P2P_REMOVE_CLIENT ",
    8720             :                 "WPS_NFC_TOKEN ",
    8721             :                 "WPS_NFC_TAG_READ ",
    8722             :                 "NFC_GET_HANDOVER_SEL ",
    8723             :                 "NFC_GET_HANDOVER_REQ ",
    8724             :                 "NFC_REPORT_HANDOVER ",
    8725             :                 "P2P_ASP_PROVISION ",
    8726             :                 "P2P_ASP_PROVISION_RESP ",
    8727             :                 NULL
    8728             :         };
    8729       12676 :         int found = 0;
    8730             :         int i;
    8731             : 
    8732       12676 :         if (global->p2p_init_wpa_s == NULL)
    8733        2173 :                 return NULL;
    8734             : 
    8735      131978 :         for (i = 0; !found && cmd[i]; i++) {
    8736      121475 :                 if (os_strcmp(buf, cmd[i]) == 0)
    8737         575 :                         found = 1;
    8738             :         }
    8739             : 
    8740      255719 :         for (i = 0; !found && prefix[i]; i++) {
    8741      245216 :                 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
    8742        2949 :                         found = 1;
    8743             :         }
    8744             : 
    8745       10503 :         if (found)
    8746        3524 :                 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
    8747             :                                                          buf, resp_len);
    8748             : #endif /* CONFIG_P2P */
    8749        6979 :         return NULL;
    8750             : }
    8751             : 
    8752             : 
    8753        9152 : static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
    8754             :                                                char *buf, size_t *resp_len)
    8755             : {
    8756             : #ifdef CONFIG_WIFI_DISPLAY
    8757        9152 :         if (global->p2p_init_wpa_s == NULL)
    8758        2173 :                 return NULL;
    8759       13957 :         if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
    8760        6978 :             os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
    8761           2 :                 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
    8762             :                                                          buf, resp_len);
    8763             : #endif /* CONFIG_WIFI_DISPLAY */
    8764        6977 :         return NULL;
    8765             : }
    8766             : 
    8767             : 
    8768       12676 : static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
    8769             :                                            char *buf, size_t *resp_len)
    8770             : {
    8771             :         char *ret;
    8772             : 
    8773       12676 :         ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
    8774       12676 :         if (ret)
    8775        3524 :                 return ret;
    8776             : 
    8777        9152 :         ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
    8778        9152 :         if (ret)
    8779           2 :                 return ret;
    8780             : 
    8781        9150 :         return NULL;
    8782             : }
    8783             : 
    8784             : 
    8785         100 : static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
    8786             : {
    8787             :         char *value;
    8788             : 
    8789         100 :         value = os_strchr(cmd, ' ');
    8790         100 :         if (value == NULL)
    8791           1 :                 return -1;
    8792          99 :         *value++ = '\0';
    8793             : 
    8794          99 :         wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
    8795             : 
    8796             : #ifdef CONFIG_WIFI_DISPLAY
    8797          99 :         if (os_strcasecmp(cmd, "wifi_display") == 0) {
    8798           4 :                 wifi_display_enable(global, !!atoi(value));
    8799           4 :                 return 0;
    8800             :         }
    8801             : #endif /* CONFIG_WIFI_DISPLAY */
    8802             : 
    8803             :         /* Restore cmd to its original value to allow redirection */
    8804          95 :         value[-1] = ' ';
    8805             : 
    8806          95 :         return -1;
    8807             : }
    8808             : 
    8809             : 
    8810             : #ifndef CONFIG_NO_CONFIG_WRITE
    8811           4 : static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
    8812             : {
    8813           4 :         int ret = 0, saved = 0;
    8814             :         struct wpa_supplicant *wpa_s;
    8815             : 
    8816           8 :         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
    8817           4 :                 if (!wpa_s->conf->update_config) {
    8818           2 :                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
    8819           2 :                         continue;
    8820             :                 }
    8821             : 
    8822           2 :                 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
    8823           1 :                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
    8824           1 :                         ret = 1;
    8825             :                 } else {
    8826           1 :                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
    8827           1 :                         saved++;
    8828             :                 }
    8829             :         }
    8830             : 
    8831           4 :         if (!saved && !ret) {
    8832           2 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    8833             :                         "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
    8834           2 :                 ret = 1;
    8835             :         }
    8836             : 
    8837           4 :         return ret;
    8838             : }
    8839             : #endif /* CONFIG_NO_CONFIG_WRITE */
    8840             : 
    8841             : 
    8842           9 : static int wpas_global_ctrl_iface_status(struct wpa_global *global,
    8843             :                                          char *buf, size_t buflen)
    8844             : {
    8845             :         char *pos, *end;
    8846             :         int ret;
    8847             :         struct wpa_supplicant *wpa_s;
    8848             : 
    8849           9 :         pos = buf;
    8850           9 :         end = buf + buflen;
    8851             : 
    8852             : #ifdef CONFIG_P2P
    8853           9 :         if (global->p2p && !global->p2p_disabled) {
    8854          56 :                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
    8855             :                                   "\n"
    8856             :                                   "p2p_state=%s\n",
    8857          48 :                                   MAC2STR(global->p2p_dev_addr),
    8858             :                                   p2p_get_state_txt(global->p2p));
    8859           8 :                 if (os_snprintf_error(end - pos, ret))
    8860           0 :                         return pos - buf;
    8861           8 :                 pos += ret;
    8862           1 :         } else if (global->p2p) {
    8863           1 :                 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
    8864           1 :                 if (os_snprintf_error(end - pos, ret))
    8865           0 :                         return pos - buf;
    8866           1 :                 pos += ret;
    8867             :         }
    8868             : #endif /* CONFIG_P2P */
    8869             : 
    8870             : #ifdef CONFIG_WIFI_DISPLAY
    8871           9 :         ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
    8872           9 :                           !!global->wifi_display);
    8873           9 :         if (os_snprintf_error(end - pos, ret))
    8874           0 :                 return pos - buf;
    8875           9 :         pos += ret;
    8876             : #endif /* CONFIG_WIFI_DISPLAY */
    8877             : 
    8878          18 :         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
    8879          63 :                 ret = os_snprintf(pos, end - pos, "ifname=%s\n"
    8880             :                                   "address=" MACSTR "\n",
    8881          63 :                                   wpa_s->ifname, MAC2STR(wpa_s->own_addr));
    8882           9 :                 if (os_snprintf_error(end - pos, ret))
    8883           0 :                         return pos - buf;
    8884           9 :                 pos += ret;
    8885             :         }
    8886             : 
    8887           9 :         return pos - buf;
    8888             : }
    8889             : 
    8890             : 
    8891       12684 : char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
    8892             :                                                 char *buf, size_t *resp_len)
    8893             : {
    8894             :         char *reply;
    8895       12684 :         const int reply_size = 2048;
    8896             :         int reply_len;
    8897       12684 :         int level = MSG_DEBUG;
    8898             : 
    8899       12684 :         if (os_strncmp(buf, "IFNAME=", 7) == 0) {
    8900           8 :                 char *pos = os_strchr(buf + 7, ' ');
    8901           8 :                 if (pos) {
    8902           8 :                         *pos++ = '\0';
    8903           8 :                         return wpas_global_ctrl_iface_ifname(global,
    8904             :                                                              buf + 7, pos,
    8905             :                                                              resp_len);
    8906             :                 }
    8907             :         }
    8908             : 
    8909       12676 :         reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
    8910       12676 :         if (reply)
    8911        3526 :                 return reply;
    8912             : 
    8913        9150 :         if (os_strcmp(buf, "PING") == 0)
    8914        3329 :                 level = MSG_EXCESSIVE;
    8915        9150 :         wpa_hexdump_ascii(level, "RX global ctrl_iface",
    8916             :                           (const u8 *) buf, os_strlen(buf));
    8917             : 
    8918        9150 :         reply = os_malloc(reply_size);
    8919        9150 :         if (reply == NULL) {
    8920           0 :                 *resp_len = 1;
    8921           0 :                 return NULL;
    8922             :         }
    8923             : 
    8924        9150 :         os_memcpy(reply, "OK\n", 3);
    8925        9150 :         reply_len = 3;
    8926             : 
    8927        9150 :         if (os_strcmp(buf, "PING") == 0) {
    8928        3329 :                 os_memcpy(reply, "PONG\n", 5);
    8929        3329 :                 reply_len = 5;
    8930        5821 :         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
    8931          90 :                 if (wpa_supplicant_global_iface_add(global, buf + 14))
    8932          11 :                         reply_len = -1;
    8933        5731 :         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
    8934          80 :                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
    8935           1 :                         reply_len = -1;
    8936        5651 :         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
    8937           1 :                 reply_len = wpa_supplicant_global_iface_list(
    8938             :                         global, reply, reply_size);
    8939        5650 :         } else if (os_strcmp(buf, "INTERFACES") == 0) {
    8940        1111 :                 reply_len = wpa_supplicant_global_iface_interfaces(
    8941             :                         global, reply, reply_size);
    8942        4539 :         } else if (os_strcmp(buf, "TERMINATE") == 0) {
    8943           0 :                 wpa_supplicant_terminate_proc(global);
    8944        4539 :         } else if (os_strcmp(buf, "SUSPEND") == 0) {
    8945           1 :                 wpas_notify_suspend(global);
    8946        4538 :         } else if (os_strcmp(buf, "RESUME") == 0) {
    8947           1 :                 wpas_notify_resume(global);
    8948        4537 :         } else if (os_strncmp(buf, "SET ", 4) == 0) {
    8949         100 :                 if (wpas_global_ctrl_iface_set(global, buf + 4)) {
    8950             : #ifdef CONFIG_P2P
    8951          96 :                         if (global->p2p_init_wpa_s) {
    8952          96 :                                 os_free(reply);
    8953             :                                 /* Check if P2P redirection would work for this
    8954             :                                  * command. */
    8955          96 :                                 return wpa_supplicant_ctrl_iface_process(
    8956             :                                         global->p2p_init_wpa_s,
    8957             :                                         buf, resp_len);
    8958             :                         }
    8959             : #endif /* CONFIG_P2P */
    8960           0 :                         reply_len = -1;
    8961             :                 }
    8962             : #ifndef CONFIG_NO_CONFIG_WRITE
    8963        4437 :         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
    8964           4 :                 if (wpas_global_ctrl_iface_save_config(global))
    8965           3 :                         reply_len = -1;
    8966             : #endif /* CONFIG_NO_CONFIG_WRITE */
    8967        4433 :         } else if (os_strcmp(buf, "STATUS") == 0) {
    8968           9 :                 reply_len = wpas_global_ctrl_iface_status(global, reply,
    8969             :                                                           reply_size);
    8970             : #ifdef CONFIG_MODULE_TESTS
    8971        4424 :         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
    8972             :                 int wpas_module_tests(void);
    8973           1 :                 if (wpas_module_tests() < 0)
    8974           0 :                         reply_len = -1;
    8975             : #endif /* CONFIG_MODULE_TESTS */
    8976        4423 :         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
    8977        4422 :                 if (wpa_debug_reopen_file() < 0)
    8978           0 :                         reply_len = -1;
    8979             :         } else {
    8980           1 :                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
    8981           1 :                 reply_len = 16;
    8982             :         }
    8983             : 
    8984        9054 :         if (reply_len < 0) {
    8985          15 :                 os_memcpy(reply, "FAIL\n", 5);
    8986          15 :                 reply_len = 5;
    8987             :         }
    8988             : 
    8989        9054 :         *resp_len = reply_len;
    8990        9054 :         return reply;
    8991             : }

Generated by: LCOV version 1.10