示例#1
0
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);
    }
}
示例#2
0
void remove_sta(hostapd *hapd, struct sta_info *sta)
{
	struct prism2_hostapd_param param;

	ieee802_1x_set_port_enabled(hapd, sta, 0);

	memset(&param, 0, sizeof(param));
	param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
	memcpy(param.sta_addr, sta->addr, ETH_ALEN);
	if (hostapd_ioctl(hapd, &param, sizeof(param))) {
		printf("Could not remove station from kernel driver.\n");
	}
}
示例#3
0
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);
}
示例#4
0
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;
}
示例#5
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;
    }
}