aboutsummaryrefslogtreecommitdiffstats
path: root/wlantest/ctrl.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2010-11-18 22:35:13 (GMT)
committerJouni Malinen <j@w1.fi>2010-11-18 22:35:13 (GMT)
commit7d23e971f0dca599ee9e1195072c200bb180e3e6 (patch)
tree084e4c0f655ea892bf614dc18527edbf14a05729 /wlantest/ctrl.c
parent6d5ce9fc90df8c7f27a80348e7362f930d28f987 (diff)
downloadhostap-7d23e971f0dca599ee9e1195072c200bb180e3e6.zip
hostap-7d23e971f0dca599ee9e1195072c200bb180e3e6.tar.gz
hostap-7d23e971f0dca599ee9e1195072c200bb180e3e6.tar.bz2
wlantest: Add preliminary infrastructure for injecting frames
This adds new commands for wlantest_cli to request wlantest to inject frames. This version can only send out Authentication frames and unprotected SA Query Request frames, but there is now place to add more frames and encryption with future commits.
Diffstat (limited to 'wlantest/ctrl.c')
-rw-r--r--wlantest/ctrl.c170
1 files changed, 170 insertions, 0 deletions
diff --git a/wlantest/ctrl.c b/wlantest/ctrl.c
index 0ca720b..b525e47 100644
--- a/wlantest/ctrl.c
+++ b/wlantest/ctrl.c
@@ -17,6 +17,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
+#include "common/ieee802_11_defs.h"
#include "wlantest.h"
#include "wlantest_ctrl.h"
@@ -49,6 +50,29 @@ static u8 * attr_get(u8 *buf, size_t buflen, enum wlantest_ctrl_attr attr,
}
+static u8 * attr_get_macaddr(u8 *buf, size_t buflen,
+ enum wlantest_ctrl_attr attr)
+{
+ u8 *addr;
+ size_t addr_len;
+ addr = attr_get(buf, buflen, attr, &addr_len);
+ if (addr && addr_len != ETH_ALEN)
+ addr = NULL;
+ return addr;
+}
+
+
+static int attr_get_int(u8 *buf, size_t buflen, enum wlantest_ctrl_attr attr)
+{
+ u8 *pos;
+ size_t len;
+ pos = attr_get(buf, buflen, attr, &len);
+ if (pos == NULL || len != 4)
+ return -1;
+ return WPA_GET_BE32(pos);
+}
+
+
static u8 * attr_add_be32(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
u32 val)
{
@@ -330,6 +354,149 @@ static void ctrl_get_bss_counter(struct wlantest *wt, int sock, u8 *cmd,
}
+static void build_mgmt_hdr(struct ieee80211_mgmt *mgmt,
+ struct wlantest_bss *bss, struct wlantest_sta *sta,
+ int sender_ap, int stype)
+{
+ os_memset(mgmt, 0, 24);
+ mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
+ if (sender_ap) {
+ if (sta)
+ os_memcpy(mgmt->da, sta->addr, ETH_ALEN);
+ else
+ os_memset(mgmt->da, 0xff, ETH_ALEN);
+ os_memcpy(mgmt->sa, bss->bssid, ETH_ALEN);
+ } else {
+ os_memcpy(mgmt->da, bss->bssid, ETH_ALEN);
+ os_memcpy(mgmt->sa, sta->addr, ETH_ALEN);
+ }
+ os_memcpy(mgmt->bssid, bss->bssid, ETH_ALEN);
+}
+
+
+static int ctrl_inject_auth(struct wlantest *wt, struct wlantest_bss *bss,
+ struct wlantest_sta *sta, int sender_ap,
+ enum wlantest_inject_protection prot)
+{
+ struct ieee80211_mgmt mgmt;
+
+ if (prot != WLANTEST_INJECT_NORMAL &&
+ prot != WLANTEST_INJECT_UNPROTECTED)
+ return -1; /* Authentication frame is never protected */
+ if (sta == NULL)
+ return -1; /* No broadcast Authentication frames */
+
+ if (sender_ap)
+ wpa_printf(MSG_INFO, "INJECT: Auth " MACSTR " -> " MACSTR,
+ MAC2STR(bss->bssid), MAC2STR(sta->addr));
+ else
+ wpa_printf(MSG_INFO, "INJECT: Auth " MACSTR " -> " MACSTR,
+ MAC2STR(sta->addr), MAC2STR(bss->bssid));
+ build_mgmt_hdr(&mgmt, bss, sta, sender_ap, WLAN_FC_STYPE_AUTH);
+
+ mgmt.u.auth.auth_alg = host_to_le16(WLAN_AUTH_OPEN);
+ mgmt.u.auth.auth_transaction = host_to_le16(1);
+ mgmt.u.auth.status_code = host_to_le16(WLAN_STATUS_SUCCESS);
+
+ return wlantest_inject(wt, bss, sta, (u8 *) &mgmt, 24 + 6,
+ WLANTEST_INJECT_UNPROTECTED);
+}
+
+
+static int ctrl_inject_saqueryreq(struct wlantest *wt,
+ struct wlantest_bss *bss,
+ struct wlantest_sta *sta, int sender_ap,
+ enum wlantest_inject_protection prot)
+{
+ struct ieee80211_mgmt mgmt;
+
+ if (sta == NULL)
+ return -1; /* No broadcast SA Query frames */
+
+ if (sender_ap)
+ wpa_printf(MSG_INFO, "INJECT: SA Query Request " MACSTR " -> "
+ MACSTR, MAC2STR(bss->bssid), MAC2STR(sta->addr));
+ else
+ wpa_printf(MSG_INFO, "INJECT: SA Query Request " MACSTR " -> "
+ MACSTR, MAC2STR(sta->addr), MAC2STR(bss->bssid));
+ build_mgmt_hdr(&mgmt, bss, sta, sender_ap, WLAN_FC_STYPE_ACTION);
+
+ mgmt.u.action.category = WLAN_ACTION_SA_QUERY;
+ mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
+ mgmt.u.action.u.sa_query_req.trans_id[0] = 0x12;
+ mgmt.u.action.u.sa_query_req.trans_id[1] = 0x34;
+ return wlantest_inject(wt, bss, sta, (u8 *) &mgmt, 24 + 4, prot);
+}
+
+
+static void ctrl_inject(struct wlantest *wt, int sock, u8 *cmd, size_t clen)
+{
+ u8 *bssid, *sta_addr;
+ struct wlantest_bss *bss;
+ struct wlantest_sta *sta;
+ int frame, sender_ap, prot;
+ int ret = 0;
+
+ bssid = attr_get_macaddr(cmd, clen, WLANTEST_ATTR_BSSID);
+ sta_addr = attr_get_macaddr(cmd, clen, WLANTEST_ATTR_STA_ADDR);
+ frame = attr_get_int(cmd, clen, WLANTEST_ATTR_INJECT_FRAME);
+ sender_ap = attr_get_int(cmd, clen, WLANTEST_ATTR_INJECT_SENDER_AP);
+ if (sender_ap < 0)
+ sender_ap = 0;
+ prot = attr_get_int(cmd, clen, WLANTEST_ATTR_INJECT_PROTECTION);
+ if (bssid == NULL || sta_addr == NULL || frame < 0 || prot < 0) {
+ wpa_printf(MSG_INFO, "Invalid inject command parameters");
+ ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD);
+ return;
+ }
+
+ bss = bss_get(wt, bssid);
+ if (bss == NULL) {
+ wpa_printf(MSG_INFO, "BSS not found for inject command");
+ ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE);
+ return;
+ }
+
+ if (is_broadcast_ether_addr(sta_addr)) {
+ if (!sender_ap) {
+ wpa_printf(MSG_INFO, "Invalid broadcast inject "
+ "command without sender_ap set");
+ ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD);
+ return;
+ } sta = NULL;
+ } else {
+ sta = sta_get(bss, sta_addr);
+ if (sta == NULL) {
+ wpa_printf(MSG_INFO, "Station not found for inject "
+ "command");
+ ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE);
+ return;
+ }
+ }
+
+ switch (frame) {
+ case WLANTEST_FRAME_AUTH:
+ ret = ctrl_inject_auth(wt, bss, sta, sender_ap, prot);
+ break;
+ case WLANTEST_FRAME_SAQUERYREQ:
+ ret = ctrl_inject_saqueryreq(wt, bss, sta, sender_ap, prot);
+ break;
+ default:
+ wpa_printf(MSG_INFO, "Unsupported inject command frame %d",
+ frame);
+ ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD);
+ return;
+ }
+
+ if (ret)
+ wpa_printf(MSG_INFO, "Failed to inject frame");
+ else
+ wpa_printf(MSG_INFO, "Frame injected successfully");
+ ctrl_send_simple(wt, sock, ret == 0 ? WLANTEST_CTRL_SUCCESS :
+ WLANTEST_CTRL_FAILURE);
+}
+
+
static void ctrl_read(int sock, void *eloop_ctx, void *sock_ctx)
{
struct wlantest *wt = eloop_ctx;
@@ -389,6 +556,9 @@ static void ctrl_read(int sock, void *eloop_ctx, void *sock_ctx)
case WLANTEST_CTRL_GET_BSS_COUNTER:
ctrl_get_bss_counter(wt, sock, buf + 4, len - 4);
break;
+ case WLANTEST_CTRL_INJECT:
+ ctrl_inject(wt, sock, buf + 4, len - 4);
+ break;
default:
ctrl_send_simple(wt, sock, WLANTEST_CTRL_UNKNOWN_CMD);
break;