LCOV - code coverage report
Current view: top level - src/ap - ctrl_iface_ap.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 284 313 90.7 %
Date: 2016-10-02 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Control interface for shared AP commands
       3             :  * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "utils/includes.h"
      10             : 
      11             : #include "utils/common.h"
      12             : #include "common/ieee802_11_defs.h"
      13             : #include "common/sae.h"
      14             : #include "eapol_auth/eapol_auth_sm.h"
      15             : #include "fst/fst_ctrl_iface.h"
      16             : #include "hostapd.h"
      17             : #include "ieee802_1x.h"
      18             : #include "wpa_auth.h"
      19             : #include "ieee802_11.h"
      20             : #include "sta_info.h"
      21             : #include "wps_hostapd.h"
      22             : #include "p2p_hostapd.h"
      23             : #include "ctrl_iface_ap.h"
      24             : #include "ap_drv_ops.h"
      25             : #include "mbo_ap.h"
      26             : #include "taxonomy.h"
      27             : 
      28             : 
      29         221 : static int hostapd_get_sta_tx_rx(struct hostapd_data *hapd,
      30             :                                  struct sta_info *sta,
      31             :                                  char *buf, size_t buflen)
      32             : {
      33             :         struct hostap_sta_driver_data data;
      34             :         int ret;
      35             : 
      36         221 :         if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
      37           1 :                 return 0;
      38             : 
      39         220 :         ret = os_snprintf(buf, buflen, "rx_packets=%lu\ntx_packets=%lu\n"
      40             :                           "rx_bytes=%llu\ntx_bytes=%llu\ninactive_msec=%lu\n",
      41             :                           data.rx_packets, data.tx_packets,
      42             :                           data.rx_bytes, data.tx_bytes, data.inactive_msec);
      43         220 :         if (os_snprintf_error(buflen, ret))
      44           0 :                 return 0;
      45         220 :         return ret;
      46             : }
      47             : 
      48             : 
      49         221 : static int hostapd_get_sta_conn_time(struct sta_info *sta,
      50             :                                      char *buf, size_t buflen)
      51             : {
      52             :         struct os_reltime age;
      53             :         int ret;
      54             : 
      55         221 :         if (!sta->connected_time.sec)
      56           0 :                 return 0;
      57             : 
      58         221 :         os_reltime_age(&sta->connected_time, &age);
      59             : 
      60         221 :         ret = os_snprintf(buf, buflen, "connected_time=%u\n",
      61         221 :                           (unsigned int) age.sec);
      62         221 :         if (os_snprintf_error(buflen, ret))
      63           0 :                 return 0;
      64         221 :         return ret;
      65             : }
      66             : 
      67             : 
      68         221 : static const char * timeout_next_str(int val)
      69             : {
      70         221 :         switch (val) {
      71             :         case STA_NULLFUNC:
      72         220 :                 return "NULLFUNC POLL";
      73             :         case STA_DISASSOC:
      74           1 :                 return "DISASSOC";
      75             :         case STA_DEAUTH:
      76           0 :                 return "DEAUTH";
      77             :         case STA_REMOVE:
      78           0 :                 return "REMOVE";
      79             :         case STA_DISASSOC_FROM_CLI:
      80           0 :                 return "DISASSOC_FROM_CLI";
      81             :         }
      82             : 
      83           0 :         return "?";
      84             : }
      85             : 
      86             : 
      87         222 : static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
      88             :                                       struct sta_info *sta,
      89             :                                       char *buf, size_t buflen)
      90             : {
      91             :         int len, res, ret, i;
      92             : 
      93         222 :         if (!sta)
      94           1 :                 return 0;
      95             : 
      96         221 :         len = 0;
      97        1326 :         ret = os_snprintf(buf + len, buflen - len, MACSTR "\nflags=",
      98        1326 :                           MAC2STR(sta->addr));
      99         221 :         if (os_snprintf_error(buflen - len, ret))
     100           0 :                 return len;
     101         221 :         len += ret;
     102             : 
     103         221 :         ret = ap_sta_flags_txt(sta->flags, buf + len, buflen - len);
     104         221 :         if (ret < 0)
     105           0 :                 return len;
     106         221 :         len += ret;
     107             : 
     108         663 :         ret = os_snprintf(buf + len, buflen - len, "\naid=%d\ncapability=0x%x\n"
     109             :                           "listen_interval=%d\nsupported_rates=",
     110         663 :                           sta->aid, sta->capability, sta->listen_interval);
     111         221 :         if (os_snprintf_error(buflen - len, ret))
     112           0 :                 return len;
     113         221 :         len += ret;
     114             : 
     115        2605 :         for (i = 0; i < sta->supported_rates_len; i++) {
     116        4768 :                 ret = os_snprintf(buf + len, buflen - len, "%02x%s",
     117        2384 :                                   sta->supported_rates[i],
     118        2384 :                                   i + 1 < sta->supported_rates_len ? " " : "");
     119        2384 :                 if (os_snprintf_error(buflen - len, ret))
     120           0 :                         return len;
     121        2384 :                 len += ret;
     122             :         }
     123             : 
     124         221 :         ret = os_snprintf(buf + len, buflen - len, "\ntimeout_next=%s\n",
     125         221 :                           timeout_next_str(sta->timeout_next));
     126         221 :         if (os_snprintf_error(buflen - len, ret))
     127           0 :                 return len;
     128         221 :         len += ret;
     129             : 
     130         221 :         res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len);
     131         221 :         if (res >= 0)
     132         221 :                 len += res;
     133         221 :         res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len);
     134         221 :         if (res >= 0)
     135         221 :                 len += res;
     136         221 :         res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len);
     137         221 :         if (res >= 0)
     138         221 :                 len += res;
     139         221 :         res = hostapd_wps_get_mib_sta(hapd, sta->addr, buf + len,
     140             :                                       buflen - len);
     141         221 :         if (res >= 0)
     142         221 :                 len += res;
     143         221 :         res = hostapd_p2p_get_mib_sta(hapd, sta, buf + len, buflen - len);
     144         221 :         if (res >= 0)
     145         221 :                 len += res;
     146             : 
     147         221 :         len += hostapd_get_sta_tx_rx(hapd, sta, buf + len, buflen - len);
     148         221 :         len += hostapd_get_sta_conn_time(sta, buf + len, buflen - len);
     149             : 
     150             : #ifdef CONFIG_SAE
     151         221 :         if (sta->sae && sta->sae->state == SAE_ACCEPTED) {
     152           0 :                 res = os_snprintf(buf + len, buflen - len, "sae_group=%d\n",
     153           0 :                                   sta->sae->group);
     154           0 :                 if (!os_snprintf_error(buflen - len, res))
     155           0 :                         len += res;
     156             :         }
     157             : #endif /* CONFIG_SAE */
     158             : 
     159         221 :         if (sta->vlan_id > 0) {
     160           4 :                 res = os_snprintf(buf + len, buflen - len, "vlan_id=%d\n",
     161             :                                   sta->vlan_id);
     162           4 :                 if (!os_snprintf_error(buflen - len, res))
     163           4 :                         len += res;
     164             :         }
     165             : 
     166         221 :         res = mbo_ap_get_info(sta, buf + len, buflen - len);
     167         221 :         if (res >= 0)
     168         221 :                 len += res;
     169             : 
     170         241 :         if (sta->supp_op_classes &&
     171          20 :             buflen - len > (unsigned) (17 + 2 * sta->supp_op_classes[0])) {
     172          20 :                 len += os_snprintf(buf + len, buflen - len, "supp_op_classes=");
     173          40 :                 len += wpa_snprintf_hex(buf + len, buflen - len,
     174          20 :                                         sta->supp_op_classes + 1,
     175          20 :                                         sta->supp_op_classes[0]);
     176          20 :                 len += os_snprintf(buf + len, buflen - len, "\n");
     177             :         }
     178             : 
     179         221 :         return len;
     180             : }
     181             : 
     182             : 
     183         116 : int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
     184             :                                  char *buf, size_t buflen)
     185             : {
     186         116 :         return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen);
     187             : }
     188             : 
     189             : 
     190         128 : int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
     191             :                            char *buf, size_t buflen)
     192             : {
     193             :         u8 addr[ETH_ALEN];
     194             :         int ret;
     195             :         const char *pos;
     196             :         struct sta_info *sta;
     197             : 
     198         128 :         if (hwaddr_aton(txtaddr, addr)) {
     199           1 :                 ret = os_snprintf(buf, buflen, "FAIL\n");
     200           1 :                 if (os_snprintf_error(buflen, ret))
     201           0 :                         return 0;
     202           1 :                 return ret;
     203             :         }
     204             : 
     205         127 :         sta = ap_get_sta(hapd, addr);
     206         127 :         if (sta == NULL)
     207           5 :                 return -1;
     208             : 
     209         122 :         pos = os_strchr(txtaddr, ' ');
     210         122 :         if (pos) {
     211          18 :                 pos++;
     212             : 
     213             : #ifdef HOSTAPD_DUMP_STATE
     214          18 :                 if (os_strcmp(pos, "eapol") == 0) {
     215          18 :                         if (sta->eapol_sm == NULL)
     216           1 :                                 return -1;
     217          17 :                         return eapol_auth_dump_state(sta->eapol_sm, buf,
     218             :                                                      buflen);
     219             :                 }
     220             : #endif /* HOSTAPD_DUMP_STATE */
     221             : 
     222           0 :                 return -1;
     223             :         }
     224             : 
     225         104 :         ret = hostapd_ctrl_iface_sta_mib(hapd, sta, buf, buflen);
     226         104 :         ret += fst_ctrl_iface_mb_info(addr, buf + ret, buflen - ret);
     227             : 
     228         104 :         return ret;
     229             : }
     230             : 
     231             : 
     232           6 : int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
     233             :                                 char *buf, size_t buflen)
     234             : {
     235             :         u8 addr[ETH_ALEN];
     236             :         struct sta_info *sta;
     237             :         int ret;
     238             : 
     239           6 :         if (hwaddr_aton(txtaddr, addr) ||
     240             :             (sta = ap_get_sta(hapd, addr)) == NULL) {
     241           1 :                 ret = os_snprintf(buf, buflen, "FAIL\n");
     242           1 :                 if (os_snprintf_error(buflen, ret))
     243           0 :                         return 0;
     244           1 :                 return ret;
     245             :         }
     246             : 
     247           5 :         if (!sta->next)
     248           3 :                 return 0;
     249             : 
     250           2 :         return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
     251             : }
     252             : 
     253             : 
     254             : #ifdef CONFIG_P2P_MANAGER
     255           4 : static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
     256             :                                   u8 minor_reason_code, const u8 *addr)
     257             : {
     258             :         struct ieee80211_mgmt *mgmt;
     259             :         int ret;
     260             :         u8 *pos;
     261             : 
     262           4 :         if (!hapd->drv_priv || !hapd->driver->send_frame)
     263           2 :                 return -1;
     264             : 
     265           2 :         mgmt = os_zalloc(sizeof(*mgmt) + 100);
     266           2 :         if (mgmt == NULL)
     267           0 :                 return -1;
     268             : 
     269           2 :         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
     270           2 :         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR
     271             :                 " with minor reason code %u (stype=%u (%s))",
     272             :                 MAC2STR(addr), minor_reason_code, stype,
     273             :                 fc2str(le_to_host16(mgmt->frame_control)));
     274             : 
     275           2 :         os_memcpy(mgmt->da, addr, ETH_ALEN);
     276           2 :         os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
     277           2 :         os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
     278           2 :         if (stype == WLAN_FC_STYPE_DEAUTH) {
     279           1 :                 mgmt->u.deauth.reason_code =
     280             :                         host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
     281           1 :                 pos = (u8 *) (&mgmt->u.deauth.reason_code + 1);
     282             :         } else {
     283           1 :                 mgmt->u.disassoc.reason_code =
     284             :                         host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
     285           1 :                 pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1);
     286             :         }
     287             : 
     288           2 :         *pos++ = WLAN_EID_VENDOR_SPECIFIC;
     289           2 :         *pos++ = 4 + 3 + 1;
     290           2 :         WPA_PUT_BE32(pos, P2P_IE_VENDOR_TYPE);
     291           2 :         pos += 4;
     292             : 
     293           2 :         *pos++ = P2P_ATTR_MINOR_REASON_CODE;
     294           2 :         WPA_PUT_LE16(pos, 1);
     295           2 :         pos += 2;
     296           2 :         *pos++ = minor_reason_code;
     297             : 
     298           4 :         ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
     299           2 :                                        pos - (u8 *) mgmt, 1);
     300           2 :         os_free(mgmt);
     301             : 
     302           2 :         return ret < 0 ? -1 : 0;
     303             : }
     304             : #endif /* CONFIG_P2P_MANAGER */
     305             : 
     306             : 
     307          43 : int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
     308             :                                       const char *txtaddr)
     309             : {
     310             :         u8 addr[ETH_ALEN];
     311             :         struct sta_info *sta;
     312             :         const char *pos;
     313          43 :         u16 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
     314             : 
     315          43 :         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s",
     316             :                 txtaddr);
     317             : 
     318          43 :         if (hwaddr_aton(txtaddr, addr))
     319           2 :                 return -1;
     320             : 
     321          41 :         pos = os_strstr(txtaddr, " reason=");
     322          41 :         if (pos)
     323          22 :                 reason = atoi(pos + 8);
     324             : 
     325          41 :         pos = os_strstr(txtaddr, " test=");
     326          41 :         if (pos) {
     327             :                 struct ieee80211_mgmt mgmt;
     328             :                 int encrypt;
     329          23 :                 if (!hapd->drv_priv || !hapd->driver->send_frame)
     330           1 :                         return -1;
     331          22 :                 pos += 6;
     332          22 :                 encrypt = atoi(pos);
     333          22 :                 os_memset(&mgmt, 0, sizeof(mgmt));
     334          22 :                 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
     335             :                                                   WLAN_FC_STYPE_DEAUTH);
     336          22 :                 os_memcpy(mgmt.da, addr, ETH_ALEN);
     337          22 :                 os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
     338          22 :                 os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
     339          22 :                 mgmt.u.deauth.reason_code = host_to_le16(reason);
     340          22 :                 if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
     341             :                                              IEEE80211_HDRLEN +
     342             :                                              sizeof(mgmt.u.deauth),
     343             :                                              encrypt) < 0)
     344           0 :                         return -1;
     345          22 :                 return 0;
     346             :         }
     347             : 
     348             : #ifdef CONFIG_P2P_MANAGER
     349          17 :         pos = os_strstr(txtaddr, " p2p=");
     350          17 :         if (pos) {
     351           2 :                 return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH,
     352           2 :                                               atoi(pos + 5), addr);
     353             :         }
     354             : #endif /* CONFIG_P2P_MANAGER */
     355             : 
     356          16 :         if (os_strstr(txtaddr, " tx=0"))
     357           2 :                 hostapd_drv_sta_remove(hapd, addr);
     358             :         else
     359          14 :                 hostapd_drv_sta_deauth(hapd, addr, reason);
     360          16 :         sta = ap_get_sta(hapd, addr);
     361          16 :         if (sta)
     362          11 :                 ap_sta_deauthenticate(hapd, sta, reason);
     363           5 :         else if (addr[0] == 0xff)
     364           5 :                 hostapd_free_stas(hapd);
     365             : 
     366          16 :         return 0;
     367             : }
     368             : 
     369             : 
     370          30 : int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
     371             :                                     const char *txtaddr)
     372             : {
     373             :         u8 addr[ETH_ALEN];
     374             :         struct sta_info *sta;
     375             :         const char *pos;
     376          30 :         u16 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
     377             : 
     378          30 :         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s",
     379             :                 txtaddr);
     380             : 
     381          30 :         if (hwaddr_aton(txtaddr, addr))
     382           2 :                 return -1;
     383             : 
     384          28 :         pos = os_strstr(txtaddr, " reason=");
     385          28 :         if (pos)
     386          17 :                 reason = atoi(pos + 8);
     387             : 
     388          28 :         pos = os_strstr(txtaddr, " test=");
     389          28 :         if (pos) {
     390             :                 struct ieee80211_mgmt mgmt;
     391             :                 int encrypt;
     392          20 :                 if (!hapd->drv_priv || !hapd->driver->send_frame)
     393           1 :                         return -1;
     394          19 :                 pos += 6;
     395          19 :                 encrypt = atoi(pos);
     396          19 :                 os_memset(&mgmt, 0, sizeof(mgmt));
     397          19 :                 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
     398             :                                                   WLAN_FC_STYPE_DISASSOC);
     399          19 :                 os_memcpy(mgmt.da, addr, ETH_ALEN);
     400          19 :                 os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
     401          19 :                 os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
     402          19 :                 mgmt.u.disassoc.reason_code = host_to_le16(reason);
     403          19 :                 if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
     404             :                                              IEEE80211_HDRLEN +
     405             :                                              sizeof(mgmt.u.deauth),
     406             :                                              encrypt) < 0)
     407           0 :                         return -1;
     408          19 :                 return 0;
     409             :         }
     410             : 
     411             : #ifdef CONFIG_P2P_MANAGER
     412           6 :         pos = os_strstr(txtaddr, " p2p=");
     413           6 :         if (pos) {
     414           2 :                 return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC,
     415           2 :                                               atoi(pos + 5), addr);
     416             :         }
     417             : #endif /* CONFIG_P2P_MANAGER */
     418             : 
     419           6 :         if (os_strstr(txtaddr, " tx=0"))
     420           2 :                 hostapd_drv_sta_remove(hapd, addr);
     421             :         else
     422           4 :                 hostapd_drv_sta_disassoc(hapd, addr, reason);
     423           6 :         sta = ap_get_sta(hapd, addr);
     424           6 :         if (sta)
     425           5 :                 ap_sta_disassociate(hapd, sta, reason);
     426           1 :         else if (addr[0] == 0xff)
     427           1 :                 hostapd_free_stas(hapd);
     428             : 
     429           6 :         return 0;
     430             : }
     431             : 
     432             : 
     433             : #ifdef CONFIG_TAXONOMY
     434           9 : int hostapd_ctrl_iface_signature(struct hostapd_data *hapd,
     435             :                                  const char *txtaddr,
     436             :                                  char *buf, size_t buflen)
     437             : {
     438             :         u8 addr[ETH_ALEN];
     439             :         struct sta_info *sta;
     440             : 
     441           9 :         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE SIGNATURE %s", txtaddr);
     442             : 
     443           9 :         if (hwaddr_aton(txtaddr, addr))
     444           1 :                 return -1;
     445             : 
     446           8 :         sta = ap_get_sta(hapd, addr);
     447           8 :         if (!sta)
     448           3 :                 return -1;
     449             : 
     450           5 :         return retrieve_sta_taxonomy(hapd, sta, buf, buflen);
     451             : }
     452             : #endif /* CONFIG_TAXONOMY */
     453             : 
     454             : 
     455           1 : int hostapd_ctrl_iface_poll_sta(struct hostapd_data *hapd,
     456             :                                 const char *txtaddr)
     457             : {
     458             :         u8 addr[ETH_ALEN];
     459             :         struct sta_info *sta;
     460             : 
     461           1 :         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE POLL_STA %s", txtaddr);
     462             : 
     463           1 :         if (hwaddr_aton(txtaddr, addr))
     464           0 :                 return -1;
     465             : 
     466           1 :         sta = ap_get_sta(hapd, addr);
     467           1 :         if (!sta)
     468           0 :                 return -1;
     469             : 
     470           1 :         hostapd_drv_poll_client(hapd, hapd->own_addr, addr,
     471           1 :                                 sta->flags & WLAN_STA_WMM);
     472           1 :         return 0;
     473             : }
     474             : 
     475             : 
     476         717 : int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
     477             :                               size_t buflen)
     478             : {
     479         717 :         struct hostapd_iface *iface = hapd->iface;
     480         717 :         int len = 0, ret;
     481             :         size_t i;
     482             : 
     483        1434 :         ret = os_snprintf(buf + len, buflen - len,
     484             :                           "state=%s\n"
     485             :                           "phy=%s\n"
     486             :                           "freq=%d\n"
     487             :                           "num_sta_non_erp=%d\n"
     488             :                           "num_sta_no_short_slot_time=%d\n"
     489             :                           "num_sta_no_short_preamble=%d\n"
     490             :                           "olbc=%d\n"
     491             :                           "num_sta_ht_no_gf=%d\n"
     492             :                           "num_sta_no_ht=%d\n"
     493             :                           "num_sta_ht_20_mhz=%d\n"
     494             :                           "num_sta_ht40_intolerant=%d\n"
     495             :                           "olbc_ht=%d\n"
     496             :                           "ht_op_mode=0x%x\n",
     497             :                           hostapd_state_text(iface->state),
     498         717 :                           iface->phy,
     499             :                           iface->freq,
     500             :                           iface->num_sta_non_erp,
     501             :                           iface->num_sta_no_short_slot_time,
     502             :                           iface->num_sta_no_short_preamble,
     503             :                           iface->olbc,
     504             :                           iface->num_sta_ht_no_gf,
     505             :                           iface->num_sta_no_ht,
     506             :                           iface->num_sta_ht_20mhz,
     507             :                           iface->num_sta_ht40_intolerant,
     508             :                           iface->olbc_ht,
     509         717 :                           iface->ht_op_mode);
     510         717 :         if (os_snprintf_error(buflen - len, ret))
     511           0 :                 return len;
     512         717 :         len += ret;
     513             : 
     514         717 :         if (!iface->cac_started || !iface->dfs_cac_ms) {
     515         706 :                 ret = os_snprintf(buf + len, buflen - len,
     516             :                                   "cac_time_seconds=%d\n"
     517             :                                   "cac_time_left_seconds=N/A\n",
     518         706 :                                   iface->dfs_cac_ms / 1000);
     519             :         } else {
     520             :                 /* CAC started and CAC time set - calculate remaining time */
     521             :                 struct os_reltime now;
     522             :                 unsigned int left_time;
     523             : 
     524          11 :                 os_reltime_age(&iface->dfs_cac_start, &now);
     525          11 :                 left_time = iface->dfs_cac_ms / 1000 - now.sec;
     526          11 :                 ret = os_snprintf(buf + len, buflen - len,
     527             :                                   "cac_time_seconds=%u\n"
     528             :                                   "cac_time_left_seconds=%u\n",
     529          11 :                                   iface->dfs_cac_ms / 1000,
     530             :                                   left_time);
     531             :         }
     532         717 :         if (os_snprintf_error(buflen - len, ret))
     533           0 :                 return len;
     534         717 :         len += ret;
     535             : 
     536        4311 :         ret = os_snprintf(buf + len, buflen - len,
     537             :                           "channel=%u\n"
     538             :                           "secondary_channel=%d\n"
     539             :                           "ieee80211n=%d\n"
     540             :                           "ieee80211ac=%d\n",
     541         717 :                           iface->conf->channel,
     542        1431 :                           iface->conf->ieee80211n && !hapd->conf->disable_11n ?
     543         696 :                           iface->conf->secondary_channel : 0,
     544        1431 :                           iface->conf->ieee80211n && !hapd->conf->disable_11n,
     545         717 :                           iface->conf->ieee80211ac &&
     546          33 :                           !hapd->conf->disable_11ac);
     547         717 :         if (os_snprintf_error(buflen - len, ret))
     548           0 :                 return len;
     549         717 :         len += ret;
     550         717 :         if (iface->conf->ieee80211ac && !hapd->conf->disable_11ac) {
     551          93 :                 ret = os_snprintf(buf + len, buflen - len,
     552             :                                   "vht_oper_chwidth=%d\n"
     553             :                                   "vht_oper_centr_freq_seg0_idx=%d\n"
     554             :                                   "vht_oper_centr_freq_seg1_idx=%d\n",
     555          31 :                                   iface->conf->vht_oper_chwidth,
     556          31 :                                   iface->conf->vht_oper_centr_freq_seg0_idx,
     557          31 :                                   iface->conf->vht_oper_centr_freq_seg1_idx);
     558          31 :                 if (os_snprintf_error(buflen - len, ret))
     559           0 :                         return len;
     560          31 :                 len += ret;
     561             :         }
     562             : 
     563        1446 :         for (i = 0; i < iface->num_bss; i++) {
     564         729 :                 struct hostapd_data *bss = iface->bss[i];
     565        7290 :                 ret = os_snprintf(buf + len, buflen - len,
     566             :                                   "bss[%d]=%s\n"
     567             :                                   "bssid[%d]=" MACSTR "\n"
     568             :                                   "ssid[%d]=%s\n"
     569             :                                   "num_sta[%d]=%d\n",
     570         729 :                                   (int) i, bss->conf->iface,
     571        4374 :                                   (int) i, MAC2STR(bss->own_addr),
     572             :                                   (int) i,
     573         729 :                                   wpa_ssid_txt(bss->conf->ssid.ssid,
     574         729 :                                                bss->conf->ssid.ssid_len),
     575             :                                   (int) i, bss->num_sta);
     576         729 :                 if (os_snprintf_error(buflen - len, ret))
     577           0 :                         return len;
     578         729 :                 len += ret;
     579             :         }
     580             : 
     581         717 :         return len;
     582             : }
     583             : 
     584             : 
     585          35 : int hostapd_parse_csa_settings(const char *pos,
     586             :                                struct csa_settings *settings)
     587             : {
     588             :         char *end;
     589             : 
     590          35 :         os_memset(settings, 0, sizeof(*settings));
     591          35 :         settings->cs_count = strtol(pos, &end, 10);
     592          35 :         if (pos == end) {
     593           2 :                 wpa_printf(MSG_ERROR, "chanswitch: invalid cs_count provided");
     594           2 :                 return -1;
     595             :         }
     596             : 
     597          33 :         settings->freq_params.freq = atoi(end);
     598          33 :         if (settings->freq_params.freq == 0) {
     599           1 :                 wpa_printf(MSG_ERROR, "chanswitch: invalid freq provided");
     600           1 :                 return -1;
     601             :         }
     602             : 
     603             : #define SET_CSA_SETTING(str) \
     604             :         do { \
     605             :                 const char *pos2 = os_strstr(pos, " " #str "="); \
     606             :                 if (pos2) { \
     607             :                         pos2 += sizeof(" " #str "=") - 1; \
     608             :                         settings->freq_params.str = atoi(pos2); \
     609             :                 } \
     610             :         } while (0)
     611             : 
     612          32 :         SET_CSA_SETTING(center_freq1);
     613          32 :         SET_CSA_SETTING(center_freq2);
     614          32 :         SET_CSA_SETTING(bandwidth);
     615          32 :         SET_CSA_SETTING(sec_channel_offset);
     616          32 :         settings->freq_params.ht_enabled = !!os_strstr(pos, " ht");
     617          32 :         settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
     618          32 :         settings->block_tx = !!os_strstr(pos, " blocktx");
     619             : #undef SET_CSA_SETTING
     620             : 
     621          32 :         return 0;
     622             : }
     623             : 
     624             : 
     625           3 : int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd)
     626             : {
     627           3 :         return hostapd_drv_stop_ap(hapd);
     628             : }
     629             : 
     630             : 
     631          18 : int hostapd_ctrl_iface_pmksa_list(struct hostapd_data *hapd, char *buf,
     632             :                                   size_t len)
     633             : {
     634          18 :         return wpa_auth_pmksa_list(hapd->wpa_auth, buf, len);
     635             : }
     636             : 
     637             : 
     638           4 : void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data *hapd)
     639             : {
     640           4 :         wpa_auth_pmksa_flush(hapd->wpa_auth);
     641           4 : }

Generated by: LCOV version 1.10