static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx) { struct hostapd_data *hapd = eloop_ctx; struct sta_info *sta = timeout_ctx; u8 addr[ETH_ALEN]; if (!(sta->flags & WLAN_STA_AUTH)) { if (sta->flags & WLAN_STA_GAS) { wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA " "entry " MACSTR, MAC2STR(sta->addr)); ap_free_sta(hapd, sta); } return; } mlme_deauthenticate_indication(hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deauthenticated due to " "session timeout"); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT; os_memcpy(addr, sta->addr, ETH_ALEN); ap_free_sta(hapd, sta); hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); }
static void rsn_preauth_finished_cb(void *circle_ctx, void *timeout_ctx) { struct asd_data *wasd = circle_ctx; struct sta_info *sta = timeout_ctx; asd_printf(ASD_DEFAULT,MSG_DEBUG, "RSN: Removing pre-authentication STA entry for " MACSTR, MAC2STR(sta->addr)); //UpdateStaInfoToWSM(wasd, sta->addr, WID_DEL); if(ASD_WLAN[wasd->WlanID]!=NULL&&ASD_WLAN[wasd->WlanID]->balance_switch == 1&&ASD_WLAN[wasd->WlanID]->balance_method==1) ap_free_sta(wasd, sta,1); else ap_free_sta(wasd, sta,0); }
void mesh_auth_timer(void *eloop_ctx, void *user_data) { struct wpa_supplicant *wpa_s = eloop_ctx; struct sta_info *sta = user_data; if (sta->sae->state != SAE_ACCEPTED) { wpa_printf(MSG_DEBUG, "AUTH: Re-authenticate with " MACSTR " (attempt %d) ", MAC2STR(sta->addr), sta->sae_auth_retry); wpa_msg(wpa_s, MSG_INFO, MESH_SAE_AUTH_FAILURE "addr=" MACSTR, MAC2STR(sta->addr)); if (sta->sae_auth_retry < MESH_AUTH_RETRY) { mesh_rsn_auth_sae_sta(wpa_s, sta); } else { if (sta->sae_auth_retry > MESH_AUTH_RETRY) { ap_free_sta(wpa_s->ifmsh->bss[0], sta); return; } /* block the STA if exceeded the number of attempts */ wpa_mesh_set_plink_state(wpa_s, sta, PLINK_BLOCKED); sta->sae->state = SAE_NOTHING; if (wpa_s->mesh_auth_block_duration < MESH_AUTH_BLOCK_DURATION) wpa_s->mesh_auth_block_duration += 60; eloop_register_timeout(wpa_s->mesh_auth_block_duration, 0, mesh_auth_timer, wpa_s, sta); wpa_msg(wpa_s, MSG_INFO, MESH_SAE_AUTH_BLOCKED "addr=" MACSTR " duration=%d", MAC2STR(sta->addr), wpa_s->mesh_auth_block_duration); } sta->sae_auth_retry++; } }
static int rtl871x_del_sta(struct rtl871x_driver_data *drv, u8 *addr) { struct hostapd_data *hapd = drv->hapd; #if 1 drv_event_disassoc(hapd, addr); #else struct sta_info *sta; sta = ap_get_sta(hapd, addr); if (sta != NULL) { sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); ap_free_sta(hapd, sta); } else { wpa_printf(MSG_DEBUG, "Disassociation notification for " "unknown STA " MACSTR, MAC2STR(addr)); } #endif return 0; }
static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd) { struct sta_info *sta; hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated"); wpa_auth_countermeasures_start(hapd->wpa_auth); hapd->tkip_countermeasures = 1; hostapd_drv_set_countermeasures(hapd, 1); wpa_gtk_rekey(hapd->wpa_auth); eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop, hapd, NULL); while ((sta = hapd->sta_list)) { sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET; if (sta->flags & WLAN_STA_AUTH) { mlme_deauthenticate_indication( hapd, sta, WLAN_REASON_MICHAEL_MIC_FAILURE); } hostapd_drv_sta_deauth(hapd, sta->addr, WLAN_REASON_MICHAEL_MIC_FAILURE); ap_sta_cancel_priority(hapd, sta); ap_free_sta(hapd, sta); } }
static void handle_deauth(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len) { struct sta_info *sta; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) { printf("handle_deauth - too short payload (len=%lu)\n", (unsigned long) len); return; } wpa_printf(MSG_DEBUG, "deauthentication: STA=" MACSTR " reason_code=%d", MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code)); sta = ap_get_sta(hapd, mgmt->sa); if (sta == NULL) { printf("Station " MACSTR " trying to deauthenticate, but it " "is not authenticated.\n", MAC2STR(mgmt->sa)); return; } sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR, MAC2STR(sta->addr)); wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "deauthenticated"); mlme_deauthenticate_indication( hapd, sta, le_to_host16(mgmt->u.deauth.reason_code)); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); ap_free_sta(hapd, sta); }
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) { struct sta_info *sta; 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 reporting a station mode event while hostapd * was running, so better make sure we stop processing such an * event here. */ wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event " "with no address"); return; } hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated"); sta = ap_get_sta(hapd, addr); if (sta == NULL) { wpa_printf(MSG_DEBUG, "Disassociation notification for " "unknown STA " MACSTR, MAC2STR(addr)); return; } ap_sta_set_authorized(hapd, sta, 0); sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); ap_free_sta(hapd, sta); }
static struct wpa_state_machine * hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) { struct hostapd_data *hapd = ctx; struct sta_info *sta; if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0) return NULL; sta = ap_sta_add(hapd, sta_addr); if (sta == NULL) return NULL; if (sta->wpa_sm) { sta->auth_alg = WLAN_AUTH_FT; return sta->wpa_sm; } sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr, NULL); if (sta->wpa_sm == NULL) { ap_free_sta(hapd, sta); return NULL; } sta->auth_alg = WLAN_AUTH_FT; return sta->wpa_sm; }
static void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx) { struct hostapd_data *hapd = eloop_ctx; struct sta_info *sta = timeout_ctx; wpa_printf(MSG_DEBUG, "RSN: Removing pre-authentication STA entry for " MACSTR, MAC2STR(sta->addr)); ap_free_sta(hapd, sta); }
static void rsn_preauth_receive(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) { struct rsn_preauth_interface *piface = ctx; struct hostapd_data *hapd = piface->hapd; struct ieee802_1x_hdr *hdr; struct sta_info *sta; struct l2_ethhdr *ethhdr; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: receive pre-auth packet " "from interface '%s'\n", piface->ifname); if (len < sizeof(*ethhdr) + sizeof(*hdr)) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: too short pre-auth " "packet (len=%lu)\n", (unsigned long) len); return; } ethhdr = (struct l2_ethhdr *) buf; hdr = (struct ieee802_1x_hdr *) (ethhdr + 1); if (memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: pre-auth for " "foreign address " MACSTR "\n", MAC2STR(ethhdr->h_dest)); return; } sta = ap_get_sta(hapd, ethhdr->h_source); if (sta && (sta->flags & WLAN_STA_ASSOC)) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: pre-auth for " "already association STA " MACSTR "\n", MAC2STR(sta->addr)); return; } if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) { sta = ap_sta_add(hapd, ethhdr->h_source); if (sta == NULL) return; sta->flags = WLAN_STA_PREAUTH; ieee802_1x_new_station(hapd, sta); if (sta->eapol_sm == NULL) { ap_free_sta(hapd, sta); sta = NULL; } else { sta->eapol_sm->radius_identifier = -1; sta->eapol_sm->portValid = TRUE; sta->eapol_sm->flags |= EAPOL_SM_PREAUTH; } } if (sta == NULL) return; sta->preauth_iface = piface; ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1), len - sizeof(*ethhdr)); }
void hostapd_free_stas(hostapd *hapd) { struct sta_info *sta, *prev; sta = hapd->sta_list; while (sta) { prev = sta; sta = sta->next; printf("Removing station " MACSTR "\n", MAC2STR(prev->addr)); ap_free_sta(hapd, prev); } }
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) { struct sta_info *sta; 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 reporting a station mode event while hostapd * was running, so better make sure we stop processing such an * event here. */ wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event " "with no address"); return; } hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated"); sta = ap_get_sta(hapd, addr); if (sta == NULL) { wpa_printf(MSG_DEBUG, "Disassociation notification for " "unknown STA " MACSTR, MAC2STR(addr)); return; } /* [ALPS00326459][6575JB][BSP Package][6577JB][CTS Verifier 4.1_r2][MT6577_PHONE][changelist 996001] GROUP JOIN 2 cases fail in Wi-Fi Direct Test */ #if defined(CONFIG_MTK_P2P) || defined(CONFIG_HOTSPOT_MGR_SUPPORT) if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa) || sta->auth_alg == WLAN_AUTH_FT) { /* * Open, static WEP, or FT protocol; no separate authorization * step. */ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR, MAC2STR(sta->addr)); } #endif /* CONFIG_MTK_P2P || CONFIG_HOTSPOT_MGR_SUPPORT */ ap_sta_set_authorized(hapd, sta, 0); sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); ap_free_sta(hapd, sta); }
void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx) { hostapd *hapd = eloop_ctx; struct sta_info *sta = timeout_ctx; if (!(sta->flags & WLAN_STA_AUTH)) return; hostapd_sta_deauth(hapd, sta->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deauthenticated due to " "session timeout"); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT; ap_free_sta(hapd, sta); }
void hostapd_free_stas(struct hostapd_data *hapd) { struct sta_info *sta, *prev; sta = hapd->sta_list; while (sta) { prev = sta; if (sta->flags & WLAN_STA_AUTH) { mlme_deauthenticate_indication( hapd, sta, WLAN_REASON_UNSPECIFIED); } sta = sta->next; printf("Removing station " MACSTR "\n", MAC2STR(prev->addr)); ap_free_sta(hapd, prev); } }
static void handle_deauth(hostapd *hapd, struct ieee80211_mgmt *mgmt, size_t len) { struct sta_info *sta; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) { printf("handle_deauth - too short payload (len=%lu)\n", (unsigned long) len); return; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "deauthentication: STA=" MACSTR " reason_code=%d\n", MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code)); if (hapd->assoc_ap_state != DO_NOT_ASSOC && memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) { printf("Assoc AP " MACSTR " sent deauthentication " "(reason_code=%d) - try to authenticate\n", MAC2STR(hapd->conf->assoc_ap_addr), le_to_host16(mgmt->u.deauth.reason_code)); hapd->assoc_ap_state = AUTHENTICATE; eloop_register_timeout(0, 500000, ieee802_11_sta_authenticate, hapd, NULL); return; } sta = ap_get_sta(hapd, mgmt->sa); if (sta == NULL) { printf("Station " MACSTR " trying to deauthenticate, but it " "is not authenticated.\n", MAC2STR(mgmt->sa)); return; } sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); wpa_sm_event(hapd, sta, WPA_DEAUTH); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "deauthenticated"); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_set_port_enabled(hapd, sta, 0); ap_free_sta(hapd, sta); }
static int madwifi_del_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) { struct hostapd_data *hapd = drv->hapd; struct sta_info *sta; hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated"); sta = ap_get_sta(hapd, addr); if (sta != NULL) { sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); ap_free_sta(hapd, sta); } return 0; }
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx) { struct hostapd_data *hapd = eloop_ctx; struct sta_info *sta = timeout_ctx; u8 addr[ETH_ALEN]; if (!(sta->flags & WLAN_STA_AUTH)) return; mlme_deauthenticate_indication(hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deauthenticated due to " "session timeout"); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT; os_memcpy(addr, sta->addr, ETH_ALEN); ap_free_sta(hapd, sta); hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); }
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) { struct sta_info *sta; hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated"); sta = ap_get_sta(hapd, addr); if (sta == NULL) { wpa_printf(MSG_DEBUG, "Disassociation notification for " "unknown STA " MACSTR, MAC2STR(addr)); return; } sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); ap_free_sta(hapd, sta); }
static int bsd_del_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) { struct hostapd_data *hapd = drv->hapd; struct hostapd_config *conf = hapd->conf; struct sta_info *sta; hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deassociated"); sta = ap_get_sta(hapd, addr); if (sta != NULL) { sta->flags &= ~WLAN_STA_ASSOC; if (conf->wpa) wpa_sm_event(hapd, sta, WPA_DISASSOC); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_set_port_enabled(hapd, sta, 0); ap_free_sta(hapd, sta); } return 0; }
static int rtl871x_del_sta(struct rtl871x_driver_data *drv, u8 *addr) { struct hostapd_data *hapd = drv->hapd; #if 1 //union wpa_event_data event; //os_memset(&event, 0, sizeof(event)); //event.disassoc_info.addr = addr; //wpa_supplicant_event(hapd, EVENT_DISASSOC, &event); drv_event_disassoc(hapd, addr); #else struct sta_info *sta; //hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, // HOSTAPD_LEVEL_INFO, "disassociated"); sta = ap_get_sta(hapd, addr); if (sta != NULL) { sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); ap_free_sta(hapd, sta); } else { wpa_printf(MSG_DEBUG, "Disassociation notification for " "unknown STA " MACSTR, MAC2STR(addr)); } #endif return 0; }
static void test_driver_disassoc(struct test_driver_data *drv, struct sockaddr_un *from, socklen_t fromlen) { struct test_client_socket *cli; struct sta_info *sta; cli = test_driver_get_cli(drv, from, fromlen); if (!cli) return; hostapd_logger(drv->hapd, cli->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated"); sta = ap_get_sta(drv->hapd, cli->addr); if (sta != NULL) { sta->flags &= ~WLAN_STA_ASSOC; wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); ap_free_sta(drv->hapd, sta); } }
int rtw_sta_flush(struct adapter *padapter) { struct list_head *phead, *plist; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) return 0; spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; plist = phead->next; /* free sta asoc_queue */ while (phead != plist) { psta = container_of(plist, struct sta_info, asoc_list); plist = plist->next; list_del_init(&psta->asoc_list); pstapriv->asoc_list_cnt--; ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING); } spin_unlock_bh(&pstapriv->asoc_list_lock); issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING); associated_clients_update(padapter, true); return 0; }
/** * 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; 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; inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr); if (inactive_sec == -1) { wpa_msg(hapd, MSG_DEBUG, "Check inactivity: Could not " "get station info rom kernel driver for " MACSTR, MAC2STR(sta->addr)); } else if (inactive_sec < hapd->conf->ap_max_inactivity && sta->flags & WLAN_STA_ASSOC) { /* station activity detected; reset timeout state */ wpa_msg(hapd, 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 - inactive_sec; } else { wpa_msg(hapd, 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 ((sta->flags & WLAN_STA_ASSOC) && sta->timeout_next == STA_DISASSOC && !(sta->flags & WLAN_STA_PENDING_POLL)) { wpa_msg(hapd, 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; } if (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)) { #ifndef CONFIG_NATIVE_WINDOWS /* send data frame to poll STA and check whether this frame * is ACKed */ struct { struct ieee80211_hdr hdr; u16 qos_ctl; } STRUCT_PACKED nulldata; int size = sizeof(struct ieee80211_hdr); wpa_printf(MSG_DEBUG, " Polling STA with data frame"); sta->flags |= WLAN_STA_PENDING_POLL; os_memset(&nulldata, 0, sizeof(nulldata)); if (hapd->driver && os_strcmp(hapd->driver->name, "hostap") == 0) { /* * WLAN_FC_STYPE_NULLFUNC would be more appropriate, * but it is apparently not retried so TX Exc events * are not received for it. */ nulldata.hdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); } else { if (sta->flags & WLAN_STA_WMM) { nulldata.hdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_QOS_NULL); size = sizeof(nulldata); } else nulldata.hdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_NULLFUNC); } nulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS); os_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN); os_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr, ETH_ALEN); os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN); if (hostapd_drv_send_mlme(hapd, &nulldata, size) < 0) perror("ap_handle_timer: send"); #endif /* CONFIG_NATIVE_WINDOWS */ } else if (sta->timeout_next != STA_REMOVE) { int deauth = sta->timeout_next == STA_DEAUTH; wpa_printf(MSG_DEBUG, "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 { hostapd_drv_sta_disassoc( hapd, sta->addr, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); } } switch (sta->timeout_next) { case STA_NULLFUNC: sta->timeout_next = STA_DISASSOC; eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer, hapd, sta); break; case STA_DISASSOC: 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"); sta->timeout_next = STA_DEAUTH; eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, hapd, sta); mlme_disassociate_indication( hapd, sta, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); break; case STA_DEAUTH: case STA_REMOVE: hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deauthenticated due to " "inactivity"); 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; } }
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; #ifdef CONFIG_IEEE80211R u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; u8 *p = buf; #endif /* CONFIG_IEEE80211R */ 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); #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 && elems.ht_capabilities_len >= sizeof(struct ieee80211_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_MTK_P2P if (elems.wfd && (elems.wfd_len > 0)) { struct p2p_message msg; wpabuf_free(sta->wfd_ie); sta->wfd_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len, WFD_IE_VENDOR_TYPE); if(p2p_parse_wfd_ie(sta->wfd_ie,&msg)==0) { wpa_printf(MSG_DEBUG, "Change our WFD role and peer wfd_ie"); if(hapd->p2p) { wpa_printf(MSG_DEBUG, "Change our WFD role and peer wfd_ie 2"); wfd_process_request_and_switch_role(hapd->p2p, &msg, 0); } } } #endif /* CONFIG_MTK_P2P */ 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); #ifdef CONFIG_IEEE80211R 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); #endif /* CONFIG_IEEE80211R */ 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_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); /* [ALPS00326459][6575JB][BSP Package][6577JB][CTS Verifier 4.1_r2][MT6577_PHONE][changelist 996001] GROUP JOIN 2 cases fail in Wi-Fi Direct Test */ #if defined(CONFIG_MTK_P2P) || defined(CONFIG_HOTSPOT_MGR_SUPPORT) if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa) || sta->auth_alg == WLAN_AUTH_FT) { /* * Open, static WEP, or FT protocol; no separate authorization * step. */ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr)); } #endif /* CONFIG_MTK_P2P || CONFIG_HOTSPOT_MGR_SUPPORT */ 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; }
void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) { hostapd *hapd = eloop_ctx; struct sta_info *sta = timeout_ctx; unsigned long next_time = 0; 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; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Checking STA " MACSTR " inactivity:\n", MAC2STR(sta->addr)); inactive_sec = hostapd_get_inact_sec(hapd, sta->addr); if (inactive_sec == -1) { printf(" Could not get station info from kernel " "driver for " MACSTR ".\n", MAC2STR(sta->addr)); } else if (inactive_sec < AP_MAX_INACTIVITY && sta->flags & WLAN_STA_ASSOC) { /* station activity detected; reset timeout state */ HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " Station has been active\n"); sta->timeout_next = STA_NULLFUNC; next_time = AP_MAX_INACTIVITY - inactive_sec; } } if ((sta->flags & WLAN_STA_ASSOC) && sta->timeout_next == STA_DISASSOC && !(sta->flags & WLAN_STA_PENDING_POLL)) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " Station has ACKed data poll\n"); /* data nullfunc frame poll did not produce TX errors; assume * station ACKed it */ sta->timeout_next = STA_NULLFUNC; next_time = AP_MAX_INACTIVITY; } if (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)) { /* send data frame to poll STA and check whether this frame * is ACKed */ struct ieee80211_hdr hdr; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " Polling STA with data frame\n"); sta->flags |= WLAN_STA_PENDING_POLL; /* FIX: WLAN_FC_STYPE_NULLFUNC would be more appropriate, but * it is apparently not retried so TX Exc events are not * received for it */ memset(&hdr, 0, sizeof(hdr)); hdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); hdr.frame_control |= host_to_le16(BIT(1)); hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS); memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN); memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr, ETH_ALEN); memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN); if (hostapd_send_mgmt_frame(hapd, &hdr, sizeof(hdr), 0) < 0) perror("ap_handle_timer: send"); } else if (sta->timeout_next != STA_REMOVE) { int deauth = sta->timeout_next == STA_DEAUTH; printf(" Sending %s info to STA " MACSTR "\n", deauth ? "deauthentication" : "disassociation", MAC2STR(sta->addr)); if (deauth) { hostapd_sta_deauth(hapd, sta->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); } else { hostapd_sta_disassoc( hapd, sta->addr, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); } } switch (sta->timeout_next) { case STA_NULLFUNC: sta->timeout_next = STA_DISASSOC; eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer, hapd, sta); break; case STA_DISASSOC: sta->flags &= ~WLAN_STA_ASSOC; ieee802_1x_set_port_enabled(hapd, sta, 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"); sta->timeout_next = STA_DEAUTH; eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, hapd, sta); break; case STA_DEAUTH: case STA_REMOVE: hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deauthenticated due to " "inactivity"); if (!sta->acct_terminate_cause) sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; ap_free_sta(hapd, sta); break; } }
void expire_timeout_chk(struct adapter *padapter) { struct list_head *phead, *plist; u8 updated = 0; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; u8 chk_alive_num = 0; char chk_alive_list[NUM_STA]; int i; spin_lock_bh(&pstapriv->auth_list_lock); phead = &pstapriv->auth_list; plist = phead->next; /* check auth_queue */ while (phead != plist) { psta = container_of(plist, struct sta_info, auth_list); plist = plist->next; if (psta->expire_to > 0) { psta->expire_to--; if (psta->expire_to == 0) { list_del_init(&psta->auth_list); pstapriv->auth_list_cnt--; DBG_88E("auth expire %6ph\n", psta->hwaddr); spin_unlock_bh(&pstapriv->auth_list_lock); spin_lock_bh(&pstapriv->sta_hash_lock); rtw_free_stainfo(padapter, psta); spin_unlock_bh(&pstapriv->sta_hash_lock); spin_lock_bh(&pstapriv->auth_list_lock); } } } spin_unlock_bh(&pstapriv->auth_list_lock); psta = NULL; spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; plist = phead->next; /* check asoc_queue */ while (phead != plist) { psta = container_of(plist, struct sta_info, asoc_list); plist = plist->next; if (chk_sta_is_alive(psta) || !psta->expire_to) { psta->expire_to = pstapriv->expire_to; psta->keep_alive_trycnt = 0; psta->under_exist_checking = 0; } else { psta->expire_to--; } if (psta->expire_to <= 0) { struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; if (padapter->registrypriv.wifi_spec == 1) { psta->expire_to = pstapriv->expire_to; continue; } if (psta->state & WIFI_SLEEP_STATE) { if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { /* to check if alive by another methods * if station is at ps mode. */ psta->expire_to = pstapriv->expire_to; psta->state |= WIFI_STA_ALIVE_CHK_STATE; /* to update bcn with tim_bitmap * for this station */ pstapriv->tim_bitmap |= BIT(psta->aid); update_beacon(padapter, _TIM_IE_, NULL, false); if (!pmlmeext->active_keep_alive_check) continue; } } if (pmlmeext->active_keep_alive_check) { int stainfo_offset; stainfo_offset = rtw_stainfo_offset(pstapriv, psta); if (stainfo_offset_valid(stainfo_offset)) chk_alive_list[chk_alive_num++] = stainfo_offset; continue; } list_del_init(&psta->asoc_list); pstapriv->asoc_list_cnt--; DBG_88E("asoc expire %pM, state = 0x%x\n", (psta->hwaddr), psta->state); updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING); } else { /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */ if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) && padapter->xmitpriv.free_xmitframe_cnt < (NR_XMITFRAME / pstapriv->asoc_list_cnt / 2)) { DBG_88E("%s sta:%pM, sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__, (psta->hwaddr), psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt); wakeup_sta_to_xmit(padapter, psta); } } } spin_unlock_bh(&pstapriv->asoc_list_lock); if (chk_alive_num) { u8 backup_oper_channel = 0; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; /* switch to correct channel of current network before issue keep-alive frames */ if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) { backup_oper_channel = rtw_get_oper_ch(padapter); SelectChannel(padapter, pmlmeext->cur_channel); } /* issue null data to check sta alive*/ for (i = 0; i < chk_alive_num; i++) { int ret = _FAIL; psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]); if (psta->state & WIFI_SLEEP_STATE) ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50); else ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50); psta->keep_alive_trycnt++; if (ret == _SUCCESS) { DBG_88E("asoc check, sta(%pM) is alive\n", (psta->hwaddr)); psta->expire_to = pstapriv->expire_to; psta->keep_alive_trycnt = 0; continue; } else if (psta->keep_alive_trycnt <= 3) { DBG_88E("ack check for asoc expire, keep_alive_trycnt =%d\n", psta->keep_alive_trycnt); psta->expire_to = 1; continue; } psta->keep_alive_trycnt = 0; DBG_88E("asoc expire %pM, state = 0x%x\n", (psta->hwaddr), psta->state); spin_lock_bh(&pstapriv->asoc_list_lock); list_del_init(&psta->asoc_list); pstapriv->asoc_list_cnt--; updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING); spin_unlock_bh(&pstapriv->asoc_list_lock); } if (backup_oper_channel > 0) /* back to the original operation channel */ SelectChannel(padapter, backup_oper_channel); } associated_clients_update(padapter, updated); }
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; #ifdef CONFIG_IEEE80211R u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; u8 *p = buf; #endif /* CONFIG_IEEE80211R */ 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"); } 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); #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_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 */ 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); #ifdef CONFIG_IEEE80211R 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); #endif /* CONFIG_IEEE80211R */ 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_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); #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; 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; }
/** * 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; 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 < hapd->conf->ap_max_inactivity && sta->flags & WLAN_STA_ASSOC) { /* 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; } 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 { hostapd_drv_sta_disassoc( hapd, sta->addr, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); } } 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: 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"); 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, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); 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; } }
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; #ifdef CONFIG_IEEE80211R u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; u8 *p = buf; size_t len = 0; #endif /* CONFIG_IEEE80211R */ int resp = WLAN_STATUS_SUCCESS; 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"); } 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) { accounting_sta_stop(hapd, sta); } else { sta = ap_sta_add(hapd, addr); if (sta == NULL) return -1; } sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2); #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); } #endif /* CONFIG_P2P */ if (hapd->conf->wpa) { if (ie == NULL || ielen == 0) { 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; } wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA"); return -1; } 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; } if (sta->wpa_sm == NULL) sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->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) resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID; else if (res == WPA_INVALID_PAIRWISE) resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; else if (res == WPA_INVALID_AKMP) resp = WLAN_REASON_AKMP_NOT_VALID; #ifdef CONFIG_IEEE80211W else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) resp = WLAN_REASON_INVALID_IE; else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID; #endif /* CONFIG_IEEE80211W */ else resp = WLAN_REASON_INVALID_IE; goto fail; } #ifdef CONFIG_IEEE80211R if (sta->auth_alg == WLAN_AUTH_FT) { resp = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies, req_ies_len); if (resp != WLAN_STATUS_SUCCESS) goto fail; } #endif /* CONFIG_IEEE80211R */ } else if (hapd->conf->wps_state) { struct wpabuf *wps; wps = ieee802_11_vendor_ie_concat(ie, ielen, WPS_IE_VENDOR_TYPE); #ifdef CONFIG_WPS_STRICT if (ie) { if (wps && wps_validate_assoc_req(wps) < 0) { resp = WLAN_REASON_INVALID_IE; wpabuf_free(wps); goto fail; } } #endif /* CONFIG_WPS_STRICT */ if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 && os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { sta->flags |= WLAN_STA_WPS; if (wps && 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); } skip_wpa_check: #ifdef CONFIG_IEEE80211R p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf), sta->auth_alg, req_ies, req_ies_len); len = p - buf; hostapd_sta_assoc(hapd, addr, reassoc, 0, buf, len); #endif /* CONFIG_IEEE80211R */ new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; 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 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, resp, buf, len); #endif /* CONFIG_IEEE80211R */ hostapd_drv_sta_disassoc(hapd, sta->addr, resp); ap_free_sta(hapd, sta); return -1; }
void rsn_preauth_receive_thinap(void *ctx, const u8 *src_addr,const u8 *des_addr, const u8 *buf, size_t len) { struct asd_data *now_wasd = ctx; struct ieee802_1x_hdr *hdr; struct sta_info *sta; struct asd_data * wasd; struct PreAuth_BSSINFO *bss; struct wasd_interfaces *interfaces = (struct wasd_interfaces*) circle.user_data; unsigned int RadioID; unsigned char BSS_L_ID; bss = PreAuth_wlan_get_bss(ASD_WLAN[now_wasd->WlanID],des_addr); if(bss == NULL){ asd_printf(ASD_DEFAULT,MSG_DEBUG,"something wrong in finding bss: "MACSTR, MAC2STR(des_addr)); return; } asd_printf(ASD_DEFAULT,MSG_DEBUG,"we got bss index:%d",bss->BSSIndex); RadioID = bss->BSSIndex/L_BSS_NUM; BSS_L_ID = bss->BSSIndex%L_BSS_NUM; if((interfaces->iface[RadioID]!=NULL)&&(interfaces->iface[RadioID]->bss[BSS_L_ID]!=NULL)) wasd = interfaces->iface[RadioID]->bss[BSS_L_ID]; else return; if (len < sizeof(*hdr)) { asd_printf(ASD_DEFAULT,MSG_DEBUG, "RSN: too short pre-auth packet " "(len=%lu)", (unsigned long) len); asd_printf(ASD_DEFAULT,MSG_DEBUG,"rsn_preauth_receive_thinap RSN: too short pre-auth packet " "(len=%lu)", (unsigned long) len); return; } hdr = (struct ieee802_1x_hdr *) (buf); if (os_memcmp(des_addr, wasd->own_addr, ETH_ALEN) != 0) { asd_printf(ASD_DEFAULT,MSG_DEBUG, "RSN: pre-auth for foreign address " MACSTR, MAC2STR(des_addr)); asd_printf(ASD_DEFAULT,MSG_DEBUG,"rsn_preauth_receive_thinap RSN: pre-auth for foreign address " MACSTR, MAC2STR(des_addr)); return; } sta = ap_get_sta(wasd, src_addr); if (sta && (sta->flags & WLAN_STA_ASSOC)) { asd_printf(ASD_DEFAULT,MSG_DEBUG, "RSN: pre-auth for already association " "STA " MACSTR, MAC2STR(sta->addr)); asd_printf(ASD_DEFAULT,MSG_DEBUG,"rsn_preauth_receive_thinap RSN: pre-auth for already association " "STA " MACSTR, MAC2STR(sta->addr)); return; } if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) { asd_printf(ASD_DEFAULT,MSG_DEBUG,"IEEE802_1X_TYPE_EAPOL_START\n"); sta = ap_sta_add(wasd, src_addr,0); if (sta == NULL) return; sta->flags = WLAN_STA_PREAUTH; ieee802_1x_new_station(wasd, sta); if (sta->eapol_sm == NULL) { ap_free_sta(wasd, sta,0); sta = NULL; } else { sta->eapol_sm->radius_identifier = -1; sta->eapol_sm->portValid = TRUE; sta->eapol_sm->flags |= EAPOL_SM_PREAUTH; } } if (sta == NULL) return; memcpy(sta->PreAuth_BSSID,now_wasd->own_addr,6); sta->PreAuth_BSSIndex = now_wasd->BSSIndex; asd_printf(ASD_DEFAULT,MSG_DEBUG,"ieee802_1x_receive \n"); ieee802_1x_receive(wasd, src_addr, (u8 *) (buf), len); }