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 1401264779 Lines: 3274 4098 79.9 %
Date: 2014-05-28 Functions: 154 159 96.9 %

          Line data    Source code
       1             : /*
       2             :  * WPA Supplicant / Control interface (shared code for all backends)
       3             :  * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "utils/includes.h"
      10             : 
      11             : #include "utils/common.h"
      12             : #include "utils/eloop.h"
      13             : #include "utils/uuid.h"
      14             : #include "common/version.h"
      15             : #include "common/ieee802_11_defs.h"
      16             : #include "common/ieee802_11_common.h"
      17             : #include "common/wpa_ctrl.h"
      18             : #include "eap_peer/eap.h"
      19             : #include "eapol_supp/eapol_supp_sm.h"
      20             : #include "rsn_supp/wpa.h"
      21             : #include "rsn_supp/preauth.h"
      22             : #include "rsn_supp/pmksa_cache.h"
      23             : #include "l2_packet/l2_packet.h"
      24             : #include "wps/wps.h"
      25             : #include "config.h"
      26             : #include "wpa_supplicant_i.h"
      27             : #include "driver_i.h"
      28             : #include "wps_supplicant.h"
      29             : #include "ibss_rsn.h"
      30             : #include "ap.h"
      31             : #include "p2p_supplicant.h"
      32             : #include "p2p/p2p.h"
      33             : #include "hs20_supplicant.h"
      34             : #include "wifi_display.h"
      35             : #include "notify.h"
      36             : #include "bss.h"
      37             : #include "scan.h"
      38             : #include "ctrl_iface.h"
      39             : #include "interworking.h"
      40             : #include "blacklist.h"
      41             : #include "autoscan.h"
      42             : #include "wnm_sta.h"
      43             : #include "offchannel.h"
      44             : 
      45             : static int wpa_supplicant_global_iface_list(struct wpa_global *global,
      46             :                                             char *buf, int len);
      47             : static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
      48             :                                                   char *buf, int len);
      49             : static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
      50             :                                         char *val);
      51             : 
      52           4 : static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
      53             : {
      54             :         char *pos;
      55           4 :         u8 addr[ETH_ALEN], *filter = NULL, *n;
      56           4 :         size_t count = 0;
      57             : 
      58           4 :         pos = val;
      59          10 :         while (pos) {
      60           5 :                 if (*pos == '\0')
      61           2 :                         break;
      62           3 :                 if (hwaddr_aton(pos, addr)) {
      63           1 :                         os_free(filter);
      64           1 :                         return -1;
      65             :                 }
      66           2 :                 n = os_realloc_array(filter, count + 1, ETH_ALEN);
      67           2 :                 if (n == NULL) {
      68           0 :                         os_free(filter);
      69           0 :                         return -1;
      70             :                 }
      71           2 :                 filter = n;
      72           2 :                 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
      73           2 :                 count++;
      74             : 
      75           2 :                 pos = os_strchr(pos, ' ');
      76           2 :                 if (pos)
      77           1 :                         pos++;
      78             :         }
      79             : 
      80           3 :         wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
      81           3 :         os_free(wpa_s->bssid_filter);
      82           3 :         wpa_s->bssid_filter = filter;
      83           3 :         wpa_s->bssid_filter_count = count;
      84             : 
      85           3 :         return 0;
      86             : }
      87             : 
      88             : 
      89          15 : static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
      90             : {
      91             :         char *pos;
      92          15 :         u8 addr[ETH_ALEN], *bssid = NULL, *n;
      93          15 :         struct wpa_ssid_value *ssid = NULL, *ns;
      94          15 :         size_t count = 0, ssid_count = 0;
      95             :         struct wpa_ssid *c;
      96             : 
      97             :         /*
      98             :          * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
      99             :          * SSID_SPEC ::= ssid <SSID_HEX>
     100             :          * BSSID_SPEC ::= bssid <BSSID_HEX>
     101             :          */
     102             : 
     103          15 :         pos = val;
     104          40 :         while (pos) {
     105          18 :                 if (*pos == '\0')
     106           1 :                         break;
     107          17 :                 if (os_strncmp(pos, "bssid ", 6) == 0) {
     108             :                         int res;
     109           9 :                         pos += 6;
     110           9 :                         res = hwaddr_aton2(pos, addr);
     111           9 :                         if (res < 0) {
     112           2 :                                 os_free(ssid);
     113           2 :                                 os_free(bssid);
     114           2 :                                 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
     115             :                                            "BSSID value '%s'", pos);
     116           2 :                                 return -1;
     117             :                         }
     118           7 :                         pos += res;
     119           7 :                         n = os_realloc_array(bssid, count + 1, ETH_ALEN);
     120           7 :                         if (n == NULL) {
     121           0 :                                 os_free(ssid);
     122           0 :                                 os_free(bssid);
     123           0 :                                 return -1;
     124             :                         }
     125           7 :                         bssid = n;
     126           7 :                         os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
     127           7 :                         count++;
     128           8 :                 } else if (os_strncmp(pos, "ssid ", 5) == 0) {
     129             :                         char *end;
     130           7 :                         pos += 5;
     131             : 
     132           7 :                         end = pos;
     133         118 :                         while (*end) {
     134         105 :                                 if (*end == '\0' || *end == ' ')
     135             :                                         break;
     136         104 :                                 end++;
     137             :                         }
     138             : 
     139           7 :                         ns = os_realloc_array(ssid, ssid_count + 1,
     140             :                                               sizeof(struct wpa_ssid_value));
     141           7 :                         if (ns == NULL) {
     142           0 :                                 os_free(ssid);
     143           0 :                                 os_free(bssid);
     144           0 :                                 return -1;
     145             :                         }
     146           7 :                         ssid = ns;
     147             : 
     148          11 :                         if ((end - pos) & 0x01 || end - pos > 2 * 32 ||
     149           4 :                             hexstr2bin(pos, ssid[ssid_count].ssid,
     150           4 :                                        (end - pos) / 2) < 0) {
     151           4 :                                 os_free(ssid);
     152           4 :                                 os_free(bssid);
     153           4 :                                 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
     154             :                                            "SSID value '%s'", pos);
     155           4 :                                 return -1;
     156             :                         }
     157           3 :                         ssid[ssid_count].ssid_len = (end - pos) / 2;
     158           6 :                         wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
     159           3 :                                           ssid[ssid_count].ssid,
     160           3 :                                           ssid[ssid_count].ssid_len);
     161           3 :                         ssid_count++;
     162           3 :                         pos = end;
     163             :                 } else {
     164           1 :                         wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
     165             :                                    "'%s'", pos);
     166           1 :                         os_free(ssid);
     167           1 :                         os_free(bssid);
     168           1 :                         return -1;
     169             :                 }
     170             : 
     171          10 :                 pos = os_strchr(pos, ' ');
     172          10 :                 if (pos)
     173           3 :                         pos++;
     174             :         }
     175             : 
     176           8 :         wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
     177           8 :         os_free(wpa_s->disallow_aps_bssid);
     178           8 :         wpa_s->disallow_aps_bssid = bssid;
     179           8 :         wpa_s->disallow_aps_bssid_count = count;
     180             : 
     181           8 :         wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
     182           8 :         os_free(wpa_s->disallow_aps_ssid);
     183           8 :         wpa_s->disallow_aps_ssid = ssid;
     184           8 :         wpa_s->disallow_aps_ssid_count = ssid_count;
     185             : 
     186           8 :         if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
     187           4 :                 return 0;
     188             : 
     189           4 :         c = wpa_s->current_ssid;
     190           4 :         if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
     191           0 :                 return 0;
     192             : 
     193           6 :         if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
     194           2 :             !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
     195           1 :                 return 0;
     196             : 
     197           3 :         wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
     198             :                    "because current AP was marked disallowed");
     199             : 
     200             : #ifdef CONFIG_SME
     201           3 :         wpa_s->sme.prev_bssid_set = 0;
     202             : #endif /* CONFIG_SME */
     203           3 :         wpa_s->reassociate = 1;
     204           3 :         wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
     205           3 :         wpa_supplicant_req_scan(wpa_s, 0, 0);
     206             : 
     207           3 :         return 0;
     208             : }
     209             : 
     210             : 
     211             : #ifndef CONFIG_NO_CONFIG_BLOBS
     212          13 : static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
     213             : {
     214          13 :         char *name = pos;
     215             :         struct wpa_config_blob *blob;
     216             :         size_t len;
     217             : 
     218          13 :         pos = os_strchr(pos, ' ');
     219          13 :         if (pos == NULL)
     220           1 :                 return -1;
     221          12 :         *pos++ = '\0';
     222          12 :         len = os_strlen(pos);
     223          12 :         if (len & 1)
     224           1 :                 return -1;
     225             : 
     226          11 :         wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
     227          11 :         blob = os_zalloc(sizeof(*blob));
     228          11 :         if (blob == NULL)
     229           0 :                 return -1;
     230          11 :         blob->name = os_strdup(name);
     231          11 :         blob->data = os_malloc(len / 2);
     232          11 :         if (blob->name == NULL || blob->data == NULL) {
     233           0 :                 wpa_config_free_blob(blob);
     234           0 :                 return -1;
     235             :         }
     236             : 
     237          11 :         if (hexstr2bin(pos, blob->data, len / 2) < 0) {
     238           1 :                 wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
     239           1 :                 wpa_config_free_blob(blob);
     240           1 :                 return -1;
     241             :         }
     242          10 :         blob->len = len / 2;
     243             : 
     244          10 :         wpa_config_set_blob(wpa_s->conf, blob);
     245             : 
     246          10 :         return 0;
     247             : }
     248             : #endif /* CONFIG_NO_CONFIG_BLOBS */
     249             : 
     250             : 
     251           5 : static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
     252             : {
     253             :         char *params;
     254             :         char *pos;
     255           5 :         int *freqs = NULL;
     256             :         int ret;
     257             : 
     258           5 :         if (atoi(cmd)) {
     259           4 :                 params = os_strchr(cmd, ' ');
     260           4 :                 os_free(wpa_s->manual_sched_scan_freqs);
     261           4 :                 if (params) {
     262           2 :                         params++;
     263           2 :                         pos = os_strstr(params, "freq=");
     264           2 :                         if (pos)
     265           2 :                                 freqs = freq_range_to_channel_list(wpa_s,
     266             :                                                                    pos + 5);
     267             :                 }
     268           4 :                 wpa_s->manual_sched_scan_freqs = freqs;
     269           4 :                 ret = wpas_start_pno(wpa_s);
     270             :         } else {
     271           1 :                 ret = wpas_stop_pno(wpa_s);
     272             :         }
     273           5 :         return ret;
     274             : }
     275             : 
     276             : 
     277       17573 : static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
     278             :                                          char *cmd)
     279             : {
     280             :         char *value;
     281       17573 :         int ret = 0;
     282             : 
     283       17573 :         value = os_strchr(cmd, ' ');
     284       17573 :         if (value == NULL)
     285           1 :                 return -1;
     286       17572 :         *value++ = '\0';
     287             : 
     288       17572 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
     289       17572 :         if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
     290           1 :                 eapol_sm_configure(wpa_s->eapol,
     291             :                                    atoi(value), -1, -1, -1);
     292       17571 :         } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
     293           1 :                 eapol_sm_configure(wpa_s->eapol,
     294             :                                    -1, atoi(value), -1, -1);
     295       17570 :         } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
     296           1 :                 eapol_sm_configure(wpa_s->eapol,
     297             :                                    -1, -1, atoi(value), -1);
     298       17569 :         } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
     299           1 :                 eapol_sm_configure(wpa_s->eapol,
     300             :                                    -1, -1, -1, atoi(value));
     301       17568 :         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
     302           3 :                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
     303           3 :                                      atoi(value)))
     304           1 :                         ret = -1;
     305       17565 :         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
     306             :                    0) {
     307           2 :                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
     308           2 :                                      atoi(value)))
     309           1 :                         ret = -1;
     310       17563 :         } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
     311           2 :                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
     312           1 :                         ret = -1;
     313       17561 :         } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
     314           3 :                 wpa_s->wps_fragment_size = atoi(value);
     315             : #ifdef CONFIG_WPS_TESTING
     316       17558 :         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
     317             :                 long int val;
     318           5 :                 val = strtol(value, NULL, 0);
     319           5 :                 if (val < 0 || val > 0xff) {
     320           2 :                         ret = -1;
     321           2 :                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
     322             :                                    "wps_version_number %ld", val);
     323             :                 } else {
     324           3 :                         wps_version_number = val;
     325           6 :                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
     326             :                                    "version %u.%u",
     327           3 :                                    (wps_version_number & 0xf0) >> 4,
     328             :                                    wps_version_number & 0x0f);
     329             :                 }
     330       17553 :         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
     331           1 :                 wps_testing_dummy_cred = atoi(value);
     332           1 :                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
     333             :                            wps_testing_dummy_cred);
     334       17552 :         } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
     335           3 :                 wps_corrupt_pkhash = atoi(value);
     336           3 :                 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
     337             :                            wps_corrupt_pkhash);
     338             : #endif /* CONFIG_WPS_TESTING */
     339       17549 :         } else if (os_strcasecmp(cmd, "ampdu") == 0) {
     340           0 :                 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
     341           0 :                         ret = -1;
     342             : #ifdef CONFIG_TDLS
     343             : #ifdef CONFIG_TDLS_TESTING
     344       17549 :         } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
     345             :                 extern unsigned int tdls_testing;
     346          10 :                 tdls_testing = strtol(value, NULL, 0);
     347          10 :                 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
     348             : #endif /* CONFIG_TDLS_TESTING */
     349       17539 :         } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
     350           2 :                 int disabled = atoi(value);
     351           2 :                 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
     352           2 :                 if (disabled) {
     353           1 :                         if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
     354           0 :                                 ret = -1;
     355           1 :                 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
     356           0 :                         ret = -1;
     357           2 :                 wpa_tdls_enable(wpa_s->wpa, !disabled);
     358             : #endif /* CONFIG_TDLS */
     359       17537 :         } else if (os_strcasecmp(cmd, "pno") == 0) {
     360           5 :                 ret = wpas_ctrl_pno(wpa_s, value);
     361       17532 :         } else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
     362           0 :                 int disabled = atoi(value);
     363           0 :                 if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
     364           0 :                         ret = -1;
     365           0 :                 else if (disabled)
     366           0 :                         wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
     367       17532 :         } else if (os_strcasecmp(cmd, "uapsd") == 0) {
     368           7 :                 if (os_strcmp(value, "disable") == 0)
     369           1 :                         wpa_s->set_sta_uapsd = 0;
     370             :                 else {
     371             :                         int be, bk, vi, vo;
     372             :                         char *pos;
     373             :                         /* format: BE,BK,VI,VO;max SP Length */
     374           6 :                         be = atoi(value);
     375           6 :                         pos = os_strchr(value, ',');
     376           6 :                         if (pos == NULL)
     377           2 :                                 return -1;
     378           4 :                         pos++;
     379           4 :                         bk = atoi(pos);
     380           4 :                         pos = os_strchr(pos, ',');
     381           4 :                         if (pos == NULL)
     382           1 :                                 return -1;
     383           3 :                         pos++;
     384           3 :                         vi = atoi(pos);
     385           3 :                         pos = os_strchr(pos, ',');
     386           3 :                         if (pos == NULL)
     387           1 :                                 return -1;
     388           2 :                         pos++;
     389           2 :                         vo = atoi(pos);
     390             :                         /* ignore max SP Length for now */
     391             : 
     392           2 :                         wpa_s->set_sta_uapsd = 1;
     393           2 :                         wpa_s->sta_uapsd = 0;
     394           2 :                         if (be)
     395           1 :                                 wpa_s->sta_uapsd |= BIT(0);
     396           2 :                         if (bk)
     397           1 :                                 wpa_s->sta_uapsd |= BIT(1);
     398           2 :                         if (vi)
     399           1 :                                 wpa_s->sta_uapsd |= BIT(2);
     400           2 :                         if (vo)
     401           1 :                                 wpa_s->sta_uapsd |= BIT(3);
     402             :                 }
     403       17525 :         } else if (os_strcasecmp(cmd, "ps") == 0) {
     404           0 :                 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
     405             : #ifdef CONFIG_WIFI_DISPLAY
     406       17525 :         } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
     407           6 :                 int enabled = !!atoi(value);
     408           6 :                 if (enabled && !wpa_s->global->p2p)
     409           0 :                         ret = -1;
     410             :                 else
     411           6 :                         wifi_display_enable(wpa_s->global, enabled);
     412             : #endif /* CONFIG_WIFI_DISPLAY */
     413       17519 :         } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
     414           4 :                 ret = set_bssid_filter(wpa_s, value);
     415       17515 :         } else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
     416          15 :                 ret = set_disallow_aps(wpa_s, value);
     417       17500 :         } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
     418           0 :                 wpa_s->no_keep_alive = !!atoi(value);
     419             : #ifdef CONFIG_TESTING_OPTIONS
     420       17500 :         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
     421           7 :                 wpa_s->ext_mgmt_frame_handling = !!atoi(value);
     422             : #endif /* CONFIG_TESTING_OPTIONS */
     423             : #ifndef CONFIG_NO_CONFIG_BLOBS
     424       17493 :         } else if (os_strcmp(cmd, "blob") == 0) {
     425          13 :                 ret = wpas_ctrl_set_blob(wpa_s, value);
     426             : #endif /* CONFIG_NO_CONFIG_BLOBS */
     427             :         } else {
     428       17480 :                 value[-1] = '=';
     429       17480 :                 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
     430       17480 :                 if (ret == 0)
     431       17475 :                         wpa_supplicant_update_config(wpa_s);
     432             :         }
     433             : 
     434       17568 :         return ret;
     435             : }
     436             : 
     437             : 
     438           5 : static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
     439             :                                          char *cmd, char *buf, size_t buflen)
     440             : {
     441           5 :         int res = -1;
     442             : 
     443           5 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
     444             : 
     445           5 :         if (os_strcmp(cmd, "version") == 0) {
     446           1 :                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
     447           4 :         } else if (os_strcasecmp(cmd, "country") == 0) {
     448           2 :                 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
     449           4 :                         res = os_snprintf(buf, buflen, "%c%c",
     450           2 :                                           wpa_s->conf->country[0],
     451           2 :                                           wpa_s->conf->country[1]);
     452             : #ifdef CONFIG_WIFI_DISPLAY
     453           2 :         } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
     454             :                 int enabled;
     455           2 :                 if (wpa_s->global->p2p == NULL ||
     456           1 :                     wpa_s->global->p2p_disabled)
     457           0 :                         enabled = 0;
     458             :                 else
     459           1 :                         enabled = wpa_s->global->wifi_display;
     460           1 :                 res = os_snprintf(buf, buflen, "%d", enabled);
     461           1 :                 if (res < 0 || (unsigned int) res >= buflen)
     462           0 :                         return -1;
     463           1 :                 return res;
     464             : #endif /* CONFIG_WIFI_DISPLAY */
     465             : #ifdef CONFIG_TESTING_GET_GTK
     466             :         } else if (os_strcmp(cmd, "gtk") == 0) {
     467             :                 if (wpa_s->last_gtk_len == 0)
     468             :                         return -1;
     469             :                 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
     470             :                                        wpa_s->last_gtk_len);
     471             :                 return res;
     472             : #endif /* CONFIG_TESTING_GET_GTK */
     473             :         }
     474             : 
     475           4 :         if (res < 0 || (unsigned int) res >= buflen)
     476           1 :                 return -1;
     477           3 :         return res;
     478             : }
     479             : 
     480             : 
     481             : #ifdef IEEE8021X_EAPOL
     482           2 : static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
     483             :                                              char *addr)
     484             : {
     485             :         u8 bssid[ETH_ALEN];
     486           2 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
     487             : 
     488           2 :         if (hwaddr_aton(addr, bssid)) {
     489           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
     490             :                            "'%s'", addr);
     491           1 :                 return -1;
     492             :         }
     493             : 
     494           1 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
     495           1 :         rsn_preauth_deinit(wpa_s->wpa);
     496           1 :         if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
     497           0 :                 return -1;
     498             : 
     499           1 :         return 0;
     500             : }
     501             : #endif /* IEEE8021X_EAPOL */
     502             : 
     503             : 
     504             : #ifdef CONFIG_PEERKEY
     505             : /* MLME-STKSTART.request(peer) */
     506           6 : static int wpa_supplicant_ctrl_iface_stkstart(
     507             :         struct wpa_supplicant *wpa_s, char *addr)
     508             : {
     509             :         u8 peer[ETH_ALEN];
     510             : 
     511           6 :         if (hwaddr_aton(addr, peer)) {
     512           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
     513             :                            "address '%s'", addr);
     514           1 :                 return -1;
     515             :         }
     516             : 
     517          30 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
     518          30 :                    MAC2STR(peer));
     519             : 
     520           5 :         return wpa_sm_stkstart(wpa_s->wpa, peer);
     521             : }
     522             : #endif /* CONFIG_PEERKEY */
     523             : 
     524             : 
     525             : #ifdef CONFIG_TDLS
     526             : 
     527           3 : static int wpa_supplicant_ctrl_iface_tdls_discover(
     528             :         struct wpa_supplicant *wpa_s, char *addr)
     529             : {
     530             :         u8 peer[ETH_ALEN];
     531             :         int ret;
     532             : 
     533           3 :         if (hwaddr_aton(addr, peer)) {
     534           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
     535             :                            "address '%s'", addr);
     536           1 :                 return -1;
     537             :         }
     538             : 
     539          12 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
     540          12 :                    MAC2STR(peer));
     541             : 
     542           2 :         if (wpa_tdls_is_external_setup(wpa_s->wpa))
     543           2 :                 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
     544             :         else
     545           0 :                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
     546             : 
     547           2 :         return ret;
     548             : }
     549             : 
     550             : 
     551          25 : static int wpa_supplicant_ctrl_iface_tdls_setup(
     552             :         struct wpa_supplicant *wpa_s, char *addr)
     553             : {
     554             :         u8 peer[ETH_ALEN];
     555             :         int ret;
     556             : 
     557          25 :         if (hwaddr_aton(addr, peer)) {
     558           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
     559             :                            "address '%s'", addr);
     560           1 :                 return -1;
     561             :         }
     562             : 
     563         144 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
     564         144 :                    MAC2STR(peer));
     565             : 
     566          24 :         if ((wpa_s->conf->tdls_external_control) &&
     567           0 :             wpa_tdls_is_external_setup(wpa_s->wpa))
     568           0 :                 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
     569             : 
     570          24 :         wpa_tdls_remove(wpa_s->wpa, peer);
     571             : 
     572          24 :         if (wpa_tdls_is_external_setup(wpa_s->wpa))
     573          24 :                 ret = wpa_tdls_start(wpa_s->wpa, peer);
     574             :         else
     575           0 :                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
     576             : 
     577          24 :         return ret;
     578             : }
     579             : 
     580             : 
     581           9 : static int wpa_supplicant_ctrl_iface_tdls_teardown(
     582             :         struct wpa_supplicant *wpa_s, char *addr)
     583             : {
     584             :         u8 peer[ETH_ALEN];
     585             :         int ret;
     586             : 
     587           9 :         if (hwaddr_aton(addr, peer)) {
     588           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
     589             :                            "address '%s'", addr);
     590           1 :                 return -1;
     591             :         }
     592             : 
     593          48 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
     594          48 :                    MAC2STR(peer));
     595             : 
     596           8 :         if ((wpa_s->conf->tdls_external_control) &&
     597           0 :             wpa_tdls_is_external_setup(wpa_s->wpa))
     598           0 :                 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
     599             : 
     600           8 :         if (wpa_tdls_is_external_setup(wpa_s->wpa))
     601           8 :                 ret = wpa_tdls_teardown_link(
     602             :                         wpa_s->wpa, peer,
     603             :                         WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
     604             :         else
     605           0 :                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
     606             : 
     607           8 :         return ret;
     608             : }
     609             : 
     610             : 
     611           1 : static int ctrl_iface_get_capability_tdls(
     612             :         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
     613             : {
     614             :         int ret;
     615             : 
     616           2 :         ret = os_snprintf(buf, buflen, "%s\n",
     617           1 :                           wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
     618           1 :                           (wpa_s->drv_flags &
     619             :                            WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
     620           1 :                            "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
     621           1 :         if (ret < 0 || (size_t) ret > buflen)
     622           0 :                 return -1;
     623           1 :         return ret;
     624             : }
     625             : 
     626             : #endif /* CONFIG_TDLS */
     627             : 
     628             : 
     629             : #ifdef CONFIG_IEEE80211R
     630          14 : static int wpa_supplicant_ctrl_iface_ft_ds(
     631             :         struct wpa_supplicant *wpa_s, char *addr)
     632             : {
     633             :         u8 target_ap[ETH_ALEN];
     634             :         struct wpa_bss *bss;
     635             :         const u8 *mdie;
     636             : 
     637          14 :         if (hwaddr_aton(addr, target_ap)) {
     638           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
     639             :                            "address '%s'", addr);
     640           1 :                 return -1;
     641             :         }
     642             : 
     643          13 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
     644             : 
     645          13 :         bss = wpa_bss_get_bssid(wpa_s, target_ap);
     646          13 :         if (bss)
     647          13 :                 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
     648             :         else
     649           0 :                 mdie = NULL;
     650             : 
     651          13 :         return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
     652             : }
     653             : #endif /* CONFIG_IEEE80211R */
     654             : 
     655             : 
     656             : #ifdef CONFIG_WPS
     657          30 : static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
     658             :                                              char *cmd)
     659             : {
     660          30 :         u8 bssid[ETH_ALEN], *_bssid = bssid;
     661             : #ifdef CONFIG_P2P
     662             :         u8 p2p_dev_addr[ETH_ALEN];
     663             : #endif /* CONFIG_P2P */
     664             : #ifdef CONFIG_AP
     665          30 :         u8 *_p2p_dev_addr = NULL;
     666             : #endif /* CONFIG_AP */
     667             : 
     668          30 :         if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
     669          27 :                 _bssid = NULL;
     670             : #ifdef CONFIG_P2P
     671           3 :         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
     672           2 :                 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
     673           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
     674             :                                    "P2P Device Address '%s'",
     675             :                                    cmd + 13);
     676           1 :                         return -1;
     677             :                 }
     678           1 :                 _p2p_dev_addr = p2p_dev_addr;
     679             : #endif /* CONFIG_P2P */
     680           1 :         } else if (hwaddr_aton(cmd, bssid)) {
     681           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
     682             :                            cmd);
     683           1 :                 return -1;
     684             :         }
     685             : 
     686             : #ifdef CONFIG_AP
     687          28 :         if (wpa_s->ap_iface)
     688           4 :                 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
     689             : #endif /* CONFIG_AP */
     690             : 
     691          24 :         return wpas_wps_start_pbc(wpa_s, _bssid, 0);
     692             : }
     693             : 
     694             : 
     695         161 : static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
     696             :                                              char *cmd, char *buf,
     697             :                                              size_t buflen)
     698             : {
     699         161 :         u8 bssid[ETH_ALEN], *_bssid = bssid;
     700             :         char *pin;
     701             :         int ret;
     702             : 
     703         161 :         pin = os_strchr(cmd, ' ');
     704         161 :         if (pin)
     705          50 :                 *pin++ = '\0';
     706             : 
     707         161 :         if (os_strcmp(cmd, "any") == 0)
     708          51 :                 _bssid = NULL;
     709         110 :         else if (os_strcmp(cmd, "get") == 0) {
     710         109 :                 ret = wps_generate_pin();
     711         109 :                 goto done;
     712           1 :         } else if (hwaddr_aton(cmd, bssid)) {
     713           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
     714             :                            cmd);
     715           1 :                 return -1;
     716             :         }
     717             : 
     718             : #ifdef CONFIG_AP
     719          51 :         if (wpa_s->ap_iface) {
     720          32 :                 int timeout = 0;
     721             :                 char *pos;
     722             : 
     723          32 :                 if (pin) {
     724          32 :                         pos = os_strchr(pin, ' ');
     725          32 :                         if (pos) {
     726           1 :                                 *pos++ = '\0';
     727           1 :                                 timeout = atoi(pos);
     728             :                         }
     729             :                 }
     730             : 
     731          32 :                 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
     732             :                                                  buf, buflen, timeout);
     733             :         }
     734             : #endif /* CONFIG_AP */
     735             : 
     736          19 :         if (pin) {
     737          18 :                 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
     738             :                                          DEV_PW_DEFAULT);
     739          18 :                 if (ret < 0)
     740           0 :                         return -1;
     741          18 :                 ret = os_snprintf(buf, buflen, "%s", pin);
     742          18 :                 if (ret < 0 || (size_t) ret >= buflen)
     743           0 :                         return -1;
     744          18 :                 return ret;
     745             :         }
     746             : 
     747           1 :         ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
     748           1 :         if (ret < 0)
     749           0 :                 return -1;
     750             : 
     751             : done:
     752             :         /* Return the generated PIN */
     753         110 :         ret = os_snprintf(buf, buflen, "%08d", ret);
     754         110 :         if (ret < 0 || (size_t) ret >= buflen)
     755           0 :                 return -1;
     756         110 :         return ret;
     757             : }
     758             : 
     759             : 
     760          17 : static int wpa_supplicant_ctrl_iface_wps_check_pin(
     761             :         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
     762             : {
     763             :         char pin[9];
     764             :         size_t len;
     765             :         char *pos;
     766             :         int ret;
     767             : 
     768          17 :         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
     769             :                               (u8 *) cmd, os_strlen(cmd));
     770         156 :         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
     771         140 :                 if (*pos < '0' || *pos > '9')
     772           6 :                         continue;
     773         134 :                 pin[len++] = *pos;
     774         134 :                 if (len == 9) {
     775           1 :                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
     776           1 :                         return -1;
     777             :                 }
     778             :         }
     779          16 :         if (len != 4 && len != 8) {
     780           1 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
     781           1 :                 return -1;
     782             :         }
     783          15 :         pin[len] = '\0';
     784             : 
     785          15 :         if (len == 8) {
     786             :                 unsigned int pin_val;
     787          15 :                 pin_val = atoi(pin);
     788          15 :                 if (!wps_pin_valid(pin_val)) {
     789           1 :                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
     790           1 :                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
     791           1 :                         if (ret < 0 || (size_t) ret >= buflen)
     792           0 :                                 return -1;
     793           1 :                         return ret;
     794             :                 }
     795             :         }
     796             : 
     797          14 :         ret = os_snprintf(buf, buflen, "%s", pin);
     798          14 :         if (ret < 0 || (size_t) ret >= buflen)
     799           0 :                 return -1;
     800             : 
     801          14 :         return ret;
     802             : }
     803             : 
     804             : 
     805             : #ifdef CONFIG_WPS_NFC
     806             : 
     807           4 : static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
     808             :                                              char *cmd)
     809             : {
     810           4 :         u8 bssid[ETH_ALEN], *_bssid = bssid;
     811             : 
     812           4 :         if (cmd == NULL || cmd[0] == '\0')
     813           3 :                 _bssid = NULL;
     814           1 :         else if (hwaddr_aton(cmd, bssid))
     815           1 :                 return -1;
     816             : 
     817           3 :         return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
     818             :                                   0, 0);
     819             : }
     820             : 
     821             : 
     822           1 : static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
     823             :         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
     824             : {
     825             :         int ndef;
     826             :         struct wpabuf *buf;
     827             :         int res;
     828             :         char *pos;
     829             : 
     830           1 :         pos = os_strchr(cmd, ' ');
     831           1 :         if (pos)
     832           0 :                 *pos++ = '\0';
     833           1 :         if (os_strcmp(cmd, "WPS") == 0)
     834           0 :                 ndef = 0;
     835           1 :         else if (os_strcmp(cmd, "NDEF") == 0)
     836           1 :                 ndef = 1;
     837             :         else
     838           0 :                 return -1;
     839             : 
     840           1 :         buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
     841           1 :         if (buf == NULL)
     842           0 :                 return -1;
     843             : 
     844           1 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
     845             :                                          wpabuf_len(buf));
     846           1 :         reply[res++] = '\n';
     847           1 :         reply[res] = '\0';
     848             : 
     849           1 :         wpabuf_free(buf);
     850             : 
     851           1 :         return res;
     852             : }
     853             : 
     854             : 
     855          11 : static int wpa_supplicant_ctrl_iface_wps_nfc_token(
     856             :         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
     857             : {
     858             :         int ndef;
     859             :         struct wpabuf *buf;
     860             :         int res;
     861             : 
     862          11 :         if (os_strcmp(cmd, "WPS") == 0)
     863           0 :                 ndef = 0;
     864          11 :         else if (os_strcmp(cmd, "NDEF") == 0)
     865          11 :                 ndef = 1;
     866             :         else
     867           0 :                 return -1;
     868             : 
     869          11 :         buf = wpas_wps_nfc_token(wpa_s, ndef);
     870          11 :         if (buf == NULL)
     871           0 :                 return -1;
     872             : 
     873          11 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
     874             :                                          wpabuf_len(buf));
     875          11 :         reply[res++] = '\n';
     876          11 :         reply[res] = '\0';
     877             : 
     878          11 :         wpabuf_free(buf);
     879             : 
     880          11 :         return res;
     881             : }
     882             : 
     883             : 
     884          25 : static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
     885             :         struct wpa_supplicant *wpa_s, char *pos)
     886             : {
     887             :         size_t len;
     888             :         struct wpabuf *buf;
     889             :         int ret;
     890             :         char *freq;
     891          25 :         int forced_freq = 0;
     892             : 
     893          25 :         freq = strstr(pos, " freq=");
     894          25 :         if (freq) {
     895           1 :                 *freq = '\0';
     896           1 :                 freq += 6;
     897           1 :                 forced_freq = atoi(freq);
     898             :         }
     899             : 
     900          25 :         len = os_strlen(pos);
     901          25 :         if (len & 0x01)
     902           1 :                 return -1;
     903          24 :         len /= 2;
     904             : 
     905          24 :         buf = wpabuf_alloc(len);
     906          24 :         if (buf == NULL)
     907           0 :                 return -1;
     908          24 :         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
     909           1 :                 wpabuf_free(buf);
     910           1 :                 return -1;
     911             :         }
     912             : 
     913          23 :         ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
     914          23 :         wpabuf_free(buf);
     915             : 
     916          23 :         return ret;
     917             : }
     918             : 
     919             : 
     920          12 : static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
     921             :                                               char *reply, size_t max_len,
     922             :                                               int ndef)
     923             : {
     924             :         struct wpabuf *buf;
     925             :         int res;
     926             : 
     927          12 :         buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
     928          12 :         if (buf == NULL)
     929           0 :                 return -1;
     930             : 
     931          12 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
     932             :                                          wpabuf_len(buf));
     933          12 :         reply[res++] = '\n';
     934          12 :         reply[res] = '\0';
     935             : 
     936          12 :         wpabuf_free(buf);
     937             : 
     938          12 :         return res;
     939             : }
     940             : 
     941             : 
     942             : #ifdef CONFIG_P2P
     943          10 : static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
     944             :                                               char *reply, size_t max_len,
     945             :                                               int ndef)
     946             : {
     947             :         struct wpabuf *buf;
     948             :         int res;
     949             : 
     950          10 :         buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
     951          10 :         if (buf == NULL) {
     952           0 :                 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
     953           0 :                 return -1;
     954             :         }
     955             : 
     956          10 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
     957             :                                          wpabuf_len(buf));
     958          10 :         reply[res++] = '\n';
     959          10 :         reply[res] = '\0';
     960             : 
     961          10 :         wpabuf_free(buf);
     962             : 
     963          10 :         return res;
     964             : }
     965             : #endif /* CONFIG_P2P */
     966             : 
     967             : 
     968          28 : static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
     969             :                                           char *cmd, char *reply,
     970             :                                           size_t max_len)
     971             : {
     972             :         char *pos;
     973             :         int ndef;
     974             : 
     975          28 :         pos = os_strchr(cmd, ' ');
     976          28 :         if (pos == NULL)
     977           1 :                 return -1;
     978          27 :         *pos++ = '\0';
     979             : 
     980          27 :         if (os_strcmp(cmd, "WPS") == 0)
     981           4 :                 ndef = 0;
     982          23 :         else if (os_strcmp(cmd, "NDEF") == 0)
     983          22 :                 ndef = 1;
     984             :         else
     985           1 :                 return -1;
     986             : 
     987          26 :         if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
     988          14 :                 if (!ndef)
     989           2 :                         return -1;
     990          12 :                 return wpas_ctrl_nfc_get_handover_req_wps(
     991             :                         wpa_s, reply, max_len, ndef);
     992             :         }
     993             : 
     994             : #ifdef CONFIG_P2P
     995          12 :         if (os_strcmp(pos, "P2P-CR") == 0) {
     996          10 :                 return wpas_ctrl_nfc_get_handover_req_p2p(
     997             :                         wpa_s, reply, max_len, ndef);
     998             :         }
     999             : #endif /* CONFIG_P2P */
    1000             : 
    1001           2 :         return -1;
    1002             : }
    1003             : 
    1004             : 
    1005           6 : static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
    1006             :                                               char *reply, size_t max_len,
    1007             :                                               int ndef, int cr, char *uuid)
    1008             : {
    1009             :         struct wpabuf *buf;
    1010             :         int res;
    1011             : 
    1012           6 :         buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
    1013           6 :         if (buf == NULL)
    1014           2 :                 return -1;
    1015             : 
    1016           4 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    1017             :                                          wpabuf_len(buf));
    1018           4 :         reply[res++] = '\n';
    1019           4 :         reply[res] = '\0';
    1020             : 
    1021           4 :         wpabuf_free(buf);
    1022             : 
    1023           4 :         return res;
    1024             : }
    1025             : 
    1026             : 
    1027             : #ifdef CONFIG_P2P
    1028          19 : static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
    1029             :                                               char *reply, size_t max_len,
    1030             :                                               int ndef, int tag)
    1031             : {
    1032             :         struct wpabuf *buf;
    1033             :         int res;
    1034             : 
    1035          19 :         buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
    1036          19 :         if (buf == NULL)
    1037           0 :                 return -1;
    1038             : 
    1039          19 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    1040             :                                          wpabuf_len(buf));
    1041          19 :         reply[res++] = '\n';
    1042          19 :         reply[res] = '\0';
    1043             : 
    1044          19 :         wpabuf_free(buf);
    1045             : 
    1046          19 :         return res;
    1047             : }
    1048             : #endif /* CONFIG_P2P */
    1049             : 
    1050             : 
    1051          31 : static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
    1052             :                                           char *cmd, char *reply,
    1053             :                                           size_t max_len)
    1054             : {
    1055             :         char *pos, *pos2;
    1056             :         int ndef;
    1057             : 
    1058          31 :         pos = os_strchr(cmd, ' ');
    1059          31 :         if (pos == NULL)
    1060           1 :                 return -1;
    1061          30 :         *pos++ = '\0';
    1062             : 
    1063          30 :         if (os_strcmp(cmd, "WPS") == 0)
    1064           5 :                 ndef = 0;
    1065          25 :         else if (os_strcmp(cmd, "NDEF") == 0)
    1066          24 :                 ndef = 1;
    1067             :         else
    1068           1 :                 return -1;
    1069             : 
    1070          29 :         pos2 = os_strchr(pos, ' ');
    1071          29 :         if (pos2)
    1072           4 :                 *pos2++ = '\0';
    1073          29 :         if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
    1074           8 :                 if (!ndef)
    1075           2 :                         return -1;
    1076           6 :                 return wpas_ctrl_nfc_get_handover_sel_wps(
    1077             :                         wpa_s, reply, max_len, ndef,
    1078           6 :                         os_strcmp(pos, "WPS-CR") == 0, pos2);
    1079             :         }
    1080             : 
    1081             : #ifdef CONFIG_P2P
    1082          21 :         if (os_strcmp(pos, "P2P-CR") == 0) {
    1083          10 :                 return wpas_ctrl_nfc_get_handover_sel_p2p(
    1084             :                         wpa_s, reply, max_len, ndef, 0);
    1085             :         }
    1086             : 
    1087          11 :         if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
    1088           9 :                 return wpas_ctrl_nfc_get_handover_sel_p2p(
    1089             :                         wpa_s, reply, max_len, ndef, 1);
    1090             :         }
    1091             : #endif /* CONFIG_P2P */
    1092             : 
    1093           2 :         return -1;
    1094             : }
    1095             : 
    1096             : 
    1097          40 : static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
    1098             :                                          char *cmd)
    1099             : {
    1100             :         size_t len;
    1101             :         struct wpabuf *req, *sel;
    1102             :         int ret;
    1103             :         char *pos, *role, *type, *pos2;
    1104             : #ifdef CONFIG_P2P
    1105             :         char *freq;
    1106          40 :         int forced_freq = 0;
    1107             : 
    1108          40 :         freq = strstr(cmd, " freq=");
    1109          40 :         if (freq) {
    1110           1 :                 *freq = '\0';
    1111           1 :                 freq += 6;
    1112           1 :                 forced_freq = atoi(freq);
    1113             :         }
    1114             : #endif /* CONFIG_P2P */
    1115             : 
    1116          40 :         role = cmd;
    1117          40 :         pos = os_strchr(role, ' ');
    1118          40 :         if (pos == NULL) {
    1119           2 :                 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
    1120           2 :                 return -1;
    1121             :         }
    1122          38 :         *pos++ = '\0';
    1123             : 
    1124          38 :         type = pos;
    1125          38 :         pos = os_strchr(type, ' ');
    1126          38 :         if (pos == NULL) {
    1127           1 :                 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
    1128           1 :                 return -1;
    1129             :         }
    1130          37 :         *pos++ = '\0';
    1131             : 
    1132          37 :         pos2 = os_strchr(pos, ' ');
    1133          37 :         if (pos2 == NULL) {
    1134           1 :                 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
    1135           1 :                 return -1;
    1136             :         }
    1137          36 :         *pos2++ = '\0';
    1138             : 
    1139          36 :         len = os_strlen(pos);
    1140          36 :         if (len & 0x01) {
    1141           1 :                 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
    1142           1 :                 return -1;
    1143             :         }
    1144          35 :         len /= 2;
    1145             : 
    1146          35 :         req = wpabuf_alloc(len);
    1147          35 :         if (req == NULL) {
    1148           0 :                 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
    1149           0 :                 return -1;
    1150             :         }
    1151          35 :         if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
    1152           1 :                 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
    1153           1 :                 wpabuf_free(req);
    1154           1 :                 return -1;
    1155             :         }
    1156             : 
    1157          34 :         len = os_strlen(pos2);
    1158          34 :         if (len & 0x01) {
    1159           1 :                 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
    1160           1 :                 wpabuf_free(req);
    1161           1 :                 return -1;
    1162             :         }
    1163          33 :         len /= 2;
    1164             : 
    1165          33 :         sel = wpabuf_alloc(len);
    1166          33 :         if (sel == NULL) {
    1167           0 :                 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
    1168           0 :                 wpabuf_free(req);
    1169           0 :                 return -1;
    1170             :         }
    1171          33 :         if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
    1172           1 :                 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
    1173           1 :                 wpabuf_free(req);
    1174           1 :                 wpabuf_free(sel);
    1175           1 :                 return -1;
    1176             :         }
    1177             : 
    1178          64 :         wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
    1179          64 :                    role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
    1180             : 
    1181          32 :         if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
    1182          11 :                 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
    1183             : #ifdef CONFIG_AP
    1184          21 :         } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
    1185             :         {
    1186           4 :                 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
    1187           8 :                 if (ret < 0)
    1188           3 :                         ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
    1189             : #endif /* CONFIG_AP */
    1190             : #ifdef CONFIG_P2P
    1191          17 :         } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
    1192             :         {
    1193           8 :                 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
    1194           9 :         } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
    1195             :         {
    1196           8 :                 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
    1197             :                                                    forced_freq);
    1198             : #endif /* CONFIG_P2P */
    1199             :         } else {
    1200           1 :                 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
    1201             :                            "reported: role=%s type=%s", role, type);
    1202           1 :                 ret = -1;
    1203             :         }
    1204          32 :         wpabuf_free(req);
    1205          32 :         wpabuf_free(sel);
    1206             : 
    1207          32 :         if (ret)
    1208           1 :                 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
    1209             : 
    1210          32 :         return ret;
    1211             : }
    1212             : 
    1213             : #endif /* CONFIG_WPS_NFC */
    1214             : 
    1215             : 
    1216          43 : static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
    1217             :                                              char *cmd)
    1218             : {
    1219             :         u8 bssid[ETH_ALEN];
    1220             :         char *pin;
    1221             :         char *new_ssid;
    1222             :         char *new_auth;
    1223             :         char *new_encr;
    1224             :         char *new_key;
    1225             :         struct wps_new_ap_settings ap;
    1226             : 
    1227          43 :         pin = os_strchr(cmd, ' ');
    1228          43 :         if (pin == NULL)
    1229           1 :                 return -1;
    1230          42 :         *pin++ = '\0';
    1231             : 
    1232          42 :         if (hwaddr_aton(cmd, bssid)) {
    1233           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
    1234             :                            cmd);
    1235           1 :                 return -1;
    1236             :         }
    1237             : 
    1238          41 :         new_ssid = os_strchr(pin, ' ');
    1239          41 :         if (new_ssid == NULL)
    1240          22 :                 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
    1241          19 :         *new_ssid++ = '\0';
    1242             : 
    1243          19 :         new_auth = os_strchr(new_ssid, ' ');
    1244          19 :         if (new_auth == NULL)
    1245           1 :                 return -1;
    1246          18 :         *new_auth++ = '\0';
    1247             : 
    1248          18 :         new_encr = os_strchr(new_auth, ' ');
    1249          18 :         if (new_encr == NULL)
    1250           1 :                 return -1;
    1251          17 :         *new_encr++ = '\0';
    1252             : 
    1253          17 :         new_key = os_strchr(new_encr, ' ');
    1254          17 :         if (new_key == NULL)
    1255           1 :                 return -1;
    1256          16 :         *new_key++ = '\0';
    1257             : 
    1258          16 :         os_memset(&ap, 0, sizeof(ap));
    1259          16 :         ap.ssid_hex = new_ssid;
    1260          16 :         ap.auth = new_auth;
    1261          16 :         ap.encr = new_encr;
    1262          16 :         ap.key_hex = new_key;
    1263          16 :         return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
    1264             : }
    1265             : 
    1266             : 
    1267             : #ifdef CONFIG_AP
    1268           7 : static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
    1269             :                                                 char *cmd, char *buf,
    1270             :                                                 size_t buflen)
    1271             : {
    1272           7 :         int timeout = 300;
    1273             :         char *pos;
    1274             :         const char *pin_txt;
    1275             : 
    1276           7 :         if (!wpa_s->ap_iface)
    1277           1 :                 return -1;
    1278             : 
    1279           6 :         pos = os_strchr(cmd, ' ');
    1280           6 :         if (pos)
    1281           2 :                 *pos++ = '\0';
    1282             : 
    1283           6 :         if (os_strcmp(cmd, "disable") == 0) {
    1284           1 :                 wpas_wps_ap_pin_disable(wpa_s);
    1285           1 :                 return os_snprintf(buf, buflen, "OK\n");
    1286             :         }
    1287             : 
    1288           5 :         if (os_strcmp(cmd, "random") == 0) {
    1289           1 :                 if (pos)
    1290           0 :                         timeout = atoi(pos);
    1291           1 :                 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
    1292           1 :                 if (pin_txt == NULL)
    1293           0 :                         return -1;
    1294           1 :                 return os_snprintf(buf, buflen, "%s", pin_txt);
    1295             :         }
    1296             : 
    1297           4 :         if (os_strcmp(cmd, "get") == 0) {
    1298           2 :                 pin_txt = wpas_wps_ap_pin_get(wpa_s);
    1299           2 :                 if (pin_txt == NULL)
    1300           1 :                         return -1;
    1301           1 :                 return os_snprintf(buf, buflen, "%s", pin_txt);
    1302             :         }
    1303             : 
    1304           2 :         if (os_strcmp(cmd, "set") == 0) {
    1305             :                 char *pin;
    1306           2 :                 if (pos == NULL)
    1307           0 :                         return -1;
    1308           2 :                 pin = pos;
    1309           2 :                 pos = os_strchr(pos, ' ');
    1310           2 :                 if (pos) {
    1311           1 :                         *pos++ = '\0';
    1312           1 :                         timeout = atoi(pos);
    1313             :                 }
    1314           2 :                 if (os_strlen(pin) > buflen)
    1315           0 :                         return -1;
    1316           2 :                 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
    1317           0 :                         return -1;
    1318           2 :                 return os_snprintf(buf, buflen, "%s", pin);
    1319             :         }
    1320             : 
    1321           0 :         return -1;
    1322             : }
    1323             : #endif /* CONFIG_AP */
    1324             : 
    1325             : 
    1326             : #ifdef CONFIG_WPS_ER
    1327           5 : static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
    1328             :                                                 char *cmd)
    1329             : {
    1330           5 :         char *uuid = cmd, *pin, *pos;
    1331           5 :         u8 addr_buf[ETH_ALEN], *addr = NULL;
    1332           5 :         pin = os_strchr(uuid, ' ');
    1333           5 :         if (pin == NULL)
    1334           1 :                 return -1;
    1335           4 :         *pin++ = '\0';
    1336           4 :         pos = os_strchr(pin, ' ');
    1337           4 :         if (pos) {
    1338           4 :                 *pos++ = '\0';
    1339           4 :                 if (hwaddr_aton(pos, addr_buf) == 0)
    1340           4 :                         addr = addr_buf;
    1341             :         }
    1342           4 :         return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
    1343             : }
    1344             : 
    1345             : 
    1346           2 : static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
    1347             :                                                   char *cmd)
    1348             : {
    1349           2 :         char *uuid = cmd, *pin;
    1350           2 :         pin = os_strchr(uuid, ' ');
    1351           2 :         if (pin == NULL)
    1352           1 :                 return -1;
    1353           1 :         *pin++ = '\0';
    1354           1 :         return wpas_wps_er_learn(wpa_s, uuid, pin);
    1355             : }
    1356             : 
    1357             : 
    1358           9 : static int wpa_supplicant_ctrl_iface_wps_er_set_config(
    1359             :         struct wpa_supplicant *wpa_s, char *cmd)
    1360             : {
    1361           9 :         char *uuid = cmd, *id;
    1362           9 :         id = os_strchr(uuid, ' ');
    1363           9 :         if (id == NULL)
    1364           1 :                 return -1;
    1365           8 :         *id++ = '\0';
    1366           8 :         return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
    1367             : }
    1368             : 
    1369             : 
    1370           6 : static int wpa_supplicant_ctrl_iface_wps_er_config(
    1371             :         struct wpa_supplicant *wpa_s, char *cmd)
    1372             : {
    1373             :         char *pin;
    1374             :         char *new_ssid;
    1375             :         char *new_auth;
    1376             :         char *new_encr;
    1377             :         char *new_key;
    1378             :         struct wps_new_ap_settings ap;
    1379             : 
    1380           6 :         pin = os_strchr(cmd, ' ');
    1381           6 :         if (pin == NULL)
    1382           1 :                 return -1;
    1383           5 :         *pin++ = '\0';
    1384             : 
    1385           5 :         new_ssid = os_strchr(pin, ' ');
    1386           5 :         if (new_ssid == NULL)
    1387           1 :                 return -1;
    1388           4 :         *new_ssid++ = '\0';
    1389             : 
    1390           4 :         new_auth = os_strchr(new_ssid, ' ');
    1391           4 :         if (new_auth == NULL)
    1392           1 :                 return -1;
    1393           3 :         *new_auth++ = '\0';
    1394             : 
    1395           3 :         new_encr = os_strchr(new_auth, ' ');
    1396           3 :         if (new_encr == NULL)
    1397           1 :                 return -1;
    1398           2 :         *new_encr++ = '\0';
    1399             : 
    1400           2 :         new_key = os_strchr(new_encr, ' ');
    1401           2 :         if (new_key == NULL)
    1402           1 :                 return -1;
    1403           1 :         *new_key++ = '\0';
    1404             : 
    1405           1 :         os_memset(&ap, 0, sizeof(ap));
    1406           1 :         ap.ssid_hex = new_ssid;
    1407           1 :         ap.auth = new_auth;
    1408           1 :         ap.encr = new_encr;
    1409           1 :         ap.key_hex = new_key;
    1410           1 :         return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
    1411             : }
    1412             : 
    1413             : 
    1414             : #ifdef CONFIG_WPS_NFC
    1415           4 : static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
    1416             :         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
    1417             : {
    1418             :         int ndef;
    1419             :         struct wpabuf *buf;
    1420             :         int res;
    1421             :         char *uuid;
    1422             : 
    1423           4 :         uuid = os_strchr(cmd, ' ');
    1424           4 :         if (uuid == NULL)
    1425           1 :                 return -1;
    1426           3 :         *uuid++ = '\0';
    1427             : 
    1428           3 :         if (os_strcmp(cmd, "WPS") == 0)
    1429           0 :                 ndef = 0;
    1430           3 :         else if (os_strcmp(cmd, "NDEF") == 0)
    1431           2 :                 ndef = 1;
    1432             :         else
    1433           1 :                 return -1;
    1434             : 
    1435           2 :         buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
    1436           2 :         if (buf == NULL)
    1437           1 :                 return -1;
    1438             : 
    1439           1 :         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
    1440             :                                          wpabuf_len(buf));
    1441           1 :         reply[res++] = '\n';
    1442           1 :         reply[res] = '\0';
    1443             : 
    1444           1 :         wpabuf_free(buf);
    1445             : 
    1446           1 :         return res;
    1447             : }
    1448             : #endif /* CONFIG_WPS_NFC */
    1449             : #endif /* CONFIG_WPS_ER */
    1450             : 
    1451             : #endif /* CONFIG_WPS */
    1452             : 
    1453             : 
    1454             : #ifdef CONFIG_IBSS_RSN
    1455           1 : static int wpa_supplicant_ctrl_iface_ibss_rsn(
    1456             :         struct wpa_supplicant *wpa_s, char *addr)
    1457             : {
    1458             :         u8 peer[ETH_ALEN];
    1459             : 
    1460           1 :         if (hwaddr_aton(addr, peer)) {
    1461           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
    1462             :                            "address '%s'", addr);
    1463           1 :                 return -1;
    1464             :         }
    1465             : 
    1466           0 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
    1467           0 :                    MAC2STR(peer));
    1468             : 
    1469           0 :         return ibss_rsn_start(wpa_s->ibss_rsn, peer);
    1470             : }
    1471             : #endif /* CONFIG_IBSS_RSN */
    1472             : 
    1473             : 
    1474          14 : static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
    1475             :                                               char *rsp)
    1476             : {
    1477             : #ifdef IEEE8021X_EAPOL
    1478             :         char *pos, *id_pos;
    1479             :         int id;
    1480             :         struct wpa_ssid *ssid;
    1481             : 
    1482          14 :         pos = os_strchr(rsp, '-');
    1483          14 :         if (pos == NULL)
    1484           0 :                 return -1;
    1485          14 :         *pos++ = '\0';
    1486          14 :         id_pos = pos;
    1487          14 :         pos = os_strchr(pos, ':');
    1488          14 :         if (pos == NULL)
    1489           0 :                 return -1;
    1490          14 :         *pos++ = '\0';
    1491          14 :         id = atoi(id_pos);
    1492          14 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
    1493          14 :         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
    1494             :                               (u8 *) pos, os_strlen(pos));
    1495             : 
    1496          14 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    1497          14 :         if (ssid == NULL) {
    1498           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
    1499             :                            "to update", id);
    1500           0 :                 return -1;
    1501             :         }
    1502             : 
    1503          14 :         return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
    1504             :                                                          pos);
    1505             : #else /* IEEE8021X_EAPOL */
    1506             :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
    1507             :         return -1;
    1508             : #endif /* IEEE8021X_EAPOL */
    1509             : }
    1510             : 
    1511             : 
    1512        2661 : static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
    1513             :                                             const char *params,
    1514             :                                             char *buf, size_t buflen)
    1515             : {
    1516             :         char *pos, *end, tmp[30];
    1517             :         int res, verbose, wps, ret;
    1518             : #ifdef CONFIG_HS20
    1519             :         const u8 *hs20;
    1520             : #endif /* CONFIG_HS20 */
    1521             : 
    1522        2661 :         if (os_strcmp(params, "-DRIVER") == 0)
    1523        1906 :                 return wpa_drv_status(wpa_s, buf, buflen);
    1524         755 :         verbose = os_strcmp(params, "-VERBOSE") == 0;
    1525         755 :         wps = os_strcmp(params, "-WPS") == 0;
    1526         755 :         pos = buf;
    1527         755 :         end = buf + buflen;
    1528         755 :         if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
    1529         502 :                 struct wpa_ssid *ssid = wpa_s->current_ssid;
    1530        3012 :                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
    1531        3012 :                                   MAC2STR(wpa_s->bssid));
    1532         502 :                 if (ret < 0 || ret >= end - pos)
    1533           0 :                         return pos - buf;
    1534         502 :                 pos += ret;
    1535         502 :                 if (ssid) {
    1536         502 :                         u8 *_ssid = ssid->ssid;
    1537         502 :                         size_t ssid_len = ssid->ssid_len;
    1538             :                         u8 ssid_buf[MAX_SSID_LEN];
    1539         502 :                         if (ssid_len == 0) {
    1540           1 :                                 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
    1541           1 :                                 if (_res < 0)
    1542           0 :                                         ssid_len = 0;
    1543             :                                 else
    1544           1 :                                         ssid_len = _res;
    1545           1 :                                 _ssid = ssid_buf;
    1546             :                         }
    1547         502 :                         ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
    1548             :                                           wpa_ssid_txt(_ssid, ssid_len),
    1549             :                                           ssid->id);
    1550         502 :                         if (ret < 0 || ret >= end - pos)
    1551           0 :                                 return pos - buf;
    1552         502 :                         pos += ret;
    1553             : 
    1554         503 :                         if (wps && ssid->passphrase &&
    1555           2 :                             wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
    1556           2 :                             (ssid->mode == WPAS_MODE_AP ||
    1557           1 :                              ssid->mode == WPAS_MODE_P2P_GO)) {
    1558           1 :                                 ret = os_snprintf(pos, end - pos,
    1559             :                                                   "passphrase=%s\n",
    1560             :                                                   ssid->passphrase);
    1561           1 :                                 if (ret < 0 || ret >= end - pos)
    1562           0 :                                         return pos - buf;
    1563           1 :                                 pos += ret;
    1564             :                         }
    1565         502 :                         if (ssid->id_str) {
    1566           1 :                                 ret = os_snprintf(pos, end - pos,
    1567             :                                                   "id_str=%s\n",
    1568             :                                                   ssid->id_str);
    1569           1 :                                 if (ret < 0 || ret >= end - pos)
    1570           0 :                                         return pos - buf;
    1571           1 :                                 pos += ret;
    1572             :                         }
    1573             : 
    1574         502 :                         switch (ssid->mode) {
    1575             :                         case WPAS_MODE_INFRA:
    1576         448 :                                 ret = os_snprintf(pos, end - pos,
    1577             :                                                   "mode=station\n");
    1578         448 :                                 break;
    1579             :                         case WPAS_MODE_IBSS:
    1580          12 :                                 ret = os_snprintf(pos, end - pos,
    1581             :                                                   "mode=IBSS\n");
    1582          12 :                                 break;
    1583             :                         case WPAS_MODE_AP:
    1584           3 :                                 ret = os_snprintf(pos, end - pos,
    1585             :                                                   "mode=AP\n");
    1586           3 :                                 break;
    1587             :                         case WPAS_MODE_P2P_GO:
    1588          39 :                                 ret = os_snprintf(pos, end - pos,
    1589             :                                                   "mode=P2P GO\n");
    1590          39 :                                 break;
    1591             :                         case WPAS_MODE_P2P_GROUP_FORMATION:
    1592           0 :                                 ret = os_snprintf(pos, end - pos,
    1593             :                                                   "mode=P2P GO - group "
    1594             :                                                   "formation\n");
    1595           0 :                                 break;
    1596             :                         default:
    1597           0 :                                 ret = 0;
    1598           0 :                                 break;
    1599             :                         }
    1600         502 :                         if (ret < 0 || ret >= end - pos)
    1601           0 :                                 return pos - buf;
    1602         502 :                         pos += ret;
    1603             :                 }
    1604             : 
    1605             : #ifdef CONFIG_AP
    1606         502 :                 if (wpa_s->ap_iface) {
    1607          42 :                         pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
    1608          42 :                                                             end - pos,
    1609             :                                                             verbose);
    1610             :                 } else
    1611             : #endif /* CONFIG_AP */
    1612         460 :                 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
    1613             :         }
    1614             : #ifdef CONFIG_SAE
    1615        1257 :         if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
    1616             : #ifdef CONFIG_AP
    1617         962 :             !wpa_s->ap_iface &&
    1618             : #endif /* CONFIG_AP */
    1619         460 :             wpa_s->sme.sae.state == SAE_ACCEPTED) {
    1620          16 :                 ret = os_snprintf(pos, end - pos, "sae_group=%d\n",
    1621             :                                   wpa_s->sme.sae.group);
    1622          16 :                 if (ret < 0 || ret >= end - pos)
    1623           0 :                         return pos - buf;
    1624          16 :                 pos += ret;
    1625             :         }
    1626             : #endif /* CONFIG_SAE */
    1627         755 :         ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
    1628             :                           wpa_supplicant_state_txt(wpa_s->wpa_state));
    1629         755 :         if (ret < 0 || ret >= end - pos)
    1630           0 :                 return pos - buf;
    1631         755 :         pos += ret;
    1632             : 
    1633        1510 :         if (wpa_s->l2 &&
    1634         755 :             l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
    1635           0 :                 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
    1636           0 :                 if (ret < 0 || ret >= end - pos)
    1637           0 :                         return pos - buf;
    1638           0 :                 pos += ret;
    1639             :         }
    1640             : 
    1641             : #ifdef CONFIG_P2P
    1642         755 :         if (wpa_s->global->p2p) {
    1643        4530 :                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
    1644        4530 :                                   "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
    1645         755 :                 if (ret < 0 || ret >= end - pos)
    1646           0 :                         return pos - buf;
    1647         755 :                 pos += ret;
    1648             :         }
    1649             : #endif /* CONFIG_P2P */
    1650             : 
    1651        4530 :         ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
    1652        4530 :                           MAC2STR(wpa_s->own_addr));
    1653         755 :         if (ret < 0 || ret >= end - pos)
    1654           0 :                 return pos - buf;
    1655         755 :         pos += ret;
    1656             : 
    1657             : #ifdef CONFIG_HS20
    1658        1203 :         if (wpa_s->current_bss &&
    1659         448 :             (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
    1660          42 :                                           HS20_IE_VENDOR_TYPE)) &&
    1661          84 :             wpa_s->wpa_proto == WPA_PROTO_RSN &&
    1662          42 :             wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
    1663          42 :                 int release = 1;
    1664          42 :                 if (hs20[1] >= 5) {
    1665          42 :                         u8 rel_num = (hs20[6] & 0xf0) >> 4;
    1666          42 :                         release = rel_num + 1;
    1667             :                 }
    1668          42 :                 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
    1669          42 :                 if (ret < 0 || ret >= end - pos)
    1670           0 :                         return pos - buf;
    1671          42 :                 pos += ret;
    1672             :         }
    1673             : 
    1674         755 :         if (wpa_s->current_ssid) {
    1675             :                 struct wpa_cred *cred;
    1676             :                 char *type;
    1677             : 
    1678        1022 :                 for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
    1679             :                         size_t i;
    1680             : 
    1681          45 :                         if (wpa_s->current_ssid->parent_cred != cred)
    1682           3 :                                 continue;
    1683             : 
    1684          42 :                         if (cred->provisioning_sp) {
    1685           6 :                                 ret = os_snprintf(pos, end - pos,
    1686             :                                                   "provisioning_sp=%s\n",
    1687             :                                                   cred->provisioning_sp);
    1688           6 :                                 if (ret < 0 || ret >= end - pos)
    1689           0 :                                         return pos - buf;
    1690           6 :                                 pos += ret;
    1691             :                         }
    1692             : 
    1693          42 :                         if (!cred->domain)
    1694          21 :                                 goto no_domain;
    1695             : 
    1696          21 :                         i = 0;
    1697          21 :                         if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
    1698          21 :                                 struct wpabuf *names =
    1699          21 :                                         wpa_s->current_bss->anqp->domain_name;
    1700          22 :                                 for (i = 0; names && i < cred->num_domain; i++)
    1701             :                                 {
    1702          17 :                                         if (domain_name_list_contains(
    1703          17 :                                                     names, cred->domain[i], 1))
    1704          16 :                                                 break;
    1705             :                                 }
    1706          21 :                                 if (i == cred->num_domain)
    1707           1 :                                         i = 0; /* show first entry by default */
    1708             :                         }
    1709          21 :                         ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
    1710          21 :                                           cred->domain[i]);
    1711          21 :                         if (ret < 0 || ret >= end - pos)
    1712           0 :                                 return pos - buf;
    1713          21 :                         pos += ret;
    1714             : 
    1715             :                 no_domain:
    1716          84 :                         if (wpa_s->current_bss == NULL ||
    1717          42 :                             wpa_s->current_bss->anqp == NULL)
    1718           0 :                                 res = -1;
    1719             :                         else
    1720          42 :                                 res = interworking_home_sp_cred(
    1721             :                                         wpa_s, cred,
    1722          42 :                                         wpa_s->current_bss->anqp->domain_name);
    1723          42 :                         if (res > 0)
    1724          20 :                                 type = "home";
    1725          22 :                         else if (res == 0)
    1726           3 :                                 type = "roaming";
    1727             :                         else
    1728          19 :                                 type = "unknown";
    1729             : 
    1730          42 :                         ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
    1731          42 :                         if (ret < 0 || ret >= end - pos)
    1732           0 :                                 return pos - buf;
    1733          42 :                         pos += ret;
    1734             : 
    1735          42 :                         break;
    1736             :                 }
    1737             :         }
    1738             : #endif /* CONFIG_HS20 */
    1739             : 
    1740        1317 :         if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
    1741         562 :             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
    1742         193 :                 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
    1743             :                                           verbose);
    1744         193 :                 if (res >= 0)
    1745         193 :                         pos += res;
    1746             :         }
    1747             : 
    1748         755 :         res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
    1749         755 :         if (res >= 0)
    1750         755 :                 pos += res;
    1751             : 
    1752             : #ifdef CONFIG_WPS
    1753             :         {
    1754             :                 char uuid_str[100];
    1755         755 :                 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
    1756         755 :                 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
    1757         755 :                 if (ret < 0 || ret >= end - pos)
    1758           0 :                         return pos - buf;
    1759         755 :                 pos += ret;
    1760             :         }
    1761             : #endif /* CONFIG_WPS */
    1762             : 
    1763             : #ifdef ANDROID
    1764             :         wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
    1765             :                      "id=%d state=%d BSSID=" MACSTR " SSID=%s",
    1766             :                      wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
    1767             :                      wpa_s->wpa_state,
    1768             :                      MAC2STR(wpa_s->bssid),
    1769             :                      wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
    1770             :                      wpa_ssid_txt(wpa_s->current_ssid->ssid,
    1771             :                                   wpa_s->current_ssid->ssid_len) : "");
    1772             :         if (wpa_s->wpa_state == WPA_COMPLETED) {
    1773             :                 struct wpa_ssid *ssid = wpa_s->current_ssid;
    1774             :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
    1775             :                              "- connection to " MACSTR
    1776             :                              " completed %s [id=%d id_str=%s]",
    1777             :                              MAC2STR(wpa_s->bssid), "(auth)",
    1778             :                              ssid ? ssid->id : -1,
    1779             :                              ssid && ssid->id_str ? ssid->id_str : "");
    1780             :         }
    1781             : #endif /* ANDROID */
    1782             : 
    1783         755 :         return pos - buf;
    1784             : }
    1785             : 
    1786             : 
    1787           4 : static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
    1788             :                                            char *cmd)
    1789             : {
    1790             :         char *pos;
    1791             :         int id;
    1792             :         struct wpa_ssid *ssid;
    1793             :         u8 bssid[ETH_ALEN];
    1794             : 
    1795             :         /* cmd: "<network id> <BSSID>" */
    1796           4 :         pos = os_strchr(cmd, ' ');
    1797           4 :         if (pos == NULL)
    1798           0 :                 return -1;
    1799           4 :         *pos++ = '\0';
    1800           4 :         id = atoi(cmd);
    1801           4 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
    1802           4 :         if (hwaddr_aton(pos, bssid)) {
    1803           1 :                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
    1804           1 :                 return -1;
    1805             :         }
    1806             : 
    1807           3 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    1808           3 :         if (ssid == NULL) {
    1809           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
    1810             :                            "to update", id);
    1811           1 :                 return -1;
    1812             :         }
    1813             : 
    1814           2 :         os_memcpy(ssid->bssid, bssid, ETH_ALEN);
    1815           2 :         ssid->bssid_set = !is_zero_ether_addr(bssid);
    1816             : 
    1817           2 :         return 0;
    1818             : }
    1819             : 
    1820             : 
    1821          11 : static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
    1822             :                                                char *cmd, char *buf,
    1823             :                                                size_t buflen)
    1824             : {
    1825             :         u8 bssid[ETH_ALEN];
    1826             :         struct wpa_blacklist *e;
    1827             :         char *pos, *end;
    1828             :         int ret;
    1829             : 
    1830             :         /* cmd: "BLACKLIST [<BSSID>]" */
    1831          11 :         if (*cmd == '\0') {
    1832           5 :                 pos = buf;
    1833           5 :                 end = buf + buflen;
    1834           5 :                 e = wpa_s->blacklist;
    1835          15 :                 while (e) {
    1836          30 :                         ret = os_snprintf(pos, end - pos, MACSTR "\n",
    1837          30 :                                           MAC2STR(e->bssid));
    1838           5 :                         if (ret < 0 || ret >= end - pos)
    1839           0 :                                 return pos - buf;
    1840           5 :                         pos += ret;
    1841           5 :                         e = e->next;
    1842             :                 }
    1843           5 :                 return pos - buf;
    1844             :         }
    1845             : 
    1846           6 :         cmd++;
    1847           6 :         if (os_strncmp(cmd, "clear", 5) == 0) {
    1848           2 :                 wpa_blacklist_clear(wpa_s);
    1849           2 :                 os_memcpy(buf, "OK\n", 3);
    1850           2 :                 return 3;
    1851             :         }
    1852             : 
    1853           4 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
    1854           4 :         if (hwaddr_aton(cmd, bssid)) {
    1855           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
    1856           1 :                 return -1;
    1857             :         }
    1858             : 
    1859             :         /*
    1860             :          * Add the BSSID twice, so its count will be 2, causing it to be
    1861             :          * skipped when processing scan results.
    1862             :          */
    1863           3 :         ret = wpa_blacklist_add(wpa_s, bssid);
    1864           3 :         if (ret < 0)
    1865           0 :                 return -1;
    1866           3 :         ret = wpa_blacklist_add(wpa_s, bssid);
    1867           3 :         if (ret < 0)
    1868           0 :                 return -1;
    1869           3 :         os_memcpy(buf, "OK\n", 3);
    1870           3 :         return 3;
    1871             : }
    1872             : 
    1873             : 
    1874          10 : static const char * debug_level_str(int level)
    1875             : {
    1876          10 :         switch (level) {
    1877             :         case MSG_EXCESSIVE:
    1878           1 :                 return "EXCESSIVE";
    1879             :         case MSG_MSGDUMP:
    1880           5 :                 return "MSGDUMP";
    1881             :         case MSG_DEBUG:
    1882           1 :                 return "DEBUG";
    1883             :         case MSG_INFO:
    1884           1 :                 return "INFO";
    1885             :         case MSG_WARNING:
    1886           1 :                 return "WARNING";
    1887             :         case MSG_ERROR:
    1888           1 :                 return "ERROR";
    1889             :         default:
    1890           0 :                 return "?";
    1891             :         }
    1892             : }
    1893             : 
    1894             : 
    1895          10 : static int str_to_debug_level(const char *s)
    1896             : {
    1897          10 :         if (os_strcasecmp(s, "EXCESSIVE") == 0)
    1898           1 :                 return MSG_EXCESSIVE;
    1899           9 :         if (os_strcasecmp(s, "MSGDUMP") == 0)
    1900           4 :                 return MSG_MSGDUMP;
    1901           5 :         if (os_strcasecmp(s, "DEBUG") == 0)
    1902           1 :                 return MSG_DEBUG;
    1903           4 :         if (os_strcasecmp(s, "INFO") == 0)
    1904           1 :                 return MSG_INFO;
    1905           3 :         if (os_strcasecmp(s, "WARNING") == 0)
    1906           1 :                 return MSG_WARNING;
    1907           2 :         if (os_strcasecmp(s, "ERROR") == 0)
    1908           1 :                 return MSG_ERROR;
    1909           1 :         return -1;
    1910             : }
    1911             : 
    1912             : 
    1913          20 : static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
    1914             :                                                char *cmd, char *buf,
    1915             :                                                size_t buflen)
    1916             : {
    1917             :         char *pos, *end, *stamp;
    1918             :         int ret;
    1919             : 
    1920          20 :         if (cmd == NULL) {
    1921           0 :                 return -1;
    1922             :         }
    1923             : 
    1924             :         /* cmd: "LOG_LEVEL [<level>]" */
    1925          20 :         if (*cmd == '\0') {
    1926          10 :                 pos = buf;
    1927          10 :                 end = buf + buflen;
    1928          10 :                 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
    1929             :                                   "Timestamp: %d\n",
    1930             :                                   debug_level_str(wpa_debug_level),
    1931             :                                   wpa_debug_timestamp);
    1932          10 :                 if (ret < 0 || ret >= end - pos)
    1933           0 :                         ret = 0;
    1934             : 
    1935          10 :                 return ret;
    1936             :         }
    1937             : 
    1938          33 :         while (*cmd == ' ')
    1939          13 :                 cmd++;
    1940             : 
    1941          10 :         stamp = os_strchr(cmd, ' ');
    1942          10 :         if (stamp) {
    1943           3 :                 *stamp++ = '\0';
    1944           9 :                 while (*stamp == ' ') {
    1945           3 :                         stamp++;
    1946             :                 }
    1947             :         }
    1948             : 
    1949          10 :         if (cmd && os_strlen(cmd)) {
    1950          10 :                 int level = str_to_debug_level(cmd);
    1951          10 :                 if (level < 0)
    1952           1 :                         return -1;
    1953           9 :                 wpa_debug_level = level;
    1954             :         }
    1955             : 
    1956           9 :         if (stamp && os_strlen(stamp))
    1957           3 :                 wpa_debug_timestamp = atoi(stamp);
    1958             : 
    1959           9 :         os_memcpy(buf, "OK\n", 3);
    1960           9 :         return 3;
    1961             : }
    1962             : 
    1963             : 
    1964          12 : static int wpa_supplicant_ctrl_iface_list_networks(
    1965             :         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
    1966             : {
    1967             :         char *pos, *end;
    1968             :         struct wpa_ssid *ssid;
    1969             :         int ret;
    1970             : 
    1971          12 :         pos = buf;
    1972          12 :         end = buf + buflen;
    1973          12 :         ret = os_snprintf(pos, end - pos,
    1974             :                           "network id / ssid / bssid / flags\n");
    1975          12 :         if (ret < 0 || ret >= end - pos)
    1976           0 :                 return pos - buf;
    1977          12 :         pos += ret;
    1978             : 
    1979          12 :         ssid = wpa_s->conf->ssid;
    1980          38 :         while (ssid) {
    1981          28 :                 ret = os_snprintf(pos, end - pos, "%d\t%s",
    1982             :                                   ssid->id,
    1983          14 :                                   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
    1984          14 :                 if (ret < 0 || ret >= end - pos)
    1985           0 :                         return pos - buf;
    1986          14 :                 pos += ret;
    1987          14 :                 if (ssid->bssid_set) {
    1988          42 :                         ret = os_snprintf(pos, end - pos, "\t" MACSTR,
    1989          42 :                                           MAC2STR(ssid->bssid));
    1990             :                 } else {
    1991           7 :                         ret = os_snprintf(pos, end - pos, "\tany");
    1992             :                 }
    1993          14 :                 if (ret < 0 || ret >= end - pos)
    1994           0 :                         return pos - buf;
    1995          14 :                 pos += ret;
    1996          56 :                 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
    1997          14 :                                   ssid == wpa_s->current_ssid ?
    1998             :                                   "[CURRENT]" : "",
    1999          14 :                                   ssid->disabled ? "[DISABLED]" : "",
    2000          14 :                                   ssid->disabled_until.sec ?
    2001             :                                   "[TEMP-DISABLED]" : "",
    2002          14 :                                   ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
    2003             :                                   "");
    2004          14 :                 if (ret < 0 || ret >= end - pos)
    2005           0 :                         return pos - buf;
    2006          14 :                 pos += ret;
    2007          14 :                 ret = os_snprintf(pos, end - pos, "\n");
    2008          14 :                 if (ret < 0 || ret >= end - pos)
    2009           0 :                         return pos - buf;
    2010          14 :                 pos += ret;
    2011             : 
    2012          14 :                 ssid = ssid->next;
    2013             :         }
    2014             : 
    2015          12 :         return pos - buf;
    2016             : }
    2017             : 
    2018             : 
    2019         153 : static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
    2020             : {
    2021             :         int ret;
    2022         153 :         ret = os_snprintf(pos, end - pos, "-");
    2023         153 :         if (ret < 0 || ret >= end - pos)
    2024           0 :                 return pos;
    2025         153 :         pos += ret;
    2026         153 :         ret = wpa_write_ciphers(pos, end, cipher, "+");
    2027         153 :         if (ret < 0)
    2028           0 :                 return pos;
    2029         153 :         pos += ret;
    2030         153 :         return pos;
    2031             : }
    2032             : 
    2033             : 
    2034         153 : static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
    2035             :                                     const u8 *ie, size_t ie_len)
    2036             : {
    2037             :         struct wpa_ie_data data;
    2038             :         char *start;
    2039             :         int ret;
    2040             : 
    2041         153 :         ret = os_snprintf(pos, end - pos, "[%s-", proto);
    2042         153 :         if (ret < 0 || ret >= end - pos)
    2043           0 :                 return pos;
    2044         153 :         pos += ret;
    2045             : 
    2046         153 :         if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
    2047           0 :                 ret = os_snprintf(pos, end - pos, "?]");
    2048           0 :                 if (ret < 0 || ret >= end - pos)
    2049           0 :                         return pos;
    2050           0 :                 pos += ret;
    2051           0 :                 return pos;
    2052             :         }
    2053             : 
    2054         153 :         start = pos;
    2055         153 :         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
    2056          94 :                 ret = os_snprintf(pos, end - pos, "%sEAP",
    2057             :                                   pos == start ? "" : "+");
    2058          94 :                 if (ret < 0 || ret >= end - pos)
    2059           0 :                         return pos;
    2060          94 :                 pos += ret;
    2061             :         }
    2062         153 :         if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
    2063          39 :                 ret = os_snprintf(pos, end - pos, "%sPSK",
    2064             :                                   pos == start ? "" : "+");
    2065          39 :                 if (ret < 0 || ret >= end - pos)
    2066           0 :                         return pos;
    2067          39 :                 pos += ret;
    2068             :         }
    2069         153 :         if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
    2070           0 :                 ret = os_snprintf(pos, end - pos, "%sNone",
    2071             :                                   pos == start ? "" : "+");
    2072           0 :                 if (ret < 0 || ret >= end - pos)
    2073           0 :                         return pos;
    2074           0 :                 pos += ret;
    2075             :         }
    2076             : #ifdef CONFIG_IEEE80211R
    2077         153 :         if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
    2078           5 :                 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
    2079             :                                   pos == start ? "" : "+");
    2080           5 :                 if (ret < 0 || ret >= end - pos)
    2081           0 :                         return pos;
    2082           5 :                 pos += ret;
    2083             :         }
    2084         153 :         if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
    2085          13 :                 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
    2086             :                                   pos == start ? "" : "+");
    2087          13 :                 if (ret < 0 || ret >= end - pos)
    2088           0 :                         return pos;
    2089          13 :                 pos += ret;
    2090             :         }
    2091             : #endif /* CONFIG_IEEE80211R */
    2092             : #ifdef CONFIG_IEEE80211W
    2093         153 :         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
    2094           0 :                 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
    2095             :                                   pos == start ? "" : "+");
    2096           0 :                 if (ret < 0 || ret >= end - pos)
    2097           0 :                         return pos;
    2098           0 :                 pos += ret;
    2099             :         }
    2100         153 :         if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
    2101           1 :                 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
    2102             :                                   pos == start ? "" : "+");
    2103           1 :                 if (ret < 0 || ret >= end - pos)
    2104           0 :                         return pos;
    2105           1 :                 pos += ret;
    2106             :         }
    2107             : #endif /* CONFIG_IEEE80211W */
    2108             : 
    2109         153 :         pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
    2110             : 
    2111         153 :         if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
    2112           1 :                 ret = os_snprintf(pos, end - pos, "-preauth");
    2113           1 :                 if (ret < 0 || ret >= end - pos)
    2114           0 :                         return pos;
    2115           1 :                 pos += ret;
    2116             :         }
    2117             : 
    2118         153 :         ret = os_snprintf(pos, end - pos, "]");
    2119         153 :         if (ret < 0 || ret >= end - pos)
    2120           0 :                 return pos;
    2121         153 :         pos += ret;
    2122             : 
    2123         153 :         return pos;
    2124             : }
    2125             : 
    2126             : 
    2127             : #ifdef CONFIG_WPS
    2128         176 : static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
    2129             :                                             char *pos, char *end,
    2130             :                                             struct wpabuf *wps_ie)
    2131             : {
    2132             :         int ret;
    2133             :         const char *txt;
    2134             : 
    2135         176 :         if (wps_ie == NULL)
    2136         142 :                 return pos;
    2137          34 :         if (wps_is_selected_pbc_registrar(wps_ie))
    2138           9 :                 txt = "[WPS-PBC]";
    2139          25 :         else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
    2140           9 :                 txt = "[WPS-AUTH]";
    2141          16 :         else if (wps_is_selected_pin_registrar(wps_ie))
    2142           1 :                 txt = "[WPS-PIN]";
    2143             :         else
    2144          15 :                 txt = "[WPS]";
    2145             : 
    2146          34 :         ret = os_snprintf(pos, end - pos, "%s", txt);
    2147          34 :         if (ret >= 0 && ret < end - pos)
    2148          34 :                 pos += ret;
    2149          34 :         wpabuf_free(wps_ie);
    2150          34 :         return pos;
    2151             : }
    2152             : #endif /* CONFIG_WPS */
    2153             : 
    2154             : 
    2155         176 : static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
    2156             :                                         char *pos, char *end,
    2157             :                                         const struct wpa_bss *bss)
    2158             : {
    2159             : #ifdef CONFIG_WPS
    2160             :         struct wpabuf *wps_ie;
    2161         176 :         wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    2162         176 :         return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
    2163             : #else /* CONFIG_WPS */
    2164             :         return pos;
    2165             : #endif /* CONFIG_WPS */
    2166             : }
    2167             : 
    2168             : 
    2169             : /* Format one result on one text line into a buffer. */
    2170          18 : static int wpa_supplicant_ctrl_iface_scan_result(
    2171             :         struct wpa_supplicant *wpa_s,
    2172             :         const struct wpa_bss *bss, char *buf, size_t buflen)
    2173             : {
    2174             :         char *pos, *end;
    2175             :         int ret;
    2176             :         const u8 *ie, *ie2, *p2p;
    2177             : 
    2178          18 :         p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
    2179          18 :         if (!p2p)
    2180          18 :                 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
    2181          18 :         if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
    2182           0 :             os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
    2183             :             0)
    2184           0 :                 return 0; /* Do not show P2P listen discovery results here */
    2185             : 
    2186          18 :         pos = buf;
    2187          18 :         end = buf + buflen;
    2188             : 
    2189         126 :         ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
    2190         108 :                           MAC2STR(bss->bssid), bss->freq, bss->level);
    2191          18 :         if (ret < 0 || ret >= end - pos)
    2192           0 :                 return -1;
    2193          18 :         pos += ret;
    2194          18 :         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
    2195          18 :         if (ie)
    2196           1 :                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
    2197          18 :         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
    2198          18 :         if (ie2)
    2199           8 :                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
    2200          18 :         pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
    2201          18 :         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
    2202           1 :                 ret = os_snprintf(pos, end - pos, "[WEP]");
    2203           1 :                 if (ret < 0 || ret >= end - pos)
    2204           0 :                         return -1;
    2205           1 :                 pos += ret;
    2206             :         }
    2207          18 :         if (bss_is_dmg(bss)) {
    2208             :                 const char *s;
    2209           0 :                 ret = os_snprintf(pos, end - pos, "[DMG]");
    2210           0 :                 if (ret < 0 || ret >= end - pos)
    2211           0 :                         return -1;
    2212           0 :                 pos += ret;
    2213           0 :                 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
    2214             :                 case IEEE80211_CAP_DMG_IBSS:
    2215           0 :                         s = "[IBSS]";
    2216           0 :                         break;
    2217             :                 case IEEE80211_CAP_DMG_AP:
    2218           0 :                         s = "[ESS]";
    2219           0 :                         break;
    2220             :                 case IEEE80211_CAP_DMG_PBSS:
    2221           0 :                         s = "[PBSS]";
    2222           0 :                         break;
    2223             :                 default:
    2224           0 :                         s = "";
    2225           0 :                         break;
    2226             :                 }
    2227           0 :                 ret = os_snprintf(pos, end - pos, "%s", s);
    2228           0 :                 if (ret < 0 || ret >= end - pos)
    2229           0 :                         return -1;
    2230           0 :                 pos += ret;
    2231             :         } else {
    2232          18 :                 if (bss->caps & IEEE80211_CAP_IBSS) {
    2233           0 :                         ret = os_snprintf(pos, end - pos, "[IBSS]");
    2234           0 :                         if (ret < 0 || ret >= end - pos)
    2235           0 :                                 return -1;
    2236           0 :                         pos += ret;
    2237             :                 }
    2238          18 :                 if (bss->caps & IEEE80211_CAP_ESS) {
    2239          18 :                         ret = os_snprintf(pos, end - pos, "[ESS]");
    2240          18 :                         if (ret < 0 || ret >= end - pos)
    2241           0 :                                 return -1;
    2242          18 :                         pos += ret;
    2243             :                 }
    2244             :         }
    2245          18 :         if (p2p) {
    2246           0 :                 ret = os_snprintf(pos, end - pos, "[P2P]");
    2247           0 :                 if (ret < 0 || ret >= end - pos)
    2248           0 :                         return -1;
    2249           0 :                 pos += ret;
    2250             :         }
    2251             : #ifdef CONFIG_HS20
    2252          18 :         if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
    2253           0 :                 ret = os_snprintf(pos, end - pos, "[HS20]");
    2254           0 :                 if (ret < 0 || ret >= end - pos)
    2255           0 :                         return -1;
    2256           0 :                 pos += ret;
    2257             :         }
    2258             : #endif /* CONFIG_HS20 */
    2259             : 
    2260          36 :         ret = os_snprintf(pos, end - pos, "\t%s",
    2261          18 :                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
    2262          18 :         if (ret < 0 || ret >= end - pos)
    2263           0 :                 return -1;
    2264          18 :         pos += ret;
    2265             : 
    2266          18 :         ret = os_snprintf(pos, end - pos, "\n");
    2267          18 :         if (ret < 0 || ret >= end - pos)
    2268           0 :                 return -1;
    2269          18 :         pos += ret;
    2270             : 
    2271          18 :         return pos - buf;
    2272             : }
    2273             : 
    2274             : 
    2275          16 : static int wpa_supplicant_ctrl_iface_scan_results(
    2276             :         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
    2277             : {
    2278             :         char *pos, *end;
    2279             :         struct wpa_bss *bss;
    2280             :         int ret;
    2281             : 
    2282          16 :         pos = buf;
    2283          16 :         end = buf + buflen;
    2284          16 :         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
    2285             :                           "flags / ssid\n");
    2286          16 :         if (ret < 0 || ret >= end - pos)
    2287           0 :                 return pos - buf;
    2288          16 :         pos += ret;
    2289             : 
    2290          34 :         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
    2291          18 :                 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
    2292          18 :                                                             end - pos);
    2293          18 :                 if (ret < 0 || ret >= end - pos)
    2294           0 :                         return pos - buf;
    2295          18 :                 pos += ret;
    2296             :         }
    2297             : 
    2298          16 :         return pos - buf;
    2299             : }
    2300             : 
    2301             : 
    2302         553 : static int wpa_supplicant_ctrl_iface_select_network(
    2303             :         struct wpa_supplicant *wpa_s, char *cmd)
    2304             : {
    2305             :         int id;
    2306             :         struct wpa_ssid *ssid;
    2307             :         char *pos;
    2308             : 
    2309             :         /* cmd: "<network id>" or "any" */
    2310         553 :         if (os_strncmp(cmd, "any", 3) == 0) {
    2311           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
    2312           1 :                 ssid = NULL;
    2313             :         } else {
    2314         552 :                 id = atoi(cmd);
    2315         552 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
    2316             : 
    2317         552 :                 ssid = wpa_config_get_network(wpa_s->conf, id);
    2318         552 :                 if (ssid == NULL) {
    2319           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
    2320             :                                    "network id=%d", id);
    2321           1 :                         return -1;
    2322             :                 }
    2323         551 :                 if (ssid->disabled == 2) {
    2324           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
    2325             :                                    "SELECT_NETWORK with persistent P2P group");
    2326           1 :                         return -1;
    2327             :                 }
    2328             :         }
    2329             : 
    2330         551 :         pos = os_strstr(cmd, " freq=");
    2331         551 :         if (pos) {
    2332          11 :                 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
    2333          11 :                 if (freqs) {
    2334          11 :                         wpa_s->scan_req = MANUAL_SCAN_REQ;
    2335          11 :                         os_free(wpa_s->manual_scan_freqs);
    2336          11 :                         wpa_s->manual_scan_freqs = freqs;
    2337             :                 }
    2338             :         }
    2339             : 
    2340         551 :         wpa_supplicant_select_network(wpa_s, ssid);
    2341             : 
    2342         551 :         return 0;
    2343             : }
    2344             : 
    2345             : 
    2346          25 : static int wpa_supplicant_ctrl_iface_enable_network(
    2347             :         struct wpa_supplicant *wpa_s, char *cmd)
    2348             : {
    2349             :         int id;
    2350             :         struct wpa_ssid *ssid;
    2351             : 
    2352             :         /* cmd: "<network id>" or "all" */
    2353          25 :         if (os_strcmp(cmd, "all") == 0) {
    2354           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
    2355           1 :                 ssid = NULL;
    2356             :         } else {
    2357          24 :                 id = atoi(cmd);
    2358          24 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
    2359             : 
    2360          24 :                 ssid = wpa_config_get_network(wpa_s->conf, id);
    2361          24 :                 if (ssid == NULL) {
    2362           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
    2363             :                                    "network id=%d", id);
    2364           1 :                         return -1;
    2365             :                 }
    2366          23 :                 if (ssid->disabled == 2) {
    2367           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
    2368             :                                    "ENABLE_NETWORK with persistent P2P group");
    2369           1 :                         return -1;
    2370             :                 }
    2371             : 
    2372          22 :                 if (os_strstr(cmd, " no-connect")) {
    2373          21 :                         ssid->disabled = 0;
    2374          21 :                         return 0;
    2375             :                 }
    2376             :         }
    2377           2 :         wpa_supplicant_enable_network(wpa_s, ssid);
    2378             : 
    2379           2 :         return 0;
    2380             : }
    2381             : 
    2382             : 
    2383           6 : static int wpa_supplicant_ctrl_iface_disable_network(
    2384             :         struct wpa_supplicant *wpa_s, char *cmd)
    2385             : {
    2386             :         int id;
    2387             :         struct wpa_ssid *ssid;
    2388             : 
    2389             :         /* cmd: "<network id>" or "all" */
    2390           6 :         if (os_strcmp(cmd, "all") == 0) {
    2391           2 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
    2392           2 :                 ssid = NULL;
    2393             :         } else {
    2394           4 :                 id = atoi(cmd);
    2395           4 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
    2396             : 
    2397           4 :                 ssid = wpa_config_get_network(wpa_s->conf, id);
    2398           4 :                 if (ssid == NULL) {
    2399           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
    2400             :                                    "network id=%d", id);
    2401           1 :                         return -1;
    2402             :                 }
    2403           3 :                 if (ssid->disabled == 2) {
    2404           1 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
    2405             :                                    "DISABLE_NETWORK with persistent P2P "
    2406             :                                    "group");
    2407           1 :                         return -1;
    2408             :                 }
    2409             :         }
    2410           4 :         wpa_supplicant_disable_network(wpa_s, ssid);
    2411             : 
    2412           4 :         return 0;
    2413             : }
    2414             : 
    2415             : 
    2416         563 : static int wpa_supplicant_ctrl_iface_add_network(
    2417             :         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
    2418             : {
    2419             :         struct wpa_ssid *ssid;
    2420             :         int ret;
    2421             : 
    2422         563 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
    2423             : 
    2424         563 :         ssid = wpa_config_add_network(wpa_s->conf);
    2425         563 :         if (ssid == NULL)
    2426           0 :                 return -1;
    2427             : 
    2428         563 :         wpas_notify_network_added(wpa_s, ssid);
    2429             : 
    2430         563 :         ssid->disabled = 1;
    2431         563 :         wpa_config_set_network_defaults(ssid);
    2432             : 
    2433         563 :         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
    2434         563 :         if (ret < 0 || (size_t) ret >= buflen)
    2435           0 :                 return -1;
    2436         563 :         return ret;
    2437             : }
    2438             : 
    2439             : 
    2440        2096 : static int wpa_supplicant_ctrl_iface_remove_network(
    2441             :         struct wpa_supplicant *wpa_s, char *cmd)
    2442             : {
    2443             :         int id;
    2444             :         struct wpa_ssid *ssid;
    2445             :         int was_disabled;
    2446             : 
    2447             :         /* cmd: "<network id>" or "all" */
    2448        2096 :         if (os_strcmp(cmd, "all") == 0) {
    2449        1984 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
    2450        1984 :                 if (wpa_s->sched_scanning)
    2451           0 :                         wpa_supplicant_cancel_sched_scan(wpa_s);
    2452             : 
    2453        1984 :                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
    2454        1984 :                 if (wpa_s->current_ssid) {
    2455             : #ifdef CONFIG_SME
    2456          91 :                         wpa_s->sme.prev_bssid_set = 0;
    2457             : #endif /* CONFIG_SME */
    2458          91 :                         wpa_sm_set_config(wpa_s->wpa, NULL);
    2459          91 :                         eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
    2460          91 :                         wpa_supplicant_deauthenticate(
    2461             :                                 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
    2462             :                 }
    2463        1984 :                 ssid = wpa_s->conf->ssid;
    2464        4581 :                 while (ssid) {
    2465         613 :                         struct wpa_ssid *remove_ssid = ssid;
    2466         613 :                         id = ssid->id;
    2467         613 :                         ssid = ssid->next;
    2468         613 :                         wpas_notify_network_removed(wpa_s, remove_ssid);
    2469         613 :                         wpa_config_remove_network(wpa_s->conf, id);
    2470             :                 }
    2471        1984 :                 return 0;
    2472             :         }
    2473             : 
    2474         112 :         id = atoi(cmd);
    2475         112 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
    2476             : 
    2477         112 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    2478         112 :         if (ssid)
    2479         111 :                 wpas_notify_network_removed(wpa_s, ssid);
    2480         112 :         if (ssid == NULL) {
    2481           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
    2482             :                            "id=%d", id);
    2483           1 :                 return -1;
    2484             :         }
    2485             : 
    2486         111 :         if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
    2487             : #ifdef CONFIG_SME
    2488         111 :                 wpa_s->sme.prev_bssid_set = 0;
    2489             : #endif /* CONFIG_SME */
    2490             :                 /*
    2491             :                  * Invalidate the EAP session cache if the current or
    2492             :                  * previously used network is removed.
    2493             :                  */
    2494         111 :                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
    2495             :         }
    2496             : 
    2497         111 :         if (ssid == wpa_s->current_ssid) {
    2498          91 :                 wpa_sm_set_config(wpa_s->wpa, NULL);
    2499          91 :                 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
    2500             : 
    2501          91 :                 wpa_supplicant_deauthenticate(wpa_s,
    2502             :                                               WLAN_REASON_DEAUTH_LEAVING);
    2503             :         }
    2504             : 
    2505         111 :         was_disabled = ssid->disabled;
    2506             : 
    2507         111 :         if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
    2508           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
    2509             :                            "network id=%d", id);
    2510           0 :                 return -1;
    2511             :         }
    2512             : 
    2513         111 :         if (!was_disabled && wpa_s->sched_scanning) {
    2514           0 :                 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
    2515             :                            "network from filters");
    2516           0 :                 wpa_supplicant_cancel_sched_scan(wpa_s);
    2517           0 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
    2518             :         }
    2519             : 
    2520         111 :         return 0;
    2521             : }
    2522             : 
    2523             : 
    2524        2958 : static int wpa_supplicant_ctrl_iface_update_network(
    2525             :         struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
    2526             :         char *name, char *value)
    2527             : {
    2528        2958 :         if (wpa_config_set(ssid, name, value, 0) < 0) {
    2529          28 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
    2530             :                            "variable '%s'", name);
    2531          28 :                 return -1;
    2532             :         }
    2533             : 
    2534        5849 :         if (os_strcmp(name, "bssid") != 0 &&
    2535        2919 :             os_strcmp(name, "priority") != 0)
    2536        2918 :                 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
    2537             : 
    2538        2930 :         if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
    2539             :                 /*
    2540             :                  * Invalidate the EAP session cache if anything in the current
    2541             :                  * or previously used configuration changes.
    2542             :                  */
    2543        2924 :                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
    2544             :         }
    2545             : 
    2546        3086 :         if ((os_strcmp(name, "psk") == 0 &&
    2547        3089 :              value[0] == '"' && ssid->ssid_len) ||
    2548        3345 :             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
    2549         146 :                 wpa_config_update_psk(ssid);
    2550        2784 :         else if (os_strcmp(name, "priority") == 0)
    2551           1 :                 wpa_config_update_prio_list(wpa_s->conf);
    2552             : 
    2553        2930 :         return 0;
    2554             : }
    2555             : 
    2556             : 
    2557        2958 : static int wpa_supplicant_ctrl_iface_set_network(
    2558             :         struct wpa_supplicant *wpa_s, char *cmd)
    2559             : {
    2560             :         int id;
    2561             :         struct wpa_ssid *ssid;
    2562             :         char *name, *value;
    2563             : 
    2564             :         /* cmd: "<network id> <variable name> <value>" */
    2565        2958 :         name = os_strchr(cmd, ' ');
    2566        2958 :         if (name == NULL)
    2567           1 :                 return -1;
    2568        2957 :         *name++ = '\0';
    2569             : 
    2570        2957 :         value = os_strchr(name, ' ');
    2571        2957 :         if (value == NULL)
    2572           1 :                 return -1;
    2573        2956 :         *value++ = '\0';
    2574             : 
    2575        2956 :         id = atoi(cmd);
    2576        2956 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
    2577             :                    id, name);
    2578        2956 :         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
    2579             :                               (u8 *) value, os_strlen(value));
    2580             : 
    2581        2956 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    2582        2956 :         if (ssid == NULL) {
    2583           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
    2584             :                            "id=%d", id);
    2585           1 :                 return -1;
    2586             :         }
    2587             : 
    2588        2955 :         return wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
    2589             :                                                         value);
    2590             : }
    2591             : 
    2592             : 
    2593          40 : static int wpa_supplicant_ctrl_iface_get_network(
    2594             :         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
    2595             : {
    2596             :         int id;
    2597             :         size_t res;
    2598             :         struct wpa_ssid *ssid;
    2599             :         char *name, *value;
    2600             : 
    2601             :         /* cmd: "<network id> <variable name>" */
    2602          40 :         name = os_strchr(cmd, ' ');
    2603          40 :         if (name == NULL || buflen == 0)
    2604           1 :                 return -1;
    2605          39 :         *name++ = '\0';
    2606             : 
    2607          39 :         id = atoi(cmd);
    2608          39 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
    2609             :                    id, name);
    2610             : 
    2611          39 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    2612          39 :         if (ssid == NULL) {
    2613           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
    2614             :                            "id=%d", id);
    2615           1 :                 return -1;
    2616             :         }
    2617             : 
    2618          38 :         value = wpa_config_get_no_key(ssid, name);
    2619          38 :         if (value == NULL) {
    2620           7 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
    2621             :                            "variable '%s'", name);
    2622           7 :                 return -1;
    2623             :         }
    2624             : 
    2625          31 :         res = os_strlcpy(buf, value, buflen);
    2626          31 :         if (res >= buflen) {
    2627           0 :                 os_free(value);
    2628           0 :                 return -1;
    2629             :         }
    2630             : 
    2631          31 :         os_free(value);
    2632             : 
    2633          31 :         return res;
    2634             : }
    2635             : 
    2636             : 
    2637           3 : static int wpa_supplicant_ctrl_iface_dup_network(
    2638             :         struct wpa_supplicant *wpa_s, char *cmd)
    2639             : {
    2640             :         struct wpa_ssid *ssid_s, *ssid_d;
    2641             :         char *name, *id, *value;
    2642             :         int id_s, id_d, ret;
    2643             : 
    2644             :         /* cmd: "<src network id> <dst network id> <variable name>" */
    2645           3 :         id = os_strchr(cmd, ' ');
    2646           3 :         if (id == NULL)
    2647           0 :                 return -1;
    2648           3 :         *id++ = '\0';
    2649             : 
    2650           3 :         name = os_strchr(id, ' ');
    2651           3 :         if (name == NULL)
    2652           0 :                 return -1;
    2653           3 :         *name++ = '\0';
    2654             : 
    2655           3 :         id_s = atoi(cmd);
    2656           3 :         id_d = atoi(id);
    2657           3 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: DUP_NETWORK id=%d -> %d name='%s'",
    2658             :                    id_s, id_d, name);
    2659             : 
    2660           3 :         ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
    2661           3 :         if (ssid_s == NULL) {
    2662           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
    2663             :                            "network id=%d", id_s);
    2664           0 :                 return -1;
    2665             :         }
    2666             : 
    2667           3 :         ssid_d = wpa_config_get_network(wpa_s->conf, id_d);
    2668           3 :         if (ssid_d == NULL) {
    2669           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
    2670             :                            "network id=%d", id_s);
    2671           0 :                 return -1;
    2672             :         }
    2673             : 
    2674           3 :         value = wpa_config_get(ssid_s, name);
    2675           3 :         if (value == NULL) {
    2676           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
    2677             :                            "variable '%s'", name);
    2678           0 :                 return -1;
    2679             :         }
    2680             : 
    2681           3 :         ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid_d, name,
    2682             :                                                        value);
    2683             : 
    2684           3 :         os_free(value);
    2685             : 
    2686           3 :         return ret;
    2687             : }
    2688             : 
    2689             : 
    2690           8 : static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
    2691             :                                                 char *buf, size_t buflen)
    2692             : {
    2693             :         char *pos, *end;
    2694             :         struct wpa_cred *cred;
    2695             :         int ret;
    2696             : 
    2697           8 :         pos = buf;
    2698           8 :         end = buf + buflen;
    2699           8 :         ret = os_snprintf(pos, end - pos,
    2700             :                           "cred id / realm / username / domain / imsi\n");
    2701           8 :         if (ret < 0 || ret >= end - pos)
    2702           0 :                 return pos - buf;
    2703           8 :         pos += ret;
    2704             : 
    2705           8 :         cred = wpa_s->conf->cred;
    2706         111 :         while (cred) {
    2707         388 :                 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
    2708          96 :                                   cred->id, cred->realm ? cred->realm : "",
    2709          96 :                                   cred->username ? cred->username : "",
    2710         100 :                                   cred->domain ? cred->domain[0] : "",
    2711          96 :                                   cred->imsi ? cred->imsi : "");
    2712          96 :                 if (ret < 0 || ret >= end - pos)
    2713           1 :                         return pos - buf;
    2714          95 :                 pos += ret;
    2715             : 
    2716          95 :                 cred = cred->next;
    2717             :         }
    2718             : 
    2719           7 :         return pos - buf;
    2720             : }
    2721             : 
    2722             : 
    2723         209 : static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
    2724             :                                               char *buf, size_t buflen)
    2725             : {
    2726             :         struct wpa_cred *cred;
    2727             :         int ret;
    2728             : 
    2729         209 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
    2730             : 
    2731         209 :         cred = wpa_config_add_cred(wpa_s->conf);
    2732         209 :         if (cred == NULL)
    2733           0 :                 return -1;
    2734             : 
    2735         209 :         wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
    2736             : 
    2737         209 :         ret = os_snprintf(buf, buflen, "%d\n", cred->id);
    2738         209 :         if (ret < 0 || (size_t) ret >= buflen)
    2739           0 :                 return -1;
    2740         209 :         return ret;
    2741             : }
    2742             : 
    2743             : 
    2744         208 : static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
    2745             :                                  struct wpa_cred *cred)
    2746             : {
    2747             :         struct wpa_ssid *ssid;
    2748             :         char str[20];
    2749             :         int id;
    2750             : 
    2751         208 :         if (cred == NULL) {
    2752           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
    2753           1 :                 return -1;
    2754             :         }
    2755             : 
    2756         207 :         id = cred->id;
    2757         207 :         if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
    2758           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
    2759           0 :                 return -1;
    2760             :         }
    2761             : 
    2762         207 :         wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
    2763             : 
    2764             :         /* Remove any network entry created based on the removed credential */
    2765         207 :         ssid = wpa_s->conf->ssid;
    2766         433 :         while (ssid) {
    2767          19 :                 if (ssid->parent_cred == cred) {
    2768          19 :                         wpa_printf(MSG_DEBUG, "Remove network id %d since it "
    2769             :                                    "used the removed credential", ssid->id);
    2770          19 :                         os_snprintf(str, sizeof(str), "%d", ssid->id);
    2771          19 :                         ssid = ssid->next;
    2772          19 :                         wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
    2773             :                 } else
    2774           0 :                         ssid = ssid->next;
    2775             :         }
    2776             : 
    2777         207 :         return 0;
    2778             : }
    2779             : 
    2780             : 
    2781        2046 : static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
    2782             :                                                  char *cmd)
    2783             : {
    2784             :         int id;
    2785             :         struct wpa_cred *cred, *prev;
    2786             : 
    2787             :         /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
    2788             :          * "provisioning_sp=<FQDN> */
    2789        2046 :         if (os_strcmp(cmd, "all") == 0) {
    2790        1905 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
    2791        1905 :                 cred = wpa_s->conf->cred;
    2792        3875 :                 while (cred) {
    2793          65 :                         prev = cred;
    2794          65 :                         cred = cred->next;
    2795          65 :                         wpas_ctrl_remove_cred(wpa_s, prev);
    2796             :                 }
    2797        1905 :                 return 0;
    2798             :         }
    2799             : 
    2800         141 :         if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
    2801           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
    2802             :                            cmd + 8);
    2803           1 :                 cred = wpa_s->conf->cred;
    2804           5 :                 while (cred) {
    2805           3 :                         prev = cred;
    2806           3 :                         cred = cred->next;
    2807           3 :                         if (prev->domain) {
    2808             :                                 size_t i;
    2809           8 :                                 for (i = 0; i < prev->num_domain; i++) {
    2810           3 :                                         if (os_strcmp(prev->domain[i], cmd + 8)
    2811             :                                             != 0)
    2812           1 :                                                 continue;
    2813           2 :                                         wpas_ctrl_remove_cred(wpa_s, prev);
    2814           2 :                                         break;
    2815             :                                 }
    2816             :                         }
    2817             :                 }
    2818           1 :                 return 0;
    2819             :         }
    2820             : 
    2821         140 :         if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
    2822           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
    2823             :                            cmd + 16);
    2824           1 :                 cred = wpa_s->conf->cred;
    2825           5 :                 while (cred) {
    2826           3 :                         prev = cred;
    2827           3 :                         cred = cred->next;
    2828           6 :                         if (prev->provisioning_sp &&
    2829           3 :                             os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
    2830           2 :                                 wpas_ctrl_remove_cred(wpa_s, prev);
    2831             :                 }
    2832           1 :                 return 0;
    2833             :         }
    2834             : 
    2835         139 :         id = atoi(cmd);
    2836         139 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
    2837             : 
    2838         139 :         cred = wpa_config_get_cred(wpa_s->conf, id);
    2839         139 :         return wpas_ctrl_remove_cred(wpa_s, cred);
    2840             : }
    2841             : 
    2842             : 
    2843         601 : static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
    2844             :                                               char *cmd)
    2845             : {
    2846             :         int id;
    2847             :         struct wpa_cred *cred;
    2848             :         char *name, *value;
    2849             : 
    2850             :         /* cmd: "<cred id> <variable name> <value>" */
    2851         601 :         name = os_strchr(cmd, ' ');
    2852         601 :         if (name == NULL)
    2853           1 :                 return -1;
    2854         600 :         *name++ = '\0';
    2855             : 
    2856         600 :         value = os_strchr(name, ' ');
    2857         600 :         if (value == NULL)
    2858           1 :                 return -1;
    2859         599 :         *value++ = '\0';
    2860             : 
    2861         599 :         id = atoi(cmd);
    2862         599 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
    2863             :                    id, name);
    2864         599 :         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
    2865             :                               (u8 *) value, os_strlen(value));
    2866             : 
    2867         599 :         cred = wpa_config_get_cred(wpa_s->conf, id);
    2868         599 :         if (cred == NULL) {
    2869           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
    2870             :                            id);
    2871           1 :                 return -1;
    2872             :         }
    2873             : 
    2874         598 :         if (wpa_config_set_cred(cred, name, value, 0) < 0) {
    2875          13 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
    2876             :                            "variable '%s'", name);
    2877          13 :                 return -1;
    2878             :         }
    2879             : 
    2880         585 :         wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
    2881             : 
    2882         585 :         return 0;
    2883             : }
    2884             : 
    2885             : 
    2886          39 : static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
    2887             :                                               char *cmd, char *buf,
    2888             :                                               size_t buflen)
    2889             : {
    2890             :         int id;
    2891             :         size_t res;
    2892             :         struct wpa_cred *cred;
    2893             :         char *name, *value;
    2894             : 
    2895             :         /* cmd: "<cred id> <variable name>" */
    2896          39 :         name = os_strchr(cmd, ' ');
    2897          39 :         if (name == NULL)
    2898           1 :                 return -1;
    2899          38 :         *name++ = '\0';
    2900             : 
    2901          38 :         id = atoi(cmd);
    2902          38 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
    2903             :                    id, name);
    2904             : 
    2905          38 :         cred = wpa_config_get_cred(wpa_s->conf, id);
    2906          38 :         if (cred == NULL) {
    2907           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
    2908             :                            id);
    2909           1 :                 return -1;
    2910             :         }
    2911             : 
    2912          37 :         value = wpa_config_get_cred_no_key(cred, name);
    2913          37 :         if (value == NULL) {
    2914           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
    2915             :                            name);
    2916           1 :                 return -1;
    2917             :         }
    2918             : 
    2919          36 :         res = os_strlcpy(buf, value, buflen);
    2920          36 :         if (res >= buflen) {
    2921           0 :                 os_free(value);
    2922           0 :                 return -1;
    2923             :         }
    2924             : 
    2925          36 :         os_free(value);
    2926             : 
    2927          36 :         return res;
    2928             : }
    2929             : 
    2930             : 
    2931             : #ifndef CONFIG_NO_CONFIG_WRITE
    2932           2 : static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
    2933             : {
    2934             :         int ret;
    2935             : 
    2936           2 :         if (!wpa_s->conf->update_config) {
    2937           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
    2938             :                            "to update configuration (update_config=0)");
    2939           0 :                 return -1;
    2940             :         }
    2941             : 
    2942           2 :         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
    2943           2 :         if (ret) {
    2944           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
    2945             :                            "update configuration");
    2946             :         } else {
    2947           2 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
    2948             :                            " updated");
    2949             :         }
    2950             : 
    2951           2 :         return ret;
    2952             : }
    2953             : #endif /* CONFIG_NO_CONFIG_WRITE */
    2954             : 
    2955             : 
    2956             : struct cipher_info {
    2957             :         unsigned int capa;
    2958             :         const char *name;
    2959             :         int group_only;
    2960             : };
    2961             : 
    2962             : static const struct cipher_info ciphers[] = {
    2963             :         { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
    2964             :         { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
    2965             :         { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
    2966             :         { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
    2967             :         { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
    2968             :         { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
    2969             :         { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
    2970             :         { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
    2971             : };
    2972             : 
    2973             : 
    2974           6 : static int ctrl_iface_get_capability_pairwise(int res, char *strict,
    2975             :                                               struct wpa_driver_capa *capa,
    2976             :                                               char *buf, size_t buflen)
    2977             : {
    2978             :         int ret;
    2979             :         char *pos, *end;
    2980             :         size_t len;
    2981             :         unsigned int i;
    2982             : 
    2983           6 :         pos = buf;
    2984           6 :         end = pos + buflen;
    2985             : 
    2986           6 :         if (res < 0) {
    2987           0 :                 if (strict)
    2988           0 :                         return 0;
    2989           0 :                 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
    2990           0 :                 if (len >= buflen)
    2991           0 :                         return -1;
    2992           0 :                 return len;
    2993             :         }
    2994             : 
    2995          54 :         for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
    2996          48 :                 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
    2997          12 :                         ret = os_snprintf(pos, end - pos, "%s%s",
    2998             :                                           pos == buf ? "" : " ",
    2999             :                                           ciphers[i].name);
    3000          12 :                         if (ret < 0 || ret >= end - pos)
    3001           0 :                                 return pos - buf;
    3002          12 :                         pos += ret;
    3003             :                 }
    3004             :         }
    3005             : 
    3006           6 :         return pos - buf;
    3007             : }
    3008             : 
    3009             : 
    3010           1 : static int ctrl_iface_get_capability_group(int res, char *strict,
    3011             :                                            struct wpa_driver_capa *capa,
    3012             :                                            char *buf, size_t buflen)
    3013             : {
    3014             :         int ret;
    3015             :         char *pos, *end;
    3016             :         size_t len;
    3017             :         unsigned int i;
    3018             : 
    3019           1 :         pos = buf;
    3020           1 :         end = pos + buflen;
    3021             : 
    3022           1 :         if (res < 0) {
    3023           0 :                 if (strict)
    3024           0 :                         return 0;
    3025           0 :                 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
    3026           0 :                 if (len >= buflen)
    3027           0 :                         return -1;
    3028           0 :                 return len;
    3029             :         }
    3030             : 
    3031           9 :         for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
    3032           8 :                 if (capa->enc & ciphers[i].capa) {
    3033           4 :                         ret = os_snprintf(pos, end - pos, "%s%s",
    3034             :                                           pos == buf ? "" : " ",
    3035             :                                           ciphers[i].name);
    3036           4 :                         if (ret < 0 || ret >= end - pos)
    3037           0 :                                 return pos - buf;
    3038           4 :                         pos += ret;
    3039             :                 }
    3040             :         }
    3041             : 
    3042           1 :         return pos - buf;
    3043             : }
    3044             : 
    3045             : 
    3046           1 : static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
    3047             :                                               struct wpa_driver_capa *capa,
    3048             :                                               char *buf, size_t buflen)
    3049             : {
    3050             :         int ret;
    3051             :         char *pos, *end;
    3052             :         size_t len;
    3053             : 
    3054           1 :         pos = buf;
    3055           1 :         end = pos + buflen;
    3056             : 
    3057           1 :         if (res < 0) {
    3058           0 :                 if (strict)
    3059           0 :                         return 0;
    3060           0 :                 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
    3061             :                                  "NONE", buflen);
    3062           0 :                 if (len >= buflen)
    3063           0 :                         return -1;
    3064           0 :                 return len;
    3065             :         }
    3066             : 
    3067           1 :         ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
    3068           1 :         if (ret < 0 || ret >= end - pos)
    3069           0 :                 return pos - buf;
    3070           1 :         pos += ret;
    3071             : 
    3072           1 :         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
    3073             :                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
    3074           1 :                 ret = os_snprintf(pos, end - pos, " WPA-EAP");
    3075           1 :                 if (ret < 0 || ret >= end - pos)
    3076           0 :                         return pos - buf;
    3077           1 :                 pos += ret;
    3078             :         }
    3079             : 
    3080           1 :         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
    3081             :                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
    3082           1 :                 ret = os_snprintf(pos, end - pos, " WPA-PSK");
    3083           1 :                 if (ret < 0 || ret >= end - pos)
    3084           0 :                         return pos - buf;
    3085           1 :                 pos += ret;
    3086             :         }
    3087             : 
    3088           1 :         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
    3089           0 :                 ret = os_snprintf(pos, end - pos, " WPA-NONE");
    3090           0 :                 if (ret < 0 || ret >= end - pos)
    3091           0 :                         return pos - buf;
    3092           0 :                 pos += ret;
    3093             :         }
    3094             : 
    3095           1 :         return pos - buf;
    3096             : }
    3097             : 
    3098             : 
    3099           1 : static int ctrl_iface_get_capability_proto(int res, char *strict,
    3100             :                                            struct wpa_driver_capa *capa,
    3101             :                                            char *buf, size_t buflen)
    3102             : {
    3103             :         int ret;
    3104             :         char *pos, *end;
    3105             :         size_t len;
    3106             : 
    3107           1 :         pos = buf;
    3108           1 :         end = pos + buflen;
    3109             : 
    3110           1 :         if (res < 0) {
    3111           0 :                 if (strict)
    3112           0 :                         return 0;
    3113           0 :                 len = os_strlcpy(buf, "RSN WPA", buflen);
    3114           0 :                 if (len >= buflen)
    3115           0 :                         return -1;
    3116           0 :                 return len;
    3117             :         }
    3118             : 
    3119           1 :         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
    3120             :                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
    3121           1 :                 ret = os_snprintf(pos, end - pos, "%sRSN",
    3122             :                                   pos == buf ? "" : " ");
    3123           1 :                 if (ret < 0 || ret >= end - pos)
    3124           0 :                         return pos - buf;
    3125           1 :                 pos += ret;
    3126             :         }
    3127             : 
    3128           1 :         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
    3129             :                               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
    3130           1 :                 ret = os_snprintf(pos, end - pos, "%sWPA",
    3131             :                                   pos == buf ? "" : " ");
    3132           1 :                 if (ret < 0 || ret >= end - pos)
    3133           0 :                         return pos - buf;
    3134           1 :                 pos += ret;
    3135             :         }
    3136             : 
    3137           1 :         return pos - buf;
    3138             : }
    3139             : 
    3140             : 
    3141           1 : static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
    3142             :                                               struct wpa_driver_capa *capa,
    3143             :                                               char *buf, size_t buflen)
    3144             : {
    3145             :         int ret;
    3146             :         char *pos, *end;
    3147             :         size_t len;
    3148             : 
    3149           1 :         pos = buf;
    3150           1 :         end = pos + buflen;
    3151             : 
    3152           1 :         if (res < 0) {
    3153           0 :                 if (strict)
    3154           0 :                         return 0;
    3155           0 :                 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
    3156           0 :                 if (len >= buflen)
    3157           0 :                         return -1;
    3158           0 :                 return len;
    3159             :         }
    3160             : 
    3161           1 :         if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
    3162           1 :                 ret = os_snprintf(pos, end - pos, "%sOPEN",
    3163             :                                   pos == buf ? "" : " ");
    3164           1 :                 if (ret < 0 || ret >= end - pos)
    3165           0 :                         return pos - buf;
    3166           1 :                 pos += ret;
    3167             :         }
    3168             : 
    3169           1 :         if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
    3170           1 :                 ret = os_snprintf(pos, end - pos, "%sSHARED",
    3171             :                                   pos == buf ? "" : " ");
    3172           1 :                 if (ret < 0 || ret >= end - pos)
    3173           0 :                         return pos - buf;
    3174           1 :                 pos += ret;
    3175             :         }
    3176             : 
    3177           1 :         if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
    3178           1 :                 ret = os_snprintf(pos, end - pos, "%sLEAP",
    3179             :                                   pos == buf ? "" : " ");
    3180           1 :                 if (ret < 0 || ret >= end - pos)
    3181           0 :                         return pos - buf;
    3182           1 :                 pos += ret;
    3183             :         }
    3184             : 
    3185           1 :         return pos - buf;
    3186             : }
    3187             : 
    3188             : 
    3189           2 : static int ctrl_iface_get_capability_modes(int res, char *strict,
    3190             :                                            struct wpa_driver_capa *capa,
    3191             :                                            char *buf, size_t buflen)
    3192             : {
    3193             :         int ret;
    3194             :         char *pos, *end;
    3195             :         size_t len;
    3196             : 
    3197           2 :         pos = buf;
    3198           2 :         end = pos + buflen;
    3199             : 
    3200           2 :         if (res < 0) {
    3201           0 :                 if (strict)
    3202           0 :                         return 0;
    3203           0 :                 len = os_strlcpy(buf, "IBSS AP", buflen);
    3204           0 :                 if (len >= buflen)
    3205           0 :                         return -1;
    3206           0 :                 return len;
    3207             :         }
    3208             : 
    3209           2 :         if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
    3210           2 :                 ret = os_snprintf(pos, end - pos, "%sIBSS",
    3211             :                                   pos == buf ? "" : " ");
    3212           2 :                 if (ret < 0 || ret >= end - pos)
    3213           0 :                         return pos - buf;
    3214           2 :                 pos += ret;
    3215             :         }
    3216             : 
    3217           2 :         if (capa->flags & WPA_DRIVER_FLAGS_AP) {
    3218           2 :                 ret = os_snprintf(pos, end - pos, "%sAP",
    3219             :                                   pos == buf ? "" : " ");
    3220           2 :                 if (ret < 0 || ret >= end - pos)
    3221           0 :                         return pos - buf;
    3222           2 :                 pos += ret;
    3223             :         }
    3224             : 
    3225           2 :         return pos - buf;
    3226             : }
    3227             : 
    3228             : 
    3229           1 : static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
    3230             :                                               char *buf, size_t buflen)
    3231             : {
    3232             :         struct hostapd_channel_data *chnl;
    3233             :         int ret, i, j;
    3234             :         char *pos, *end, *hmode;
    3235             : 
    3236           1 :         pos = buf;
    3237           1 :         end = pos + buflen;
    3238             : 
    3239           4 :         for (j = 0; j < wpa_s->hw.num_modes; j++) {
    3240           3 :                 switch (wpa_s->hw.modes[j].mode) {
    3241             :                 case HOSTAPD_MODE_IEEE80211B:
    3242           1 :                         hmode = "B";
    3243           1 :                         break;
    3244             :                 case HOSTAPD_MODE_IEEE80211G:
    3245           1 :                         hmode = "G";
    3246           1 :                         break;
    3247             :                 case HOSTAPD_MODE_IEEE80211A:
    3248           1 :                         hmode = "A";
    3249           1 :                         break;
    3250             :                 case HOSTAPD_MODE_IEEE80211AD:
    3251           0 :                         hmode = "AD";
    3252           0 :                         break;
    3253             :                 default:
    3254           0 :                         continue;
    3255             :                 }
    3256           3 :                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
    3257           3 :                 if (ret < 0 || ret >= end - pos)
    3258           0 :                         return pos - buf;
    3259           3 :                 pos += ret;
    3260           3 :                 chnl = wpa_s->hw.modes[j].channels;
    3261          55 :                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
    3262          52 :                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
    3263          15 :                                 continue;
    3264          37 :                         ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
    3265          37 :                         if (ret < 0 || ret >= end - pos)
    3266           0 :                                 return pos - buf;
    3267          37 :                         pos += ret;
    3268             :                 }
    3269           3 :                 ret = os_snprintf(pos, end - pos, "\n");
    3270           3 :                 if (ret < 0 || ret >= end - pos)
    3271           0 :                         return pos - buf;
    3272           3 :                 pos += ret;
    3273             :         }
    3274             : 
    3275           1 :         return pos - buf;
    3276             : }
    3277             : 
    3278             : 
    3279           1 : static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
    3280             :                                           char *buf, size_t buflen)
    3281             : {
    3282             :         struct hostapd_channel_data *chnl;
    3283             :         int ret, i, j;
    3284             :         char *pos, *end, *hmode;
    3285             : 
    3286           1 :         pos = buf;
    3287           1 :         end = pos + buflen;
    3288             : 
    3289           4 :         for (j = 0; j < wpa_s->hw.num_modes; j++) {
    3290           3 :                 switch (wpa_s->hw.modes[j].mode) {
    3291             :                 case HOSTAPD_MODE_IEEE80211B:
    3292           1 :                         hmode = "B";
    3293           1 :                         break;
    3294             :                 case HOSTAPD_MODE_IEEE80211G:
    3295           1 :                         hmode = "G";
    3296           1 :                         break;
    3297             :                 case HOSTAPD_MODE_IEEE80211A:
    3298           1 :                         hmode = "A";
    3299           1 :                         break;
    3300             :                 case HOSTAPD_MODE_IEEE80211AD:
    3301           0 :                         hmode = "AD";
    3302           0 :                         break;
    3303             :                 default:
    3304           0 :                         continue;
    3305             :                 }
    3306           3 :                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
    3307             :                                   hmode);
    3308           3 :                 if (ret < 0 || ret >= end - pos)
    3309           0 :                         return pos - buf;
    3310           3 :                 pos += ret;
    3311           3 :                 chnl = wpa_s->hw.modes[j].channels;
    3312          55 :                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
    3313          52 :                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
    3314          15 :                                 continue;
    3315         148 :                         ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
    3316          74 :                                           chnl[i].chan, chnl[i].freq,
    3317          37 :                                           chnl[i].flag & HOSTAPD_CHAN_NO_IBSS ?
    3318             :                                           " (NO_IBSS)" : "",
    3319          37 :                                           chnl[i].flag & HOSTAPD_CHAN_RADAR ?
    3320             :                                           " (DFS)" : "");
    3321             : 
    3322          37 :                         if (ret < 0 || ret >= end - pos)
    3323           0 :                                 return pos - buf;
    3324          37 :                         pos += ret;
    3325             :                 }
    3326           3 :                 ret = os_snprintf(pos, end - pos, "\n");
    3327           3 :                 if (ret < 0 || ret >= end - pos)
    3328           0 :                         return pos - buf;
    3329           3 :                 pos += ret;
    3330             :         }
    3331             : 
    3332           1 :         return pos - buf;
    3333             : }
    3334             : 
    3335             : 
    3336          18 : static int wpa_supplicant_ctrl_iface_get_capability(
    3337             :         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
    3338             :         size_t buflen)
    3339             : {
    3340             :         struct wpa_driver_capa capa;
    3341             :         int res;
    3342             :         char *strict;
    3343             :         char field[30];
    3344             :         size_t len;
    3345             : 
    3346             :         /* Determine whether or not strict checking was requested */
    3347          18 :         len = os_strlcpy(field, _field, sizeof(field));
    3348          18 :         if (len >= sizeof(field))
    3349           1 :                 return -1;
    3350          17 :         strict = os_strchr(field, ' ');
    3351          17 :         if (strict != NULL) {
    3352           1 :                 *strict++ = '\0';
    3353           1 :                 if (os_strcmp(strict, "strict") != 0)
    3354           0 :                         return -1;
    3355             :         }
    3356             : 
    3357          17 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
    3358             :                 field, strict ? strict : "");
    3359             : 
    3360          17 :         if (os_strcmp(field, "eap") == 0) {
    3361           1 :                 return eap_get_names(buf, buflen);
    3362             :         }
    3363             : 
    3364          16 :         res = wpa_drv_get_capa(wpa_s, &capa);
    3365             : 
    3366          16 :         if (os_strcmp(field, "pairwise") == 0)
    3367           6 :                 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
    3368             :                                                           buf, buflen);
    3369             : 
    3370          10 :         if (os_strcmp(field, "group") == 0)
    3371           1 :                 return ctrl_iface_get_capability_group(res, strict, &capa,
    3372             :                                                        buf, buflen);
    3373             : 
    3374           9 :         if (os_strcmp(field, "key_mgmt") == 0)
    3375           1 :                 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
    3376             :                                                           buf, buflen);
    3377             : 
    3378           8 :         if (os_strcmp(field, "proto") == 0)
    3379           1 :                 return ctrl_iface_get_capability_proto(res, strict, &capa,
    3380             :                                                        buf, buflen);
    3381             : 
    3382           7 :         if (os_strcmp(field, "auth_alg") == 0)
    3383           1 :                 return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
    3384             :                                                           buf, buflen);
    3385             : 
    3386           6 :         if (os_strcmp(field, "modes") == 0)
    3387           2 :                 return ctrl_iface_get_capability_modes(res, strict, &capa,
    3388             :                                                        buf, buflen);
    3389             : 
    3390           4 :         if (os_strcmp(field, "channels") == 0)
    3391           1 :                 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
    3392             : 
    3393           3 :         if (os_strcmp(field, "freq") == 0)
    3394           1 :                 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
    3395             : 
    3396             : #ifdef CONFIG_TDLS
    3397           2 :         if (os_strcmp(field, "tdls") == 0)
    3398           1 :                 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
    3399             : #endif /* CONFIG_TDLS */
    3400             : 
    3401           1 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
    3402             :                    field);
    3403             : 
    3404           1 :         return -1;
    3405             : }
    3406             : 
    3407             : 
    3408             : #ifdef CONFIG_INTERWORKING
    3409         312 : static char * anqp_add_hex(char *pos, char *end, const char *title,
    3410             :                            struct wpabuf *data)
    3411             : {
    3412         312 :         char *start = pos;
    3413             :         size_t i;
    3414             :         int ret;
    3415             :         const u8 *d;
    3416             : 
    3417         312 :         if (data == NULL)
    3418         260 :                 return start;
    3419             : 
    3420          52 :         ret = os_snprintf(pos, end - pos, "%s=", title);
    3421          52 :         if (ret < 0 || ret >= end - pos)
    3422           0 :                 return start;
    3423          52 :         pos += ret;
    3424             : 
    3425          52 :         d = wpabuf_head_u8(data);
    3426        1998 :         for (i = 0; i < wpabuf_len(data); i++) {
    3427        1946 :                 ret = os_snprintf(pos, end - pos, "%02x", *d++);
    3428        1946 :                 if (ret < 0 || ret >= end - pos)
    3429           0 :                         return start;
    3430        1946 :                 pos += ret;
    3431             :         }
    3432             : 
    3433          52 :         ret = os_snprintf(pos, end - pos, "\n");
    3434          52 :         if (ret < 0 || ret >= end - pos)
    3435           0 :                 return start;
    3436          52 :         pos += ret;
    3437             : 
    3438          52 :         return pos;
    3439             : }
    3440             : #endif /* CONFIG_INTERWORKING */
    3441             : 
    3442             : 
    3443         319 : static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
    3444             :                           unsigned long mask, char *buf, size_t buflen)
    3445             : {
    3446             :         size_t i;
    3447             :         int ret;
    3448             :         char *pos, *end;
    3449             :         const u8 *ie, *ie2;
    3450             : 
    3451         319 :         pos = buf;
    3452         319 :         end = buf + buflen;
    3453             : 
    3454         319 :         if (mask & WPA_BSS_MASK_ID) {
    3455         178 :                 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
    3456         178 :                 if (ret < 0 || ret >= end - pos)
    3457           0 :                         return 0;
    3458         178 :                 pos += ret;
    3459             :         }
    3460             : 
    3461         319 :         if (mask & WPA_BSS_MASK_BSSID) {
    3462        1794 :                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
    3463        1794 :                                   MAC2STR(bss->bssid));
    3464         299 :                 if (ret < 0 || ret >= end - pos)
    3465           0 :                         return 0;
    3466         299 :                 pos += ret;
    3467             :         }
    3468             : 
    3469         319 :         if (mask & WPA_BSS_MASK_FREQ) {
    3470         158 :                 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
    3471         158 :                 if (ret < 0 || ret >= end - pos)
    3472           0 :                         return 0;
    3473         158 :                 pos += ret;
    3474             :         }
    3475             : 
    3476         319 :         if (mask & WPA_BSS_MASK_BEACON_INT) {
    3477         158 :                 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
    3478         158 :                                   bss->beacon_int);
    3479         158 :                 if (ret < 0 || ret >= end - pos)
    3480           0 :                         return 0;
    3481         158 :                 pos += ret;
    3482             :         }
    3483             : 
    3484         319 :         if (mask & WPA_BSS_MASK_CAPABILITIES) {
    3485         158 :                 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
    3486         158 :                                   bss->caps);
    3487         158 :                 if (ret < 0 || ret >= end - pos)
    3488           0 :                         return 0;
    3489         158 :                 pos += ret;
    3490             :         }
    3491             : 
    3492         319 :         if (mask & WPA_BSS_MASK_QUAL) {
    3493         158 :                 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
    3494         158 :                 if (ret < 0 || ret >= end - pos)
    3495           0 :                         return 0;
    3496         158 :                 pos += ret;
    3497             :         }
    3498             : 
    3499         319 :         if (mask & WPA_BSS_MASK_NOISE) {
    3500         158 :                 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
    3501         158 :                 if (ret < 0 || ret >= end - pos)
    3502           0 :                         return 0;
    3503         158 :                 pos += ret;
    3504             :         }
    3505             : 
    3506         319 :         if (mask & WPA_BSS_MASK_LEVEL) {
    3507         158 :                 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
    3508         158 :                 if (ret < 0 || ret >= end - pos)
    3509           0 :                         return 0;
    3510         158 :                 pos += ret;
    3511             :         }
    3512             : 
    3513         319 :         if (mask & WPA_BSS_MASK_TSF) {
    3514         158 :                 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
    3515         158 :                                   (unsigned long long) bss->tsf);
    3516         158 :                 if (ret < 0 || ret >= end - pos)
    3517           0 :                         return 0;
    3518         158 :                 pos += ret;
    3519             :         }
    3520             : 
    3521         319 :         if (mask & WPA_BSS_MASK_AGE) {
    3522             :                 struct os_reltime now;
    3523             : 
    3524         158 :                 os_get_reltime(&now);
    3525         316 :                 ret = os_snprintf(pos, end - pos, "age=%d\n",
    3526         316 :                                   (int) (now.sec - bss->last_update.sec));
    3527         158 :                 if (ret < 0 || ret >= end - pos)
    3528           0 :                         return 0;
    3529         158 :                 pos += ret;
    3530             :         }
    3531             : 
    3532         319 :         if (mask & WPA_BSS_MASK_IE) {
    3533         158 :                 ret = os_snprintf(pos, end - pos, "ie=");
    3534         158 :                 if (ret < 0 || ret >= end - pos)
    3535           0 :                         return 0;
    3536         158 :                 pos += ret;
    3537             : 
    3538         158 :                 ie = (const u8 *) (bss + 1);
    3539       30932 :                 for (i = 0; i < bss->ie_len; i++) {
    3540       30774 :                         ret = os_snprintf(pos, end - pos, "%02x", *ie++);
    3541       30774 :                         if (ret < 0 || ret >= end - pos)
    3542           0 :                                 return 0;
    3543       30774 :                         pos += ret;
    3544             :                 }
    3545             : 
    3546         158 :                 ret = os_snprintf(pos, end - pos, "\n");
    3547         158 :                 if (ret < 0 || ret >= end - pos)
    3548           0 :                         return 0;
    3549         158 :                 pos += ret;
    3550             :         }
    3551             : 
    3552         319 :         if (mask & WPA_BSS_MASK_FLAGS) {
    3553         158 :                 ret = os_snprintf(pos, end - pos, "flags=");
    3554         158 :                 if (ret < 0 || ret >= end - pos)
    3555           0 :                         return 0;
    3556         158 :                 pos += ret;
    3557             : 
    3558         158 :                 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
    3559         158 :                 if (ie)
    3560          10 :                         pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
    3561          10 :                                                     2 + ie[1]);
    3562         158 :                 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
    3563         158 :                 if (ie2)
    3564         134 :                         pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
    3565         134 :                                                     2 + ie2[1]);
    3566         158 :                 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
    3567         158 :                 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
    3568           0 :                         ret = os_snprintf(pos, end - pos, "[WEP]");
    3569           0 :                         if (ret < 0 || ret >= end - pos)
    3570           0 :                                 return 0;
    3571           0 :                         pos += ret;
    3572             :                 }
    3573         158 :                 if (bss_is_dmg(bss)) {
    3574             :                         const char *s;
    3575           0 :                         ret = os_snprintf(pos, end - pos, "[DMG]");
    3576           0 :                         if (ret < 0 || ret >= end - pos)
    3577           0 :                                 return 0;
    3578           0 :                         pos += ret;
    3579           0 :                         switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
    3580             :                         case IEEE80211_CAP_DMG_IBSS:
    3581           0 :                                 s = "[IBSS]";
    3582           0 :                                 break;
    3583             :                         case IEEE80211_CAP_DMG_AP:
    3584           0 :                                 s = "[ESS]";
    3585           0 :                                 break;
    3586             :                         case IEEE80211_CAP_DMG_PBSS:
    3587           0 :                                 s = "[PBSS]";
    3588           0 :                                 break;
    3589             :                         default:
    3590           0 :                                 s = "";
    3591           0 :                                 break;
    3592             :                         }
    3593           0 :                         ret = os_snprintf(pos, end - pos, "%s", s);
    3594           0 :                         if (ret < 0 || ret >= end - pos)
    3595           0 :                                 return 0;
    3596           0 :                         pos += ret;
    3597             :                 } else {
    3598         158 :                         if (bss->caps & IEEE80211_CAP_IBSS) {
    3599           0 :                                 ret = os_snprintf(pos, end - pos, "[IBSS]");
    3600           0 :                                 if (ret < 0 || ret >= end - pos)
    3601           0 :                                         return 0;
    3602           0 :                                 pos += ret;
    3603             :                         }
    3604         158 :                         if (bss->caps & IEEE80211_CAP_ESS) {
    3605         158 :                                 ret = os_snprintf(pos, end - pos, "[ESS]");
    3606         158 :                                 if (ret < 0 || ret >= end - pos)
    3607           0 :                                         return 0;
    3608         158 :                                 pos += ret;
    3609             :                         }
    3610             :                 }
    3611         312 :                 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
    3612         154 :                     wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
    3613           4 :                         ret = os_snprintf(pos, end - pos, "[P2P]");
    3614           4 :                         if (ret < 0 || ret >= end - pos)
    3615           0 :                                 return 0;
    3616           4 :                         pos += ret;
    3617             :                 }
    3618             : #ifdef CONFIG_HS20
    3619         158 :                 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
    3620          92 :                         ret = os_snprintf(pos, end - pos, "[HS20]");
    3621          92 :                         if (ret < 0 || ret >= end - pos)
    3622           0 :                                 return 0;
    3623          92 :                         pos += ret;
    3624             :                 }
    3625             : #endif /* CONFIG_HS20 */
    3626             : 
    3627         158 :                 ret = os_snprintf(pos, end - pos, "\n");
    3628         158 :                 if (ret < 0 || ret >= end - pos)
    3629           0 :                         return 0;
    3630         158 :                 pos += ret;
    3631             :         }
    3632             : 
    3633         319 :         if (mask & WPA_BSS_MASK_SSID) {
    3634         316 :                 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
    3635         158 :                                   wpa_ssid_txt(bss->ssid, bss->ssid_len));
    3636         158 :                 if (ret < 0 || ret >= end - pos)
    3637           0 :                         return 0;
    3638         158 :                 pos += ret;
    3639             :         }
    3640             : 
    3641             : #ifdef CONFIG_WPS
    3642         319 :         if (mask & WPA_BSS_MASK_WPS_SCAN) {
    3643         158 :                 ie = (const u8 *) (bss + 1);
    3644         158 :                 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
    3645         158 :                 if (ret < 0 || ret >= end - pos)
    3646           0 :                         return 0;
    3647         158 :                 pos += ret;
    3648             :         }
    3649             : #endif /* CONFIG_WPS */
    3650             : 
    3651             : #ifdef CONFIG_P2P
    3652         319 :         if (mask & WPA_BSS_MASK_P2P_SCAN) {
    3653         158 :                 ie = (const u8 *) (bss + 1);
    3654         158 :                 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
    3655         158 :                 if (ret < 0 || ret >= end - pos)
    3656           0 :                         return 0;
    3657         158 :                 pos += ret;
    3658             :         }
    3659             : #endif /* CONFIG_P2P */
    3660             : 
    3661             : #ifdef CONFIG_WIFI_DISPLAY
    3662         319 :         if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
    3663             :                 struct wpabuf *wfd;
    3664         158 :                 ie = (const u8 *) (bss + 1);
    3665         158 :                 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
    3666             :                                                   WFD_IE_VENDOR_TYPE);
    3667         158 :                 if (wfd) {
    3668           2 :                         ret = os_snprintf(pos, end - pos, "wfd_subelems=");
    3669           2 :                         if (ret < 0 || ret >= end - pos) {
    3670           0 :                                 wpabuf_free(wfd);
    3671           0 :                                 return 0;
    3672             :                         }
    3673           2 :                         pos += ret;
    3674             : 
    3675           4 :                         pos += wpa_snprintf_hex(pos, end - pos,
    3676           2 :                                                 wpabuf_head(wfd),
    3677             :                                                 wpabuf_len(wfd));
    3678           2 :                         wpabuf_free(wfd);
    3679             : 
    3680           2 :                         ret = os_snprintf(pos, end - pos, "\n");
    3681           2 :                         if (ret < 0 || ret >= end - pos)
    3682           0 :                                 return 0;
    3683           2 :                         pos += ret;
    3684             :                 }
    3685             :         }
    3686             : #endif /* CONFIG_WIFI_DISPLAY */
    3687             : 
    3688             : #ifdef CONFIG_INTERWORKING
    3689         319 :         if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
    3690          26 :                 struct wpa_bss_anqp *anqp = bss->anqp;
    3691          26 :                 pos = anqp_add_hex(pos, end, "anqp_venue_name",
    3692             :                                    anqp->venue_name);
    3693          26 :                 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
    3694             :                                    anqp->network_auth_type);
    3695          26 :                 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
    3696             :                                    anqp->roaming_consortium);
    3697          26 :                 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
    3698             :                                    anqp->ip_addr_type_availability);
    3699          26 :                 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
    3700             :                                    anqp->nai_realm);
    3701          26 :                 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
    3702          26 :                 pos = anqp_add_hex(pos, end, "anqp_domain_name",
    3703             :                                    anqp->domain_name);
    3704             : #ifdef CONFIG_HS20
    3705          26 :                 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
    3706             :                                    anqp->hs20_operator_friendly_name);
    3707          26 :                 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
    3708             :                                    anqp->hs20_wan_metrics);
    3709          26 :                 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
    3710             :                                    anqp->hs20_connection_capability);
    3711          26 :                 pos = anqp_add_hex(pos, end, "hs20_operating_class",
    3712             :                                    anqp->hs20_operating_class);
    3713          26 :                 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
    3714             :                                    anqp->hs20_osu_providers_list);
    3715             : #endif /* CONFIG_HS20 */
    3716             :         }
    3717             : #endif /* CONFIG_INTERWORKING */
    3718             : 
    3719         319 :         if (mask & WPA_BSS_MASK_DELIM) {
    3720           2 :                 ret = os_snprintf(pos, end - pos, "====\n");
    3721           2 :                 if (ret < 0 || ret >= end - pos)
    3722           0 :                         return 0;
    3723           2 :                 pos += ret;
    3724             :         }
    3725             : 
    3726         319 :         return pos - buf;
    3727             : }
    3728             : 
    3729             : 
    3730         311 : static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
    3731             :                                          const char *cmd, char *buf,
    3732             :                                          size_t buflen)
    3733             : {
    3734             :         u8 bssid[ETH_ALEN];
    3735             :         size_t i;
    3736             :         struct wpa_bss *bss;
    3737         311 :         struct wpa_bss *bsslast = NULL;
    3738             :         struct dl_list *next;
    3739         311 :         int ret = 0;
    3740             :         int len;
    3741             :         char *ctmp;
    3742         311 :         unsigned long mask = WPA_BSS_MASK_ALL;
    3743             : 
    3744         311 :         if (os_strncmp(cmd, "RANGE=", 6) == 0) {
    3745          91 :                 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
    3746          83 :                         bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
    3747             :                                             list_id);
    3748          83 :                         bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
    3749             :                                                list_id);
    3750             :                 } else { /* N1-N2 */
    3751             :                         unsigned int id1, id2;
    3752             : 
    3753           8 :                         if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
    3754           1 :                                 wpa_printf(MSG_INFO, "Wrong BSS range "
    3755             :                                            "format");
    3756           1 :                                 return 0;
    3757             :                         }
    3758             : 
    3759           7 :                         if (*(cmd + 6) == '-')
    3760           1 :                                 id1 = 0;
    3761             :                         else
    3762           6 :                                 id1 = atoi(cmd + 6);
    3763           7 :                         ctmp++;
    3764           7 :                         if (*ctmp >= '0' && *ctmp <= '9')
    3765           5 :                                 id2 = atoi(ctmp);
    3766             :                         else
    3767           2 :                                 id2 = (unsigned int) -1;
    3768           7 :                         bss = wpa_bss_get_id_range(wpa_s, id1, id2);
    3769           7 :                         if (id2 == (unsigned int) -1)
    3770           2 :                                 bsslast = dl_list_last(&wpa_s->bss_id,
    3771             :                                                        struct wpa_bss,
    3772             :                                                        list_id);
    3773             :                         else {
    3774           5 :                                 bsslast = wpa_bss_get_id(wpa_s, id2);
    3775           5 :                                 if (bsslast == NULL && bss && id2 > id1) {
    3776           1 :                                         struct wpa_bss *tmp = bss;
    3777             :                                         for (;;) {
    3778           2 :                                                 next = tmp->list_id.next;
    3779           2 :                                                 if (next == &wpa_s->bss_id)
    3780           1 :                                                         break;
    3781           1 :                                                 tmp = dl_list_entry(
    3782             :                                                         next, struct wpa_bss,
    3783             :                                                         list_id);
    3784           1 :                                                 if (tmp->id > id2)
    3785           0 :                                                         break;
    3786           1 :                                                 bsslast = tmp;
    3787           1 :                                         }
    3788             :                                 }
    3789             :                         }
    3790             :                 }
    3791         220 :         } else if (os_strncmp(cmd, "FIRST", 5) == 0)
    3792           2 :                 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
    3793         218 :         else if (os_strncmp(cmd, "LAST", 4) == 0)
    3794           2 :                 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
    3795         216 :         else if (os_strncmp(cmd, "ID-", 3) == 0) {
    3796           2 :                 i = atoi(cmd + 3);
    3797           2 :                 bss = wpa_bss_get_id(wpa_s, i);
    3798         214 :         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
    3799           1 :                 i = atoi(cmd + 5);
    3800           1 :                 bss = wpa_bss_get_id(wpa_s, i);
    3801           1 :                 if (bss) {
    3802           1 :                         next = bss->list_id.next;
    3803           1 :                         if (next == &wpa_s->bss_id)
    3804           0 :                                 bss = NULL;
    3805             :                         else
    3806           1 :                                 bss = dl_list_entry(next, struct wpa_bss,
    3807             :                                                     list_id);
    3808             :                 }
    3809             : #ifdef CONFIG_P2P
    3810         213 :         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
    3811           3 :                 if (hwaddr_aton(cmd + 13, bssid) == 0)
    3812           3 :                         bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
    3813             :                 else
    3814           0 :                         bss = NULL;
    3815             : #endif /* CONFIG_P2P */
    3816         210 :         } else if (hwaddr_aton(cmd, bssid) == 0)
    3817         200 :                 bss = wpa_bss_get_bssid(wpa_s, bssid);
    3818             :         else {
    3819             :                 struct wpa_bss *tmp;
    3820          10 :                 i = atoi(cmd);
    3821          10 :                 bss = NULL;
    3822          10 :                 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
    3823             :                 {
    3824           5 :                         if (i-- == 0) {
    3825           5 :                                 bss = tmp;
    3826           5 :                                 break;
    3827             :                         }
    3828             :                 }
    3829             :         }
    3830             : 
    3831         310 :         if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
    3832          96 :                 mask = strtoul(ctmp + 5, NULL, 0x10);
    3833          96 :                 if (mask == 0)
    3834           0 :                         mask = WPA_BSS_MASK_ALL;
    3835             :         }
    3836             : 
    3837         310 :         if (bss == NULL)
    3838          71 :                 return 0;
    3839             : 
    3840         239 :         if (bsslast == NULL)
    3841         164 :                 bsslast = bss;
    3842             :         do {
    3843         319 :                 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
    3844         319 :                 ret += len;
    3845         319 :                 buf += len;
    3846         319 :                 buflen -= len;
    3847         319 :                 if (bss == bsslast) {
    3848         240 :                         if ((mask & WPA_BSS_MASK_DELIM) && len &&
    3849           1 :                             (bss == dl_list_last(&wpa_s->bss_id,
    3850             :                                                  struct wpa_bss, list_id)))
    3851           1 :                                 os_snprintf(buf - 5, 5, "####\n");
    3852         239 :                         break;
    3853             :                 }
    3854          80 :                 next = bss->list_id.next;
    3855          80 :                 if (next == &wpa_s->bss_id)
    3856           0 :                         break;
    3857          80 :                 bss = dl_list_entry(next, struct wpa_bss, list_id);
    3858          80 :         } while (bss && len);
    3859             : 
    3860         239 :         return ret;
    3861             : }
    3862             : 
    3863             : 
    3864           8 : static int wpa_supplicant_ctrl_iface_ap_scan(
    3865             :         struct wpa_supplicant *wpa_s, char *cmd)
    3866             : {
    3867           8 :         int ap_scan = atoi(cmd);
    3868           8 :         return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
    3869             : }
    3870             : 
    3871             : 
    3872           3 : static int wpa_supplicant_ctrl_iface_scan_interval(
    3873             :         struct wpa_supplicant *wpa_s, char *cmd)
    3874             : {
    3875           3 :         int scan_int = atoi(cmd);
    3876           3 :         return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
    3877             : }
    3878             : 
    3879             : 
    3880           3 : static int wpa_supplicant_ctrl_iface_bss_expire_age(
    3881             :         struct wpa_supplicant *wpa_s, char *cmd)
    3882             : {
    3883           3 :         int expire_age = atoi(cmd);
    3884           3 :         return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
    3885             : }
    3886             : 
    3887             : 
    3888           2 : static int wpa_supplicant_ctrl_iface_bss_expire_count(
    3889             :         struct wpa_supplicant *wpa_s, char *cmd)
    3890             : {
    3891           2 :         int expire_count = atoi(cmd);
    3892           2 :         return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
    3893             : }
    3894             : 
    3895             : 
    3896          89 : static int wpa_supplicant_ctrl_iface_bss_flush(
    3897             :         struct wpa_supplicant *wpa_s, char *cmd)
    3898             : {
    3899          89 :         int flush_age = atoi(cmd);
    3900             : 
    3901          89 :         if (flush_age == 0)
    3902          89 :                 wpa_bss_flush(wpa_s);
    3903             :         else
    3904           0 :                 wpa_bss_flush_by_age(wpa_s, flush_age);
    3905          89 :         return 0;
    3906             : }
    3907             : 
    3908             : 
    3909             : #ifdef CONFIG_TESTING_OPTIONS
    3910           1 : static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
    3911             : {
    3912           1 :         wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
    3913             :         /* MLME-DELETEKEYS.request */
    3914           1 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
    3915           1 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
    3916           1 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
    3917           1 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
    3918             : #ifdef CONFIG_IEEE80211W
    3919           1 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
    3920           1 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
    3921             : #endif /* CONFIG_IEEE80211W */
    3922             : 
    3923           1 :         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
    3924             :                         0);
    3925             :         /* MLME-SETPROTECTION.request(None) */
    3926           1 :         wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
    3927             :                                    MLME_SETPROTECTION_PROTECT_TYPE_NONE,
    3928             :                                    MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
    3929           1 :         wpa_sm_drop_sa(wpa_s->wpa);
    3930           1 : }
    3931             : #endif /* CONFIG_TESTING_OPTIONS */
    3932             : 
    3933             : 
    3934          28 : static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
    3935             :                                           char *addr)
    3936             : {
    3937             : #ifdef CONFIG_NO_SCAN_PROCESSING
    3938             :         return -1;
    3939             : #else /* CONFIG_NO_SCAN_PROCESSING */
    3940             :         u8 bssid[ETH_ALEN];
    3941             :         struct wpa_bss *bss;
    3942          28 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
    3943             : 
    3944          28 :         if (hwaddr_aton(addr, bssid)) {
    3945           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
    3946             :                            "address '%s'", addr);
    3947           1 :                 return -1;
    3948             :         }
    3949             : 
    3950          27 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
    3951             : 
    3952          27 :         if (!ssid) {
    3953           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
    3954             :                            "configuration known for the target AP");
    3955           1 :                 return -1;
    3956             :         }
    3957             : 
    3958          26 :         bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
    3959          26 :         if (!bss) {
    3960           1 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
    3961             :                            "from BSS table");
    3962           1 :                 return -1;
    3963             :         }
    3964             : 
    3965             :         /*
    3966             :          * TODO: Find best network configuration block from configuration to
    3967             :          * allow roaming to other networks
    3968             :          */
    3969             : 
    3970          25 :         wpa_s->reassociate = 1;
    3971          25 :         wpa_supplicant_connect(wpa_s, bss, ssid);
    3972             : 
    3973          25 :         return 0;
    3974             : #endif /* CONFIG_NO_SCAN_PROCESSING */
    3975             : }
    3976             : 
    3977             : 
    3978             : #ifdef CONFIG_P2P
    3979         208 : static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
    3980             : {
    3981         208 :         unsigned int timeout = atoi(cmd);
    3982         208 :         enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
    3983         208 :         u8 dev_id[ETH_ALEN], *_dev_id = NULL;
    3984         208 :         u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
    3985             :         char *pos;
    3986             :         unsigned int search_delay;
    3987             : 
    3988         208 :         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
    3989           1 :                 wpa_dbg(wpa_s, MSG_INFO,
    3990             :                         "Reject P2P_FIND since interface is disabled");
    3991           1 :                 return -1;
    3992             :         }
    3993         207 :         if (os_strstr(cmd, "type=social"))
    3994         180 :                 type = P2P_FIND_ONLY_SOCIAL;
    3995          27 :         else if (os_strstr(cmd, "type=progressive"))
    3996           1 :                 type = P2P_FIND_PROGRESSIVE;
    3997             : 
    3998         207 :         pos = os_strstr(cmd, "dev_id=");
    3999         207 :         if (pos) {
    4000           4 :                 pos += 7;
    4001           4 :                 if (hwaddr_aton(pos, dev_id))
    4002           0 :                         return -1;
    4003           4 :                 _dev_id = dev_id;
    4004             :         }
    4005             : 
    4006         207 :         pos = os_strstr(cmd, "dev_type=");
    4007         207 :         if (pos) {
    4008           4 :                 pos += 9;
    4009           4 :                 if (wps_dev_type_str2bin(pos, dev_type) < 0)
    4010           0 :                         return -1;
    4011           4 :                 _dev_type = dev_type;
    4012             :         }
    4013             : 
    4014         207 :         pos = os_strstr(cmd, "delay=");
    4015         207 :         if (pos) {
    4016           0 :                 pos += 6;
    4017           0 :                 search_delay = atoi(pos);
    4018             :         } else
    4019         207 :                 search_delay = wpas_p2p_search_delay(wpa_s);
    4020             : 
    4021         207 :         return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
    4022             :                              _dev_id, search_delay);
    4023             : }
    4024             : 
    4025             : 
    4026         184 : static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
    4027             :                             char *buf, size_t buflen)
    4028             : {
    4029             :         u8 addr[ETH_ALEN];
    4030             :         char *pos, *pos2;
    4031         184 :         char *pin = NULL;
    4032             :         enum p2p_wps_method wps_method;
    4033             :         int new_pin;
    4034             :         int ret;
    4035         184 :         int persistent_group, persistent_id = -1;
    4036             :         int join;
    4037             :         int auth;
    4038             :         int automatic;
    4039         184 :         int go_intent = -1;
    4040         184 :         int freq = 0;
    4041             :         int pd;
    4042             :         int ht40, vht;
    4043             : 
    4044             :         /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
    4045             :          * [persistent|persistent=<network id>]
    4046             :          * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
    4047             :          * [ht40] [vht] */
    4048             : 
    4049         184 :         if (hwaddr_aton(cmd, addr))
    4050           0 :                 return -1;
    4051             : 
    4052         184 :         pos = cmd + 17;
    4053         184 :         if (*pos != ' ')
    4054           0 :                 return -1;
    4055         184 :         pos++;
    4056             : 
    4057         184 :         persistent_group = os_strstr(pos, " persistent") != NULL;
    4058         184 :         pos2 = os_strstr(pos, " persistent=");
    4059         184 :         if (pos2) {
    4060             :                 struct wpa_ssid *ssid;
    4061           1 :                 persistent_id = atoi(pos2 + 12);
    4062           1 :                 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
    4063           2 :                 if (ssid == NULL || ssid->disabled != 2 ||
    4064           1 :                     ssid->mode != WPAS_MODE_P2P_GO) {
    4065           0 :                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
    4066             :                                    "SSID id=%d for persistent P2P group (GO)",
    4067             :                                    persistent_id);
    4068           0 :                         return -1;
    4069             :                 }
    4070             :         }
    4071         184 :         join = os_strstr(pos, " join") != NULL;
    4072         184 :         auth = os_strstr(pos, " auth") != NULL;
    4073         184 :         automatic = os_strstr(pos, " auto") != NULL;
    4074         184 :         pd = os_strstr(pos, " provdisc") != NULL;
    4075         184 :         vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
    4076         184 :         ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
    4077             :                 vht;
    4078             : 
    4079         184 :         pos2 = os_strstr(pos, " go_intent=");
    4080         184 :         if (pos2) {
    4081          61 :                 pos2 += 11;
    4082          61 :                 go_intent = atoi(pos2);
    4083          61 :                 if (go_intent < 0 || go_intent > 15)
    4084           0 :                         return -1;
    4085             :         }
    4086             : 
    4087         184 :         pos2 = os_strstr(pos, " freq=");
    4088         184 :         if (pos2) {
    4089          20 :                 pos2 += 6;
    4090          20 :                 freq = atoi(pos2);
    4091          20 :                 if (freq <= 0)
    4092           0 :                         return -1;
    4093             :         }
    4094             : 
    4095         184 :         if (os_strncmp(pos, "pin", 3) == 0) {
    4096             :                 /* Request random PIN (to be displayed) and enable the PIN */
    4097           0 :                 wps_method = WPS_PIN_DISPLAY;
    4098         184 :         } else if (os_strncmp(pos, "pbc", 3) == 0) {
    4099          38 :                 wps_method = WPS_PBC;
    4100             :         } else {
    4101         146 :                 pin = pos;
    4102         146 :                 pos = os_strchr(pin, ' ');
    4103         146 :                 wps_method = WPS_PIN_KEYPAD;
    4104         146 :                 if (pos) {
    4105         146 :                         *pos++ = '\0';
    4106         146 :                         if (os_strncmp(pos, "display", 7) == 0)
    4107          60 :                                 wps_method = WPS_PIN_DISPLAY;
    4108             :                 }
    4109         146 :                 if (!wps_pin_str_valid(pin)) {
    4110           0 :                         os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
    4111           0 :                         return 17;
    4112             :                 }
    4113             :         }
    4114             : 
    4115         184 :         new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
    4116             :                                    persistent_group, automatic, join,
    4117             :                                    auth, go_intent, freq, persistent_id, pd,
    4118             :                                    ht40, vht);
    4119         184 :         if (new_pin == -2) {
    4120           0 :                 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
    4121           0 :                 return 25;
    4122             :         }
    4123         184 :         if (new_pin == -3) {
    4124           0 :                 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
    4125           0 :                 return 25;
    4126             :         }
    4127         184 :         if (new_pin < 0)
    4128           0 :                 return -1;
    4129         184 :         if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
    4130           0 :                 ret = os_snprintf(buf, buflen, "%08d", new_pin);
    4131           0 :                 if (ret < 0 || (size_t) ret >= buflen)
    4132           0 :                         return -1;
    4133           0 :                 return ret;
    4134             :         }
    4135             : 
    4136         184 :         os_memcpy(buf, "OK\n", 3);
    4137         184 :         return 3;
    4138             : }
    4139             : 
    4140             : 
    4141         205 : static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
    4142             : {
    4143         205 :         unsigned int timeout = atoi(cmd);
    4144         205 :         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
    4145           0 :                 wpa_dbg(wpa_s, MSG_INFO,
    4146             :                         "Reject P2P_LISTEN since interface is disabled");
    4147           0 :                 return -1;
    4148             :         }
    4149         205 :         return wpas_p2p_listen(wpa_s, timeout);
    4150             : }
    4151             : 
    4152             : 
    4153           8 : static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
    4154             : {
    4155             :         u8 addr[ETH_ALEN];
    4156             :         char *pos;
    4157           8 :         enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
    4158             : 
    4159             :         /* <addr> <config method> [join|auto] */
    4160             : 
    4161           8 :         if (hwaddr_aton(cmd, addr))
    4162           0 :                 return -1;
    4163             : 
    4164           8 :         pos = cmd + 17;
    4165           8 :         if (*pos != ' ')
    4166           0 :                 return -1;
    4167           8 :         pos++;
    4168             : 
    4169           8 :         if (os_strstr(pos, " join") != NULL)
    4170           0 :                 use = WPAS_P2P_PD_FOR_JOIN;
    4171           8 :         else if (os_strstr(pos, " auto") != NULL)
    4172           0 :                 use = WPAS_P2P_PD_AUTO;
    4173             : 
    4174           8 :         return wpas_p2p_prov_disc(wpa_s, addr, pos, use);
    4175             : }
    4176             : 
    4177             : 
    4178           0 : static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
    4179             :                               size_t buflen)
    4180             : {
    4181           0 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
    4182             : 
    4183           0 :         if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
    4184           0 :             ssid->passphrase == NULL)
    4185           0 :                 return -1;
    4186             : 
    4187           0 :         os_strlcpy(buf, ssid->passphrase, buflen);
    4188           0 :         return os_strlen(buf);
    4189             : }
    4190             : 
    4191             : 
    4192          25 : static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
    4193             :                                   char *buf, size_t buflen)
    4194             : {
    4195             :         u64 ref;
    4196             :         int res;
    4197             :         u8 dst_buf[ETH_ALEN], *dst;
    4198             :         struct wpabuf *tlvs;
    4199             :         char *pos;
    4200             :         size_t len;
    4201             : 
    4202          25 :         if (hwaddr_aton(cmd, dst_buf))
    4203           0 :                 return -1;
    4204          25 :         dst = dst_buf;
    4205          38 :         if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
    4206          26 :             dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
    4207          13 :                 dst = NULL;
    4208          25 :         pos = cmd + 17;
    4209          25 :         if (*pos != ' ')
    4210           0 :                 return -1;
    4211          25 :         pos++;
    4212             : 
    4213          25 :         if (os_strncmp(pos, "upnp ", 5) == 0) {
    4214             :                 u8 version;
    4215           1 :                 pos += 5;
    4216           1 :                 if (hexstr2bin(pos, &version, 1) < 0)
    4217           0 :                         return -1;
    4218           1 :                 pos += 2;
    4219           1 :                 if (*pos != ' ')
    4220           0 :                         return -1;
    4221           1 :                 pos++;
    4222           1 :                 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
    4223             : #ifdef CONFIG_WIFI_DISPLAY
    4224          24 :         } else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
    4225           1 :                 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
    4226             : #endif /* CONFIG_WIFI_DISPLAY */
    4227             :         } else {
    4228          23 :                 len = os_strlen(pos);
    4229          23 :                 if (len & 1)
    4230           0 :                         return -1;
    4231          23 :                 len /= 2;
    4232          23 :                 tlvs = wpabuf_alloc(len);
    4233          23 :                 if (tlvs == NULL)
    4234           0 :                         return -1;
    4235          23 :                 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
    4236           0 :                         wpabuf_free(tlvs);
    4237           0 :                         return -1;
    4238             :                 }
    4239             : 
    4240          23 :                 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
    4241          23 :                 wpabuf_free(tlvs);
    4242             :         }
    4243          25 :         if (ref == 0)
    4244           0 :                 return -1;
    4245          25 :         res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
    4246          25 :         if (res < 0 || (unsigned) res >= buflen)
    4247           0 :                 return -1;
    4248          25 :         return res;
    4249             : }
    4250             : 
    4251             : 
    4252           6 : static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
    4253             :                                          char *cmd)
    4254             : {
    4255             :         long long unsigned val;
    4256             :         u64 req;
    4257           6 :         if (sscanf(cmd, "%llx", &val) != 1)
    4258           0 :                 return -1;
    4259           6 :         req = val;
    4260           6 :         return wpas_p2p_sd_cancel_request(wpa_s, req);
    4261             : }
    4262             : 
    4263             : 
    4264           0 : static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
    4265             : {
    4266             :         int freq;
    4267             :         u8 dst[ETH_ALEN];
    4268             :         u8 dialog_token;
    4269             :         struct wpabuf *resp_tlvs;
    4270             :         char *pos, *pos2;
    4271             :         size_t len;
    4272             : 
    4273           0 :         pos = os_strchr(cmd, ' ');
    4274           0 :         if (pos == NULL)
    4275           0 :                 return -1;
    4276           0 :         *pos++ = '\0';
    4277           0 :         freq = atoi(cmd);
    4278           0 :         if (freq == 0)
    4279           0 :                 return -1;
    4280             : 
    4281           0 :         if (hwaddr_aton(pos, dst))
    4282           0 :                 return -1;
    4283           0 :         pos += 17;
    4284           0 :         if (*pos != ' ')
    4285           0 :                 return -1;
    4286           0 :         pos++;
    4287             : 
    4288           0 :         pos2 = os_strchr(pos, ' ');
    4289           0 :         if (pos2 == NULL)
    4290           0 :                 return -1;
    4291           0 :         *pos2++ = '\0';
    4292           0 :         dialog_token = atoi(pos);
    4293             : 
    4294           0 :         len = os_strlen(pos2);
    4295           0 :         if (len & 1)
    4296           0 :                 return -1;
    4297           0 :         len /= 2;
    4298           0 :         resp_tlvs = wpabuf_alloc(len);
    4299           0 :         if (resp_tlvs == NULL)
    4300           0 :                 return -1;
    4301           0 :         if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
    4302           0 :                 wpabuf_free(resp_tlvs);
    4303           0 :                 return -1;
    4304             :         }
    4305             : 
    4306           0 :         wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
    4307           0 :         wpabuf_free(resp_tlvs);
    4308           0 :         return 0;
    4309             : }
    4310             : 
    4311             : 
    4312           0 : static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
    4313             :                                        char *cmd)
    4314             : {
    4315           0 :         if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
    4316           0 :                 return -1;
    4317           0 :         wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
    4318           0 :         return 0;
    4319             : }
    4320             : 
    4321             : 
    4322          60 : static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
    4323             :                                         char *cmd)
    4324             : {
    4325             :         char *pos;
    4326             :         size_t len;
    4327             :         struct wpabuf *query, *resp;
    4328             : 
    4329          60 :         pos = os_strchr(cmd, ' ');
    4330          60 :         if (pos == NULL)
    4331           0 :                 return -1;
    4332          60 :         *pos++ = '\0';
    4333             : 
    4334          60 :         len = os_strlen(cmd);
    4335          60 :         if (len & 1)
    4336           0 :                 return -1;
    4337          60 :         len /= 2;
    4338          60 :         query = wpabuf_alloc(len);
    4339          60 :         if (query == NULL)
    4340           0 :                 return -1;
    4341          60 :         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
    4342           0 :                 wpabuf_free(query);
    4343           0 :                 return -1;
    4344             :         }
    4345             : 
    4346          60 :         len = os_strlen(pos);
    4347          60 :         if (len & 1) {
    4348           0 :                 wpabuf_free(query);
    4349           0 :                 return -1;
    4350             :         }
    4351          60 :         len /= 2;
    4352          60 :         resp = wpabuf_alloc(len);
    4353          60 :         if (resp == NULL) {
    4354           0 :                 wpabuf_free(query);
    4355           0 :                 return -1;
    4356             :         }
    4357          60 :         if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
    4358           0 :                 wpabuf_free(query);
    4359           0 :                 wpabuf_free(resp);
    4360           0 :                 return -1;
    4361             :         }
    4362             : 
    4363          60 :         if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
    4364           0 :                 wpabuf_free(query);
    4365           0 :                 wpabuf_free(resp);
    4366           0 :                 return -1;
    4367             :         }
    4368          60 :         return 0;
    4369             : }
    4370             : 
    4371             : 
    4372         275 : static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
    4373             : {
    4374             :         char *pos;
    4375             :         u8 version;
    4376             : 
    4377         275 :         pos = os_strchr(cmd, ' ');
    4378         275 :         if (pos == NULL)
    4379           0 :                 return -1;
    4380         275 :         *pos++ = '\0';
    4381             : 
    4382         275 :         if (hexstr2bin(cmd, &version, 1) < 0)
    4383           0 :                 return -1;
    4384             : 
    4385         275 :         return wpas_p2p_service_add_upnp(wpa_s, version, pos);
    4386             : }
    4387             : 
    4388             : 
    4389         335 : static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
    4390             : {
    4391             :         char *pos;
    4392             : 
    4393         335 :         pos = os_strchr(cmd, ' ');
    4394         335 :         if (pos == NULL)
    4395           0 :                 return -1;
    4396         335 :         *pos++ = '\0';
    4397             : 
    4398         335 :         if (os_strcmp(cmd, "bonjour") == 0)
    4399          60 :                 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
    4400         275 :         if (os_strcmp(cmd, "upnp") == 0)
    4401         275 :                 return p2p_ctrl_service_add_upnp(wpa_s, pos);
    4402           0 :         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
    4403           0 :         return -1;
    4404             : }
    4405             : 
    4406             : 
    4407          22 : static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
    4408             :                                         char *cmd)
    4409             : {
    4410             :         size_t len;
    4411             :         struct wpabuf *query;
    4412             :         int ret;
    4413             : 
    4414          22 :         len = os_strlen(cmd);
    4415          22 :         if (len & 1)
    4416           0 :                 return -1;
    4417          22 :         len /= 2;
    4418          22 :         query = wpabuf_alloc(len);
    4419          22 :         if (query == NULL)
    4420           0 :                 return -1;
    4421          22 :         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
    4422           0 :                 wpabuf_free(query);
    4423           0 :                 return -1;
    4424             :         }
    4425             : 
    4426          22 :         ret = wpas_p2p_service_del_bonjour(wpa_s, query);
    4427          22 :         wpabuf_free(query);
    4428          22 :         return ret;
    4429             : }
    4430             : 
    4431             : 
    4432          22 : static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
    4433             : {
    4434             :         char *pos;
    4435             :         u8 version;
    4436             : 
    4437          22 :         pos = os_strchr(cmd, ' ');
    4438          22 :         if (pos == NULL)
    4439           0 :                 return -1;
    4440          22 :         *pos++ = '\0';
    4441             : 
    4442          22 :         if (hexstr2bin(cmd, &version, 1) < 0)
    4443           0 :                 return -1;
    4444             : 
    4445          22 :         return wpas_p2p_service_del_upnp(wpa_s, version, pos);
    4446             : }
    4447             : 
    4448             : 
    4449          44 : static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
    4450             : {
    4451             :         char *pos;
    4452             : 
    4453          44 :         pos = os_strchr(cmd, ' ');
    4454          44 :         if (pos == NULL)
    4455           0 :                 return -1;
    4456          44 :         *pos++ = '\0';
    4457             : 
    4458          44 :         if (os_strcmp(cmd, "bonjour") == 0)
    4459          22 :                 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
    4460          22 :         if (os_strcmp(cmd, "upnp") == 0)
    4461          22 :                 return p2p_ctrl_service_del_upnp(wpa_s, pos);
    4462           0 :         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
    4463           0 :         return -1;
    4464             : }
    4465             : 
    4466             : 
    4467           2 : static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
    4468             : {
    4469             :         u8 addr[ETH_ALEN];
    4470             : 
    4471             :         /* <addr> */
    4472             : 
    4473           2 :         if (hwaddr_aton(cmd, addr))
    4474           0 :                 return -1;
    4475             : 
    4476           2 :         return wpas_p2p_reject(wpa_s, addr);
    4477             : }
    4478             : 
    4479             : 
    4480          19 : static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
    4481             : {
    4482             :         char *pos;
    4483             :         int id;
    4484             :         struct wpa_ssid *ssid;
    4485          19 :         u8 *_peer = NULL, peer[ETH_ALEN];
    4486          19 :         int freq = 0, pref_freq = 0;
    4487             :         int ht40, vht;
    4488             : 
    4489          19 :         id = atoi(cmd);
    4490          19 :         pos = os_strstr(cmd, " peer=");
    4491          19 :         if (pos) {
    4492          19 :                 pos += 6;
    4493          19 :                 if (hwaddr_aton(pos, peer))
    4494           0 :                         return -1;
    4495          19 :                 _peer = peer;
    4496             :         }
    4497          19 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    4498          19 :         if (ssid == NULL || ssid->disabled != 2) {
    4499           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
    4500             :                            "for persistent P2P group",
    4501             :                            id);
    4502           0 :                 return -1;
    4503             :         }
    4504             : 
    4505          19 :         pos = os_strstr(cmd, " freq=");
    4506          19 :         if (pos) {
    4507           4 :                 pos += 6;
    4508           4 :                 freq = atoi(pos);
    4509           4 :                 if (freq <= 0)
    4510           0 :                         return -1;
    4511             :         }
    4512             : 
    4513          19 :         pos = os_strstr(cmd, " pref=");
    4514          19 :         if (pos) {
    4515           1 :                 pos += 6;
    4516           1 :                 pref_freq = atoi(pos);
    4517           1 :                 if (pref_freq <= 0)
    4518           0 :                         return -1;
    4519             :         }
    4520             : 
    4521          19 :         vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
    4522          19 :         ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
    4523             :                 vht;
    4524             : 
    4525          19 :         return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, vht,
    4526             :                                pref_freq);
    4527             : }
    4528             : 
    4529             : 
    4530           4 : static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
    4531             : {
    4532             :         char *pos;
    4533           4 :         u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
    4534             : 
    4535           4 :         pos = os_strstr(cmd, " peer=");
    4536           4 :         if (!pos)
    4537           0 :                 return -1;
    4538             : 
    4539           4 :         *pos = '\0';
    4540           4 :         pos += 6;
    4541           4 :         if (hwaddr_aton(pos, peer)) {
    4542           0 :                 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
    4543           0 :                 return -1;
    4544             :         }
    4545             : 
    4546           4 :         pos = os_strstr(pos, " go_dev_addr=");
    4547           4 :         if (pos) {
    4548           0 :                 pos += 13;
    4549           0 :                 if (hwaddr_aton(pos, go_dev_addr)) {
    4550           0 :                         wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
    4551             :                                    pos);
    4552           0 :                         return -1;
    4553             :                 }
    4554           0 :                 go_dev = go_dev_addr;
    4555             :         }
    4556             : 
    4557           4 :         return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
    4558             : }
    4559             : 
    4560             : 
    4561          23 : static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
    4562             : {
    4563          23 :         if (os_strncmp(cmd, "persistent=", 11) == 0)
    4564          19 :                 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
    4565           4 :         if (os_strncmp(cmd, "group=", 6) == 0)
    4566           4 :                 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
    4567             : 
    4568           0 :         return -1;
    4569             : }
    4570             : 
    4571             : 
    4572           6 : static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
    4573             :                                          char *cmd, int freq, int ht40,
    4574             :                                          int vht)
    4575             : {
    4576             :         int id;
    4577             :         struct wpa_ssid *ssid;
    4578             : 
    4579           6 :         id = atoi(cmd);
    4580           6 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    4581           6 :         if (ssid == NULL || ssid->disabled != 2) {
    4582           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
    4583             :                            "for persistent P2P group",
    4584             :                            id);
    4585           0 :                 return -1;
    4586             :         }
    4587             : 
    4588           6 :         return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, ht40, vht,
    4589             :                                              NULL, 0);
    4590             : }
    4591             : 
    4592             : 
    4593          20 : static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
    4594             : {
    4595          20 :         int freq = 0, ht40, vht;
    4596             :         char *pos;
    4597             : 
    4598          20 :         pos = os_strstr(cmd, "freq=");
    4599          20 :         if (pos)
    4600          14 :                 freq = atoi(pos + 5);
    4601             : 
    4602          20 :         vht = (os_strstr(cmd, "vht") != NULL) || wpa_s->conf->p2p_go_vht;
    4603          20 :         ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
    4604             :                 vht;
    4605             : 
    4606          20 :         if (os_strncmp(cmd, "persistent=", 11) == 0)
    4607           6 :                 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
    4608             :                                                      ht40, vht);
    4609          27 :         if (os_strcmp(cmd, "persistent") == 0 ||
    4610          13 :             os_strncmp(cmd, "persistent ", 11) == 0)
    4611           1 :                 return wpas_p2p_group_add(wpa_s, 1, freq, ht40, vht);
    4612          13 :         if (os_strncmp(cmd, "freq=", 5) == 0)
    4613          13 :                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
    4614           0 :         if (ht40)
    4615           0 :                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
    4616             : 
    4617           0 :         wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
    4618             :                    cmd);
    4619           0 :         return -1;
    4620             : }
    4621             : 
    4622             : 
    4623         465 : static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
    4624             :                          char *buf, size_t buflen)
    4625             : {
    4626             :         u8 addr[ETH_ALEN], *addr_ptr;
    4627             :         int next, res;
    4628             :         const struct p2p_peer_info *info;
    4629             :         char *pos, *end;
    4630             :         char devtype[WPS_DEV_TYPE_BUFSIZE];
    4631             :         struct wpa_ssid *ssid;
    4632             :         size_t i;
    4633             : 
    4634         465 :         if (!wpa_s->global->p2p)
    4635           0 :                 return -1;
    4636             : 
    4637         465 :         if (os_strcmp(cmd, "FIRST") == 0) {
    4638           0 :                 addr_ptr = NULL;
    4639           0 :                 next = 0;
    4640         465 :         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
    4641           0 :                 if (hwaddr_aton(cmd + 5, addr) < 0)
    4642           0 :                         return -1;
    4643           0 :                 addr_ptr = addr;
    4644           0 :                 next = 1;
    4645             :         } else {
    4646         465 :                 if (hwaddr_aton(cmd, addr) < 0)
    4647           0 :                         return -1;
    4648         465 :                 addr_ptr = addr;
    4649         465 :                 next = 0;
    4650             :         }
    4651             : 
    4652         465 :         info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
    4653         465 :         if (info == NULL)
    4654         139 :                 return -1;
    4655             : 
    4656         326 :         pos = buf;
    4657         326 :         end = buf + buflen;
    4658             : 
    4659        3586 :         res = os_snprintf(pos, end - pos, MACSTR "\n"
    4660             :                           "pri_dev_type=%s\n"
    4661             :                           "device_name=%s\n"
    4662             :                           "manufacturer=%s\n"
    4663             :                           "model_name=%s\n"
    4664             :                           "model_number=%s\n"
    4665             :                           "serial_number=%s\n"
    4666             :                           "config_methods=0x%x\n"
    4667             :                           "dev_capab=0x%x\n"
    4668             :                           "group_capab=0x%x\n"
    4669             :                           "level=%d\n",
    4670        1956 :                           MAC2STR(info->p2p_device_addr),
    4671         326 :                           wps_dev_type_bin2str(info->pri_dev_type,
    4672             :                                                devtype, sizeof(devtype)),
    4673         326 :                           info->device_name,
    4674         326 :                           info->manufacturer,
    4675         326 :                           info->model_name,
    4676         326 :                           info->model_number,
    4677         326 :                           info->serial_number,
    4678         326 :                           info->config_methods,
    4679         326 :                           info->dev_capab,
    4680         326 :                           info->group_capab,
    4681             :                           info->level);
    4682         326 :         if (res < 0 || res >= end - pos)
    4683           0 :                 return pos - buf;
    4684         326 :         pos += res;
    4685             : 
    4686         341 :         for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
    4687             :         {
    4688             :                 const u8 *t;
    4689          15 :                 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
    4690          15 :                 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
    4691             :                                   wps_dev_type_bin2str(t, devtype,
    4692             :                                                        sizeof(devtype)));
    4693          15 :                 if (res < 0 || res >= end - pos)
    4694           0 :                         return pos - buf;
    4695          15 :                 pos += res;
    4696             :         }
    4697             : 
    4698         326 :         ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
    4699         326 :         if (ssid) {
    4700          48 :                 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
    4701          48 :                 if (res < 0 || res >= end - pos)
    4702           0 :                         return pos - buf;
    4703          48 :                 pos += res;
    4704             :         }
    4705             : 
    4706         326 :         res = p2p_get_peer_info_txt(info, pos, end - pos);
    4707         326 :         if (res < 0)
    4708           0 :                 return pos - buf;
    4709         326 :         pos += res;
    4710             : 
    4711         326 :         return pos - buf;
    4712             : }
    4713             : 
    4714             : 
    4715           8 : static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
    4716             :                                   const char *param)
    4717             : {
    4718             :         unsigned int i;
    4719             : 
    4720           8 :         if (wpa_s->global->p2p == NULL)
    4721           0 :                 return -1;
    4722             : 
    4723           8 :         if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
    4724           0 :                 return -1;
    4725             : 
    4726          16 :         for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
    4727             :                 struct wpa_freq_range *freq;
    4728           8 :                 freq = &wpa_s->global->p2p_disallow_freq.range[i];
    4729           8 :                 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
    4730             :                            freq->min, freq->max);
    4731             :         }
    4732             : 
    4733           8 :         wpas_p2p_update_channel_list(wpa_s);
    4734           8 :         return 0;
    4735             : }
    4736             : 
    4737             : 
    4738          32 : static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
    4739             : {
    4740             :         char *param;
    4741             : 
    4742          32 :         if (wpa_s->global->p2p == NULL)
    4743           0 :                 return -1;
    4744             : 
    4745          32 :         param = os_strchr(cmd, ' ');
    4746          32 :         if (param == NULL)
    4747           0 :                 return -1;
    4748          32 :         *param++ = '\0';
    4749             : 
    4750          32 :         if (os_strcmp(cmd, "discoverability") == 0) {
    4751           0 :                 p2p_set_client_discoverability(wpa_s->global->p2p,
    4752             :                                                atoi(param));
    4753           0 :                 return 0;
    4754             :         }
    4755             : 
    4756          32 :         if (os_strcmp(cmd, "managed") == 0) {
    4757           0 :                 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
    4758           0 :                 return 0;
    4759             :         }
    4760             : 
    4761          32 :         if (os_strcmp(cmd, "listen_channel") == 0) {
    4762           2 :                 return p2p_set_listen_channel(wpa_s->global->p2p, 81,
    4763           2 :                                               atoi(param));
    4764             :         }
    4765             : 
    4766          30 :         if (os_strcmp(cmd, "ssid_postfix") == 0) {
    4767           0 :                 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
    4768             :                                             os_strlen(param));
    4769             :         }
    4770             : 
    4771          30 :         if (os_strcmp(cmd, "noa") == 0) {
    4772             :                 char *pos;
    4773             :                 int count, start, duration;
    4774             :                 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
    4775           0 :                 count = atoi(param);
    4776           0 :                 pos = os_strchr(param, ',');
    4777           0 :                 if (pos == NULL)
    4778           0 :                         return -1;
    4779           0 :                 pos++;
    4780           0 :                 start = atoi(pos);
    4781           0 :                 pos = os_strchr(pos, ',');
    4782           0 :                 if (pos == NULL)
    4783           0 :                         return -1;
    4784           0 :                 pos++;
    4785           0 :                 duration = atoi(pos);
    4786           0 :                 if (count < 0 || count > 255 || start < 0 || duration < 0)
    4787           0 :                         return -1;
    4788           0 :                 if (count == 0 && duration > 0)
    4789           0 :                         return -1;
    4790           0 :                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
    4791             :                            "start=%d duration=%d", count, start, duration);
    4792           0 :                 return wpas_p2p_set_noa(wpa_s, count, start, duration);
    4793             :         }
    4794             : 
    4795          30 :         if (os_strcmp(cmd, "ps") == 0)
    4796           0 :                 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
    4797             : 
    4798          30 :         if (os_strcmp(cmd, "oppps") == 0)
    4799           0 :                 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
    4800             : 
    4801          30 :         if (os_strcmp(cmd, "ctwindow") == 0)
    4802           0 :                 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
    4803             : 
    4804          30 :         if (os_strcmp(cmd, "disabled") == 0) {
    4805           4 :                 wpa_s->global->p2p_disabled = atoi(param);
    4806           4 :                 wpa_printf(MSG_DEBUG, "P2P functionality %s",
    4807           4 :                            wpa_s->global->p2p_disabled ?
    4808             :                            "disabled" : "enabled");
    4809           4 :                 if (wpa_s->global->p2p_disabled) {
    4810           3 :                         wpas_p2p_stop_find(wpa_s);
    4811           3 :                         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
    4812           3 :                         p2p_flush(wpa_s->global->p2p);
    4813             :                 }
    4814           4 :                 return 0;
    4815             :         }
    4816             : 
    4817          26 :         if (os_strcmp(cmd, "conc_pref") == 0) {
    4818           0 :                 if (os_strcmp(param, "sta") == 0)
    4819           0 :                         wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
    4820           0 :                 else if (os_strcmp(param, "p2p") == 0)
    4821           0 :                         wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
    4822             :                 else {
    4823           0 :                         wpa_printf(MSG_INFO, "Invalid conc_pref value");
    4824           0 :                         return -1;
    4825             :                 }
    4826           0 :                 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
    4827             :                            "%s", param);
    4828           0 :                 return 0;
    4829             :         }
    4830             : 
    4831          26 :         if (os_strcmp(cmd, "force_long_sd") == 0) {
    4832           0 :                 wpa_s->force_long_sd = atoi(param);
    4833           0 :                 return 0;
    4834             :         }
    4835             : 
    4836          26 :         if (os_strcmp(cmd, "peer_filter") == 0) {
    4837             :                 u8 addr[ETH_ALEN];
    4838           0 :                 if (hwaddr_aton(param, addr))
    4839           0 :                         return -1;
    4840           0 :                 p2p_set_peer_filter(wpa_s->global->p2p, addr);
    4841           0 :                 return 0;
    4842             :         }
    4843             : 
    4844          26 :         if (os_strcmp(cmd, "cross_connect") == 0)
    4845           0 :                 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
    4846             : 
    4847          26 :         if (os_strcmp(cmd, "go_apsd") == 0) {
    4848           0 :                 if (os_strcmp(param, "disable") == 0)
    4849           0 :                         wpa_s->set_ap_uapsd = 0;
    4850             :                 else {
    4851           0 :                         wpa_s->set_ap_uapsd = 1;
    4852           0 :                         wpa_s->ap_uapsd = atoi(param);
    4853             :                 }
    4854           0 :                 return 0;
    4855             :         }
    4856             : 
    4857          26 :         if (os_strcmp(cmd, "client_apsd") == 0) {
    4858           0 :                 if (os_strcmp(param, "disable") == 0)
    4859           0 :                         wpa_s->set_sta_uapsd = 0;
    4860             :                 else {
    4861             :                         int be, bk, vi, vo;
    4862             :                         char *pos;
    4863             :                         /* format: BE,BK,VI,VO;max SP Length */
    4864           0 :                         be = atoi(param);
    4865           0 :                         pos = os_strchr(param, ',');
    4866           0 :                         if (pos == NULL)
    4867           0 :                                 return -1;
    4868           0 :                         pos++;
    4869           0 :                         bk = atoi(pos);
    4870           0 :                         pos = os_strchr(pos, ',');
    4871           0 :                         if (pos == NULL)
    4872           0 :                                 return -1;
    4873           0 :                         pos++;
    4874           0 :                         vi = atoi(pos);
    4875           0 :                         pos = os_strchr(pos, ',');
    4876           0 :                         if (pos == NULL)
    4877           0 :                                 return -1;
    4878           0 :                         pos++;
    4879           0 :                         vo = atoi(pos);
    4880             :                         /* ignore max SP Length for now */
    4881             : 
    4882           0 :                         wpa_s->set_sta_uapsd = 1;
    4883           0 :                         wpa_s->sta_uapsd = 0;
    4884           0 :                         if (be)
    4885           0 :                                 wpa_s->sta_uapsd |= BIT(0);
    4886           0 :                         if (bk)
    4887           0 :                                 wpa_s->sta_uapsd |= BIT(1);
    4888           0 :                         if (vi)
    4889           0 :                                 wpa_s->sta_uapsd |= BIT(2);
    4890           0 :                         if (vo)
    4891           0 :                                 wpa_s->sta_uapsd |= BIT(3);
    4892             :                 }
    4893           0 :                 return 0;
    4894             :         }
    4895             : 
    4896          26 :         if (os_strcmp(cmd, "disallow_freq") == 0)
    4897           8 :                 return p2p_ctrl_disallow_freq(wpa_s, param);
    4898             : 
    4899          18 :         if (os_strcmp(cmd, "disc_int") == 0) {
    4900             :                 int min_disc_int, max_disc_int, max_disc_tu;
    4901             :                 char *pos;
    4902             : 
    4903           0 :                 pos = param;
    4904             : 
    4905           0 :                 min_disc_int = atoi(pos);
    4906           0 :                 pos = os_strchr(pos, ' ');
    4907           0 :                 if (pos == NULL)
    4908           0 :                         return -1;
    4909           0 :                 *pos++ = '\0';
    4910             : 
    4911           0 :                 max_disc_int = atoi(pos);
    4912           0 :                 pos = os_strchr(pos, ' ');
    4913           0 :                 if (pos == NULL)
    4914           0 :                         return -1;
    4915           0 :                 *pos++ = '\0';
    4916             : 
    4917           0 :                 max_disc_tu = atoi(pos);
    4918             : 
    4919           0 :                 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
    4920             :                                         max_disc_int, max_disc_tu);
    4921             :         }
    4922             : 
    4923          18 :         if (os_strcmp(cmd, "per_sta_psk") == 0) {
    4924           4 :                 wpa_s->global->p2p_per_sta_psk = !!atoi(param);
    4925           4 :                 return 0;
    4926             :         }
    4927             : 
    4928             : #ifdef CONFIG_WPS_NFC
    4929          14 :         if (os_strcmp(cmd, "nfc_tag") == 0)
    4930          13 :                 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
    4931             : #endif /* CONFIG_WPS_NFC */
    4932             : 
    4933           1 :         if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
    4934           1 :                 wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
    4935           1 :                 return 0;
    4936             :         }
    4937             : 
    4938           0 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
    4939             :                    cmd);
    4940             : 
    4941           0 :         return -1;
    4942             : }
    4943             : 
    4944             : 
    4945        1920 : static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
    4946             : {
    4947        1920 :         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
    4948        1920 :         wpa_s->force_long_sd = 0;
    4949        1920 :         if (wpa_s->global->p2p)
    4950        1920 :                 p2p_flush(wpa_s->global->p2p);
    4951        1920 : }
    4952             : 
    4953             : 
    4954           1 : static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
    4955             : {
    4956             :         char *pos, *pos2;
    4957           1 :         unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
    4958             : 
    4959           1 :         if (cmd[0]) {
    4960           1 :                 pos = os_strchr(cmd, ' ');
    4961           1 :                 if (pos == NULL)
    4962           0 :                         return -1;
    4963           1 :                 *pos++ = '\0';
    4964           1 :                 dur1 = atoi(cmd);
    4965             : 
    4966           1 :                 pos2 = os_strchr(pos, ' ');
    4967           1 :                 if (pos2)
    4968           0 :                         *pos2++ = '\0';
    4969           1 :                 int1 = atoi(pos);
    4970             :         } else
    4971           0 :                 pos2 = NULL;
    4972             : 
    4973           1 :         if (pos2) {
    4974           0 :                 pos = os_strchr(pos2, ' ');
    4975           0 :                 if (pos == NULL)
    4976           0 :                         return -1;
    4977           0 :                 *pos++ = '\0';
    4978           0 :                 dur2 = atoi(pos2);
    4979           0 :                 int2 = atoi(pos);
    4980             :         }
    4981             : 
    4982           1 :         return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
    4983             : }
    4984             : 
    4985             : 
    4986           4 : static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
    4987             : {
    4988             :         char *pos;
    4989           4 :         unsigned int period = 0, interval = 0;
    4990             : 
    4991           4 :         if (cmd[0]) {
    4992           2 :                 pos = os_strchr(cmd, ' ');
    4993           2 :                 if (pos == NULL)
    4994           0 :                         return -1;
    4995           2 :                 *pos++ = '\0';
    4996           2 :                 period = atoi(cmd);
    4997           2 :                 interval = atoi(pos);
    4998             :         }
    4999             : 
    5000           4 :         return wpas_p2p_ext_listen(wpa_s, period, interval);
    5001             : }
    5002             : 
    5003             : 
    5004           4 : static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
    5005             : {
    5006             :         const char *pos;
    5007             :         u8 peer[ETH_ALEN];
    5008           4 :         int iface_addr = 0;
    5009             : 
    5010           4 :         pos = cmd;
    5011           4 :         if (os_strncmp(pos, "iface=", 6) == 0) {
    5012           0 :                 iface_addr = 1;
    5013           0 :                 pos += 6;
    5014             :         }
    5015           4 :         if (hwaddr_aton(pos, peer))
    5016           0 :                 return -1;
    5017             : 
    5018           4 :         wpas_p2p_remove_client(wpa_s, peer, iface_addr);
    5019           4 :         return 0;
    5020             : }
    5021             : 
    5022             : #endif /* CONFIG_P2P */
    5023             : 
    5024             : 
    5025         265 : static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
    5026             : {
    5027             :         struct wpa_freq_range_list ranges;
    5028         265 :         int *freqs = NULL;
    5029             :         struct hostapd_hw_modes *mode;
    5030             :         u16 i;
    5031             : 
    5032         265 :         if (wpa_s->hw.modes == NULL)
    5033           0 :                 return NULL;
    5034             : 
    5035         265 :         os_memset(&ranges, 0, sizeof(ranges));
    5036         265 :         if (freq_range_list_parse(&ranges, val) < 0)
    5037           0 :                 return NULL;
    5038             : 
    5039        1060 :         for (i = 0; i < wpa_s->hw.num_modes; i++) {
    5040             :                 int j;
    5041             : 
    5042         795 :                 mode = &wpa_s->hw.modes[i];
    5043       14575 :                 for (j = 0; j < mode->num_channels; j++) {
    5044             :                         unsigned int freq;
    5045             : 
    5046       13780 :                         if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
    5047        3975 :                                 continue;
    5048             : 
    5049        9805 :                         freq = mode->channels[j].freq;
    5050        9805 :                         if (!freq_range_list_includes(&ranges, freq))
    5051        9129 :                                 continue;
    5052             : 
    5053         676 :                         int_array_add_unique(&freqs, freq);
    5054             :                 }
    5055             :         }
    5056             : 
    5057         265 :         os_free(ranges.range);
    5058         265 :         return freqs;
    5059             : }
    5060             : 
    5061             : 
    5062             : #ifdef CONFIG_INTERWORKING
    5063             : 
    5064         116 : static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
    5065             : {
    5066         116 :         int auto_sel = 0;
    5067         116 :         int *freqs = NULL;
    5068             : 
    5069         116 :         if (param) {
    5070             :                 char *pos;
    5071             : 
    5072         115 :                 auto_sel = os_strstr(param, "auto") != NULL;
    5073             : 
    5074         115 :                 pos = os_strstr(param, "freq=");
    5075         115 :                 if (pos) {
    5076         114 :                         freqs = freq_range_to_channel_list(wpa_s, pos + 5);
    5077         114 :                         if (freqs == NULL)
    5078           0 :                                 return -1;
    5079             :                 }
    5080             : 
    5081             :         }
    5082             : 
    5083         116 :         return interworking_select(wpa_s, auto_sel, freqs);
    5084             : }
    5085             : 
    5086             : 
    5087          40 : static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
    5088             : {
    5089             :         u8 bssid[ETH_ALEN];
    5090             :         struct wpa_bss *bss;
    5091             : 
    5092          40 :         if (hwaddr_aton(dst, bssid)) {
    5093           0 :                 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
    5094           0 :                 return -1;
    5095             :         }
    5096             : 
    5097          40 :         bss = wpa_bss_get_bssid(wpa_s, bssid);
    5098          40 :         if (bss == NULL) {
    5099           0 :                 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
    5100           0 :                            MAC2STR(bssid));
    5101           0 :                 return -1;
    5102             :         }
    5103             : 
    5104          40 :         return interworking_connect(wpa_s, bss);
    5105             : }
    5106             : 
    5107             : 
    5108          19 : static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
    5109             : {
    5110             :         u8 dst_addr[ETH_ALEN];
    5111             :         int used;
    5112             :         char *pos;
    5113             : #define MAX_ANQP_INFO_ID 100
    5114             :         u16 id[MAX_ANQP_INFO_ID];
    5115          19 :         size_t num_id = 0;
    5116          19 :         u32 subtypes = 0;
    5117             : 
    5118          19 :         used = hwaddr_aton2(dst, dst_addr);
    5119          19 :         if (used < 0)
    5120           0 :                 return -1;
    5121          19 :         pos = dst + used;
    5122          41 :         while (num_id < MAX_ANQP_INFO_ID) {
    5123          22 :                 if (os_strncmp(pos, "hs20:", 5) == 0) {
    5124             : #ifdef CONFIG_HS20
    5125           2 :                         int num = atoi(pos + 5);
    5126           2 :                         if (num <= 0 || num > 31)
    5127           0 :                                 return -1;
    5128           2 :                         subtypes |= BIT(num);
    5129             : #else /* CONFIG_HS20 */
    5130             :                         return -1;
    5131             : #endif /* CONFIG_HS20 */
    5132             :                 } else {
    5133          20 :                         id[num_id] = atoi(pos);
    5134          20 :                         if (id[num_id])
    5135          20 :                                 num_id++;
    5136             :                 }
    5137          22 :                 pos = os_strchr(pos + 1, ',');
    5138          22 :                 if (pos == NULL)
    5139          19 :                         break;
    5140           3 :                 pos++;
    5141             :         }
    5142             : 
    5143          19 :         if (num_id == 0)
    5144           0 :                 return -1;
    5145             : 
    5146          19 :         return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes);
    5147             : }
    5148             : 
    5149             : 
    5150           8 : static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
    5151             : {
    5152             :         u8 dst_addr[ETH_ALEN];
    5153           8 :         struct wpabuf *advproto, *query = NULL;
    5154           8 :         int used, ret = -1;
    5155             :         char *pos, *end;
    5156             :         size_t len;
    5157             : 
    5158           8 :         used = hwaddr_aton2(cmd, dst_addr);
    5159           8 :         if (used < 0)
    5160           0 :                 return -1;
    5161             : 
    5162           8 :         pos = cmd + used;
    5163          24 :         while (*pos == ' ')
    5164           8 :                 pos++;
    5165             : 
    5166             :         /* Advertisement Protocol ID */
    5167           8 :         end = os_strchr(pos, ' ');
    5168           8 :         if (end)
    5169           8 :                 len = end - pos;
    5170             :         else
    5171           0 :                 len = os_strlen(pos);
    5172           8 :         if (len & 0x01)
    5173           0 :                 return -1;
    5174           8 :         len /= 2;
    5175           8 :         if (len == 0)
    5176           0 :                 return -1;
    5177           8 :         advproto = wpabuf_alloc(len);
    5178           8 :         if (advproto == NULL)
    5179           0 :                 return -1;
    5180           8 :         if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
    5181           0 :                 goto fail;
    5182             : 
    5183           8 :         if (end) {
    5184             :                 /* Optional Query Request */
    5185           8 :                 pos = end + 1;
    5186          16 :                 while (*pos == ' ')
    5187           0 :                         pos++;
    5188             : 
    5189           8 :                 len = os_strlen(pos);
    5190           8 :                 if (len) {
    5191           8 :                         if (len & 0x01)
    5192           0 :                                 goto fail;
    5193           8 :                         len /= 2;
    5194           8 :                         if (len == 0)
    5195           0 :                                 goto fail;
    5196           8 :                         query = wpabuf_alloc(len);
    5197           8 :                         if (query == NULL)
    5198           0 :                                 goto fail;
    5199           8 :                         if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
    5200           0 :                                 goto fail;
    5201             :                 }
    5202             :         }
    5203             : 
    5204           8 :         ret = gas_send_request(wpa_s, dst_addr, advproto, query);
    5205             : 
    5206             : fail:
    5207           8 :         wpabuf_free(advproto);
    5208           8 :         wpabuf_free(query);
    5209             : 
    5210           8 :         return ret;
    5211             : }
    5212             : 
    5213             : 
    5214           7 : static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
    5215             :                             size_t buflen)
    5216             : {
    5217             :         u8 addr[ETH_ALEN];
    5218             :         int dialog_token;
    5219             :         int used;
    5220             :         char *pos;
    5221             :         size_t resp_len, start, requested_len;
    5222             :         struct wpabuf *resp;
    5223             :         int ret;
    5224             : 
    5225           7 :         used = hwaddr_aton2(cmd, addr);
    5226           7 :         if (used < 0)
    5227           0 :                 return -1;
    5228             : 
    5229           7 :         pos = cmd + used;
    5230          21 :         while (*pos == ' ')
    5231           7 :                 pos++;
    5232           7 :         dialog_token = atoi(pos);
    5233             : 
    5234          14 :         if (wpa_s->last_gas_resp &&
    5235          14 :             os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
    5236           7 :             dialog_token == wpa_s->last_gas_dialog_token)
    5237           6 :                 resp = wpa_s->last_gas_resp;
    5238           2 :         else if (wpa_s->prev_gas_resp &&
    5239           2 :                  os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
    5240           1 :                  dialog_token == wpa_s->prev_gas_dialog_token)
    5241           1 :                 resp = wpa_s->prev_gas_resp;
    5242             :         else
    5243           0 :                 return -1;
    5244             : 
    5245           7 :         resp_len = wpabuf_len(resp);
    5246           7 :         start = 0;
    5247           7 :         requested_len = resp_len;
    5248             : 
    5249           7 :         pos = os_strchr(pos, ' ');
    5250           7 :         if (pos) {
    5251           0 :                 start = atoi(pos);
    5252           0 :                 if (start > resp_len)
    5253           0 :                         return os_snprintf(buf, buflen, "FAIL-Invalid range");
    5254           0 :                 pos = os_strchr(pos, ',');
    5255           0 :                 if (pos == NULL)
    5256           0 :                         return -1;
    5257           0 :                 pos++;
    5258           0 :                 requested_len = atoi(pos);
    5259           0 :                 if (start + requested_len > resp_len)
    5260           0 :                         return os_snprintf(buf, buflen, "FAIL-Invalid range");
    5261             :         }
    5262             : 
    5263           7 :         if (requested_len * 2 + 1 > buflen)
    5264           0 :                 return os_snprintf(buf, buflen, "FAIL-Too long response");
    5265             : 
    5266           7 :         ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
    5267             :                                requested_len);
    5268             : 
    5269           7 :         if (start + requested_len == resp_len) {
    5270             :                 /*
    5271             :                  * Free memory by dropping the response after it has been
    5272             :                  * fetched.
    5273             :                  */
    5274           7 :                 if (resp == wpa_s->prev_gas_resp) {
    5275           1 :                         wpabuf_free(wpa_s->prev_gas_resp);
    5276           1 :                         wpa_s->prev_gas_resp = NULL;
    5277             :                 } else {
    5278           6 :                         wpabuf_free(wpa_s->last_gas_resp);
    5279           6 :                         wpa_s->last_gas_resp = NULL;
    5280             :                 }
    5281             :         }
    5282             : 
    5283           7 :         return ret;
    5284             : }
    5285             : #endif /* CONFIG_INTERWORKING */
    5286             : 
    5287             : 
    5288             : #ifdef CONFIG_HS20
    5289             : 
    5290           1 : static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
    5291             : {
    5292             :         u8 dst_addr[ETH_ALEN];
    5293             :         int used;
    5294             :         char *pos;
    5295           1 :         u32 subtypes = 0;
    5296             : 
    5297           1 :         used = hwaddr_aton2(dst, dst_addr);
    5298           1 :         if (used < 0)
    5299           0 :                 return -1;
    5300           1 :         pos = dst + used;
    5301             :         for (;;) {
    5302           2 :                 int num = atoi(pos);
    5303           2 :                 if (num <= 0 || num > 31)
    5304           0 :                         return -1;
    5305           2 :                 subtypes |= BIT(num);
    5306           2 :                 pos = os_strchr(pos + 1, ',');
    5307           2 :                 if (pos == NULL)
    5308           1 :                         break;
    5309           1 :                 pos++;
    5310           1 :         }
    5311             : 
    5312           1 :         if (subtypes == 0)
    5313           0 :                 return -1;
    5314             : 
    5315           1 :         return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
    5316             : }
    5317             : 
    5318             : 
    5319           1 : static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
    5320             :                                     const u8 *addr, const char *realm)
    5321             : {
    5322             :         u8 *buf;
    5323             :         size_t rlen, len;
    5324             :         int ret;
    5325             : 
    5326           1 :         rlen = os_strlen(realm);
    5327           1 :         len = 3 + rlen;
    5328           1 :         buf = os_malloc(len);
    5329           1 :         if (buf == NULL)
    5330           0 :                 return -1;
    5331           1 :         buf[0] = 1; /* NAI Home Realm Count */
    5332           1 :         buf[1] = 0; /* Formatted in accordance with RFC 4282 */
    5333           1 :         buf[2] = rlen;
    5334           1 :         os_memcpy(buf + 3, realm, rlen);
    5335             : 
    5336           1 :         ret = hs20_anqp_send_req(wpa_s, addr,
    5337             :                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
    5338             :                                  buf, len);
    5339             : 
    5340           1 :         os_free(buf);
    5341             : 
    5342           1 :         return ret;
    5343             : }
    5344             : 
    5345             : 
    5346           1 : static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
    5347             :                                         char *dst)
    5348             : {
    5349           1 :         struct wpa_cred *cred = wpa_s->conf->cred;
    5350             :         u8 dst_addr[ETH_ALEN];
    5351             :         int used;
    5352             :         u8 *buf;
    5353             :         size_t len;
    5354             :         int ret;
    5355             : 
    5356           1 :         used = hwaddr_aton2(dst, dst_addr);
    5357           1 :         if (used < 0)
    5358           0 :                 return -1;
    5359             : 
    5360           3 :         while (dst[used] == ' ')
    5361           1 :                 used++;
    5362           1 :         if (os_strncmp(dst + used, "realm=", 6) == 0)
    5363           1 :                 return hs20_nai_home_realm_list(wpa_s, dst_addr,
    5364           1 :                                                 dst + used + 6);
    5365             : 
    5366           0 :         len = os_strlen(dst + used);
    5367             : 
    5368           0 :         if (len == 0 && cred && cred->realm)
    5369           0 :                 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
    5370             : 
    5371             :         if (len % 1)
    5372             :                 return -1;
    5373           0 :         len /= 2;
    5374           0 :         buf = os_malloc(len);
    5375           0 :         if (buf == NULL)
    5376           0 :                 return -1;
    5377           0 :         if (hexstr2bin(dst + used, buf, len) < 0) {
    5378           0 :                 os_free(buf);
    5379           0 :                 return -1;
    5380             :         }
    5381             : 
    5382           0 :         ret = hs20_anqp_send_req(wpa_s, dst_addr,
    5383             :                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
    5384             :                                  buf, len);
    5385           0 :         os_free(buf);
    5386             : 
    5387           0 :         return ret;
    5388             : }
    5389             : 
    5390             : 
    5391           1 : static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd)
    5392             : {
    5393             :         u8 dst_addr[ETH_ALEN];
    5394             :         int used;
    5395             :         char *icon;
    5396             : 
    5397           1 :         used = hwaddr_aton2(cmd, dst_addr);
    5398           1 :         if (used < 0)
    5399           0 :                 return -1;
    5400             : 
    5401           3 :         while (cmd[used] == ' ')
    5402           1 :                 used++;
    5403           1 :         icon = &cmd[used];
    5404             : 
    5405           1 :         wpa_s->fetch_osu_icon_in_progress = 0;
    5406           1 :         return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
    5407             :                                   (u8 *) icon, os_strlen(icon));
    5408             : }
    5409             : 
    5410             : #endif /* CONFIG_HS20 */
    5411             : 
    5412             : 
    5413           0 : static int wpa_supplicant_ctrl_iface_sta_autoconnect(
    5414             :         struct wpa_supplicant *wpa_s, char *cmd)
    5415             : {
    5416           0 :         wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
    5417           0 :         return 0;
    5418             : }
    5419             : 
    5420             : 
    5421             : #ifdef CONFIG_AUTOSCAN
    5422             : 
    5423           6 : static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
    5424             :                                               char *cmd)
    5425             : {
    5426           6 :         enum wpa_states state = wpa_s->wpa_state;
    5427           6 :         char *new_params = NULL;
    5428             : 
    5429           6 :         if (os_strlen(cmd) > 0) {
    5430           3 :                 new_params = os_strdup(cmd);
    5431           3 :                 if (new_params == NULL)
    5432           0 :                         return -1;
    5433             :         }
    5434             : 
    5435           6 :         os_free(wpa_s->conf->autoscan);
    5436           6 :         wpa_s->conf->autoscan = new_params;
    5437             : 
    5438           6 :         if (wpa_s->conf->autoscan == NULL)
    5439           3 :                 autoscan_deinit(wpa_s);
    5440           3 :         else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
    5441           3 :                 autoscan_init(wpa_s, 1);
    5442           0 :         else if (state == WPA_SCANNING)
    5443           0 :                 wpa_supplicant_reinit_autoscan(wpa_s);
    5444             : 
    5445           6 :         return 0;
    5446             : }
    5447             : 
    5448             : #endif /* CONFIG_AUTOSCAN */
    5449             : 
    5450             : 
    5451             : #ifdef CONFIG_WNM
    5452             : 
    5453          10 : static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
    5454             : {
    5455             :         int enter;
    5456          10 :         int intval = 0;
    5457             :         char *pos;
    5458             :         int ret;
    5459          10 :         struct wpabuf *tfs_req = NULL;
    5460             : 
    5461          10 :         if (os_strncmp(cmd, "enter", 5) == 0)
    5462           5 :                 enter = 1;
    5463           5 :         else if (os_strncmp(cmd, "exit", 4) == 0)
    5464           5 :                 enter = 0;
    5465             :         else
    5466           0 :                 return -1;
    5467             : 
    5468          10 :         pos = os_strstr(cmd, " interval=");
    5469          10 :         if (pos)
    5470           1 :                 intval = atoi(pos + 10);
    5471             : 
    5472          10 :         pos = os_strstr(cmd, " tfs_req=");
    5473          10 :         if (pos) {
    5474             :                 char *end;
    5475             :                 size_t len;
    5476           1 :                 pos += 9;
    5477           1 :                 end = os_strchr(pos, ' ');
    5478           1 :                 if (end)
    5479           0 :                         len = end - pos;
    5480             :                 else
    5481           1 :                         len = os_strlen(pos);
    5482           1 :                 if (len & 1)
    5483           0 :                         return -1;
    5484           1 :                 len /= 2;
    5485           1 :                 tfs_req = wpabuf_alloc(len);
    5486           1 :                 if (tfs_req == NULL)
    5487           0 :                         return -1;
    5488           1 :                 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
    5489           0 :                         wpabuf_free(tfs_req);
    5490           0 :                         return -1;
    5491             :                 }
    5492             :         }
    5493             : 
    5494          10 :         ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
    5495             :                                            WNM_SLEEP_MODE_EXIT, intval,
    5496             :                                            tfs_req);
    5497          10 :         wpabuf_free(tfs_req);
    5498             : 
    5499          10 :         return ret;
    5500             : }
    5501             : 
    5502             : 
    5503           1 : static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
    5504             : {
    5505             :         int query_reason;
    5506             : 
    5507           1 :         query_reason = atoi(cmd);
    5508             : 
    5509           1 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d",
    5510             :                    query_reason);
    5511             : 
    5512           1 :         return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason);
    5513             : }
    5514             : 
    5515             : #endif /* CONFIG_WNM */
    5516             : 
    5517             : 
    5518             : /* Get string representation of channel width */
    5519           1 : static const char * channel_width_name(enum chan_width width)
    5520             : {
    5521           1 :         switch (width) {
    5522             :         case CHAN_WIDTH_20_NOHT:
    5523           0 :                 return "20 MHz (no HT)";
    5524             :         case CHAN_WIDTH_20:
    5525           1 :                 return "20 MHz";
    5526             :         case CHAN_WIDTH_40:
    5527           0 :                 return "40 MHz";
    5528             :         case CHAN_WIDTH_80:
    5529           0 :                 return "80 MHz";
    5530             :         case CHAN_WIDTH_80P80:
    5531           0 :                 return "80+80 MHz";
    5532             :         case CHAN_WIDTH_160:
    5533           0 :                 return "160 MHz";
    5534             :         default:
    5535           0 :                 return "unknown";
    5536             :         }
    5537             : }
    5538             : 
    5539             : 
    5540           1 : static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
    5541             :                                       size_t buflen)
    5542             : {
    5543             :         struct wpa_signal_info si;
    5544             :         int ret;
    5545             :         char *pos, *end;
    5546             : 
    5547           1 :         ret = wpa_drv_signal_poll(wpa_s, &si);
    5548           1 :         if (ret)
    5549           0 :                 return -1;
    5550             : 
    5551           1 :         pos = buf;
    5552           1 :         end = buf + buflen;
    5553             : 
    5554           2 :         ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
    5555             :                           "NOISE=%d\nFREQUENCY=%u\n",
    5556           1 :                           si.current_signal, si.current_txrate / 1000,
    5557             :                           si.current_noise, si.frequency);
    5558           1 :         if (ret < 0 || ret > end - pos)
    5559           0 :                 return -1;
    5560           1 :         pos += ret;
    5561             : 
    5562           1 :         if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
    5563           1 :                 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
    5564             :                                   channel_width_name(si.chanwidth));
    5565           1 :                 if (ret < 0 || ret > end - pos)
    5566           0 :                         return -1;
    5567           1 :                 pos += ret;
    5568             :         }
    5569             : 
    5570           1 :         if (si.center_frq1 > 0 && si.center_frq2 > 0) {
    5571           0 :                 ret = os_snprintf(pos, end - pos,
    5572             :                                   "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
    5573             :                                   si.center_frq1, si.center_frq2);
    5574           0 :                 if (ret < 0 || ret > end - pos)
    5575           0 :                         return -1;
    5576           0 :                 pos += ret;
    5577             :         }
    5578             : 
    5579           1 :         if (si.avg_signal) {
    5580           1 :                 ret = os_snprintf(pos, end - pos,
    5581             :                                   "AVG_RSSI=%d\n", si.avg_signal);
    5582           1 :                 if (ret < 0 || ret >= end - pos)
    5583           0 :                         return -1;
    5584           1 :                 pos += ret;
    5585             :         }
    5586             : 
    5587           1 :         return pos - buf;
    5588             : }
    5589             : 
    5590             : 
    5591           1 : static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
    5592             :                                       size_t buflen)
    5593             : {
    5594             :         struct hostap_sta_driver_data sta;
    5595             :         int ret;
    5596             : 
    5597           1 :         ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
    5598           1 :         if (ret)
    5599           0 :                 return -1;
    5600             : 
    5601           1 :         ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
    5602             :                           sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
    5603           1 :         if (ret < 0 || (size_t) ret > buflen)
    5604           0 :                 return -1;
    5605           1 :         return ret;
    5606             : }
    5607             : 
    5608             : 
    5609             : #ifdef ANDROID
    5610             : static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
    5611             :                                      char *buf, size_t buflen)
    5612             : {
    5613             :         int ret;
    5614             : 
    5615             :         ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
    5616             :         if (ret == 0) {
    5617             :                 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
    5618             :                         struct p2p_data *p2p = wpa_s->global->p2p;
    5619             :                         if (p2p) {
    5620             :                                 char country[3];
    5621             :                                 country[0] = cmd[8];
    5622             :                                 country[1] = cmd[9];
    5623             :                                 country[2] = 0x04;
    5624             :                                 p2p_set_country(p2p, country);
    5625             :                         }
    5626             :                 }
    5627             :                 ret = os_snprintf(buf, buflen, "%s\n", "OK");
    5628             :         }
    5629             :         return ret;
    5630             : }
    5631             : #endif /* ANDROID */
    5632             : 
    5633             : 
    5634           1 : static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
    5635             :                                      char *buf, size_t buflen)
    5636             : {
    5637             :         int ret;
    5638             :         char *pos;
    5639           1 :         u8 *data = NULL;
    5640             :         unsigned int vendor_id, subcmd;
    5641             :         struct wpabuf *reply;
    5642           1 :         size_t data_len = 0;
    5643             : 
    5644             :         /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
    5645           1 :         vendor_id = strtoul(cmd, &pos, 16);
    5646           1 :         if (!isblank(*pos))
    5647           0 :                 return -EINVAL;
    5648             : 
    5649           1 :         subcmd = strtoul(pos, &pos, 10);
    5650             : 
    5651           1 :         if (*pos != '\0') {
    5652           1 :                 if (!isblank(*pos++))
    5653           0 :                         return -EINVAL;
    5654           1 :                 data_len = os_strlen(pos);
    5655             :         }
    5656             : 
    5657           1 :         if (data_len) {
    5658           1 :                 data_len /= 2;
    5659           1 :                 data = os_malloc(data_len);
    5660           1 :                 if (!data)
    5661           0 :                         return -1;
    5662             : 
    5663           1 :                 if (hexstr2bin(pos, data, data_len)) {
    5664           0 :                         wpa_printf(MSG_DEBUG,
    5665             :                                    "Vendor command: wrong parameter format");
    5666           0 :                         os_free(data);
    5667           0 :                         return -EINVAL;
    5668             :                 }
    5669             :         }
    5670             : 
    5671           1 :         reply = wpabuf_alloc((buflen - 1) / 2);
    5672           1 :         if (!reply) {
    5673           0 :                 os_free(data);
    5674           0 :                 return -1;
    5675             :         }
    5676             : 
    5677           1 :         ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
    5678             :                                  reply);
    5679             : 
    5680           1 :         if (ret == 0)
    5681           1 :                 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
    5682             :                                        wpabuf_len(reply));
    5683             : 
    5684           1 :         wpabuf_free(reply);
    5685           1 :         os_free(data);
    5686             : 
    5687           1 :         return ret;
    5688             : }
    5689             : 
    5690             : 
    5691        1903 : static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
    5692             : {
    5693        1903 :         wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
    5694             : 
    5695             : #ifdef CONFIG_P2P
    5696        1903 :         wpas_p2p_cancel(wpa_s);
    5697        1903 :         wpas_p2p_stop_find(wpa_s);
    5698        1903 :         p2p_ctrl_flush(wpa_s);
    5699        1903 :         wpas_p2p_group_remove(wpa_s, "*");
    5700        1903 :         wpas_p2p_service_flush(wpa_s);
    5701        1903 :         wpa_s->global->p2p_disabled = 0;
    5702        1903 :         wpa_s->global->p2p_per_sta_psk = 0;
    5703        1903 :         wpa_s->conf->num_sec_device_types = 0;
    5704        1903 :         wpa_s->p2p_disable_ip_addr_req = 0;
    5705        1903 :         os_free(wpa_s->global->p2p_go_avoid_freq.range);
    5706        1903 :         wpa_s->global->p2p_go_avoid_freq.range = NULL;
    5707             : #endif /* CONFIG_P2P */
    5708             : 
    5709             : #ifdef CONFIG_WPS_TESTING
    5710        1903 :         wps_version_number = 0x20;
    5711        1903 :         wps_testing_dummy_cred = 0;
    5712        1903 :         wps_corrupt_pkhash = 0;
    5713             : #endif /* CONFIG_WPS_TESTING */
    5714             : #ifdef CONFIG_WPS
    5715        1903 :         wpa_s->wps_fragment_size = 0;
    5716        1903 :         wpas_wps_cancel(wpa_s);
    5717             : #endif /* CONFIG_WPS */
    5718        1903 :         wpa_s->after_wps = 0;
    5719        1903 :         wpa_s->known_wps_freq = 0;
    5720             : 
    5721             : #ifdef CONFIG_TDLS
    5722             : #ifdef CONFIG_TDLS_TESTING
    5723             :         extern unsigned int tdls_testing;
    5724        1903 :         tdls_testing = 0;
    5725             : #endif /* CONFIG_TDLS_TESTING */
    5726        1903 :         wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
    5727        1903 :         wpa_tdls_enable(wpa_s->wpa, 1);
    5728             : #endif /* CONFIG_TDLS */
    5729             : 
    5730        1903 :         eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
    5731        1903 :         wpa_supplicant_stop_countermeasures(wpa_s, NULL);
    5732             : 
    5733        1903 :         wpa_s->no_keep_alive = 0;
    5734             : 
    5735        1903 :         os_free(wpa_s->disallow_aps_bssid);
    5736        1903 :         wpa_s->disallow_aps_bssid = NULL;
    5737        1903 :         wpa_s->disallow_aps_bssid_count = 0;
    5738        1903 :         os_free(wpa_s->disallow_aps_ssid);
    5739        1903 :         wpa_s->disallow_aps_ssid = NULL;
    5740        1903 :         wpa_s->disallow_aps_ssid_count = 0;
    5741             : 
    5742        1903 :         wpa_s->set_sta_uapsd = 0;
    5743        1903 :         wpa_s->sta_uapsd = 0;
    5744             : 
    5745        1903 :         wpa_drv_radio_disable(wpa_s, 0);
    5746             : 
    5747        1903 :         wpa_bss_flush(wpa_s);
    5748        1903 :         wpa_blacklist_clear(wpa_s);
    5749        1903 :         wpa_s->extra_blacklist_count = 0;
    5750        1903 :         wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
    5751        1903 :         wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
    5752        1903 :         wpa_config_flush_blobs(wpa_s->conf);
    5753        1903 :         wpa_s->conf->auto_interworking = 0;
    5754        1903 :         wpa_s->conf->okc = 0;
    5755             : 
    5756        1903 :         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
    5757        1903 :         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
    5758        1903 :         wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
    5759        1903 :         eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
    5760             : 
    5761        1903 :         radio_remove_works(wpa_s, NULL, 1);
    5762             : 
    5763        1903 :         wpa_s->next_ssid = NULL;
    5764             : 
    5765             : #ifdef CONFIG_INTERWORKING
    5766        1903 :         hs20_cancel_fetch_osu(wpa_s);
    5767             : #endif /* CONFIG_INTERWORKING */
    5768             : 
    5769        1903 :         wpa_s->ext_mgmt_frame_handling = 0;
    5770        1903 : }
    5771             : 
    5772             : 
    5773           2 : static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
    5774             :                                      char *buf, size_t buflen)
    5775             : {
    5776             :         struct wpa_radio_work *work;
    5777             :         char *pos, *end;
    5778             :         struct os_reltime now, diff;
    5779             : 
    5780           2 :         pos = buf;
    5781           2 :         end = buf + buflen;
    5782             : 
    5783           2 :         os_get_reltime(&now);
    5784             : 
    5785           5 :         dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
    5786             :         {
    5787             :                 int ret;
    5788             : 
    5789           3 :                 os_reltime_sub(&now, &work->time, &diff);
    5790           9 :                 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
    5791           3 :                                   work->type, work->wpa_s->ifname, work->freq,
    5792           3 :                                   work->started, diff.sec, diff.usec);
    5793           3 :                 if (ret < 0 || ret >= end - pos)
    5794             :                         break;
    5795           3 :                 pos += ret;
    5796             :         }
    5797             : 
    5798           2 :         return pos - buf;
    5799             : }
    5800             : 
    5801             : 
    5802           1 : static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
    5803             : {
    5804           1 :         struct wpa_radio_work *work = eloop_ctx;
    5805           1 :         struct wpa_external_work *ework = work->ctx;
    5806             : 
    5807           1 :         wpa_dbg(work->wpa_s, MSG_DEBUG,
    5808             :                 "Timing out external radio work %u (%s)",
    5809             :                 ework->id, work->type);
    5810           1 :         wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
    5811           1 :         os_free(ework);
    5812           1 :         radio_work_done(work);
    5813           1 : }
    5814             : 
    5815             : 
    5816           4 : static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
    5817             : {
    5818           4 :         struct wpa_external_work *ework = work->ctx;
    5819             : 
    5820           4 :         if (deinit) {
    5821           0 :                 if (work->started)
    5822           0 :                         eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
    5823             :                                              work, NULL);
    5824             : 
    5825           0 :                 os_free(ework);
    5826           4 :                 return;
    5827             :         }
    5828             : 
    5829           4 :         wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
    5830             :                 ework->id, ework->type);
    5831           4 :         wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
    5832           4 :         if (!ework->timeout)
    5833           3 :                 ework->timeout = 10;
    5834           4 :         eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
    5835             :                                work, NULL);
    5836             : }
    5837             : 
    5838             : 
    5839           5 : static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
    5840             :                                     char *buf, size_t buflen)
    5841             : {
    5842             :         struct wpa_external_work *ework;
    5843             :         char *pos, *pos2;
    5844             :         size_t type_len;
    5845             :         int ret;
    5846           5 :         unsigned int freq = 0;
    5847             : 
    5848             :         /* format: <name> [freq=<MHz>] [timeout=<seconds>] */
    5849             : 
    5850           5 :         ework = os_zalloc(sizeof(*ework));
    5851           5 :         if (ework == NULL)
    5852           0 :                 return -1;
    5853             : 
    5854           5 :         pos = os_strchr(cmd, ' ');
    5855           5 :         if (pos) {
    5856           2 :                 type_len = pos - cmd;
    5857           2 :                 pos++;
    5858             : 
    5859           2 :                 pos2 = os_strstr(pos, "freq=");
    5860           2 :                 if (pos2)
    5861           1 :                         freq = atoi(pos2 + 5);
    5862             : 
    5863           2 :                 pos2 = os_strstr(pos, "timeout=");
    5864           2 :                 if (pos2)
    5865           1 :                         ework->timeout = atoi(pos2 + 8);
    5866             :         } else {
    5867           3 :                 type_len = os_strlen(cmd);
    5868             :         }
    5869           5 :         if (4 + type_len >= sizeof(ework->type))
    5870           0 :                 type_len = sizeof(ework->type) - 4 - 1;
    5871           5 :         os_strlcpy(ework->type, "ext:", sizeof(ework->type));
    5872           5 :         os_memcpy(ework->type + 4, cmd, type_len);
    5873           5 :         ework->type[4 + type_len] = '\0';
    5874             : 
    5875           5 :         wpa_s->ext_work_id++;
    5876           5 :         if (wpa_s->ext_work_id == 0)
    5877           0 :                 wpa_s->ext_work_id++;
    5878           5 :         ework->id = wpa_s->ext_work_id;
    5879             : 
    5880           5 :         if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
    5881             :                            ework) < 0) {
    5882           0 :                 os_free(ework);
    5883           0 :                 return -1;
    5884             :         }
    5885             : 
    5886           5 :         ret = os_snprintf(buf, buflen, "%u", ework->id);
    5887           5 :         if (ret < 0 || (size_t) ret >= buflen)
    5888           0 :                 return -1;
    5889           5 :         return ret;
    5890             : }
    5891             : 
    5892             : 
    5893           3 : static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
    5894             : {
    5895             :         struct wpa_radio_work *work;
    5896           3 :         unsigned int id = atoi(cmd);
    5897             : 
    5898           4 :         dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
    5899             :         {
    5900             :                 struct wpa_external_work *ework;
    5901             : 
    5902           4 :                 if (os_strncmp(work->type, "ext:", 4) != 0)
    5903           0 :                         continue;
    5904           4 :                 ework = work->ctx;
    5905           4 :                 if (id && ework->id != id)
    5906           1 :                         continue;
    5907           3 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    5908             :                         "Completed external radio work %u (%s)",
    5909             :                         ework->id, ework->type);
    5910           3 :                 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
    5911           3 :                 radio_work_done(work);
    5912           3 :                 os_free(ework);
    5913           3 :                 return 3; /* "OK\n" */
    5914             :         }
    5915             : 
    5916           0 :         return -1;
    5917             : }
    5918             : 
    5919             : 
    5920          10 : static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
    5921             :                                 char *buf, size_t buflen)
    5922             : {
    5923          10 :         if (os_strcmp(cmd, "show") == 0)
    5924           2 :                 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
    5925           8 :         if (os_strncmp(cmd, "add ", 4) == 0)
    5926           5 :                 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
    5927           3 :         if (os_strncmp(cmd, "done ", 5) == 0)
    5928           3 :                 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
    5929           0 :         return -1;
    5930             : }
    5931             : 
    5932             : 
    5933          78 : void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
    5934             : {
    5935             :         struct wpa_radio_work *work, *tmp;
    5936             : 
    5937          78 :         if (!wpa_s || !wpa_s->radio)
    5938          87 :                 return;
    5939             : 
    5940          72 :         dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
    5941             :                               struct wpa_radio_work, list) {
    5942             :                 struct wpa_external_work *ework;
    5943             : 
    5944           3 :                 if (os_strncmp(work->type, "ext:", 4) != 0)
    5945           2 :                         continue;
    5946           1 :                 ework = work->ctx;
    5947           1 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    5948             :                         "Flushing%s external radio work %u (%s)",
    5949             :                         work->started ? " started" : "", ework->id,
    5950             :                         ework->type);
    5951           1 :                 if (work->started)
    5952           1 :                         eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
    5953             :                                              work, NULL);
    5954           1 :                 os_free(ework);
    5955           1 :                 radio_work_done(work);
    5956             :         }
    5957             : }
    5958             : 
    5959             : 
    5960          14 : static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
    5961             : {
    5962          14 :         struct wpa_supplicant *wpa_s = eloop_ctx;
    5963          14 :         eapol_sm_notify_ctrl_response(wpa_s->eapol);
    5964          14 : }
    5965             : 
    5966             : 
    5967         138 : static int set_scan_freqs(struct wpa_supplicant *wpa_s, char *val)
    5968             : {
    5969         138 :         int *freqs = NULL;
    5970             : 
    5971         138 :         freqs = freq_range_to_channel_list(wpa_s, val);
    5972         138 :         if (freqs == NULL)
    5973           0 :                 return -1;
    5974             : 
    5975         138 :         os_free(wpa_s->manual_scan_freqs);
    5976         138 :         wpa_s->manual_scan_freqs = freqs;
    5977             : 
    5978         138 :         return 0;
    5979             : }
    5980             : 
    5981             : 
    5982         153 : static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
    5983             :                            char *reply, int reply_size, int *reply_len)
    5984             : {
    5985             :         char *pos;
    5986             : 
    5987         153 :         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
    5988           1 :                 *reply_len = -1;
    5989           1 :                 return;
    5990             :         }
    5991             : 
    5992         152 :         wpa_s->manual_scan_passive = 0;
    5993         152 :         wpa_s->manual_scan_use_id = 0;
    5994         152 :         wpa_s->manual_scan_only_new = 0;
    5995             : 
    5996         152 :         if (params) {
    5997         144 :                 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
    5998           5 :                         wpa_s->scan_res_handler = scan_only_handler;
    5999             : 
    6000         144 :                 pos = os_strstr(params, "freq=");
    6001         144 :                 if (pos && set_scan_freqs(wpa_s, pos + 5) < 0) {
    6002           0 :                         *reply_len = -1;
    6003           0 :                         return;
    6004             :                 }
    6005             : 
    6006         144 :                 pos = os_strstr(params, "passive=");
    6007         144 :                 if (pos)
    6008           4 :                         wpa_s->manual_scan_passive = !!atoi(pos + 8);
    6009             : 
    6010         144 :                 pos = os_strstr(params, "use_id=");
    6011         144 :                 if (pos)
    6012          11 :                         wpa_s->manual_scan_use_id = atoi(pos + 7);
    6013             : 
    6014         144 :                 pos = os_strstr(params, "only_new=1");
    6015         144 :                 if (pos)
    6016          12 :                         wpa_s->manual_scan_only_new = 1;
    6017             :         } else {
    6018           8 :                 os_free(wpa_s->manual_scan_freqs);
    6019           8 :                 wpa_s->manual_scan_freqs = NULL;
    6020           8 :                 if (wpa_s->scan_res_handler == scan_only_handler)
    6021           0 :                         wpa_s->scan_res_handler = NULL;
    6022             :         }
    6023             : 
    6024         304 :         if (!wpa_s->sched_scanning && !wpa_s->scanning &&
    6025         172 :             ((wpa_s->wpa_state <= WPA_SCANNING) ||
    6026          20 :              (wpa_s->wpa_state == WPA_COMPLETED))) {
    6027         152 :                 wpa_s->normal_scans = 0;
    6028         152 :                 wpa_s->scan_req = MANUAL_SCAN_REQ;
    6029         152 :                 wpa_s->after_wps = 0;
    6030         152 :                 wpa_s->known_wps_freq = 0;
    6031         152 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
    6032         304 :                 if (wpa_s->manual_scan_use_id) {
    6033          11 :                         wpa_s->manual_scan_id++;
    6034          11 :                         wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
    6035             :                                 wpa_s->manual_scan_id);
    6036          11 :                         *reply_len = os_snprintf(reply, reply_size, "%u\n",
    6037             :                                                  wpa_s->manual_scan_id);
    6038             :                 }
    6039           0 :         } else if (wpa_s->sched_scanning) {
    6040           0 :                 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
    6041           0 :                 wpa_supplicant_cancel_sched_scan(wpa_s);
    6042           0 :                 wpa_s->scan_req = MANUAL_SCAN_REQ;
    6043           0 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
    6044           0 :                 if (wpa_s->manual_scan_use_id) {
    6045           0 :                         wpa_s->manual_scan_id++;
    6046           0 :                         *reply_len = os_snprintf(reply, reply_size, "%u\n",
    6047             :                                                  wpa_s->manual_scan_id);
    6048           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
    6049             :                                 wpa_s->manual_scan_id);
    6050             :                 }
    6051             :         } else {
    6052           0 :                 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
    6053           0 :                 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
    6054             :         }
    6055             : }
    6056             : 
    6057             : 
    6058             : #ifdef CONFIG_TESTING_OPTIONS
    6059             : 
    6060          27 : static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
    6061             :                                        unsigned int freq, const u8 *dst,
    6062             :                                        const u8 *src, const u8 *bssid,
    6063             :                                        const u8 *data, size_t data_len,
    6064             :                                        enum offchannel_send_action_result
    6065             :                                        result)
    6066             : {
    6067         515 :         wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
    6068             :                 " src=" MACSTR " bssid=" MACSTR " result=%s",
    6069         486 :                 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
    6070             :                 result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
    6071             :                 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
    6072           2 :                              "NO_ACK" : "FAILED"));
    6073          27 : }
    6074             : 
    6075             : 
    6076          27 : static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
    6077             : {
    6078             :         char *pos, *param;
    6079             :         size_t len;
    6080             :         u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
    6081             :         int res, used;
    6082          27 :         int freq = 0, no_cck = 0, wait_time = 0;
    6083             : 
    6084             :         /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
    6085             :          *    <action=Action frame payload> */
    6086             : 
    6087          27 :         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
    6088             : 
    6089          27 :         pos = cmd;
    6090          27 :         used = hwaddr_aton2(pos, da);
    6091          27 :         if (used < 0)
    6092           0 :                 return -1;
    6093          27 :         pos += used;
    6094          81 :         while (*pos == ' ')
    6095          27 :                 pos++;
    6096          27 :         used = hwaddr_aton2(pos, bssid);
    6097          27 :         if (used < 0)
    6098           0 :                 return -1;
    6099          27 :         pos += used;
    6100             : 
    6101          27 :         param = os_strstr(pos, " freq=");
    6102          27 :         if (param) {
    6103          27 :                 param += 6;
    6104          27 :                 freq = atoi(param);
    6105             :         }
    6106             : 
    6107          27 :         param = os_strstr(pos, " no_cck=");
    6108          27 :         if (param) {
    6109          16 :                 param += 8;
    6110          16 :                 no_cck = atoi(param);
    6111             :         }
    6112             : 
    6113          27 :         param = os_strstr(pos, " wait_time=");
    6114          27 :         if (param) {
    6115          26 :                 param += 11;
    6116          26 :                 wait_time = atoi(param);
    6117             :         }
    6118             : 
    6119          27 :         param = os_strstr(pos, " action=");
    6120          27 :         if (param == NULL)
    6121           0 :                 return -1;
    6122          27 :         param += 8;
    6123             : 
    6124          27 :         len = os_strlen(param);
    6125          27 :         if (len & 1)
    6126           0 :                 return -1;
    6127          27 :         len /= 2;
    6128             : 
    6129          27 :         buf = os_malloc(len);
    6130          27 :         if (buf == NULL)
    6131           0 :                 return -1;
    6132             : 
    6133          27 :         if (hexstr2bin(param, buf, len) < 0) {
    6134           0 :                 os_free(buf);
    6135           0 :                 return -1;
    6136             :         }
    6137             : 
    6138          27 :         res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
    6139             :                                      buf, len, wait_time,
    6140             :                                      wpas_ctrl_iface_mgmt_tx_cb, no_cck);
    6141          27 :         os_free(buf);
    6142          27 :         return res;
    6143             : }
    6144             : 
    6145             : 
    6146           0 : static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
    6147             : {
    6148           0 :         wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
    6149           0 :         offchannel_send_action_done(wpa_s);
    6150           0 : }
    6151             : 
    6152             : 
    6153          10 : static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
    6154             : {
    6155             :         char *pos, *param;
    6156             :         union wpa_event_data event;
    6157             :         enum wpa_event_type ev;
    6158             : 
    6159             :         /* <event name> [parameters..] */
    6160             : 
    6161          10 :         wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
    6162             : 
    6163          10 :         pos = cmd;
    6164          10 :         param = os_strchr(pos, ' ');
    6165          10 :         if (param)
    6166           2 :                 *param++ = '\0';
    6167             : 
    6168          10 :         os_memset(&event, 0, sizeof(event));
    6169             : 
    6170          10 :         if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
    6171           4 :                 ev = EVENT_INTERFACE_ENABLED;
    6172           6 :         } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
    6173           2 :                 ev = EVENT_INTERFACE_DISABLED;
    6174           4 :         } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
    6175           4 :                 ev = EVENT_AVOID_FREQUENCIES;
    6176           4 :                 if (param == NULL)
    6177           2 :                         param = "";
    6178           4 :                 if (freq_range_list_parse(&event.freq_range, param) < 0)
    6179           0 :                         return -1;
    6180           4 :                 wpa_supplicant_event(wpa_s, ev, &event);
    6181           4 :                 os_free(event.freq_range.range);
    6182           4 :                 return 0;
    6183             :         } else {
    6184           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
    6185             :                         cmd);
    6186           0 :                 return -1;
    6187             :         }
    6188             : 
    6189           6 :         wpa_supplicant_event(wpa_s, ev, &event);
    6190             : 
    6191           6 :         return 0;
    6192             : }
    6193             : 
    6194             : #endif /* CONFIG_TESTING_OPTIONS */
    6195             : 
    6196             : 
    6197       42290 : char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
    6198             :                                          char *buf, size_t *resp_len)
    6199             : {
    6200             :         char *reply;
    6201       42290 :         const int reply_size = 4096;
    6202             :         int reply_len;
    6203             : 
    6204       84566 :         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
    6205       42276 :             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
    6206        5944 :                 if (wpa_debug_show_keys)
    6207        2972 :                         wpa_dbg(wpa_s, MSG_DEBUG,
    6208             :                                 "Control interface command '%s'", buf);
    6209             :                 else
    6210           0 :                         wpa_dbg(wpa_s, MSG_DEBUG,
    6211             :                                 "Control interface command '%s [REMOVED]'",
    6212             :                                 os_strncmp(buf, WPA_CTRL_RSP,
    6213             :                                            os_strlen(WPA_CTRL_RSP)) == 0 ?
    6214             :                                 WPA_CTRL_RSP : "SET_NETWORK");
    6215       78611 :         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
    6216       39293 :                    os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
    6217          65 :                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
    6218             :                                       (const u8 *) buf, os_strlen(buf));
    6219             :         } else {
    6220       39253 :                 int level = MSG_DEBUG;
    6221       39253 :                 if (os_strcmp(buf, "PING") == 0)
    6222        3789 :                         level = MSG_EXCESSIVE;
    6223       39253 :                 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
    6224             :         }
    6225             : 
    6226       42290 :         reply = os_malloc(reply_size);
    6227       42290 :         if (reply == NULL) {
    6228           0 :                 *resp_len = 1;
    6229           0 :                 return NULL;
    6230             :         }
    6231             : 
    6232       42290 :         os_memcpy(reply, "OK\n", 3);
    6233       42290 :         reply_len = 3;
    6234             : 
    6235       42290 :         if (os_strcmp(buf, "PING") == 0) {
    6236        3789 :                 os_memcpy(reply, "PONG\n", 5);
    6237        3789 :                 reply_len = 5;
    6238       38501 :         } else if (os_strcmp(buf, "IFNAME") == 0) {
    6239           0 :                 reply_len = os_strlen(wpa_s->ifname);
    6240           0 :                 os_memcpy(reply, wpa_s->ifname, reply_len);
    6241       38501 :         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
    6242        1918 :                 if (wpa_debug_reopen_file() < 0)
    6243           0 :                         reply_len = -1;
    6244       36583 :         } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
    6245        3780 :                 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
    6246       32803 :         } else if (os_strcmp(buf, "MIB") == 0) {
    6247           8 :                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
    6248           8 :                 if (reply_len >= 0) {
    6249             :                         int res;
    6250           8 :                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
    6251           8 :                                                reply_size - reply_len);
    6252           8 :                         if (res < 0)
    6253           0 :                                 reply_len = -1;
    6254             :                         else
    6255           8 :                                 reply_len += res;
    6256             :                 }
    6257       32795 :         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
    6258        2661 :                 reply_len = wpa_supplicant_ctrl_iface_status(
    6259             :                         wpa_s, buf + 6, reply, reply_size);
    6260       30134 :         } else if (os_strcmp(buf, "PMKSA") == 0) {
    6261          30 :                 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
    6262             :                                                     reply_size);
    6263       30104 :         } else if (os_strncmp(buf, "SET ", 4) == 0) {
    6264       17573 :                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
    6265          30 :                         reply_len = -1;
    6266       12531 :         } else if (os_strncmp(buf, "GET ", 4) == 0) {
    6267           5 :                 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
    6268             :                                                           reply, reply_size);
    6269       12526 :         } else if (os_strcmp(buf, "LOGON") == 0) {
    6270           1 :                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
    6271       12525 :         } else if (os_strcmp(buf, "LOGOFF") == 0) {
    6272           1 :                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
    6273       12524 :         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
    6274           8 :                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
    6275           0 :                         reply_len = -1;
    6276             :                 else
    6277           8 :                         wpas_request_connection(wpa_s);
    6278       12516 :         } else if (os_strcmp(buf, "REATTACH") == 0) {
    6279           2 :                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
    6280           1 :                     !wpa_s->current_ssid)
    6281           0 :                         reply_len = -1;
    6282             :                 else {
    6283           1 :                         wpa_s->reattach = 1;
    6284           1 :                         wpas_request_connection(wpa_s);
    6285             :                 }
    6286       12515 :         } else if (os_strcmp(buf, "RECONNECT") == 0) {
    6287           2 :                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
    6288           0 :                         reply_len = -1;
    6289           2 :                 else if (wpa_s->disconnected)
    6290           2 :                         wpas_request_connection(wpa_s);
    6291             : #ifdef IEEE8021X_EAPOL
    6292       12513 :         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
    6293           2 :                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
    6294           1 :                         reply_len = -1;
    6295             : #endif /* IEEE8021X_EAPOL */
    6296             : #ifdef CONFIG_PEERKEY
    6297       12511 :         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
    6298           6 :                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
    6299           2 :                         reply_len = -1;
    6300             : #endif /* CONFIG_PEERKEY */
    6301             : #ifdef CONFIG_IEEE80211R
    6302       12505 :         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
    6303          14 :                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
    6304           1 :                         reply_len = -1;
    6305             : #endif /* CONFIG_IEEE80211R */
    6306             : #ifdef CONFIG_WPS
    6307       12491 :         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
    6308          26 :                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
    6309          26 :                 if (res == -2) {
    6310           0 :                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
    6311           0 :                         reply_len = 17;
    6312          26 :                 } else if (res)
    6313           0 :                         reply_len = -1;
    6314       12465 :         } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
    6315           4 :                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
    6316           4 :                 if (res == -2) {
    6317           0 :                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
    6318           0 :                         reply_len = 17;
    6319           4 :                 } else if (res)
    6320           2 :                         reply_len = -1;
    6321       12461 :         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
    6322         161 :                 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
    6323             :                                                               reply,
    6324             :                                                               reply_size);
    6325       12300 :         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
    6326          17 :                 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
    6327             :                         wpa_s, buf + 14, reply, reply_size);
    6328       12283 :         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
    6329           9 :                 if (wpas_wps_cancel(wpa_s))
    6330           1 :                         reply_len = -1;
    6331             : #ifdef CONFIG_WPS_NFC
    6332       12274 :         } else if (os_strcmp(buf, "WPS_NFC") == 0) {
    6333           3 :                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
    6334           0 :                         reply_len = -1;
    6335       12271 :         } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
    6336           1 :                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
    6337           1 :                         reply_len = -1;
    6338       12270 :         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
    6339           1 :                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
    6340             :                         wpa_s, buf + 21, reply, reply_size);
    6341       12269 :         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
    6342          11 :                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
    6343             :                         wpa_s, buf + 14, reply, reply_size);
    6344       12258 :         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
    6345          25 :                 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
    6346             :                                                                buf + 17))
    6347          11 :                         reply_len = -1;
    6348       12233 :         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
    6349          28 :                 reply_len = wpas_ctrl_nfc_get_handover_req(
    6350             :                         wpa_s, buf + 21, reply, reply_size);
    6351       12205 :         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
    6352          31 :                 reply_len = wpas_ctrl_nfc_get_handover_sel(
    6353             :                         wpa_s, buf + 21, reply, reply_size);
    6354       12174 :         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
    6355          40 :                 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
    6356           9 :                         reply_len = -1;
    6357             : #endif /* CONFIG_WPS_NFC */
    6358       12134 :         } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
    6359          43 :                 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
    6360           5 :                         reply_len = -1;
    6361             : #ifdef CONFIG_AP
    6362       12091 :         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
    6363           7 :                 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
    6364             :                         wpa_s, buf + 11, reply, reply_size);
    6365             : #endif /* CONFIG_AP */
    6366             : #ifdef CONFIG_WPS_ER
    6367       12084 :         } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
    6368           0 :                 if (wpas_wps_er_start(wpa_s, NULL))
    6369           0 :                         reply_len = -1;
    6370       12084 :         } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
    6371           9 :                 if (wpas_wps_er_start(wpa_s, buf + 13))
    6372           0 :                         reply_len = -1;
    6373       12075 :         } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
    6374        1899 :                 if (wpas_wps_er_stop(wpa_s))
    6375           0 :                         reply_len = -1;
    6376       10176 :         } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
    6377           5 :                 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
    6378           1 :                         reply_len = -1;
    6379       10171 :         } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
    6380           1 :                 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
    6381           1 :                 if (ret == -2) {
    6382           0 :                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
    6383           0 :                         reply_len = 17;
    6384           1 :                 } else if (ret == -3) {
    6385           0 :                         os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
    6386           0 :                         reply_len = 18;
    6387           1 :                 } else if (ret == -4) {
    6388           0 :                         os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
    6389           0 :                         reply_len = 20;
    6390           1 :                 } else if (ret)
    6391           0 :                         reply_len = -1;
    6392       10170 :         } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
    6393           2 :                 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
    6394           1 :                         reply_len = -1;
    6395       10168 :         } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
    6396           9 :                 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
    6397             :                                                                 buf + 18))
    6398           1 :                         reply_len = -1;
    6399       10159 :         } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
    6400           6 :                 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
    6401           5 :                         reply_len = -1;
    6402             : #ifdef CONFIG_WPS_NFC
    6403       10153 :         } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
    6404           4 :                 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
    6405             :                         wpa_s, buf + 24, reply, reply_size);
    6406             : #endif /* CONFIG_WPS_NFC */
    6407             : #endif /* CONFIG_WPS_ER */
    6408             : #endif /* CONFIG_WPS */
    6409             : #ifdef CONFIG_IBSS_RSN
    6410       10149 :         } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
    6411           1 :                 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
    6412           1 :                         reply_len = -1;
    6413             : #endif /* CONFIG_IBSS_RSN */
    6414             : #ifdef CONFIG_P2P
    6415       10148 :         } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
    6416         181 :                 if (p2p_ctrl_find(wpa_s, buf + 9))
    6417           0 :                         reply_len = -1;
    6418        9967 :         } else if (os_strcmp(buf, "P2P_FIND") == 0) {
    6419          27 :                 if (p2p_ctrl_find(wpa_s, ""))
    6420           1 :                         reply_len = -1;
    6421        9940 :         } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
    6422          65 :                 wpas_p2p_stop_find(wpa_s);
    6423        9875 :         } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
    6424         184 :                 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
    6425             :                                              reply_size);
    6426        9691 :         } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
    6427           1 :                 if (p2p_ctrl_listen(wpa_s, buf + 11))
    6428           0 :                         reply_len = -1;
    6429        9690 :         } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
    6430         204 :                 if (p2p_ctrl_listen(wpa_s, ""))
    6431           0 :                         reply_len = -1;
    6432        9486 :         } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
    6433         132 :                 if (wpas_p2p_group_remove(wpa_s, buf + 17))
    6434          14 :                         reply_len = -1;
    6435        9354 :         } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
    6436          21 :                 if (wpas_p2p_group_add(wpa_s, 0, 0, 0, 0))
    6437           0 :                         reply_len = -1;
    6438        9333 :         } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
    6439          20 :                 if (p2p_ctrl_group_add(wpa_s, buf + 14))
    6440           0 :                         reply_len = -1;
    6441        9313 :         } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
    6442           8 :                 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
    6443           2 :                         reply_len = -1;
    6444        9305 :         } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
    6445           0 :                 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
    6446        9305 :         } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
    6447          25 :                 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
    6448             :                                                    reply_size);
    6449        9280 :         } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
    6450           6 :                 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
    6451           1 :                         reply_len = -1;
    6452        9274 :         } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
    6453           0 :                 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
    6454           0 :                         reply_len = -1;
    6455        9274 :         } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
    6456           0 :                 wpas_p2p_sd_service_update(wpa_s);
    6457        9274 :         } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
    6458           0 :                 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
    6459           0 :                         reply_len = -1;
    6460        9274 :         } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
    6461           0 :                 wpas_p2p_service_flush(wpa_s);
    6462        9274 :         } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
    6463         335 :                 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
    6464           0 :                         reply_len = -1;
    6465        8939 :         } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
    6466          44 :                 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
    6467          22 :                         reply_len = -1;
    6468        8895 :         } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
    6469           2 :                 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
    6470           0 :                         reply_len = -1;
    6471        8893 :         } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
    6472          23 :                 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
    6473           0 :                         reply_len = -1;
    6474        8870 :         } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
    6475         465 :                 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
    6476             :                                               reply_size);
    6477        8405 :         } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
    6478          32 :                 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
    6479           0 :                         reply_len = -1;
    6480        8373 :         } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
    6481          17 :                 p2p_ctrl_flush(wpa_s);
    6482        8356 :         } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
    6483           0 :                 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
    6484           0 :                         reply_len = -1;
    6485        8356 :         } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
    6486           0 :                 if (wpas_p2p_cancel(wpa_s))
    6487           0 :                         reply_len = -1;
    6488        8356 :         } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
    6489           1 :                 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
    6490           0 :                         reply_len = -1;
    6491        8355 :         } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
    6492           0 :                 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
    6493           0 :                         reply_len = -1;
    6494        8355 :         } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
    6495           2 :                 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
    6496           0 :                         reply_len = -1;
    6497        8353 :         } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
    6498           2 :                 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
    6499           0 :                         reply_len = -1;
    6500        8351 :         } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
    6501           4 :                 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
    6502           0 :                         reply_len = -1;
    6503             : #endif /* CONFIG_P2P */
    6504             : #ifdef CONFIG_WIFI_DISPLAY
    6505        8347 :         } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
    6506          17 :                 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
    6507           4 :                         reply_len = -1;
    6508        8330 :         } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
    6509          10 :                 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
    6510             :                                                      reply, reply_size);
    6511             : #endif /* CONFIG_WIFI_DISPLAY */
    6512             : #ifdef CONFIG_INTERWORKING
    6513        8320 :         } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
    6514           5 :                 if (interworking_fetch_anqp(wpa_s) < 0)
    6515           0 :                         reply_len = -1;
    6516        8315 :         } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
    6517           0 :                 interworking_stop_fetch_anqp(wpa_s);
    6518        8315 :         } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
    6519           1 :                 if (ctrl_interworking_select(wpa_s, NULL) < 0)
    6520           0 :                         reply_len = -1;
    6521        8314 :         } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
    6522         115 :                 if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
    6523           0 :                         reply_len = -1;
    6524        8199 :         } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
    6525          40 :                 if (ctrl_interworking_connect(wpa_s, buf + 21) < 0)
    6526           1 :                         reply_len = -1;
    6527        8159 :         } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
    6528          19 :                 if (get_anqp(wpa_s, buf + 9) < 0)
    6529           0 :                         reply_len = -1;
    6530        8140 :         } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
    6531           8 :                 if (gas_request(wpa_s, buf + 12) < 0)
    6532           0 :                         reply_len = -1;
    6533        8132 :         } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
    6534           7 :                 reply_len = gas_response_get(wpa_s, buf + 17, reply,
    6535             :                                              reply_size);
    6536             : #endif /* CONFIG_INTERWORKING */
    6537             : #ifdef CONFIG_HS20
    6538        8125 :         } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
    6539           1 :                 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
    6540           0 :                         reply_len = -1;
    6541        8124 :         } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
    6542           1 :                 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
    6543           0 :                         reply_len = -1;
    6544        8123 :         } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
    6545           1 :                 if (hs20_icon_request(wpa_s, buf + 18) < 0)
    6546           0 :                         reply_len = -1;
    6547        8122 :         } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
    6548           1 :                 if (hs20_fetch_osu(wpa_s) < 0)
    6549           0 :                         reply_len = -1;
    6550        8121 :         } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
    6551           0 :                 hs20_cancel_fetch_osu(wpa_s);
    6552             : #endif /* CONFIG_HS20 */
    6553        8121 :         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
    6554             :         {
    6555          14 :                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
    6556             :                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
    6557           0 :                         reply_len = -1;
    6558             :                 else {
    6559             :                         /*
    6560             :                          * Notify response from timeout to allow the control
    6561             :                          * interface response to be sent first.
    6562             :                          */
    6563          14 :                         eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
    6564             :                                                wpa_s, NULL);
    6565             :                 }
    6566        8107 :         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
    6567           0 :                 if (wpa_supplicant_reload_configuration(wpa_s))
    6568           0 :                         reply_len = -1;
    6569        8107 :         } else if (os_strcmp(buf, "TERMINATE") == 0) {
    6570           0 :                 wpa_supplicant_terminate_proc(wpa_s->global);
    6571        8107 :         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
    6572           4 :                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
    6573           2 :                         reply_len = -1;
    6574        8103 :         } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
    6575          11 :                 reply_len = wpa_supplicant_ctrl_iface_blacklist(
    6576             :                         wpa_s, buf + 9, reply, reply_size);
    6577        8092 :         } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
    6578          20 :                 reply_len = wpa_supplicant_ctrl_iface_log_level(
    6579             :                         wpa_s, buf + 9, reply, reply_size);
    6580        8072 :         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
    6581          12 :                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
    6582             :                         wpa_s, reply, reply_size);
    6583        8060 :         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
    6584             : #ifdef CONFIG_SME
    6585          30 :                 wpa_s->sme.prev_bssid_set = 0;
    6586             : #endif /* CONFIG_SME */
    6587          30 :                 wpa_s->reassociate = 0;
    6588          30 :                 wpa_s->disconnected = 1;
    6589          30 :                 wpa_supplicant_cancel_sched_scan(wpa_s);
    6590          30 :                 wpa_supplicant_cancel_scan(wpa_s);
    6591          30 :                 wpa_supplicant_deauthenticate(wpa_s,
    6592             :                                               WLAN_REASON_DEAUTH_LEAVING);
    6593        8030 :         } else if (os_strcmp(buf, "SCAN") == 0) {
    6594           9 :                 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
    6595        8021 :         } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
    6596         144 :                 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
    6597        7877 :         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
    6598          16 :                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
    6599             :                         wpa_s, reply, reply_size);
    6600        7861 :         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
    6601         553 :                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
    6602           2 :                         reply_len = -1;
    6603        7308 :         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
    6604          25 :                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
    6605           2 :                         reply_len = -1;
    6606        7283 :         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
    6607           6 :                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
    6608           2 :                         reply_len = -1;
    6609        7277 :         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
    6610         563 :                 reply_len = wpa_supplicant_ctrl_iface_add_network(
    6611             :                         wpa_s, reply, reply_size);
    6612        6714 :         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
    6613         174 :                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
    6614           1 :                         reply_len = -1;
    6615        6540 :         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
    6616        2958 :                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
    6617          31 :                         reply_len = -1;
    6618        3582 :         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
    6619          40 :                 reply_len = wpa_supplicant_ctrl_iface_get_network(
    6620             :                         wpa_s, buf + 12, reply, reply_size);
    6621        3542 :         } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
    6622           3 :                 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12))
    6623           0 :                         reply_len = -1;
    6624        3539 :         } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
    6625           8 :                 reply_len = wpa_supplicant_ctrl_iface_list_creds(
    6626             :                         wpa_s, reply, reply_size);
    6627        3531 :         } else if (os_strcmp(buf, "ADD_CRED") == 0) {
    6628         209 :                 reply_len = wpa_supplicant_ctrl_iface_add_cred(
    6629             :                         wpa_s, reply, reply_size);
    6630        3322 :         } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
    6631         143 :                 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
    6632           1 :                         reply_len = -1;
    6633        3179 :         } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
    6634         601 :                 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
    6635          16 :                         reply_len = -1;
    6636        2578 :         } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
    6637          39 :                 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
    6638             :                                                                reply,
    6639             :                                                                reply_size);
    6640             : #ifndef CONFIG_NO_CONFIG_WRITE
    6641        2539 :         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
    6642           2 :                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
    6643           0 :                         reply_len = -1;
    6644             : #endif /* CONFIG_NO_CONFIG_WRITE */
    6645        2537 :         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
    6646          18 :                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
    6647             :                         wpa_s, buf + 15, reply, reply_size);
    6648        2519 :         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
    6649           8 :                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
    6650           2 :                         reply_len = -1;
    6651        2511 :         } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
    6652           3 :                 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
    6653           1 :                         reply_len = -1;
    6654        2508 :         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
    6655           0 :                 reply_len = wpa_supplicant_global_iface_list(
    6656             :                         wpa_s->global, reply, reply_size);
    6657        2508 :         } else if (os_strcmp(buf, "INTERFACES") == 0) {
    6658           1 :                 reply_len = wpa_supplicant_global_iface_interfaces(
    6659             :                         wpa_s->global, reply, reply_size);
    6660        2507 :         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
    6661         311 :                 reply_len = wpa_supplicant_ctrl_iface_bss(
    6662             :                         wpa_s, buf + 4, reply, reply_size);
    6663             : #ifdef CONFIG_AP
    6664        2196 :         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
    6665           1 :                 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
    6666        2195 :         } else if (os_strncmp(buf, "STA ", 4) == 0) {
    6667           1 :                 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
    6668             :                                               reply_size);
    6669        2194 :         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
    6670           2 :                 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
    6671             :                                                    reply_size);
    6672        2192 :         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
    6673           3 :                 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
    6674           0 :                         reply_len = -1;
    6675        2189 :         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
    6676           3 :                 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
    6677           0 :                         reply_len = -1;
    6678        2186 :         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
    6679           1 :                 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
    6680           1 :                         reply_len = -1;
    6681             : #endif /* CONFIG_AP */
    6682        2185 :         } else if (os_strcmp(buf, "SUSPEND") == 0) {
    6683           1 :                 wpas_notify_suspend(wpa_s->global);
    6684        2184 :         } else if (os_strcmp(buf, "RESUME") == 0) {
    6685           1 :                 wpas_notify_resume(wpa_s->global);
    6686             : #ifdef CONFIG_TESTING_OPTIONS
    6687        2183 :         } else if (os_strcmp(buf, "DROP_SA") == 0) {
    6688           1 :                 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
    6689             : #endif /* CONFIG_TESTING_OPTIONS */
    6690        2182 :         } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
    6691          28 :                 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
    6692           3 :                         reply_len = -1;
    6693        2154 :         } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
    6694           0 :                 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
    6695           0 :                         reply_len = -1;
    6696        2154 :         } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
    6697           3 :                 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
    6698           1 :                         reply_len = -1;
    6699        2151 :         } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
    6700           2 :                 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
    6701             :                                                                buf + 17))
    6702           1 :                         reply_len = -1;
    6703        2149 :         } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
    6704          89 :                 if (wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10))
    6705           0 :                         reply_len = -1;
    6706             : #ifdef CONFIG_TDLS
    6707        2060 :         } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
    6708           3 :                 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
    6709           2 :                         reply_len = -1;
    6710        2057 :         } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
    6711          25 :                 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
    6712           1 :                         reply_len = -1;
    6713        2032 :         } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
    6714           9 :                 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
    6715           1 :                         reply_len = -1;
    6716             : #endif /* CONFIG_TDLS */
    6717        2023 :         } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
    6718           1 :                 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
    6719             :                                                        reply_size);
    6720        2022 :         } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
    6721           1 :                 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
    6722             :                                                        reply_size);
    6723             : #ifdef CONFIG_AUTOSCAN
    6724        2021 :         } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
    6725           6 :                 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
    6726           0 :                         reply_len = -1;
    6727             : #endif /* CONFIG_AUTOSCAN */
    6728             : #ifdef ANDROID
    6729             :         } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
    6730             :                 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
    6731             :                                                       reply_size);
    6732             : #endif /* ANDROID */
    6733        2015 :         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
    6734           1 :                 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
    6735             :                                                       reply_size);
    6736        2014 :         } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
    6737          53 :                 pmksa_cache_clear_current(wpa_s->wpa);
    6738          53 :                 eapol_sm_request_reauth(wpa_s->eapol);
    6739             : #ifdef CONFIG_WNM
    6740        1961 :         } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
    6741          10 :                 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
    6742           0 :                         reply_len = -1;
    6743        1951 :         } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 10) == 0) {
    6744           1 :                 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 10))
    6745           0 :                                 reply_len = -1;
    6746             : #endif /* CONFIG_WNM */
    6747        1950 :         } else if (os_strcmp(buf, "FLUSH") == 0) {
    6748        1903 :                 wpa_supplicant_ctrl_iface_flush(wpa_s);
    6749          47 :         } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
    6750          10 :                 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
    6751             :                                                  reply_size);
    6752             : #ifdef CONFIG_TESTING_OPTIONS
    6753          37 :         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
    6754          27 :                 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
    6755           0 :                         reply_len = -1;
    6756          10 :         } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
    6757           0 :                 wpas_ctrl_iface_mgmt_tx_done(wpa_s);
    6758          10 :         } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
    6759          10 :                 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
    6760           0 :                         reply_len = -1;
    6761             : #endif /* CONFIG_TESTING_OPTIONS */
    6762             :         } else {
    6763           0 :                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
    6764           0 :                 reply_len = 16;
    6765             :         }
    6766             : 
    6767       42290 :         if (reply_len < 0) {
    6768         366 :                 os_memcpy(reply, "FAIL\n", 5);
    6769         366 :                 reply_len = 5;
    6770             :         }
    6771             : 
    6772       42290 :         *resp_len = reply_len;
    6773       42290 :         return reply;
    6774             : }
    6775             : 
    6776             : 
    6777          41 : static int wpa_supplicant_global_iface_add(struct wpa_global *global,
    6778             :                                            char *cmd)
    6779             : {
    6780             :         struct wpa_interface iface;
    6781             :         char *pos;
    6782             : 
    6783             :         /*
    6784             :          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
    6785             :          * TAB<bridge_ifname>
    6786             :          */
    6787          41 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
    6788             : 
    6789          41 :         os_memset(&iface, 0, sizeof(iface));
    6790             : 
    6791             :         do {
    6792          41 :                 iface.ifname = pos = cmd;
    6793          41 :                 pos = os_strchr(pos, '\t');
    6794          41 :                 if (pos)
    6795          39 :                         *pos++ = '\0';
    6796          41 :                 if (iface.ifname[0] == '\0')
    6797           1 :                         return -1;
    6798          40 :                 if (pos == NULL)
    6799           1 :                         break;
    6800             : 
    6801          39 :                 iface.confname = pos;
    6802          39 :                 pos = os_strchr(pos, '\t');
    6803          39 :                 if (pos)
    6804          38 :                         *pos++ = '\0';
    6805          39 :                 if (iface.confname[0] == '\0')
    6806          30 :                         iface.confname = NULL;
    6807          39 :                 if (pos == NULL)
    6808           1 :                         break;
    6809             : 
    6810          38 :                 iface.driver = pos;
    6811          38 :                 pos = os_strchr(pos, '\t');
    6812          38 :                 if (pos)
    6813          37 :                         *pos++ = '\0';
    6814          38 :                 if (iface.driver[0] == '\0')
    6815           1 :                         iface.driver = NULL;
    6816          38 :                 if (pos == NULL)
    6817           1 :                         break;
    6818             : 
    6819          37 :                 iface.ctrl_interface = pos;
    6820          37 :                 pos = os_strchr(pos, '\t');
    6821          37 :                 if (pos)
    6822          17 :                         *pos++ = '\0';
    6823          37 :                 if (iface.ctrl_interface[0] == '\0')
    6824           1 :                         iface.ctrl_interface = NULL;
    6825          37 :                 if (pos == NULL)
    6826          20 :                         break;
    6827             : 
    6828          17 :                 iface.driver_param = pos;
    6829          17 :                 pos = os_strchr(pos, '\t');
    6830          17 :                 if (pos)
    6831           3 :                         *pos++ = '\0';
    6832          17 :                 if (iface.driver_param[0] == '\0')
    6833           1 :                         iface.driver_param = NULL;
    6834          17 :                 if (pos == NULL)
    6835          14 :                         break;
    6836             : 
    6837           3 :                 iface.bridge_ifname = pos;
    6838           3 :                 pos = os_strchr(pos, '\t');
    6839           3 :                 if (pos)
    6840           1 :                         *pos++ = '\0';
    6841           3 :                 if (iface.bridge_ifname[0] == '\0')
    6842           1 :                         iface.bridge_ifname = NULL;
    6843           3 :                 if (pos == NULL)
    6844           2 :                         break;
    6845             :         } while (0);
    6846             : 
    6847          40 :         if (wpa_supplicant_get_iface(global, iface.ifname))
    6848           0 :                 return -1;
    6849             : 
    6850          40 :         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
    6851             : }
    6852             : 
    6853             : 
    6854         634 : static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
    6855             :                                               char *cmd)
    6856             : {
    6857             :         struct wpa_supplicant *wpa_s;
    6858             : 
    6859         634 :         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
    6860             : 
    6861         634 :         wpa_s = wpa_supplicant_get_iface(global, cmd);
    6862         634 :         if (wpa_s == NULL)
    6863         603 :                 return -1;
    6864          31 :         return wpa_supplicant_remove_iface(global, wpa_s, 0);
    6865             : }
    6866             : 
    6867             : 
    6868           1 : static void wpa_free_iface_info(struct wpa_interface_info *iface)
    6869             : {
    6870             :         struct wpa_interface_info *prev;
    6871             : 
    6872           2 :         while (iface) {
    6873           0 :                 prev = iface;
    6874           0 :                 iface = iface->next;
    6875             : 
    6876           0 :                 os_free(prev->ifname);
    6877           0 :                 os_free(prev->desc);
    6878           0 :                 os_free(prev);
    6879             :         }
    6880           1 : }
    6881             : 
    6882             : 
    6883           1 : static int wpa_supplicant_global_iface_list(struct wpa_global *global,
    6884             :                                             char *buf, int len)
    6885             : {
    6886             :         int i, res;
    6887           1 :         struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
    6888             :         char *pos, *end;
    6889             : 
    6890           3 :         for (i = 0; wpa_drivers[i]; i++) {
    6891           2 :                 struct wpa_driver_ops *drv = wpa_drivers[i];
    6892           2 :                 if (drv->get_interfaces == NULL)
    6893           2 :                         continue;
    6894           0 :                 tmp = drv->get_interfaces(global->drv_priv[i]);
    6895           0 :                 if (tmp == NULL)
    6896           0 :                         continue;
    6897             : 
    6898           0 :                 if (last == NULL)
    6899           0 :                         iface = last = tmp;
    6900             :                 else
    6901           0 :                         last->next = tmp;
    6902           0 :                 while (last->next)
    6903           0 :                         last = last->next;
    6904             :         }
    6905             : 
    6906           1 :         pos = buf;
    6907           1 :         end = buf + len;
    6908           1 :         for (tmp = iface; tmp; tmp = tmp->next) {
    6909           0 :                 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
    6910             :                                   tmp->drv_name, tmp->ifname,
    6911           0 :                                   tmp->desc ? tmp->desc : "");
    6912           0 :                 if (res < 0 || res >= end - pos) {
    6913           0 :                         *pos = '\0';
    6914           0 :                         break;
    6915             :                 }
    6916           0 :                 pos += res;
    6917             :         }
    6918             : 
    6919           1 :         wpa_free_iface_info(iface);
    6920             : 
    6921           1 :         return pos - buf;
    6922             : }
    6923             : 
    6924             : 
    6925           2 : static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
    6926             :                                                   char *buf, int len)
    6927             : {
    6928             :         int res;
    6929             :         char *pos, *end;
    6930             :         struct wpa_supplicant *wpa_s;
    6931             : 
    6932           2 :         wpa_s = global->ifaces;
    6933           2 :         pos = buf;
    6934           2 :         end = buf + len;
    6935             : 
    6936           7 :         while (wpa_s) {
    6937           3 :                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
    6938           3 :                 if (res < 0 || res >= end - pos) {
    6939           0 :                         *pos = '\0';
    6940           0 :                         break;
    6941             :                 }
    6942           3 :                 pos += res;
    6943           3 :                 wpa_s = wpa_s->next;
    6944             :         }
    6945           2 :         return pos - buf;
    6946             : }
    6947             : 
    6948             : 
    6949           2 : static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
    6950             :                                             const char *ifname,
    6951             :                                             char *cmd, size_t *resp_len)
    6952             : {
    6953             :         struct wpa_supplicant *wpa_s;
    6954             : 
    6955           3 :         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
    6956           2 :                 if (os_strcmp(ifname, wpa_s->ifname) == 0)
    6957           1 :                         break;
    6958             :         }
    6959             : 
    6960           2 :         if (wpa_s == NULL) {
    6961           1 :                 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
    6962           1 :                 if (resp)
    6963           1 :                         *resp_len = os_strlen(resp);
    6964             :                 else
    6965           0 :                         *resp_len = 1;
    6966           1 :                 return resp;
    6967             :         }
    6968             : 
    6969           1 :         return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
    6970             : }
    6971             : 
    6972             : 
    6973        3899 : static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
    6974             :                                                char *buf, size_t *resp_len)
    6975             : {
    6976             : #ifdef CONFIG_P2P
    6977             :         static const char * cmd[] = {
    6978             :                 "LIST_NETWORKS",
    6979             :                 "P2P_FIND",
    6980             :                 "P2P_STOP_FIND",
    6981             :                 "P2P_LISTEN",
    6982             :                 "P2P_GROUP_ADD",
    6983             :                 "P2P_GET_PASSPHRASE",
    6984             :                 "P2P_SERVICE_UPDATE",
    6985             :                 "P2P_SERVICE_FLUSH",
    6986             :                 "P2P_FLUSH",
    6987             :                 "P2P_CANCEL",
    6988             :                 "P2P_PRESENCE_REQ",
    6989             :                 "P2P_EXT_LISTEN",
    6990             :                 NULL
    6991             :         };
    6992             :         static const char * prefix[] = {
    6993             : #ifdef ANDROID
    6994             :                 "DRIVER ",
    6995             : #endif /* ANDROID */
    6996             :                 "GET_NETWORK ",
    6997             :                 "REMOVE_NETWORK ",
    6998             :                 "P2P_FIND ",
    6999             :                 "P2P_CONNECT ",
    7000             :                 "P2P_LISTEN ",
    7001             :                 "P2P_GROUP_REMOVE ",
    7002             :                 "P2P_GROUP_ADD ",
    7003             :                 "P2P_PROV_DISC ",
    7004             :                 "P2P_SERV_DISC_REQ ",
    7005             :                 "P2P_SERV_DISC_CANCEL_REQ ",
    7006             :                 "P2P_SERV_DISC_RESP ",
    7007             :                 "P2P_SERV_DISC_EXTERNAL ",
    7008             :                 "P2P_SERVICE_ADD ",
    7009             :                 "P2P_SERVICE_DEL ",
    7010             :                 "P2P_REJECT ",
    7011             :                 "P2P_INVITE ",
    7012             :                 "P2P_PEER ",
    7013             :                 "P2P_SET ",
    7014             :                 "P2P_UNAUTHORIZE ",
    7015             :                 "P2P_PRESENCE_REQ ",
    7016             :                 "P2P_EXT_LISTEN ",
    7017             :                 "P2P_REMOVE_CLIENT ",
    7018             :                 "NFC_GET_HANDOVER_SEL ",
    7019             :                 "NFC_GET_HANDOVER_REQ ",
    7020             :                 "NFC_REPORT_HANDOVER ",
    7021             :                 NULL
    7022             :         };
    7023        3899 :         int found = 0;
    7024             :         int i;
    7025             : 
    7026        3899 :         if (global->p2p_init_wpa_s == NULL)
    7027         635 :                 return NULL;
    7028             : 
    7029       39855 :         for (i = 0; !found && cmd[i]; i++) {
    7030       36591 :                 if (os_strcmp(buf, cmd[i]) == 0)
    7031         312 :                         found = 1;
    7032             :         }
    7033             : 
    7034       62716 :         for (i = 0; !found && prefix[i]; i++) {
    7035       59452 :                 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
    7036         998 :                         found = 1;
    7037             :         }
    7038             : 
    7039        3264 :         if (found)
    7040        1310 :                 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
    7041             :                                                          buf, resp_len);
    7042             : #endif /* CONFIG_P2P */
    7043        1954 :         return NULL;
    7044             : }
    7045             : 
    7046             : 
    7047        2589 : static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
    7048             :                                                char *buf, size_t *resp_len)
    7049             : {
    7050             : #ifdef CONFIG_WIFI_DISPLAY
    7051        2589 :         if (global->p2p_init_wpa_s == NULL)
    7052         635 :                 return NULL;
    7053        3907 :         if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
    7054        1953 :             os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
    7055           2 :                 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
    7056             :                                                          buf, resp_len);
    7057             : #endif /* CONFIG_WIFI_DISPLAY */
    7058        1952 :         return NULL;
    7059             : }
    7060             : 
    7061             : 
    7062        3899 : static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
    7063             :                                            char *buf, size_t *resp_len)
    7064             : {
    7065             :         char *ret;
    7066             : 
    7067        3899 :         ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
    7068        3899 :         if (ret)
    7069        1310 :                 return ret;
    7070             : 
    7071        2589 :         ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
    7072        2589 :         if (ret)
    7073           2 :                 return ret;
    7074             : 
    7075        2587 :         return NULL;
    7076             : }
    7077             : 
    7078             : 
    7079           3 : static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
    7080             : {
    7081             :         char *value;
    7082             : 
    7083           3 :         value = os_strchr(cmd, ' ');
    7084           3 :         if (value == NULL)
    7085           0 :                 return -1;
    7086           3 :         *value++ = '\0';
    7087             : 
    7088           3 :         wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
    7089             : 
    7090             : #ifdef CONFIG_WIFI_DISPLAY
    7091           3 :         if (os_strcasecmp(cmd, "wifi_display") == 0) {
    7092           2 :                 wifi_display_enable(global, !!atoi(value));
    7093           2 :                 return 0;
    7094             :         }
    7095             : #endif /* CONFIG_WIFI_DISPLAY */
    7096             : 
    7097             :         /* Restore cmd to its original value to allow redirection */
    7098           1 :         value[-1] = ' ';
    7099             : 
    7100           1 :         return -1;
    7101             : }
    7102             : 
    7103             : 
    7104             : #ifndef CONFIG_NO_CONFIG_WRITE
    7105           2 : static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
    7106             : {
    7107           2 :         int ret = 0, saved = 0;
    7108             :         struct wpa_supplicant *wpa_s;
    7109             : 
    7110           4 :         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
    7111           2 :                 if (!wpa_s->conf->update_config) {
    7112           1 :                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
    7113           1 :                         continue;
    7114             :                 }
    7115             : 
    7116           1 :                 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
    7117           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
    7118           0 :                         ret = 1;
    7119             :                 } else {
    7120           1 :                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
    7121           1 :                         saved++;
    7122             :                 }
    7123             :         }
    7124             : 
    7125           2 :         if (!saved && !ret) {
    7126           1 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    7127             :                         "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
    7128           1 :                 ret = 1;
    7129             :         }
    7130             : 
    7131           2 :         return ret;
    7132             : }
    7133             : #endif /* CONFIG_NO_CONFIG_WRITE */
    7134             : 
    7135             : 
    7136           7 : static int wpas_global_ctrl_iface_status(struct wpa_global *global,
    7137             :                                          char *buf, size_t buflen)
    7138             : {
    7139             :         char *pos, *end;
    7140             :         int ret;
    7141             :         struct wpa_supplicant *wpa_s;
    7142             : 
    7143           7 :         pos = buf;
    7144           7 :         end = buf + buflen;
    7145             : 
    7146             : #ifdef CONFIG_P2P
    7147           7 :         if (global->p2p && !global->p2p_disabled) {
    7148          42 :                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
    7149             :                                   "\n"
    7150             :                                   "p2p_state=%s\n",
    7151          36 :                                   MAC2STR(global->p2p_dev_addr),
    7152             :                                   p2p_get_state_txt(global->p2p));
    7153           6 :                 if (ret < 0 || ret >= end - pos)
    7154           0 :                         return pos - buf;
    7155           6 :                 pos += ret;
    7156           1 :         } else if (global->p2p) {
    7157           1 :                 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
    7158           1 :                 if (ret < 0 || ret >= end - pos)
    7159           0 :                         return pos - buf;
    7160           1 :                 pos += ret;
    7161             :         }
    7162             : #endif /* CONFIG_P2P */
    7163             : 
    7164             : #ifdef CONFIG_WIFI_DISPLAY
    7165           7 :         ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
    7166           7 :                           !!global->wifi_display);
    7167           7 :         if (ret < 0 || ret >= end - pos)
    7168           0 :                 return pos - buf;
    7169           7 :         pos += ret;
    7170             : #endif /* CONFIG_WIFI_DISPLAY */
    7171             : 
    7172          14 :         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
    7173          49 :                 ret = os_snprintf(pos, end - pos, "ifname=%s\n"
    7174             :                                   "address=" MACSTR "\n",
    7175          49 :                                   wpa_s->ifname, MAC2STR(wpa_s->own_addr));
    7176           7 :                 if (ret < 0 || ret >= end - pos)
    7177           0 :                         return pos - buf;
    7178           7 :                 pos += ret;
    7179             :         }
    7180             : 
    7181           7 :         return pos - buf;
    7182             : }
    7183             : 
    7184             : 
    7185        3901 : char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
    7186             :                                                 char *buf, size_t *resp_len)
    7187             : {
    7188             :         char *reply;
    7189        3901 :         const int reply_size = 2048;
    7190             :         int reply_len;
    7191        3901 :         int level = MSG_DEBUG;
    7192             : 
    7193        3901 :         if (os_strncmp(buf, "IFNAME=", 7) == 0) {
    7194           2 :                 char *pos = os_strchr(buf + 7, ' ');
    7195           2 :                 if (pos) {
    7196           2 :                         *pos++ = '\0';
    7197           2 :                         return wpas_global_ctrl_iface_ifname(global,
    7198             :                                                              buf + 7, pos,
    7199             :                                                              resp_len);
    7200             :                 }
    7201             :         }
    7202             : 
    7203        3899 :         reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
    7204        3899 :         if (reply)
    7205        1312 :                 return reply;
    7206             : 
    7207        2587 :         if (os_strcmp(buf, "PING") == 0)
    7208        1894 :                 level = MSG_EXCESSIVE;
    7209        2587 :         wpa_hexdump_ascii(level, "RX global ctrl_iface",
    7210             :                           (const u8 *) buf, os_strlen(buf));
    7211             : 
    7212        2587 :         reply = os_malloc(reply_size);
    7213        2587 :         if (reply == NULL) {
    7214           0 :                 *resp_len = 1;
    7215           0 :                 return NULL;
    7216             :         }
    7217             : 
    7218        2587 :         os_memcpy(reply, "OK\n", 3);
    7219        2587 :         reply_len = 3;
    7220             : 
    7221        2587 :         if (os_strcmp(buf, "PING") == 0) {
    7222        1894 :                 os_memcpy(reply, "PONG\n", 5);
    7223        1894 :                 reply_len = 5;
    7224         693 :         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
    7225          41 :                 if (wpa_supplicant_global_iface_add(global, buf + 14))
    7226          10 :                         reply_len = -1;
    7227         652 :         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
    7228         634 :                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
    7229         603 :                         reply_len = -1;
    7230          18 :         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
    7231           1 :                 reply_len = wpa_supplicant_global_iface_list(
    7232             :                         global, reply, reply_size);
    7233          17 :         } else if (os_strcmp(buf, "INTERFACES") == 0) {
    7234           1 :                 reply_len = wpa_supplicant_global_iface_interfaces(
    7235             :                         global, reply, reply_size);
    7236          16 :         } else if (os_strcmp(buf, "TERMINATE") == 0) {
    7237           0 :                 wpa_supplicant_terminate_proc(global);
    7238          16 :         } else if (os_strcmp(buf, "SUSPEND") == 0) {
    7239           1 :                 wpas_notify_suspend(global);
    7240          15 :         } else if (os_strcmp(buf, "RESUME") == 0) {
    7241           1 :                 wpas_notify_resume(global);
    7242          14 :         } else if (os_strncmp(buf, "SET ", 4) == 0) {
    7243           3 :                 if (wpas_global_ctrl_iface_set(global, buf + 4)) {
    7244             : #ifdef CONFIG_P2P
    7245           1 :                         if (global->p2p_init_wpa_s) {
    7246           1 :                                 os_free(reply);
    7247             :                                 /* Check if P2P redirection would work for this
    7248             :                                  * command. */
    7249           1 :                                 return wpa_supplicant_ctrl_iface_process(
    7250             :                                         global->p2p_init_wpa_s,
    7251             :                                         buf, resp_len);
    7252             :                         }
    7253             : #endif /* CONFIG_P2P */
    7254           0 :                         reply_len = -1;
    7255             :                 }
    7256             : #ifndef CONFIG_NO_CONFIG_WRITE
    7257          11 :         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
    7258           2 :                 if (wpas_global_ctrl_iface_save_config(global))
    7259           1 :                         reply_len = -1;
    7260             : #endif /* CONFIG_NO_CONFIG_WRITE */
    7261           9 :         } else if (os_strcmp(buf, "STATUS") == 0) {
    7262           7 :                 reply_len = wpas_global_ctrl_iface_status(global, reply,
    7263             :                                                           reply_size);
    7264             : #ifdef CONFIG_MODULE_TESTS
    7265           2 :         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
    7266             :                 int wpas_module_tests(void);
    7267           1 :                 if (wpas_module_tests() < 0)
    7268           0 :                         reply_len = -1;
    7269             : #endif /* CONFIG_MODULE_TESTS */
    7270             :         } else {
    7271           1 :                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
    7272           1 :                 reply_len = 16;
    7273             :         }
    7274             : 
    7275        2586 :         if (reply_len < 0) {
    7276         614 :                 os_memcpy(reply, "FAIL\n", 5);
    7277         614 :                 reply_len = 5;
    7278             :         }
    7279             : 
    7280        2586 :         *resp_len = reply_len;
    7281        2586 :         return reply;
    7282             : }

Generated by: LCOV version 1.10