Handle NULL return from os_zalloc() in sta_track_add()
[mech_eap.git] / wlantest / wlantest_cli.c
index 05e0121..ad5a48d 100644 (file)
@@ -1,15 +1,9 @@
 /*
  * wlantest controller
- * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2010-2013, Jouni Malinen <j@w1.fi>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
  */
 
 #include "utils/includes.h"
@@ -176,7 +170,7 @@ static char ** get_bssid_list(int s)
        if (bssid == NULL)
                return NULL;
 
-       res = os_zalloc((len / ETH_ALEN + 1) * sizeof(char *));
+       res = os_calloc(len / ETH_ALEN + 1, sizeof(char *));
        if (res == NULL)
                return NULL;
        for (i = 0; i < len / ETH_ALEN; i++) {
@@ -214,7 +208,7 @@ static char ** get_sta_list(int s, const u8 *bssid, int add_bcast)
        if (addr == NULL)
                return NULL;
 
-       res = os_zalloc((len / ETH_ALEN + 1 + add_bcast) * sizeof(char *));
+       res = os_calloc(len / ETH_ALEN + 1 + add_bcast, sizeof(char *));
        if (res == NULL)
                return NULL;
        for (i = 0; i < len / ETH_ALEN; i++) {
@@ -552,6 +546,10 @@ static const struct sta_counters sta_counters[] = {
        { "disassoc_rx_asleep", WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP },
        { "disassoc_rx_awake", WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE },
        { "prot_data_tx", WLANTEST_STA_COUNTER_PROT_DATA_TX },
+       { "deauth_rx_rc6", WLANTEST_STA_COUNTER_DEAUTH_RX_RC6 },
+       { "deauth_rx_rc7", WLANTEST_STA_COUNTER_DEAUTH_RX_RC7 },
+       { "disassoc_rx_rc6", WLANTEST_STA_COUNTER_DISASSOC_RX_RC6 },
+       { "disassoc_rx_rc7", WLANTEST_STA_COUNTER_DISASSOC_RX_RC7 },
        { NULL, 0 }
 };
 
@@ -624,8 +622,8 @@ static char ** complete_get_sta_counter(int s, const char *str, int pos)
        switch (arg) {
        case 1:
                /* counter list */
-               count = sizeof(sta_counters) / sizeof(sta_counters[0]);
-               res = os_zalloc(count * sizeof(char *));
+               count = ARRAY_SIZE(sta_counters);
+               res = os_calloc(count, sizeof(char *));
                if (res == NULL)
                        return NULL;
                for (i = 0; sta_counters[i].name; i++) {
@@ -659,6 +657,7 @@ static const struct bss_counters bss_counters[] = {
        { "missing_bip_mmie", WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE },
        { "bip_deauth", WLANTEST_BSS_COUNTER_BIP_DEAUTH },
        { "bip_disassoc", WLANTEST_BSS_COUNTER_BIP_DISASSOC },
+       { "probe_response", WLANTEST_BSS_COUNTER_PROBE_RESPONSE },
        { NULL, 0 }
 };
 
@@ -723,8 +722,8 @@ static char ** complete_get_bss_counter(int s, const char *str, int pos)
        switch (arg) {
        case 1:
                /* counter list */
-               count = sizeof(bss_counters) / sizeof(bss_counters[0]);
-               res = os_zalloc(count * sizeof(char *));
+               count = ARRAY_SIZE(bss_counters);
+               res = os_calloc(count, sizeof(char *));
                if (res == NULL)
                        return NULL;
                for (i = 0; bss_counters[i].name; i++) {
@@ -742,6 +741,12 @@ static char ** complete_get_bss_counter(int s, const char *str, int pos)
 }
 
 
+static int cmd_relog(int s, int argc, char *argv[])
+{
+       return cmd_simple(s, WLANTEST_CTRL_RELOG);
+}
+
+
 struct tdls_counters {
        const char *name;
        enum wlantest_tdls_counter num;
@@ -757,6 +762,7 @@ static const struct tdls_counters tdls_counters[] = {
        { "setup_resp_fail", WLANTEST_TDLS_COUNTER_SETUP_RESP_FAIL },
        { "setup_conf_ok", WLANTEST_TDLS_COUNTER_SETUP_CONF_OK },
        { "setup_conf_fail", WLANTEST_TDLS_COUNTER_SETUP_CONF_FAIL },
+       { "teardown", WLANTEST_TDLS_COUNTER_TEARDOWN },
        { NULL, 0 }
 };
 
@@ -836,8 +842,8 @@ static char ** complete_get_tdls_counter(int s, const char *str, int pos)
        switch (arg) {
        case 1:
                /* counter list */
-               count = sizeof(tdls_counters) / sizeof(tdls_counters[0]);
-               res = os_zalloc(count * sizeof(char *));
+               count = ARRAY_SIZE(tdls_counters);
+               res = os_calloc(count, sizeof(char *));
                if (res == NULL)
                        return NULL;
                for (i = 0; tdls_counters[i].name; i++) {
@@ -972,8 +978,8 @@ static char ** complete_inject(int s, const char *str, int pos)
        switch (arg) {
        case 1:
                /* frame list */
-               count = sizeof(inject_frames) / sizeof(inject_frames[0]);
-               res = os_zalloc(count * sizeof(char *));
+               count = ARRAY_SIZE(inject_frames);
+               res = os_calloc(count, sizeof(char *));
                if (res == NULL)
                        break;
                for (i = 0; inject_frames[i].name; i++) {
@@ -983,7 +989,7 @@ static char ** complete_inject(int s, const char *str, int pos)
                }
                break;
        case 2:
-               res = os_zalloc(5 * sizeof(char *));
+               res = os_calloc(5, sizeof(char *));
                if (res == NULL)
                        break;
                res[0] = os_strdup("normal");
@@ -1000,7 +1006,7 @@ static char ** complete_inject(int s, const char *str, int pos)
                        break;
                break;
        case 3:
-               res = os_zalloc(3 * sizeof(char *));
+               res = os_calloc(3, sizeof(char *));
                if (res == NULL)
                        break;
                res[0] = os_strdup("ap");
@@ -1123,7 +1129,7 @@ static char ** complete_send(int s, const char *str, int pos)
 
        switch (arg) {
        case 1:
-               res = os_zalloc(5 * sizeof(char *));
+               res = os_calloc(5, sizeof(char *));
                if (res == NULL)
                        break;
                res[0] = os_strdup("normal");
@@ -1210,6 +1216,30 @@ static int cmd_add_passphrase(int s, int argc, char *argv[])
 }
 
 
+static int cmd_add_wepkey(int s, int argc, char *argv[])
+{
+       u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
+       u8 buf[100], *pos, *end;
+       int rlen;
+
+       if (argc < 1) {
+               printf("add_wepkey needs one argument: WEP key\n");
+               return -1;
+       }
+
+       pos = buf;
+       end = buf + sizeof(buf);
+       WPA_PUT_BE32(pos, WLANTEST_CTRL_ADD_PASSPHRASE);
+       pos += 4;
+       pos = attr_add_str(pos, end, WLANTEST_ATTR_WEPKEY, argv[0]);
+
+       rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
+       if (rlen < 0)
+               return -1;
+       return 0;
+}
+
+
 struct sta_infos {
        const char *name;
        enum wlantest_sta_info num;
@@ -1221,6 +1251,7 @@ static const struct sta_infos sta_infos[] = {
        { "key_mgmt", WLANTEST_STA_INFO_KEY_MGMT },
        { "rsn_capab", WLANTEST_STA_INFO_RSN_CAPAB },
        { "state", WLANTEST_STA_INFO_STATE },
+       { "gtk", WLANTEST_STA_INFO_GTK },
        { NULL, 0 }
 };
 
@@ -1298,8 +1329,8 @@ static char ** complete_info_sta(int s, const char *str, int pos)
        switch (arg) {
        case 1:
                /* counter list */
-               count = sizeof(sta_infos) / sizeof(sta_infos[0]);
-               res = os_zalloc(count * sizeof(char *));
+               count = ARRAY_SIZE(sta_infos);
+               res = os_calloc(count, sizeof(char *));
                if (res == NULL)
                        return NULL;
                for (i = 0; sta_infos[i].name; i++) {
@@ -1403,8 +1434,8 @@ static char ** complete_info_bss(int s, const char *str, int pos)
        switch (arg) {
        case 1:
                /* counter list */
-               count = sizeof(bss_infos) / sizeof(bss_infos[0]);
-               res = os_zalloc(count * sizeof(char *));
+               count = ARRAY_SIZE(bss_infos);
+               res = os_calloc(count, sizeof(char *));
                if (res == NULL)
                        return NULL;
                for (i = 0; bss_infos[i].name; i++) {
@@ -1422,6 +1453,119 @@ static char ** complete_info_bss(int s, const char *str, int pos)
 }
 
 
+static int cmd_get_tx_tid(int s, int argc, char *argv[])
+{
+       u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
+       u8 buf[100], *end, *pos;
+       int rlen;
+       size_t len;
+
+       if (argc != 3) {
+               printf("get_tx_tid needs three arguments: "
+                      "BSSID, STA address, and TID\n");
+               return -1;
+       }
+
+       pos = buf;
+       end = buf + sizeof(buf);
+       WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_TX_TID);
+       pos += 4;
+
+       pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
+       if (hwaddr_aton(argv[0], pos) < 0) {
+               printf("Invalid BSSID '%s'\n", argv[0]);
+               return -1;
+       }
+       pos += ETH_ALEN;
+
+       pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
+       if (hwaddr_aton(argv[1], pos) < 0) {
+               printf("Invalid STA address '%s'\n", argv[1]);
+               return -1;
+       }
+       pos += ETH_ALEN;
+
+       pos = attr_add_be32(pos, end, WLANTEST_ATTR_TID, atoi(argv[2]));
+
+       rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
+       if (rlen < 0)
+               return -1;
+
+       pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
+       if (pos == NULL || len != 4)
+               return -1;
+       printf("%u\n", WPA_GET_BE32(pos));
+       return 0;
+}
+
+
+static int cmd_get_rx_tid(int s, int argc, char *argv[])
+{
+       u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
+       u8 buf[100], *end, *pos;
+       int rlen;
+       size_t len;
+
+       if (argc != 3) {
+               printf("get_tx_tid needs three arguments: "
+                      "BSSID, STA address, and TID\n");
+               return -1;
+       }
+
+       pos = buf;
+       end = buf + sizeof(buf);
+       WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_RX_TID);
+       pos += 4;
+
+       pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
+       if (hwaddr_aton(argv[0], pos) < 0) {
+               printf("Invalid BSSID '%s'\n", argv[0]);
+               return -1;
+       }
+       pos += ETH_ALEN;
+
+       pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
+       if (hwaddr_aton(argv[1], pos) < 0) {
+               printf("Invalid STA address '%s'\n", argv[1]);
+               return -1;
+       }
+       pos += ETH_ALEN;
+
+       pos = attr_add_be32(pos, end, WLANTEST_ATTR_TID, atoi(argv[2]));
+
+       rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
+       if (rlen < 0)
+               return -1;
+
+       pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
+       if (pos == NULL || len != 4)
+               return -1;
+       printf("%u\n", WPA_GET_BE32(pos));
+       return 0;
+}
+
+
+static char ** complete_get_tid(int s, const char *str, int pos)
+{
+       int arg = get_cmd_arg_num(str, pos);
+       char **res = NULL;
+       u8 addr[ETH_ALEN];
+
+       switch (arg) {
+       case 1:
+               res = get_bssid_list(s);
+               break;
+       case 2:
+               if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
+                       break;
+               res = get_sta_list(s, addr, 0);
+               break;
+       }
+
+       return res;
+}
+
+
 struct wlantest_cli_cmd {
        const char *cmd;
        int (*handler)(int s, int argc, char *argv[]);
@@ -1455,6 +1599,8 @@ static const struct wlantest_cli_cmd wlantest_cli_commands[] = {
        { "version", cmd_version, "= get wlantest version", NULL },
        { "add_passphrase", cmd_add_passphrase,
          "<passphrase> = add a known passphrase", NULL },
+       { "add_wepkey", cmd_add_wepkey,
+         "<WEP key> = add a known WEP key", NULL },
        { "info_sta", cmd_info_sta,
          "<field> <BSSID> <STA> = get STA information",
          complete_info_sta },
@@ -1470,6 +1616,13 @@ static const struct wlantest_cli_cmd wlantest_cli_commands[] = {
        { "get_bss_counter", cmd_get_bss_counter,
          "<counter> <BSSID> = get BSS counter value",
          complete_get_bss_counter },
+       { "relog", cmd_relog, "= re-open log-file (allow rolling logs)", NULL },
+       { "get_tx_tid", cmd_get_tx_tid,
+         "<BSSID> <STA> <TID> = get STA TX TID counter value",
+         complete_get_tid },
+       { "get_rx_tid", cmd_get_rx_tid,
+         "<BSSID> <STA> <TID> = get STA RX TID counter value",
+         complete_get_tid },
        { NULL, NULL, NULL, NULL }
 };
 
@@ -1580,11 +1733,9 @@ static void wlantest_cli_edit_eof_cb(void *ctx)
 static char ** wlantest_cli_cmd_list(void)
 {
        char **res;
-       int i, count;
+       int i;
 
-       count = sizeof(wlantest_cli_commands) /
-               sizeof(wlantest_cli_commands[0]);
-       res = os_zalloc(count * sizeof(char *));
+       res = os_calloc(ARRAY_SIZE(wlantest_cli_commands), sizeof(char *));
        if (res == NULL)
                return NULL;
 
@@ -1663,7 +1814,7 @@ static void wlantest_cli_interactive(int s)
        cli.s = s;
        eloop_register_signal_terminate(wlantest_cli_eloop_terminate, &cli);
        edit_init(wlantest_cli_edit_cmd_cb, wlantest_cli_edit_eof_cb,
-                 wlantest_cli_edit_completion_cb, &cli, hfile);
+                 wlantest_cli_edit_completion_cb, &cli, hfile, NULL);
 
        eloop_run();