X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fap%2Fctrl_iface_ap.c;h=3680fda3153f5197fc14a0a69eeaf6d70c34ca56;hb=04059ab84458f43dda9130e4fff745b268424b99;hp=4125fd56bb9c40010fa7210ddb23c3849f05a4c3;hpb=b3493fa1101eac07ee248018b4bdccb6ad0e6d95;p=mech_eap.git diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index 4125fd5..3680fda 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -1,6 +1,6 @@ /* * Control interface for shared AP commands - * Copyright (c) 2004-2013, Jouni Malinen + * Copyright (c) 2004-2014, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -10,6 +10,9 @@ #include "utils/common.h" #include "common/ieee802_11_defs.h" +#include "common/sae.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "fst/fst_ctrl_iface.h" #include "hostapd.h" #include "ieee802_1x.h" #include "wpa_auth.h" @@ -19,26 +22,65 @@ #include "p2p_hostapd.h" #include "ctrl_iface_ap.h" #include "ap_drv_ops.h" +#include "mbo_ap.h" +#include "taxonomy.h" + + +static int hostapd_get_sta_tx_rx(struct hostapd_data *hapd, + struct sta_info *sta, + char *buf, size_t buflen) +{ + struct hostap_sta_driver_data data; + int ret; + + if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0) + return 0; + + ret = os_snprintf(buf, buflen, "rx_packets=%lu\ntx_packets=%lu\n" + "rx_bytes=%llu\ntx_bytes=%llu\ninactive_msec=%lu\n", + data.rx_packets, data.tx_packets, + data.rx_bytes, data.tx_bytes, data.inactive_msec); + if (os_snprintf_error(buflen, ret)) + return 0; + return ret; +} static int hostapd_get_sta_conn_time(struct sta_info *sta, char *buf, size_t buflen) { struct os_reltime age; - int len = 0, ret; + int ret; if (!sta->connected_time.sec) return 0; os_reltime_age(&sta->connected_time, &age); - ret = os_snprintf(buf + len, buflen - len, "connected_time=%u\n", + ret = os_snprintf(buf, buflen, "connected_time=%u\n", (unsigned int) age.sec); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; + if (os_snprintf_error(buflen, ret)) + return 0; + return ret; +} - return len; + +static const char * timeout_next_str(int val) +{ + switch (val) { + case STA_NULLFUNC: + return "NULLFUNC POLL"; + case STA_DISASSOC: + return "DISASSOC"; + case STA_DEAUTH: + return "DEAUTH"; + case STA_REMOVE: + return "REMOVE"; + case STA_DISASSOC_FROM_CLI: + return "DISASSOC_FROM_CLI"; + } + + return "?"; } @@ -46,19 +88,42 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, struct sta_info *sta, char *buf, size_t buflen) { - int len, res, ret; + int len, res, ret, i; - if (sta == NULL) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } + if (!sta) + return 0; len = 0; - ret = os_snprintf(buf + len, buflen - len, MACSTR "\n", + ret = os_snprintf(buf + len, buflen - len, MACSTR "\nflags=", MAC2STR(sta->addr)); - if (ret < 0 || (size_t) ret >= buflen - len) + if (os_snprintf_error(buflen - len, ret)) + return len; + len += ret; + + ret = ap_sta_flags_txt(sta->flags, buf + len, buflen - len); + if (ret < 0) + return len; + len += ret; + + ret = os_snprintf(buf + len, buflen - len, "\naid=%d\ncapability=0x%x\n" + "listen_interval=%d\nsupported_rates=", + sta->aid, sta->capability, sta->listen_interval); + if (os_snprintf_error(buflen - len, ret)) + return len; + len += ret; + + for (i = 0; i < sta->supported_rates_len; i++) { + ret = os_snprintf(buf + len, buflen - len, "%02x%s", + sta->supported_rates[i], + i + 1 < sta->supported_rates_len ? " " : ""); + if (os_snprintf_error(buflen - len, ret)) + return len; + len += ret; + } + + ret = os_snprintf(buf + len, buflen - len, "\ntimeout_next=%s\n", + timeout_next_str(sta->timeout_next)); + if (os_snprintf_error(buflen - len, ret)) return len; len += ret; @@ -79,10 +144,38 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, if (res >= 0) len += res; - res = hostapd_get_sta_conn_time(sta, buf + len, buflen - len); + len += hostapd_get_sta_tx_rx(hapd, sta, buf + len, buflen - len); + len += hostapd_get_sta_conn_time(sta, buf + len, buflen - len); + +#ifdef CONFIG_SAE + if (sta->sae && sta->sae->state == SAE_ACCEPTED) { + res = os_snprintf(buf + len, buflen - len, "sae_group=%d\n", + sta->sae->group); + if (!os_snprintf_error(buflen - len, res)) + len += res; + } +#endif /* CONFIG_SAE */ + + if (sta->vlan_id > 0) { + res = os_snprintf(buf + len, buflen - len, "vlan_id=%d\n", + sta->vlan_id); + if (!os_snprintf_error(buflen - len, res)) + len += res; + } + + res = mbo_ap_get_info(sta, buf + len, buflen - len); if (res >= 0) len += res; + if (sta->supp_op_classes && + buflen - len > (unsigned) (17 + 2 * sta->supp_op_classes[0])) { + len += os_snprintf(buf + len, buflen - len, "supp_op_classes="); + len += wpa_snprintf_hex(buf + len, buflen - len, + sta->supp_op_classes + 1, + sta->supp_op_classes[0]); + len += os_snprintf(buf + len, buflen - len, "\n"); + } + return len; } @@ -99,15 +192,40 @@ int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr, { u8 addr[ETH_ALEN]; int ret; + const char *pos; + struct sta_info *sta; if (hwaddr_aton(txtaddr, addr)) { ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) + if (os_snprintf_error(buflen, ret)) return 0; return ret; } - return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr), - buf, buflen); + + sta = ap_get_sta(hapd, addr); + if (sta == NULL) + return -1; + + pos = os_strchr(txtaddr, ' '); + if (pos) { + pos++; + +#ifdef HOSTAPD_DUMP_STATE + if (os_strcmp(pos, "eapol") == 0) { + if (sta->eapol_sm == NULL) + return -1; + return eapol_auth_dump_state(sta->eapol_sm, buf, + buflen); + } +#endif /* HOSTAPD_DUMP_STATE */ + + return -1; + } + + ret = hostapd_ctrl_iface_sta_mib(hapd, sta, buf, buflen); + ret += fst_ctrl_iface_mb_info(addr, buf + ret, buflen - ret); + + return ret; } @@ -121,10 +239,14 @@ int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr, if (hwaddr_aton(txtaddr, addr) || (sta = ap_get_sta(hapd, addr)) == NULL) { ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) + if (os_snprintf_error(buflen, ret)) return 0; return ret; - } + } + + if (!sta->next) + return 0; + return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen); } @@ -137,18 +259,19 @@ static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype, int ret; u8 *pos; - if (hapd->driver->send_frame == NULL) + if (!hapd->drv_priv || !hapd->driver->send_frame) return -1; mgmt = os_zalloc(sizeof(*mgmt) + 100); if (mgmt == NULL) return -1; + mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype); wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR - " with minor reason code %u (stype=%u)", - MAC2STR(addr), minor_reason_code, stype); + " with minor reason code %u (stype=%u (%s))", + MAC2STR(addr), minor_reason_code, stype, + fc2str(le_to_host16(mgmt->frame_control))); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype); os_memcpy(mgmt->da, addr, ETH_ALEN); os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); @@ -164,9 +287,8 @@ static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype, *pos++ = WLAN_EID_VENDOR_SPECIFIC; *pos++ = 4 + 3 + 1; - WPA_PUT_BE24(pos, OUI_WFA); - pos += 3; - *pos++ = P2P_OUI_TYPE; + WPA_PUT_BE32(pos, P2P_IE_VENDOR_TYPE); + pos += 4; *pos++ = P2P_ATTR_MINOR_REASON_CODE; WPA_PUT_LE16(pos, 1); @@ -196,11 +318,15 @@ int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, if (hwaddr_aton(txtaddr, addr)) return -1; + pos = os_strstr(txtaddr, " reason="); + if (pos) + reason = atoi(pos + 8); + pos = os_strstr(txtaddr, " test="); if (pos) { struct ieee80211_mgmt mgmt; int encrypt; - if (hapd->driver->send_frame == NULL) + if (!hapd->drv_priv || !hapd->driver->send_frame) return -1; pos += 6; encrypt = atoi(pos); @@ -210,8 +336,7 @@ int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, os_memcpy(mgmt.da, addr, ETH_ALEN); os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); - mgmt.u.deauth.reason_code = - host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + mgmt.u.deauth.reason_code = host_to_le16(reason); if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt, IEEE80211_HDRLEN + sizeof(mgmt.u.deauth), @@ -228,11 +353,10 @@ int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, } #endif /* CONFIG_P2P_MANAGER */ - pos = os_strstr(txtaddr, " reason="); - if (pos) - reason = atoi(pos + 8); - - hostapd_drv_sta_deauth(hapd, addr, reason); + if (os_strstr(txtaddr, " tx=0")) + hostapd_drv_sta_remove(hapd, addr); + else + hostapd_drv_sta_deauth(hapd, addr, reason); sta = ap_get_sta(hapd, addr); if (sta) ap_sta_deauthenticate(hapd, sta, reason); @@ -257,11 +381,15 @@ int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, if (hwaddr_aton(txtaddr, addr)) return -1; + pos = os_strstr(txtaddr, " reason="); + if (pos) + reason = atoi(pos + 8); + pos = os_strstr(txtaddr, " test="); if (pos) { struct ieee80211_mgmt mgmt; int encrypt; - if (hapd->driver->send_frame == NULL) + if (!hapd->drv_priv || !hapd->driver->send_frame) return -1; pos += 6; encrypt = atoi(pos); @@ -271,8 +399,7 @@ int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, os_memcpy(mgmt.da, addr, ETH_ALEN); os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); - mgmt.u.disassoc.reason_code = - host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + mgmt.u.disassoc.reason_code = host_to_le16(reason); if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt, IEEE80211_HDRLEN + sizeof(mgmt.u.deauth), @@ -289,11 +416,10 @@ int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, } #endif /* CONFIG_P2P_MANAGER */ - pos = os_strstr(txtaddr, " reason="); - if (pos) - reason = atoi(pos + 8); - - hostapd_drv_sta_disassoc(hapd, addr, reason); + if (os_strstr(txtaddr, " tx=0")) + hostapd_drv_sta_remove(hapd, addr); + else + hostapd_drv_sta_disassoc(hapd, addr, reason); sta = ap_get_sta(hapd, addr); if (sta) ap_sta_disassociate(hapd, sta, reason); @@ -304,6 +430,49 @@ int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, } +#ifdef CONFIG_TAXONOMY +int hostapd_ctrl_iface_signature(struct hostapd_data *hapd, + const char *txtaddr, + char *buf, size_t buflen) +{ + u8 addr[ETH_ALEN]; + struct sta_info *sta; + + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE SIGNATURE %s", txtaddr); + + if (hwaddr_aton(txtaddr, addr)) + return -1; + + sta = ap_get_sta(hapd, addr); + if (!sta) + return -1; + + return retrieve_sta_taxonomy(hapd, sta, buf, buflen); +} +#endif /* CONFIG_TAXONOMY */ + + +int hostapd_ctrl_iface_poll_sta(struct hostapd_data *hapd, + const char *txtaddr) +{ + u8 addr[ETH_ALEN]; + struct sta_info *sta; + + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE POLL_STA %s", txtaddr); + + if (hwaddr_aton(txtaddr, addr)) + return -1; + + sta = ap_get_sta(hapd, addr); + if (!sta) + return -1; + + hostapd_drv_poll_client(hapd, hapd->own_addr, addr, + sta->flags & WLAN_STA_WMM); + return 0; +} + + int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, size_t buflen) { @@ -322,6 +491,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, "num_sta_ht_no_gf=%d\n" "num_sta_no_ht=%d\n" "num_sta_ht_20_mhz=%d\n" + "num_sta_ht40_intolerant=%d\n" "olbc_ht=%d\n" "ht_op_mode=0x%x\n", hostapd_state_text(iface->state), @@ -334,9 +504,32 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, iface->num_sta_ht_no_gf, iface->num_sta_no_ht, iface->num_sta_ht_20mhz, + iface->num_sta_ht40_intolerant, iface->olbc_ht, iface->ht_op_mode); - if (ret < 0 || (size_t) ret >= buflen - len) + if (os_snprintf_error(buflen - len, ret)) + return len; + len += ret; + + if (!iface->cac_started || !iface->dfs_cac_ms) { + ret = os_snprintf(buf + len, buflen - len, + "cac_time_seconds=%d\n" + "cac_time_left_seconds=N/A\n", + iface->dfs_cac_ms / 1000); + } else { + /* CAC started and CAC time set - calculate remaining time */ + struct os_reltime now; + unsigned int left_time; + + os_reltime_age(&iface->dfs_cac_start, &now); + left_time = iface->dfs_cac_ms / 1000 - now.sec; + ret = os_snprintf(buf + len, buflen - len, + "cac_time_seconds=%u\n" + "cac_time_left_seconds=%u\n", + iface->dfs_cac_ms / 1000, + left_time); + } + if (os_snprintf_error(buflen - len, ret)) return len; len += ret; @@ -344,20 +537,28 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, "channel=%u\n" "secondary_channel=%d\n" "ieee80211n=%d\n" - "ieee80211ac=%d\n" - "vht_oper_chwidth=%d\n" - "vht_oper_centr_freq_seg0_idx=%d\n" - "vht_oper_centr_freq_seg1_idx=%d\n", + "ieee80211ac=%d\n", iface->conf->channel, - iface->conf->secondary_channel, - iface->conf->ieee80211n, - iface->conf->ieee80211ac, - iface->conf->vht_oper_chwidth, - iface->conf->vht_oper_centr_freq_seg0_idx, - iface->conf->vht_oper_centr_freq_seg1_idx); - if (ret < 0 || (size_t) ret >= buflen - len) + iface->conf->ieee80211n && !hapd->conf->disable_11n ? + iface->conf->secondary_channel : 0, + iface->conf->ieee80211n && !hapd->conf->disable_11n, + iface->conf->ieee80211ac && + !hapd->conf->disable_11ac); + if (os_snprintf_error(buflen - len, ret)) return len; len += ret; + if (iface->conf->ieee80211ac && !hapd->conf->disable_11ac) { + ret = os_snprintf(buf + len, buflen - len, + "vht_oper_chwidth=%d\n" + "vht_oper_centr_freq_seg0_idx=%d\n" + "vht_oper_centr_freq_seg1_idx=%d\n", + iface->conf->vht_oper_chwidth, + iface->conf->vht_oper_centr_freq_seg0_idx, + iface->conf->vht_oper_centr_freq_seg1_idx); + if (os_snprintf_error(buflen - len, ret)) + return len; + len += ret; + } for (i = 0; i < iface->num_bss; i++) { struct hostapd_data *bss = iface->bss[i]; @@ -372,7 +573,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, wpa_ssid_txt(bss->conf->ssid.ssid, bss->conf->ssid.ssid_len), (int) i, bss->num_sta); - if (ret < 0 || (size_t) ret >= buflen - len) + if (os_snprintf_error(buflen - len, ret)) return len; len += ret; } @@ -386,9 +587,6 @@ int hostapd_parse_csa_settings(const char *pos, { char *end; - if (!settings) - return -1; - os_memset(settings, 0, sizeof(*settings)); settings->cs_count = strtol(pos, &end, 10); if (pos == end) { @@ -422,3 +620,22 @@ int hostapd_parse_csa_settings(const char *pos, return 0; } + + +int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd) +{ + return hostapd_drv_stop_ap(hapd); +} + + +int hostapd_ctrl_iface_pmksa_list(struct hostapd_data *hapd, char *buf, + size_t len) +{ + return wpa_auth_pmksa_list(hapd->wpa_auth, buf, len); +} + + +void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data *hapd) +{ + wpa_auth_pmksa_flush(hapd->wpa_auth); +}