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
},
660 { "probe_response", WLANTEST_BSS_COUNTER_PROBE_RESPONSE
},
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
= ARRAY_SIZE(bss_counters
);
726 res
= os_calloc(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 static int cmd_relog(int s
, int argc
, char *argv
[])
746 return cmd_simple(s
, WLANTEST_CTRL_RELOG
);
750 struct tdls_counters
{
752 enum wlantest_tdls_counter num
;
755 static const struct tdls_counters tdls_counters
[] = {
756 { "valid_direct_link", WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK
},
757 { "invalid_direct_link", WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK
},
758 { "valid_ap_path", WLANTEST_TDLS_COUNTER_VALID_AP_PATH
},
759 { "invalid_ap_path", WLANTEST_TDLS_COUNTER_INVALID_AP_PATH
},
760 { "setup_req", WLANTEST_TDLS_COUNTER_SETUP_REQ
},
761 { "setup_resp_ok", WLANTEST_TDLS_COUNTER_SETUP_RESP_OK
},
762 { "setup_resp_fail", WLANTEST_TDLS_COUNTER_SETUP_RESP_FAIL
},
763 { "setup_conf_ok", WLANTEST_TDLS_COUNTER_SETUP_CONF_OK
},
764 { "setup_conf_fail", WLANTEST_TDLS_COUNTER_SETUP_CONF_FAIL
},
765 { "teardown", WLANTEST_TDLS_COUNTER_TEARDOWN
},
769 static int cmd_get_tdls_counter(int s
, int argc
, char *argv
[])
771 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
772 u8 buf
[100], *end
, *pos
;
777 printf("get_tdls_counter needs four arguments: "
778 "counter name, BSSID, STA1 address, STA2 address\n");
783 end
= buf
+ sizeof(buf
);
784 WPA_PUT_BE32(pos
, WLANTEST_CTRL_GET_TDLS_COUNTER
);
787 for (i
= 0; tdls_counters
[i
].name
; i
++) {
788 if (os_strcasecmp(tdls_counters
[i
].name
, argv
[0]) == 0)
791 if (tdls_counters
[i
].name
== NULL
) {
792 printf("Unknown TDLS counter '%s'\n", argv
[0]);
794 for (i
= 0; tdls_counters
[i
].name
; i
++)
795 printf(" %s", tdls_counters
[i
].name
);
800 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_TDLS_COUNTER
,
801 tdls_counters
[i
].num
);
802 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
803 if (hwaddr_aton(argv
[1], pos
) < 0) {
804 printf("Invalid BSSID '%s'\n", argv
[1]);
809 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
810 if (hwaddr_aton(argv
[2], pos
) < 0) {
811 printf("Invalid STA1 address '%s'\n", argv
[2]);
816 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA2_ADDR
, ETH_ALEN
);
817 if (hwaddr_aton(argv
[3], pos
) < 0) {
818 printf("Invalid STA2 address '%s'\n", argv
[3]);
823 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
827 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_COUNTER
, &len
);
828 if (pos
== NULL
|| len
!= 4)
830 printf("%u\n", WPA_GET_BE32(pos
));
835 static char ** complete_get_tdls_counter(int s
, const char *str
, int pos
)
837 int arg
= get_cmd_arg_num(str
, pos
);
845 count
= ARRAY_SIZE(tdls_counters
);
846 res
= os_calloc(count
, sizeof(char *));
849 for (i
= 0; tdls_counters
[i
].name
; i
++) {
850 res
[i
] = os_strdup(tdls_counters
[i
].name
);
856 res
= get_bssid_list(s
);
860 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
862 res
= get_sta_list(s
, addr
, 0);
870 struct inject_frames
{
872 enum wlantest_inject_frame frame
;
875 static const struct inject_frames inject_frames
[] = {
876 { "auth", WLANTEST_FRAME_AUTH
},
877 { "assocreq", WLANTEST_FRAME_ASSOCREQ
},
878 { "reassocreq", WLANTEST_FRAME_REASSOCREQ
},
879 { "deauth", WLANTEST_FRAME_DEAUTH
},
880 { "disassoc", WLANTEST_FRAME_DISASSOC
},
881 { "saqueryreq", WLANTEST_FRAME_SAQUERYREQ
},
885 static int cmd_inject(int s
, int argc
, char *argv
[])
887 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
888 u8 buf
[100], *end
, *pos
;
890 enum wlantest_inject_protection prot
;
892 /* <frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff> */
895 printf("inject needs five arguments: frame, protection, "
896 "sender, BSSID, STA/ff:ff:ff:ff:ff:ff\n");
901 end
= buf
+ sizeof(buf
);
902 WPA_PUT_BE32(pos
, WLANTEST_CTRL_INJECT
);
905 for (i
= 0; inject_frames
[i
].name
; i
++) {
906 if (os_strcasecmp(inject_frames
[i
].name
, argv
[0]) == 0)
909 if (inject_frames
[i
].name
== NULL
) {
910 printf("Unknown inject frame '%s'\n", argv
[0]);
912 for (i
= 0; inject_frames
[i
].name
; i
++)
913 printf(" %s", inject_frames
[i
].name
);
918 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_FRAME
,
919 inject_frames
[i
].frame
);
921 if (os_strcasecmp(argv
[1], "normal") == 0)
922 prot
= WLANTEST_INJECT_NORMAL
;
923 else if (os_strcasecmp(argv
[1], "protected") == 0)
924 prot
= WLANTEST_INJECT_PROTECTED
;
925 else if (os_strcasecmp(argv
[1], "unprotected") == 0)
926 prot
= WLANTEST_INJECT_UNPROTECTED
;
927 else if (os_strcasecmp(argv
[1], "incorrect") == 0)
928 prot
= WLANTEST_INJECT_INCORRECT_KEY
;
930 printf("Unknown protection type '%s'\n", argv
[1]);
931 printf("Protection types: normal protected unprotected "
935 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_PROTECTION
, prot
);
937 if (os_strcasecmp(argv
[2], "ap") == 0) {
938 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_SENDER_AP
,
940 } else if (os_strcasecmp(argv
[2], "sta") == 0) {
941 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_SENDER_AP
,
944 printf("Unknown sender '%s'\n", argv
[2]);
945 printf("Sender types: ap sta\n");
949 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
950 if (hwaddr_aton(argv
[3], pos
) < 0) {
951 printf("Invalid BSSID '%s'\n", argv
[3]);
956 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
957 if (hwaddr_aton(argv
[4], pos
) < 0) {
958 printf("Invalid STA '%s'\n", argv
[4]);
963 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
971 static char ** complete_inject(int s
, const char *str
, int pos
)
973 int arg
= get_cmd_arg_num(str
, pos
);
981 count
= ARRAY_SIZE(inject_frames
);
982 res
= os_calloc(count
, sizeof(char *));
985 for (i
= 0; inject_frames
[i
].name
; i
++) {
986 res
[i
] = os_strdup(inject_frames
[i
].name
);
992 res
= os_calloc(5, sizeof(char *));
995 res
[0] = os_strdup("normal");
998 res
[1] = os_strdup("protected");
1001 res
[2] = os_strdup("unprotected");
1004 res
[3] = os_strdup("incorrect");
1009 res
= os_calloc(3, sizeof(char *));
1012 res
[0] = os_strdup("ap");
1015 res
[1] = os_strdup("sta");
1020 res
= get_bssid_list(s
);
1023 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
1025 res
= get_sta_list(s
, addr
, 1);
1033 static u8
* add_hex(u8
*pos
, u8
*end
, const char *str
)
1040 while (*s
== ' ' || *s
== '\t' || *s
== '\r' || *s
== '\n' ||
1046 while (*s
!= '\0' && *s
!= '\r' && *s
!= '\n')
1053 printf("Invalid hex encoding '%s'\n", s
);
1057 printf("Too long frame\n");
1068 static int cmd_send(int s
, int argc
, char *argv
[])
1070 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1071 u8 buf
[WLANTEST_CTRL_MAX_CMD_LEN
], *end
, *pos
, *len_pos
;
1073 enum wlantest_inject_protection prot
;
1076 /* <prot> <raw frame as hex dump> */
1079 printf("send needs two arguments: protected/unprotected, "
1080 "raw frame as hex dump\n");
1085 end
= buf
+ sizeof(buf
);
1086 WPA_PUT_BE32(pos
, WLANTEST_CTRL_SEND
);
1089 if (os_strcasecmp(argv
[0], "normal") == 0)
1090 prot
= WLANTEST_INJECT_NORMAL
;
1091 else if (os_strcasecmp(argv
[0], "protected") == 0)
1092 prot
= WLANTEST_INJECT_PROTECTED
;
1093 else if (os_strcasecmp(argv
[0], "unprotected") == 0)
1094 prot
= WLANTEST_INJECT_UNPROTECTED
;
1095 else if (os_strcasecmp(argv
[0], "incorrect") == 0)
1096 prot
= WLANTEST_INJECT_INCORRECT_KEY
;
1098 printf("Unknown protection type '%s'\n", argv
[1]);
1099 printf("Protection types: normal protected unprotected "
1103 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_PROTECTION
, prot
);
1105 WPA_PUT_BE32(pos
, WLANTEST_ATTR_FRAME
);
1110 for (arg
= 1; pos
&& arg
< argc
; arg
++)
1111 pos
= add_hex(pos
, end
, argv
[arg
]);
1115 WPA_PUT_BE32(len_pos
, pos
- len_pos
- 4);
1117 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1125 static char ** complete_send(int s
, const char *str
, int pos
)
1127 int arg
= get_cmd_arg_num(str
, pos
);
1132 res
= os_calloc(5, sizeof(char *));
1135 res
[0] = os_strdup("normal");
1138 res
[1] = os_strdup("protected");
1141 res
[2] = os_strdup("unprotected");
1144 res
[3] = os_strdup("incorrect");
1154 static int cmd_version(int s
, int argc
, char *argv
[])
1156 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1162 WPA_PUT_BE32(buf
, WLANTEST_CTRL_VERSION
);
1163 rlen
= cmd_send_and_recv(s
, buf
, sizeof(buf
), resp
, sizeof(resp
));
1167 version
= (char *) attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_VERSION
,
1169 if (version
== NULL
)
1172 for (i
= 0; i
< len
; i
++)
1173 putchar(version
[i
]);
1180 static int cmd_add_passphrase(int s
, int argc
, char *argv
[])
1182 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1183 u8 buf
[100], *pos
, *end
;
1188 printf("add_passphrase needs one argument: passphrase\n");
1192 len
= os_strlen(argv
[0]);
1193 if (len
< 8 || len
> 63) {
1194 printf("Invalid passphrase '%s'\n", argv
[0]);
1198 end
= buf
+ sizeof(buf
);
1199 WPA_PUT_BE32(pos
, WLANTEST_CTRL_ADD_PASSPHRASE
);
1201 pos
= attr_add_str(pos
, end
, WLANTEST_ATTR_PASSPHRASE
,
1204 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1205 if (hwaddr_aton(argv
[1], pos
) < 0) {
1206 printf("Invalid BSSID '%s'\n", argv
[3]);
1212 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1219 static int cmd_add_wepkey(int s
, int argc
, char *argv
[])
1221 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1222 u8 buf
[100], *pos
, *end
;
1226 printf("add_wepkey needs one argument: WEP key\n");
1231 end
= buf
+ sizeof(buf
);
1232 WPA_PUT_BE32(pos
, WLANTEST_CTRL_ADD_PASSPHRASE
);
1234 pos
= attr_add_str(pos
, end
, WLANTEST_ATTR_WEPKEY
, argv
[0]);
1236 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1245 enum wlantest_sta_info num
;
1248 static const struct sta_infos sta_infos
[] = {
1249 { "proto", WLANTEST_STA_INFO_PROTO
},
1250 { "pairwise", WLANTEST_STA_INFO_PAIRWISE
},
1251 { "key_mgmt", WLANTEST_STA_INFO_KEY_MGMT
},
1252 { "rsn_capab", WLANTEST_STA_INFO_RSN_CAPAB
},
1253 { "state", WLANTEST_STA_INFO_STATE
},
1254 { "gtk", WLANTEST_STA_INFO_GTK
},
1258 static int cmd_info_sta(int s
, int argc
, char *argv
[])
1260 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1261 u8 buf
[100], *end
, *pos
;
1267 printf("sta_info needs at three arguments: "
1268 "counter name, BSSID, and STA address\n");
1273 end
= buf
+ sizeof(buf
);
1274 WPA_PUT_BE32(pos
, WLANTEST_CTRL_INFO_STA
);
1277 for (i
= 0; sta_infos
[i
].name
; i
++) {
1278 if (os_strcasecmp(sta_infos
[i
].name
, argv
[0]) == 0)
1281 if (sta_infos
[i
].name
== NULL
) {
1282 printf("Unknown STA info '%s'\n", argv
[0]);
1283 printf("Info fields:");
1284 for (i
= 0; sta_infos
[i
].name
; i
++)
1285 printf(" %s", sta_infos
[i
].name
);
1290 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_STA_INFO
,
1292 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1293 if (hwaddr_aton(argv
[1], pos
) < 0) {
1294 printf("Invalid BSSID '%s'\n", argv
[1]);
1299 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
1300 if (hwaddr_aton(argv
[2], pos
) < 0) {
1301 printf("Invalid STA address '%s'\n", argv
[2]);
1306 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1310 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_INFO
, &len
);
1313 if (len
>= sizeof(info
))
1314 len
= sizeof(info
) - 1;
1315 os_memcpy(info
, pos
, len
);
1317 printf("%s\n", info
);
1322 static char ** complete_info_sta(int s
, const char *str
, int pos
)
1324 int arg
= get_cmd_arg_num(str
, pos
);
1332 count
= ARRAY_SIZE(sta_infos
);
1333 res
= os_calloc(count
, sizeof(char *));
1336 for (i
= 0; sta_infos
[i
].name
; i
++) {
1337 res
[i
] = os_strdup(sta_infos
[i
].name
);
1343 res
= get_bssid_list(s
);
1346 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
1348 res
= get_sta_list(s
, addr
, 0);
1358 enum wlantest_bss_info num
;
1361 static const struct bss_infos bss_infos
[] = {
1362 { "proto", WLANTEST_BSS_INFO_PROTO
},
1363 { "pairwise", WLANTEST_BSS_INFO_PAIRWISE
},
1364 { "group", WLANTEST_BSS_INFO_GROUP
},
1365 { "group_mgmt", WLANTEST_BSS_INFO_GROUP_MGMT
},
1366 { "key_mgmt", WLANTEST_BSS_INFO_KEY_MGMT
},
1367 { "rsn_capab", WLANTEST_BSS_INFO_RSN_CAPAB
},
1371 static int cmd_info_bss(int s
, int argc
, char *argv
[])
1373 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1374 u8 buf
[100], *end
, *pos
;
1380 printf("bss_info needs at two arguments: "
1381 "field name and BSSID\n");
1386 end
= buf
+ sizeof(buf
);
1387 WPA_PUT_BE32(pos
, WLANTEST_CTRL_INFO_BSS
);
1390 for (i
= 0; bss_infos
[i
].name
; i
++) {
1391 if (os_strcasecmp(bss_infos
[i
].name
, argv
[0]) == 0)
1394 if (bss_infos
[i
].name
== NULL
) {
1395 printf("Unknown BSS info '%s'\n", argv
[0]);
1396 printf("Info fields:");
1397 for (i
= 0; bss_infos
[i
].name
; i
++)
1398 printf(" %s", bss_infos
[i
].name
);
1403 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_BSS_INFO
,
1405 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1406 if (hwaddr_aton(argv
[1], pos
) < 0) {
1407 printf("Invalid BSSID '%s'\n", argv
[1]);
1412 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1416 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_INFO
, &len
);
1419 if (len
>= sizeof(info
))
1420 len
= sizeof(info
) - 1;
1421 os_memcpy(info
, pos
, len
);
1423 printf("%s\n", info
);
1428 static char ** complete_info_bss(int s
, const char *str
, int pos
)
1430 int arg
= get_cmd_arg_num(str
, pos
);
1437 count
= ARRAY_SIZE(bss_infos
);
1438 res
= os_calloc(count
, sizeof(char *));
1441 for (i
= 0; bss_infos
[i
].name
; i
++) {
1442 res
[i
] = os_strdup(bss_infos
[i
].name
);
1448 res
= get_bssid_list(s
);
1456 static int cmd_get_tx_tid(int s
, int argc
, char *argv
[])
1458 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1459 u8 buf
[100], *end
, *pos
;
1464 printf("get_tx_tid needs three arguments: "
1465 "BSSID, STA address, and TID\n");
1470 end
= buf
+ sizeof(buf
);
1471 WPA_PUT_BE32(pos
, WLANTEST_CTRL_GET_TX_TID
);
1474 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1475 if (hwaddr_aton(argv
[0], pos
) < 0) {
1476 printf("Invalid BSSID '%s'\n", argv
[0]);
1481 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
1482 if (hwaddr_aton(argv
[1], pos
) < 0) {
1483 printf("Invalid STA address '%s'\n", argv
[1]);
1488 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_TID
, atoi(argv
[2]));
1490 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1494 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_COUNTER
, &len
);
1495 if (pos
== NULL
|| len
!= 4)
1497 printf("%u\n", WPA_GET_BE32(pos
));
1502 static int cmd_get_rx_tid(int s
, int argc
, char *argv
[])
1504 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1505 u8 buf
[100], *end
, *pos
;
1510 printf("get_tx_tid needs three arguments: "
1511 "BSSID, STA address, and TID\n");
1516 end
= buf
+ sizeof(buf
);
1517 WPA_PUT_BE32(pos
, WLANTEST_CTRL_GET_RX_TID
);
1520 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1521 if (hwaddr_aton(argv
[0], pos
) < 0) {
1522 printf("Invalid BSSID '%s'\n", argv
[0]);
1527 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
1528 if (hwaddr_aton(argv
[1], pos
) < 0) {
1529 printf("Invalid STA address '%s'\n", argv
[1]);
1534 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_TID
, atoi(argv
[2]));
1536 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1540 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_COUNTER
, &len
);
1541 if (pos
== NULL
|| len
!= 4)
1543 printf("%u\n", WPA_GET_BE32(pos
));
1548 static char ** complete_get_tid(int s
, const char *str
, int pos
)
1550 int arg
= get_cmd_arg_num(str
, pos
);
1556 res
= get_bssid_list(s
);
1559 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
1561 res
= get_sta_list(s
, addr
, 0);
1569 struct wlantest_cli_cmd
{
1571 int (*handler
)(int s
, int argc
, char *argv
[]);
1573 char ** (*complete
)(int s
, const char *str
, int pos
);
1576 static const struct wlantest_cli_cmd wlantest_cli_commands
[] = {
1577 { "ping", cmd_ping
, "= test connection to wlantest", NULL
},
1578 { "terminate", cmd_terminate
, "= terminate wlantest", NULL
},
1579 { "list_bss", cmd_list_bss
, "= get BSS list", NULL
},
1580 { "list_sta", cmd_list_sta
, "<BSSID> = get STA list",
1581 complete_list_sta
},
1582 { "flush", cmd_flush
, "= drop all collected BSS data", NULL
},
1583 { "clear_sta_counters", cmd_clear_sta_counters
,
1584 "<BSSID> <STA> = clear STA counters", complete_clear_sta_counters
},
1585 { "clear_bss_counters", cmd_clear_bss_counters
,
1586 "<BSSID> = clear BSS counters", complete_clear_bss_counters
},
1587 { "get_sta_counter", cmd_get_sta_counter
,
1588 "<counter> <BSSID> <STA> = get STA counter value",
1589 complete_get_sta_counter
},
1590 { "get_bss_counter", cmd_get_bss_counter
,
1591 "<counter> <BSSID> = get BSS counter value",
1592 complete_get_bss_counter
},
1593 { "inject", cmd_inject
,
1594 "<frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff>",
1597 "<prot> <raw frame as hex dump>",
1599 { "version", cmd_version
, "= get wlantest version", NULL
},
1600 { "add_passphrase", cmd_add_passphrase
,
1601 "<passphrase> = add a known passphrase", NULL
},
1602 { "add_wepkey", cmd_add_wepkey
,
1603 "<WEP key> = add a known WEP key", NULL
},
1604 { "info_sta", cmd_info_sta
,
1605 "<field> <BSSID> <STA> = get STA information",
1606 complete_info_sta
},
1607 { "info_bss", cmd_info_bss
,
1608 "<field> <BSSID> = get BSS information",
1609 complete_info_bss
},
1610 { "clear_tdls_counters", cmd_clear_tdls_counters
,
1611 "<BSSID> <STA1> <STA2> = clear TDLS counters",
1612 complete_clear_tdls_counters
},
1613 { "get_tdls_counter", cmd_get_tdls_counter
,
1614 "<counter> <BSSID> <STA1> <STA2> = get TDLS counter value",
1615 complete_get_tdls_counter
},
1616 { "get_bss_counter", cmd_get_bss_counter
,
1617 "<counter> <BSSID> = get BSS counter value",
1618 complete_get_bss_counter
},
1619 { "relog", cmd_relog
, "= re-open log-file (allow rolling logs)", NULL
},
1620 { "get_tx_tid", cmd_get_tx_tid
,
1621 "<BSSID> <STA> <TID> = get STA TX TID counter value",
1623 { "get_rx_tid", cmd_get_rx_tid
,
1624 "<BSSID> <STA> <TID> = get STA RX TID counter value",
1626 { NULL
, NULL
, NULL
, NULL
}
1630 static int ctrl_command(int s
, int argc
, char *argv
[])
1632 const struct wlantest_cli_cmd
*cmd
, *match
= NULL
;
1636 for (cmd
= wlantest_cli_commands
; cmd
->cmd
; cmd
++) {
1637 if (os_strncasecmp(cmd
->cmd
, argv
[0], os_strlen(argv
[0])) == 0)
1640 if (os_strcasecmp(cmd
->cmd
, argv
[0]) == 0) {
1650 printf("Ambiguous command '%s'; possible commands:", argv
[0]);
1651 for (cmd
= wlantest_cli_commands
; cmd
->cmd
; cmd
++) {
1652 if (os_strncasecmp(cmd
->cmd
, argv
[0],
1653 os_strlen(argv
[0])) == 0) {
1654 printf(" %s", cmd
->cmd
);
1659 } else if (count
== 0) {
1660 printf("Unknown command '%s'\n", argv
[0]);
1663 ret
= match
->handler(s
, argc
- 1, &argv
[1]);
1670 struct wlantest_cli
{
1677 static int tokenize_cmd(char *cmd
, char *argv
[])
1690 if (argc
== max_args
)
1693 char *pos2
= os_strrchr(pos
, '"');
1697 while (*pos
!= '\0' && *pos
!= ' ')
1707 static void wlantest_cli_edit_cmd_cb(void *ctx
, char *cmd
)
1709 struct wlantest_cli
*cli
= ctx
;
1710 char *argv
[max_args
];
1712 argc
= tokenize_cmd(cmd
, argv
);
1714 int ret
= ctrl_command(cli
->s
, argc
, argv
);
1721 static void wlantest_cli_eloop_terminate(int sig
, void *signal_ctx
)
1727 static void wlantest_cli_edit_eof_cb(void *ctx
)
1733 static char ** wlantest_cli_cmd_list(void)
1738 res
= os_calloc(ARRAY_SIZE(wlantest_cli_commands
), sizeof(char *));
1742 for (i
= 0; wlantest_cli_commands
[i
].cmd
; i
++) {
1743 res
[i
] = os_strdup(wlantest_cli_commands
[i
].cmd
);
1752 static char ** wlantest_cli_cmd_completion(struct wlantest_cli
*cli
,
1753 const char *cmd
, const char *str
,
1758 for (i
= 0; wlantest_cli_commands
[i
].cmd
; i
++) {
1759 const struct wlantest_cli_cmd
*c
= &wlantest_cli_commands
[i
];
1760 if (os_strcasecmp(c
->cmd
, cmd
) == 0) {
1762 printf("\r%s\n", c
->usage
);
1765 return c
->complete(cli
->s
, str
, pos
);
1774 static char ** wlantest_cli_edit_completion_cb(void *ctx
, const char *str
,
1777 struct wlantest_cli
*cli
= ctx
;
1782 end
= os_strchr(str
, ' ');
1783 if (end
== NULL
|| str
+ pos
< end
)
1784 return wlantest_cli_cmd_list();
1786 cmd
= os_malloc(pos
+ 1);
1789 os_memcpy(cmd
, str
, pos
);
1790 cmd
[end
- str
] = '\0';
1791 res
= wlantest_cli_cmd_completion(cli
, cmd
, str
, pos
);
1797 static void wlantest_cli_interactive(int s
)
1799 struct wlantest_cli cli
;
1800 char *home
, *hfile
= NULL
;
1805 home
= getenv("HOME");
1807 const char *fname
= ".wlantest_cli_history";
1808 int hfile_len
= os_strlen(home
) + 1 + os_strlen(fname
) + 1;
1809 hfile
= os_malloc(hfile_len
);
1811 os_snprintf(hfile
, hfile_len
, "%s/%s", home
, fname
);
1815 eloop_register_signal_terminate(wlantest_cli_eloop_terminate
, &cli
);
1816 edit_init(wlantest_cli_edit_cmd_cb
, wlantest_cli_edit_eof_cb
,
1817 wlantest_cli_edit_completion_cb
, &cli
, hfile
, NULL
);
1821 edit_deinit(hfile
, NULL
);
1827 int main(int argc
, char *argv
[])
1830 struct sockaddr_un addr
;
1833 if (os_program_init())
1836 s
= socket(AF_UNIX
, SOCK_SEQPACKET
, 0);
1842 os_memset(&addr
, 0, sizeof(addr
));
1843 addr
.sun_family
= AF_UNIX
;
1844 os_strlcpy(addr
.sun_path
+ 1, WLANTEST_SOCK_NAME
,
1845 sizeof(addr
.sun_path
) - 1);
1846 if (connect(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1853 ret
= ctrl_command(s
, argc
- 1, &argv
[1]);
1857 wlantest_cli_interactive(s
);
1862 os_program_deinit();