2 * Control interface for shared AP commands
3 * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
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"
17 #include "ieee802_1x.h"
19 #include "ieee802_11.h"
21 #include "wps_hostapd.h"
22 #include "p2p_hostapd.h"
23 #include "ctrl_iface_ap.h"
24 #include "ap_drv_ops.h"
29 static size_t hostapd_write_ht_mcs_bitmask(char *buf
, size_t buflen
,
30 size_t curr_len
, const u8
*mcs_set
)
33 size_t len
= curr_len
;
35 ret
= os_snprintf(buf
+ len
, buflen
- len
,
37 if (os_snprintf_error(buflen
- len
, ret
))
41 /* 77 first bits (+ 3 reserved bits) */
42 len
+= wpa_snprintf_hex(buf
+ len
, buflen
- len
, mcs_set
, 10);
44 ret
= os_snprintf(buf
+ len
, buflen
- len
, "\n");
45 if (os_snprintf_error(buflen
- len
, ret
))
53 static int hostapd_get_sta_tx_rx(struct hostapd_data
*hapd
,
55 char *buf
, size_t buflen
)
57 struct hostap_sta_driver_data data
;
61 if (hostapd_drv_read_sta_data(hapd
, &data
, sta
->addr
) < 0)
64 ret
= os_snprintf(buf
, buflen
, "rx_packets=%lu\ntx_packets=%lu\n"
65 "rx_bytes=%llu\ntx_bytes=%llu\ninactive_msec=%lu\n"
67 data
.rx_packets
, data
.tx_packets
,
68 data
.rx_bytes
, data
.tx_bytes
, data
.inactive_msec
,
70 if (os_snprintf_error(buflen
, ret
))
74 ret
= os_snprintf(buf
+ len
, buflen
- len
, "rx_rate_info=%lu",
75 data
.current_rx_rate
);
76 if (os_snprintf_error(buflen
- len
, ret
))
79 if (data
.flags
& STA_DRV_DATA_RX_MCS
) {
80 ret
= os_snprintf(buf
+ len
, buflen
- len
, " mcs %u",
82 if (!os_snprintf_error(buflen
- len
, ret
))
85 if (data
.flags
& STA_DRV_DATA_RX_VHT_MCS
) {
86 ret
= os_snprintf(buf
+ len
, buflen
- len
, " vhtmcs %u",
88 if (!os_snprintf_error(buflen
- len
, ret
))
91 if (data
.flags
& STA_DRV_DATA_RX_VHT_NSS
) {
92 ret
= os_snprintf(buf
+ len
, buflen
- len
, " vhtnss %u",
94 if (!os_snprintf_error(buflen
- len
, ret
))
97 if (data
.flags
& STA_DRV_DATA_RX_SHORT_GI
) {
98 ret
= os_snprintf(buf
+ len
, buflen
- len
, " shortGI");
99 if (!os_snprintf_error(buflen
- len
, ret
))
102 ret
= os_snprintf(buf
+ len
, buflen
- len
, "\n");
103 if (!os_snprintf_error(buflen
- len
, ret
))
106 ret
= os_snprintf(buf
+ len
, buflen
- len
, "tx_rate_info=%lu",
107 data
.current_tx_rate
);
108 if (os_snprintf_error(buflen
- len
, ret
))
111 if (data
.flags
& STA_DRV_DATA_TX_MCS
) {
112 ret
= os_snprintf(buf
+ len
, buflen
- len
, " mcs %u",
114 if (!os_snprintf_error(buflen
- len
, ret
))
117 if (data
.flags
& STA_DRV_DATA_TX_VHT_MCS
) {
118 ret
= os_snprintf(buf
+ len
, buflen
- len
, " vhtmcs %u",
120 if (!os_snprintf_error(buflen
- len
, ret
))
123 if (data
.flags
& STA_DRV_DATA_TX_VHT_NSS
) {
124 ret
= os_snprintf(buf
+ len
, buflen
- len
, " vhtnss %u",
126 if (!os_snprintf_error(buflen
- len
, ret
))
129 if (data
.flags
& STA_DRV_DATA_TX_SHORT_GI
) {
130 ret
= os_snprintf(buf
+ len
, buflen
- len
, " shortGI");
131 if (!os_snprintf_error(buflen
- len
, ret
))
134 ret
= os_snprintf(buf
+ len
, buflen
- len
, "\n");
135 if (!os_snprintf_error(buflen
- len
, ret
))
138 if ((sta
->flags
& WLAN_STA_VHT
) && sta
->vht_capabilities
) {
139 ret
= os_snprintf(buf
+ len
, buflen
- len
,
140 "rx_vht_mcs_map=%04x\n"
141 "tx_vht_mcs_map=%04x\n",
142 le_to_host16(sta
->vht_capabilities
->
143 vht_supported_mcs_set
.rx_map
),
144 le_to_host16(sta
->vht_capabilities
->
145 vht_supported_mcs_set
.tx_map
));
146 if (!os_snprintf_error(buflen
- len
, ret
))
150 if ((sta
->flags
& WLAN_STA_HT
) && sta
->ht_capabilities
) {
151 len
= hostapd_write_ht_mcs_bitmask(buf
, buflen
, len
,
152 sta
->ht_capabilities
->
156 if (data
.flags
& STA_DRV_DATA_LAST_ACK_RSSI
) {
157 ret
= os_snprintf(buf
+ len
, buflen
- len
,
158 "last_ack_signal=%d\n", data
.last_ack_rssi
);
159 if (!os_snprintf_error(buflen
- len
, ret
))
167 static int hostapd_get_sta_conn_time(struct sta_info
*sta
,
168 char *buf
, size_t buflen
)
170 struct os_reltime age
;
173 if (!sta
->connected_time
.sec
)
176 os_reltime_age(&sta
->connected_time
, &age
);
178 ret
= os_snprintf(buf
, buflen
, "connected_time=%u\n",
179 (unsigned int) age
.sec
);
180 if (os_snprintf_error(buflen
, ret
))
186 static const char * timeout_next_str(int val
)
190 return "NULLFUNC POLL";
197 case STA_DISASSOC_FROM_CLI
:
198 return "DISASSOC_FROM_CLI";
205 static int hostapd_ctrl_iface_sta_mib(struct hostapd_data
*hapd
,
206 struct sta_info
*sta
,
207 char *buf
, size_t buflen
)
209 int len
, res
, ret
, i
;
215 ret
= os_snprintf(buf
+ len
, buflen
- len
, MACSTR
"\nflags=",
217 if (os_snprintf_error(buflen
- len
, ret
))
221 ret
= ap_sta_flags_txt(sta
->flags
, buf
+ len
, buflen
- len
);
226 ret
= os_snprintf(buf
+ len
, buflen
- len
, "\naid=%d\ncapability=0x%x\n"
227 "listen_interval=%d\nsupported_rates=",
228 sta
->aid
, sta
->capability
, sta
->listen_interval
);
229 if (os_snprintf_error(buflen
- len
, ret
))
233 for (i
= 0; i
< sta
->supported_rates_len
; i
++) {
234 ret
= os_snprintf(buf
+ len
, buflen
- len
, "%02x%s",
235 sta
->supported_rates
[i
],
236 i
+ 1 < sta
->supported_rates_len
? " " : "");
237 if (os_snprintf_error(buflen
- len
, ret
))
242 ret
= os_snprintf(buf
+ len
, buflen
- len
, "\ntimeout_next=%s\n",
243 timeout_next_str(sta
->timeout_next
));
244 if (os_snprintf_error(buflen
- len
, ret
))
248 res
= ieee802_11_get_mib_sta(hapd
, sta
, buf
+ len
, buflen
- len
);
251 res
= wpa_get_mib_sta(sta
->wpa_sm
, buf
+ len
, buflen
- len
);
254 res
= ieee802_1x_get_mib_sta(hapd
, sta
, buf
+ len
, buflen
- len
);
257 res
= hostapd_wps_get_mib_sta(hapd
, sta
->addr
, buf
+ len
,
261 res
= hostapd_p2p_get_mib_sta(hapd
, sta
, buf
+ len
, buflen
- len
);
265 len
+= hostapd_get_sta_tx_rx(hapd
, sta
, buf
+ len
, buflen
- len
);
266 len
+= hostapd_get_sta_conn_time(sta
, buf
+ len
, buflen
- len
);
269 if (sta
->sae
&& sta
->sae
->state
== SAE_ACCEPTED
) {
270 res
= os_snprintf(buf
+ len
, buflen
- len
, "sae_group=%d\n",
272 if (!os_snprintf_error(buflen
- len
, res
))
275 #endif /* CONFIG_SAE */
277 if (sta
->vlan_id
> 0) {
278 res
= os_snprintf(buf
+ len
, buflen
- len
, "vlan_id=%d\n",
280 if (!os_snprintf_error(buflen
- len
, res
))
284 res
= mbo_ap_get_info(sta
, buf
+ len
, buflen
- len
);
288 if (sta
->supp_op_classes
&&
289 buflen
- len
> (unsigned) (17 + 2 * sta
->supp_op_classes
[0])) {
290 len
+= os_snprintf(buf
+ len
, buflen
- len
, "supp_op_classes=");
291 len
+= wpa_snprintf_hex(buf
+ len
, buflen
- len
,
292 sta
->supp_op_classes
+ 1,
293 sta
->supp_op_classes
[0]);
294 len
+= os_snprintf(buf
+ len
, buflen
- len
, "\n");
297 if (sta
->power_capab
) {
298 ret
= os_snprintf(buf
+ len
, buflen
- len
,
301 sta
->min_tx_power
, sta
->max_tx_power
);
302 if (!os_snprintf_error(buflen
- len
, ret
))
306 #ifdef CONFIG_IEEE80211AC
307 if ((sta
->flags
& WLAN_STA_VHT
) && sta
->vht_capabilities
) {
308 res
= os_snprintf(buf
+ len
, buflen
- len
,
309 "vht_caps_info=0x%08x\n",
310 le_to_host32(sta
->vht_capabilities
->
311 vht_capabilities_info
));
312 if (!os_snprintf_error(buflen
- len
, res
))
315 #endif /* CONFIG_IEEE80211AC */
317 #ifdef CONFIG_IEEE80211N
318 if ((sta
->flags
& WLAN_STA_HT
) && sta
->ht_capabilities
) {
319 res
= os_snprintf(buf
+ len
, buflen
- len
,
320 "ht_caps_info=0x%04x\n",
321 le_to_host16(sta
->ht_capabilities
->
322 ht_capabilities_info
));
323 if (!os_snprintf_error(buflen
- len
, res
))
326 #endif /* CONFIG_IEEE80211N */
328 if (sta
->ext_capability
&&
329 buflen
- len
> (unsigned) (11 + 2 * sta
->ext_capability
[0])) {
330 len
+= os_snprintf(buf
+ len
, buflen
- len
, "ext_capab=");
331 len
+= wpa_snprintf_hex(buf
+ len
, buflen
- len
,
332 sta
->ext_capability
+ 1,
333 sta
->ext_capability
[0]);
334 len
+= os_snprintf(buf
+ len
, buflen
- len
, "\n");
337 if (sta
->flags
& WLAN_STA_WDS
&& sta
->ifname_wds
) {
338 ret
= os_snprintf(buf
+ len
, buflen
- len
,
339 "wds_sta_ifname=%s\n", sta
->ifname_wds
);
340 if (!os_snprintf_error(buflen
- len
, ret
))
348 int hostapd_ctrl_iface_sta_first(struct hostapd_data
*hapd
,
349 char *buf
, size_t buflen
)
351 return hostapd_ctrl_iface_sta_mib(hapd
, hapd
->sta_list
, buf
, buflen
);
355 int hostapd_ctrl_iface_sta(struct hostapd_data
*hapd
, const char *txtaddr
,
356 char *buf
, size_t buflen
)
361 struct sta_info
*sta
;
363 if (hwaddr_aton(txtaddr
, addr
)) {
364 ret
= os_snprintf(buf
, buflen
, "FAIL\n");
365 if (os_snprintf_error(buflen
, ret
))
370 sta
= ap_get_sta(hapd
, addr
);
374 pos
= os_strchr(txtaddr
, ' ');
378 #ifdef HOSTAPD_DUMP_STATE
379 if (os_strcmp(pos
, "eapol") == 0) {
380 if (sta
->eapol_sm
== NULL
)
382 return eapol_auth_dump_state(sta
->eapol_sm
, buf
,
385 #endif /* HOSTAPD_DUMP_STATE */
390 ret
= hostapd_ctrl_iface_sta_mib(hapd
, sta
, buf
, buflen
);
391 ret
+= fst_ctrl_iface_mb_info(addr
, buf
+ ret
, buflen
- ret
);
397 int hostapd_ctrl_iface_sta_next(struct hostapd_data
*hapd
, const char *txtaddr
,
398 char *buf
, size_t buflen
)
401 struct sta_info
*sta
;
404 if (hwaddr_aton(txtaddr
, addr
) ||
405 (sta
= ap_get_sta(hapd
, addr
)) == NULL
) {
406 ret
= os_snprintf(buf
, buflen
, "FAIL\n");
407 if (os_snprintf_error(buflen
, ret
))
415 return hostapd_ctrl_iface_sta_mib(hapd
, sta
->next
, buf
, buflen
);
419 #ifdef CONFIG_P2P_MANAGER
420 static int p2p_manager_disconnect(struct hostapd_data
*hapd
, u16 stype
,
421 u8 minor_reason_code
, const u8
*addr
)
423 struct ieee80211_mgmt
*mgmt
;
427 if (!hapd
->drv_priv
|| !hapd
->driver
->send_frame
)
430 mgmt
= os_zalloc(sizeof(*mgmt
) + 100);
434 mgmt
->frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
, stype
);
435 wpa_dbg(hapd
->msg_ctx
, MSG_DEBUG
, "P2P: Disconnect STA " MACSTR
436 " with minor reason code %u (stype=%u (%s))",
437 MAC2STR(addr
), minor_reason_code
, stype
,
438 fc2str(le_to_host16(mgmt
->frame_control
)));
440 os_memcpy(mgmt
->da
, addr
, ETH_ALEN
);
441 os_memcpy(mgmt
->sa
, hapd
->own_addr
, ETH_ALEN
);
442 os_memcpy(mgmt
->bssid
, hapd
->own_addr
, ETH_ALEN
);
443 if (stype
== WLAN_FC_STYPE_DEAUTH
) {
444 mgmt
->u
.deauth
.reason_code
=
445 host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID
);
446 pos
= (u8
*) (&mgmt
->u
.deauth
.reason_code
+ 1);
448 mgmt
->u
.disassoc
.reason_code
=
449 host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID
);
450 pos
= (u8
*) (&mgmt
->u
.disassoc
.reason_code
+ 1);
453 *pos
++ = WLAN_EID_VENDOR_SPECIFIC
;
455 WPA_PUT_BE32(pos
, P2P_IE_VENDOR_TYPE
);
458 *pos
++ = P2P_ATTR_MINOR_REASON_CODE
;
459 WPA_PUT_LE16(pos
, 1);
461 *pos
++ = minor_reason_code
;
463 ret
= hapd
->driver
->send_frame(hapd
->drv_priv
, (u8
*) mgmt
,
464 pos
- (u8
*) mgmt
, 1);
467 return ret
< 0 ? -1 : 0;
469 #endif /* CONFIG_P2P_MANAGER */
472 int hostapd_ctrl_iface_deauthenticate(struct hostapd_data
*hapd
,
476 struct sta_info
*sta
;
478 u16 reason
= WLAN_REASON_PREV_AUTH_NOT_VALID
;
480 wpa_dbg(hapd
->msg_ctx
, MSG_DEBUG
, "CTRL_IFACE DEAUTHENTICATE %s",
483 if (hwaddr_aton(txtaddr
, addr
))
486 pos
= os_strstr(txtaddr
, " reason=");
488 reason
= atoi(pos
+ 8);
490 pos
= os_strstr(txtaddr
, " test=");
492 struct ieee80211_mgmt mgmt
;
494 if (!hapd
->drv_priv
|| !hapd
->driver
->send_frame
)
498 os_memset(&mgmt
, 0, sizeof(mgmt
));
499 mgmt
.frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
500 WLAN_FC_STYPE_DEAUTH
);
501 os_memcpy(mgmt
.da
, addr
, ETH_ALEN
);
502 os_memcpy(mgmt
.sa
, hapd
->own_addr
, ETH_ALEN
);
503 os_memcpy(mgmt
.bssid
, hapd
->own_addr
, ETH_ALEN
);
504 mgmt
.u
.deauth
.reason_code
= host_to_le16(reason
);
505 if (hapd
->driver
->send_frame(hapd
->drv_priv
, (u8
*) &mgmt
,
507 sizeof(mgmt
.u
.deauth
),
513 #ifdef CONFIG_P2P_MANAGER
514 pos
= os_strstr(txtaddr
, " p2p=");
516 return p2p_manager_disconnect(hapd
, WLAN_FC_STYPE_DEAUTH
,
517 atoi(pos
+ 5), addr
);
519 #endif /* CONFIG_P2P_MANAGER */
521 if (os_strstr(txtaddr
, " tx=0"))
522 hostapd_drv_sta_remove(hapd
, addr
);
524 hostapd_drv_sta_deauth(hapd
, addr
, reason
);
525 sta
= ap_get_sta(hapd
, addr
);
527 ap_sta_deauthenticate(hapd
, sta
, reason
);
528 else if (addr
[0] == 0xff)
529 hostapd_free_stas(hapd
);
535 int hostapd_ctrl_iface_disassociate(struct hostapd_data
*hapd
,
539 struct sta_info
*sta
;
541 u16 reason
= WLAN_REASON_PREV_AUTH_NOT_VALID
;
543 wpa_dbg(hapd
->msg_ctx
, MSG_DEBUG
, "CTRL_IFACE DISASSOCIATE %s",
546 if (hwaddr_aton(txtaddr
, addr
))
549 pos
= os_strstr(txtaddr
, " reason=");
551 reason
= atoi(pos
+ 8);
553 pos
= os_strstr(txtaddr
, " test=");
555 struct ieee80211_mgmt mgmt
;
557 if (!hapd
->drv_priv
|| !hapd
->driver
->send_frame
)
561 os_memset(&mgmt
, 0, sizeof(mgmt
));
562 mgmt
.frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
563 WLAN_FC_STYPE_DISASSOC
);
564 os_memcpy(mgmt
.da
, addr
, ETH_ALEN
);
565 os_memcpy(mgmt
.sa
, hapd
->own_addr
, ETH_ALEN
);
566 os_memcpy(mgmt
.bssid
, hapd
->own_addr
, ETH_ALEN
);
567 mgmt
.u
.disassoc
.reason_code
= host_to_le16(reason
);
568 if (hapd
->driver
->send_frame(hapd
->drv_priv
, (u8
*) &mgmt
,
570 sizeof(mgmt
.u
.deauth
),
576 #ifdef CONFIG_P2P_MANAGER
577 pos
= os_strstr(txtaddr
, " p2p=");
579 return p2p_manager_disconnect(hapd
, WLAN_FC_STYPE_DISASSOC
,
580 atoi(pos
+ 5), addr
);
582 #endif /* CONFIG_P2P_MANAGER */
584 if (os_strstr(txtaddr
, " tx=0"))
585 hostapd_drv_sta_remove(hapd
, addr
);
587 hostapd_drv_sta_disassoc(hapd
, addr
, reason
);
588 sta
= ap_get_sta(hapd
, addr
);
590 ap_sta_disassociate(hapd
, sta
, reason
);
591 else if (addr
[0] == 0xff)
592 hostapd_free_stas(hapd
);
598 #ifdef CONFIG_TAXONOMY
599 int hostapd_ctrl_iface_signature(struct hostapd_data
*hapd
,
601 char *buf
, size_t buflen
)
604 struct sta_info
*sta
;
606 wpa_dbg(hapd
->msg_ctx
, MSG_DEBUG
, "CTRL_IFACE SIGNATURE %s", txtaddr
);
608 if (hwaddr_aton(txtaddr
, addr
))
611 sta
= ap_get_sta(hapd
, addr
);
615 return retrieve_sta_taxonomy(hapd
, sta
, buf
, buflen
);
617 #endif /* CONFIG_TAXONOMY */
620 int hostapd_ctrl_iface_poll_sta(struct hostapd_data
*hapd
,
624 struct sta_info
*sta
;
626 wpa_dbg(hapd
->msg_ctx
, MSG_DEBUG
, "CTRL_IFACE POLL_STA %s", txtaddr
);
628 if (hwaddr_aton(txtaddr
, addr
))
631 sta
= ap_get_sta(hapd
, addr
);
635 hostapd_drv_poll_client(hapd
, hapd
->own_addr
, addr
,
636 sta
->flags
& WLAN_STA_WMM
);
641 int hostapd_ctrl_iface_status(struct hostapd_data
*hapd
, char *buf
,
644 struct hostapd_iface
*iface
= hapd
->iface
;
645 struct hostapd_hw_modes
*mode
= iface
->current_mode
;
649 ret
= os_snprintf(buf
+ len
, buflen
- len
,
653 "num_sta_non_erp=%d\n"
654 "num_sta_no_short_slot_time=%d\n"
655 "num_sta_no_short_preamble=%d\n"
657 "num_sta_ht_no_gf=%d\n"
659 "num_sta_ht_20_mhz=%d\n"
660 "num_sta_ht40_intolerant=%d\n"
663 hostapd_state_text(iface
->state
),
666 iface
->num_sta_non_erp
,
667 iface
->num_sta_no_short_slot_time
,
668 iface
->num_sta_no_short_preamble
,
670 iface
->num_sta_ht_no_gf
,
671 iface
->num_sta_no_ht
,
672 iface
->num_sta_ht_20mhz
,
673 iface
->num_sta_ht40_intolerant
,
676 if (os_snprintf_error(buflen
- len
, ret
))
680 if (!iface
->cac_started
|| !iface
->dfs_cac_ms
) {
681 ret
= os_snprintf(buf
+ len
, buflen
- len
,
682 "cac_time_seconds=%d\n"
683 "cac_time_left_seconds=N/A\n",
684 iface
->dfs_cac_ms
/ 1000);
686 /* CAC started and CAC time set - calculate remaining time */
687 struct os_reltime now
;
688 unsigned int left_time
;
690 os_reltime_age(&iface
->dfs_cac_start
, &now
);
691 left_time
= iface
->dfs_cac_ms
/ 1000 - now
.sec
;
692 ret
= os_snprintf(buf
+ len
, buflen
- len
,
693 "cac_time_seconds=%u\n"
694 "cac_time_left_seconds=%u\n",
695 iface
->dfs_cac_ms
/ 1000,
698 if (os_snprintf_error(buflen
- len
, ret
))
702 ret
= os_snprintf(buf
+ len
, buflen
- len
,
704 "secondary_channel=%d\n"
709 iface
->conf
->channel
,
710 iface
->conf
->ieee80211n
&& !hapd
->conf
->disable_11n
?
711 iface
->conf
->secondary_channel
: 0,
712 iface
->conf
->ieee80211n
&& !hapd
->conf
->disable_11n
,
713 iface
->conf
->ieee80211ac
&&
714 !hapd
->conf
->disable_11ac
,
715 iface
->conf
->beacon_int
,
716 hapd
->conf
->dtim_period
);
717 if (os_snprintf_error(buflen
- len
, ret
))
720 if (iface
->conf
->ieee80211ac
&& !hapd
->conf
->disable_11ac
) {
721 ret
= os_snprintf(buf
+ len
, buflen
- len
,
722 "vht_oper_chwidth=%d\n"
723 "vht_oper_centr_freq_seg0_idx=%d\n"
724 "vht_oper_centr_freq_seg1_idx=%d\n"
725 "vht_caps_info=%08x\n",
726 iface
->conf
->vht_oper_chwidth
,
727 iface
->conf
->vht_oper_centr_freq_seg0_idx
,
728 iface
->conf
->vht_oper_centr_freq_seg1_idx
,
729 iface
->conf
->vht_capab
);
730 if (os_snprintf_error(buflen
- len
, ret
))
735 if (iface
->conf
->ieee80211ac
&& !hapd
->conf
->disable_11ac
&& mode
) {
736 u16 rxmap
= WPA_GET_LE16(&mode
->vht_mcs_set
[0]);
737 u16 txmap
= WPA_GET_LE16(&mode
->vht_mcs_set
[4]);
739 ret
= os_snprintf(buf
+ len
, buflen
- len
,
740 "rx_vht_mcs_map=%04x\n"
741 "tx_vht_mcs_map=%04x\n",
743 if (os_snprintf_error(buflen
- len
, ret
))
748 if (iface
->conf
->ieee80211n
&& !hapd
->conf
->disable_11n
) {
749 ret
= os_snprintf(buf
+ len
, buflen
- len
,
750 "ht_caps_info=%04x\n",
751 hapd
->iconf
->ht_capab
);
752 if (os_snprintf_error(buflen
- len
, ret
))
757 if (iface
->conf
->ieee80211n
&& !hapd
->conf
->disable_11n
&& mode
) {
758 len
= hostapd_write_ht_mcs_bitmask(buf
, buflen
, len
,
762 if (iface
->current_rates
&& iface
->num_rates
) {
763 ret
= os_snprintf(buf
+ len
, buflen
- len
, "supported_rates=");
764 if (os_snprintf_error(buflen
- len
, ret
))
768 for (j
= 0; j
< iface
->num_rates
; j
++) {
769 ret
= os_snprintf(buf
+ len
, buflen
- len
, "%s%02x",
771 iface
->current_rates
[j
].rate
/ 5);
772 if (os_snprintf_error(buflen
- len
, ret
))
776 ret
= os_snprintf(buf
+ len
, buflen
- len
, "\n");
777 if (os_snprintf_error(buflen
- len
, ret
))
782 for (j
= 0; mode
&& j
< mode
->num_channels
; j
++) {
783 if (mode
->channels
[j
].freq
== iface
->freq
) {
784 ret
= os_snprintf(buf
+ len
, buflen
- len
,
786 mode
->channels
[j
].max_tx_power
);
787 if (os_snprintf_error(buflen
- len
, ret
))
794 for (i
= 0; i
< iface
->num_bss
; i
++) {
795 struct hostapd_data
*bss
= iface
->bss
[i
];
796 ret
= os_snprintf(buf
+ len
, buflen
- len
,
798 "bssid[%d]=" MACSTR
"\n"
801 (int) i
, bss
->conf
->iface
,
802 (int) i
, MAC2STR(bss
->own_addr
),
804 wpa_ssid_txt(bss
->conf
->ssid
.ssid
,
805 bss
->conf
->ssid
.ssid_len
),
806 (int) i
, bss
->num_sta
);
807 if (os_snprintf_error(buflen
- len
, ret
))
812 if (hapd
->conf
->chan_util_avg_period
) {
813 ret
= os_snprintf(buf
+ len
, buflen
- len
,
814 "chan_util_avg=%u\n",
815 iface
->chan_util_average
);
816 if (os_snprintf_error(buflen
- len
, ret
))
825 int hostapd_parse_csa_settings(const char *pos
,
826 struct csa_settings
*settings
)
830 os_memset(settings
, 0, sizeof(*settings
));
831 settings
->cs_count
= strtol(pos
, &end
, 10);
833 wpa_printf(MSG_ERROR
, "chanswitch: invalid cs_count provided");
837 settings
->freq_params
.freq
= atoi(end
);
838 if (settings
->freq_params
.freq
== 0) {
839 wpa_printf(MSG_ERROR
, "chanswitch: invalid freq provided");
843 #define SET_CSA_SETTING(str) \
845 const char *pos2 = os_strstr(pos, " " #str "="); \
847 pos2 += sizeof(" " #str "=") - 1; \
848 settings->freq_params.str = atoi(pos2); \
852 SET_CSA_SETTING(center_freq1
);
853 SET_CSA_SETTING(center_freq2
);
854 SET_CSA_SETTING(bandwidth
);
855 SET_CSA_SETTING(sec_channel_offset
);
856 settings
->freq_params
.ht_enabled
= !!os_strstr(pos
, " ht");
857 settings
->freq_params
.vht_enabled
= !!os_strstr(pos
, " vht");
858 settings
->block_tx
= !!os_strstr(pos
, " blocktx");
859 #undef SET_CSA_SETTING
865 int hostapd_ctrl_iface_stop_ap(struct hostapd_data
*hapd
)
867 return hostapd_drv_stop_ap(hapd
);
871 int hostapd_ctrl_iface_pmksa_list(struct hostapd_data
*hapd
, char *buf
,
874 return wpa_auth_pmksa_list(hapd
->wpa_auth
, buf
, len
);
878 void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data
*hapd
)
880 wpa_auth_pmksa_flush(hapd
->wpa_auth
);
884 int hostapd_ctrl_iface_pmksa_add(struct hostapd_data
*hapd
, char *cmd
)
891 int akmp
= 0, expiration
= 0;
895 * <STA addr> <PMKID> <PMK> <expiration in seconds> <akmp>
898 if (hwaddr_aton(cmd
, spa
))
901 pos
= os_strchr(cmd
, ' ');
906 if (hexstr2bin(pos
, pmkid
, PMKID_LEN
) < 0)
909 pos
= os_strchr(pos
, ' ');
914 pos2
= os_strchr(pos
, ' ');
917 pmk_len
= (pos2
- pos
) / 2;
918 if (pmk_len
< PMK_LEN
|| pmk_len
> PMK_LEN_MAX
||
919 hexstr2bin(pos
, pmk
, pmk_len
) < 0)
924 if (sscanf(pos
, "%d %d", &expiration
, &akmp
) != 2)
927 return wpa_auth_pmksa_add2(hapd
->wpa_auth
, spa
, pmk
, pmk_len
,
928 pmkid
, expiration
, akmp
);
932 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
935 int hostapd_ctrl_iface_pmksa_list_mesh(struct hostapd_data
*hapd
,
936 const u8
*addr
, char *buf
, size_t len
)
938 return wpa_auth_pmksa_list_mesh(hapd
->wpa_auth
, addr
, buf
, len
);
942 void * hostapd_ctrl_iface_pmksa_create_entry(const u8
*aa
, char *cmd
)
952 * <BSSID> <PMKID> <PMK> <expiration in seconds>
955 if (hwaddr_aton(cmd
, spa
))
958 pos
= os_strchr(cmd
, ' ');
963 if (hexstr2bin(pos
, pmkid
, PMKID_LEN
) < 0)
966 pos
= os_strchr(pos
, ' ');
971 if (hexstr2bin(pos
, pmk
, PMK_LEN
) < 0)
974 pos
= os_strchr(pos
, ' ');
979 if (sscanf(pos
, "%d", &expiration
) != 1)
982 return wpa_auth_pmksa_create_entry(aa
, spa
, pmk
, pmkid
, expiration
);
985 #endif /* CONFIG_MESH */
986 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */