Add test commands for sending deauth/disassoc without dropping state

This can be used to test 802.11w by sending a protected or unprotected
deauth/disassoc frame.

hostapd_cli deauth <dst addr> test=<0/1>
hostapd_cli disassoc <dst addr> test=<0/1>

test=0: unprotected
test=1: protected
This commit is contained in:
Jouni Malinen 2010-03-29 12:01:40 -07:00 committed by Jouni Malinen
parent 90a3206a14
commit b91ab76e8c
5 changed files with 88 additions and 5 deletions

View file

@ -160,12 +160,37 @@ static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
{ {
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
struct sta_info *sta; struct sta_info *sta;
const char *pos;
wpa_printf(MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", txtaddr); wpa_printf(MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", txtaddr);
if (hwaddr_aton(txtaddr, addr)) if (hwaddr_aton(txtaddr, addr))
return -1; return -1;
pos = os_strstr(txtaddr, " test=");
if (pos) {
struct ieee80211_mgmt mgmt;
int encrypt;
if (hapd->driver->send_frame == NULL)
return -1;
pos += 6;
encrypt = atoi(pos);
os_memset(&mgmt, 0, sizeof(mgmt));
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_DEAUTH);
os_memcpy(mgmt.da, addr, ETH_ALEN);
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
mgmt.u.deauth.reason_code =
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.deauth),
encrypt) < 0)
return -1;
return 0;
}
hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
sta = ap_get_sta(hapd, addr); sta = ap_get_sta(hapd, addr);
if (sta) if (sta)
@ -181,12 +206,37 @@ static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
{ {
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
struct sta_info *sta; struct sta_info *sta;
const char *pos;
wpa_printf(MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr); wpa_printf(MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr);
if (hwaddr_aton(txtaddr, addr)) if (hwaddr_aton(txtaddr, addr))
return -1; return -1;
pos = os_strstr(txtaddr, " test=");
if (pos) {
struct ieee80211_mgmt mgmt;
int encrypt;
if (hapd->driver->send_frame == NULL)
return -1;
pos += 6;
encrypt = atoi(pos);
os_memset(&mgmt, 0, sizeof(mgmt));
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_DISASSOC);
os_memcpy(mgmt.da, addr, ETH_ALEN);
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
mgmt.u.deauth.reason_code =
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.deauth),
encrypt) < 0)
return -1;
return 0;
}
hapd->drv.sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); hapd->drv.sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
sta = ap_get_sta(hapd, addr); sta = ap_get_sta(hapd, addr);
if (sta) if (sta)

View file

@ -246,12 +246,16 @@ static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
char *argv[]) char *argv[])
{ {
char buf[64]; char buf[64];
if (argc != 1) { if (argc < 1) {
printf("Invalid 'deauthenticate' command - exactly one " printf("Invalid 'deauthenticate' command - exactly one "
"argument, STA address, is required.\n"); "argument, STA address, is required.\n");
return -1; return -1;
} }
snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]); if (argc > 1)
os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
argv[0], argv[1]);
else
os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
return wpa_ctrl_command(ctrl, buf); return wpa_ctrl_command(ctrl, buf);
} }
@ -260,12 +264,16 @@ static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
char *argv[]) char *argv[])
{ {
char buf[64]; char buf[64];
if (argc != 1) { if (argc < 1) {
printf("Invalid 'disassociate' command - exactly one " printf("Invalid 'disassociate' command - exactly one "
"argument, STA address, is required.\n"); "argument, STA address, is required.\n");
return -1; return -1;
} }
snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]); if (argc > 1)
os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
argv[0], argv[1]);
else
os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
return wpa_ctrl_command(ctrl, buf); return wpa_ctrl_command(ctrl, buf);
} }

View file

@ -1774,6 +1774,20 @@ struct wpa_driver_ops {
* least %hysteresis from the previously indicated signal change event. * least %hysteresis from the previously indicated signal change event.
*/ */
int (*signal_monitor)(void *priv, int threshold, int hysteresis); int (*signal_monitor)(void *priv, int threshold, int hysteresis);
/**
* send_frame - Send IEEE 802.11 frame (testing use only)
* @priv: Private driver interface data
* @data: IEEE 802.11 frame with IEEE 802.11 header
* @data_len: Size of the frame
* @encrypt: Whether to encrypt the frame (if keys are set)
* Returns: 0 on success, -1 on failure
*
* This function is only used for debugging purposes and is not
* required to be implemented for normal operations.
*/
int (*send_frame)(void *priv, const u8 *data, size_t data_len,
int encrypt);
}; };

View file

@ -3275,5 +3275,6 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
NULL /* deinit_ap */, NULL /* deinit_ap */,
NULL /* suspend */, NULL /* suspend */,
NULL /* resume */, NULL /* resume */,
NULL /* signal_monitor */ NULL /* signal_monitor */,
NULL /* send_frame */
}; };

View file

@ -5237,6 +5237,15 @@ nla_put_failure:
} }
static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
int encrypt)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
return wpa_driver_nl80211_send_frame(drv, data, data_len, encrypt);
}
const struct wpa_driver_ops wpa_driver_nl80211_ops = { const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211", .name = "nl80211",
.desc = "Linux nl80211/cfg80211", .desc = "Linux nl80211/cfg80211",
@ -5297,4 +5306,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.resume = wpa_driver_nl80211_resume, .resume = wpa_driver_nl80211_resume,
.send_ft_action = nl80211_send_ft_action, .send_ft_action = nl80211_send_ft_action,
.signal_monitor = nl80211_signal_monitor, .signal_monitor = nl80211_signal_monitor,
.send_frame = nl80211_send_frame,
}; };