static void handle_disassoc(hostapd *hapd, struct ieee80211_mgmt *mgmt, size_t len) { struct sta_info *sta; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) { printf("handle_disassoc - too short payload (len=%lu)\n", (unsigned long) len); return; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "disassocation: STA=" MACSTR " reason_code=%d\n", MAC2STR(mgmt->sa), le_to_host16(mgmt->u.disassoc.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 disassociation " "(reason_code=%d) - try to authenticate\n", MAC2STR(hapd->conf->assoc_ap_addr), le_to_host16(mgmt->u.disassoc.reason_code)); hapd->assoc_ap_state = AUTHENTICATE; ieee802_11_sta_authenticate(hapd, NULL); 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 disassociate, but it " "is not associated.\n", MAC2STR(mgmt->sa)); return; } sta->flags &= ~WLAN_STA_ASSOC; wpa_sm_event(hapd, sta, WPA_DISASSOC); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated"); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_set_port_enabled(hapd, sta, 0); /* Stop Accounting and IEEE 802.1X sessions, but leave the STA * authenticated. */ accounting_sta_stop(hapd, sta); ieee802_1x_free_station(sta); hostapd_sta_remove(hapd, sta->addr); if (sta->timeout_next == STA_NULLFUNC || sta->timeout_next == STA_DISASSOC) { sta->timeout_next = STA_DEAUTH; eloop_cancel_timeout(ap_handle_timer, hapd, sta); eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, hapd, sta); } }
void remove_sta(hostapd *hapd, struct sta_info *sta) { struct prism2_hostapd_param param; ieee802_1x_set_port_enabled(hapd, sta, 0); memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_REMOVE_STA; memcpy(param.sta_addr, sta->addr, ETH_ALEN); if (hostapd_ioctl(hapd, ¶m, sizeof(param))) { printf("Could not remove station from kernel driver.\n"); } }
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 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; }
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; } }