3 * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
15 #include "utils/includes.h"
18 #include "utils/common.h"
19 #include "utils/eloop.h"
20 #include "utils/edit.h"
21 #include "wlantest_ctrl.h"
24 static int get_cmd_arg_num(const char *str, int pos)
28 for (i = 0; i <= pos; i++) {
31 while (i <= pos && str[i] != ' ')
42 static int get_prev_arg_pos(const char *str, int pos)
44 while (pos > 0 && str[pos - 1] != ' ')
46 while (pos > 0 && str[pos - 1] == ' ')
48 while (pos > 0 && str[pos - 1] != ' ')
54 static u8 * attr_get(u8 *buf, size_t buflen, enum wlantest_ctrl_attr attr,
59 while (pos + 8 <= buf + buflen) {
60 enum wlantest_ctrl_attr a;
62 a = WPA_GET_BE32(pos);
64 alen = WPA_GET_BE32(pos);
66 if (pos + alen > buf + buflen) {
67 printf("Invalid control message attribute\n");
81 static u8 * attr_hdr_add(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
84 if (pos == NULL || end - pos < 8 + len)
86 WPA_PUT_BE32(pos, attr);
88 WPA_PUT_BE32(pos, len);
94 static u8 * attr_add_str(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
97 size_t len = os_strlen(str);
99 if (pos == NULL || end - pos < 8 + len)
101 WPA_PUT_BE32(pos, attr);
103 WPA_PUT_BE32(pos, len);
105 os_memcpy(pos, str, len);
111 static u8 * attr_add_be32(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
114 if (pos == NULL || end - pos < 12)
116 WPA_PUT_BE32(pos, attr);
118 WPA_PUT_BE32(pos, 4);
120 WPA_PUT_BE32(pos, val);
126 static int cmd_send_and_recv(int s, const u8 *cmd, size_t cmd_len,
127 u8 *resp, size_t max_resp_len)
130 enum wlantest_ctrl_cmd cmd_resp;
132 if (send(s, cmd, cmd_len, 0) < 0)
134 res = recv(s, resp, max_resp_len, 0);
138 cmd_resp = WPA_GET_BE32(resp);
139 if (cmd_resp == WLANTEST_CTRL_SUCCESS)
142 if (cmd_resp == WLANTEST_CTRL_UNKNOWN_CMD)
143 printf("Unknown command\n");
144 else if (cmd_resp == WLANTEST_CTRL_INVALID_CMD)
145 printf("Invalid command\n");
151 static int cmd_simple(int s, enum wlantest_ctrl_cmd cmd)
155 WPA_PUT_BE32(buf, cmd);
156 res = cmd_send_and_recv(s, buf, sizeof(buf), buf, sizeof(buf));
157 return res < 0 ? -1 : 0;
161 static char ** get_bssid_list(int s)
163 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
170 WPA_PUT_BE32(buf, WLANTEST_CTRL_LIST_BSS);
171 rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
175 bssid = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_BSSID, &len);
179 res = os_zalloc((len / ETH_ALEN + 1) * sizeof(char *));
182 for (i = 0; i < len / ETH_ALEN; i++) {
183 res[i] = os_zalloc(18);
186 os_snprintf(res[i], 18, MACSTR, MAC2STR(bssid + ETH_ALEN * i));
193 static char ** get_sta_list(int s, const u8 *bssid, int add_bcast)
195 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
196 u8 buf[100], *pos, *end;
203 end = buf + sizeof(buf);
204 WPA_PUT_BE32(pos, WLANTEST_CTRL_LIST_STA);
206 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
207 os_memcpy(pos, bssid, ETH_ALEN);
209 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
213 addr = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_STA_ADDR, &len);
217 res = os_zalloc((len / ETH_ALEN + 1 + add_bcast) * sizeof(char *));
220 for (i = 0; i < len / ETH_ALEN; i++) {
221 res[i] = os_zalloc(18);
224 os_snprintf(res[i], 18, MACSTR, MAC2STR(addr + ETH_ALEN * i));
227 res[i] = os_strdup("ff:ff:ff:ff:ff:ff");
233 static int cmd_ping(int s, int argc, char *argv[])
235 int res = cmd_simple(s, WLANTEST_CTRL_PING);
242 static int cmd_terminate(int s, int argc, char *argv[])
244 return cmd_simple(s, WLANTEST_CTRL_TERMINATE);
248 static int cmd_list_bss(int s, int argc, char *argv[])
250 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
256 WPA_PUT_BE32(buf, WLANTEST_CTRL_LIST_BSS);
257 rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
261 bssid = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_BSSID, &len);
265 for (i = 0; i < len / ETH_ALEN; i++)
266 printf(MACSTR " ", MAC2STR(bssid + ETH_ALEN * i));
273 static int cmd_list_sta(int s, int argc, char *argv[])
275 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
282 printf("list_sta needs one argument: BSSID\n");
287 WPA_PUT_BE32(pos, WLANTEST_CTRL_LIST_STA);
289 WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
291 WPA_PUT_BE32(pos, ETH_ALEN);
293 if (hwaddr_aton(argv[0], pos) < 0) {
294 printf("Invalid BSSID '%s'\n", argv[0]);
299 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
303 addr = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_STA_ADDR, &len);
307 for (i = 0; i < len / ETH_ALEN; i++)
308 printf(MACSTR " ", MAC2STR(addr + ETH_ALEN * i));
315 static char ** complete_list_sta(int s, const char *str, int pos)
317 if (get_cmd_arg_num(str, pos) == 1)
318 return get_bssid_list(s);
323 static int cmd_flush(int s, int argc, char *argv[])
325 return cmd_simple(s, WLANTEST_CTRL_FLUSH);
329 static int cmd_clear_sta_counters(int s, int argc, char *argv[])
331 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
336 printf("clear_sta_counters needs two arguments: BSSID and "
342 WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_STA_COUNTERS);
344 WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
346 WPA_PUT_BE32(pos, ETH_ALEN);
348 if (hwaddr_aton(argv[0], pos) < 0) {
349 printf("Invalid BSSID '%s'\n", argv[0]);
354 WPA_PUT_BE32(pos, WLANTEST_ATTR_STA_ADDR);
356 WPA_PUT_BE32(pos, ETH_ALEN);
358 if (hwaddr_aton(argv[1], pos) < 0) {
359 printf("Invalid STA address '%s'\n", argv[1]);
364 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
372 static char ** complete_clear_sta_counters(int s, const char *str, int pos)
374 int arg = get_cmd_arg_num(str, pos);
380 res = get_bssid_list(s);
383 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
385 res = get_sta_list(s, addr, 0);
393 static int cmd_clear_bss_counters(int s, int argc, char *argv[])
395 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
400 printf("clear_bss_counters needs one argument: BSSID\n");
405 WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_BSS_COUNTERS);
407 WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
409 WPA_PUT_BE32(pos, ETH_ALEN);
411 if (hwaddr_aton(argv[0], pos) < 0) {
412 printf("Invalid BSSID '%s'\n", argv[0]);
417 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
425 static char ** complete_clear_bss_counters(int s, const char *str, int pos)
427 if (get_cmd_arg_num(str, pos) == 1)
428 return get_bssid_list(s);
433 static int cmd_clear_tdls_counters(int s, int argc, char *argv[])
435 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
440 printf("clear_tdls_counters needs three arguments: BSSID, "
441 "STA1 address, STA2 address\n");
446 WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_TDLS_COUNTERS);
448 WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
450 WPA_PUT_BE32(pos, ETH_ALEN);
452 if (hwaddr_aton(argv[0], pos) < 0) {
453 printf("Invalid BSSID '%s'\n", argv[0]);
458 WPA_PUT_BE32(pos, WLANTEST_ATTR_STA_ADDR);
460 WPA_PUT_BE32(pos, ETH_ALEN);
462 if (hwaddr_aton(argv[1], pos) < 0) {
463 printf("Invalid STA1 address '%s'\n", argv[1]);
468 WPA_PUT_BE32(pos, WLANTEST_ATTR_STA2_ADDR);
470 WPA_PUT_BE32(pos, ETH_ALEN);
472 if (hwaddr_aton(argv[2], pos) < 0) {
473 printf("Invalid STA2 address '%s'\n", argv[2]);
478 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
486 static char ** complete_clear_tdls_counters(int s, const char *str, int pos)
488 int arg = get_cmd_arg_num(str, pos);
494 res = get_bssid_list(s);
498 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
500 res = get_sta_list(s, addr, 0);
508 struct sta_counters {
510 enum wlantest_sta_counter num;
513 static const struct sta_counters sta_counters[] = {
514 { "auth_tx", WLANTEST_STA_COUNTER_AUTH_TX },
515 { "auth_rx", WLANTEST_STA_COUNTER_AUTH_RX },
516 { "assocreq_tx", WLANTEST_STA_COUNTER_ASSOCREQ_TX },
517 { "reassocreq_tx", WLANTEST_STA_COUNTER_REASSOCREQ_TX },
518 { "ptk_learned", WLANTEST_STA_COUNTER_PTK_LEARNED },
519 { "valid_deauth_tx", WLANTEST_STA_COUNTER_VALID_DEAUTH_TX },
520 { "valid_deauth_rx", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX },
521 { "invalid_deauth_tx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX },
522 { "invalid_deauth_rx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX },
523 { "valid_disassoc_tx", WLANTEST_STA_COUNTER_VALID_DISASSOC_TX },
524 { "valid_disassoc_rx", WLANTEST_STA_COUNTER_VALID_DISASSOC_RX },
525 { "invalid_disassoc_tx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX },
526 { "invalid_disassoc_rx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX },
527 { "valid_saqueryreq_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX },
528 { "valid_saqueryreq_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX },
529 { "invalid_saqueryreq_tx",
530 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX },
531 { "invalid_saqueryreq_rx",
532 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX },
533 { "valid_saqueryresp_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX },
534 { "valid_saqueryresp_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX },
535 { "invalid_saqueryresp_tx",
536 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX },
537 { "invalid_saqueryresp_rx",
538 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX },
539 { "ping_ok", WLANTEST_STA_COUNTER_PING_OK },
540 { "assocresp_comeback", WLANTEST_STA_COUNTER_ASSOCRESP_COMEBACK },
541 { "reassocresp_comeback", WLANTEST_STA_COUNTER_REASSOCRESP_COMEBACK },
542 { "ping_ok_first_assoc", WLANTEST_STA_COUNTER_PING_OK_FIRST_ASSOC },
543 { "valid_deauth_rx_ack", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX_ACK },
544 { "valid_disassoc_rx_ack",
545 WLANTEST_STA_COUNTER_VALID_DISASSOC_RX_ACK },
546 { "invalid_deauth_rx_ack",
547 WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX_ACK },
548 { "invalid_disassoc_rx_ack",
549 WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX_ACK },
550 { "deauth_rx_asleep", WLANTEST_STA_COUNTER_DEAUTH_RX_ASLEEP },
551 { "deauth_rx_awake", WLANTEST_STA_COUNTER_DEAUTH_RX_AWAKE },
552 { "disassoc_rx_asleep", WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP },
553 { "disassoc_rx_awake", WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE },
554 { "prot_data_tx", WLANTEST_STA_COUNTER_PROT_DATA_TX },
558 static int cmd_get_sta_counter(int s, int argc, char *argv[])
560 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
561 u8 buf[100], *end, *pos;
566 printf("get_sta_counter needs at three arguments: "
567 "counter name, BSSID, and STA address\n");
572 end = buf + sizeof(buf);
573 WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_STA_COUNTER);
576 for (i = 0; sta_counters[i].name; i++) {
577 if (os_strcasecmp(sta_counters[i].name, argv[0]) == 0)
580 if (sta_counters[i].name == NULL) {
581 printf("Unknown STA counter '%s'\n", argv[0]);
583 for (i = 0; sta_counters[i].name; i++)
584 printf(" %s", sta_counters[i].name);
589 pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_COUNTER,
590 sta_counters[i].num);
591 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
592 if (hwaddr_aton(argv[1], pos) < 0) {
593 printf("Invalid BSSID '%s'\n", argv[1]);
598 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
599 if (hwaddr_aton(argv[2], pos) < 0) {
600 printf("Invalid STA address '%s'\n", argv[2]);
605 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
609 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
610 if (pos == NULL || len != 4)
612 printf("%u\n", WPA_GET_BE32(pos));
617 static char ** complete_get_sta_counter(int s, const char *str, int pos)
619 int arg = get_cmd_arg_num(str, pos);
627 count = sizeof(sta_counters) / sizeof(sta_counters[0]);
628 res = os_zalloc(count * sizeof(char *));
631 for (i = 0; sta_counters[i].name; i++) {
632 res[i] = os_strdup(sta_counters[i].name);
638 res = get_bssid_list(s);
641 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
643 res = get_sta_list(s, addr, 0);
651 struct bss_counters {
653 enum wlantest_bss_counter num;
656 static const struct bss_counters bss_counters[] = {
657 { "valid_bip_mmie", WLANTEST_BSS_COUNTER_VALID_BIP_MMIE },
658 { "invalid_bip_mmie", WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE },
659 { "missing_bip_mmie", WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE },
660 { "bip_deauth", WLANTEST_BSS_COUNTER_BIP_DEAUTH },
661 { "bip_disassoc", WLANTEST_BSS_COUNTER_BIP_DISASSOC },
665 static int cmd_get_bss_counter(int s, int argc, char *argv[])
667 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
668 u8 buf[100], *end, *pos;
673 printf("get_bss_counter needs at two arguments: "
674 "counter name and BSSID\n");
679 end = buf + sizeof(buf);
680 WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_BSS_COUNTER);
683 for (i = 0; bss_counters[i].name; i++) {
684 if (os_strcasecmp(bss_counters[i].name, argv[0]) == 0)
687 if (bss_counters[i].name == NULL) {
688 printf("Unknown BSS counter '%s'\n", argv[0]);
690 for (i = 0; bss_counters[i].name; i++)
691 printf(" %s", bss_counters[i].name);
696 pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_COUNTER,
697 bss_counters[i].num);
698 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
699 if (hwaddr_aton(argv[1], pos) < 0) {
700 printf("Invalid BSSID '%s'\n", argv[1]);
705 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
709 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
710 if (pos == NULL || len != 4)
712 printf("%u\n", WPA_GET_BE32(pos));
717 static char ** complete_get_bss_counter(int s, const char *str, int pos)
719 int arg = get_cmd_arg_num(str, pos);
726 count = sizeof(bss_counters) / sizeof(bss_counters[0]);
727 res = os_zalloc(count * sizeof(char *));
730 for (i = 0; bss_counters[i].name; i++) {
731 res[i] = os_strdup(bss_counters[i].name);
737 res = get_bssid_list(s);
745 struct tdls_counters {
747 enum wlantest_tdls_counter num;
750 static const struct tdls_counters tdls_counters[] = {
751 { "valid_direct_link", WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK },
752 { "invalid_direct_link", WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK },
753 { "valid_ap_path", WLANTEST_TDLS_COUNTER_VALID_AP_PATH },
754 { "invalid_ap_path", WLANTEST_TDLS_COUNTER_INVALID_AP_PATH },
758 static int cmd_get_tdls_counter(int s, int argc, char *argv[])
760 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
761 u8 buf[100], *end, *pos;
766 printf("get_tdls_counter needs four arguments: "
767 "counter name, BSSID, STA1 address, STA2 address\n");
772 end = buf + sizeof(buf);
773 WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_TDLS_COUNTER);
776 for (i = 0; tdls_counters[i].name; i++) {
777 if (os_strcasecmp(tdls_counters[i].name, argv[0]) == 0)
780 if (tdls_counters[i].name == NULL) {
781 printf("Unknown TDLS counter '%s'\n", argv[0]);
783 for (i = 0; tdls_counters[i].name; i++)
784 printf(" %s", tdls_counters[i].name);
789 pos = attr_add_be32(pos, end, WLANTEST_ATTR_TDLS_COUNTER,
790 tdls_counters[i].num);
791 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
792 if (hwaddr_aton(argv[1], pos) < 0) {
793 printf("Invalid BSSID '%s'\n", argv[1]);
798 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
799 if (hwaddr_aton(argv[2], pos) < 0) {
800 printf("Invalid STA1 address '%s'\n", argv[2]);
805 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA2_ADDR, ETH_ALEN);
806 if (hwaddr_aton(argv[3], pos) < 0) {
807 printf("Invalid STA2 address '%s'\n", argv[3]);
812 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
816 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
817 if (pos == NULL || len != 4)
819 printf("%u\n", WPA_GET_BE32(pos));
824 static char ** complete_get_tdls_counter(int s, const char *str, int pos)
826 int arg = get_cmd_arg_num(str, pos);
834 count = sizeof(tdls_counters) / sizeof(tdls_counters[0]);
835 res = os_zalloc(count * sizeof(char *));
838 for (i = 0; tdls_counters[i].name; i++) {
839 res[i] = os_strdup(tdls_counters[i].name);
845 res = get_bssid_list(s);
849 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
851 res = get_sta_list(s, addr, 0);
859 struct inject_frames {
861 enum wlantest_inject_frame frame;
864 static const struct inject_frames inject_frames[] = {
865 { "auth", WLANTEST_FRAME_AUTH },
866 { "assocreq", WLANTEST_FRAME_ASSOCREQ },
867 { "reassocreq", WLANTEST_FRAME_REASSOCREQ },
868 { "deauth", WLANTEST_FRAME_DEAUTH },
869 { "disassoc", WLANTEST_FRAME_DISASSOC },
870 { "saqueryreq", WLANTEST_FRAME_SAQUERYREQ },
874 static int cmd_inject(int s, int argc, char *argv[])
876 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
877 u8 buf[100], *end, *pos;
879 enum wlantest_inject_protection prot;
881 /* <frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff> */
884 printf("inject needs five arguments: frame, protection, "
885 "sender, BSSID, STA/ff:ff:ff:ff:ff:ff\n");
890 end = buf + sizeof(buf);
891 WPA_PUT_BE32(pos, WLANTEST_CTRL_INJECT);
894 for (i = 0; inject_frames[i].name; i++) {
895 if (os_strcasecmp(inject_frames[i].name, argv[0]) == 0)
898 if (inject_frames[i].name == NULL) {
899 printf("Unknown inject frame '%s'\n", argv[0]);
901 for (i = 0; inject_frames[i].name; i++)
902 printf(" %s", inject_frames[i].name);
907 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_FRAME,
908 inject_frames[i].frame);
910 if (os_strcasecmp(argv[1], "normal") == 0)
911 prot = WLANTEST_INJECT_NORMAL;
912 else if (os_strcasecmp(argv[1], "protected") == 0)
913 prot = WLANTEST_INJECT_PROTECTED;
914 else if (os_strcasecmp(argv[1], "unprotected") == 0)
915 prot = WLANTEST_INJECT_UNPROTECTED;
916 else if (os_strcasecmp(argv[1], "incorrect") == 0)
917 prot = WLANTEST_INJECT_INCORRECT_KEY;
919 printf("Unknown protection type '%s'\n", argv[1]);
920 printf("Protection types: normal protected unprotected "
924 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot);
926 if (os_strcasecmp(argv[2], "ap") == 0) {
927 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
929 } else if (os_strcasecmp(argv[2], "sta") == 0) {
930 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
933 printf("Unknown sender '%s'\n", argv[2]);
934 printf("Sender types: ap sta\n");
938 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
939 if (hwaddr_aton(argv[3], pos) < 0) {
940 printf("Invalid BSSID '%s'\n", argv[3]);
945 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
946 if (hwaddr_aton(argv[4], pos) < 0) {
947 printf("Invalid STA '%s'\n", argv[4]);
952 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
960 static char ** complete_inject(int s, const char *str, int pos)
962 int arg = get_cmd_arg_num(str, pos);
970 count = sizeof(inject_frames) / sizeof(inject_frames[0]);
971 res = os_zalloc(count * sizeof(char *));
974 for (i = 0; inject_frames[i].name; i++) {
975 res[i] = os_strdup(inject_frames[i].name);
981 res = os_zalloc(5 * sizeof(char *));
984 res[0] = os_strdup("normal");
987 res[1] = os_strdup("protected");
990 res[2] = os_strdup("unprotected");
993 res[3] = os_strdup("incorrect");
998 res = os_zalloc(3 * sizeof(char *));
1001 res[0] = os_strdup("ap");
1004 res[1] = os_strdup("sta");
1009 res = get_bssid_list(s);
1012 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
1014 res = get_sta_list(s, addr, 1);
1022 static u8 * add_hex(u8 *pos, u8 *end, const char *str)
1029 while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n' ||
1035 while (*s != '\0' && *s != '\r' && *s != '\n')
1042 printf("Invalid hex encoding '%s'\n", s);
1046 printf("Too long frame\n");
1057 static int cmd_send(int s, int argc, char *argv[])
1059 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1060 u8 buf[WLANTEST_CTRL_MAX_CMD_LEN], *end, *pos, *len_pos;
1062 enum wlantest_inject_protection prot;
1065 /* <prot> <raw frame as hex dump> */
1068 printf("send needs two arguments: protected/unprotected, "
1069 "raw frame as hex dump\n");
1074 end = buf + sizeof(buf);
1075 WPA_PUT_BE32(pos, WLANTEST_CTRL_SEND);
1078 if (os_strcasecmp(argv[0], "normal") == 0)
1079 prot = WLANTEST_INJECT_NORMAL;
1080 else if (os_strcasecmp(argv[0], "protected") == 0)
1081 prot = WLANTEST_INJECT_PROTECTED;
1082 else if (os_strcasecmp(argv[0], "unprotected") == 0)
1083 prot = WLANTEST_INJECT_UNPROTECTED;
1084 else if (os_strcasecmp(argv[0], "incorrect") == 0)
1085 prot = WLANTEST_INJECT_INCORRECT_KEY;
1087 printf("Unknown protection type '%s'\n", argv[1]);
1088 printf("Protection types: normal protected unprotected "
1092 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot);
1094 WPA_PUT_BE32(pos, WLANTEST_ATTR_FRAME);
1099 for (arg = 1; pos && arg < argc; arg++)
1100 pos = add_hex(pos, end, argv[arg]);
1104 WPA_PUT_BE32(len_pos, pos - len_pos - 4);
1106 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1114 static char ** complete_send(int s, const char *str, int pos)
1116 int arg = get_cmd_arg_num(str, pos);
1121 res = os_zalloc(5 * sizeof(char *));
1124 res[0] = os_strdup("normal");
1127 res[1] = os_strdup("protected");
1130 res[2] = os_strdup("unprotected");
1133 res[3] = os_strdup("incorrect");
1143 static int cmd_version(int s, int argc, char *argv[])
1145 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1151 WPA_PUT_BE32(buf, WLANTEST_CTRL_VERSION);
1152 rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
1156 version = (char *) attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_VERSION,
1158 if (version == NULL)
1161 for (i = 0; i < len; i++)
1162 putchar(version[i]);
1169 static int cmd_add_passphrase(int s, int argc, char *argv[])
1171 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1172 u8 buf[100], *pos, *end;
1177 printf("add_passphrase needs one argument: passphrase\n");
1181 len = os_strlen(argv[0]);
1182 if (len < 8 || len > 63) {
1183 printf("Invalid passphrase '%s'\n", argv[0]);
1187 end = buf + sizeof(buf);
1188 WPA_PUT_BE32(pos, WLANTEST_CTRL_ADD_PASSPHRASE);
1190 pos = attr_add_str(pos, end, WLANTEST_ATTR_PASSPHRASE,
1193 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1194 if (hwaddr_aton(argv[1], pos) < 0) {
1195 printf("Invalid BSSID '%s'\n", argv[3]);
1201 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1210 enum wlantest_sta_info num;
1213 static const struct sta_infos sta_infos[] = {
1214 { "proto", WLANTEST_STA_INFO_PROTO },
1215 { "pairwise", WLANTEST_STA_INFO_PAIRWISE },
1216 { "key_mgmt", WLANTEST_STA_INFO_KEY_MGMT },
1217 { "rsn_capab", WLANTEST_STA_INFO_RSN_CAPAB },
1218 { "state", WLANTEST_STA_INFO_STATE },
1222 static int cmd_info_sta(int s, int argc, char *argv[])
1224 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1225 u8 buf[100], *end, *pos;
1231 printf("sta_info needs at three arguments: "
1232 "counter name, BSSID, and STA address\n");
1237 end = buf + sizeof(buf);
1238 WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_STA);
1241 for (i = 0; sta_infos[i].name; i++) {
1242 if (os_strcasecmp(sta_infos[i].name, argv[0]) == 0)
1245 if (sta_infos[i].name == NULL) {
1246 printf("Unknown STA info '%s'\n", argv[0]);
1247 printf("Info fields:");
1248 for (i = 0; sta_infos[i].name; i++)
1249 printf(" %s", sta_infos[i].name);
1254 pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_INFO,
1256 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1257 if (hwaddr_aton(argv[1], pos) < 0) {
1258 printf("Invalid BSSID '%s'\n", argv[1]);
1263 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
1264 if (hwaddr_aton(argv[2], pos) < 0) {
1265 printf("Invalid STA address '%s'\n", argv[2]);
1270 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1274 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len);
1277 if (len >= sizeof(info))
1278 len = sizeof(info) - 1;
1279 os_memcpy(info, pos, len);
1281 printf("%s\n", info);
1286 static char ** complete_info_sta(int s, const char *str, int pos)
1288 int arg = get_cmd_arg_num(str, pos);
1296 count = sizeof(sta_infos) / sizeof(sta_infos[0]);
1297 res = os_zalloc(count * sizeof(char *));
1300 for (i = 0; sta_infos[i].name; i++) {
1301 res[i] = os_strdup(sta_infos[i].name);
1307 res = get_bssid_list(s);
1310 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
1312 res = get_sta_list(s, addr, 0);
1322 enum wlantest_bss_info num;
1325 static const struct bss_infos bss_infos[] = {
1326 { "proto", WLANTEST_BSS_INFO_PROTO },
1327 { "pairwise", WLANTEST_BSS_INFO_PAIRWISE },
1328 { "group", WLANTEST_BSS_INFO_GROUP },
1329 { "group_mgmt", WLANTEST_BSS_INFO_GROUP_MGMT },
1330 { "key_mgmt", WLANTEST_BSS_INFO_KEY_MGMT },
1331 { "rsn_capab", WLANTEST_BSS_INFO_RSN_CAPAB },
1335 static int cmd_info_bss(int s, int argc, char *argv[])
1337 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1338 u8 buf[100], *end, *pos;
1344 printf("bss_info needs at two arguments: "
1345 "field name and BSSID\n");
1350 end = buf + sizeof(buf);
1351 WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_BSS);
1354 for (i = 0; bss_infos[i].name; i++) {
1355 if (os_strcasecmp(bss_infos[i].name, argv[0]) == 0)
1358 if (bss_infos[i].name == NULL) {
1359 printf("Unknown BSS info '%s'\n", argv[0]);
1360 printf("Info fields:");
1361 for (i = 0; bss_infos[i].name; i++)
1362 printf(" %s", bss_infos[i].name);
1367 pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_INFO,
1369 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1370 if (hwaddr_aton(argv[1], pos) < 0) {
1371 printf("Invalid BSSID '%s'\n", argv[1]);
1376 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1380 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len);
1383 if (len >= sizeof(info))
1384 len = sizeof(info) - 1;
1385 os_memcpy(info, pos, len);
1387 printf("%s\n", info);
1392 static char ** complete_info_bss(int s, const char *str, int pos)
1394 int arg = get_cmd_arg_num(str, pos);
1401 count = sizeof(bss_infos) / sizeof(bss_infos[0]);
1402 res = os_zalloc(count * sizeof(char *));
1405 for (i = 0; bss_infos[i].name; i++) {
1406 res[i] = os_strdup(bss_infos[i].name);
1412 res = get_bssid_list(s);
1420 struct wlantest_cli_cmd {
1422 int (*handler)(int s, int argc, char *argv[]);
1424 char ** (*complete)(int s, const char *str, int pos);
1427 static const struct wlantest_cli_cmd wlantest_cli_commands[] = {
1428 { "ping", cmd_ping, "= test connection to wlantest", NULL },
1429 { "terminate", cmd_terminate, "= terminate wlantest", NULL },
1430 { "list_bss", cmd_list_bss, "= get BSS list", NULL },
1431 { "list_sta", cmd_list_sta, "<BSSID> = get STA list",
1432 complete_list_sta },
1433 { "flush", cmd_flush, "= drop all collected BSS data", NULL },
1434 { "clear_sta_counters", cmd_clear_sta_counters,
1435 "<BSSID> <STA> = clear STA counters", complete_clear_sta_counters },
1436 { "clear_bss_counters", cmd_clear_bss_counters,
1437 "<BSSID> = clear BSS counters", complete_clear_bss_counters },
1438 { "get_sta_counter", cmd_get_sta_counter,
1439 "<counter> <BSSID> <STA> = get STA counter value",
1440 complete_get_sta_counter },
1441 { "get_bss_counter", cmd_get_bss_counter,
1442 "<counter> <BSSID> = get BSS counter value",
1443 complete_get_bss_counter },
1444 { "inject", cmd_inject,
1445 "<frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff>",
1448 "<prot> <raw frame as hex dump>",
1450 { "version", cmd_version, "= get wlantest version", NULL },
1451 { "add_passphrase", cmd_add_passphrase,
1452 "<passphrase> = add a known passphrase", NULL },
1453 { "info_sta", cmd_info_sta,
1454 "<field> <BSSID> <STA> = get STA information",
1455 complete_info_sta },
1456 { "info_bss", cmd_info_bss,
1457 "<field> <BSSID> = get BSS information",
1458 complete_info_bss },
1459 { "clear_tdls_counters", cmd_clear_tdls_counters,
1460 "<BSSID> <STA1> <STA2> = clear TDLS counters",
1461 complete_clear_tdls_counters },
1462 { "get_tdls_counter", cmd_get_tdls_counter,
1463 "<counter> <BSSID> <STA1> <STA2> = get TDLS counter value",
1464 complete_get_tdls_counter },
1465 { "get_bss_counter", cmd_get_bss_counter,
1466 "<counter> <BSSID> = get BSS counter value",
1467 complete_get_bss_counter },
1468 { NULL, NULL, NULL, NULL }
1472 static int ctrl_command(int s, int argc, char *argv[])
1474 const struct wlantest_cli_cmd *cmd, *match = NULL;
1478 for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) {
1479 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1482 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1492 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1493 for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) {
1494 if (os_strncasecmp(cmd->cmd, argv[0],
1495 os_strlen(argv[0])) == 0) {
1496 printf(" %s", cmd->cmd);
1501 } else if (count == 0) {
1502 printf("Unknown command '%s'\n", argv[0]);
1505 ret = match->handler(s, argc - 1, &argv[1]);
1512 struct wlantest_cli {
1519 static int tokenize_cmd(char *cmd, char *argv[])
1532 if (argc == max_args)
1535 char *pos2 = os_strrchr(pos, '"');
1539 while (*pos != '\0' && *pos != ' ')
1549 static void wlantest_cli_edit_cmd_cb(void *ctx, char *cmd)
1551 struct wlantest_cli *cli = ctx;
1552 char *argv[max_args];
1554 argc = tokenize_cmd(cmd, argv);
1556 int ret = ctrl_command(cli->s, argc, argv);
1563 static void wlantest_cli_eloop_terminate(int sig, void *signal_ctx)
1569 static void wlantest_cli_edit_eof_cb(void *ctx)
1575 static char ** wlantest_cli_cmd_list(void)
1580 count = sizeof(wlantest_cli_commands) /
1581 sizeof(wlantest_cli_commands[0]);
1582 res = os_zalloc(count * sizeof(char *));
1586 for (i = 0; wlantest_cli_commands[i].cmd; i++) {
1587 res[i] = os_strdup(wlantest_cli_commands[i].cmd);
1596 static char ** wlantest_cli_cmd_completion(struct wlantest_cli *cli,
1597 const char *cmd, const char *str,
1602 for (i = 0; wlantest_cli_commands[i].cmd; i++) {
1603 const struct wlantest_cli_cmd *c = &wlantest_cli_commands[i];
1604 if (os_strcasecmp(c->cmd, cmd) == 0) {
1606 printf("\r%s\n", c->usage);
1609 return c->complete(cli->s, str, pos);
1618 static char ** wlantest_cli_edit_completion_cb(void *ctx, const char *str,
1621 struct wlantest_cli *cli = ctx;
1626 end = os_strchr(str, ' ');
1627 if (end == NULL || str + pos < end)
1628 return wlantest_cli_cmd_list();
1630 cmd = os_malloc(pos + 1);
1633 os_memcpy(cmd, str, pos);
1634 cmd[end - str] = '\0';
1635 res = wlantest_cli_cmd_completion(cli, cmd, str, pos);
1641 static void wlantest_cli_interactive(int s)
1643 struct wlantest_cli cli;
1644 char *home, *hfile = NULL;
1649 home = getenv("HOME");
1651 const char *fname = ".wlantest_cli_history";
1652 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1653 hfile = os_malloc(hfile_len);
1655 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
1659 eloop_register_signal_terminate(wlantest_cli_eloop_terminate, &cli);
1660 edit_init(wlantest_cli_edit_cmd_cb, wlantest_cli_edit_eof_cb,
1661 wlantest_cli_edit_completion_cb, &cli, hfile);
1665 edit_deinit(hfile, NULL);
1671 int main(int argc, char *argv[])
1674 struct sockaddr_un addr;
1677 if (os_program_init())
1680 s = socket(AF_UNIX, SOCK_SEQPACKET, 0);
1686 os_memset(&addr, 0, sizeof(addr));
1687 addr.sun_family = AF_UNIX;
1688 os_strlcpy(addr.sun_path + 1, WLANTEST_SOCK_NAME,
1689 sizeof(addr.sun_path) - 1);
1690 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1697 ret = ctrl_command(s, argc - 1, &argv[1]);
1701 wlantest_cli_interactive(s);
1706 os_program_deinit();