📄 hostapd.c
字号:
/* * hostapd / Initialization and configuration * Copyright (c) 2002-2009, Jouni Malinen <j@w1.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 "ap_list.h"#include "sta_info.h"#include "driver.h"#include "radius/radius_client.h"#include "radius/radius_server.h"#include "wpa.h"#include "preauth.h"#include "wme.h"#include "vlan_init.h"#include "ctrl_iface.h"#include "tls.h"#include "eap_server/eap_sim_db.h"#include "eap_server/eap.h"#include "eap_server/tncs.h"#include "version.h"#include "l2_packet/l2_packet.h"#include "wps_hostapd.h"static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity, size_t identity_len, int phase2, struct eap_user *user);static int hostapd_flush_old_stations(struct hostapd_data *hapd);static int hostapd_setup_wpa(struct hostapd_data *hapd);static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);struct hapd_interfaces { size_t 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;static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, int level, const char *txt, size_t len){ struct hostapd_data *hapd = ctx; char *format, *module_str; int maxlen; int conf_syslog_level, conf_stdout_level; unsigned int conf_syslog, conf_stdout; maxlen = len + 100; format = os_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; case HOSTAPD_MODULE_MLME: module_str = "MLME"; break; default: module_str = NULL; break; } if (hapd && hapd->conf && addr) os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s", hapd->conf->iface, MAC2STR(addr), module_str ? " " : "", module_str, txt); else if (hapd && hapd->conf) os_snprintf(format, maxlen, "%s:%s%s %s", hapd->conf->iface, module_str ? " " : "", module_str, txt); else if (addr) os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", MAC2STR(addr), module_str ? " " : "", module_str, txt); else os_snprintf(format, maxlen, "%s%s%s", module_str, module_str ? ": " : "", txt); if ((conf_stdout & module) && level >= conf_stdout_level) { wpa_debug_print_timestamp(); printf("%s\n", format); }#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; } syslog(priority, "%s", format); }#endif /* CONFIG_NATIVE_WINDOWS */ os_free(format);}static void hostapd_deauth_all_stas(struct hostapd_data *hapd){ u8 addr[ETH_ALEN]; /* 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 the hostap * driver. */ if (hapd->driver && os_strcmp(hapd->driver->name, "hostap") != 0) { os_memset(addr, 0xff, ETH_ALEN); hostapd_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); }}/** * hostapd_prune_associations - Remove extraneous associations * @hapd: Pointer to BSS data for the most recent association * @sta: Pointer to the associated STA data * * This function looks through all radios and BSS's for previous * (stale) associations of STA. If any are found they are removed. */static void hostapd_prune_associations(struct hostapd_data *hapd, struct sta_info *sta){ struct sta_info *osta; struct hostapd_data *ohapd; size_t i, j; struct hapd_interfaces *interfaces = eloop_get_user_data(); for (i = 0; i < interfaces->count; i++) { for (j = 0; j < interfaces->iface[i]->num_bss; j++) { ohapd = interfaces->iface[i]->bss[j]; if (ohapd == hapd) continue; osta = ap_get_sta(ohapd, sta->addr); if (!osta) continue; ap_sta_disassociate(ohapd, osta, WLAN_REASON_UNSPECIFIED); } }}/** * hostapd_new_assoc_sta - Notify that a new station associated with the AP * @hapd: Pointer to BSS data * @sta: Pointer to the associated STA data * @reassoc: 1 to indicate this was a re-association; 0 = first association * * This function will be called whenever a station associates with the AP. It * can be called for ieee802_11.c for drivers that export MLME to hostapd and * from driver_*.c for drivers that take care of management frames (IEEE 802.11 * authentication and association) internally. */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; } hostapd_prune_associations(hapd, sta); /* 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); hostapd_wme_sta_config(hapd, sta); /* Start IEEE 802.1X authentication process for new stations */ ieee802_1x_new_station(hapd, sta); if (reassoc) { if (sta->auth_alg != WLAN_AUTH_FT && !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) 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_auth_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 *//** * handle_term - SIGINT and SIGTERM handler to terminate hostapd process */static void handle_term(int sig, void *eloop_ctx, void *signal_ctx){ wpa_printf(MSG_DEBUG, "Signal %d received - terminating", 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->wpa_ptk_rekey = conf->wpa_ptk_rekey; wconf->rsn_pairwise = conf->rsn_pairwise; wconf->rsn_preauth = conf->rsn_preauth; wconf->eapol_version = conf->eapol_version; wconf->peerkey = conf->peerkey; wconf->wme_enabled = conf->wme_enabled; wconf->okc = conf->okc;#ifdef CONFIG_IEEE80211W wconf->ieee80211w = conf->ieee80211w;#endif /* CONFIG_IEEE80211W */#ifdef CONFIG_IEEE80211R wconf->ssid_len = conf->ssid.ssid_len; if (wconf->ssid_len > SSID_LEN) wconf->ssid_len = SSID_LEN; os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len); os_memcpy(wconf->mobility_domain, conf->mobility_domain, MOBILITY_DOMAIN_ID_LEN); if (conf->nas_identifier && os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) { wconf->r0_key_holder_len = os_strlen(conf->nas_identifier); os_memcpy(wconf->r0_key_holder, conf->nas_identifier, wconf->r0_key_holder_len); } os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN); wconf->r0_key_lifetime = conf->r0_key_lifetime; wconf->reassociation_deadline = conf->reassociation_deadline; wconf->r0kh_list = conf->r0kh_list; wconf->r1kh_list = conf->r1kh_list; wconf->pmk_r1_push = conf->pmk_r1_push;#endif /* CONFIG_IEEE80211R */}int hostapd_reload_config(struct hostapd_iface *iface){ struct hostapd_data *hapd = iface->bss[0]; struct hostapd_config *newconf, *oldconf; struct wpa_auth_config wpa_auth_conf; newconf = hostapd_config_read(iface->config_fname); if (newconf == NULL) return -1; /* * Deauthenticate all stations since the new configuration may not * allow them to use the BSS anymore. */ hostapd_flush_old_stations(hapd); /* TODO: update dynamic data based on changed configuration * items (e.g., open/close sockets, etc.) */ radius_client_flush(hapd->radius, 0); oldconf = hapd->iconf; hapd->iconf = newconf; hapd->conf = &newconf->bss[0]; iface->conf = newconf; if (hostapd_setup_wpa_psk(hapd->conf)) { wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK " "after reloading configuration"); } if (hapd->conf->wpa && hapd->wpa_auth == NULL) hostapd_setup_wpa(hapd); else if (hapd->conf->wpa) { hostapd_wpa_auth_conf(&newconf->bss[0], &wpa_auth_conf); wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf); } else if (hapd->wpa_auth) { wpa_deinit(hapd->wpa_auth); hapd->wpa_auth = NULL; hostapd_set_privacy(hapd, 0); hostapd_setup_encryption(hapd->conf->iface, hapd); } ieee802_11_set_beacon(hapd); hostapd_config_free(oldconf); wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface); return 0;}#ifndef CONFIG_NATIVE_WINDOWS/** * handle_reload - SIGHUP handler to reload configuration */static void handle_reload(int sig, void *eloop_ctx, void *signal_ctx){ struct hapd_interfaces *hapds = (struct hapd_interfaces *) eloop_ctx; size_t i; wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration", sig); for (i = 0; i < hapds->count; i++) { if (hostapd_reload_config(hapds->iface[i]) < 0) { wpa_printf(MSG_WARNING, "Failed to read new " "configuration file - continuing with " "old."); continue; } }}#ifdef HOSTAPD_DUMP_STATE/** * hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file */static 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) { wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump " "request"); return; } wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'", hapd->conf->dump_log_name); f = fopen(hapd->conf->dump_log_name, "w"); if (f == NULL) { wpa_printf(MSG_WARNING, "Could not open dump file '%s' for " "writing.", hapd->conf->dump_log_name); return; } time(&now); fprintf(f, "hostapd state dump - %s", ctime(&now)); fprintf(f, "num_sta=%d num_sta_non_erp=%d " "num_sta_no_short_slot_time=%d\n" "num_sta_no_short_preamble=%d\n", hapd->num_sta, hapd->iface->num_sta_non_erp, hapd->iface->num_sta_no_short_slot_time, hapd->iface->num_sta_no_short_preamble); 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%s%s%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->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" : ""), (sta->flags & WLAN_STA_SHORT_PREAMBLE ? "[SHORT_PREAMBLE]" : ""), (sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""), (sta->flags & WLAN_STA_WME ? "[WME]" : ""), (sta->flags & WLAN_STA_MFP ? "[MFP]" : ""), (sta->flags & WLAN_STA_WPS ? "[WPS]" : ""), (sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""), (sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""), 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 = os_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); os_free(buf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -