From e60b295186f5a70ab066eb35c4cea0153f54976c Mon Sep 17 00:00:00 2001 From: Jithu Jance Date: Sat, 25 Feb 2012 17:22:48 +0200 Subject: [PATCH] Add wpa_supplicant AP mode STA deauthenticate/disassociate commands Move disassociate and deauthenticate commands to ctrl_iface_ap.c, so that they ares accessible for wpa_supplicant AP mode and wpa_cli (with CONFIG_AP option enabled). Signed-hostap: Jithu Jance --- hostapd/ctrl_iface.c | 167 ----------------------------------- src/ap/ctrl_iface_ap.c | 169 ++++++++++++++++++++++++++++++++++++ src/ap/ctrl_iface_ap.h | 4 + wpa_supplicant/ap.c | 20 +++++ wpa_supplicant/ap.h | 4 + wpa_supplicant/ctrl_iface.c | 6 ++ wpa_supplicant/wpa_cli.c | 42 +++++++++ 7 files changed, 245 insertions(+), 167 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index a2e7cc5de..0fe761b38 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -153,173 +153,6 @@ static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, } -#ifdef CONFIG_P2P_MANAGER -static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype, - u8 minor_reason_code, const u8 *addr) -{ - struct ieee80211_mgmt *mgmt; - int ret; - u8 *pos; - - if (hapd->driver->send_frame == NULL) - return -1; - - mgmt = os_zalloc(sizeof(*mgmt) + 100); - if (mgmt == NULL) - return -1; - - wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR - " with minor reason code %u (stype=%u)", - MAC2STR(addr), minor_reason_code, stype); - - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype); - 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); - if (stype == WLAN_FC_STYPE_DEAUTH) { - mgmt->u.deauth.reason_code = - host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); - pos = (u8 *) (&mgmt->u.deauth.reason_code + 1); - } else { - mgmt->u.disassoc.reason_code = - host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); - pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1); - } - - *pos++ = WLAN_EID_VENDOR_SPECIFIC; - *pos++ = 4 + 3 + 1; - WPA_PUT_BE24(pos, OUI_WFA); - pos += 3; - *pos++ = P2P_OUI_TYPE; - - *pos++ = P2P_ATTR_MINOR_REASON_CODE; - WPA_PUT_LE16(pos, 1); - pos += 2; - *pos++ = minor_reason_code; - - ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt, - pos - (u8 *) mgmt, 1); - os_free(mgmt); - - return ret < 0 ? -1 : 0; -} -#endif /* CONFIG_P2P_MANAGER */ - - -static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, - const char *txtaddr) -{ - u8 addr[ETH_ALEN]; - struct sta_info *sta; - const char *pos; - - wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", - txtaddr); - - if (hwaddr_aton(txtaddr, addr)) - 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; - } - -#ifdef CONFIG_P2P_MANAGER - pos = os_strstr(txtaddr, " p2p="); - if (pos) { - return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH, - atoi(pos + 5), addr); - } -#endif /* CONFIG_P2P_MANAGER */ - - hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); - sta = ap_get_sta(hapd, addr); - if (sta) - ap_sta_deauthenticate(hapd, sta, - WLAN_REASON_PREV_AUTH_NOT_VALID); - else if (addr[0] == 0xff) - hostapd_free_stas(hapd); - - return 0; -} - - -static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, - const char *txtaddr) -{ - u8 addr[ETH_ALEN]; - struct sta_info *sta; - const char *pos; - - wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", - txtaddr); - - if (hwaddr_aton(txtaddr, addr)) - 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.disassoc.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; - } - -#ifdef CONFIG_P2P_MANAGER - pos = os_strstr(txtaddr, " p2p="); - if (pos) { - return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC, - atoi(pos + 5), addr); - } -#endif /* CONFIG_P2P_MANAGER */ - - hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); - sta = ap_get_sta(hapd, addr); - if (sta) - ap_sta_disassociate(hapd, sta, - WLAN_REASON_PREV_AUTH_NOT_VALID); - else if (addr[0] == 0xff) - hostapd_free_stas(hapd); - - return 0; -} - - #ifdef CONFIG_IEEE80211W #ifdef NEED_AP_MLME static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index d76b381bd..ab9c83eb8 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -9,6 +9,7 @@ #include "utils/includes.h" #include "utils/common.h" +#include "common/ieee802_11_defs.h" #include "hostapd.h" #include "ieee802_1x.h" #include "wpa_auth.h" @@ -17,6 +18,7 @@ #include "wps_hostapd.h" #include "p2p_hostapd.h" #include "ctrl_iface_ap.h" +#include "ap_drv_ops.h" static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, @@ -100,3 +102,170 @@ int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr, } return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen); } + + +#ifdef CONFIG_P2P_MANAGER +static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype, + u8 minor_reason_code, const u8 *addr) +{ + struct ieee80211_mgmt *mgmt; + int ret; + u8 *pos; + + if (hapd->driver->send_frame == NULL) + return -1; + + mgmt = os_zalloc(sizeof(*mgmt) + 100); + if (mgmt == NULL) + return -1; + + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR + " with minor reason code %u (stype=%u)", + MAC2STR(addr), minor_reason_code, stype); + + mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype); + 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); + if (stype == WLAN_FC_STYPE_DEAUTH) { + mgmt->u.deauth.reason_code = + host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + pos = (u8 *) (&mgmt->u.deauth.reason_code + 1); + } else { + mgmt->u.disassoc.reason_code = + host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1); + } + + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 4 + 3 + 1; + WPA_PUT_BE24(pos, OUI_WFA); + pos += 3; + *pos++ = P2P_OUI_TYPE; + + *pos++ = P2P_ATTR_MINOR_REASON_CODE; + WPA_PUT_LE16(pos, 1); + pos += 2; + *pos++ = minor_reason_code; + + ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt, + pos - (u8 *) mgmt, 1); + os_free(mgmt); + + return ret < 0 ? -1 : 0; +} +#endif /* CONFIG_P2P_MANAGER */ + + +int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, + const char *txtaddr) +{ + u8 addr[ETH_ALEN]; + struct sta_info *sta; + const char *pos; + + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", + txtaddr); + + if (hwaddr_aton(txtaddr, addr)) + 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; + } + +#ifdef CONFIG_P2P_MANAGER + pos = os_strstr(txtaddr, " p2p="); + if (pos) { + return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH, + atoi(pos + 5), addr); + } +#endif /* CONFIG_P2P_MANAGER */ + + hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); + sta = ap_get_sta(hapd, addr); + if (sta) + ap_sta_deauthenticate(hapd, sta, + WLAN_REASON_PREV_AUTH_NOT_VALID); + else if (addr[0] == 0xff) + hostapd_free_stas(hapd); + + return 0; +} + + +int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, + const char *txtaddr) +{ + u8 addr[ETH_ALEN]; + struct sta_info *sta; + const char *pos; + + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", + txtaddr); + + if (hwaddr_aton(txtaddr, addr)) + 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.disassoc.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; + } + +#ifdef CONFIG_P2P_MANAGER + pos = os_strstr(txtaddr, " p2p="); + if (pos) { + return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC, + atoi(pos + 5), addr); + } +#endif /* CONFIG_P2P_MANAGER */ + + hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); + sta = ap_get_sta(hapd, addr); + if (sta) + ap_sta_disassociate(hapd, sta, + WLAN_REASON_PREV_AUTH_NOT_VALID); + else if (addr[0] == 0xff) + hostapd_free_stas(hapd); + + return 0; +} diff --git a/src/ap/ctrl_iface_ap.h b/src/ap/ctrl_iface_ap.h index 0e4286d65..e83f89414 100644 --- a/src/ap/ctrl_iface_ap.h +++ b/src/ap/ctrl_iface_ap.h @@ -15,5 +15,9 @@ int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr, char *buf, size_t buflen); int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr, char *buf, size_t buflen); +int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, + const char *txtaddr); +int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, + const char *txtaddr); #endif /* CTRL_IFACE_AP_H */ diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 60462496d..52f421a1c 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -870,6 +870,26 @@ int ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr, } +int ap_ctrl_iface_sta_disassociate(struct wpa_supplicant *wpa_s, + const char *txtaddr) +{ + if (wpa_s->ap_iface == NULL) + return -1; + return hostapd_ctrl_iface_disassociate(wpa_s->ap_iface->bss[0], + txtaddr); +} + + +int ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant *wpa_s, + const char *txtaddr) +{ + if (wpa_s->ap_iface == NULL) + return -1; + return hostapd_ctrl_iface_deauthenticate(wpa_s->ap_iface->bss[0], + txtaddr); +} + + int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf, size_t buflen, int verbose) { diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h index f0eb67dad..91ab423ac 100644 --- a/wpa_supplicant/ap.h +++ b/wpa_supplicant/ap.h @@ -31,6 +31,10 @@ int ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr, char *buf, size_t buflen); int ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr, char *buf, size_t buflen); +int ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant *wpa_s, + const char *txtaddr); +int ap_ctrl_iface_sta_disassociate(struct wpa_supplicant *wpa_s, + const char *txtaddr); int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf, size_t buflen, int verbose); void ap_tx_status(void *ctx, const u8 *addr, diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index d623e91b9..11f46740a 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -4026,6 +4026,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, reply_size); + } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { + if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15)) + reply_len = -1; + } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { + if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13)) + reply_len = -1; #endif /* CONFIG_AP */ } else if (os_strcmp(buf, "SUSPEND") == 0) { wpas_notify_suspend(wpa_s->global); diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index d28641bf8..1d59bcd1d 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -1916,6 +1916,42 @@ static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) return -1; } + + +static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char buf[64]; + if (argc < 1) { + printf("Invalid 'deauthenticate' command - exactly one " + "argument, STA address, is required.\n"); + return -1; + } + 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); +} + + +static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char buf[64]; + if (argc < 1) { + printf("Invalid 'disassociate' command - exactly one " + "argument, STA address, is required.\n"); + return -1; + } + 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); +} #endif /* CONFIG_AP */ @@ -2963,6 +2999,12 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { { "all_sta", wpa_cli_cmd_all_sta, cli_cmd_flag_none, "= get information about all associated stations (AP)" }, + { "deauthenticate", wpa_cli_cmd_deauthenticate, + cli_cmd_flag_none, + " = deauthenticate a station" }, + { "disassociate", wpa_cli_cmd_disassociate, + cli_cmd_flag_none, + " = disassociate a station" }, #endif /* CONFIG_AP */ { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none, "= notification of suspend/hibernate" },