Add test commands for sending deauth/disassoc without dropping state
authorJouni Malinen <jouni.malinen@atheros.com>
Mon, 29 Mar 2010 19:01:40 +0000 (12:01 -0700)
committerJouni Malinen <j@w1.fi>
Mon, 29 Mar 2010 19:01:40 +0000 (12:01 -0700)
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

hostapd/ctrl_iface.c
hostapd/hostapd_cli.c
src/drivers/driver.h
src/drivers/driver_ndis.c
src/drivers/driver_nl80211.c

index fe32282..fca4189 100644 (file)
@@ -160,12 +160,37 @@ static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
 {
        u8 addr[ETH_ALEN];
        struct sta_info *sta;
+       const char *pos;
 
        wpa_printf(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;
+       }
+
        hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
        sta = ap_get_sta(hapd, addr);
        if (sta)
@@ -181,12 +206,37 @@ static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
 {
        u8 addr[ETH_ALEN];
        struct sta_info *sta;
+       const char *pos;
 
        wpa_printf(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.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);
        sta = ap_get_sta(hapd, addr);
        if (sta)
index 4548924..6fab4ad 100644 (file)
@@ -246,12 +246,16 @@ static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
                                          char *argv[])
 {
        char buf[64];
-       if (argc != 1) {
+       if (argc < 1) {
                printf("Invalid 'deauthenticate' command - exactly one "
                       "argument, STA address, is required.\n");
                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);
 }
 
@@ -260,12 +264,16 @@ static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
                                        char *argv[])
 {
        char buf[64];
-       if (argc != 1) {
+       if (argc < 1) {
                printf("Invalid 'disassociate' command - exactly one "
                       "argument, STA address, is required.\n");
                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);
 }
 
index 1d51a49..39bbcd9 100644 (file)
@@ -1774,6 +1774,20 @@ struct wpa_driver_ops {
         * least %hysteresis from the previously indicated signal change event.
         */
        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);
 };
 
 
index 662b1a1..6d7a1fc 100644 (file)
@@ -3275,5 +3275,6 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
        NULL /* deinit_ap */,
        NULL /* suspend */,
        NULL /* resume */,
-       NULL /* signal_monitor */
+       NULL /* signal_monitor */,
+       NULL /* send_frame */
 };
index b1007fe..70a0d07 100644 (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 = {
        .name = "nl80211",
        .desc = "Linux nl80211/cfg80211",
@@ -5297,4 +5306,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .resume = wpa_driver_nl80211_resume,
        .send_ft_action = nl80211_send_ft_action,
        .signal_monitor = nl80211_signal_monitor,
+       .send_frame = nl80211_send_frame,
 };