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, sizeof(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 struct sta_counters {
435 enum wlantest_sta_counter num;
438 static const struct sta_counters sta_counters[] = {
439 { "auth_tx", WLANTEST_STA_COUNTER_AUTH_TX },
440 { "auth_rx", WLANTEST_STA_COUNTER_AUTH_RX },
441 { "assocreq_tx", WLANTEST_STA_COUNTER_ASSOCREQ_TX },
442 { "reassocreq_tx", WLANTEST_STA_COUNTER_REASSOCREQ_TX },
443 { "ptk_learned", WLANTEST_STA_COUNTER_PTK_LEARNED },
444 { "valid_deauth_tx", WLANTEST_STA_COUNTER_VALID_DEAUTH_TX },
445 { "valid_deauth_rx", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX },
446 { "invalid_deauth_tx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX },
447 { "invalid_deauth_rx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX },
448 { "valid_disassoc_tx", WLANTEST_STA_COUNTER_VALID_DISASSOC_TX },
449 { "valid_disassoc_rx", WLANTEST_STA_COUNTER_VALID_DISASSOC_RX },
450 { "invalid_disassoc_tx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX },
451 { "invalid_disassoc_rx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX },
452 { "valid_saqueryreq_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX },
453 { "valid_saqueryreq_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX },
454 { "invalid_saqueryreq_tx",
455 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX },
456 { "invalid_saqueryreq_rx",
457 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX },
458 { "valid_saqueryresp_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX },
459 { "valid_saqueryresp_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX },
460 { "invalid_saqueryresp_tx",
461 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX },
462 { "invalid_saqueryresp_rx",
463 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX },
467 static int cmd_get_sta_counter(int s, int argc, char *argv[])
469 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
470 u8 buf[100], *end, *pos;
475 printf("get_sta_counter needs at three arguments: "
476 "counter name, BSSID, and STA address\n");
481 end = buf + sizeof(buf);
482 WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_STA_COUNTER);
485 for (i = 0; sta_counters[i].name; i++) {
486 if (os_strcasecmp(sta_counters[i].name, argv[0]) == 0)
489 if (sta_counters[i].name == NULL) {
490 printf("Unknown STA counter '%s'\n", argv[0]);
492 for (i = 0; sta_counters[i].name; i++)
493 printf(" %s", sta_counters[i].name);
498 pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_COUNTER,
499 sta_counters[i].num);
500 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
501 if (hwaddr_aton(argv[1], pos) < 0) {
502 printf("Invalid BSSID '%s'\n", argv[1]);
507 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
508 if (hwaddr_aton(argv[2], pos) < 0) {
509 printf("Invalid STA address '%s'\n", argv[2]);
514 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
518 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
519 if (pos == NULL || len != 4)
521 printf("%u\n", WPA_GET_BE32(pos));
526 static char ** complete_get_sta_counter(int s, const char *str, int pos)
528 int arg = get_cmd_arg_num(str, pos);
536 count = sizeof(sta_counters) / sizeof(sta_counters[0]);
537 res = os_zalloc(count * sizeof(char *));
540 for (i = 0; sta_counters[i].name; i++) {
541 res[i] = os_strdup(sta_counters[i].name);
547 res = get_bssid_list(s);
550 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
552 res = get_sta_list(s, addr, 0);
560 struct bss_counters {
562 enum wlantest_bss_counter num;
565 static const struct bss_counters bss_counters[] = {
566 { "valid_bip_mmie", WLANTEST_BSS_COUNTER_VALID_BIP_MMIE },
567 { "invalid_bip_mmie", WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE },
568 { "missing_bip_mmie", WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE },
572 static int cmd_get_bss_counter(int s, int argc, char *argv[])
574 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
575 u8 buf[100], *end, *pos;
580 printf("get_bss_counter needs at three arguments: "
581 "counter name and BSSID\n");
586 end = buf + sizeof(buf);
587 WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_BSS_COUNTER);
590 for (i = 0; bss_counters[i].name; i++) {
591 if (os_strcasecmp(bss_counters[i].name, argv[0]) == 0)
594 if (bss_counters[i].name == NULL) {
595 printf("Unknown BSS counter '%s'\n", argv[0]);
597 for (i = 0; bss_counters[i].name; i++)
598 printf(" %s", bss_counters[i].name);
603 pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_COUNTER,
604 bss_counters[i].num);
605 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
606 if (hwaddr_aton(argv[1], pos) < 0) {
607 printf("Invalid BSSID '%s'\n", argv[1]);
612 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
616 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
617 if (pos == NULL || len != 4)
619 printf("%u\n", WPA_GET_BE32(pos));
624 static char ** complete_get_bss_counter(int s, const char *str, int pos)
626 int arg = get_cmd_arg_num(str, pos);
633 count = sizeof(bss_counters) / sizeof(bss_counters[0]);
634 res = os_zalloc(count * sizeof(char *));
637 for (i = 0; bss_counters[i].name; i++) {
638 res[i] = os_strdup(bss_counters[i].name);
644 res = get_bssid_list(s);
652 struct inject_frames {
654 enum wlantest_inject_frame frame;
657 static const struct inject_frames inject_frames[] = {
658 { "auth", WLANTEST_FRAME_AUTH },
659 { "assocreq", WLANTEST_FRAME_ASSOCREQ },
660 { "reassocreq", WLANTEST_FRAME_REASSOCREQ },
661 { "deauth", WLANTEST_FRAME_DEAUTH },
662 { "disassoc", WLANTEST_FRAME_DISASSOC },
663 { "saqueryreq", WLANTEST_FRAME_SAQUERYREQ },
667 static int cmd_inject(int s, int argc, char *argv[])
669 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
670 u8 buf[100], *end, *pos;
672 enum wlantest_inject_protection prot;
674 /* <frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff> */
677 printf("inject needs five arguments: frame, protection, "
678 "sender, BSSID, STA/ff:ff:ff:ff:ff:ff\n");
683 end = buf + sizeof(buf);
684 WPA_PUT_BE32(pos, WLANTEST_CTRL_INJECT);
687 for (i = 0; inject_frames[i].name; i++) {
688 if (os_strcasecmp(inject_frames[i].name, argv[0]) == 0)
691 if (inject_frames[i].name == NULL) {
692 printf("Unknown inject frame '%s'\n", argv[0]);
694 for (i = 0; inject_frames[i].name; i++)
695 printf(" %s", inject_frames[i].name);
700 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_FRAME,
701 inject_frames[i].frame);
703 if (os_strcasecmp(argv[1], "normal") == 0)
704 prot = WLANTEST_INJECT_NORMAL;
705 else if (os_strcasecmp(argv[1], "protected") == 0)
706 prot = WLANTEST_INJECT_PROTECTED;
707 else if (os_strcasecmp(argv[1], "unprotected") == 0)
708 prot = WLANTEST_INJECT_UNPROTECTED;
709 else if (os_strcasecmp(argv[1], "incorrect") == 0)
710 prot = WLANTEST_INJECT_INCORRECT_KEY;
712 printf("Unknown protection type '%s'\n", argv[1]);
713 printf("Protection types: normal protected unprotected "
717 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot);
719 if (os_strcasecmp(argv[2], "ap") == 0) {
720 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
722 } else if (os_strcasecmp(argv[2], "sta") == 0) {
723 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
726 printf("Unknown sender '%s'\n", argv[2]);
727 printf("Sender types: ap sta\n");
731 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
732 if (hwaddr_aton(argv[3], pos) < 0) {
733 printf("Invalid BSSID '%s'\n", argv[3]);
738 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
739 if (hwaddr_aton(argv[4], pos) < 0) {
740 printf("Invalid STA '%s'\n", argv[4]);
745 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
753 static char ** complete_inject(int s, const char *str, int pos)
755 int arg = get_cmd_arg_num(str, pos);
763 count = sizeof(inject_frames) / sizeof(inject_frames[0]);
764 res = os_zalloc(count * sizeof(char *));
767 for (i = 0; inject_frames[i].name; i++) {
768 res[i] = os_strdup(inject_frames[i].name);
774 res = os_zalloc(5 * sizeof(char *));
777 res[0] = os_strdup("normal");
780 res[1] = os_strdup("protected");
783 res[2] = os_strdup("unprotected");
786 res[3] = os_strdup("incorrect");
791 res = os_zalloc(3 * sizeof(char *));
794 res[0] = os_strdup("ap");
797 res[1] = os_strdup("sta");
802 res = get_bssid_list(s);
805 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
807 res = get_sta_list(s, addr, 1);
815 static int cmd_version(int s, int argc, char *argv[])
817 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
823 WPA_PUT_BE32(buf, WLANTEST_CTRL_VERSION);
824 rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
828 version = (char *) attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_VERSION,
833 for (i = 0; i < len; i++)
841 static int cmd_add_passphrase(int s, int argc, char *argv[])
843 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
844 u8 buf[100], *pos, *end;
849 printf("add_passphrase needs one argument: passphrase\n");
853 len = os_strlen(argv[0]);
854 if (len < 8 || len > 63) {
855 printf("Invalid passphrase '%s'\n", argv[0]);
859 end = buf + sizeof(buf);
860 WPA_PUT_BE32(pos, WLANTEST_CTRL_ADD_PASSPHRASE);
862 pos = attr_add_str(pos, end, WLANTEST_ATTR_PASSPHRASE,
865 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
866 if (hwaddr_aton(argv[1], pos) < 0) {
867 printf("Invalid BSSID '%s'\n", argv[3]);
873 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
880 struct wlantest_cli_cmd {
882 int (*handler)(int s, int argc, char *argv[]);
884 char ** (*complete)(int s, const char *str, int pos);
887 static const struct wlantest_cli_cmd wlantest_cli_commands[] = {
888 { "ping", cmd_ping, "= test connection to wlantest", NULL },
889 { "terminate", cmd_terminate, "= terminate wlantest", NULL },
890 { "list_bss", cmd_list_bss, "= get BSS list", NULL },
891 { "list_sta", cmd_list_sta, "<BSSID> = get STA list",
893 { "flush", cmd_flush, "= drop all collected BSS data", NULL },
894 { "clear_sta_counters", cmd_clear_sta_counters,
895 "<BSSID> <STA> = clear STA counters", complete_clear_sta_counters },
896 { "clear_bss_counters", cmd_clear_bss_counters,
897 "<BSSID> = clear BSS counters", complete_clear_bss_counters },
898 { "get_sta_counter", cmd_get_sta_counter,
899 "<counter> <BSSID> <STA> = get STA counter value",
900 complete_get_sta_counter},
901 { "get_bss_counter", cmd_get_bss_counter,
902 "<counter> <BSSID> = get BSS counter value",
903 complete_get_bss_counter },
904 { "inject", cmd_inject,
905 "<frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff>",
907 { "version", cmd_version, "= get wlantest version", NULL },
908 { "add_passphrase", cmd_add_passphrase,
909 "<passphrase> = add a known passphrase", NULL },
910 { NULL, NULL, NULL, NULL }
914 static int ctrl_command(int s, int argc, char *argv[])
916 const struct wlantest_cli_cmd *cmd, *match = NULL;
920 for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) {
921 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
924 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
934 printf("Ambiguous command '%s'; possible commands:", argv[0]);
935 for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) {
936 if (os_strncasecmp(cmd->cmd, argv[0],
937 os_strlen(argv[0])) == 0) {
938 printf(" %s", cmd->cmd);
943 } else if (count == 0) {
944 printf("Unknown command '%s'\n", argv[0]);
947 ret = match->handler(s, argc - 1, &argv[1]);
954 struct wlantest_cli {
961 static int tokenize_cmd(char *cmd, char *argv[])
974 if (argc == max_args)
977 char *pos2 = os_strrchr(pos, '"');
981 while (*pos != '\0' && *pos != ' ')
991 static void wlantest_cli_edit_cmd_cb(void *ctx, char *cmd)
993 struct wlantest_cli *cli = ctx;
994 char *argv[max_args];
996 argc = tokenize_cmd(cmd, argv);
998 int ret = ctrl_command(cli->s, argc, argv);
1005 static void wlantest_cli_eloop_terminate(int sig, void *signal_ctx)
1011 static void wlantest_cli_edit_eof_cb(void *ctx)
1017 static char ** wlantest_cli_cmd_list(void)
1022 count = sizeof(wlantest_cli_commands) /
1023 sizeof(wlantest_cli_commands[0]);
1024 res = os_zalloc(count * sizeof(char *));
1028 for (i = 0; wlantest_cli_commands[i].cmd; i++) {
1029 res[i] = os_strdup(wlantest_cli_commands[i].cmd);
1038 static char ** wlantest_cli_cmd_completion(struct wlantest_cli *cli,
1039 const char *cmd, const char *str,
1044 for (i = 0; wlantest_cli_commands[i].cmd; i++) {
1045 const struct wlantest_cli_cmd *c = &wlantest_cli_commands[i];
1046 if (os_strcasecmp(c->cmd, cmd) == 0) {
1048 printf("\r%s\n", c->usage);
1051 return c->complete(cli->s, str, pos);
1060 static char ** wlantest_cli_edit_completion_cb(void *ctx, const char *str,
1063 struct wlantest_cli *cli = ctx;
1068 end = os_strchr(str, ' ');
1069 if (end == NULL || str + pos < end)
1070 return wlantest_cli_cmd_list();
1072 cmd = os_malloc(pos + 1);
1075 os_memcpy(cmd, str, pos);
1076 cmd[end - str] = '\0';
1077 res = wlantest_cli_cmd_completion(cli, cmd, str, pos);
1083 static void wlantest_cli_interactive(int s)
1085 struct wlantest_cli cli;
1091 eloop_register_signal_terminate(wlantest_cli_eloop_terminate, &cli);
1092 edit_init(wlantest_cli_edit_cmd_cb, wlantest_cli_edit_eof_cb, &cli);
1093 edit_set_completion_cb(wlantest_cli_edit_completion_cb);
1102 int main(int argc, char *argv[])
1105 struct sockaddr_un addr;
1108 if (os_program_init())
1111 s = socket(AF_UNIX, SOCK_SEQPACKET, 0);
1117 os_memset(&addr, 0, sizeof(addr));
1118 addr.sun_family = AF_UNIX;
1119 os_strlcpy(addr.sun_path + 1, WLANTEST_SOCK_NAME,
1120 sizeof(addr.sun_path) - 1);
1121 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1128 ret = ctrl_command(s, argc - 1, &argv[1]);
1132 wlantest_cli_interactive(s);
1137 os_program_deinit();