📄 hostapd.c
字号:
/* * hostapd / Initialization and configuration * Copyright (c) 2002-2006, Jouni Malinen <jkmaline@cc.hut.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#ifndef CONFIG_NATIVE_WINDOWS#include <syslog.h>#endif /* CONFIG_NATIVE_WINDOWS */#include "eloop.h"#include "hostapd.h"#include "ieee802_1x.h"#include "ieee802_11.h"#include "beacon.h"#include "hw_features.h"#include "accounting.h"#include "eapol_sm.h"#include "iapp.h"#include "ap.h"#include "ieee802_11_auth.h"#include "sta_info.h"#include "driver.h"#include "radius_client.h"#include "radius_server.h"#include "wpa.h"#include "preauth.h"#include "ctrl_iface.h"#include "tls.h"#include "eap_sim_db.h"#include "eap.h"#include "version.h"#ifndef CONFIG_NATIVE_WINDOWS#include "hostap_common.h"#else /* CONFIG_NATIVE_WINDOWS */#define WLAN_REASON_MICHAEL_MIC_FAILURE 14#endif /* CONFIG_NATIVE_WINDOWS */struct hapd_interfaces { int count; struct hostapd_iface **iface;};unsigned char rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };extern int wpa_debug_level;extern int wpa_debug_show_keys;extern int wpa_debug_timestamp;void hostapd_logger(struct hostapd_data *hapd, const u8 *addr, unsigned int module, int level, const char *fmt, ...){ char *format, *module_str; int maxlen; va_list ap; int conf_syslog_level, conf_stdout_level; unsigned int conf_syslog, conf_stdout; maxlen = strlen(fmt) + 100; format = malloc(maxlen); if (!format) return; if (hapd && hapd->conf) { conf_syslog_level = hapd->conf->logger_syslog_level; conf_stdout_level = hapd->conf->logger_stdout_level; conf_syslog = hapd->conf->logger_syslog; conf_stdout = hapd->conf->logger_stdout; } else { conf_syslog_level = conf_stdout_level = 0; conf_syslog = conf_stdout = (unsigned int) -1; } switch (module) { case HOSTAPD_MODULE_IEEE80211: module_str = "IEEE 802.11"; break; case HOSTAPD_MODULE_IEEE8021X: module_str = "IEEE 802.1X"; break; case HOSTAPD_MODULE_RADIUS: module_str = "RADIUS"; break; case HOSTAPD_MODULE_WPA: module_str = "WPA"; break; case HOSTAPD_MODULE_DRIVER: module_str = "DRIVER"; break; case HOSTAPD_MODULE_IAPP: module_str = "IAPP"; break; default: module_str = NULL; break; } if (hapd && hapd->conf && addr) snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s", hapd->conf->iface, MAC2STR(addr), module_str ? " " : "", module_str, fmt); else if (hapd && hapd->conf) snprintf(format, maxlen, "%s:%s%s %s", hapd->conf->iface, module_str ? " " : "", module_str, fmt); else if (addr) snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", MAC2STR(addr), module_str ? " " : "", module_str, fmt); else snprintf(format, maxlen, "%s%s%s", module_str, module_str ? ": " : "", fmt); if ((conf_stdout & module) && level >= conf_stdout_level) { wpa_debug_print_timestamp(); va_start(ap, fmt); vprintf(format, ap); va_end(ap); printf("\n"); }#ifndef CONFIG_NATIVE_WINDOWS if ((conf_syslog & module) && level >= conf_syslog_level) { int priority; switch (level) { case HOSTAPD_LEVEL_DEBUG_VERBOSE: case HOSTAPD_LEVEL_DEBUG: priority = LOG_DEBUG; break; case HOSTAPD_LEVEL_INFO: priority = LOG_INFO; break; case HOSTAPD_LEVEL_NOTICE: priority = LOG_NOTICE; break; case HOSTAPD_LEVEL_WARNING: priority = LOG_WARNING; break; default: priority = LOG_INFO; break; } va_start(ap, fmt); vsyslog(priority, format, ap); va_end(ap); }#endif /* CONFIG_NATIVE_WINDOWS */ free(format);}const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf, size_t buflen){ if (buflen == 0 || addr == NULL) return NULL; if (addr->af == AF_INET) { snprintf(buf, buflen, "%s", inet_ntoa(addr->u.v4)); } else { buf[0] = '\0'; }#ifdef CONFIG_IPV6 if (addr->af == AF_INET6) { if (inet_ntop(AF_INET6, &addr->u.v6, buf, buflen) == NULL) buf[0] = '\0'; }#endif /* CONFIG_IPV6 */ return buf;}static void hostapd_deauth_all_stas(struct hostapd_data *hapd){#if 0 u8 addr[ETH_ALEN]; memset(addr, 0xff, ETH_ALEN); hostapd_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);#else /* New Prism2.5/3 STA firmware versions seem to have issues with this * broadcast deauth frame. This gets the firmware in odd state where * nothing works correctly, so let's skip sending this for a while * until the issue has been resolved. */#endif}/* This function will be called whenever a station associates with the AP */void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, int reassoc){ if (hapd->tkip_countermeasures) { hostapd_sta_deauth(hapd, sta->addr, WLAN_REASON_MICHAEL_MIC_FAILURE); return; } /* IEEE 802.11F (IAPP) */ if (hapd->conf->ieee802_11f) iapp_new_station(hapd->iapp, sta); /* Start accounting here, if IEEE 802.1X and WPA are not used. * IEEE 802.1X/WPA code will start accounting after the station has * been authorized. */ if (!hapd->conf->ieee802_1x && !hapd->conf->wpa) accounting_sta_start(hapd, sta); /* Start IEEE 802.1X authentication process for new stations */ ieee802_1x_new_station(hapd, sta); if (reassoc) wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH); else wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);}#ifdef EAP_SERVERstatic int hostapd_sim_db_cb_sta(struct hostapd_data *hapd, struct sta_info *sta, void *ctx){ if (eapol_sm_eap_pending_cb(sta->eapol_sm, ctx) == 0) return 1; return 0;}static void hostapd_sim_db_cb(void *ctx, void *session_ctx){ struct hostapd_data *hapd = ctx; if (ap_for_each_sta(hapd, hostapd_sim_db_cb_sta, session_ctx) == 0) radius_server_eap_pending_cb(hapd->radius_srv, session_ctx);}#endif /* EAP_SERVER */static void handle_term(int sig, void *eloop_ctx, void *signal_ctx){ printf("Signal %d received - terminating\n", sig); eloop_terminate();}static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, struct wpa_auth_config *wconf){ wconf->wpa = conf->wpa; wconf->wpa_key_mgmt = conf->wpa_key_mgmt; wconf->wpa_pairwise = conf->wpa_pairwise; wconf->wpa_group = conf->wpa_group; wconf->wpa_group_rekey = conf->wpa_group_rekey; wconf->wpa_strict_rekey = conf->wpa_strict_rekey; wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey; wconf->rsn_preauth = conf->rsn_preauth; wconf->stakey = conf->stakey; wconf->eapol_version = conf->eapol_version;}#ifndef CONFIG_NATIVE_WINDOWSstatic void handle_reload(int sig, void *eloop_ctx, void *signal_ctx){ struct hapd_interfaces *hapds = (struct hapd_interfaces *) eloop_ctx; struct hostapd_config *newconf; int i; struct wpa_auth_config wpa_auth_conf; printf("Signal %d received - reloading configuration\n", sig); for (i = 0; i < hapds->count; i++) { struct hostapd_data *hapd = hapds->iface[i]->bss[0]; newconf = hostapd_config_read(hapds->iface[i]->config_fname); if (newconf == NULL) { printf("Failed to read new configuration file - " "continuing with old.\n"); continue; } /* TODO: update dynamic data based on changed configuration * items (e.g., open/close sockets, remove stations added to * deny list, etc.) */ radius_client_flush(hapd->radius, 0); hostapd_config_free(hapd->iconf); hostapd_wpa_auth_conf(&newconf->bss[0], &wpa_auth_conf); wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf); hapd->iconf = newconf; hapd->conf = &newconf->bss[0]; hapds->iface[i]->conf = newconf; }}#ifdef HOSTAPD_DUMP_STATEstatic void hostapd_dump_state(struct hostapd_data *hapd){ FILE *f; time_t now; struct sta_info *sta; int i; char *buf; if (!hapd->conf->dump_log_name) { printf("Dump file not defined - ignoring dump request\n"); return; } printf("Dumping hostapd state to '%s'\n", hapd->conf->dump_log_name); f = fopen(hapd->conf->dump_log_name, "w"); if (f == NULL) { printf("Could not open dump file '%s' for writing.\n", hapd->conf->dump_log_name); return; } time(&now); fprintf(f, "hostapd state dump - %s", ctime(&now)); for (sta = hapd->sta_list; sta != NULL; sta = sta->next) { fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr)); fprintf(f, " AID=%d flags=0x%x %s%s%s%s%s%s\n" " capability=0x%x listen_interval=%d\n", sta->aid, sta->flags, (sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""), (sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), (sta->flags & WLAN_STA_PS ? "[PS]" : ""), (sta->flags & WLAN_STA_TIM ? "[TIM]" : ""), (sta->flags & WLAN_STA_PERM ? "[PERM]" : ""), (sta->flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""), sta->capability, sta->listen_interval); fprintf(f, " supported_rates="); for (i = 0; i < sta->supported_rates_len; i++) fprintf(f, "%02x ", sta->supported_rates[i]); fprintf(f, "\n"); fprintf(f, " timeout_next=%s\n", (sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" : (sta->timeout_next == STA_DISASSOC ? "DISASSOC" : "DEAUTH"))); ieee802_1x_dump_state(f, " ", sta); } buf = malloc(4096); if (buf) { int count = radius_client_get_mib(hapd->radius, buf, 4096); if (count < 0) count = 0; else if (count > 4095) count = 4095; buf[count] = '\0'; fprintf(f, "%s", buf); count = radius_server_get_mib(hapd->radius_srv, buf, 4096); if (count < 0) count = 0; else if (count > 4095) count = 4095; buf[count] = '\0'; fprintf(f, "%s", buf); free(buf); } fclose(f);}#endif /* HOSTAPD_DUMP_STATE */static void handle_dump_state(int sig, void *eloop_ctx, void *signal_ctx){#ifdef HOSTAPD_DUMP_STATE struct hapd_interfaces *hapds = (struct hapd_interfaces *) eloop_ctx; int i, j; for (i = 0; i < hapds->count; i++) { struct hostapd_iface *hapd_iface = hapds->iface[i]; for (j = 0; j < hapd_iface->num_bss; j++) hostapd_dump_state(hapd_iface->bss[j]); }#endif /* HOSTAPD_DUMP_STATE */}#endif /* CONFIG_NATIVE_WINDOWS */static void hostapd_cleanup(struct hostapd_data *hapd){ hostapd_ctrl_iface_deinit(hapd); free(hapd->default_wep_key); hapd->default_wep_key = NULL; iapp_deinit(hapd->iapp); accounting_deinit(hapd); rsn_preauth_iface_deinit(hapd); if (hapd->wpa_auth) { wpa_deinit(hapd->wpa_auth); hapd->wpa_auth = NULL; if (hostapd_set_privacy(hapd, 0)) { wpa_printf(MSG_DEBUG, "Could not disable " "PrivacyInvoked for interface %s", hapd->conf->iface); } if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) { wpa_printf(MSG_DEBUG, "Could not remove generic " "information element from interface %s", hapd->conf->iface); } } ieee802_1x_deinit(hapd); hostapd_acl_deinit(hapd); radius_client_deinit(hapd->radius); hapd->radius = NULL; radius_server_deinit(hapd->radius_srv); hapd->radius_srv = NULL; hostapd_wireless_event_deinit(hapd);#ifdef EAP_TLS_FUNCS if (hapd->ssl_ctx) { tls_deinit(hapd->ssl_ctx); hapd->ssl_ctx = NULL; }#endif /* EAP_TLS_FUNCS */#ifdef EAP_SERVER if (hapd->eap_sim_db_priv) eap_sim_db_deinit(hapd->eap_sim_db_priv);#endif /* EAP_SERVER */}static void hostapd_cleanup_iface(struct hostapd_iface *iface){ hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); free(iface->current_rates); hostapd_config_free(iface->conf); free(iface->config_fname); free(iface->bss); free(iface);}static int hostapd_flush_old_stations(struct hostapd_data *hapd){ int ret = 0; wpa_printf(MSG_DEBUG, "Flushing old station entries"); if (hostapd_flush(hapd)) { printf("Could not connect to kernel driver.\n"); ret = -1; } wpa_printf(MSG_DEBUG, "Deauthenticate all stations"); hostapd_deauth_all_stas(hapd); return ret;}static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr, logger_level level, const char *txt){ struct hostapd_data *hapd = ctx; int hlevel; switch (level) { case LOGGER_WARNING: hlevel = HOSTAPD_LEVEL_WARNING; break; case LOGGER_INFO: hlevel = HOSTAPD_LEVEL_INFO; break; case LOGGER_DEBUG: default: hlevel = HOSTAPD_LEVEL_DEBUG; break; } hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt);}static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr, u16 reason){ struct hostapd_data *hapd = ctx; struct sta_info *sta; wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: " "STA " MACSTR " reason %d", __func__, MAC2STR(addr), reason); sta = ap_get_sta(hapd, addr); hostapd_sta_deauth(hapd, addr, reason); if (sta == NULL) return; sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED); eloop_cancel_timeout(ap_handle_timer, hapd, sta); eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta); sta->timeout_next = STA_REMOVE;}static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr){ struct hostapd_data *hapd = ctx; ieee80211_michael_mic_failure(hapd, addr, 0);}static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr, wpa_eapol_variable var, int value){ struct hostapd_data *hapd = ctx; struct sta_info *sta = ap_get_sta(hapd, addr); if (sta == NULL) return; switch (var) { case WPA_EAPOL_portEnabled: ieee802_1x_notify_port_enabled(sta->eapol_sm, value); break; case WPA_EAPOL_portValid: ieee802_1x_notify_port_valid(sta->eapol_sm, value); break; case WPA_EAPOL_authorized: ieee802_1x_set_sta_authorized(hapd, sta, value); break; case WPA_EAPOL_portControl_Auto: if (sta->eapol_sm) sta->eapol_sm->portControl = Auto; break; case WPA_EAPOL_keyRun: if (sta->eapol_sm) sta->eapol_sm->keyRun = value ? TRUE : FALSE; break; case WPA_EAPOL_keyAvailable: if (sta->eapol_sm) sta->eapol_sm->keyAvailable = value ? TRUE : FALSE; break; case WPA_EAPOL_keyDone: if (sta->eapol_sm) sta->eapol_sm->keyDone = value ? TRUE : FALSE; break; case WPA_EAPOL_inc_EapolFramesTx: if (sta->eapol_sm) sta->eapol_sm->dot1xAuthEapolFramesTx++; break; }}static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr, wpa_eapol_variable var){ struct hostapd_data *hapd = ctx; struct sta_info *sta = ap_get_sta(hapd, addr); if (sta == NULL || sta->eapol_sm == NULL) return -1; switch (var) { case WPA_EAPOL_keyRun: return sta->eapol_sm->keyRun; case WPA_EAPOL_keyAvailable: return sta->eapol_sm->keyAvailable; default: return -1; }}static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, const u8 *prev_psk){ struct hostapd_data *hapd = ctx; return hostapd_get_psk(hapd->conf, addr, prev_psk);}static int hostapd_wpa_auth_get_pmk(void *ctx, const u8 *addr, u8 *pmk, size_t *len){ struct hostapd_data *hapd = ctx; u8 *key; size_t keylen; struct sta_info *sta; sta = ap_get_sta(hapd, addr); if (sta == NULL) return -1; key = ieee802_1x_get_key_crypt(sta->eapol_sm, &keylen); if (key == NULL) return -1; if (keylen > *len) keylen = WPA_PMK_LEN; memcpy(pmk, key, keylen); *len = keylen; return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -