Add DATA_TEST_FRAME for testing Data frame processing on AP side
authorJouni Malinen <jouni@qca.qualcomm.com>
Fri, 28 Nov 2014 17:26:11 +0000 (19:26 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 28 Nov 2014 20:37:05 +0000 (22:37 +0200)
The new hostapd control interface command can be used in automated
testing to verify how AP processes Data frames with arbitrary contents.
This is enabled only in builds with CONFIG_TESTING_OPTIONS=y.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
hostapd/ctrl_iface.c

index 33cb8bc..14f128b 100644 (file)
@@ -1641,6 +1641,57 @@ static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
        return 0;
 }
 
+
+static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
+                                             char *cmd)
+{
+       u8 *buf;
+       struct ether_header *eth;
+       struct l2_packet_data *l2 = NULL;
+       size_t len;
+       u16 ethertype;
+       int res = -1;
+       const char *ifname = hapd->conf->iface;
+
+       if (os_strncmp(cmd, "ifname=", 7) == 0) {
+               cmd += 7;
+               ifname = cmd;
+               cmd = os_strchr(cmd, ' ');
+               if (cmd == NULL)
+                       return -1;
+               *cmd++ = '\0';
+       }
+
+       len = os_strlen(cmd);
+       if (len & 1 || len < ETH_HLEN * 2)
+               return -1;
+       len /= 2;
+
+       buf = os_malloc(len);
+       if (buf == NULL)
+               return -1;
+
+       if (hexstr2bin(cmd, buf, len) < 0)
+               goto done;
+
+       eth = (struct ether_header *) buf;
+       ethertype = ntohs(eth->ether_type);
+
+       l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
+                           hostapd_data_test_rx, hapd, 1);
+       if (l2 == NULL)
+               goto done;
+
+       res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
+       wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
+done:
+       if (l2)
+               l2_packet_deinit(l2);
+       os_free(buf);
+
+       return res < 0 ? -1 : 0;
+}
+
 #endif /* CONFIG_TESTING_OPTIONS */
 
 
@@ -1958,6 +2009,9 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
        } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
                if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
                        reply_len = -1;
+       } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
+               if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
+                       reply_len = -1;
 #endif /* CONFIG_TESTING_OPTIONS */
        } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
                if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))