1214503Srpaulo/* 2214503Srpaulo * hostapd / State dump 3214503Srpaulo * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> 4214503Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214503Srpaulo */ 8214503Srpaulo 9214503Srpaulo#include "utils/includes.h" 10252726Srpaulo#include <time.h> 11214503Srpaulo 12214503Srpaulo#include "utils/common.h" 13214503Srpaulo#include "radius/radius_client.h" 14214503Srpaulo#include "radius/radius_server.h" 15214503Srpaulo#include "eapol_auth/eapol_auth_sm.h" 16214503Srpaulo#include "eapol_auth/eapol_auth_sm_i.h" 17214503Srpaulo#include "eap_server/eap.h" 18214503Srpaulo#include "ap/hostapd.h" 19214503Srpaulo#include "ap/ap_config.h" 20214503Srpaulo#include "ap/sta_info.h" 21214503Srpaulo#include "dump_state.h" 22214503Srpaulo 23214503Srpaulo 24214503Srpaulostatic void fprint_char(FILE *f, char c) 25214503Srpaulo{ 26214503Srpaulo if (c >= 32 && c < 127) 27214503Srpaulo fprintf(f, "%c", c); 28214503Srpaulo else 29214503Srpaulo fprintf(f, "<%02x>", c); 30214503Srpaulo} 31214503Srpaulo 32214503Srpaulo 33214503Srpaulostatic void ieee802_1x_dump_state(FILE *f, const char *prefix, 34214503Srpaulo struct sta_info *sta) 35214503Srpaulo{ 36214503Srpaulo struct eapol_state_machine *sm = sta->eapol_sm; 37214503Srpaulo if (sm == NULL) 38214503Srpaulo return; 39214503Srpaulo 40214503Srpaulo fprintf(f, "%sIEEE 802.1X:\n", prefix); 41214503Srpaulo 42214503Srpaulo if (sm->identity) { 43214503Srpaulo size_t i; 44214503Srpaulo fprintf(f, "%sidentity=", prefix); 45214503Srpaulo for (i = 0; i < sm->identity_len; i++) 46214503Srpaulo fprint_char(f, sm->identity[i]); 47214503Srpaulo fprintf(f, "\n"); 48214503Srpaulo } 49214503Srpaulo 50214503Srpaulo fprintf(f, "%slast EAP type: Authentication Server: %d (%s) " 51214503Srpaulo "Supplicant: %d (%s)\n", prefix, 52214503Srpaulo sm->eap_type_authsrv, 53214503Srpaulo eap_server_get_name(0, sm->eap_type_authsrv), 54214503Srpaulo sm->eap_type_supp, eap_server_get_name(0, sm->eap_type_supp)); 55214503Srpaulo 56214503Srpaulo fprintf(f, "%scached_packets=%s\n", prefix, 57214503Srpaulo sm->last_recv_radius ? "[RX RADIUS]" : ""); 58214503Srpaulo 59214503Srpaulo eapol_auth_dump_state(f, prefix, sm); 60214503Srpaulo} 61214503Srpaulo 62214503Srpaulo 63214503Srpaulo/** 64214503Srpaulo * hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file 65214503Srpaulo */ 66214503Srpaulostatic void hostapd_dump_state(struct hostapd_data *hapd) 67214503Srpaulo{ 68214503Srpaulo FILE *f; 69214503Srpaulo time_t now; 70214503Srpaulo struct sta_info *sta; 71214503Srpaulo int i; 72214503Srpaulo#ifndef CONFIG_NO_RADIUS 73214503Srpaulo char *buf; 74214503Srpaulo#endif /* CONFIG_NO_RADIUS */ 75214503Srpaulo 76214503Srpaulo if (!hapd->conf->dump_log_name) { 77214503Srpaulo wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump " 78214503Srpaulo "request"); 79214503Srpaulo return; 80214503Srpaulo } 81214503Srpaulo 82214503Srpaulo wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'", 83214503Srpaulo hapd->conf->dump_log_name); 84214503Srpaulo f = fopen(hapd->conf->dump_log_name, "w"); 85214503Srpaulo if (f == NULL) { 86214503Srpaulo wpa_printf(MSG_WARNING, "Could not open dump file '%s' for " 87214503Srpaulo "writing.", hapd->conf->dump_log_name); 88214503Srpaulo return; 89214503Srpaulo } 90214503Srpaulo 91214503Srpaulo time(&now); 92214503Srpaulo fprintf(f, "hostapd state dump - %s", ctime(&now)); 93214503Srpaulo fprintf(f, "num_sta=%d num_sta_non_erp=%d " 94214503Srpaulo "num_sta_no_short_slot_time=%d\n" 95214503Srpaulo "num_sta_no_short_preamble=%d\n", 96214503Srpaulo hapd->num_sta, hapd->iface->num_sta_non_erp, 97214503Srpaulo hapd->iface->num_sta_no_short_slot_time, 98214503Srpaulo hapd->iface->num_sta_no_short_preamble); 99214503Srpaulo 100214503Srpaulo for (sta = hapd->sta_list; sta != NULL; sta = sta->next) { 101214503Srpaulo fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr)); 102214503Srpaulo 103214503Srpaulo fprintf(f, 104252726Srpaulo " AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" 105252726Srpaulo "\n" 106214503Srpaulo " capability=0x%x listen_interval=%d\n", 107214503Srpaulo sta->aid, 108214503Srpaulo sta->flags, 109214503Srpaulo (sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""), 110214503Srpaulo (sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), 111214503Srpaulo (sta->flags & WLAN_STA_PS ? "[PS]" : ""), 112214503Srpaulo (sta->flags & WLAN_STA_TIM ? "[TIM]" : ""), 113214503Srpaulo (sta->flags & WLAN_STA_PERM ? "[PERM]" : ""), 114252726Srpaulo (ap_sta_is_authorized(sta) ? "[AUTHORIZED]" : ""), 115214503Srpaulo (sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" : 116214503Srpaulo ""), 117214503Srpaulo (sta->flags & WLAN_STA_SHORT_PREAMBLE ? 118214503Srpaulo "[SHORT_PREAMBLE]" : ""), 119214503Srpaulo (sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""), 120214503Srpaulo (sta->flags & WLAN_STA_WMM ? "[WMM]" : ""), 121214503Srpaulo (sta->flags & WLAN_STA_MFP ? "[MFP]" : ""), 122214503Srpaulo (sta->flags & WLAN_STA_WPS ? "[WPS]" : ""), 123214503Srpaulo (sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""), 124214503Srpaulo (sta->flags & WLAN_STA_WDS ? "[WDS]" : ""), 125214503Srpaulo (sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""), 126252726Srpaulo (sta->flags & WLAN_STA_WPS2 ? "[WPS2]" : ""), 127214503Srpaulo sta->capability, 128214503Srpaulo sta->listen_interval); 129214503Srpaulo 130214503Srpaulo fprintf(f, " supported_rates="); 131214503Srpaulo for (i = 0; i < sta->supported_rates_len; i++) 132214503Srpaulo fprintf(f, "%02x ", sta->supported_rates[i]); 133214503Srpaulo fprintf(f, "\n"); 134214503Srpaulo 135214503Srpaulo fprintf(f, 136214503Srpaulo " timeout_next=%s\n", 137214503Srpaulo (sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" : 138214503Srpaulo (sta->timeout_next == STA_DISASSOC ? "DISASSOC" : 139214503Srpaulo "DEAUTH"))); 140214503Srpaulo 141214503Srpaulo ieee802_1x_dump_state(f, " ", sta); 142214503Srpaulo } 143214503Srpaulo 144214503Srpaulo#ifndef CONFIG_NO_RADIUS 145214503Srpaulo buf = os_malloc(4096); 146214503Srpaulo if (buf) { 147214503Srpaulo int count = radius_client_get_mib(hapd->radius, buf, 4096); 148214503Srpaulo if (count < 0) 149214503Srpaulo count = 0; 150214503Srpaulo else if (count > 4095) 151214503Srpaulo count = 4095; 152214503Srpaulo buf[count] = '\0'; 153214503Srpaulo fprintf(f, "%s", buf); 154214503Srpaulo 155214503Srpaulo#ifdef RADIUS_SERVER 156214503Srpaulo count = radius_server_get_mib(hapd->radius_srv, buf, 4096); 157214503Srpaulo if (count < 0) 158214503Srpaulo count = 0; 159214503Srpaulo else if (count > 4095) 160214503Srpaulo count = 4095; 161214503Srpaulo buf[count] = '\0'; 162214503Srpaulo fprintf(f, "%s", buf); 163214503Srpaulo#endif /* RADIUS_SERVER */ 164214503Srpaulo 165214503Srpaulo os_free(buf); 166214503Srpaulo } 167214503Srpaulo#endif /* CONFIG_NO_RADIUS */ 168214503Srpaulo fclose(f); 169214503Srpaulo} 170214503Srpaulo 171214503Srpaulo 172214503Srpauloint handle_dump_state_iface(struct hostapd_iface *iface, void *ctx) 173214503Srpaulo{ 174214503Srpaulo size_t i; 175214503Srpaulo 176214503Srpaulo for (i = 0; i < iface->num_bss; i++) 177214503Srpaulo hostapd_dump_state(iface->bss[i]); 178214503Srpaulo 179214503Srpaulo return 0; 180214503Srpaulo} 181