static int wps_process_cred_e(struct wps_data *wps, const u8 *cred, size_t cred_len, int wps2) { struct wps_parse_attr attr; struct wpabuf msg; wpa_printf(MSG_DEBUG, "WPS: Received Credential"); os_memset(&wps->cred, 0, sizeof(wps->cred)); wpabuf_set(&msg, cred, cred_len); if (wps_parse_msg(&msg, &attr) < 0 || wps_process_cred(&attr, &wps->cred)) return -1; if (os_memcmp(wps->cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: MAC Address in the Credential (" MACSTR ") does not match with own address (" MACSTR ")", MAC2STR(wps->cred.mac_addr), MAC2STR(wps->wps->dev.mac_addr)); /* * In theory, this could be consider fatal error, but there are * number of deployed implementations using other address here * due to unclarity in the specification. For interoperability * reasons, allow this to be processed since we do not really * use the MAC Address information for anything. */ #ifdef CONFIG_WPS_STRICT if (wps2) { wpa_printf(MSG_INFO, "WPS: Do not accept incorrect " "MAC Address in AP Settings"); return -1; } #endif /* CONFIG_WPS_STRICT */ } #ifdef CONFIG_WPS2 if (!(wps->cred.encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) { if (wps->cred.encr_type & WPS_ENCR_WEP) { wpa_printf(MSG_INFO, "WPS: Reject Credential " "due to WEP configuration"); wps->error_indication = WPS_EI_SECURITY_WEP_PROHIBITED; return -2; } wpa_printf(MSG_INFO, "WPS: Reject Credential due to " "invalid encr_type 0x%x", wps->cred.encr_type); return -1; } #endif /* CONFIG_WPS2 */ if (wps->wps->cred_cb) { wps->cred.cred_attr = cred - 4; wps->cred.cred_attr_len = cred_len + 4; wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred); wps->cred.cred_attr = NULL; wps->cred.cred_attr_len = 0; } return 0; }
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) { int set_beacon = 0; accounting_sta_stop(hapd, sta); /* just in case */ ap_sta_set_authorized(hapd, sta, 0); if (sta->flags & WLAN_STA_WDS) hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0); if (sta->ipaddr) hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr); ap_sta_ip6addr_del(hapd, sta); if (!hapd->iface->driver_ap_teardown && !(sta->flags & WLAN_STA_PREAUTH)) hostapd_drv_sta_remove(hapd, sta->addr); ap_sta_hash_del(hapd, sta); ap_sta_list_del(hapd, sta); if (sta->aid > 0) hapd->sta_aid[(sta->aid - 1) / 32] &= ~BIT((sta->aid - 1) % 32); hapd->num_sta--; if (sta->nonerp_set) { sta->nonerp_set = 0; hapd->iface->num_sta_non_erp--; if (hapd->iface->num_sta_non_erp == 0) set_beacon++; } if (sta->no_short_slot_time_set) { sta->no_short_slot_time_set = 0; hapd->iface->num_sta_no_short_slot_time--; if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->iface->num_sta_no_short_slot_time == 0) set_beacon++; } if (sta->no_short_preamble_set) { sta->no_short_preamble_set = 0; hapd->iface->num_sta_no_short_preamble--; if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->iface->num_sta_no_short_preamble == 0) set_beacon++; } if (sta->no_ht_gf_set) { sta->no_ht_gf_set = 0; hapd->iface->num_sta_ht_no_gf--; } if (sta->no_ht_set) { sta->no_ht_set = 0; hapd->iface->num_sta_no_ht--; } if (sta->ht_20mhz_set) { sta->ht_20mhz_set = 0; hapd->iface->num_sta_ht_20mhz--; } #ifdef CONFIG_IEEE80211N ht40_intolerant_remove(hapd->iface, sta); #endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_P2P if (sta->no_p2p_set) { sta->no_p2p_set = 0; hapd->num_sta_no_p2p--; if (hapd->num_sta_no_p2p == 0) hostapd_p2p_non_p2p_sta_disconnected(hapd); } #endif /* CONFIG_P2P */ #if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N) if (hostapd_ht_operation_update(hapd->iface) > 0) set_beacon++; #endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ #ifdef CONFIG_MESH if (hapd->mesh_sta_free_cb) hapd->mesh_sta_free_cb(sta); #endif /* CONFIG_MESH */ if (set_beacon) ieee802_11_set_beacons(hapd->iface); wpa_printf(MSG_DEBUG, "%s: cancel ap_handle_timer for " MACSTR, __func__, MAC2STR(sta->addr)); eloop_cancel_timeout(ap_handle_timer, hapd, sta); eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta); eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); sae_clear_retransmit_timer(hapd, sta); ieee802_1x_free_station(sta); wpa_auth_sta_deinit(sta->wpa_sm); rsn_preauth_free_station(hapd, sta); #ifndef CONFIG_NO_RADIUS if (hapd->radius) radius_client_flush_auth(hapd->radius, sta->addr); #endif /* CONFIG_NO_RADIUS */ os_free(sta->challenge); #ifdef CONFIG_IEEE80211W os_free(sta->sa_query_trans_id); eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P p2p_group_notif_disassoc(hapd->p2p_group, sta->addr); #endif /* CONFIG_P2P */ #ifdef CONFIG_INTERWORKING if (sta->gas_dialog) { int i; for (i = 0; i < GAS_DIALOG_MAX; i++) gas_serv_dialog_clear(&sta->gas_dialog[i]); os_free(sta->gas_dialog); } #endif /* CONFIG_INTERWORKING */ wpabuf_free(sta->wps_ie); wpabuf_free(sta->p2p_ie); wpabuf_free(sta->hs20_ie); os_free(sta->ht_capabilities); os_free(sta->vht_capabilities); hostapd_free_psk_list(sta->psk); os_free(sta->identity); os_free(sta->radius_cui); os_free(sta->remediation_url); wpabuf_free(sta->hs20_deauth_req); os_free(sta->hs20_session_info_url); #ifdef CONFIG_SAE sae_clear_data(sta->sae); os_free(sta->sae); #endif /* CONFIG_SAE */ os_free(sta); }
void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, int authorized) { const u8 *dev_addr = NULL; char buf[100]; #ifdef CONFIG_P2P u8 addr[ETH_ALEN]; u8 ip_addr_buf[4]; #endif /* CONFIG_P2P */ if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED)) return; if (authorized) sta->flags |= WLAN_STA_AUTHORIZED; else sta->flags &= ~WLAN_STA_AUTHORIZED; #ifdef CONFIG_P2P if (hapd->p2p_group == NULL) { if (sta->p2p_ie != NULL && p2p_parse_dev_addr_in_p2p_ie(sta->p2p_ie, addr) == 0) dev_addr = addr; } else dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr); if (dev_addr) os_snprintf(buf, sizeof(buf), MACSTR " p2p_dev_addr=" MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr)); else #endif /* CONFIG_P2P */ os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr)); if (hapd->sta_authorized_cb) hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx, sta->addr, authorized, dev_addr); if (authorized) { char ip_addr[100]; ip_addr[0] = '\0'; #ifdef CONFIG_P2P if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) { os_snprintf(ip_addr, sizeof(ip_addr), " ip_addr=%u.%u.%u.%u", ip_addr_buf[0], ip_addr_buf[1], ip_addr_buf[2], ip_addr_buf[3]); } #endif /* CONFIG_P2P */ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s", buf, ip_addr); if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx) wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, AP_STA_CONNECTED "%s%s", buf, ip_addr); } else { wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx) wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); } }
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 ? module_str : "", txt); else if (hapd && hapd->conf) os_snprintf(format, maxlen, "%s:%s%s %s", hapd->conf->iface, module_str ? " " : "", module_str ? module_str : "", txt); else if (addr) os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", MAC2STR(addr), module_str ? " " : "", module_str ? module_str : "", txt); else os_snprintf(format, maxlen, "%s%s%s", module_str ? module_str : "", module_str ? ": " : "", txt); if ((conf_stdout & module) && level >= conf_stdout_level) { wpa_debug_print_timestamp(); wpa_printf(MSG_INFO, "%s", 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); }
void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { struct wpa_ssid *ssid = wpa_s->current_ssid; if (ssid == NULL) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event " "when network is not selected"); return; } if (wpa_s->wpa_state != WPA_AUTHENTICATING) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event " "when not in authenticating state"); return; } if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with " "unexpected peer " MACSTR, MAC2STR(data->auth.peer)); return; } wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR " auth_type=%d auth_transaction=%d status_code=%d", MAC2STR(data->auth.peer), data->auth.auth_type, data->auth.auth_transaction, data->auth.status_code); wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs", data->auth.ies, data->auth.ies_len); eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); #ifdef CONFIG_SAE if (data->auth.auth_type == WLAN_AUTH_SAE) { int res; res = sme_sae_auth(wpa_s, data->auth.auth_transaction, data->auth.status_code, data->auth.ies, data->auth.ies_len); if (res < 0) { wpas_connection_failed(wpa_s, wpa_s->pending_bssid, 1); wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); } if (res != 1) return; wpa_printf(MSG_DEBUG, "SME: SAE completed - setting PMK for " "4-way handshake"); wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN); } #endif /* CONFIG_SAE */ if (data->auth.status_code != WLAN_STATUS_SUCCESS) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication failed (status " "code %d)", data->auth.status_code); if (data->auth.status_code != WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG || wpa_s->sme.auth_alg == data->auth.auth_type || wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) { wpas_connection_failed(wpa_s, wpa_s->pending_bssid, 1); wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); return; } wpas_connect_work_done(wpa_s); switch (data->auth.auth_type) { case WLAN_AUTH_OPEN: wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED; wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth"); wpa_supplicant_associate(wpa_s, wpa_s->current_bss, wpa_s->current_ssid); return; case WLAN_AUTH_SHARED_KEY: wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP; wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth"); wpa_supplicant_associate(wpa_s, wpa_s->current_bss, wpa_s->current_ssid); return; default: return; } } #ifdef CONFIG_IEEE80211R if (data->auth.auth_type == WLAN_AUTH_FT) { union wpa_event_data edata; os_memset(&edata, 0, sizeof(edata)); edata.ft_ies.ies = data->auth.ies; edata.ft_ies.ies_len = data->auth.ies_len; os_memcpy(edata.ft_ies.target_ap, data->auth.peer, ETH_ALEN); wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &edata); } #endif /* CONFIG_IEEE80211R */ sme_associate(wpa_s, ssid->mode, data->auth.peer, data->auth.auth_type); }
static void wpa_config_write_global(FILE *f, struct wpa_config *config) { #ifdef CONFIG_CTRL_IFACE if (config->ctrl_interface) fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface); if (config->ctrl_interface_group) fprintf(f, "ctrl_interface_group=%s\n", config->ctrl_interface_group); #endif /* CONFIG_CTRL_IFACE */ if (config->eapol_version != DEFAULT_EAPOL_VERSION) fprintf(f, "eapol_version=%d\n", config->eapol_version); if (config->ap_scan != DEFAULT_AP_SCAN) fprintf(f, "ap_scan=%d\n", config->ap_scan); if (config->disable_scan_offload) fprintf(f, "disable_scan_offload=%d\n", config->disable_scan_offload); if (config->fast_reauth != DEFAULT_FAST_REAUTH) fprintf(f, "fast_reauth=%d\n", config->fast_reauth); if (config->opensc_engine_path) fprintf(f, "opensc_engine_path=%s\n", config->opensc_engine_path); if (config->pkcs11_engine_path) fprintf(f, "pkcs11_engine_path=%s\n", config->pkcs11_engine_path); if (config->pkcs11_module_path) fprintf(f, "pkcs11_module_path=%s\n", config->pkcs11_module_path); if (config->pcsc_reader) fprintf(f, "pcsc_reader=%s\n", config->pcsc_reader); if (config->pcsc_pin) fprintf(f, "pcsc_pin=%s\n", config->pcsc_pin); if (config->driver_param) fprintf(f, "driver_param=%s\n", config->driver_param); if (config->dot11RSNAConfigPMKLifetime) fprintf(f, "dot11RSNAConfigPMKLifetime=%d\n", config->dot11RSNAConfigPMKLifetime); if (config->dot11RSNAConfigPMKReauthThreshold) fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%d\n", config->dot11RSNAConfigPMKReauthThreshold); if (config->dot11RSNAConfigSATimeout) fprintf(f, "dot11RSNAConfigSATimeout=%d\n", config->dot11RSNAConfigSATimeout); if (config->update_config) fprintf(f, "update_config=%d\n", config->update_config); #ifdef CONFIG_WPS if (!is_nil_uuid(config->uuid)) { char buf[40]; uuid_bin2str(config->uuid, buf, sizeof(buf)); fprintf(f, "uuid=%s\n", buf); } if (config->device_name) fprintf(f, "device_name=%s\n", config->device_name); if (config->manufacturer) fprintf(f, "manufacturer=%s\n", config->manufacturer); if (config->model_name) fprintf(f, "model_name=%s\n", config->model_name); if (config->model_number) fprintf(f, "model_number=%s\n", config->model_number); if (config->serial_number) fprintf(f, "serial_number=%s\n", config->serial_number); { char _buf[WPS_DEV_TYPE_BUFSIZE], *buf; buf = wps_dev_type_bin2str(config->device_type, _buf, sizeof(_buf)); if (os_strcmp(buf, "0-00000000-0") != 0) fprintf(f, "device_type=%s\n", buf); } if (WPA_GET_BE32(config->os_version)) fprintf(f, "os_version=%08x\n", WPA_GET_BE32(config->os_version)); if (config->config_methods) fprintf(f, "config_methods=%s\n", config->config_methods); if (config->wps_cred_processing) fprintf(f, "wps_cred_processing=%d\n", config->wps_cred_processing); if (config->wps_vendor_ext_m1) { int i, len = wpabuf_len(config->wps_vendor_ext_m1); const u8 *p = wpabuf_head_u8(config->wps_vendor_ext_m1); if (len > 0) { fprintf(f, "wps_vendor_ext_m1="); for (i = 0; i < len; i++) fprintf(f, "%02x", *p++); fprintf(f, "\n"); } } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if (config->p2p_listen_reg_class) fprintf(f, "p2p_listen_reg_class=%u\n", config->p2p_listen_reg_class); if (config->p2p_listen_channel) fprintf(f, "p2p_listen_channel=%u\n", config->p2p_listen_channel); if (config->p2p_oper_reg_class) fprintf(f, "p2p_oper_reg_class=%u\n", config->p2p_oper_reg_class); if (config->p2p_oper_channel) fprintf(f, "p2p_oper_channel=%u\n", config->p2p_oper_channel); if (config->p2p_go_intent != DEFAULT_P2P_GO_INTENT) fprintf(f, "p2p_go_intent=%u\n", config->p2p_go_intent); if (config->p2p_ssid_postfix) fprintf(f, "p2p_ssid_postfix=%s\n", config->p2p_ssid_postfix); if (config->persistent_reconnect) fprintf(f, "persistent_reconnect=%u\n", config->persistent_reconnect); if (config->p2p_intra_bss != DEFAULT_P2P_INTRA_BSS) fprintf(f, "p2p_intra_bss=%u\n", config->p2p_intra_bss); if (config->p2p_group_idle) fprintf(f, "p2p_group_idle=%u\n", config->p2p_group_idle); if (config->p2p_pref_chan) { unsigned int i; fprintf(f, "p2p_pref_chan="); for (i = 0; i < config->num_p2p_pref_chan; i++) { fprintf(f, "%s%u:%u", i > 0 ? "," : "", config->p2p_pref_chan[i].op_class, config->p2p_pref_chan[i].chan); } fprintf(f, "\n"); } if (config->p2p_go_ht40) fprintf(f, "p2p_go_ht40=%u\n", config->p2p_go_ht40); if (config->p2p_disabled) fprintf(f, "p2p_disabled=%u\n", config->p2p_disabled); if (config->p2p_no_group_iface) fprintf(f, "p2p_no_group_iface=%u\n", config->p2p_no_group_iface); if (config->p2p_ignore_shared_freq) fprintf(f, "p2p_ignore_shared_freq=%u\n", config->p2p_ignore_shared_freq); #endif /* CONFIG_P2P */ if (config->country[0] && config->country[1]) { fprintf(f, "country=%c%c\n", config->country[0], config->country[1]); } if (config->bss_max_count != DEFAULT_BSS_MAX_COUNT) fprintf(f, "bss_max_count=%u\n", config->bss_max_count); if (config->bss_expiration_age != DEFAULT_BSS_EXPIRATION_AGE) fprintf(f, "bss_expiration_age=%u\n", config->bss_expiration_age); if (config->bss_expiration_scan_count != DEFAULT_BSS_EXPIRATION_SCAN_COUNT) fprintf(f, "bss_expiration_scan_count=%u\n", config->bss_expiration_scan_count); if (config->filter_ssids) fprintf(f, "filter_ssids=%d\n", config->filter_ssids); if (config->max_num_sta != DEFAULT_MAX_NUM_STA) fprintf(f, "max_num_sta=%u\n", config->max_num_sta); if (config->disassoc_low_ack) fprintf(f, "disassoc_low_ack=%u\n", config->disassoc_low_ack); #ifdef CONFIG_HS20 if (config->hs20) fprintf(f, "hs20=1\n"); #endif /* CONFIG_HS20 */ #ifdef CONFIG_INTERWORKING if (config->interworking) fprintf(f, "interworking=%u\n", config->interworking); if (!is_zero_ether_addr(config->hessid)) fprintf(f, "hessid=" MACSTR "\n", MAC2STR(config->hessid)); if (config->access_network_type != DEFAULT_ACCESS_NETWORK_TYPE) fprintf(f, "access_network_type=%d\n", config->access_network_type); #endif /* CONFIG_INTERWORKING */ if (config->pbc_in_m1) fprintf(f, "pbc_in_m1=%u\n", config->pbc_in_m1); if (config->wps_nfc_pw_from_config) { if (config->wps_nfc_dev_pw_id) fprintf(f, "wps_nfc_dev_pw_id=%d\n", config->wps_nfc_dev_pw_id); write_global_bin(f, "wps_nfc_dh_pubkey", config->wps_nfc_dh_pubkey); write_global_bin(f, "wps_nfc_dh_privkey", config->wps_nfc_dh_privkey); write_global_bin(f, "wps_nfc_dev_pw", config->wps_nfc_dev_pw); } if (config->ext_password_backend) fprintf(f, "ext_password_backend=%s\n", config->ext_password_backend); if (config->p2p_go_max_inactivity != DEFAULT_P2P_GO_MAX_INACTIVITY) fprintf(f, "p2p_go_max_inactivity=%d\n", config->p2p_go_max_inactivity); if (config->auto_interworking) fprintf(f, "auto_interworking=%d\n", config->auto_interworking); if (config->okc) fprintf(f, "okc=%d\n", config->okc); if (config->pmf) fprintf(f, "pmf=%d\n", config->pmf); if (config->dtim_period) fprintf(f, "dtim_period=%d\n", config->dtim_period); if (config->beacon_int) fprintf(f, "beacon_int=%d\n", config->beacon_int); if (config->sae_groups) { int i; fprintf(f, "sae_groups="); for (i = 0; config->sae_groups[i] >= 0; i++) { fprintf(f, "%s%d", i > 0 ? " " : "", config->sae_groups[i]); } fprintf(f, "\n"); } if (config->ap_vendor_elements) { int i, len = wpabuf_len(config->ap_vendor_elements); const u8 *p = wpabuf_head_u8(config->ap_vendor_elements); if (len > 0) { fprintf(f, "ap_vendor_elements="); for (i = 0; i < len; i++) fprintf(f, "%02x", *p++); fprintf(f, "\n"); } } if (config->ignore_old_scan_res) fprintf(f, "ignore_old_scan_res=%d\n", config->ignore_old_scan_res); if (config->freq_list && config->freq_list[0]) { int i; fprintf(f, "freq_list="); for (i = 0; config->freq_list[i]; i++) { fprintf(f, "%s%u", i > 0 ? " " : "", config->freq_list[i]); } fprintf(f, "\n"); } if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ) fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq); if (config->sched_scan_interval) fprintf(f, "sched_scan_interval=%u\n", config->sched_scan_interval); }
static int l2_packet_init_libpcap(struct l2_packet_data *l2, unsigned short protocol) { bpf_u_int32 pcap_maskp, pcap_netp; char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE]; struct bpf_program pcap_fp; #ifdef CONFIG_WINPCAP char ifname[128]; os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", l2->ifname); pcap_lookupnet(ifname, &pcap_netp, &pcap_maskp, pcap_err); l2->pcap = pcap_open_live(ifname, 2500, 0, 10, pcap_err); if (l2->pcap == NULL) { fprintf(stderr, "pcap_open_live: %s\n", pcap_err); fprintf(stderr, "ifname='%s'\n", ifname); return -1; } if (pcap_setnonblock(l2->pcap, 1, pcap_err) < 0) fprintf(stderr, "pcap_setnonblock: %s\n", pcap_geterr(l2->pcap)); #else /* CONFIG_WINPCAP */ pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err); l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 10, pcap_err); if (l2->pcap == NULL) { fprintf(stderr, "pcap_open_live: %s\n", pcap_err); fprintf(stderr, "ifname='%s'\n", l2->ifname); return -1; } if (pcap_datalink(l2->pcap) != DLT_EN10MB && pcap_set_datalink(l2->pcap, DLT_EN10MB) < 0) { fprintf(stderr, "pcap_set_datalinke(DLT_EN10MB): %s\n", pcap_geterr(l2->pcap)); return -1; } #endif /* CONFIG_WINPCAP */ os_snprintf(pcap_filter, sizeof(pcap_filter), "not ether src " MACSTR " and " "( ether dst " MACSTR " or ether dst " MACSTR " ) and " "ether proto 0x%x", MAC2STR(l2->own_addr), /* do not receive own packets */ MAC2STR(l2->own_addr), MAC2STR(pae_group_addr), protocol); if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) { fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap)); return -1; } if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) { fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap)); return -1; } pcap_freecode(&pcap_fp); #ifdef BIOCIMMEDIATE /* * When libpcap uses BPF we must enable "immediate mode" to * receive frames right away; otherwise the system may * buffer them for us. */ { unsigned int on = 1; if (ioctl(pcap_fileno(l2->pcap), BIOCIMMEDIATE, &on) < 0) { fprintf(stderr, "%s: cannot enable immediate mode on " "interface %s: %s\n", __func__, l2->ifname, strerror(errno)); /* XXX should we fail? */ } } #endif /* BIOCIMMEDIATE */ #ifdef CONFIG_WINPCAP eloop_register_timeout(0, 100000, l2_packet_receive_timeout, l2, l2->pcap); #else /* CONFIG_WINPCAP */ eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap), l2_packet_receive, l2, l2->pcap); #endif /* CONFIG_WINPCAP */ return 0; }
static void handle_assoc_cb(hostapd *hapd, struct ieee80211_mgmt *mgmt, size_t len, int reassoc, int ok) { u16 status; struct prism2_hostapd_param param; struct sta_info *sta; int new_assoc = 1; if (!ok) { hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "did not acknowledge association response"); return; } if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) : sizeof(mgmt->u.assoc_req))) { printf("handle_assoc_cb(reassoc=%d) - too short payload " "(len=%d)\n", reassoc, len); return; } if (reassoc) status = le_to_host16(mgmt->u.reassoc_resp.status_code); else status = le_to_host16(mgmt->u.assoc_resp.status_code); sta = ap_get_sta(hapd, mgmt->da); if (!sta) { printf("handle_assoc_cb: STA " MACSTR " not found\n", MAC2STR(mgmt->da)); return; } if (status != WLAN_STATUS_SUCCESS) goto fail; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "associated (aid %d)", sta->aid); if (sta->flags & WLAN_STA_ASSOC) new_assoc = 0; sta->flags |= WLAN_STA_ASSOC; memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_ADD_STA; memcpy(param.sta_addr, sta->addr, ETH_ALEN); param.u.add_sta.aid = sta->aid; param.u.add_sta.capability = sta->capability; param.u.add_sta.tx_supp_rates = sta->tx_supp_rates; if (hostapd_ioctl(hapd->driver.data, ¶m, sizeof(param))) { printf("Could not add station to kernel driver.\n"); } wpa_sm_event(hapd, sta, WPA_ASSOC); if (new_assoc) hostapd_new_assoc_sta(hapd, sta); else wpa_sm_event(hapd, sta, WPA_REAUTH); ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); fail: /* Copy of the association request is not needed anymore */ if (sta->last_assoc_req) { free(sta->last_assoc_req); sta->last_assoc_req = NULL; } }
static void handle_auth(hostapd *hapd, struct ieee80211_mgmt *mgmt, size_t len) { u16 auth_alg, auth_transaction, status_code; u16 resp = WLAN_STATUS_SUCCESS; struct sta_info *sta = NULL; int res; u16 fc; u8 *challenge = NULL; u32 session_timeout, acct_interim_interval; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { printf("handle_auth - too short payload (len=%d)\n", len); return; } auth_alg = le_to_host16(mgmt->u.auth.auth_alg); auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); status_code = le_to_host16(mgmt->u.auth.status_code); fc = le_to_host16(mgmt->frame_control); if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) + 2 + WLAN_AUTH_CHALLENGE_LEN && mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE && mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN) challenge = &mgmt->u.auth.variable[2]; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "authentication: STA=" MACSTR " auth_alg=%d " "auth_transaction=%d status_code=%d wep=%d%s\n", MAC2STR(mgmt->sa), auth_alg, auth_transaction, status_code, !!(fc & WLAN_FC_ISWEP), challenge ? " challenge" : ""); if (hapd->assoc_ap_state == AUTHENTICATE && auth_transaction == 2 && memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0 && memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) { if (status_code != 0) { printf("Authentication (as station) with AP " MACSTR " failed (status_code=%d)\n", MAC2STR(hapd->conf->assoc_ap_addr), status_code); return; } printf("Authenticated (as station) with AP " MACSTR "\n", MAC2STR(hapd->conf->assoc_ap_addr)); ieee802_11_sta_associate(hapd, NULL); return; } if (hapd->tkip_countermeasures) { resp = WLAN_REASON_MICHAEL_MIC_FAILURE; goto fail; } if (!(((hapd->conf->auth_algs & HOSTAPD_AUTH_OPEN) && auth_alg == WLAN_AUTH_OPEN) || ((hapd->conf->auth_algs & HOSTAPD_AUTH_SHARED_KEY) && auth_alg == WLAN_AUTH_SHARED_KEY))) { printf("Unsupported authentication algorithm (%d)\n", auth_alg); resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; goto fail; } if (!(auth_transaction == 1 || (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) { printf("Unknown authentication transaction number (%d)\n", auth_transaction); resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; goto fail; } if (memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) { printf("Station " MACSTR " not allowed to authenticate.\n", MAC2STR(mgmt->sa)); resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len, &session_timeout, &acct_interim_interval); if (res == HOSTAPD_ACL_REJECT) { printf("Station " MACSTR " not allowed to authenticate.\n", MAC2STR(mgmt->sa)); resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } if (res == HOSTAPD_ACL_PENDING) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Authentication frame " "from " MACSTR " waiting for an external " "authentication\n", MAC2STR(mgmt->sa)); /* Authentication code will re-send the authentication frame * after it has received (and cached) information from the * external source. */ return; } sta = auth_get_sta(hapd, mgmt->sa); if (!sta) { resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } sta->flags &= ~WLAN_STA_PREAUTH; ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); if (hapd->conf->radius_acct_interim_interval == 0 && acct_interim_interval) sta->acct_interim_interval = acct_interim_interval; if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) ap_sta_session_timeout(hapd, sta, session_timeout); else ap_sta_no_session_timeout(hapd, sta); switch (auth_alg) { case WLAN_AUTH_OPEN: hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "authentication OK (open system)"); #ifdef IEEE80211_REQUIRE_AUTH_ACK /* Station will be marked authenticated if it ACKs the * authentication reply. */ #else sta->flags |= WLAN_STA_AUTH; wpa_sm_event(hapd, sta, WPA_AUTH); #endif break; case WLAN_AUTH_SHARED_KEY: resp = auth_shared_key(hapd, sta, auth_transaction, challenge, fc & WLAN_FC_ISWEP); break; } fail: send_auth_reply(hapd, mgmt, auth_alg, auth_transaction + 1, resp, sta ? sta->challenge : NULL); }
void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, int authorized) { const u8 *dev_addr = NULL; #ifdef CONFIG_P2P u8 addr[ETH_ALEN]; #endif /* CONFIG_P2P */ if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED)) return; #ifdef CONFIG_P2P if (hapd->p2p_group == NULL) { if (sta->p2p_ie != NULL && p2p_parse_dev_addr_in_p2p_ie(sta->p2p_ie, addr) == 0) dev_addr = addr; } else dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr); #endif /* CONFIG_P2P */ if (authorized) { if (dev_addr) wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED MACSTR " p2p_dev_addr=" MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr)); else wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr)); if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr) wpa_msg(hapd->msg_ctx_parent, MSG_INFO, AP_STA_CONNECTED MACSTR " p2p_dev_addr=" MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr)); else if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx) wpa_msg(hapd->msg_ctx_parent, MSG_INFO, AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr)); sta->flags |= WLAN_STA_AUTHORIZED; } else { if (dev_addr) wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR " p2p_dev_addr=" MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr)); else wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR, MAC2STR(sta->addr)); if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr) wpa_msg(hapd->msg_ctx_parent, MSG_INFO, AP_STA_DISCONNECTED MACSTR " p2p_dev_addr=" MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr)); else if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx) wpa_msg(hapd->msg_ctx_parent, MSG_INFO, AP_STA_DISCONNECTED MACSTR, MAC2STR(sta->addr)); sta->flags &= ~WLAN_STA_AUTHORIZED; } if (hapd->sta_authorized_cb) hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx, sta->addr, authorized, dev_addr); }
u8 * ccmp_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr, const u8 *data, size_t data_len, size_t *decrypted_len) { u8 aad[2 + 30], nonce[13]; size_t aad_len; u8 b[AES_BLOCK_SIZE], x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE]; void *aes; const u8 *m, *mpos, *mic; size_t mlen, last; int i; u8 *plain, *ppos; u8 t[8]; if (data_len < 8 + 8) return NULL; plain = os_malloc(data_len + AES_BLOCK_SIZE); if (plain == NULL) return NULL; aes = aes_encrypt_init(tk, 16); if (aes == NULL) { os_free(plain); return NULL; } m = data + 8; mlen = data_len - 8 - 8; last = mlen % AES_BLOCK_SIZE; os_memset(aad, 0, sizeof(aad)); ccmp_aad_nonce(hdr, data, &aad[2], &aad_len, nonce); WPA_PUT_BE16(aad, aad_len); wpa_hexdump(MSG_EXCESSIVE, "CCMP AAD", &aad[2], aad_len); wpa_hexdump(MSG_EXCESSIVE, "CCMP nonce", nonce, 13); /* CCM: M=8 L=2, Adata=1, M' = (M-2)/2 = 3, L' = L-1 = 1 */ /* A_i = Flags | Nonce N | Counter i */ a[0] = 0x01; /* Flags = L' */ os_memcpy(&a[1], nonce, 13); /* Decryption */ mic = data + data_len - 8; wpa_hexdump(MSG_EXCESSIVE, "CCMP U", mic, 8); /* U = T XOR S_0; S_0 = E(K, A_0) */ WPA_PUT_BE16(&a[14], 0); aes_encrypt(aes, a, x); for (i = 0; i < 8; i++) t[i] = mic[i] ^ x[i]; wpa_hexdump(MSG_EXCESSIVE, "CCMP T", t, 8); /* plaintext = msg XOR (S_1 | S_2 | ... | S_n) */ ppos = plain; mpos = m; for (i = 1; i <= mlen / AES_BLOCK_SIZE; i++) { WPA_PUT_BE16(&a[14], i); /* S_i = E(K, A_i) */ aes_encrypt(aes, a, ppos); xor_aes_block(ppos, mpos); ppos += AES_BLOCK_SIZE; mpos += AES_BLOCK_SIZE; } if (last) { WPA_PUT_BE16(&a[14], i); aes_encrypt(aes, a, ppos); /* XOR zero-padded last block */ for (i = 0; i < last; i++) *ppos++ ^= *mpos++; } wpa_hexdump(MSG_EXCESSIVE, "CCMP decrypted", plain, mlen); /* Authentication */ /* B_0: Flags | Nonce N | l(m) */ b[0] = 0x40 /* Adata */ | (3 /* M' */ << 3) | 1 /* L' */; os_memcpy(&b[1], nonce, 13); WPA_PUT_BE16(&b[14], mlen); wpa_hexdump(MSG_EXCESSIVE, "CCMP B_0", b, AES_BLOCK_SIZE); aes_encrypt(aes, b, x); /* X_1 = E(K, B_0) */ wpa_hexdump(MSG_EXCESSIVE, "CCMP B_1", aad, AES_BLOCK_SIZE); xor_aes_block(aad, x); aes_encrypt(aes, aad, x); /* X_2 = E(K, X_1 XOR B_1) */ wpa_hexdump(MSG_EXCESSIVE, "CCMP B_2", &aad[AES_BLOCK_SIZE], AES_BLOCK_SIZE); xor_aes_block(&aad[AES_BLOCK_SIZE], x); aes_encrypt(aes, &aad[AES_BLOCK_SIZE], x); /* X_3 = E(K, X_2 XOR B_2) */ ppos = plain; for (i = 0; i < mlen / AES_BLOCK_SIZE; i++) { /* X_i+1 = E(K, X_i XOR B_i) */ xor_aes_block(x, ppos); ppos += AES_BLOCK_SIZE; aes_encrypt(aes, x, x); } if (last) { /* XOR zero-padded last block */ for (i = 0; i < last; i++) x[i] ^= *ppos++; aes_encrypt(aes, x, x); } aes_encrypt_deinit(aes); if (os_memcmp(x, t, 8) != 0) { u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); wpa_printf(MSG_INFO, "Invalid CCMP MIC in frame: A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3), WLAN_GET_SEQ_SEQ(seq_ctrl), WLAN_GET_SEQ_FRAG(seq_ctrl)); wpa_hexdump(MSG_DEBUG, "CCMP decrypted", plain, mlen); os_free(plain); return NULL; } *decrypted_len = mlen; return plain; }
static int radius_client_retransmit(struct radius_client_data *radius, struct radius_msg_list *entry, os_time_t now) { struct hostapd_radius_servers *conf = radius->conf; int s; struct wpabuf *buf; size_t prev_num_msgs; u8 *acct_delay_time; size_t acct_delay_time_len; if (entry->msg_type == RADIUS_ACCT || entry->msg_type == RADIUS_ACCT_INTERIM) { if (radius->acct_sock < 0) radius_client_init_acct(radius); if (radius->acct_sock < 0 && conf->num_acct_servers > 1) { prev_num_msgs = radius->num_msgs; radius_client_acct_failover(radius); if (prev_num_msgs != radius->num_msgs) return 0; } s = radius->acct_sock; if (entry->attempts == 0) conf->acct_server->requests++; else { conf->acct_server->timeouts++; conf->acct_server->retransmissions++; } } else { if (radius->auth_sock < 0) radius_client_init_auth(radius); if (radius->auth_sock < 0 && conf->num_auth_servers > 1) { prev_num_msgs = radius->num_msgs; radius_client_auth_failover(radius); if (prev_num_msgs != radius->num_msgs) return 0; } s = radius->auth_sock; if (entry->attempts == 0) conf->auth_server->requests++; else { conf->auth_server->timeouts++; conf->auth_server->retransmissions++; } } if (entry->msg_type == RADIUS_ACCT_INTERIM) { wpa_printf(MSG_DEBUG, "RADIUS: Failed to transmit interim accounting update to " MACSTR " - drop message and request a new update", MAC2STR(entry->addr)); if (radius->interim_error_cb) radius->interim_error_cb(entry->addr, radius->interim_error_cb_ctx); return 1; } if (s < 0) { wpa_printf(MSG_INFO, "RADIUS: No valid socket for retransmission"); return 1; } if (entry->msg_type == RADIUS_ACCT && radius_msg_get_attr_ptr(entry->msg, RADIUS_ATTR_ACCT_DELAY_TIME, &acct_delay_time, &acct_delay_time_len, NULL) == 0 && acct_delay_time_len == 4) { struct radius_hdr *hdr; u32 delay_time; /* * Need to assign a new identifier since attribute contents * changes. */ hdr = radius_msg_get_hdr(entry->msg); hdr->identifier = radius_client_get_id(radius); /* Update Acct-Delay-Time to show wait time in queue */ delay_time = now - entry->first_try; WPA_PUT_BE32(acct_delay_time, delay_time); wpa_printf(MSG_DEBUG, "RADIUS: Updated Acct-Delay-Time to %u for retransmission", delay_time); radius_msg_finish_acct(entry->msg, entry->shared_secret, entry->shared_secret_len); if (radius->conf->msg_dumps) radius_msg_dump(entry->msg); } /* retransmit; remove entry if too many attempts */ entry->attempts++; hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)", radius_msg_get_hdr(entry->msg)->identifier); os_get_reltime(&entry->last_attempt); buf = radius_msg_get_buf(entry->msg); if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) { if (radius_client_handle_send_error(radius, s, entry->msg_type) > 0) return 0; } entry->next_try = now + entry->next_wait; entry->next_wait *= 2; if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT) entry->next_wait = RADIUS_CLIENT_MAX_WAIT; if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) { wpa_printf(MSG_INFO, "RADIUS: Removing un-ACKed message due to too many failed retransmit attempts"); return 1; } return 0; }
VOID kalP2PIndicateRxMgmtFrame ( IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb, IN BOOLEAN fgIsDevInterface, IN UINT_8 ucRoleIdx ) { #define DBG_P2P_MGMT_FRAME_INDICATION 1 P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL; INT_32 i4Freq = 0; UINT_8 ucChnlNum = 0; #if DBG_P2P_MGMT_FRAME_INDICATION P_WLAN_MAC_HEADER_T prWlanHeader = (P_WLAN_MAC_HEADER_T)NULL; #endif do { if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { ASSERT(FALSE); break; } prGlueP2pInfo = prGlueInfo->prP2PInfo; //ToDo[6630]: Get the following by chnnel freq //HAL_RX_STATUS_GET_CHAN_FREQ( prSwRfb->prRxStatus) //ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; ucChnlNum = HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus); #if DBG_P2P_MGMT_FRAME_INDICATION prWlanHeader = (P_WLAN_MAC_HEADER_T)prSwRfb->pvHeader; switch (prWlanHeader->u2FrameCtrl) { case MAC_FRAME_PROBE_REQ: DBGLOG(P2P, TRACE, ("RX Probe Req at channel %d ", ucChnlNum)); break; case MAC_FRAME_PROBE_RSP: DBGLOG(P2P, TRACE, ("RX Probe Rsp at channel %d ", ucChnlNum)); break; case MAC_FRAME_ACTION: DBGLOG(P2P, TRACE, ("RX Action frame at channel %d ", ucChnlNum)); break; default: DBGLOG(P2P, TRACE, ("RX Packet:%d at channel %d ", prWlanHeader->u2FrameCtrl, ucChnlNum)); break; } DBGLOG(P2P, TRACE, ("from: "MACSTR"\n", MAC2STR(prWlanHeader->aucAddr2))); #endif i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) cfg80211_rx_mgmt(&prGlueP2pInfo->wdev, //struct net_device * dev, #else cfg80211_rx_mgmt((fgIsDevInterface)?prGlueP2pInfo->prDevHandler:prGlueP2pInfo->aprRoleHandler[ucRoleIdx], //struct net_device * dev, #endif /* LINUX_VERSION_CODE */ i4Freq, RCPI_TO_dBm(HAL_RX_STATUS_GET_RCPI(prSwRfb->prRxStatusGroup3)), prSwRfb->pvHeader, prSwRfb->u2PacketLen, GFP_ATOMIC); #else cfg80211_rx_mgmt((fgIsDevInterface)?prGlueP2pInfo->prDevHandler:prGlueP2pInfo->aprRoleHandler[ucRoleIdx], //struct net_device * dev, i4Freq, prSwRfb->pvHeader, prSwRfb->u2PacketLen, GFP_ATOMIC); #endif } while (FALSE); } /* kalP2PIndicateRxMgmtFrame */
static int wps_process_ap_settings_e(struct wps_data *wps, struct wps_parse_attr *attr, struct wpabuf *attrs, int wps2) { struct wps_credential cred; if (!wps->wps->ap) return 0; if (wps_process_ap_settings(attr, &cred) < 0) return -1; wpa_printf(MSG_INFO, "WPS: Received new AP configuration from " "Registrar"); if (os_memcmp(cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: MAC Address in the AP Settings (" MACSTR ") does not match with own address (" MACSTR ")", MAC2STR(cred.mac_addr), MAC2STR(wps->wps->dev.mac_addr)); /* * In theory, this could be consider fatal error, but there are * number of deployed implementations using other address here * due to unclarity in the specification. For interoperability * reasons, allow this to be processed since we do not really * use the MAC Address information for anything. */ #ifdef CONFIG_WPS_STRICT if (wps2) { wpa_printf(MSG_INFO, "WPS: Do not accept incorrect " "MAC Address in AP Settings"); return -1; } #endif /* CONFIG_WPS_STRICT */ } #ifdef CONFIG_WPS2 if (!(cred.encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) { if (cred.encr_type & WPS_ENCR_WEP) { wpa_printf(MSG_INFO, "WPS: Reject new AP settings " "due to WEP configuration"); wps->error_indication = WPS_EI_SECURITY_WEP_PROHIBITED; return -1; } wpa_printf(MSG_INFO, "WPS: Reject new AP settings due to " "invalid encr_type 0x%x", cred.encr_type); return -1; } #endif /* CONFIG_WPS2 */ #ifdef CONFIG_WPS_STRICT if (wps2) { if ((cred.encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) == WPS_ENCR_TKIP || (cred.auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) == WPS_AUTH_WPAPSK) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC 2.0 " "AP Settings: WPA-Personal/TKIP only"); wps->error_indication = WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED; return -1; } } #endif /* CONFIG_WPS_STRICT */ #ifdef CONFIG_WPS2 if ((cred.encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) == WPS_ENCR_TKIP) { wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> " "TKIP+AES"); cred.encr_type |= WPS_ENCR_AES; } if ((cred.auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) == WPS_AUTH_WPAPSK) { wpa_printf(MSG_DEBUG, "WPS: Upgrade auth_type WPAPSK -> " "WPAPSK+WPA2PSK"); cred.auth_type |= WPS_AUTH_WPA2PSK; } #endif /* CONFIG_WPS2 */ if (wps->wps->cred_cb) { cred.cred_attr = wpabuf_head(attrs); cred.cred_attr_len = wpabuf_len(attrs); wps->wps->cred_cb(wps->wps->cb_ctx, &cred); } return 0; }
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, const u8 *req_ies, size_t req_ies_len, int reassoc) { struct sta_info *sta; int new_assoc, res; struct ieee802_11_elems elems; const u8 *ie; size_t ielen; #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; u8 *p = buf; #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ u16 reason = WLAN_REASON_UNSPECIFIED; u16 status = WLAN_STATUS_SUCCESS; const u8 *p2p_dev_addr = NULL; if (addr == NULL) { /* * This could potentially happen with unexpected event from the * driver wrapper. This was seen at least in one case where the * driver ended up being set to station mode while hostapd was * running, so better make sure we stop processing such an * event here. */ wpa_printf(MSG_DEBUG, "hostapd_notif_assoc: Skip event with no address"); return -1; } random_add_randomness(addr, ETH_ALEN); hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "associated"); ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0); if (elems.wps_ie) { ie = elems.wps_ie - 2; ielen = elems.wps_ie_len + 2; wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq"); } else if (elems.rsn_ie) { ie = elems.rsn_ie - 2; ielen = elems.rsn_ie_len + 2; wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq"); } else if (elems.wpa_ie) { ie = elems.wpa_ie - 2; ielen = elems.wpa_ie_len + 2; wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq"); #ifdef CONFIG_HS20 } else if (elems.osen) { ie = elems.osen - 2; ielen = elems.osen_len + 2; wpa_printf(MSG_DEBUG, "STA included OSEN IE in (Re)AssocReq"); #endif /* CONFIG_HS20 */ } else { ie = NULL; ielen = 0; wpa_printf(MSG_DEBUG, "STA did not include WPS/RSN/WPA IE in (Re)AssocReq"); } sta = ap_get_sta(hapd, addr); if (sta) { ap_sta_no_session_timeout(hapd, sta); accounting_sta_stop(hapd, sta); /* * Make sure that the previously registered inactivity timer * will not remove the STA immediately. */ sta->timeout_next = STA_NULLFUNC; } else { sta = ap_sta_add(hapd, addr); if (sta == NULL) { hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_AP_BUSY); return -1; } } sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2); /* * ACL configurations to the drivers (implementing AP SME and ACL * offload) without hostapd's knowledge, can result in a disconnection * though the driver accepts the connection. Skip the hostapd check for * ACL if the driver supports ACL offload to avoid potentially * conflicting ACL rules. */ if (hapd->iface->drv_max_acl_mac_addrs == 0 && hostapd_check_acl(hapd, addr, NULL) != HOSTAPD_ACL_ACCEPT) { wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect", MAC2STR(addr)); reason = WLAN_REASON_UNSPECIFIED; goto fail; } #ifdef CONFIG_P2P if (elems.p2p) { wpabuf_free(sta->p2p_ie); sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len, P2P_IE_VENDOR_TYPE); if (sta->p2p_ie) p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie); } #endif /* CONFIG_P2P */ #ifdef CONFIG_IEEE80211N #ifdef NEED_AP_MLME if (elems.ht_capabilities && (hapd->iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { struct ieee80211_ht_capabilities *ht_cap = (struct ieee80211_ht_capabilities *) elems.ht_capabilities; if (le_to_host16(ht_cap->ht_capabilities_info) & HT_CAP_INFO_40MHZ_INTOLERANT) ht40_intolerant_add(hapd->iface, sta); } #endif /* NEED_AP_MLME */ #endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_INTERWORKING if (elems.ext_capab && elems.ext_capab_len > 4) { if (elems.ext_capab[4] & 0x01) sta->qos_map_enabled = 1; } #endif /* CONFIG_INTERWORKING */ #ifdef CONFIG_HS20 wpabuf_free(sta->hs20_ie); if (elems.hs20 && elems.hs20_len > 4) { sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4, elems.hs20_len - 4); } else sta->hs20_ie = NULL; #endif /* CONFIG_HS20 */ #ifdef CONFIG_FST wpabuf_free(sta->mb_ies); if (hapd->iface->fst) sta->mb_ies = mb_ies_by_info(&elems.mb_ies); else sta->mb_ies = NULL; #endif /* CONFIG_FST */ mbo_ap_check_sta_assoc(hapd, sta, &elems); ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes, elems.supp_op_classes_len); if (hapd->conf->wpa) { if (ie == NULL || ielen == 0) { #ifdef CONFIG_WPS if (hapd->conf->wps_state) { wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in (Re)Association Request - possible WPS use"); sta->flags |= WLAN_STA_MAYBE_WPS; goto skip_wpa_check; } #endif /* CONFIG_WPS */ wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA"); return -1; } #ifdef CONFIG_WPS if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 && os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { struct wpabuf *wps; sta->flags |= WLAN_STA_WPS; wps = ieee802_11_vendor_ie_concat(ie, ielen, WPS_IE_VENDOR_TYPE); if (wps) { if (wps_is_20(wps)) { wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0"); sta->flags |= WLAN_STA_WPS2; } wpabuf_free(wps); } goto skip_wpa_check; } #endif /* CONFIG_WPS */ if (sta->wpa_sm == NULL) sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr, p2p_dev_addr); if (sta->wpa_sm == NULL) { wpa_printf(MSG_ERROR, "Failed to initialize WPA state machine"); return -1; } res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, ie, ielen, elems.mdie, elems.mdie_len); if (res != WPA_IE_OK) { wpa_printf(MSG_DEBUG, "WPA/RSN information element rejected? (res %u)", res); wpa_hexdump(MSG_DEBUG, "IE", ie, ielen); if (res == WPA_INVALID_GROUP) { reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID; status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; } else if (res == WPA_INVALID_PAIRWISE) { reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; } else if (res == WPA_INVALID_AKMP) { reason = WLAN_REASON_AKMP_NOT_VALID; status = WLAN_STATUS_AKMP_NOT_VALID; } #ifdef CONFIG_IEEE80211W else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) { reason = WLAN_REASON_INVALID_IE; status = WLAN_STATUS_INVALID_IE; } else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) { reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID; status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; } #endif /* CONFIG_IEEE80211W */ else { reason = WLAN_REASON_INVALID_IE; status = WLAN_STATUS_INVALID_IE; } goto fail; } #ifdef CONFIG_IEEE80211W if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && sta->sa_query_count > 0) ap_check_sa_query_timeout(hapd, sta); if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && (sta->auth_alg != WLAN_AUTH_FT)) { /* * STA has already been associated with MFP and SA * Query timeout has not been reached. Reject the * association attempt temporarily and start SA Query, * if one is not pending. */ if (sta->sa_query_count == 0) ap_sta_start_sa_query(hapd, sta); status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; p = hostapd_eid_assoc_comeback_time(hapd, sta, p); hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); return 0; } if (wpa_auth_uses_mfp(sta->wpa_sm)) sta->flags |= WLAN_STA_MFP; else sta->flags &= ~WLAN_STA_MFP; #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_IEEE80211R if (sta->auth_alg == WLAN_AUTH_FT) { status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies, req_ies_len); if (status != WLAN_STATUS_SUCCESS) { if (status == WLAN_STATUS_INVALID_PMKID) reason = WLAN_REASON_INVALID_IE; if (status == WLAN_STATUS_INVALID_MDIE) reason = WLAN_REASON_INVALID_IE; if (status == WLAN_STATUS_INVALID_FTIE) reason = WLAN_REASON_INVALID_IE; goto fail; } } #endif /* CONFIG_IEEE80211R */ } else if (hapd->conf->wps_state) { #ifdef CONFIG_WPS struct wpabuf *wps; if (req_ies) wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len, WPS_IE_VENDOR_TYPE); else wps = NULL; #ifdef CONFIG_WPS_STRICT if (wps && wps_validate_assoc_req(wps) < 0) { reason = WLAN_REASON_INVALID_IE; status = WLAN_STATUS_INVALID_IE; wpabuf_free(wps); goto fail; } #endif /* CONFIG_WPS_STRICT */ if (wps) { sta->flags |= WLAN_STA_WPS; if (wps_is_20(wps)) { wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0"); sta->flags |= WLAN_STA_WPS2; } } else sta->flags |= WLAN_STA_MAYBE_WPS; wpabuf_free(wps); #endif /* CONFIG_WPS */ #ifdef CONFIG_HS20 } else if (hapd->conf->osen) { if (elems.osen == NULL) { hostapd_logger( hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "No HS 2.0 OSEN element in association request"); return WLAN_STATUS_INVALID_IE; } wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association"); if (sta->wpa_sm == NULL) sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr, NULL); if (sta->wpa_sm == NULL) { wpa_printf(MSG_WARNING, "Failed to initialize WPA state machine"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm, elems.osen - 2, elems.osen_len + 2) < 0) return WLAN_STATUS_INVALID_IE; #endif /* CONFIG_HS20 */ } #ifdef CONFIG_MBO if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) && elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) && hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { wpa_printf(MSG_INFO, "MBO: Reject WPA2 association without PMF"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } #endif /* CONFIG_MBO */ #ifdef CONFIG_WPS skip_wpa_check: #endif /* CONFIG_WPS */ #ifdef CONFIG_IEEE80211R p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf), sta->auth_alg, req_ies, req_ies_len); hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); if (sta->auth_alg == WLAN_AUTH_FT) ap_sta_set_authorized(hapd, sta, 1); #else /* CONFIG_IEEE80211R */ /* Keep compiler silent about unused variables */ if (status) { } #endif /* CONFIG_IEEE80211R */ new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE; hostapd_set_sta_flags(hapd, sta); if (reassoc && (sta->auth_alg == WLAN_AUTH_FT)) wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT); else wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); hostapd_new_assoc_sta(hapd, sta, !new_assoc); ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); #ifdef CONFIG_P2P if (req_ies) { p2p_group_notif_assoc(hapd->p2p_group, sta->addr, req_ies, req_ies_len); } #endif /* CONFIG_P2P */ return 0; fail: #ifdef CONFIG_IEEE80211R hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); #endif /* CONFIG_IEEE80211R */ hostapd_drv_sta_disassoc(hapd, sta->addr, reason); ap_free_sta(hapd, sta); return -1; }
static void handle_assoc(hostapd *hapd, struct ieee80211_mgmt *mgmt, size_t len, int reassoc) { u16 capab_info, listen_interval; u16 resp = WLAN_STATUS_SUCCESS; u8 *pos, *wpa_ie; size_t wpa_ie_len; int send_deauth = 0, send_len, left, i; struct sta_info *sta; struct ieee802_11_elems elems; if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) : sizeof(mgmt->u.assoc_req))) { printf("handle_assoc(reassoc=%d) - too short payload (len=%d)" "\n", reassoc, len); return; } if (reassoc) { capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info); listen_interval = le_to_host16( mgmt->u.reassoc_req.listen_interval); HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "reassociation request: STA=" MACSTR " capab_info=0x%02x " "listen_interval=%d current_ap=" MACSTR "\n", MAC2STR(mgmt->sa), capab_info, listen_interval, MAC2STR(mgmt->u.reassoc_req.current_ap)); left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req)); pos = mgmt->u.reassoc_req.variable; } else { capab_info = le_to_host16(mgmt->u.assoc_req.capab_info); listen_interval = le_to_host16( mgmt->u.assoc_req.listen_interval); HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "association request: STA=" MACSTR " capab_info=0x%02x listen_interval=%d\n", MAC2STR(mgmt->sa), capab_info, listen_interval); left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req)); pos = mgmt->u.assoc_req.variable; } sta = ap_get_sta(hapd, mgmt->sa); if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) { printf("STA " MACSTR " trying to associate before " "authentication\n", MAC2STR(mgmt->sa)); if (sta) { printf(" sta: addr=" MACSTR " aid=%d flags=0x%04x\n", MAC2STR(sta->addr), sta->aid, sta->flags); } send_deauth = 1; resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } if (hapd->tkip_countermeasures) { resp = WLAN_REASON_MICHAEL_MIC_FAILURE; goto fail; } sta->capability = capab_info; /* followed by SSID and Supported rates */ if (ieee802_11_parse_elems(hapd, pos, left, &elems) == ParseFailed || !elems.ssid) { printf("STA " MACSTR " sent invalid association request\n", MAC2STR(sta->addr)); resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } if (elems.ssid_len != hapd->conf->ssid_len || memcmp(elems.ssid, hapd->conf->ssid, elems.ssid_len) != 0) { printf("Station " MACSTR " tried to associate with " "unknown SSID '", MAC2STR(sta->addr)); ieee802_11_print_ssid(elems.ssid, elems.ssid_len); printf("'\n"); resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } if (elems.supp_rates) { if (elems.supp_rates_len > sizeof(sta->supported_rates)) { printf("STA " MACSTR ": Invalid supported rates " "element length %d\n", MAC2STR(sta->addr), elems.supp_rates_len); resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); memcpy(sta->supported_rates, elems.supp_rates, elems.supp_rates_len); sta->tx_supp_rates = 0; for (i = 0; i < elems.supp_rates_len; i++) { if ((sta->supported_rates[i] & 0x7f) == 2) sta->tx_supp_rates |= WLAN_RATE_1M; if ((sta->supported_rates[i] & 0x7f) == 4) sta->tx_supp_rates |= WLAN_RATE_2M; if ((sta->supported_rates[i] & 0x7f) == 11) sta->tx_supp_rates |= WLAN_RATE_5M5; if ((sta->supported_rates[i] & 0x7f) == 22) sta->tx_supp_rates |= WLAN_RATE_11M; } } else sta->tx_supp_rates = 0xff; if ((hapd->conf->wpa & HOSTAPD_WPA_VERSION_WPA2) && elems.rsn_ie) { wpa_ie = elems.rsn_ie; wpa_ie_len = elems.rsn_ie_len; } else if ((hapd->conf->wpa & HOSTAPD_WPA_VERSION_WPA) && elems.wpa_ie) { wpa_ie = elems.wpa_ie; wpa_ie_len = elems.wpa_ie_len; } else { wpa_ie = NULL; wpa_ie_len = 0; } if (hapd->conf->wpa && wpa_ie == NULL) { printf("STA " MACSTR ": No WPA/RSN IE in association " "request\n", MAC2STR(sta->addr)); resp = WLAN_STATUS_INVALID_IE; goto fail; } if (hapd->conf->wpa) { int res; wpa_ie -= 2; wpa_ie_len += 2; res = wpa_validate_wpa_ie(hapd, sta, wpa_ie, wpa_ie_len, elems.rsn_ie ? HOSTAPD_WPA_VERSION_WPA2 : HOSTAPD_WPA_VERSION_WPA); if (res == WPA_INVALID_GROUP) resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; else if (res == WPA_INVALID_PAIRWISE) resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; else if (res == WPA_INVALID_AKMP) resp = WLAN_STATUS_AKMP_NOT_VALID; else if (res != WPA_IE_OK) resp = WLAN_STATUS_INVALID_IE; if (resp != WLAN_STATUS_SUCCESS) goto fail; free(sta->wpa_ie); sta->wpa_ie = malloc(wpa_ie_len); if (sta->wpa_ie == NULL) { resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } sta->wpa_ie_len = wpa_ie_len; memcpy(sta->wpa_ie, wpa_ie, wpa_ie_len); } /* get a unique AID */ if (sta->aid > 0) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " old AID %d\n", sta->aid); } else { for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++) if (hapd->sta_aid[sta->aid - 1] == NULL) break; if (sta->aid > MAX_AID_TABLE_SIZE) { sta->aid = 0; resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; printf(" no room for more AIDs\n"); goto fail; } else { hapd->sta_aid[sta->aid - 1] = sta; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " new AID %d\n", sta->aid); } } hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "association OK (aid %d)", sta->aid); /* Station will be marked associated, after it acknowledges AssocResp */ if (sta->last_assoc_req) free(sta->last_assoc_req); sta->last_assoc_req = (struct ieee80211_mgmt *) malloc(len); if (sta->last_assoc_req) memcpy(sta->last_assoc_req, mgmt, len); /* Make sure that the previously registered inactivity timer will not * remove the STA immediately. */ sta->timeout_next = STA_NULLFUNC; fail: /* use the queued buffer for transmission because it is large enough * and not needed anymore */ mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, (send_deauth ? WLAN_FC_STYPE_DEAUTH : (reassoc ? WLAN_FC_STYPE_REASSOC_RESP : WLAN_FC_STYPE_ASSOC_RESP))); memcpy(mgmt->da, mgmt->sa, ETH_ALEN); memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); /* Addr3 = BSSID - already set */ send_len = IEEE80211_HDRLEN; if (send_deauth) { send_len += sizeof(mgmt->u.deauth); mgmt->u.deauth.reason_code = host_to_le16(resp); } else { u8 *p; send_len += sizeof(mgmt->u.assoc_resp); mgmt->u.assoc_resp.capab_info = host_to_le16(hostapd_own_capab_info(hapd)); mgmt->u.assoc_resp.status_code = host_to_le16(resp); mgmt->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) | BIT(14) | BIT(15)); /* Supported rates */ p = hostapd_eid_supp_rates(hapd, mgmt->u.assoc_resp.variable); send_len += p - mgmt->u.assoc_resp.variable; /* Request TX callback */ mgmt->frame_control |= host_to_le16(BIT(1)); } if (hapd->driver.send_mgmt_frame && hapd->driver.send_mgmt_frame(hapd->driver.data, mgmt, send_len, 0) < 0) perror("handle_assoc: send"); }
/** * gas_query_rx - Indicate reception of a Public Action or Protected Dual frame * @gas: GAS query data from gas_query_init() * @da: Destination MAC address of the Action frame * @sa: Source MAC address of the Action frame * @bssid: BSSID of the Action frame * @categ: Category of the Action frame * @data: Payload of the Action frame * @len: Length of @data * @freq: Frequency (in MHz) on which the frame was received * Returns: 0 if the Public Action frame was a GAS frame or -1 if not */ int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa, const u8 *bssid, u8 categ, const u8 *data, size_t len, int freq) { struct gas_query_pending *query; u8 action, dialog_token, frag_id = 0, more_frags = 0; u16 comeback_delay, resp_len; const u8 *pos, *adv_proto; int prot, pmf; unsigned int left; if (gas == NULL || len < 4) return -1; prot = categ == WLAN_ACTION_PROTECTED_DUAL; pmf = pmf_in_use(gas->wpa_s, sa); if (prot && !pmf) { wpa_printf(MSG_DEBUG, "GAS: Drop unexpected protected GAS frame when PMF is disabled"); return 0; } if (!prot && pmf) { wpa_printf(MSG_DEBUG, "GAS: Drop unexpected unprotected GAS frame when PMF is enabled"); return 0; } pos = data; action = *pos++; dialog_token = *pos++; if (action != WLAN_PA_GAS_INITIAL_RESP && action != WLAN_PA_GAS_COMEBACK_RESP) return -1; /* Not a GAS response */ query = gas_query_get_pending(gas, sa, dialog_token); if (query == NULL) { wpa_printf(MSG_DEBUG, "GAS: No pending query found for " MACSTR " dialog token %u", MAC2STR(sa), dialog_token); return -1; } wpa_printf(MSG_DEBUG, "GAS: Response in %d ms from " MACSTR, ms_from_time(&query->last_oper), MAC2STR(sa)); if (query->wait_comeback && action == WLAN_PA_GAS_INITIAL_RESP) { wpa_printf(MSG_DEBUG, "GAS: Unexpected initial response from " MACSTR " dialog token %u when waiting for comeback " "response", MAC2STR(sa), dialog_token); return 0; } if (!query->wait_comeback && action == WLAN_PA_GAS_COMEBACK_RESP) { wpa_printf(MSG_DEBUG, "GAS: Unexpected comeback response from " MACSTR " dialog token %u when waiting for initial " "response", MAC2STR(sa), dialog_token); return 0; } query->status_code = WPA_GET_LE16(pos); pos += 2; if (query->status_code == WLAN_STATUS_QUERY_RESP_OUTSTANDING && action == WLAN_PA_GAS_COMEBACK_RESP) { wpa_printf(MSG_DEBUG, "GAS: Allow non-zero status for outstanding comeback response"); } else if (query->status_code != WLAN_STATUS_SUCCESS) { wpa_printf(MSG_DEBUG, "GAS: Query to " MACSTR " dialog token " "%u failed - status code %u", MAC2STR(sa), dialog_token, query->status_code); gas_query_done(gas, query, GAS_QUERY_FAILURE); return 0; } if (action == WLAN_PA_GAS_COMEBACK_RESP) { if (pos + 1 > data + len) return 0; frag_id = *pos & 0x7f; more_frags = (*pos & 0x80) >> 7; pos++; } /* Comeback Delay */ if (pos + 2 > data + len) return 0; comeback_delay = WPA_GET_LE16(pos); pos += 2; /* Advertisement Protocol element */ if (pos + 2 > data + len || pos + 2 + pos[1] > data + len) { wpa_printf(MSG_DEBUG, "GAS: No room for Advertisement " "Protocol element in the response from " MACSTR, MAC2STR(sa)); return 0; } if (*pos != WLAN_EID_ADV_PROTO) { wpa_printf(MSG_DEBUG, "GAS: Unexpected Advertisement " "Protocol element ID %u in response from " MACSTR, *pos, MAC2STR(sa)); return 0; } adv_proto = pos; pos += 2 + pos[1]; /* Query Response Length */ if (pos + 2 > data + len) { wpa_printf(MSG_DEBUG, "GAS: No room for GAS Response Length"); return 0; } resp_len = WPA_GET_LE16(pos); pos += 2; left = data + len - pos; if (resp_len > left) { wpa_printf(MSG_DEBUG, "GAS: Truncated Query Response in " "response from " MACSTR, MAC2STR(sa)); return 0; } if (resp_len < left) { wpa_printf(MSG_DEBUG, "GAS: Ignore %u octets of extra data " "after Query Response from " MACSTR, left - resp_len, MAC2STR(sa)); } if (action == WLAN_PA_GAS_COMEBACK_RESP) gas_query_rx_comeback(gas, query, adv_proto, pos, resp_len, frag_id, more_frags, comeback_delay); else gas_query_rx_initial(gas, query, adv_proto, pos, resp_len, comeback_delay); return 0; }
static void prism2_host_roaming(local_info_t *local) { struct hfa384x_join_request req; struct net_device *dev = local->dev; struct hfa384x_hostscan_result *selected, *entry; int i; unsigned long flags; if (local->last_join_time && time_before(jiffies, local->last_join_time + 10 * HZ)) { PDEBUG(DEBUG_EXTRA, "%s: last join request has not yet been " "completed - waiting for it before issuing new one\n", dev->name); return; } /* ScanResults are sorted: first ESS results in decreasing signal * quality then IBSS results in similar order. * Trivial roaming policy: just select the first entry. * This could probably be improved by adding hysteresis to limit * number of handoffs, etc. * * Could do periodic RID_SCANREQUEST or Inquire F101 to get new * ScanResults */ spin_lock_irqsave(&local->lock, flags); if (local->last_scan_results == NULL || local->last_scan_results_count == 0) { spin_unlock_irqrestore(&local->lock, flags); PDEBUG(DEBUG_EXTRA, "%s: no scan results for host roaming\n", dev->name); return; } selected = &local->last_scan_results[0]; if (local->preferred_ap[0] || local->preferred_ap[1] || local->preferred_ap[2] || local->preferred_ap[3] || local->preferred_ap[4] || local->preferred_ap[5]) { /* Try to find preferred AP */ PDEBUG(DEBUG_EXTRA, "%s: Preferred AP BSSID " MACSTR "\n", dev->name, MAC2STR(local->preferred_ap)); for (i = 0; i < local->last_scan_results_count; i++) { entry = &local->last_scan_results[i]; if (memcmp(local->preferred_ap, entry->bssid, 6) == 0) { PDEBUG(DEBUG_EXTRA, "%s: using preferred AP " "selection\n", dev->name); selected = entry; break; } } } memcpy(req.bssid, selected->bssid, 6); req.channel = selected->chid; spin_unlock_irqrestore(&local->lock, flags); PDEBUG(DEBUG_EXTRA, "%s: JoinRequest: BSSID=" MACSTR " channel=%d\n", dev->name, MAC2STR(req.bssid), le16_to_cpu(req.channel)); if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req, sizeof(req))) { printk(KERN_DEBUG "%s: JoinRequest failed\n", dev->name); } local->last_join_time = jiffies; }
int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, size_t buf_len ) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; struct ifreq ifr; int ret = 0; if (os_strcasecmp(cmd, "STOP") == 0) { linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0); wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); } else if (os_strcasecmp(cmd, "START") == 0) { linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1); wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); } else if (os_strcasecmp(cmd, "RELOAD") == 0) { wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); } else if (os_strncasecmp(cmd, "POWERMODE ", 10) == 0) { int mode; mode = atoi(cmd + 10); ret = wpa_driver_set_power_save(priv, mode); if (ret < 0) { wpa_driver_send_hang_msg(drv); } else { g_power_mode = mode; g_drv_errors = 0; } } else if (os_strncasecmp(cmd, "GETPOWER", 8) == 0) { ret = os_snprintf(buf, buf_len, "POWERMODE = %d\n", g_power_mode); } else if (os_strncasecmp(cmd, "BTCOEXMODE ", 11) == 0) { int mode = atoi(cmd + 11); if (mode == BLUETOOTH_COEXISTENCE_MODE_DISABLED) { /* disable BT-coex */ ret = wpa_driver_toggle_btcoex_state('0'); } else if (mode == BLUETOOTH_COEXISTENCE_MODE_SENSE) { /* enable BT-coex */ ret = wpa_driver_toggle_btcoex_state('1'); } else { wpa_printf(MSG_DEBUG, "invalid btcoex mode: %d", mode); ret = -1; } } else if (os_strcasecmp(cmd, "MACADDR") == 0) { u8 macaddr[ETH_ALEN] = {}; ret = linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, macaddr); if (!ret) ret = os_snprintf(buf, buf_len, "Macaddr = " MACSTR "\n", MAC2STR(macaddr)); } else if( os_strncasecmp(cmd, "RXFILTER-ADD ", 13) == 0 ) { int i = nl80211_parse_wowlan_trigger_nr(cmd + 13); if(i < 0) return i; return nl80211_toggle_wowlan_trigger(bss, i, 1); } else if( os_strncasecmp(cmd, "RXFILTER-REMOVE ", 16) == 0 ) { int i = nl80211_parse_wowlan_trigger_nr(cmd + 16); if(i < 0) return i; return nl80211_toggle_wowlan_trigger(bss, i, 0); } else if( os_strcasecmp(cmd, "RXFILTER-START") == 0 ) { return nl80211_set_wowlan_triggers(bss, 1); } else if( os_strcasecmp(cmd, "RXFILTER-STOP") == 0 ) { return nl80211_set_wowlan_triggers(bss, 0); } else if( os_strncasecmp(cmd, "DROPBCAST", 9) == 0 ) { char *value = cmd + 10; if (!os_strcasecmp(value, "ENABLE") || !os_strcasecmp(value, "1")) { ret = nl80211_toggle_dropbcast(1); } else if (!os_strcasecmp(value, "DISABLE") || !os_strcasecmp(value, "0")) { ret = nl80211_toggle_dropbcast(0); } else if (!os_strcasecmp(value, "GET") || !os_strlen(value)) { ret = nl80211_dropbcast_get(buf, buf_len); } else { wpa_printf(MSG_ERROR, "Invalid parameter for DROPBCAST: %s", value); ret = -1; } } else if( os_strncasecmp(cmd, "SETBAND ", 8) == 0 ) { int val = atoi(cmd + 8); ret = 0; if ( val < 0 || val > 2 ) ret = -1; } else { wpa_printf(MSG_INFO, "%s: Unsupported command %s", __func__, cmd); } return ret; }
static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) { const struct wps_credential *cred = ctx; FILE *oconf, *nconf; size_t len, i; char *tmp_fname; char buf[1024]; int multi_bss; int wpa; if (hapd->wps == NULL) return 0; wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", cred->cred_attr, cred->cred_attr_len); wpa_printf(MSG_DEBUG, "WPS: Received new AP Settings"); wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len); wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x", cred->auth_type); wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type); wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx); wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", cred->key, cred->key_len); wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(cred->mac_addr)); if ((hapd->conf->wps_cred_processing == 1 || hapd->conf->wps_cred_processing == 2) && cred->cred_attr) { hapd_new_ap_event(hapd, cred->cred_attr, cred->cred_attr_len); } else if (hapd->conf->wps_cred_processing == 1 || hapd->conf->wps_cred_processing == 2) { struct wpabuf *attr; attr = wpabuf_alloc(200); if (attr && wps_build_credential_wrap(attr, cred) == 0) hapd_new_ap_event(hapd, wpabuf_head_u8(attr), wpabuf_len(attr)); wpabuf_free(attr); } else wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS); if (hapd->conf->wps_cred_processing == 1) return 0; os_memcpy(hapd->wps->ssid, cred->ssid, cred->ssid_len); hapd->wps->ssid_len = cred->ssid_len; hapd->wps->encr_types = cred->encr_type; hapd->wps->auth_types = cred->auth_type; if (cred->key_len == 0) { os_free(hapd->wps->network_key); hapd->wps->network_key = NULL; hapd->wps->network_key_len = 0; } else { if (hapd->wps->network_key == NULL || hapd->wps->network_key_len < cred->key_len) { hapd->wps->network_key_len = 0; os_free(hapd->wps->network_key); hapd->wps->network_key = os_malloc(cred->key_len); if (hapd->wps->network_key == NULL) return -1; } hapd->wps->network_key_len = cred->key_len; os_memcpy(hapd->wps->network_key, cred->key, cred->key_len); } hapd->wps->wps_state = WPS_STATE_CONFIGURED; if (hapd->iface->config_fname == NULL) return hapd_wps_reconfig_in_memory(hapd, cred); len = os_strlen(hapd->iface->config_fname) + 5; tmp_fname = os_malloc(len); if (tmp_fname == NULL) return -1; os_snprintf(tmp_fname, len, "%s-new", hapd->iface->config_fname); oconf = fopen(hapd->iface->config_fname, "r"); if (oconf == NULL) { wpa_printf(MSG_WARNING, "WPS: Could not open current " "configuration file"); os_free(tmp_fname); return -1; } nconf = fopen(tmp_fname, "w"); if (nconf == NULL) { wpa_printf(MSG_WARNING, "WPS: Could not write updated " "configuration file"); os_free(tmp_fname); fclose(oconf); return -1; } fprintf(nconf, "# WPS configuration - START\n"); fprintf(nconf, "wps_state=2\n"); if (is_hex(cred->ssid, cred->ssid_len)) { fprintf(nconf, "ssid2="); for (i = 0; i < cred->ssid_len; i++) fprintf(nconf, "%02x", cred->ssid[i]); fprintf(nconf, "\n"); } else { fprintf(nconf, "ssid="); for (i = 0; i < cred->ssid_len; i++) fputc(cred->ssid[i], nconf); fprintf(nconf, "\n"); } if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) && (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))) wpa = 3; else if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) wpa = 2; else if (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)) wpa = 1; else wpa = 0; if (wpa) { char *prefix; fprintf(nconf, "wpa=%d\n", wpa); fprintf(nconf, "wpa_key_mgmt="); prefix = ""; if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA)) { fprintf(nconf, "WPA-EAP"); prefix = " "; } if (cred->auth_type & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) fprintf(nconf, "%sWPA-PSK", prefix); fprintf(nconf, "\n"); fprintf(nconf, "wpa_pairwise="); prefix = ""; if (cred->encr_type & WPS_ENCR_AES) { fprintf(nconf, "CCMP"); prefix = " "; } if (cred->encr_type & WPS_ENCR_TKIP) { fprintf(nconf, "%sTKIP", prefix); } fprintf(nconf, "\n"); if (cred->key_len >= 8 && cred->key_len < 64) { fprintf(nconf, "wpa_passphrase="); for (i = 0; i < cred->key_len; i++) fputc(cred->key[i], nconf); fprintf(nconf, "\n"); } else if (cred->key_len == 64) { fprintf(nconf, "wpa_psk="); for (i = 0; i < cred->key_len; i++) fputc(cred->key[i], nconf); fprintf(nconf, "\n"); } else { wpa_printf(MSG_WARNING, "WPS: Invalid key length %lu " "for WPA/WPA2", (unsigned long) cred->key_len); } fprintf(nconf, "auth_algs=1\n"); } else { if ((cred->auth_type & WPS_AUTH_OPEN) && (cred->auth_type & WPS_AUTH_SHARED)) fprintf(nconf, "auth_algs=3\n"); else if (cred->auth_type & WPS_AUTH_SHARED) fprintf(nconf, "auth_algs=2\n"); else fprintf(nconf, "auth_algs=1\n"); if (cred->encr_type & WPS_ENCR_WEP && cred->key_idx <= 4) { int key_idx = cred->key_idx; if (key_idx) key_idx--; fprintf(nconf, "wep_default_key=%d\n", key_idx); fprintf(nconf, "wep_key%d=", key_idx); if (cred->key_len == 10 || cred->key_len == 26) { /* WEP key as a hex string */ for (i = 0; i < cred->key_len; i++) fputc(cred->key[i], nconf); } else { /* Raw WEP key; convert to hex */ for (i = 0; i < cred->key_len; i++) fprintf(nconf, "%02x", cred->key[i]); } fprintf(nconf, "\n"); } } fprintf(nconf, "# WPS configuration - END\n"); multi_bss = 0; while (fgets(buf, sizeof(buf), oconf)) { if (os_strncmp(buf, "bss=", 4) == 0) multi_bss = 1; if (!multi_bss && (str_starts(buf, "ssid=") || str_starts(buf, "ssid2=") || str_starts(buf, "auth_algs=") || str_starts(buf, "wep_default_key=") || str_starts(buf, "wep_key") || str_starts(buf, "wps_state=") || str_starts(buf, "wpa=") || str_starts(buf, "wpa_psk=") || str_starts(buf, "wpa_pairwise=") || str_starts(buf, "rsn_pairwise=") || str_starts(buf, "wpa_key_mgmt=") || str_starts(buf, "wpa_passphrase="))) { fprintf(nconf, "#WPS# %s", buf); } else fprintf(nconf, "%s", buf); } fclose(nconf); fclose(oconf); if (rename(tmp_fname, hapd->iface->config_fname) < 0) { wpa_printf(MSG_WARNING, "WPS: Failed to rename the updated " "configuration file: %s", strerror(errno)); os_free(tmp_fname); return -1; } os_free(tmp_fname); /* Schedule configuration reload after short period of time to allow * EAP-WSC to be finished. */ eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface, NULL); wpa_printf(MSG_DEBUG, "WPS: AP configuration updated"); return 0; }
VOID kalP2PIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb) { #define DBG_P2P_MGMT_FRAME_INDICATION 0 P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; INT_32 i4Freq = 0; UINT_8 ucChnlNum = 0; #if DBG_P2P_MGMT_FRAME_INDICATION P_WLAN_MAC_HEADER_T prWlanHeader = (P_WLAN_MAC_HEADER_T) NULL; #endif do { if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { ASSERT(FALSE); break; } prGlueP2pInfo = prGlueInfo->prP2PInfo; ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; #if DBG_P2P_MGMT_FRAME_INDICATION prWlanHeader = (P_WLAN_MAC_HEADER_T) prSwRfb->pvHeader; switch (prWlanHeader->u2FrameCtrl) { case MAC_FRAME_PROBE_REQ: DBGLOG(P2P, TRACE, ("RX Probe Req at channel %d ", ucChnlNum)); break; case MAC_FRAME_PROBE_RSP: DBGLOG(P2P, TRACE, ("RX Probe Rsp at channel %d ", ucChnlNum)); break; case MAC_FRAME_ACTION: DBGLOG(P2P, TRACE, ("RX Action frame at channel %d ", ucChnlNum)); break; default: DBGLOG(P2P, TRACE, ("RX Packet:%d at channel %d ", prWlanHeader->u2FrameCtrl, ucChnlNum)); break; } DBGLOG(P2P, TRACE, ("from: " MACSTR "\n", MAC2STR(prWlanHeader->aucAddr2))); #endif i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) cfg80211_rx_mgmt(&prGlueP2pInfo->wdev, /* struct net_device * dev, */ #else cfg80211_rx_mgmt(prGlueP2pInfo->prDevHandler, /* struct net_device * dev, */ #endif /* LINUX_VERSION_CODE */ i4Freq, RCPI_TO_dBm(prSwRfb->prHifRxHdr->ucRcpi), prSwRfb->pvHeader, prSwRfb->u2PacketLen, GFP_KERNEL); #else cfg80211_rx_mgmt(prGlueP2pInfo->prDevHandler, /* struct net_device * dev, */ i4Freq, prSwRfb->pvHeader, prSwRfb->u2PacketLen, GFP_KERNEL); #endif } while (FALSE); } /* kalP2PIndicateRxMgmtFrame */
int mtk_cfg80211_get_station ( struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_info *sinfo ) { P_GLUE_INFO_T prGlueInfo = NULL; WLAN_STATUS rStatus; PARAM_MAC_ADDRESS arBssid; UINT_32 u4BufLen, u4Rate; INT_32 i4Rssi; prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ASSERT(prGlueInfo); kalMemZero(arBssid, MAC_ADDR_LEN); wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &u4BufLen); /* 1. check BSSID */ if(UNEQUAL_MAC_ADDR(arBssid, mac)) { /* wrong MAC address */ DBGLOG(REQ, WARN, ("incorrect BSSID: ["MACSTR"] currently connected BSSID["MACSTR"]\n", MAC2STR(mac), MAC2STR(arBssid))); return -ENOENT; } /* 2. fill TX rate */ rStatus = kalIoctl(prGlueInfo, wlanoidQueryLinkSpeed, &u4Rate, sizeof(u4Rate), TRUE, FALSE, FALSE, FALSE, &u4BufLen); if (rStatus != WLAN_STATUS_SUCCESS) { DBGLOG(REQ, WARN, ("unable to retrieve link speed\n")); } else { sinfo->filled |= STATION_INFO_TX_BITRATE; sinfo->txrate.legacy = u4Rate / 1000; /* convert from 100bps to 100kbps */ } if(prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { /* not connected */ DBGLOG(REQ, WARN, ("not yet connected\n")); } else { /* 3. fill RSSI */ rStatus = kalIoctl(prGlueInfo, wlanoidQueryRssi, &i4Rssi, sizeof(i4Rssi), TRUE, FALSE, FALSE, FALSE, &u4BufLen); if (rStatus != WLAN_STATUS_SUCCESS) { DBGLOG(REQ, WARN, ("unable to retrieve link speed\n")); } else { #if RSSI_ENHANCE i4Rssi = processRssiHistory(i4Rssi); #endif sinfo->filled |= STATION_INFO_SIGNAL; sinfo->signal = i4Rssi; /* dBm */ } } return 0; }
static void sme_send_authentication(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid, int start) { struct wpa_driver_auth_params params; struct wpa_ssid *old_ssid; #ifdef CONFIG_IEEE80211R const u8 *ie; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211R const u8 *md = NULL; #endif /* CONFIG_IEEE80211R */ int i, bssid_changed; struct wpabuf *resp = NULL; u8 ext_capab[10]; int ext_capab_len; if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " "the network"); wpas_connect_work_done(wpa_s); return; } wpa_s->current_bss = bss; os_memset(¶ms, 0, sizeof(params)); wpa_s->reassociate = 0; params.freq = bss->freq; params.bssid = bss->bssid; params.ssid = bss->ssid; params.ssid_len = bss->ssid_len; params.p2p = ssid->p2p_group; if (wpa_s->sme.ssid_len != params.ssid_len || os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) wpa_s->sme.prev_bssid_set = 0; wpa_s->sme.freq = params.freq; os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); wpa_s->sme.ssid_len = params.ssid_len; params.auth_alg = WPA_AUTH_ALG_OPEN; #ifdef IEEE8021X_EAPOL if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (ssid->leap) { if (ssid->non_leap == 0) params.auth_alg = WPA_AUTH_ALG_LEAP; else params.auth_alg |= WPA_AUTH_ALG_LEAP; } } #endif /* IEEE8021X_EAPOL */ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", params.auth_alg); if (ssid->auth_alg) { params.auth_alg = ssid->auth_alg; wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " "0x%x", params.auth_alg); } #ifdef CONFIG_SAE if (wpa_key_mgmt_sae(ssid->key_mgmt)) { const u8 *rsn; struct wpa_ie_data ied; rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0) { if (wpa_key_mgmt_sae(ied.key_mgmt)) { wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg"); params.auth_alg = WPA_AUTH_ALG_SAE; } } } #endif /* CONFIG_SAE */ for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i]) params.wep_key[i] = ssid->wep_key[i]; params.wep_key_len[i] = ssid->wep_key_len[i]; } params.wep_tx_keyidx = ssid->wep_tx_keyidx; bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); if (bssid_changed) wpas_notify_bssid_changed(wpa_s); if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt)) { int try_opportunistic; try_opportunistic = (ssid->proactive_key_caching < 0 ? wpa_s->conf->okc : ssid->proactive_key_caching) && (ssid->proto & WPA_PROTO_RSN); if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, wpa_s->current_ssid, try_opportunistic) == 0) eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites"); wpas_connect_work_done(wpa_s); return; } } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) { /* * Both WPA and non-WPA IEEE 802.1X enabled in configuration - * use non-WPA since the scan results did not indicate that the * AP is using WPA or WPA2. */ wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites (no " "scan results)"); wpas_connect_work_done(wpa_s); return; } #ifdef CONFIG_WPS } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { struct wpabuf *wps_ie; wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_s->sme.assoc_req_ie)) { wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), wpa_s->sme.assoc_req_ie_len); } else wpa_s->sme.assoc_req_ie_len = 0; wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); #endif /* CONFIG_WPS */ } else { wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } #ifdef CONFIG_IEEE80211R ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) md = ie + 2; wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) { if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; *pos++ = WLAN_EID_MOBILITY_DOMAIN; *pos++ = sizeof(*mdie); mdie = (struct rsn_mdie *) pos; os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; wpa_s->sme.assoc_req_ie_len += 5; } if (wpa_s->sme.ft_used && os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && wpa_sm_has_ptk(wpa_s->wpa)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT " "over-the-air"); params.auth_alg = WPA_AUTH_ALG_FT; params.ie = wpa_s->sme.ft_ies; params.ie_len = wpa_s->sme.ft_ies_len; } } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W wpa_s->sme.mfp = ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? wpa_s->conf->pmf : ssid->ieee80211w; if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data _ie; if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && _ie.capabilities & (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports " "MFP: require MFP"); wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; } } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P if (wpa_s->global->p2p) { u8 *pos; size_t len; int res; pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, ssid->p2p_group); if (res >= 0) wpa_s->sme.assoc_req_ie_len += res; } #endif /* CONFIG_P2P */ #ifdef CONFIG_HS20 if (is_hs20_network(wpa_s, ssid, bss)) { struct wpabuf *hs20; hs20 = wpabuf_alloc(20); if (hs20) { int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid); wpas_hs20_add_indication(hs20, pps_mo_id); os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpabuf_head(hs20), wpabuf_len(hs20)); wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20); wpabuf_free(hs20); } } #endif /* CONFIG_HS20 */ ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab); if (ext_capab_len > 0) { u8 *pos = wpa_s->sme.assoc_req_ie; if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) pos += 2 + pos[1]; os_memmove(pos + ext_capab_len, pos, wpa_s->sme.assoc_req_ie_len - (pos - wpa_s->sme.assoc_req_ie)); wpa_s->sme.assoc_req_ie_len += ext_capab_len; os_memcpy(pos, ext_capab, ext_capab_len); } #ifdef CONFIG_SAE if (params.auth_alg == WPA_AUTH_ALG_SAE) { if (start) resp = sme_auth_build_sae_commit(wpa_s, ssid, bss->bssid); else resp = sme_auth_build_sae_confirm(wpa_s); if (resp == NULL) { wpas_connect_work_done(wpa_s); return; } params.sae_data = wpabuf_head(resp); params.sae_data_len = wpabuf_len(resp); wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED; } #endif /* CONFIG_SAE */ wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_cancel_scan(wpa_s); wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); wpa_clear_keys(wpa_s, bss->bssid); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); old_ssid = wpa_s->current_ssid; wpa_s->current_ssid = ssid; wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); wpa_supplicant_initiate_eapol(wpa_s); if (old_ssid != wpa_s->current_ssid) wpas_notify_network_changed(wpa_s); #ifdef CONFIG_P2P /* * If multi-channel concurrency is not supported, check for any * frequency conflict. In case of any frequency conflict, remove the * least prioritized connection. */ if (wpa_s->num_multichan_concurrent < 2) { int freq, num; num = get_shared_radio_freqs(wpa_s, &freq, 1); if (num > 0 && freq > 0 && freq != params.freq) { wpa_printf(MSG_DEBUG, "Conflicting frequency found (%d != %d)", freq, params.freq); if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq, ssid) < 0) { wpas_connection_failed(wpa_s, bss->bssid, 0); wpa_supplicant_mark_disassoc(wpa_s); wpabuf_free(resp); wpas_connect_work_done(wpa_s); return; } } } #endif /* CONFIG_P2P */ wpa_s->sme.auth_alg = params.auth_alg; if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " "driver failed"); wpas_connection_failed(wpa_s, bss->bssid, 1); wpa_supplicant_mark_disassoc(wpa_s); wpabuf_free(resp); wpas_connect_work_done(wpa_s); return; } eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, NULL); /* * Association will be started based on the authentication event from * the driver. */ wpabuf_free(resp); }
static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e, const u8 *eap, size_t len) { struct radius_msg *msg; char buf[128]; const struct eap_hdr *hdr; const u8 *pos; wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS " "packet"); e->radius_identifier = radius_client_get_id(e->radius); msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, e->radius_identifier); if (msg == NULL) { printf("Could not create net RADIUS packet\n"); return; } radius_msg_make_authenticator(msg, (u8 *) e, sizeof(*e)); hdr = (const struct eap_hdr *) eap; pos = (const u8 *) (hdr + 1); if (len > sizeof(*hdr) && hdr->code == EAP_CODE_RESPONSE && pos[0] == EAP_TYPE_IDENTITY) { pos++; os_free(e->eap_identity); e->eap_identity_len = len - sizeof(*hdr) - 1; e->eap_identity = os_malloc(e->eap_identity_len); if (e->eap_identity) { os_memcpy(e->eap_identity, pos, e->eap_identity_len); wpa_hexdump(MSG_DEBUG, "Learned identity from " "EAP-Response-Identity", e->eap_identity, e->eap_identity_len); } } if (e->eap_identity && !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, e->eap_identity, e->eap_identity_len)) { printf("Could not add User-Name\n"); goto fail; } if (!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, (u8 *) &e->own_ip_addr, 4)) { printf("Could not add NAS-IP-Address\n"); goto fail; } os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, MAC2STR(e->wpa_s->own_addr)); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, (u8 *) buf, os_strlen(buf))) { printf("Could not add Calling-Station-Id\n"); goto fail; } /* TODO: should probably check MTU from driver config; 2304 is max for * IEEE 802.11, but use 1400 to avoid problems with too large packets */ if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) { printf("Could not add Framed-MTU\n"); goto fail; } if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { printf("Could not add NAS-Port-Type\n"); goto fail; } os_snprintf(buf, sizeof(buf), "%s", e->connect_info); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, (u8 *) buf, os_strlen(buf))) { printf("Could not add Connect-Info\n"); goto fail; } if (eap && !radius_msg_add_eap(msg, eap, len)) { printf("Could not add EAP-Message\n"); goto fail; } /* State attribute must be copied if and only if this packet is * Access-Request reply to the previous Access-Challenge */ if (e->last_recv_radius && e->last_recv_radius->hdr->code == RADIUS_CODE_ACCESS_CHALLENGE) { int res = radius_msg_copy_attr(msg, e->last_recv_radius, RADIUS_ATTR_STATE); if (res < 0) { printf("Could not copy State attribute from previous " "Access-Challenge\n"); goto fail; } if (res > 0) { wpa_printf(MSG_DEBUG, " Copied RADIUS State " "Attribute"); } } radius_client_send(e->radius, msg, RADIUS_AUTH, e->wpa_s->own_addr); return; fail: radius_msg_free(msg); os_free(msg); }
void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, const u8 *bssid, u16 auth_type) { struct wpa_driver_associate_params params; struct ieee802_11_elems elems; #ifdef CONFIG_HT_OVERRIDES struct ieee80211_ht_capabilities htcaps; struct ieee80211_ht_capabilities htcaps_mask; #endif /* CONFIG_HT_OVERRIDES */ #ifdef CONFIG_VHT_OVERRIDES struct ieee80211_vht_capabilities vhtcaps; struct ieee80211_vht_capabilities vhtcaps_mask; #endif /* CONFIG_VHT_OVERRIDES */ os_memset(¶ms, 0, sizeof(params)); params.bssid = bssid; params.ssid = wpa_s->sme.ssid; params.ssid_len = wpa_s->sme.ssid_len; params.freq = wpa_s->sme.freq; params.bg_scan_period = wpa_s->current_ssid ? wpa_s->current_ssid->bg_scan_period : -1; params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? wpa_s->sme.assoc_req_ie : NULL; params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; params.pairwise_suite = wpa_s->pairwise_cipher; params.group_suite = wpa_s->group_cipher; #ifdef CONFIG_HT_OVERRIDES os_memset(&htcaps, 0, sizeof(htcaps)); os_memset(&htcaps_mask, 0, sizeof(htcaps_mask)); params.htcaps = (u8 *) &htcaps; params.htcaps_mask = (u8 *) &htcaps_mask; wpa_supplicant_apply_ht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); #endif /* CONFIG_HT_OVERRIDES */ #ifdef CONFIG_VHT_OVERRIDES os_memset(&vhtcaps, 0, sizeof(vhtcaps)); os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask)); params.vhtcaps = &vhtcaps; params.vhtcaps_mask = &vhtcaps_mask; wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); #endif /* CONFIG_VHT_OVERRIDES */ #ifdef CONFIG_IEEE80211R if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) { params.wpa_ie = wpa_s->sme.ft_ies; params.wpa_ie_len = wpa_s->sme.ft_ies_len; } #endif /* CONFIG_IEEE80211R */ params.mode = mode; params.mgmt_frame_protection = wpa_s->sme.mfp; if (wpa_s->sme.prev_bssid_set) params.prev_bssid = wpa_s->sme.prev_bssid; wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "", params.freq); wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); if (params.wpa_ie == NULL || ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0) < 0) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!"); os_memset(&elems, 0, sizeof(elems)); } if (elems.rsn_ie) { params.wpa_proto = WPA_PROTO_RSN; wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2, elems.rsn_ie_len + 2); } else if (elems.wpa_ie) { params.wpa_proto = WPA_PROTO_WPA; wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2, elems.wpa_ie_len + 2); } else if (elems.osen) { params.wpa_proto = WPA_PROTO_OSEN; wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.osen - 2, elems.osen_len + 2); } else wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group) params.p2p = 1; if (wpa_s->parent->set_sta_uapsd) params.uapsd = wpa_s->parent->sta_uapsd; else params.uapsd = -1; if (wpa_drv_associate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the " "driver failed"); wpas_connection_failed(wpa_s, wpa_s->pending_bssid, 1); wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); return; } eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s, NULL); }
static struct wpa_bss * compare_scan_neighbor_results(struct wpa_supplicant *wpa_s) { u8 i; struct wpa_bss *bss = wpa_s->current_bss; struct wpa_bss *target; if (!bss) return 0; wpa_printf(MSG_DEBUG, "WNM: Current BSS " MACSTR " RSSI %d", MAC2STR(wpa_s->bssid), bss->level); for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) { struct neighbor_report *nei; nei = &wpa_s->wnm_neighbor_report_elements[i]; if (nei->preference_present && nei->preference == 0) { wpa_printf(MSG_DEBUG, "Skip excluded BSS " MACSTR, MAC2STR(nei->bssid)); continue; } target = wpa_bss_get_bssid(wpa_s, nei->bssid); if (!target) { wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR " (pref %d) not found in scan results", MAC2STR(nei->bssid), nei->preference_present ? nei->preference : -1); continue; } if (bss->ssid_len != target->ssid_len || os_memcmp(bss->ssid, target->ssid, bss->ssid_len) != 0) { /* * TODO: Could consider allowing transition to another * ESS if PMF was enabled for the association. */ wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR " (pref %d) in different ESS", MAC2STR(nei->bssid), nei->preference_present ? nei->preference : -1); continue; } if (target->level < bss->level && target->level < -80) { wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR " (pref %d) does not have sufficient signal level (%d)", MAC2STR(nei->bssid), nei->preference_present ? nei->preference : -1, target->level); continue; } wpa_printf(MSG_DEBUG, "WNM: Found an acceptable preferred transition candidate BSS " MACSTR " (RSSI %d)", MAC2STR(nei->bssid), target->level); return target; } return NULL; }
/** * ap_handle_timer - Per STA timer handler * @eloop_ctx: struct hostapd_data * * @timeout_ctx: struct sta_info * * * This function is called to check station activity and to remove inactive * stations. */ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) { struct hostapd_data *hapd = eloop_ctx; struct sta_info *sta = timeout_ctx; unsigned long next_time = 0; int reason; wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d", __func__, MAC2STR(sta->addr), sta->flags, sta->timeout_next); if (sta->timeout_next == STA_REMOVE) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deauthenticated due to " "local deauth request"); ap_free_sta(hapd, sta); return; } if ((sta->flags & WLAN_STA_ASSOC) && (sta->timeout_next == STA_NULLFUNC || sta->timeout_next == STA_DISASSOC)) { int inactive_sec; /* * Add random value to timeout so that we don't end up bouncing * all stations at the same time if we have lots of associated * stations that are idle (but keep re-associating). */ int fuzz = os_random() % 20; inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr); if (inactive_sec == -1) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Check inactivity: Could not " "get station info from kernel driver for " MACSTR, MAC2STR(sta->addr)); /* * The driver may not support this functionality. * Anyway, try again after the next inactivity timeout, * but do not disconnect the station now. */ next_time = hapd->conf->ap_max_inactivity + fuzz; } else if (inactive_sec == -ENOENT) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " has lost its driver entry", MAC2STR(sta->addr)); /* Avoid sending client probe on removed client */ sta->timeout_next = STA_DISASSOC; goto skip_poll; } else if (inactive_sec < hapd->conf->ap_max_inactivity) { /* station activity detected; reset timeout state */ wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " has been active %is ago", MAC2STR(sta->addr), inactive_sec); sta->timeout_next = STA_NULLFUNC; next_time = hapd->conf->ap_max_inactivity + fuzz - inactive_sec; } else { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " has been " "inactive too long: %d sec, max allowed: %d", MAC2STR(sta->addr), inactive_sec, hapd->conf->ap_max_inactivity); if (hapd->conf->skip_inactivity_poll) sta->timeout_next = STA_DISASSOC; } } if ((sta->flags & WLAN_STA_ASSOC) && sta->timeout_next == STA_DISASSOC && !(sta->flags & WLAN_STA_PENDING_POLL) && !hapd->conf->skip_inactivity_poll) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " has ACKed data poll", MAC2STR(sta->addr)); /* data nullfunc frame poll did not produce TX errors; assume * station ACKed it */ sta->timeout_next = STA_NULLFUNC; next_time = hapd->conf->ap_max_inactivity; } skip_poll: if (next_time) { wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " "for " MACSTR " (%lu seconds)", __func__, MAC2STR(sta->addr), next_time); eloop_register_timeout(next_time, 0, ap_handle_timer, hapd, sta); return; } if (sta->timeout_next == STA_NULLFUNC && (sta->flags & WLAN_STA_ASSOC)) { wpa_printf(MSG_DEBUG, " Polling STA"); sta->flags |= WLAN_STA_PENDING_POLL; hostapd_drv_poll_client(hapd, hapd->own_addr, sta->addr, sta->flags & WLAN_STA_WMM); } else if (sta->timeout_next != STA_REMOVE) { int deauth = sta->timeout_next == STA_DEAUTH; wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Timeout, sending %s info to STA " MACSTR, deauth ? "deauthentication" : "disassociation", MAC2STR(sta->addr)); if (deauth) { hostapd_drv_sta_deauth( hapd, sta->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); } else { reason = (sta->timeout_next == STA_DISASSOC) ? WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY : WLAN_REASON_PREV_AUTH_NOT_VALID; hostapd_drv_sta_disassoc(hapd, sta->addr, reason); } } switch (sta->timeout_next) { case STA_NULLFUNC: sta->timeout_next = STA_DISASSOC; wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " "for " MACSTR " (%d seconds - AP_DISASSOC_DELAY)", __func__, MAC2STR(sta->addr), AP_DISASSOC_DELAY); eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer, hapd, sta); break; case STA_DISASSOC: case STA_DISASSOC_FROM_CLI: ap_sta_set_authorized(hapd, sta, 0); sta->flags &= ~WLAN_STA_ASSOC; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); if (!sta->acct_terminate_cause) sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; accounting_sta_stop(hapd, sta); ieee802_1x_free_station(sta); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated due to " "inactivity"); reason = (sta->timeout_next == STA_DISASSOC) ? WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY : WLAN_REASON_PREV_AUTH_NOT_VALID; sta->timeout_next = STA_DEAUTH; wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " "for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)", __func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY); eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, hapd, sta); mlme_disassociate_indication(hapd, sta, reason); break; case STA_DEAUTH: case STA_REMOVE: hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deauthenticated due to " "inactivity (timer DEAUTH/REMOVE)"); if (!sta->acct_terminate_cause) sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; mlme_deauthenticate_indication( hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID); ap_free_sta(hapd, sta); break; } }
/* MLME-SLEEPMODE.request */ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s, u8 action, u16 intval, struct wpabuf *tfs_req) { struct ieee80211_mgmt *mgmt; int res; size_t len; struct wnm_sleep_element *wnmsleep_ie; u8 *wnmtfs_ie; u8 wnmsleep_ie_len; u16 wnmtfs_ie_len; /* possibly multiple IE(s) */ enum wnm_oper tfs_oper = action == 0 ? WNM_SLEEP_TFS_REQ_IE_ADD : WNM_SLEEP_TFS_REQ_IE_NONE; wpa_printf(MSG_DEBUG, "WNM: Request to send WNM-Sleep Mode Request " "action=%s to " MACSTR, action == 0 ? "enter" : "exit", MAC2STR(wpa_s->bssid)); /* WNM-Sleep Mode IE */ wnmsleep_ie_len = sizeof(struct wnm_sleep_element); wnmsleep_ie = os_zalloc(sizeof(struct wnm_sleep_element)); if (wnmsleep_ie == NULL) return -1; wnmsleep_ie->eid = WLAN_EID_WNMSLEEP; wnmsleep_ie->len = wnmsleep_ie_len - 2; wnmsleep_ie->action_type = action; wnmsleep_ie->status = WNM_STATUS_SLEEP_ACCEPT; wnmsleep_ie->intval = host_to_le16(intval); wpa_hexdump(MSG_DEBUG, "WNM: WNM-Sleep Mode element", (u8 *) wnmsleep_ie, wnmsleep_ie_len); /* TFS IE(s) */ if (tfs_req) { wnmtfs_ie_len = wpabuf_len(tfs_req); wnmtfs_ie = os_malloc(wnmtfs_ie_len); if (wnmtfs_ie == NULL) { os_free(wnmsleep_ie); return -1; } os_memcpy(wnmtfs_ie, wpabuf_head(tfs_req), wnmtfs_ie_len); } else { wnmtfs_ie = os_zalloc(MAX_TFS_IE_LEN); if (wnmtfs_ie == NULL) { os_free(wnmsleep_ie); return -1; } if (ieee80211_11_get_tfs_ie(wpa_s, wnmtfs_ie, &wnmtfs_ie_len, tfs_oper)) { wnmtfs_ie_len = 0; os_free(wnmtfs_ie); wnmtfs_ie = NULL; } } wpa_hexdump(MSG_DEBUG, "WNM: TFS Request element", (u8 *) wnmtfs_ie, wnmtfs_ie_len); mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + wnmtfs_ie_len); if (mgmt == NULL) { wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for " "WNM-Sleep Request action frame"); os_free(wnmsleep_ie); os_free(wnmtfs_ie); return -1; } os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN); os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN); mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION); mgmt->u.action.category = WLAN_ACTION_WNM; mgmt->u.action.u.wnm_sleep_req.action = WNM_SLEEP_MODE_REQ; mgmt->u.action.u.wnm_sleep_req.dialogtoken = 1; os_memcpy(mgmt->u.action.u.wnm_sleep_req.variable, wnmsleep_ie, wnmsleep_ie_len); /* copy TFS IE here */ if (wnmtfs_ie_len > 0) { os_memcpy(mgmt->u.action.u.wnm_sleep_req.variable + wnmsleep_ie_len, wnmtfs_ie, wnmtfs_ie_len); } len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_req) + wnmsleep_ie_len + wnmtfs_ie_len; res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, wpa_s->own_addr, wpa_s->bssid, &mgmt->u.action.category, len, 0); if (res < 0) wpa_printf(MSG_DEBUG, "Failed to send WNM-Sleep Request " "(action=%d, intval=%d)", action, intval); os_free(wnmsleep_ie); os_free(wnmtfs_ie); os_free(mgmt); return res; }
static struct ap_info *ap_ap_add(struct hostapd_iface *iface, const u8 *addr) { struct ap_info *ap; ap = os_zalloc(sizeof(struct ap_info)); if (ap == NULL) { return NULL; } /* initialize AP info data */ os_memcpy(ap->addr, addr, ETH_ALEN); ap_ap_list_add(iface, ap); iface->num_ap++; ap_ap_hash_add(iface, ap); if (iface->num_ap > iface->conf->ap_table_max_size && ap != ap->prev) { wpa_printf(MSG_DEBUG, "Removing the least recently used AP " MACSTR " from AP table", MAC2STR(ap->prev->addr)); ap_free_ap(iface, ap->prev); } return ap; }
/** * hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages * @msg: RADIUS response message * @req: RADIUS request message * @shared_secret: RADIUS shared secret * @shared_secret_len: Length of shared_secret in octets * @data: Context data (struct hostapd_data *) * Returns: RADIUS_RX_PROCESSED if RADIUS message was a reply to ACL query (and * was processed here) or RADIUS_RX_UNKNOWN if not. */ static RadiusRxResult hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, const u8 *shared_secret, size_t shared_secret_len, void *data) { struct hostapd_data *hapd = data; struct hostapd_acl_query_data *query, *prev; struct hostapd_cached_radius_acl *cache; struct radius_hdr *hdr = radius_msg_get_hdr(msg); query = hapd->acl_queries; prev = NULL; while (query) { if (query->radius_id == hdr->identifier) break; prev = query; query = query->next; } if (query == NULL) return RADIUS_RX_UNKNOWN; wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS " "message (id=%d)", query->radius_id); if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) { wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have " "correct authenticator - dropped\n"); return RADIUS_RX_INVALID_AUTHENTICATOR; } if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && hdr->code != RADIUS_CODE_ACCESS_REJECT) { wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL " "query", hdr->code); return RADIUS_RX_UNKNOWN; } /* Insert Accept/Reject info into ACL cache */ cache = os_zalloc(sizeof(*cache)); if (cache == NULL) { wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry"); goto done; } os_get_reltime(&cache->timestamp); os_memcpy(cache->addr, query->addr, sizeof(cache->addr)); if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) { u8 *buf; size_t len; if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, &cache->session_timeout) == 0) cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT; else cache->accepted = HOSTAPD_ACL_ACCEPT; if (radius_msg_get_attr_int32( msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, &cache->acct_interim_interval) == 0 && cache->acct_interim_interval < 60) { wpa_printf(MSG_DEBUG, "Ignored too small " "Acct-Interim-Interval %d for STA " MACSTR, cache->acct_interim_interval, MAC2STR(query->addr)); cache->acct_interim_interval = 0; } cache->vlan_id = radius_msg_get_vlanid(msg); decode_tunnel_passwords(hapd, shared_secret, shared_secret_len, msg, req, cache); if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &buf, &len, NULL) == 0) { cache->identity = os_zalloc(len + 1); if (cache->identity) os_memcpy(cache->identity, buf, len); } if (radius_msg_get_attr_ptr( msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, &buf, &len, NULL) == 0) { cache->radius_cui = os_zalloc(len + 1); if (cache->radius_cui) os_memcpy(cache->radius_cui, buf, len); } if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED && !cache->psk) cache->accepted = HOSTAPD_ACL_REJECT; if (cache->vlan_id && !hostapd_vlan_id_valid(hapd->conf->vlan, cache->vlan_id)) { hostapd_logger(hapd, query->addr, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO, "Invalid VLAN ID %d received from RADIUS server", cache->vlan_id); cache->vlan_id = 0; } if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED && !cache->vlan_id) cache->accepted = HOSTAPD_ACL_REJECT; } else cache->accepted = HOSTAPD_ACL_REJECT; cache->next = hapd->acl_cache; hapd->acl_cache = cache; #ifdef CONFIG_DRIVER_RADIUS_ACL hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted, cache->session_timeout); #else /* CONFIG_DRIVER_RADIUS_ACL */ #ifdef NEED_AP_MLME /* Re-send original authentication frame for 802.11 processing */ wpa_printf(MSG_DEBUG, "Re-sending authentication frame after " "successful RADIUS ACL query"); ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL); #endif /* NEED_AP_MLME */ #endif /* CONFIG_DRIVER_RADIUS_ACL */ done: if (prev == NULL) hapd->acl_queries = query->next; else prev->next = query->next; hostapd_acl_query_free(query); return RADIUS_RX_PROCESSED; }