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 },
557 static int cmd_get_sta_counter(int s, int argc, char *argv[])
559 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
560 u8 buf[100], *end, *pos;
565 printf("get_sta_counter needs at three arguments: "
566 "counter name, BSSID, and STA address\n");
571 end = buf + sizeof(buf);
572 WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_STA_COUNTER);
575 for (i = 0; sta_counters[i].name; i++) {
576 if (os_strcasecmp(sta_counters[i].name, argv[0]) == 0)
579 if (sta_counters[i].name == NULL) {
580 printf("Unknown STA counter '%s'\n", argv[0]);
582 for (i = 0; sta_counters[i].name; i++)
583 printf(" %s", sta_counters[i].name);
588 pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_COUNTER,
589 sta_counters[i].num);
590 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
591 if (hwaddr_aton(argv[1], pos) < 0) {
592 printf("Invalid BSSID '%s'\n", argv[1]);
597 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
598 if (hwaddr_aton(argv[2], pos) < 0) {
599 printf("Invalid STA address '%s'\n", argv[2]);
604 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
608 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
609 if (pos == NULL || len != 4)
611 printf("%u\n", WPA_GET_BE32(pos));
616 static char ** complete_get_sta_counter(int s, const char *str, int pos)
618 int arg = get_cmd_arg_num(str, pos);
626 count = sizeof(sta_counters) / sizeof(sta_counters[0]);
627 res = os_zalloc(count * sizeof(char *));
630 for (i = 0; sta_counters[i].name; i++) {
631 res[i] = os_strdup(sta_counters[i].name);
637 res = get_bssid_list(s);
640 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
642 res = get_sta_list(s, addr, 0);
650 struct bss_counters {
652 enum wlantest_bss_counter num;
655 static const struct bss_counters bss_counters[] = {
656 { "valid_bip_mmie", WLANTEST_BSS_COUNTER_VALID_BIP_MMIE },
657 { "invalid_bip_mmie", WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE },
658 { "missing_bip_mmie", WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE },
659 { "bip_deauth", WLANTEST_BSS_COUNTER_BIP_DEAUTH },
660 { "bip_disassoc", WLANTEST_BSS_COUNTER_BIP_DISASSOC },
664 static int cmd_get_bss_counter(int s, int argc, char *argv[])
666 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
667 u8 buf[100], *end, *pos;
672 printf("get_bss_counter needs at two arguments: "
673 "counter name and BSSID\n");
678 end = buf + sizeof(buf);
679 WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_BSS_COUNTER);
682 for (i = 0; bss_counters[i].name; i++) {
683 if (os_strcasecmp(bss_counters[i].name, argv[0]) == 0)
686 if (bss_counters[i].name == NULL) {
687 printf("Unknown BSS counter '%s'\n", argv[0]);
689 for (i = 0; bss_counters[i].name; i++)
690 printf(" %s", bss_counters[i].name);
695 pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_COUNTER,
696 bss_counters[i].num);
697 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
698 if (hwaddr_aton(argv[1], pos) < 0) {
699 printf("Invalid BSSID '%s'\n", argv[1]);
704 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
708 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
709 if (pos == NULL || len != 4)
711 printf("%u\n", WPA_GET_BE32(pos));
716 static char ** complete_get_bss_counter(int s, const char *str, int pos)
718 int arg = get_cmd_arg_num(str, pos);
725 count = sizeof(bss_counters) / sizeof(bss_counters[0]);
726 res = os_zalloc(count * sizeof(char *));
729 for (i = 0; bss_counters[i].name; i++) {
730 res[i] = os_strdup(bss_counters[i].name);
736 res = get_bssid_list(s);
744 struct tdls_counters {
746 enum wlantest_tdls_counter num;
749 static const struct tdls_counters tdls_counters[] = {
750 { "valid_direct_link", WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK },
751 { "invalid_direct_link", WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK },
752 { "valid_ap_path", WLANTEST_TDLS_COUNTER_VALID_AP_PATH },
753 { "invalid_ap_path", WLANTEST_TDLS_COUNTER_INVALID_AP_PATH },
757 static int cmd_get_tdls_counter(int s, int argc, char *argv[])
759 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
760 u8 buf[100], *end, *pos;
765 printf("get_tdls_counter needs four arguments: "
766 "counter name, BSSID, STA1 address, STA2 address\n");
771 end = buf + sizeof(buf);
772 WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_TDLS_COUNTER);
775 for (i = 0; tdls_counters[i].name; i++) {
776 if (os_strcasecmp(tdls_counters[i].name, argv[0]) == 0)
779 if (tdls_counters[i].name == NULL) {
780 printf("Unknown TDLS counter '%s'\n", argv[0]);
782 for (i = 0; tdls_counters[i].name; i++)
783 printf(" %s", tdls_counters[i].name);
788 pos = attr_add_be32(pos, end, WLANTEST_ATTR_TDLS_COUNTER,
789 tdls_counters[i].num);
790 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
791 if (hwaddr_aton(argv[1], pos) < 0) {
792 printf("Invalid BSSID '%s'\n", argv[1]);
797 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
798 if (hwaddr_aton(argv[2], pos) < 0) {
799 printf("Invalid STA1 address '%s'\n", argv[2]);
804 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA2_ADDR, ETH_ALEN);
805 if (hwaddr_aton(argv[3], pos) < 0) {
806 printf("Invalid STA2 address '%s'\n", argv[3]);
811 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
815 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
816 if (pos == NULL || len != 4)
818 printf("%u\n", WPA_GET_BE32(pos));
823 static char ** complete_get_tdls_counter(int s, const char *str, int pos)
825 int arg = get_cmd_arg_num(str, pos);
833 count = sizeof(tdls_counters) / sizeof(tdls_counters[0]);
834 res = os_zalloc(count * sizeof(char *));
837 for (i = 0; tdls_counters[i].name; i++) {
838 res[i] = os_strdup(tdls_counters[i].name);
844 res = get_bssid_list(s);
848 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
850 res = get_sta_list(s, addr, 0);
858 struct inject_frames {
860 enum wlantest_inject_frame frame;
863 static const struct inject_frames inject_frames[] = {
864 { "auth", WLANTEST_FRAME_AUTH },
865 { "assocreq", WLANTEST_FRAME_ASSOCREQ },
866 { "reassocreq", WLANTEST_FRAME_REASSOCREQ },
867 { "deauth", WLANTEST_FRAME_DEAUTH },
868 { "disassoc", WLANTEST_FRAME_DISASSOC },
869 { "saqueryreq", WLANTEST_FRAME_SAQUERYREQ },
873 static int cmd_inject(int s, int argc, char *argv[])
875 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
876 u8 buf[100], *end, *pos;
878 enum wlantest_inject_protection prot;
880 /* <frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff> */
883 printf("inject needs five arguments: frame, protection, "
884 "sender, BSSID, STA/ff:ff:ff:ff:ff:ff\n");
889 end = buf + sizeof(buf);
890 WPA_PUT_BE32(pos, WLANTEST_CTRL_INJECT);
893 for (i = 0; inject_frames[i].name; i++) {
894 if (os_strcasecmp(inject_frames[i].name, argv[0]) == 0)
897 if (inject_frames[i].name == NULL) {
898 printf("Unknown inject frame '%s'\n", argv[0]);
900 for (i = 0; inject_frames[i].name; i++)
901 printf(" %s", inject_frames[i].name);
906 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_FRAME,
907 inject_frames[i].frame);
909 if (os_strcasecmp(argv[1], "normal") == 0)
910 prot = WLANTEST_INJECT_NORMAL;
911 else if (os_strcasecmp(argv[1], "protected") == 0)
912 prot = WLANTEST_INJECT_PROTECTED;
913 else if (os_strcasecmp(argv[1], "unprotected") == 0)
914 prot = WLANTEST_INJECT_UNPROTECTED;
915 else if (os_strcasecmp(argv[1], "incorrect") == 0)
916 prot = WLANTEST_INJECT_INCORRECT_KEY;
918 printf("Unknown protection type '%s'\n", argv[1]);
919 printf("Protection types: normal protected unprotected "
923 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot);
925 if (os_strcasecmp(argv[2], "ap") == 0) {
926 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
928 } else if (os_strcasecmp(argv[2], "sta") == 0) {
929 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
932 printf("Unknown sender '%s'\n", argv[2]);
933 printf("Sender types: ap sta\n");
937 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
938 if (hwaddr_aton(argv[3], pos) < 0) {
939 printf("Invalid BSSID '%s'\n", argv[3]);
944 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
945 if (hwaddr_aton(argv[4], pos) < 0) {
946 printf("Invalid STA '%s'\n", argv[4]);
951 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
959 static char ** complete_inject(int s, const char *str, int pos)
961 int arg = get_cmd_arg_num(str, pos);
969 count = sizeof(inject_frames) / sizeof(inject_frames[0]);
970 res = os_zalloc(count * sizeof(char *));
973 for (i = 0; inject_frames[i].name; i++) {
974 res[i] = os_strdup(inject_frames[i].name);
980 res = os_zalloc(5 * sizeof(char *));
983 res[0] = os_strdup("normal");
986 res[1] = os_strdup("protected");
989 res[2] = os_strdup("unprotected");
992 res[3] = os_strdup("incorrect");
997 res = os_zalloc(3 * sizeof(char *));
1000 res[0] = os_strdup("ap");
1003 res[1] = os_strdup("sta");
1008 res = get_bssid_list(s);
1011 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
1013 res = get_sta_list(s, addr, 1);
1021 static u8 * add_hex(u8 *pos, u8 *end, const char *str)
1028 while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n' ||
1034 while (*s != '\0' && *s != '\r' && *s != '\n')
1041 printf("Invalid hex encoding '%s'\n", s);
1045 printf("Too long frame\n");
1056 static int cmd_send(int s, int argc, char *argv[])
1058 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1059 u8 buf[WLANTEST_CTRL_MAX_CMD_LEN], *end, *pos, *len_pos;
1061 enum wlantest_inject_protection prot;
1064 /* <prot> <raw frame as hex dump> */
1067 printf("send needs two arguments: protected/unprotected, "
1068 "raw frame as hex dump\n");
1073 end = buf + sizeof(buf);
1074 WPA_PUT_BE32(pos, WLANTEST_CTRL_SEND);
1077 if (os_strcasecmp(argv[0], "normal") == 0)
1078 prot = WLANTEST_INJECT_NORMAL;
1079 else if (os_strcasecmp(argv[0], "protected") == 0)
1080 prot = WLANTEST_INJECT_PROTECTED;
1081 else if (os_strcasecmp(argv[0], "unprotected") == 0)
1082 prot = WLANTEST_INJECT_UNPROTECTED;
1083 else if (os_strcasecmp(argv[0], "incorrect") == 0)
1084 prot = WLANTEST_INJECT_INCORRECT_KEY;
1086 printf("Unknown protection type '%s'\n", argv[1]);
1087 printf("Protection types: normal protected unprotected "
1091 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot);
1093 WPA_PUT_BE32(pos, WLANTEST_ATTR_FRAME);
1098 for (arg = 1; pos && arg < argc; arg++)
1099 pos = add_hex(pos, end, argv[arg]);
1103 WPA_PUT_BE32(len_pos, pos - len_pos - 4);
1105 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1113 static char ** complete_send(int s, const char *str, int pos)
1115 int arg = get_cmd_arg_num(str, pos);
1120 res = os_zalloc(5 * sizeof(char *));
1123 res[0] = os_strdup("normal");
1126 res[1] = os_strdup("protected");
1129 res[2] = os_strdup("unprotected");
1132 res[3] = os_strdup("incorrect");
1142 static int cmd_version(int s, int argc, char *argv[])
1144 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1150 WPA_PUT_BE32(buf, WLANTEST_CTRL_VERSION);
1151 rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
1155 version = (char *) attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_VERSION,
1157 if (version == NULL)
1160 for (i = 0; i < len; i++)
1161 putchar(version[i]);
1168 static int cmd_add_passphrase(int s, int argc, char *argv[])
1170 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1171 u8 buf[100], *pos, *end;
1176 printf("add_passphrase needs one argument: passphrase\n");
1180 len = os_strlen(argv[0]);
1181 if (len < 8 || len > 63) {
1182 printf("Invalid passphrase '%s'\n", argv[0]);
1186 end = buf + sizeof(buf);
1187 WPA_PUT_BE32(pos, WLANTEST_CTRL_ADD_PASSPHRASE);
1189 pos = attr_add_str(pos, end, WLANTEST_ATTR_PASSPHRASE,
1192 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1193 if (hwaddr_aton(argv[1], pos) < 0) {
1194 printf("Invalid BSSID '%s'\n", argv[3]);
1200 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1209 enum wlantest_sta_info num;
1212 static const struct sta_infos sta_infos[] = {
1213 { "proto", WLANTEST_STA_INFO_PROTO },
1214 { "pairwise", WLANTEST_STA_INFO_PAIRWISE },
1215 { "key_mgmt", WLANTEST_STA_INFO_KEY_MGMT },
1216 { "rsn_capab", WLANTEST_STA_INFO_RSN_CAPAB },
1217 { "state", WLANTEST_STA_INFO_STATE },
1221 static int cmd_info_sta(int s, int argc, char *argv[])
1223 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1224 u8 buf[100], *end, *pos;
1230 printf("sta_info needs at three arguments: "
1231 "counter name, BSSID, and STA address\n");
1236 end = buf + sizeof(buf);
1237 WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_STA);
1240 for (i = 0; sta_infos[i].name; i++) {
1241 if (os_strcasecmp(sta_infos[i].name, argv[0]) == 0)
1244 if (sta_infos[i].name == NULL) {
1245 printf("Unknown STA info '%s'\n", argv[0]);
1246 printf("Info fields:");
1247 for (i = 0; sta_infos[i].name; i++)
1248 printf(" %s", sta_infos[i].name);
1253 pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_INFO,
1255 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1256 if (hwaddr_aton(argv[1], pos) < 0) {
1257 printf("Invalid BSSID '%s'\n", argv[1]);
1262 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
1263 if (hwaddr_aton(argv[2], pos) < 0) {
1264 printf("Invalid STA address '%s'\n", argv[2]);
1269 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1273 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len);
1276 if (len >= sizeof(info))
1277 len = sizeof(info) - 1;
1278 os_memcpy(info, pos, len);
1280 printf("%s\n", info);
1285 static char ** complete_info_sta(int s, const char *str, int pos)
1287 int arg = get_cmd_arg_num(str, pos);
1295 count = sizeof(sta_infos) / sizeof(sta_infos[0]);
1296 res = os_zalloc(count * sizeof(char *));
1299 for (i = 0; sta_infos[i].name; i++) {
1300 res[i] = os_strdup(sta_infos[i].name);
1306 res = get_bssid_list(s);
1309 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
1311 res = get_sta_list(s, addr, 0);
1321 enum wlantest_bss_info num;
1324 static const struct bss_infos bss_infos[] = {
1325 { "proto", WLANTEST_BSS_INFO_PROTO },
1326 { "pairwise", WLANTEST_BSS_INFO_PAIRWISE },
1327 { "group", WLANTEST_BSS_INFO_GROUP },
1328 { "group_mgmt", WLANTEST_BSS_INFO_GROUP_MGMT },
1329 { "key_mgmt", WLANTEST_BSS_INFO_KEY_MGMT },
1330 { "rsn_capab", WLANTEST_BSS_INFO_RSN_CAPAB },
1334 static int cmd_info_bss(int s, int argc, char *argv[])
1336 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1337 u8 buf[100], *end, *pos;
1343 printf("bss_info needs at two arguments: "
1344 "field name and BSSID\n");
1349 end = buf + sizeof(buf);
1350 WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_BSS);
1353 for (i = 0; bss_infos[i].name; i++) {
1354 if (os_strcasecmp(bss_infos[i].name, argv[0]) == 0)
1357 if (bss_infos[i].name == NULL) {
1358 printf("Unknown BSS info '%s'\n", argv[0]);
1359 printf("Info fields:");
1360 for (i = 0; bss_infos[i].name; i++)
1361 printf(" %s", bss_infos[i].name);
1366 pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_INFO,
1368 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1369 if (hwaddr_aton(argv[1], pos) < 0) {
1370 printf("Invalid BSSID '%s'\n", argv[1]);
1375 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1379 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len);
1382 if (len >= sizeof(info))
1383 len = sizeof(info) - 1;
1384 os_memcpy(info, pos, len);
1386 printf("%s\n", info);
1391 static char ** complete_info_bss(int s, const char *str, int pos)
1393 int arg = get_cmd_arg_num(str, pos);
1400 count = sizeof(bss_infos) / sizeof(bss_infos[0]);
1401 res = os_zalloc(count * sizeof(char *));
1404 for (i = 0; bss_infos[i].name; i++) {
1405 res[i] = os_strdup(bss_infos[i].name);
1411 res = get_bssid_list(s);
1419 struct wlantest_cli_cmd {
1421 int (*handler)(int s, int argc, char *argv[]);
1423 char ** (*complete)(int s, const char *str, int pos);
1426 static const struct wlantest_cli_cmd wlantest_cli_commands[] = {
1427 { "ping", cmd_ping, "= test connection to wlantest", NULL },
1428 { "terminate", cmd_terminate, "= terminate wlantest", NULL },
1429 { "list_bss", cmd_list_bss, "= get BSS list", NULL },
1430 { "list_sta", cmd_list_sta, "<BSSID> = get STA list",
1431 complete_list_sta },
1432 { "flush", cmd_flush, "= drop all collected BSS data", NULL },
1433 { "clear_sta_counters", cmd_clear_sta_counters,
1434 "<BSSID> <STA> = clear STA counters", complete_clear_sta_counters },
1435 { "clear_bss_counters", cmd_clear_bss_counters,
1436 "<BSSID> = clear BSS counters", complete_clear_bss_counters },
1437 { "get_sta_counter", cmd_get_sta_counter,
1438 "<counter> <BSSID> <STA> = get STA counter value",
1439 complete_get_sta_counter },
1440 { "get_bss_counter", cmd_get_bss_counter,
1441 "<counter> <BSSID> = get BSS counter value",
1442 complete_get_bss_counter },
1443 { "inject", cmd_inject,
1444 "<frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff>",
1447 "<prot> <raw frame as hex dump>",
1449 { "version", cmd_version, "= get wlantest version", NULL },
1450 { "add_passphrase", cmd_add_passphrase,
1451 "<passphrase> = add a known passphrase", NULL },
1452 { "info_sta", cmd_info_sta,
1453 "<field> <BSSID> <STA> = get STA information",
1454 complete_info_sta },
1455 { "info_bss", cmd_info_bss,
1456 "<field> <BSSID> = get BSS information",
1457 complete_info_bss },
1458 { "clear_tdls_counters", cmd_clear_tdls_counters,
1459 "<BSSID> <STA1> <STA2> = clear TDLS counters",
1460 complete_clear_tdls_counters },
1461 { "get_tdls_counter", cmd_get_tdls_counter,
1462 "<counter> <BSSID> <STA1> <STA2> = get TDLS counter value",
1463 complete_get_tdls_counter },
1464 { "get_bss_counter", cmd_get_bss_counter,
1465 "<counter> <BSSID> = get BSS counter value",
1466 complete_get_bss_counter },
1467 { NULL, NULL, NULL, NULL }
1471 static int ctrl_command(int s, int argc, char *argv[])
1473 const struct wlantest_cli_cmd *cmd, *match = NULL;
1477 for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) {
1478 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1481 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1491 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1492 for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) {
1493 if (os_strncasecmp(cmd->cmd, argv[0],
1494 os_strlen(argv[0])) == 0) {
1495 printf(" %s", cmd->cmd);
1500 } else if (count == 0) {
1501 printf("Unknown command '%s'\n", argv[0]);
1504 ret = match->handler(s, argc - 1, &argv[1]);
1511 struct wlantest_cli {
1518 static int tokenize_cmd(char *cmd, char *argv[])
1531 if (argc == max_args)
1534 char *pos2 = os_strrchr(pos, '"');
1538 while (*pos != '\0' && *pos != ' ')
1548 static void wlantest_cli_edit_cmd_cb(void *ctx, char *cmd)
1550 struct wlantest_cli *cli = ctx;
1551 char *argv[max_args];
1553 argc = tokenize_cmd(cmd, argv);
1555 int ret = ctrl_command(cli->s, argc, argv);
1562 static void wlantest_cli_eloop_terminate(int sig, void *signal_ctx)
1568 static void wlantest_cli_edit_eof_cb(void *ctx)
1574 static char ** wlantest_cli_cmd_list(void)
1579 count = sizeof(wlantest_cli_commands) /
1580 sizeof(wlantest_cli_commands[0]);
1581 res = os_zalloc(count * sizeof(char *));
1585 for (i = 0; wlantest_cli_commands[i].cmd; i++) {
1586 res[i] = os_strdup(wlantest_cli_commands[i].cmd);
1595 static char ** wlantest_cli_cmd_completion(struct wlantest_cli *cli,
1596 const char *cmd, const char *str,
1601 for (i = 0; wlantest_cli_commands[i].cmd; i++) {
1602 const struct wlantest_cli_cmd *c = &wlantest_cli_commands[i];
1603 if (os_strcasecmp(c->cmd, cmd) == 0) {
1605 printf("\r%s\n", c->usage);
1608 return c->complete(cli->s, str, pos);
1617 static char ** wlantest_cli_edit_completion_cb(void *ctx, const char *str,
1620 struct wlantest_cli *cli = ctx;
1625 end = os_strchr(str, ' ');
1626 if (end == NULL || str + pos < end)
1627 return wlantest_cli_cmd_list();
1629 cmd = os_malloc(pos + 1);
1632 os_memcpy(cmd, str, pos);
1633 cmd[end - str] = '\0';
1634 res = wlantest_cli_cmd_completion(cli, cmd, str, pos);
1640 static void wlantest_cli_interactive(int s)
1642 struct wlantest_cli cli;
1643 char *home, *hfile = NULL;
1648 home = getenv("HOME");
1650 const char *fname = ".wlantest_cli_history";
1651 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1652 hfile = os_malloc(hfile_len);
1654 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
1658 eloop_register_signal_terminate(wlantest_cli_eloop_terminate, &cli);
1659 edit_init(wlantest_cli_edit_cmd_cb, wlantest_cli_edit_eof_cb,
1660 wlantest_cli_edit_completion_cb, &cli, hfile);
1664 edit_deinit(hfile, NULL);
1670 int main(int argc, char *argv[])
1673 struct sockaddr_un addr;
1676 if (os_program_init())
1679 s = socket(AF_UNIX, SOCK_SEQPACKET, 0);
1685 os_memset(&addr, 0, sizeof(addr));
1686 addr.sun_family = AF_UNIX;
1687 os_strlcpy(addr.sun_path + 1, WLANTEST_SOCK_NAME,
1688 sizeof(addr.sun_path) - 1);
1689 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1696 ret = ctrl_command(s, argc - 1, &argv[1]);
1700 wlantest_cli_interactive(s);
1705 os_program_deinit();