1/* 2 * hostapd / State dump 3 * Copyright (c) 2002-2009, 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#include <time.h> 11 12#include "utils/common.h" 13#include "radius/radius_client.h" 14#include "radius/radius_server.h" 15#include "eapol_auth/eapol_auth_sm.h" 16#include "eapol_auth/eapol_auth_sm_i.h" 17#include "eap_server/eap.h" 18#include "ap/hostapd.h" 19#include "ap/ap_config.h" 20#include "ap/sta_info.h" 21#include "dump_state.h" 22#include "ap/ap_drv_ops.h" 23 24 25static void fprint_char(FILE *f, char c) 26{ 27 if (c >= 32 && c < 127) 28 fprintf(f, "%c", c); 29 else 30 fprintf(f, "<%02x>", c); 31} 32 33 34static void ieee802_1x_dump_state(FILE *f, const char *prefix, 35 struct sta_info *sta) 36{ 37 struct eapol_state_machine *sm = sta->eapol_sm; 38 if (sm == NULL) 39 return; 40 41 fprintf(f, "%sIEEE 802.1X:\n", prefix); 42 43 if (sm->identity) { 44 size_t i; 45 fprintf(f, "%sidentity=", prefix); 46 for (i = 0; i < sm->identity_len; i++) 47 fprint_char(f, sm->identity[i]); 48 fprintf(f, "\n"); 49 } 50 51 fprintf(f, "%slast EAP type: Authentication Server: %d (%s) " 52 "Supplicant: %d (%s)\n", prefix, 53 sm->eap_type_authsrv, 54 eap_server_get_name(0, sm->eap_type_authsrv), 55 sm->eap_type_supp, eap_server_get_name(0, sm->eap_type_supp)); 56 57 fprintf(f, "%scached_packets=%s\n", prefix, 58 sm->last_recv_radius ? "[RX RADIUS]" : ""); 59 60 eapol_auth_dump_state(f, prefix, sm); 61} 62 63 64/** 65 * hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file 66 */ 67static void hostapd_dump_state(struct hostapd_data *hapd) 68{ 69 FILE *f; 70 time_t now; 71 struct sta_info *sta; 72 int i; 73#ifndef CONFIG_NO_RADIUS 74 char *buf; 75#endif /* CONFIG_NO_RADIUS */ 76 struct hostap_sta_driver_data data; 77 78 if (!hapd->conf->dump_log_name) { 79 wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump " 80 "request"); 81 return; 82 } 83 84 wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'", 85 hapd->conf->dump_log_name); 86 f = fopen(hapd->conf->dump_log_name, "w"); 87 if (f == NULL) { 88 wpa_printf(MSG_WARNING, "Could not open dump file '%s' for " 89 "writing.", hapd->conf->dump_log_name); 90 return; 91 } 92 93 time(&now); 94 fprintf(f, "hostapd state dump - %s", ctime(&now)); 95 fprintf(f, "num_sta=%d num_sta_non_erp=%d " 96 "num_sta_no_short_slot_time=%d\n" 97 "num_sta_no_short_preamble=%d\n", 98 hapd->num_sta, hapd->iface->num_sta_non_erp, 99 hapd->iface->num_sta_no_short_slot_time, 100 hapd->iface->num_sta_no_short_preamble); 101 102 for (sta = hapd->sta_list; sta != NULL; sta = sta->next) { 103 fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr)); 104 105 fprintf(f, 106 " AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" 107 "\n" 108 " capability=0x%x listen_interval=%d\n", 109 sta->aid, 110 sta->flags, 111 (sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""), 112 (sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), 113 (sta->flags & WLAN_STA_PS ? "[PS]" : ""), 114 (sta->flags & WLAN_STA_TIM ? "[TIM]" : ""), 115 (sta->flags & WLAN_STA_PERM ? "[PERM]" : ""), 116 (ap_sta_is_authorized(sta) ? "[AUTHORIZED]" : ""), 117 (sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" : 118 ""), 119 (sta->flags & WLAN_STA_SHORT_PREAMBLE ? 120 "[SHORT_PREAMBLE]" : ""), 121 (sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""), 122 (sta->flags & WLAN_STA_WMM ? "[WMM]" : ""), 123 (sta->flags & WLAN_STA_MFP ? "[MFP]" : ""), 124 (sta->flags & WLAN_STA_WPS ? "[WPS]" : ""), 125 (sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""), 126 (sta->flags & WLAN_STA_WDS ? "[WDS]" : ""), 127 (sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""), 128 (sta->flags & WLAN_STA_WPS2 ? "[WPS2]" : ""), 129 sta->capability, 130 sta->listen_interval); 131 132 fprintf(f, " supported_rates="); 133 for (i = 0; i < sta->supported_rates_len; i++) 134 fprintf(f, "%02x ", sta->supported_rates[i]); 135 fprintf(f, "\n"); 136 137 fprintf(f, 138 " timeout_next=%s\n", 139 (sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" : 140 (sta->timeout_next == STA_DISASSOC ? "DISASSOC" : 141 "DEAUTH"))); 142 143 ieee802_1x_dump_state(f, " ", sta); 144 145 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) == 0) { 146 fprintf(f, " rx_pkt=%lu tx_pkt=%lu\n" 147 " rx_byte=%lu tx_byte=%lu\n", 148 data.rx_packets, data.tx_packets, 149 data.rx_bytes, data.tx_bytes); 150 } 151 } 152 153#ifndef CONFIG_NO_RADIUS 154 buf = os_malloc(4096); 155 if (buf) { 156 int count = radius_client_get_mib(hapd->radius, buf, 4096); 157 if (count < 0) 158 count = 0; 159 else if (count > 4095) 160 count = 4095; 161 buf[count] = '\0'; 162 fprintf(f, "%s", buf); 163 164#ifdef RADIUS_SERVER 165 count = radius_server_get_mib(hapd->radius_srv, buf, 4096); 166 if (count < 0) 167 count = 0; 168 else if (count > 4095) 169 count = 4095; 170 buf[count] = '\0'; 171 fprintf(f, "%s", buf); 172#endif /* RADIUS_SERVER */ 173 174 os_free(buf); 175 } 176#endif /* CONFIG_NO_RADIUS */ 177 fclose(f); 178} 179 180 181int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx) 182{ 183 size_t i; 184 185 for (i = 0; i < iface->num_bss; i++) 186 hostapd_dump_state(iface->bss[i]); 187 188 return 0; 189} 190