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:
parent
90a3206a14
commit
b91ab76e8c
5 changed files with 88 additions and 5 deletions
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue