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 1388338050 Lines: 1586 3619 43.8 %
Date: 2013-12-29 Functions: 73 140 52.1 %
Branches: 982 2702 36.3 %

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

Generated by: LCOV version 1.9