3 * Copyright (c) 2010-2013, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
12 #include "utils/common.h"
13 #include "utils/eloop.h"
14 #include "utils/edit.h"
15 #include "wlantest_ctrl.h"
18 static int get_cmd_arg_num(const char *str
, int pos
)
22 for (i
= 0; i
<= pos
; i
++) {
25 while (i
<= pos
&& str
[i
] != ' ')
36 static int get_prev_arg_pos(const char *str
, int pos
)
38 while (pos
> 0 && str
[pos
- 1] != ' ')
40 while (pos
> 0 && str
[pos
- 1] == ' ')
42 while (pos
> 0 && str
[pos
- 1] != ' ')
48 static u8
* attr_get(u8
*buf
, size_t buflen
, enum wlantest_ctrl_attr attr
,
53 while (pos
+ 8 <= buf
+ buflen
) {
54 enum wlantest_ctrl_attr a
;
56 a
= WPA_GET_BE32(pos
);
58 alen
= WPA_GET_BE32(pos
);
60 if (pos
+ alen
> buf
+ buflen
) {
61 printf("Invalid control message attribute\n");
75 static u8
* attr_hdr_add(u8
*pos
, u8
*end
, enum wlantest_ctrl_attr attr
,
78 if (pos
== NULL
|| end
- pos
< 8 + len
)
80 WPA_PUT_BE32(pos
, attr
);
82 WPA_PUT_BE32(pos
, len
);
88 static u8
* attr_add_str(u8
*pos
, u8
*end
, enum wlantest_ctrl_attr attr
,
91 size_t len
= os_strlen(str
);
93 if (pos
== NULL
|| end
- pos
< 8 + len
)
95 WPA_PUT_BE32(pos
, attr
);
97 WPA_PUT_BE32(pos
, len
);
99 os_memcpy(pos
, str
, len
);
105 static u8
* attr_add_be32(u8
*pos
, u8
*end
, enum wlantest_ctrl_attr attr
,
108 if (pos
== NULL
|| end
- pos
< 12)
110 WPA_PUT_BE32(pos
, attr
);
112 WPA_PUT_BE32(pos
, 4);
114 WPA_PUT_BE32(pos
, val
);
120 static int cmd_send_and_recv(int s
, const u8
*cmd
, size_t cmd_len
,
121 u8
*resp
, size_t max_resp_len
)
124 enum wlantest_ctrl_cmd cmd_resp
;
126 if (send(s
, cmd
, cmd_len
, 0) < 0)
128 res
= recv(s
, resp
, max_resp_len
, 0);
132 cmd_resp
= WPA_GET_BE32(resp
);
133 if (cmd_resp
== WLANTEST_CTRL_SUCCESS
)
136 if (cmd_resp
== WLANTEST_CTRL_UNKNOWN_CMD
)
137 printf("Unknown command\n");
138 else if (cmd_resp
== WLANTEST_CTRL_INVALID_CMD
)
139 printf("Invalid command\n");
145 static int cmd_simple(int s
, enum wlantest_ctrl_cmd cmd
)
149 WPA_PUT_BE32(buf
, cmd
);
150 res
= cmd_send_and_recv(s
, buf
, sizeof(buf
), buf
, sizeof(buf
));
151 return res
< 0 ? -1 : 0;
155 static char ** get_bssid_list(int s
)
157 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
164 WPA_PUT_BE32(buf
, WLANTEST_CTRL_LIST_BSS
);
165 rlen
= cmd_send_and_recv(s
, buf
, sizeof(buf
), resp
, sizeof(resp
));
169 bssid
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_BSSID
, &len
);
173 res
= os_calloc(len
/ ETH_ALEN
+ 1, sizeof(char *));
176 for (i
= 0; i
< len
/ ETH_ALEN
; i
++) {
177 res
[i
] = os_zalloc(18);
180 os_snprintf(res
[i
], 18, MACSTR
, MAC2STR(bssid
+ ETH_ALEN
* i
));
187 static char ** get_sta_list(int s
, const u8
*bssid
, int add_bcast
)
189 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
190 u8 buf
[100], *pos
, *end
;
197 end
= buf
+ sizeof(buf
);
198 WPA_PUT_BE32(pos
, WLANTEST_CTRL_LIST_STA
);
200 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
201 os_memcpy(pos
, bssid
, ETH_ALEN
);
203 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
207 addr
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_STA_ADDR
, &len
);
211 res
= os_calloc(len
/ ETH_ALEN
+ 1 + add_bcast
, sizeof(char *));
214 for (i
= 0; i
< len
/ ETH_ALEN
; i
++) {
215 res
[i
] = os_zalloc(18);
218 os_snprintf(res
[i
], 18, MACSTR
, MAC2STR(addr
+ ETH_ALEN
* i
));
221 res
[i
] = os_strdup("ff:ff:ff:ff:ff:ff");
227 static int cmd_ping(int s
, int argc
, char *argv
[])
229 int res
= cmd_simple(s
, WLANTEST_CTRL_PING
);
236 static int cmd_terminate(int s
, int argc
, char *argv
[])
238 return cmd_simple(s
, WLANTEST_CTRL_TERMINATE
);
242 static int cmd_list_bss(int s
, int argc
, char *argv
[])
244 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
250 WPA_PUT_BE32(buf
, WLANTEST_CTRL_LIST_BSS
);
251 rlen
= cmd_send_and_recv(s
, buf
, sizeof(buf
), resp
, sizeof(resp
));
255 bssid
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_BSSID
, &len
);
259 for (i
= 0; i
< len
/ ETH_ALEN
; i
++)
260 printf(MACSTR
" ", MAC2STR(bssid
+ ETH_ALEN
* i
));
267 static int cmd_list_sta(int s
, int argc
, char *argv
[])
269 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
276 printf("list_sta needs one argument: BSSID\n");
281 WPA_PUT_BE32(pos
, WLANTEST_CTRL_LIST_STA
);
283 WPA_PUT_BE32(pos
, WLANTEST_ATTR_BSSID
);
285 WPA_PUT_BE32(pos
, ETH_ALEN
);
287 if (hwaddr_aton(argv
[0], pos
) < 0) {
288 printf("Invalid BSSID '%s'\n", argv
[0]);
293 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
297 addr
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_STA_ADDR
, &len
);
301 for (i
= 0; i
< len
/ ETH_ALEN
; i
++)
302 printf(MACSTR
" ", MAC2STR(addr
+ ETH_ALEN
* i
));
309 static char ** complete_list_sta(int s
, const char *str
, int pos
)
311 if (get_cmd_arg_num(str
, pos
) == 1)
312 return get_bssid_list(s
);
317 static int cmd_flush(int s
, int argc
, char *argv
[])
319 return cmd_simple(s
, WLANTEST_CTRL_FLUSH
);
323 static int cmd_clear_sta_counters(int s
, int argc
, char *argv
[])
325 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
330 printf("clear_sta_counters needs two arguments: BSSID and "
336 WPA_PUT_BE32(pos
, WLANTEST_CTRL_CLEAR_STA_COUNTERS
);
338 WPA_PUT_BE32(pos
, WLANTEST_ATTR_BSSID
);
340 WPA_PUT_BE32(pos
, ETH_ALEN
);
342 if (hwaddr_aton(argv
[0], pos
) < 0) {
343 printf("Invalid BSSID '%s'\n", argv
[0]);
348 WPA_PUT_BE32(pos
, WLANTEST_ATTR_STA_ADDR
);
350 WPA_PUT_BE32(pos
, ETH_ALEN
);
352 if (hwaddr_aton(argv
[1], pos
) < 0) {
353 printf("Invalid STA address '%s'\n", argv
[1]);
358 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
366 static char ** complete_clear_sta_counters(int s
, const char *str
, int pos
)
368 int arg
= get_cmd_arg_num(str
, pos
);
374 res
= get_bssid_list(s
);
377 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
379 res
= get_sta_list(s
, addr
, 0);
387 static int cmd_clear_bss_counters(int s
, int argc
, char *argv
[])
389 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
394 printf("clear_bss_counters needs one argument: BSSID\n");
399 WPA_PUT_BE32(pos
, WLANTEST_CTRL_CLEAR_BSS_COUNTERS
);
401 WPA_PUT_BE32(pos
, WLANTEST_ATTR_BSSID
);
403 WPA_PUT_BE32(pos
, ETH_ALEN
);
405 if (hwaddr_aton(argv
[0], pos
) < 0) {
406 printf("Invalid BSSID '%s'\n", argv
[0]);
411 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
419 static char ** complete_clear_bss_counters(int s
, const char *str
, int pos
)
421 if (get_cmd_arg_num(str
, pos
) == 1)
422 return get_bssid_list(s
);
427 static int cmd_clear_tdls_counters(int s
, int argc
, char *argv
[])
429 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
434 printf("clear_tdls_counters needs three arguments: BSSID, "
435 "STA1 address, STA2 address\n");
440 WPA_PUT_BE32(pos
, WLANTEST_CTRL_CLEAR_TDLS_COUNTERS
);
442 WPA_PUT_BE32(pos
, WLANTEST_ATTR_BSSID
);
444 WPA_PUT_BE32(pos
, ETH_ALEN
);
446 if (hwaddr_aton(argv
[0], pos
) < 0) {
447 printf("Invalid BSSID '%s'\n", argv
[0]);
452 WPA_PUT_BE32(pos
, WLANTEST_ATTR_STA_ADDR
);
454 WPA_PUT_BE32(pos
, ETH_ALEN
);
456 if (hwaddr_aton(argv
[1], pos
) < 0) {
457 printf("Invalid STA1 address '%s'\n", argv
[1]);
462 WPA_PUT_BE32(pos
, WLANTEST_ATTR_STA2_ADDR
);
464 WPA_PUT_BE32(pos
, ETH_ALEN
);
466 if (hwaddr_aton(argv
[2], pos
) < 0) {
467 printf("Invalid STA2 address '%s'\n", argv
[2]);
472 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
480 static char ** complete_clear_tdls_counters(int s
, const char *str
, int pos
)
482 int arg
= get_cmd_arg_num(str
, pos
);
488 res
= get_bssid_list(s
);
492 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
494 res
= get_sta_list(s
, addr
, 0);
502 struct sta_counters
{
504 enum wlantest_sta_counter num
;
507 static const struct sta_counters sta_counters
[] = {
508 { "auth_tx", WLANTEST_STA_COUNTER_AUTH_TX
},
509 { "auth_rx", WLANTEST_STA_COUNTER_AUTH_RX
},
510 { "assocreq_tx", WLANTEST_STA_COUNTER_ASSOCREQ_TX
},
511 { "reassocreq_tx", WLANTEST_STA_COUNTER_REASSOCREQ_TX
},
512 { "ptk_learned", WLANTEST_STA_COUNTER_PTK_LEARNED
},
513 { "valid_deauth_tx", WLANTEST_STA_COUNTER_VALID_DEAUTH_TX
},
514 { "valid_deauth_rx", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX
},
515 { "invalid_deauth_tx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX
},
516 { "invalid_deauth_rx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX
},
517 { "valid_disassoc_tx", WLANTEST_STA_COUNTER_VALID_DISASSOC_TX
},
518 { "valid_disassoc_rx", WLANTEST_STA_COUNTER_VALID_DISASSOC_RX
},
519 { "invalid_disassoc_tx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX
},
520 { "invalid_disassoc_rx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX
},
521 { "valid_saqueryreq_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX
},
522 { "valid_saqueryreq_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX
},
523 { "invalid_saqueryreq_tx",
524 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX
},
525 { "invalid_saqueryreq_rx",
526 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX
},
527 { "valid_saqueryresp_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX
},
528 { "valid_saqueryresp_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX
},
529 { "invalid_saqueryresp_tx",
530 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX
},
531 { "invalid_saqueryresp_rx",
532 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX
},
533 { "ping_ok", WLANTEST_STA_COUNTER_PING_OK
},
534 { "assocresp_comeback", WLANTEST_STA_COUNTER_ASSOCRESP_COMEBACK
},
535 { "reassocresp_comeback", WLANTEST_STA_COUNTER_REASSOCRESP_COMEBACK
},
536 { "ping_ok_first_assoc", WLANTEST_STA_COUNTER_PING_OK_FIRST_ASSOC
},
537 { "valid_deauth_rx_ack", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX_ACK
},
538 { "valid_disassoc_rx_ack",
539 WLANTEST_STA_COUNTER_VALID_DISASSOC_RX_ACK
},
540 { "invalid_deauth_rx_ack",
541 WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX_ACK
},
542 { "invalid_disassoc_rx_ack",
543 WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX_ACK
},
544 { "deauth_rx_asleep", WLANTEST_STA_COUNTER_DEAUTH_RX_ASLEEP
},
545 { "deauth_rx_awake", WLANTEST_STA_COUNTER_DEAUTH_RX_AWAKE
},
546 { "disassoc_rx_asleep", WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP
},
547 { "disassoc_rx_awake", WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE
},
548 { "prot_data_tx", WLANTEST_STA_COUNTER_PROT_DATA_TX
},
549 { "deauth_rx_rc6", WLANTEST_STA_COUNTER_DEAUTH_RX_RC6
},
550 { "deauth_rx_rc7", WLANTEST_STA_COUNTER_DEAUTH_RX_RC7
},
551 { "disassoc_rx_rc6", WLANTEST_STA_COUNTER_DISASSOC_RX_RC6
},
552 { "disassoc_rx_rc7", WLANTEST_STA_COUNTER_DISASSOC_RX_RC7
},
556 static int cmd_get_sta_counter(int s
, int argc
, char *argv
[])
558 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
559 u8 buf
[100], *end
, *pos
;
564 printf("get_sta_counter needs at three arguments: "
565 "counter name, BSSID, and STA address\n");
570 end
= buf
+ sizeof(buf
);
571 WPA_PUT_BE32(pos
, WLANTEST_CTRL_GET_STA_COUNTER
);
574 for (i
= 0; sta_counters
[i
].name
; i
++) {
575 if (os_strcasecmp(sta_counters
[i
].name
, argv
[0]) == 0)
578 if (sta_counters
[i
].name
== NULL
) {
579 printf("Unknown STA counter '%s'\n", argv
[0]);
581 for (i
= 0; sta_counters
[i
].name
; i
++)
582 printf(" %s", sta_counters
[i
].name
);
587 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_STA_COUNTER
,
588 sta_counters
[i
].num
);
589 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
590 if (hwaddr_aton(argv
[1], pos
) < 0) {
591 printf("Invalid BSSID '%s'\n", argv
[1]);
596 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
597 if (hwaddr_aton(argv
[2], pos
) < 0) {
598 printf("Invalid STA address '%s'\n", argv
[2]);
603 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
607 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_COUNTER
, &len
);
608 if (pos
== NULL
|| len
!= 4)
610 printf("%u\n", WPA_GET_BE32(pos
));
615 static char ** complete_get_sta_counter(int s
, const char *str
, int pos
)
617 int arg
= get_cmd_arg_num(str
, pos
);
625 count
= ARRAY_SIZE(sta_counters
);
626 res
= os_calloc(count
, sizeof(char *));
629 for (i
= 0; sta_counters
[i
].name
; i
++) {
630 res
[i
] = os_strdup(sta_counters
[i
].name
);
636 res
= get_bssid_list(s
);
639 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
641 res
= get_sta_list(s
, addr
, 0);
649 struct bss_counters
{
651 enum wlantest_bss_counter num
;
654 static const struct bss_counters bss_counters
[] = {
655 { "valid_bip_mmie", WLANTEST_BSS_COUNTER_VALID_BIP_MMIE
},
656 { "invalid_bip_mmie", WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE
},
657 { "missing_bip_mmie", WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE
},
658 { "bip_deauth", WLANTEST_BSS_COUNTER_BIP_DEAUTH
},
659 { "bip_disassoc", WLANTEST_BSS_COUNTER_BIP_DISASSOC
},
663 static int cmd_get_bss_counter(int s
, int argc
, char *argv
[])
665 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
666 u8 buf
[100], *end
, *pos
;
671 printf("get_bss_counter needs at two arguments: "
672 "counter name and BSSID\n");
677 end
= buf
+ sizeof(buf
);
678 WPA_PUT_BE32(pos
, WLANTEST_CTRL_GET_BSS_COUNTER
);
681 for (i
= 0; bss_counters
[i
].name
; i
++) {
682 if (os_strcasecmp(bss_counters
[i
].name
, argv
[0]) == 0)
685 if (bss_counters
[i
].name
== NULL
) {
686 printf("Unknown BSS counter '%s'\n", argv
[0]);
688 for (i
= 0; bss_counters
[i
].name
; i
++)
689 printf(" %s", bss_counters
[i
].name
);
694 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_BSS_COUNTER
,
695 bss_counters
[i
].num
);
696 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
697 if (hwaddr_aton(argv
[1], pos
) < 0) {
698 printf("Invalid BSSID '%s'\n", argv
[1]);
703 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
707 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_COUNTER
, &len
);
708 if (pos
== NULL
|| len
!= 4)
710 printf("%u\n", WPA_GET_BE32(pos
));
715 static char ** complete_get_bss_counter(int s
, const char *str
, int pos
)
717 int arg
= get_cmd_arg_num(str
, pos
);
724 count
= ARRAY_SIZE(bss_counters
);
725 res
= os_calloc(count
, sizeof(char *));
728 for (i
= 0; bss_counters
[i
].name
; i
++) {
729 res
[i
] = os_strdup(bss_counters
[i
].name
);
735 res
= get_bssid_list(s
);
743 static int cmd_relog(int s
, int argc
, char *argv
[])
745 return cmd_simple(s
, WLANTEST_CTRL_RELOG
);
749 struct tdls_counters
{
751 enum wlantest_tdls_counter num
;
754 static const struct tdls_counters tdls_counters
[] = {
755 { "valid_direct_link", WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK
},
756 { "invalid_direct_link", WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK
},
757 { "valid_ap_path", WLANTEST_TDLS_COUNTER_VALID_AP_PATH
},
758 { "invalid_ap_path", WLANTEST_TDLS_COUNTER_INVALID_AP_PATH
},
759 { "setup_req", WLANTEST_TDLS_COUNTER_SETUP_REQ
},
760 { "setup_resp_ok", WLANTEST_TDLS_COUNTER_SETUP_RESP_OK
},
761 { "setup_resp_fail", WLANTEST_TDLS_COUNTER_SETUP_RESP_FAIL
},
762 { "setup_conf_ok", WLANTEST_TDLS_COUNTER_SETUP_CONF_OK
},
763 { "setup_conf_fail", WLANTEST_TDLS_COUNTER_SETUP_CONF_FAIL
},
764 { "teardown", WLANTEST_TDLS_COUNTER_TEARDOWN
},
768 static int cmd_get_tdls_counter(int s
, int argc
, char *argv
[])
770 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
771 u8 buf
[100], *end
, *pos
;
776 printf("get_tdls_counter needs four arguments: "
777 "counter name, BSSID, STA1 address, STA2 address\n");
782 end
= buf
+ sizeof(buf
);
783 WPA_PUT_BE32(pos
, WLANTEST_CTRL_GET_TDLS_COUNTER
);
786 for (i
= 0; tdls_counters
[i
].name
; i
++) {
787 if (os_strcasecmp(tdls_counters
[i
].name
, argv
[0]) == 0)
790 if (tdls_counters
[i
].name
== NULL
) {
791 printf("Unknown TDLS counter '%s'\n", argv
[0]);
793 for (i
= 0; tdls_counters
[i
].name
; i
++)
794 printf(" %s", tdls_counters
[i
].name
);
799 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_TDLS_COUNTER
,
800 tdls_counters
[i
].num
);
801 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
802 if (hwaddr_aton(argv
[1], pos
) < 0) {
803 printf("Invalid BSSID '%s'\n", argv
[1]);
808 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
809 if (hwaddr_aton(argv
[2], pos
) < 0) {
810 printf("Invalid STA1 address '%s'\n", argv
[2]);
815 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA2_ADDR
, ETH_ALEN
);
816 if (hwaddr_aton(argv
[3], pos
) < 0) {
817 printf("Invalid STA2 address '%s'\n", argv
[3]);
822 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
826 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_COUNTER
, &len
);
827 if (pos
== NULL
|| len
!= 4)
829 printf("%u\n", WPA_GET_BE32(pos
));
834 static char ** complete_get_tdls_counter(int s
, const char *str
, int pos
)
836 int arg
= get_cmd_arg_num(str
, pos
);
844 count
= ARRAY_SIZE(tdls_counters
);
845 res
= os_calloc(count
, sizeof(char *));
848 for (i
= 0; tdls_counters
[i
].name
; i
++) {
849 res
[i
] = os_strdup(tdls_counters
[i
].name
);
855 res
= get_bssid_list(s
);
859 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
861 res
= get_sta_list(s
, addr
, 0);
869 struct inject_frames
{
871 enum wlantest_inject_frame frame
;
874 static const struct inject_frames inject_frames
[] = {
875 { "auth", WLANTEST_FRAME_AUTH
},
876 { "assocreq", WLANTEST_FRAME_ASSOCREQ
},
877 { "reassocreq", WLANTEST_FRAME_REASSOCREQ
},
878 { "deauth", WLANTEST_FRAME_DEAUTH
},
879 { "disassoc", WLANTEST_FRAME_DISASSOC
},
880 { "saqueryreq", WLANTEST_FRAME_SAQUERYREQ
},
884 static int cmd_inject(int s
, int argc
, char *argv
[])
886 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
887 u8 buf
[100], *end
, *pos
;
889 enum wlantest_inject_protection prot
;
891 /* <frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff> */
894 printf("inject needs five arguments: frame, protection, "
895 "sender, BSSID, STA/ff:ff:ff:ff:ff:ff\n");
900 end
= buf
+ sizeof(buf
);
901 WPA_PUT_BE32(pos
, WLANTEST_CTRL_INJECT
);
904 for (i
= 0; inject_frames
[i
].name
; i
++) {
905 if (os_strcasecmp(inject_frames
[i
].name
, argv
[0]) == 0)
908 if (inject_frames
[i
].name
== NULL
) {
909 printf("Unknown inject frame '%s'\n", argv
[0]);
911 for (i
= 0; inject_frames
[i
].name
; i
++)
912 printf(" %s", inject_frames
[i
].name
);
917 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_FRAME
,
918 inject_frames
[i
].frame
);
920 if (os_strcasecmp(argv
[1], "normal") == 0)
921 prot
= WLANTEST_INJECT_NORMAL
;
922 else if (os_strcasecmp(argv
[1], "protected") == 0)
923 prot
= WLANTEST_INJECT_PROTECTED
;
924 else if (os_strcasecmp(argv
[1], "unprotected") == 0)
925 prot
= WLANTEST_INJECT_UNPROTECTED
;
926 else if (os_strcasecmp(argv
[1], "incorrect") == 0)
927 prot
= WLANTEST_INJECT_INCORRECT_KEY
;
929 printf("Unknown protection type '%s'\n", argv
[1]);
930 printf("Protection types: normal protected unprotected "
934 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_PROTECTION
, prot
);
936 if (os_strcasecmp(argv
[2], "ap") == 0) {
937 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_SENDER_AP
,
939 } else if (os_strcasecmp(argv
[2], "sta") == 0) {
940 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_SENDER_AP
,
943 printf("Unknown sender '%s'\n", argv
[2]);
944 printf("Sender types: ap sta\n");
948 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
949 if (hwaddr_aton(argv
[3], pos
) < 0) {
950 printf("Invalid BSSID '%s'\n", argv
[3]);
955 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
956 if (hwaddr_aton(argv
[4], pos
) < 0) {
957 printf("Invalid STA '%s'\n", argv
[4]);
962 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
970 static char ** complete_inject(int s
, const char *str
, int pos
)
972 int arg
= get_cmd_arg_num(str
, pos
);
980 count
= ARRAY_SIZE(inject_frames
);
981 res
= os_calloc(count
, sizeof(char *));
984 for (i
= 0; inject_frames
[i
].name
; i
++) {
985 res
[i
] = os_strdup(inject_frames
[i
].name
);
991 res
= os_calloc(5, sizeof(char *));
994 res
[0] = os_strdup("normal");
997 res
[1] = os_strdup("protected");
1000 res
[2] = os_strdup("unprotected");
1003 res
[3] = os_strdup("incorrect");
1008 res
= os_calloc(3, sizeof(char *));
1011 res
[0] = os_strdup("ap");
1014 res
[1] = os_strdup("sta");
1019 res
= get_bssid_list(s
);
1022 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
1024 res
= get_sta_list(s
, addr
, 1);
1032 static u8
* add_hex(u8
*pos
, u8
*end
, const char *str
)
1039 while (*s
== ' ' || *s
== '\t' || *s
== '\r' || *s
== '\n' ||
1045 while (*s
!= '\0' && *s
!= '\r' && *s
!= '\n')
1052 printf("Invalid hex encoding '%s'\n", s
);
1056 printf("Too long frame\n");
1067 static int cmd_send(int s
, int argc
, char *argv
[])
1069 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1070 u8 buf
[WLANTEST_CTRL_MAX_CMD_LEN
], *end
, *pos
, *len_pos
;
1072 enum wlantest_inject_protection prot
;
1075 /* <prot> <raw frame as hex dump> */
1078 printf("send needs two arguments: protected/unprotected, "
1079 "raw frame as hex dump\n");
1084 end
= buf
+ sizeof(buf
);
1085 WPA_PUT_BE32(pos
, WLANTEST_CTRL_SEND
);
1088 if (os_strcasecmp(argv
[0], "normal") == 0)
1089 prot
= WLANTEST_INJECT_NORMAL
;
1090 else if (os_strcasecmp(argv
[0], "protected") == 0)
1091 prot
= WLANTEST_INJECT_PROTECTED
;
1092 else if (os_strcasecmp(argv
[0], "unprotected") == 0)
1093 prot
= WLANTEST_INJECT_UNPROTECTED
;
1094 else if (os_strcasecmp(argv
[0], "incorrect") == 0)
1095 prot
= WLANTEST_INJECT_INCORRECT_KEY
;
1097 printf("Unknown protection type '%s'\n", argv
[1]);
1098 printf("Protection types: normal protected unprotected "
1102 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_PROTECTION
, prot
);
1104 WPA_PUT_BE32(pos
, WLANTEST_ATTR_FRAME
);
1109 for (arg
= 1; pos
&& arg
< argc
; arg
++)
1110 pos
= add_hex(pos
, end
, argv
[arg
]);
1114 WPA_PUT_BE32(len_pos
, pos
- len_pos
- 4);
1116 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1124 static char ** complete_send(int s
, const char *str
, int pos
)
1126 int arg
= get_cmd_arg_num(str
, pos
);
1131 res
= os_calloc(5, sizeof(char *));
1134 res
[0] = os_strdup("normal");
1137 res
[1] = os_strdup("protected");
1140 res
[2] = os_strdup("unprotected");
1143 res
[3] = os_strdup("incorrect");
1153 static int cmd_version(int s
, int argc
, char *argv
[])
1155 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1161 WPA_PUT_BE32(buf
, WLANTEST_CTRL_VERSION
);
1162 rlen
= cmd_send_and_recv(s
, buf
, sizeof(buf
), resp
, sizeof(resp
));
1166 version
= (char *) attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_VERSION
,
1168 if (version
== NULL
)
1171 for (i
= 0; i
< len
; i
++)
1172 putchar(version
[i
]);
1179 static int cmd_add_passphrase(int s
, int argc
, char *argv
[])
1181 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1182 u8 buf
[100], *pos
, *end
;
1187 printf("add_passphrase needs one argument: passphrase\n");
1191 len
= os_strlen(argv
[0]);
1192 if (len
< 8 || len
> 63) {
1193 printf("Invalid passphrase '%s'\n", argv
[0]);
1197 end
= buf
+ sizeof(buf
);
1198 WPA_PUT_BE32(pos
, WLANTEST_CTRL_ADD_PASSPHRASE
);
1200 pos
= attr_add_str(pos
, end
, WLANTEST_ATTR_PASSPHRASE
,
1203 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1204 if (hwaddr_aton(argv
[1], pos
) < 0) {
1205 printf("Invalid BSSID '%s'\n", argv
[3]);
1211 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1218 static int cmd_add_wepkey(int s
, int argc
, char *argv
[])
1220 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1221 u8 buf
[100], *pos
, *end
;
1225 printf("add_wepkey needs one argument: WEP key\n");
1230 end
= buf
+ sizeof(buf
);
1231 WPA_PUT_BE32(pos
, WLANTEST_CTRL_ADD_PASSPHRASE
);
1233 pos
= attr_add_str(pos
, end
, WLANTEST_ATTR_WEPKEY
, argv
[0]);
1235 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1244 enum wlantest_sta_info num
;
1247 static const struct sta_infos sta_infos
[] = {
1248 { "proto", WLANTEST_STA_INFO_PROTO
},
1249 { "pairwise", WLANTEST_STA_INFO_PAIRWISE
},
1250 { "key_mgmt", WLANTEST_STA_INFO_KEY_MGMT
},
1251 { "rsn_capab", WLANTEST_STA_INFO_RSN_CAPAB
},
1252 { "state", WLANTEST_STA_INFO_STATE
},
1253 { "gtk", WLANTEST_STA_INFO_GTK
},
1257 static int cmd_info_sta(int s
, int argc
, char *argv
[])
1259 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1260 u8 buf
[100], *end
, *pos
;
1266 printf("sta_info needs at three arguments: "
1267 "counter name, BSSID, and STA address\n");
1272 end
= buf
+ sizeof(buf
);
1273 WPA_PUT_BE32(pos
, WLANTEST_CTRL_INFO_STA
);
1276 for (i
= 0; sta_infos
[i
].name
; i
++) {
1277 if (os_strcasecmp(sta_infos
[i
].name
, argv
[0]) == 0)
1280 if (sta_infos
[i
].name
== NULL
) {
1281 printf("Unknown STA info '%s'\n", argv
[0]);
1282 printf("Info fields:");
1283 for (i
= 0; sta_infos
[i
].name
; i
++)
1284 printf(" %s", sta_infos
[i
].name
);
1289 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_STA_INFO
,
1291 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1292 if (hwaddr_aton(argv
[1], pos
) < 0) {
1293 printf("Invalid BSSID '%s'\n", argv
[1]);
1298 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
1299 if (hwaddr_aton(argv
[2], pos
) < 0) {
1300 printf("Invalid STA address '%s'\n", argv
[2]);
1305 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1309 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_INFO
, &len
);
1312 if (len
>= sizeof(info
))
1313 len
= sizeof(info
) - 1;
1314 os_memcpy(info
, pos
, len
);
1316 printf("%s\n", info
);
1321 static char ** complete_info_sta(int s
, const char *str
, int pos
)
1323 int arg
= get_cmd_arg_num(str
, pos
);
1331 count
= ARRAY_SIZE(sta_infos
);
1332 res
= os_calloc(count
, sizeof(char *));
1335 for (i
= 0; sta_infos
[i
].name
; i
++) {
1336 res
[i
] = os_strdup(sta_infos
[i
].name
);
1342 res
= get_bssid_list(s
);
1345 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
1347 res
= get_sta_list(s
, addr
, 0);
1357 enum wlantest_bss_info num
;
1360 static const struct bss_infos bss_infos
[] = {
1361 { "proto", WLANTEST_BSS_INFO_PROTO
},
1362 { "pairwise", WLANTEST_BSS_INFO_PAIRWISE
},
1363 { "group", WLANTEST_BSS_INFO_GROUP
},
1364 { "group_mgmt", WLANTEST_BSS_INFO_GROUP_MGMT
},
1365 { "key_mgmt", WLANTEST_BSS_INFO_KEY_MGMT
},
1366 { "rsn_capab", WLANTEST_BSS_INFO_RSN_CAPAB
},
1370 static int cmd_info_bss(int s
, int argc
, char *argv
[])
1372 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1373 u8 buf
[100], *end
, *pos
;
1379 printf("bss_info needs at two arguments: "
1380 "field name and BSSID\n");
1385 end
= buf
+ sizeof(buf
);
1386 WPA_PUT_BE32(pos
, WLANTEST_CTRL_INFO_BSS
);
1389 for (i
= 0; bss_infos
[i
].name
; i
++) {
1390 if (os_strcasecmp(bss_infos
[i
].name
, argv
[0]) == 0)
1393 if (bss_infos
[i
].name
== NULL
) {
1394 printf("Unknown BSS info '%s'\n", argv
[0]);
1395 printf("Info fields:");
1396 for (i
= 0; bss_infos
[i
].name
; i
++)
1397 printf(" %s", bss_infos
[i
].name
);
1402 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_BSS_INFO
,
1404 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1405 if (hwaddr_aton(argv
[1], pos
) < 0) {
1406 printf("Invalid BSSID '%s'\n", argv
[1]);
1411 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1415 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_INFO
, &len
);
1418 if (len
>= sizeof(info
))
1419 len
= sizeof(info
) - 1;
1420 os_memcpy(info
, pos
, len
);
1422 printf("%s\n", info
);
1427 static char ** complete_info_bss(int s
, const char *str
, int pos
)
1429 int arg
= get_cmd_arg_num(str
, pos
);
1436 count
= ARRAY_SIZE(bss_infos
);
1437 res
= os_calloc(count
, sizeof(char *));
1440 for (i
= 0; bss_infos
[i
].name
; i
++) {
1441 res
[i
] = os_strdup(bss_infos
[i
].name
);
1447 res
= get_bssid_list(s
);
1455 static int cmd_get_tx_tid(int s
, int argc
, char *argv
[])
1457 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1458 u8 buf
[100], *end
, *pos
;
1463 printf("get_tx_tid needs three arguments: "
1464 "BSSID, STA address, and TID\n");
1469 end
= buf
+ sizeof(buf
);
1470 WPA_PUT_BE32(pos
, WLANTEST_CTRL_GET_TX_TID
);
1473 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1474 if (hwaddr_aton(argv
[0], pos
) < 0) {
1475 printf("Invalid BSSID '%s'\n", argv
[0]);
1480 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
1481 if (hwaddr_aton(argv
[1], pos
) < 0) {
1482 printf("Invalid STA address '%s'\n", argv
[1]);
1487 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_TID
, atoi(argv
[2]));
1489 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1493 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_COUNTER
, &len
);
1494 if (pos
== NULL
|| len
!= 4)
1496 printf("%u\n", WPA_GET_BE32(pos
));
1501 static int cmd_get_rx_tid(int s
, int argc
, char *argv
[])
1503 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1504 u8 buf
[100], *end
, *pos
;
1509 printf("get_tx_tid needs three arguments: "
1510 "BSSID, STA address, and TID\n");
1515 end
= buf
+ sizeof(buf
);
1516 WPA_PUT_BE32(pos
, WLANTEST_CTRL_GET_RX_TID
);
1519 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1520 if (hwaddr_aton(argv
[0], pos
) < 0) {
1521 printf("Invalid BSSID '%s'\n", argv
[0]);
1526 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
1527 if (hwaddr_aton(argv
[1], pos
) < 0) {
1528 printf("Invalid STA address '%s'\n", argv
[1]);
1533 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_TID
, atoi(argv
[2]));
1535 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1539 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_COUNTER
, &len
);
1540 if (pos
== NULL
|| len
!= 4)
1542 printf("%u\n", WPA_GET_BE32(pos
));
1547 static char ** complete_get_tid(int s
, const char *str
, int pos
)
1549 int arg
= get_cmd_arg_num(str
, pos
);
1555 res
= get_bssid_list(s
);
1558 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
1560 res
= get_sta_list(s
, addr
, 0);
1568 struct wlantest_cli_cmd
{
1570 int (*handler
)(int s
, int argc
, char *argv
[]);
1572 char ** (*complete
)(int s
, const char *str
, int pos
);
1575 static const struct wlantest_cli_cmd wlantest_cli_commands
[] = {
1576 { "ping", cmd_ping
, "= test connection to wlantest", NULL
},
1577 { "terminate", cmd_terminate
, "= terminate wlantest", NULL
},
1578 { "list_bss", cmd_list_bss
, "= get BSS list", NULL
},
1579 { "list_sta", cmd_list_sta
, "<BSSID> = get STA list",
1580 complete_list_sta
},
1581 { "flush", cmd_flush
, "= drop all collected BSS data", NULL
},
1582 { "clear_sta_counters", cmd_clear_sta_counters
,
1583 "<BSSID> <STA> = clear STA counters", complete_clear_sta_counters
},
1584 { "clear_bss_counters", cmd_clear_bss_counters
,
1585 "<BSSID> = clear BSS counters", complete_clear_bss_counters
},
1586 { "get_sta_counter", cmd_get_sta_counter
,
1587 "<counter> <BSSID> <STA> = get STA counter value",
1588 complete_get_sta_counter
},
1589 { "get_bss_counter", cmd_get_bss_counter
,
1590 "<counter> <BSSID> = get BSS counter value",
1591 complete_get_bss_counter
},
1592 { "inject", cmd_inject
,
1593 "<frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff>",
1596 "<prot> <raw frame as hex dump>",
1598 { "version", cmd_version
, "= get wlantest version", NULL
},
1599 { "add_passphrase", cmd_add_passphrase
,
1600 "<passphrase> = add a known passphrase", NULL
},
1601 { "add_wepkey", cmd_add_wepkey
,
1602 "<WEP key> = add a known WEP key", NULL
},
1603 { "info_sta", cmd_info_sta
,
1604 "<field> <BSSID> <STA> = get STA information",
1605 complete_info_sta
},
1606 { "info_bss", cmd_info_bss
,
1607 "<field> <BSSID> = get BSS information",
1608 complete_info_bss
},
1609 { "clear_tdls_counters", cmd_clear_tdls_counters
,
1610 "<BSSID> <STA1> <STA2> = clear TDLS counters",
1611 complete_clear_tdls_counters
},
1612 { "get_tdls_counter", cmd_get_tdls_counter
,
1613 "<counter> <BSSID> <STA1> <STA2> = get TDLS counter value",
1614 complete_get_tdls_counter
},
1615 { "get_bss_counter", cmd_get_bss_counter
,
1616 "<counter> <BSSID> = get BSS counter value",
1617 complete_get_bss_counter
},
1618 { "relog", cmd_relog
, "= re-open log-file (allow rolling logs)", NULL
},
1619 { "get_tx_tid", cmd_get_tx_tid
,
1620 "<BSSID> <STA> <TID> = get STA TX TID counter value",
1622 { "get_rx_tid", cmd_get_rx_tid
,
1623 "<BSSID> <STA> <TID> = get STA RX TID counter value",
1625 { NULL
, NULL
, NULL
, NULL
}
1629 static int ctrl_command(int s
, int argc
, char *argv
[])
1631 const struct wlantest_cli_cmd
*cmd
, *match
= NULL
;
1635 for (cmd
= wlantest_cli_commands
; cmd
->cmd
; cmd
++) {
1636 if (os_strncasecmp(cmd
->cmd
, argv
[0], os_strlen(argv
[0])) == 0)
1639 if (os_strcasecmp(cmd
->cmd
, argv
[0]) == 0) {
1649 printf("Ambiguous command '%s'; possible commands:", argv
[0]);
1650 for (cmd
= wlantest_cli_commands
; cmd
->cmd
; cmd
++) {
1651 if (os_strncasecmp(cmd
->cmd
, argv
[0],
1652 os_strlen(argv
[0])) == 0) {
1653 printf(" %s", cmd
->cmd
);
1658 } else if (count
== 0) {
1659 printf("Unknown command '%s'\n", argv
[0]);
1662 ret
= match
->handler(s
, argc
- 1, &argv
[1]);
1669 struct wlantest_cli
{
1676 static int tokenize_cmd(char *cmd
, char *argv
[])
1689 if (argc
== max_args
)
1692 char *pos2
= os_strrchr(pos
, '"');
1696 while (*pos
!= '\0' && *pos
!= ' ')
1706 static void wlantest_cli_edit_cmd_cb(void *ctx
, char *cmd
)
1708 struct wlantest_cli
*cli
= ctx
;
1709 char *argv
[max_args
];
1711 argc
= tokenize_cmd(cmd
, argv
);
1713 int ret
= ctrl_command(cli
->s
, argc
, argv
);
1720 static void wlantest_cli_eloop_terminate(int sig
, void *signal_ctx
)
1726 static void wlantest_cli_edit_eof_cb(void *ctx
)
1732 static char ** wlantest_cli_cmd_list(void)
1737 res
= os_calloc(ARRAY_SIZE(wlantest_cli_commands
), sizeof(char *));
1741 for (i
= 0; wlantest_cli_commands
[i
].cmd
; i
++) {
1742 res
[i
] = os_strdup(wlantest_cli_commands
[i
].cmd
);
1751 static char ** wlantest_cli_cmd_completion(struct wlantest_cli
*cli
,
1752 const char *cmd
, const char *str
,
1757 for (i
= 0; wlantest_cli_commands
[i
].cmd
; i
++) {
1758 const struct wlantest_cli_cmd
*c
= &wlantest_cli_commands
[i
];
1759 if (os_strcasecmp(c
->cmd
, cmd
) == 0) {
1761 printf("\r%s\n", c
->usage
);
1764 return c
->complete(cli
->s
, str
, pos
);
1773 static char ** wlantest_cli_edit_completion_cb(void *ctx
, const char *str
,
1776 struct wlantest_cli
*cli
= ctx
;
1781 end
= os_strchr(str
, ' ');
1782 if (end
== NULL
|| str
+ pos
< end
)
1783 return wlantest_cli_cmd_list();
1785 cmd
= os_malloc(pos
+ 1);
1788 os_memcpy(cmd
, str
, pos
);
1789 cmd
[end
- str
] = '\0';
1790 res
= wlantest_cli_cmd_completion(cli
, cmd
, str
, pos
);
1796 static void wlantest_cli_interactive(int s
)
1798 struct wlantest_cli cli
;
1799 char *home
, *hfile
= NULL
;
1804 home
= getenv("HOME");
1806 const char *fname
= ".wlantest_cli_history";
1807 int hfile_len
= os_strlen(home
) + 1 + os_strlen(fname
) + 1;
1808 hfile
= os_malloc(hfile_len
);
1810 os_snprintf(hfile
, hfile_len
, "%s/%s", home
, fname
);
1814 eloop_register_signal_terminate(wlantest_cli_eloop_terminate
, &cli
);
1815 edit_init(wlantest_cli_edit_cmd_cb
, wlantest_cli_edit_eof_cb
,
1816 wlantest_cli_edit_completion_cb
, &cli
, hfile
, NULL
);
1820 edit_deinit(hfile
, NULL
);
1826 int main(int argc
, char *argv
[])
1829 struct sockaddr_un addr
;
1832 if (os_program_init())
1835 s
= socket(AF_UNIX
, SOCK_SEQPACKET
, 0);
1841 os_memset(&addr
, 0, sizeof(addr
));
1842 addr
.sun_family
= AF_UNIX
;
1843 os_strlcpy(addr
.sun_path
+ 1, WLANTEST_SOCK_NAME
,
1844 sizeof(addr
.sun_path
) - 1);
1845 if (connect(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1852 ret
= ctrl_command(s
, argc
- 1, &argv
[1]);
1856 wlantest_cli_interactive(s
);
1861 os_program_deinit();