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:
parent
f65f539d9a
commit
d5b559b641
4 changed files with 52 additions and 15 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue