int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, const char *txtaddr) { u8 addr[ETH_ALEN]; struct sta_info *sta; const char *pos; u16 reason = WLAN_REASON_PREV_AUTH_NOT_VALID; wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr); if (hwaddr_aton(txtaddr, addr)) return -1; pos = os_strstr(txtaddr, " test="); if (pos) { struct ieee80211_mgmt mgmt; int encrypt; if (hapd->driver->send_frame == NULL) return -1; pos += 6; encrypt = atoi(pos); os_memset(&mgmt, 0, sizeof(mgmt)); mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DISASSOC); os_memcpy(mgmt.da, addr, ETH_ALEN); os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); mgmt.u.disassoc.reason_code = host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt, IEEE80211_HDRLEN + sizeof(mgmt.u.deauth), encrypt) < 0) return -1; return 0; } #ifdef CONFIG_P2P_MANAGER pos = os_strstr(txtaddr, " p2p="); if (pos) { return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC, atoi(pos + 5), addr); } #endif /* CONFIG_P2P_MANAGER */ pos = os_strstr(txtaddr, " reason="); if (pos) reason = atoi(pos + 8); hostapd_drv_sta_disassoc(hapd, addr, reason); sta = ap_get_sta(hapd, addr); if (sta) ap_sta_disassociate(hapd, sta, reason); else if (addr[0] == 0xff) hostapd_free_stas(hapd); return 0; }
/** * hostapd_config_reload_iface_start - Start interface reload * @hapd_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. */ static int hostapd_config_reload_iface_start(struct hostapd_iface *hapd_iface, hostapd_iface_cb cb) { struct hostapd_config_change *change = hapd_iface->change; struct hostapd_config *newconf = change->newconf; struct hostapd_config *oldconf = change->oldconf; struct hostapd_data *hapd = hapd_iface->bss[0]; if (hapd_iface->reload_iface_cb) { wpa_printf(MSG_DEBUG, "%s: Interface reload already in progress.", hapd_iface->bss[0]->conf->iface); return -1; } hapd_iface->reload_iface_cb = cb; if (newconf->bridge_packets != oldconf->bridge_packets && hapd->iconf->bridge_packets != INTERNAL_BRIDGE_DO_NOT_CONTROL && hostapd_set_internal_bridge(hapd, hapd->iconf->bridge_packets)) printf("Failed to set bridge_packets for kernel driver\n"); if (newconf->channel != oldconf->channel || newconf->hw_mode != oldconf->hw_mode || rate_array_diff(newconf->supported_rates, oldconf->supported_rates) || rate_array_diff(newconf->basic_rates, oldconf->basic_rates)) { hostapd_free_stas(hapd); if (hostapd_get_hw_features(hapd_iface)) { printf("Could not read HW feature info from the kernel" " driver.\n"); hapd_iface->reload_iface_cb = NULL; return -1; } if (hostapd_select_hw_mode_start(hapd_iface, reload_hw_mode_done)) { printf("Failed to start select hw_mode.\n"); hapd_iface->reload_iface_cb = NULL; return -1; } return 0; } eloop_register_timeout(0, 0, reload_iface2_handler, hapd_iface, NULL); return 0; }
static int hostapd_flush_old_stations(struct hostapd_data *hapd) { int ret = 0; u8 addr[ETH_ALEN]; if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL) return 0; wpa_printf(MSG_DEBUG, "Flushing old station entries"); if (hostapd_flush(hapd)) { wpa_printf(MSG_WARNING, "Could not connect to kernel driver."); ret = -1; } wpa_printf(MSG_DEBUG, "Deauthenticate all stations"); os_memset(addr, 0xff, ETH_ALEN); hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); hostapd_free_stas(hapd); return ret; }
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason) { int ret = 0; u8 addr[ETH_ALEN]; if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL) return 0; wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Flushing old station entries"); if (hostapd_flush(hapd)) { wpa_msg(hapd->msg_ctx, MSG_WARNING, "Could not connect to " "kernel driver"); ret = -1; } wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Deauthenticate all stations"); os_memset(addr, 0xff, ETH_ALEN); hostapd_drv_sta_deauth(hapd, addr, reason); hostapd_free_stas(hapd); return ret; }
int main(int argc, char *argv[]) { struct hapd_interfaces interfaces; int ret = 1, i, j; int c, debug = 0, daemonize = 0; for (;;) { c = getopt(argc, argv, "Bdh"); if (c < 0) break; switch (c) { case 'h': usage(); break; case 'd': debug++; break; case 'B': daemonize++; break; default: usage(); break; } } if (optind == argc) usage(); interfaces.count = argc - optind; interfaces.hapd = malloc(interfaces.count * sizeof(hostapd *)); if (interfaces.hapd == NULL) { printf("malloc failed\n"); exit(1); } eloop_init(&interfaces); eloop_register_signal(SIGHUP, handle_reload, NULL); eloop_register_signal(SIGINT, handle_term, NULL); eloop_register_signal(SIGTERM, handle_term, NULL); eloop_register_signal(SIGUSR1, handle_dump_state, NULL); for (i = 0; i < interfaces.count; i++) { printf("Configuration file: %s\n", argv[optind + i]); interfaces.hapd[i] = hostapd_init(argv[optind + i]); if (!interfaces.hapd[i]) goto out; for (j = 0; j < debug; j++) { if (interfaces.hapd[i]->conf->logger_stdout_level > 0) interfaces.hapd[i]->conf-> logger_stdout_level--; interfaces.hapd[i]->conf->debug++; } hostapd_set_broadcast_wep(interfaces.hapd[i]); if (hostapd_setup_interface(interfaces.hapd[i])) goto out; } if (daemonize && daemon(0, 0)) { perror("daemon"); goto out; } openlog("hostapd", 0, LOG_DAEMON); eloop_run(); for (i = 0; i < interfaces.count; i++) { hostapd_free_stas(interfaces.hapd[i]); hostapd_flush_old_stations(interfaces.hapd[i]); } ret = 0; out: for (i = 0; i < interfaces.count; i++) { if (!interfaces.hapd[i]) continue; hostapd_cleanup(interfaces.hapd[i]); free(interfaces.hapd[i]); } free(interfaces.hapd); eloop_destroy(); closelog(); return ret; }
void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) { struct hostapd_data *hapd = ctx; #ifndef CONFIG_NO_STDOUT_DEBUG int level = MSG_DEBUG; if (event == EVENT_RX_MGMT && data->rx_mgmt.frame && data->rx_mgmt.frame_len >= 24) { const struct ieee80211_hdr *hdr; u16 fc; hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame; fc = le_to_host16(hdr->frame_control); if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) level = MSG_EXCESSIVE; if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) level = MSG_EXCESSIVE; } wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received", event_to_string(event), event); #endif /* CONFIG_NO_STDOUT_DEBUG */ switch (event) { case EVENT_MICHAEL_MIC_FAILURE: michael_mic_failure(hapd, data->michael_mic_failure.src, 1); break; case EVENT_SCAN_RESULTS: if (hapd->iface->scan_cb) hapd->iface->scan_cb(hapd->iface); break; case EVENT_WPS_BUTTON_PUSHED: hostapd_wps_button_pushed(hapd, NULL); break; #ifdef NEED_AP_MLME case EVENT_TX_STATUS: switch (data->tx_status.type) { case WLAN_FC_TYPE_MGMT: hostapd_mgmt_tx_cb(hapd, data->tx_status.data, data->tx_status.data_len, data->tx_status.stype, data->tx_status.ack); break; case WLAN_FC_TYPE_DATA: hostapd_tx_status(hapd, data->tx_status.dst, data->tx_status.data, data->tx_status.data_len, data->tx_status.ack); break; } break; case EVENT_EAPOL_TX_STATUS: hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst, data->eapol_tx_status.data, data->eapol_tx_status.data_len, data->eapol_tx_status.ack); break; case EVENT_DRIVER_CLIENT_POLL_OK: hostapd_client_poll_ok(hapd, data->client_poll.addr); break; case EVENT_RX_FROM_UNKNOWN: hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid, data->rx_from_unknown.addr, data->rx_from_unknown.wds); break; #endif /* NEED_AP_MLME */ case EVENT_RX_MGMT: if (!data->rx_mgmt.frame) break; #ifdef NEED_AP_MLME if (hostapd_mgmt_rx(hapd, &data->rx_mgmt) > 0) break; #endif /* NEED_AP_MLME */ hostapd_action_rx(hapd, &data->rx_mgmt); break; case EVENT_RX_PROBE_REQ: if (data->rx_probe_req.sa == NULL || data->rx_probe_req.ie == NULL) break; hostapd_probe_req_rx(hapd, data->rx_probe_req.sa, data->rx_probe_req.da, data->rx_probe_req.bssid, data->rx_probe_req.ie, data->rx_probe_req.ie_len, data->rx_probe_req.ssi_signal); break; case EVENT_NEW_STA: hostapd_event_new_sta(hapd, data->new_sta.addr); break; case EVENT_EAPOL_RX: hostapd_event_eapol_rx(hapd, data->eapol_rx.src, data->eapol_rx.data, data->eapol_rx.data_len); break; case EVENT_ASSOC: if (!data) return; hostapd_notif_assoc(hapd, data->assoc_info.addr, data->assoc_info.req_ies, data->assoc_info.req_ies_len, data->assoc_info.reassoc); break; case EVENT_DISASSOC: if (data) hostapd_notif_disassoc(hapd, data->disassoc_info.addr); break; case EVENT_DEAUTH: if (data) hostapd_notif_disassoc(hapd, data->deauth_info.addr); break; case EVENT_STATION_LOW_ACK: if (!data) break; hostapd_event_sta_low_ack(hapd, data->low_ack.addr); break; case EVENT_AUTH: hostapd_notif_auth(hapd, &data->auth); break; case EVENT_CH_SWITCH: if (!data) break; hostapd_event_ch_switch(hapd, data->ch_switch.freq, data->ch_switch.ht_enabled, data->ch_switch.ch_offset, data->ch_switch.ch_width, data->ch_switch.cf1, data->ch_switch.cf2); break; case EVENT_CONNECT_FAILED_REASON: if (!data) break; hostapd_event_connect_failed_reason( hapd, data->connect_failed_reason.addr, data->connect_failed_reason.code); break; case EVENT_SURVEY: hostapd_event_get_survey(hapd->iface, &data->survey_results); break; #ifdef NEED_AP_MLME case EVENT_INTERFACE_UNAVAILABLE: hostapd_event_iface_unavailable(hapd); break; case EVENT_DFS_RADAR_DETECTED: if (!data) break; hostapd_event_dfs_radar_detected(hapd, &data->dfs_event); break; case EVENT_DFS_CAC_FINISHED: if (!data) break; hostapd_event_dfs_cac_finished(hapd, &data->dfs_event); break; case EVENT_DFS_CAC_ABORTED: if (!data) break; hostapd_event_dfs_cac_aborted(hapd, &data->dfs_event); break; case EVENT_DFS_NOP_FINISHED: if (!data) break; hostapd_event_dfs_nop_finished(hapd, &data->dfs_event); break; case EVENT_CHANNEL_LIST_CHANGED: /* channel list changed (regulatory?), update channel list */ /* TODO: check this. hostapd_get_hw_features() initializes * too much stuff. */ /* hostapd_get_hw_features(hapd->iface); */ hostapd_channel_list_updated( hapd->iface, data->channel_list_changed.initiator); break; case EVENT_DFS_CAC_STARTED: if (!data) break; hostapd_event_dfs_cac_started(hapd, &data->dfs_event); break; #endif /* NEED_AP_MLME */ case EVENT_INTERFACE_ENABLED: wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED); if (hapd->disabled && hapd->started) { hapd->disabled = 0; /* * Try to re-enable interface if the driver stopped it * when the interface got disabled. */ wpa_auth_reconfig_group_keys(hapd->wpa_auth); hapd->reenable_beacon = 1; ieee802_11_set_beacon(hapd); } break; case EVENT_INTERFACE_DISABLED: hostapd_free_stas(hapd); wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED); hapd->disabled = 1; break; #ifdef CONFIG_ACS case EVENT_ACS_CHANNEL_SELECTED: hostapd_acs_channel_selected(hapd, &data->acs_selected_channels); break; #endif /* CONFIG_ACS */ default: wpa_printf(MSG_DEBUG, "Unknown event %d", event); break; } }
/** * config_reload2 - Part 2 of configuration reloading * @hapd_iface: */ static void config_reload2(struct hostapd_iface *hapd_iface, int status) { struct hostapd_config_change *change = hapd_iface->change; struct hostapd_data *hapd = change->hapd; struct hostapd_config *newconf = change->newconf; struct hostapd_config *oldconf = change->oldconf; int beacon_changed = change->beacon_changed; struct hostapd_data **new_hapd = change->new_hapd; struct hostapd_data **old_hapd = change->old_hapd; int num_old_hapd = change->num_old_hapd; size_t i, j, max_bss, same_bssid; struct hostapd_bss_config *newbss, *oldbss; u8 *prev_addr; hostapd_iface_cb cb; free(change); hapd_iface->change = NULL; if (status) { printf("Failed to setup new interface config\n"); cb = hapd_iface->config_reload_cb; hapd_iface->config_reload_cb = NULL; /* Invalid configuration - cleanup and terminate hostapd */ hapd_iface->bss = old_hapd; hapd_iface->num_bss = num_old_hapd; hapd_iface->conf = hapd->iconf = oldconf; hapd->conf = &oldconf->bss[0]; hostapd_config_free(newconf); free(new_hapd); cb(hapd_iface, -2); return; } /* * If any BSSes have been removed, added, or had their BSSIDs changed, * completely remove and reinitialize such BSSes and all the BSSes * following them since their BSSID might have changed. */ max_bss = oldconf->num_bss; if (max_bss > newconf->num_bss) max_bss = newconf->num_bss; for (i = 0; i < max_bss; i++) { if (strcmp(oldconf->bss[i].iface, newconf->bss[i].iface) != 0 || hostapd_mac_comp(oldconf->bss[i].bssid, newconf->bss[i].bssid) != 0) break; } same_bssid = i; for (i = 0; i < oldconf->num_bss; i++) { oldbss = &oldconf->bss[i]; newbss = NULL; for (j = 0; j < newconf->num_bss; j++) { if (strcmp(oldbss->iface, newconf->bss[j].iface) == 0) { newbss = &newconf->bss[j]; break; } } if (newbss && i < same_bssid) { hapd = hapd_iface->bss[j] = old_hapd[i]; hapd->iconf = newconf; hapd->conf = newbss; hostapd_reconfig_bss(hapd, newbss, oldbss, oldconf, beacon_changed); } else { hapd = old_hapd[i]; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Removing BSS (ifname %s)\n", hapd->conf->iface); hostapd_free_stas(hapd); /* Send broadcast deauthentication for this BSS, but do * not clear all STAs from the driver since other BSSes * may have STA entries. The driver will remove all STA * entries for this BSS anyway when the interface is * being removed. */ #if 0 hostapd_deauth_all_stas(hapd); hostapd_cleanup(hapd); #endif free(hapd); } } prev_addr = hapd_iface->bss[0]->own_addr; hapd = hapd_iface->bss[0]; for (j = 0; j < newconf->num_bss; j++) { if (hapd_iface->bss[j] != NULL) { prev_addr = hapd_iface->bss[j]->own_addr; continue; } newbss = &newconf->bss[j]; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Reconfiguration: adding " "new BSS (ifname=%s)\n", newbss->iface); #if 0 hapd = hapd_iface->bss[j] = hostapd_alloc_bss_data(hapd_iface, newconf, newbss); #endif if (hapd == NULL) { printf("Failed to initialize new BSS\n"); /* FIX: This one is somewhat hard to recover * from.. Would need to remove this BSS from * conf and BSS list. */ exit(1); } hapd->driver = hapd_iface->bss[0]->driver; hapd->iface = hapd_iface; hapd->iconf = newconf; hapd->conf = newbss; memcpy(hapd->own_addr, prev_addr, ETH_ALEN); if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) prev_addr = hapd->own_addr; #if 0 if (hostapd_setup_bss(hapd, j == 0)) { printf("Failed to setup new BSS\n"); /* FIX */ exit(1); } #endif } free(old_hapd); hostapd_config_free(oldconf); cb = hapd_iface->config_reload_cb; hapd_iface->config_reload_cb = NULL; cb(hapd_iface, 0); }
int main(int argc, char *argv[]) { struct hapd_interfaces interfaces; int ret = 1, i, j; int c, debug = 0, daemonize = 0; #ifdef JUMPSTART char *js_passwd = NULL; #endif for (;;) { c = getopt(argc, argv, "BdhKtvj:"); if (c < 0) break; switch (c) { case 'h': usage(); break; case 'd': debug++; break; case 'B': daemonize++; break; case 'K': wpa_debug_show_keys++; break; case 't': wpa_debug_timestamp++; break; case 'v': show_version(); exit(1); break; #ifdef JUMPSTART case 'j': js_passwd = optarg; break; #endif default: usage(); break; } } if (optind == argc) usage(); register_drivers(); /* NB: generated by Makefile */ interfaces.count = argc - optind; interfaces.hapd = malloc(interfaces.count * sizeof(hostapd *)); if (interfaces.hapd == NULL) { printf("malloc failed\n"); exit(1); } eloop_init(&interfaces); eloop_register_signal(SIGHUP, handle_reload, NULL); eloop_register_signal(SIGINT, handle_term, NULL); eloop_register_signal(SIGTERM, handle_term, NULL); eloop_register_signal(SIGUSR1, handle_dump_state, NULL); for (i = 0; i < interfaces.count; i++) { printf("Configuration file: %s\n", argv[optind + i]); #ifdef JUMPSTART interfaces.hapd[i] = hostapd_init(argv[optind + i], js_passwd); #else interfaces.hapd[i] = hostapd_init(argv[optind + i]); #endif if (!interfaces.hapd[i]) goto out; for (j = 0; j < debug; j++) { if (interfaces.hapd[i]->conf->logger_stdout_level > 0) interfaces.hapd[i]->conf-> logger_stdout_level--; interfaces.hapd[i]->conf->debug++; } if (hostapd_setup_interface(interfaces.hapd[i])) goto out; wpa_debug_level -= interfaces.hapd[0]->conf->debug; } if (daemonize && daemon(0, 0)) { perror("daemon"); goto out; } openlog("hostapd", 0, LOG_DAEMON); eloop_run(); for (i = 0; i < interfaces.count; i++) { hostapd_free_stas(interfaces.hapd[i]); hostapd_flush_old_stations(interfaces.hapd[i]); } ret = 0; out: for (i = 0; i < interfaces.count; i++) { if (!interfaces.hapd[i]) continue; hostapd_cleanup(interfaces.hapd[i]); free(interfaces.hapd[i]); } free(interfaces.hapd); eloop_destroy(); closelog(); driver_unregister_all(); return ret; }