WNM: Add disassociation timeout processing for ESS_DISASSOC

The hostapd_cli ess_disassoc command now takes three arguments (STA MAC
address, timeout in ms, URL) and the STA is disconnected after the
specified timeout.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Kyeyoon Park 2013-04-05 18:41:26 +03:00 committed by Jouni Malinen
parent f65f539d9a
commit d5b559b641
4 changed files with 52 additions and 15 deletions

View file

@ -537,14 +537,24 @@ static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
const char *cmd) const char *cmd)
{ {
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
const char *url; const char *url, *timerstr;
u8 buf[1000], *pos; u8 buf[1000], *pos;
struct ieee80211_mgmt *mgmt; struct ieee80211_mgmt *mgmt;
size_t url_len; size_t url_len;
int disassoc_timer;
if (hwaddr_aton(cmd, addr)) if (hwaddr_aton(cmd, addr))
return -1; return -1;
url = cmd + 17;
timerstr = cmd + 17;
if (*timerstr != ' ')
return -1;
timerstr++;
disassoc_timer = atoi(timerstr);
if (disassoc_timer < 0 || disassoc_timer > 65535)
return -1;
url = os_strchr(timerstr, ' ');
if (*url != ' ') if (*url != ' ')
return -1; return -1;
url++; url++;
@ -564,8 +574,9 @@ static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
mgmt->u.action.u.bss_tm_req.dialog_token = 1; mgmt->u.action.u.bss_tm_req.dialog_token = 1;
mgmt->u.action.u.bss_tm_req.req_mode = mgmt->u.action.u.bss_tm_req.req_mode =
WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT; WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0); mgmt->u.action.u.bss_tm_req.disassoc_timer =
mgmt->u.action.u.bss_tm_req.validity_interval = 0; host_to_le16(disassoc_timer);
mgmt->u.action.u.bss_tm_req.validity_interval = 0x01;
pos = mgmt->u.action.u.bss_tm_req.variable; pos = mgmt->u.action.u.bss_tm_req.variable;
@ -580,6 +591,25 @@ static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
return -1; return -1;
} }
/* send disassociation frame after time-out */
if (disassoc_timer) {
struct sta_info *sta;
sta = ap_get_sta(hapd, addr);
if (sta == NULL) {
wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
"for ESS disassociation imminent message",
MAC2STR(addr));
return -1;
}
sta->timeout_next = STA_DISASSOC_FROM_CLI;
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(disassoc_timer / 1000,
disassoc_timer % 1000 * 1000,
ap_handle_timer, hapd, sta);
}
return 0; return 0;
} }

View file

@ -588,14 +588,14 @@ static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
char buf[300]; char buf[300];
int res; int res;
if (argc < 2) { if (argc < 3) {
printf("Invalid 'ess_disassoc' command - two arguments (STA " printf("Invalid 'ess_disassoc' command - three arguments (STA "
"addr and URL) are needed\n"); "addr, disassoc timer, and URL) are needed\n");
return -1; return -1;
} }
res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s", res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
argv[0], argv[1]); argv[0], argv[1], argv[2]);
if (res < 0 || res >= (int) sizeof(buf)) if (res < 0 || res >= (int) sizeof(buf))
return -1; return -1;
return wpa_ctrl_command(ctrl, buf); return wpa_ctrl_command(ctrl, buf);

View file

@ -283,6 +283,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
struct hostapd_data *hapd = eloop_ctx; struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx; struct sta_info *sta = timeout_ctx;
unsigned long next_time = 0; unsigned long next_time = 0;
int reason;
wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d", wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d",
__func__, MAC2STR(sta->addr), sta->flags, __func__, MAC2STR(sta->addr), sta->flags,
@ -378,9 +379,11 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
hapd, sta->addr, hapd, sta->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID); WLAN_REASON_PREV_AUTH_NOT_VALID);
} else { } else {
hostapd_drv_sta_disassoc( reason = (sta->timeout_next == STA_DISASSOC) ?
hapd, sta->addr, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY :
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); WLAN_REASON_PREV_AUTH_NOT_VALID;
hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
} }
} }
@ -394,6 +397,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
hapd, sta); hapd, sta);
break; break;
case STA_DISASSOC: case STA_DISASSOC:
case STA_DISASSOC_FROM_CLI:
ap_sta_set_authorized(hapd, sta, 0); ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~WLAN_STA_ASSOC; sta->flags &= ~WLAN_STA_ASSOC;
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
@ -405,14 +409,16 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "disassociated due to " HOSTAPD_LEVEL_INFO, "disassociated due to "
"inactivity"); "inactivity");
reason = (sta->timeout_next == STA_DISASSOC) ?
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY :
WLAN_REASON_PREV_AUTH_NOT_VALID;
sta->timeout_next = STA_DEAUTH; sta->timeout_next = STA_DEAUTH;
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
"for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)", "for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)",
__func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY); __func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY);
eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
hapd, sta); hapd, sta);
mlme_disassociate_indication( mlme_disassociate_indication(hapd, sta, reason);
hapd, sta, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
break; break;
case STA_DEAUTH: case STA_DEAUTH:
case STA_REMOVE: case STA_REMOVE:

View file

@ -62,7 +62,8 @@ struct sta_info {
u8 previous_ap[6]; u8 previous_ap[6];
enum { enum {
STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE,
STA_DISASSOC_FROM_CLI
} timeout_next; } timeout_next;
u16 deauth_reason; u16 deauth_reason;