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