X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=hostapd%2Fhostapd.c;h=225ad3abfd8ad42d58957bb6bb1c831227951719;hb=f07688e37da087d290991ca3942085628f9e954d;hp=d9f39e62fd7e1bde48db484edccc15c0a57ab1b9;hpb=edd360e170f15caa614bf4bb3847f5937b0517e5;p=wpasupplicant diff --git a/hostapd/hostapd.c b/hostapd/hostapd.c index d9f39e6..225ad3a 100644 --- a/hostapd/hostapd.c +++ b/hostapd/hostapd.c @@ -44,11 +44,15 @@ #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; @@ -250,7 +254,8 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *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) + 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); @@ -293,6 +298,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, 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; @@ -325,41 +331,72 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, } +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 static void handle_reload(int sig, void *eloop_ctx, void *signal_ctx) { struct hapd_interfaces *hapds = (struct hapd_interfaces *) eloop_ctx; - struct hostapd_config *newconf; size_t 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) { + if (hostapd_reload_config(hapds->iface[i]) < 0) { 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; - - if (hostapd_setup_wpa_psk(hapd->conf)) { - wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK " - "after reloading configuration"); - } } } @@ -399,7 +436,7 @@ static void hostapd_dump_state(struct hostapd_data *hapd) 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\n" + " 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, @@ -417,6 +454,8 @@ static void hostapd_dump_state(struct hostapd_data *hapd) (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); @@ -587,6 +626,8 @@ static void hostapd_cleanup(struct hostapd_data *hapd) l2_packet_deinit(hapd->l2); #endif /* CONFIG_IEEE80211R */ + hostapd_deinit_wps(hapd); + hostapd_wireless_event_deinit(hapd); #ifdef EAP_TLS_FUNCS @@ -677,6 +718,9 @@ static int hostapd_flush_old_stations(struct hostapd_data *hapd) { int ret = 0; + if (hostapd_drv_none(hapd)) + return 0; + wpa_printf(MSG_DEBUG, "Flushing old station entries"); if (hostapd_flush(hapd)) { printf("Could not connect to kernel driver.\n"); @@ -1006,6 +1050,9 @@ static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface) unsigned int i = iface->conf->num_bss, bits = 0, j; int res; + if (hostapd_drv_none(hapd)) + return 0; + /* Generate BSSID mask that is large enough to cover the BSSIDs. */ /* Determine the bits necessary to cover the number of BSSIDs. */ @@ -1164,8 +1211,14 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd, srv.ssl_ctx = hapd->ssl_ctx; srv.pac_opaque_encr_key = conf->pac_opaque_encr_key; srv.eap_fast_a_id = conf->eap_fast_a_id; + srv.eap_fast_a_id_len = conf->eap_fast_a_id_len; + srv.eap_fast_a_id_info = conf->eap_fast_a_id_info; + srv.eap_fast_prov = conf->eap_fast_prov; + srv.pac_key_lifetime = conf->pac_key_lifetime; + srv.pac_key_refresh_time = conf->pac_key_refresh_time; srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; srv.tnc = conf->tnc; + srv.wps = hapd->wps; srv.ipv6 = conf->radius_server_ipv6; srv.get_eap_user = hostapd_radius_get_eap_user; @@ -1253,9 +1306,12 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) conf->ssid.ssid[conf->ssid.ssid_len] = '\0'; } - printf("Using interface %s with hwaddr " MACSTR " and ssid '%s'\n", - hapd->conf->iface, MAC2STR(hapd->own_addr), - hapd->conf->ssid.ssid); + if (!hostapd_drv_none(hapd)) { + printf("Using interface %s with hwaddr " MACSTR + " and ssid '%s'\n", + hapd->conf->iface, MAC2STR(hapd->own_addr), + hapd->conf->ssid.ssid); + } if (hostapd_setup_wpa_psk(conf)) { printf("WPA-PSK setup failed.\n"); @@ -1295,6 +1351,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) printf("ACL initialization failed.\n"); return -1; } + if (hostapd_init_wps(hapd, conf)) + return -1; if (ieee802_1x_init(hapd)) { printf("IEEE 802.1X initialization failed.\n"); @@ -1320,18 +1378,21 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) return -1; } - if (vlan_init(hapd)) { + if (!hostapd_drv_none(hapd) && vlan_init(hapd)) { printf("VLAN initialization failed.\n"); return -1; } #ifdef CONFIG_IEEE80211R - hapd->l2 = l2_packet_init(hapd->conf->iface, NULL, ETH_P_RRB, - hostapd_rrb_receive, hapd, 0); - if (hapd->l2 == NULL && - (hapd->driver == NULL || hapd->driver->send_ether == NULL)) { - printf("Failed to open l2_packet interface\n"); - return -1; + if (!hostapd_drv_none(hapd)) { + hapd->l2 = l2_packet_init(hapd->conf->iface, NULL, ETH_P_RRB, + hostapd_rrb_receive, hapd, 0); + if (hapd->l2 == NULL && + (hapd->driver == NULL || + hapd->driver->send_ether == NULL)) { + printf("Failed to open l2_packet interface\n"); + return -1; + } } #endif /* CONFIG_IEEE80211R */ @@ -1345,140 +1406,25 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) } -/** - * setup_interface2 - Setup (initialize) an interface (part 2) - * @iface: Pointer to interface data. - * Returns: 0 on success; -1 on failure. - * - * Flushes old stations, sets the channel, DFS parameters, encryption, - * beacons, and WDS links based on the configuration. - */ -static int setup_interface2(struct hostapd_iface *iface) +static void hostapd_tx_queue_params(struct hostapd_iface *iface) { struct hostapd_data *hapd = iface->bss[0]; - int freq; - size_t j; - int ret = 0; - u8 *prev_addr; + int i; + struct hostapd_tx_queue_params *p; - hostapd_flush_old_stations(hapd); - hostapd_set_privacy(hapd, 0); + for (i = 0; i < NUM_TX_QUEUES; i++) { + p = &iface->conf->tx_queue[i]; - if (hapd->iconf->channel) { - freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel); - printf("Mode: %s Channel: %d Frequency: %d MHz\n", - hostapd_hw_mode_txt(hapd->iconf->hw_mode), - hapd->iconf->channel, freq); + if (!p->configured) + continue; - if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, freq)) { - printf("Could not set channel for kernel driver\n"); - return -1; + if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin, + p->cwmax, p->burst)) { + printf("Failed to set TX queue parameters for queue %d" + ".\n", i); + /* Continue anyway */ } } - - hostapd_broadcast_wep_clear(hapd); - if (hostapd_setup_encryption(hapd->conf->iface, hapd)) - return -1; - - hostapd_set_beacon_int(hapd, hapd->iconf->beacon_int); - ieee802_11_set_beacon(hapd); - - if (hapd->iconf->rts_threshold > -1 && - hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) { - printf("Could not set RTS threshold for kernel driver\n"); - return -1; - } - - if (hapd->iconf->fragm_threshold > -1 && - hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) { - printf("Could not set fragmentation threshold for kernel " - "driver\n"); - return -1; - } - - prev_addr = hapd->own_addr; - - for (j = 0; j < iface->num_bss; j++) { - hapd = iface->bss[j]; - if (j) - os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); - if (hostapd_setup_bss(hapd, j == 0)) - return -1; - if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) - prev_addr = hapd->own_addr; - } - - ap_list_init(iface); - - if (hostapd_driver_commit(hapd) < 0) { - wpa_printf(MSG_ERROR, "%s: Failed to commit driver " - "configuration", __func__); - return -1; - } - - return ret; -} - - -static void setup_interface_start(void *eloop_data, void *user_ctx); -static void setup_interface2_handler(void *eloop_data, void *user_ctx); - -/** - * setup_interface_finalize - Finish setup interface & call the callback - * @iface: Pointer to interface data. - * @status: Status of the setup interface (0 on success; -1 on failure). - * Returns: 0 on success; -1 on failure (e.g., was not in progress). - */ -static int setup_interface_finalize(struct hostapd_iface *iface, int status) -{ - hostapd_iface_cb cb; - - if (!iface->setup_cb) - return -1; - - eloop_cancel_timeout(setup_interface_start, iface, NULL); - eloop_cancel_timeout(setup_interface2_handler, iface, NULL); - hostapd_select_hw_mode_stop(iface); - - cb = iface->setup_cb; - - iface->setup_cb = NULL; - - cb(iface, status); - - return 0; -} - - -/** - * setup_interface2_wrapper - Wrapper for setup_interface2() - * @iface: Pointer to interface data. - * @status: Status of the hw mode select. - * - * Wrapper for setup_interface2() to calls finalize function upon completion. - */ -static void setup_interface2_wrapper(struct hostapd_iface *iface, int status) -{ - int ret = status; - if (ret) - printf("Could not select hw_mode and channel. (%d)\n", ret); - else - ret = setup_interface2(iface); - - setup_interface_finalize(iface, ret); -} - - -/** - * setup_interface2_handler - Used for immediate call of setup_interface2 - * @eloop_data: Stores the struct hostapd_iface * for the interface. - * @user_ctx: Unused. - */ -static void setup_interface2_handler(void *eloop_data, void *user_ctx) -{ - struct hostapd_iface *iface = eloop_data; - - setup_interface2_wrapper(iface, 0); } @@ -1521,23 +1467,17 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity, } -/** - * setup_interface1 - Setup (initialize) an interface (part 1) - * @iface: Pointer to interface data - * Returns: 0 on success, -1 on failure - * - * Initializes the driver interface, validates the configuration, - * and sets driver parameters based on the configuration. - * Schedules setup_interface2() to be called immediately or after - * hardware mode setup takes place. - */ -static int setup_interface1(struct hostapd_iface *iface) +static int setup_interface(struct hostapd_iface *iface) { struct hostapd_data *hapd = iface->bss[0]; struct hostapd_bss_config *conf = hapd->conf; size_t i; char country[4]; u8 *b = conf->bssid; + int freq; + size_t j; + int ret = 0; + u8 *prev_addr; /* * Initialize the driver interface and make sure that all BSSes get @@ -1576,12 +1516,11 @@ static int setup_interface1(struct hostapd_iface *iface) return -1; } - if (hapd->iconf->ieee80211d || hapd->iconf->ieee80211h) { - if (hostapd_set_ieee80211d(hapd, 1) < 0) { - printf("Failed to set ieee80211d (%d)\n", - hapd->iconf->ieee80211d); - return -1; - } + if (hapd->iconf->ieee80211d && + hostapd_set_ieee80211d(hapd, 1) < 0) { + printf("Failed to set ieee80211d (%d)\n", + hapd->iconf->ieee80211d); + return -1; } if (hapd->iconf->bridge_packets != INTERNAL_BRIDGE_DO_NOT_CONTROL && @@ -1598,77 +1537,106 @@ static int setup_interface1(struct hostapd_iface *iface) /* Not all drivers support this yet, so continue without hw * feature data. */ } else { - return hostapd_select_hw_mode_start(iface, - setup_interface2_wrapper); + int ret = hostapd_select_hw_mode(iface); + if (ret < 0) { + printf("Could not select hw_mode and channel. (%d)\n", + ret); + return -1; + } } - eloop_register_timeout(0, 0, setup_interface2_handler, iface, NULL); - return 0; -} + hostapd_flush_old_stations(hapd); + hostapd_set_privacy(hapd, 0); + if (hapd->iconf->channel) { + freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel); + printf("Mode: %s Channel: %d Frequency: %d MHz\n", + hostapd_hw_mode_txt(hapd->iconf->hw_mode), + hapd->iconf->channel, freq); -/** - * setup_interface_start - Handler to start setup interface - * @eloop_data: Stores the struct hostapd_iface * for the interface. - * @user_ctx: Unused. - * - * An eloop handler is used so that all errors can be processed by the - * callback without introducing stack recursion. - */ -static void setup_interface_start(void *eloop_data, void *user_ctx) -{ - struct hostapd_iface *iface = eloop_data; + if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, freq, + hapd->iconf->ieee80211n, + hapd->iconf->secondary_channel)) { + printf("Could not set channel for kernel driver\n"); + return -1; + } + } - int ret; + hostapd_broadcast_wep_clear(hapd); + if (hostapd_setup_encryption(hapd->conf->iface, hapd)) + return -1; + + hostapd_set_beacon_int(hapd, hapd->iconf->beacon_int); + ieee802_11_set_beacon(hapd); + + if (hapd->iconf->rts_threshold > -1 && + hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) { + printf("Could not set RTS threshold for kernel driver\n"); + return -1; + } + + if (hapd->iconf->fragm_threshold > -1 && + hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) { + printf("Could not set fragmentation threshold for kernel " + "driver\n"); + return -1; + } + + prev_addr = hapd->own_addr; - ret = setup_interface1(iface); - if (ret) - setup_interface_finalize(iface, ret); + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + if (j) + os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); + if (hostapd_setup_bss(hapd, j == 0)) + return -1; + if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) + prev_addr = hapd->own_addr; + } + + hostapd_tx_queue_params(iface); + + ap_list_init(iface); + + if (hostapd_driver_commit(hapd) < 0) { + wpa_printf(MSG_ERROR, "%s: Failed to commit driver " + "configuration", __func__); + return -1; + } + + return ret; } /** - * hostapd_setup_interface_start - Start the setup of an interface + * hostapd_setup_interface - Setup of an interface * @iface: Pointer to interface data. - * @cb: The function to callback when done. - * Returns: 0 if it starts successfully; cb will be called when done. - * -1 on failure; cb will not be called. + * Returns: 0 on success, -1 on failure * * Initializes the driver interface, validates the configuration, * and sets driver parameters based on the configuration. - * Flushes old stations, sets the channel, DFS parameters, encryption, + * Flushes old stations, sets the channel, encryption, * beacons, and WDS links based on the configuration. */ -int hostapd_setup_interface_start(struct hostapd_iface *iface, - hostapd_iface_cb cb) +static int hostapd_setup_interface(struct hostapd_iface *iface) { - if (iface->setup_cb) { - wpa_printf(MSG_DEBUG, - "%s: Interface setup already in progress.\n", + int ret; + + ret = setup_interface(iface); + if (ret) { + wpa_printf(MSG_DEBUG, "%s: Unable to setup interface.", iface->bss[0]->conf->iface); + eloop_terminate(); return -1; + } else if (!hostapd_drv_none(iface->bss[0])) { + wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", + iface->bss[0]->conf->iface); } - iface->setup_cb = cb; - - eloop_register_timeout(0, 0, setup_interface_start, iface, NULL); - return 0; } -/** - * hostapd_setup_interace_stop - Stops the setup of an interface - * @iface: Pointer to interface data - * Returns: 0 if successfully stopped; - * -1 on failure (i.e., was not in progress) - */ -int hostapd_setup_interface_stop(struct hostapd_iface *iface) -{ - return setup_interface_finalize(iface, -1); -} - - static void show_version(void) { fprintf(stderr, @@ -1777,9 +1745,6 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, } #endif /* EAP_SERVER */ - if (hapd->conf->assoc_ap) - hapd->assoc_ap_state = WAIT_BEACON; - hapd->driver = hapd->iconf->driver; return hapd; @@ -1856,32 +1821,6 @@ fail: } -/** - * register_drivers - Register driver interfaces - * - * This function is generated by Makefile (into driver_conf.c) to call all - * configured driver interfaces to register them to core hostapd. - */ -void register_drivers(void); - - -/** - * setup_interface_done - Callback when an interface is done being setup. - * @iface: Pointer to interface data. - * @status: Status of the interface setup (0 on success; -1 on failure). - */ -static void setup_interface_done(struct hostapd_iface *iface, int status) -{ - if (status) { - wpa_printf(MSG_DEBUG, "%s: Unable to setup interface.", - iface->bss[0]->conf->iface); - eloop_terminate(); - } else - wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", - iface->bss[0]->conf->iface); -} - - int main(int argc, char *argv[]) { struct hapd_interfaces interfaces; @@ -1969,8 +1908,7 @@ int main(int argc, char *argv[]) logger_stdout_level--; } - ret = hostapd_setup_interface_start(interfaces.iface[i], - setup_interface_done); + ret = hostapd_setup_interface(interfaces.iface[i]); if (ret) goto out; @@ -2015,7 +1953,6 @@ int main(int argc, char *argv[]) for (i = 0; i < interfaces.count; i++) { if (!interfaces.iface[i]) continue; - hostapd_setup_interface_stop(interfaces.iface[i]); hostapd_cleanup_iface_pre(interfaces.iface[i]); for (j = 0; j < interfaces.iface[i]->num_bss; j++) { struct hostapd_data *hapd =