3 * Copyright (c) 2010, 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
= sizeof(sta_counters
) / sizeof(sta_counters
[0]);
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
= sizeof(bss_counters
) / sizeof(bss_counters
[0]);
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 struct tdls_counters
{
745 enum wlantest_tdls_counter num
;
748 static const struct tdls_counters tdls_counters
[] = {
749 { "valid_direct_link", WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK
},
750 { "invalid_direct_link", WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK
},
751 { "valid_ap_path", WLANTEST_TDLS_COUNTER_VALID_AP_PATH
},
752 { "invalid_ap_path", WLANTEST_TDLS_COUNTER_INVALID_AP_PATH
},
753 { "setup_req", WLANTEST_TDLS_COUNTER_SETUP_REQ
},
754 { "setup_resp_ok", WLANTEST_TDLS_COUNTER_SETUP_RESP_OK
},
755 { "setup_resp_fail", WLANTEST_TDLS_COUNTER_SETUP_RESP_FAIL
},
756 { "setup_conf_ok", WLANTEST_TDLS_COUNTER_SETUP_CONF_OK
},
757 { "setup_conf_fail", WLANTEST_TDLS_COUNTER_SETUP_CONF_FAIL
},
758 { "teardown", WLANTEST_TDLS_COUNTER_TEARDOWN
},
762 static int cmd_get_tdls_counter(int s
, int argc
, char *argv
[])
764 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
765 u8 buf
[100], *end
, *pos
;
770 printf("get_tdls_counter needs four arguments: "
771 "counter name, BSSID, STA1 address, STA2 address\n");
776 end
= buf
+ sizeof(buf
);
777 WPA_PUT_BE32(pos
, WLANTEST_CTRL_GET_TDLS_COUNTER
);
780 for (i
= 0; tdls_counters
[i
].name
; i
++) {
781 if (os_strcasecmp(tdls_counters
[i
].name
, argv
[0]) == 0)
784 if (tdls_counters
[i
].name
== NULL
) {
785 printf("Unknown TDLS counter '%s'\n", argv
[0]);
787 for (i
= 0; tdls_counters
[i
].name
; i
++)
788 printf(" %s", tdls_counters
[i
].name
);
793 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_TDLS_COUNTER
,
794 tdls_counters
[i
].num
);
795 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
796 if (hwaddr_aton(argv
[1], pos
) < 0) {
797 printf("Invalid BSSID '%s'\n", argv
[1]);
802 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
803 if (hwaddr_aton(argv
[2], pos
) < 0) {
804 printf("Invalid STA1 address '%s'\n", argv
[2]);
809 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA2_ADDR
, ETH_ALEN
);
810 if (hwaddr_aton(argv
[3], pos
) < 0) {
811 printf("Invalid STA2 address '%s'\n", argv
[3]);
816 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
820 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_COUNTER
, &len
);
821 if (pos
== NULL
|| len
!= 4)
823 printf("%u\n", WPA_GET_BE32(pos
));
828 static char ** complete_get_tdls_counter(int s
, const char *str
, int pos
)
830 int arg
= get_cmd_arg_num(str
, pos
);
838 count
= sizeof(tdls_counters
) / sizeof(tdls_counters
[0]);
839 res
= os_calloc(count
, sizeof(char *));
842 for (i
= 0; tdls_counters
[i
].name
; i
++) {
843 res
[i
] = os_strdup(tdls_counters
[i
].name
);
849 res
= get_bssid_list(s
);
853 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
855 res
= get_sta_list(s
, addr
, 0);
863 struct inject_frames
{
865 enum wlantest_inject_frame frame
;
868 static const struct inject_frames inject_frames
[] = {
869 { "auth", WLANTEST_FRAME_AUTH
},
870 { "assocreq", WLANTEST_FRAME_ASSOCREQ
},
871 { "reassocreq", WLANTEST_FRAME_REASSOCREQ
},
872 { "deauth", WLANTEST_FRAME_DEAUTH
},
873 { "disassoc", WLANTEST_FRAME_DISASSOC
},
874 { "saqueryreq", WLANTEST_FRAME_SAQUERYREQ
},
878 static int cmd_inject(int s
, int argc
, char *argv
[])
880 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
881 u8 buf
[100], *end
, *pos
;
883 enum wlantest_inject_protection prot
;
885 /* <frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff> */
888 printf("inject needs five arguments: frame, protection, "
889 "sender, BSSID, STA/ff:ff:ff:ff:ff:ff\n");
894 end
= buf
+ sizeof(buf
);
895 WPA_PUT_BE32(pos
, WLANTEST_CTRL_INJECT
);
898 for (i
= 0; inject_frames
[i
].name
; i
++) {
899 if (os_strcasecmp(inject_frames
[i
].name
, argv
[0]) == 0)
902 if (inject_frames
[i
].name
== NULL
) {
903 printf("Unknown inject frame '%s'\n", argv
[0]);
905 for (i
= 0; inject_frames
[i
].name
; i
++)
906 printf(" %s", inject_frames
[i
].name
);
911 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_FRAME
,
912 inject_frames
[i
].frame
);
914 if (os_strcasecmp(argv
[1], "normal") == 0)
915 prot
= WLANTEST_INJECT_NORMAL
;
916 else if (os_strcasecmp(argv
[1], "protected") == 0)
917 prot
= WLANTEST_INJECT_PROTECTED
;
918 else if (os_strcasecmp(argv
[1], "unprotected") == 0)
919 prot
= WLANTEST_INJECT_UNPROTECTED
;
920 else if (os_strcasecmp(argv
[1], "incorrect") == 0)
921 prot
= WLANTEST_INJECT_INCORRECT_KEY
;
923 printf("Unknown protection type '%s'\n", argv
[1]);
924 printf("Protection types: normal protected unprotected "
928 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_PROTECTION
, prot
);
930 if (os_strcasecmp(argv
[2], "ap") == 0) {
931 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_SENDER_AP
,
933 } else if (os_strcasecmp(argv
[2], "sta") == 0) {
934 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_SENDER_AP
,
937 printf("Unknown sender '%s'\n", argv
[2]);
938 printf("Sender types: ap sta\n");
942 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
943 if (hwaddr_aton(argv
[3], pos
) < 0) {
944 printf("Invalid BSSID '%s'\n", argv
[3]);
949 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
950 if (hwaddr_aton(argv
[4], pos
) < 0) {
951 printf("Invalid STA '%s'\n", argv
[4]);
956 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
964 static char ** complete_inject(int s
, const char *str
, int pos
)
966 int arg
= get_cmd_arg_num(str
, pos
);
974 count
= sizeof(inject_frames
) / sizeof(inject_frames
[0]);
975 res
= os_calloc(count
, sizeof(char *));
978 for (i
= 0; inject_frames
[i
].name
; i
++) {
979 res
[i
] = os_strdup(inject_frames
[i
].name
);
985 res
= os_calloc(5, sizeof(char *));
988 res
[0] = os_strdup("normal");
991 res
[1] = os_strdup("protected");
994 res
[2] = os_strdup("unprotected");
997 res
[3] = os_strdup("incorrect");
1002 res
= os_calloc(3, sizeof(char *));
1005 res
[0] = os_strdup("ap");
1008 res
[1] = os_strdup("sta");
1013 res
= get_bssid_list(s
);
1016 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
1018 res
= get_sta_list(s
, addr
, 1);
1026 static u8
* add_hex(u8
*pos
, u8
*end
, const char *str
)
1033 while (*s
== ' ' || *s
== '\t' || *s
== '\r' || *s
== '\n' ||
1039 while (*s
!= '\0' && *s
!= '\r' && *s
!= '\n')
1046 printf("Invalid hex encoding '%s'\n", s
);
1050 printf("Too long frame\n");
1061 static int cmd_send(int s
, int argc
, char *argv
[])
1063 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1064 u8 buf
[WLANTEST_CTRL_MAX_CMD_LEN
], *end
, *pos
, *len_pos
;
1066 enum wlantest_inject_protection prot
;
1069 /* <prot> <raw frame as hex dump> */
1072 printf("send needs two arguments: protected/unprotected, "
1073 "raw frame as hex dump\n");
1078 end
= buf
+ sizeof(buf
);
1079 WPA_PUT_BE32(pos
, WLANTEST_CTRL_SEND
);
1082 if (os_strcasecmp(argv
[0], "normal") == 0)
1083 prot
= WLANTEST_INJECT_NORMAL
;
1084 else if (os_strcasecmp(argv
[0], "protected") == 0)
1085 prot
= WLANTEST_INJECT_PROTECTED
;
1086 else if (os_strcasecmp(argv
[0], "unprotected") == 0)
1087 prot
= WLANTEST_INJECT_UNPROTECTED
;
1088 else if (os_strcasecmp(argv
[0], "incorrect") == 0)
1089 prot
= WLANTEST_INJECT_INCORRECT_KEY
;
1091 printf("Unknown protection type '%s'\n", argv
[1]);
1092 printf("Protection types: normal protected unprotected "
1096 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_INJECT_PROTECTION
, prot
);
1098 WPA_PUT_BE32(pos
, WLANTEST_ATTR_FRAME
);
1103 for (arg
= 1; pos
&& arg
< argc
; arg
++)
1104 pos
= add_hex(pos
, end
, argv
[arg
]);
1108 WPA_PUT_BE32(len_pos
, pos
- len_pos
- 4);
1110 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1118 static char ** complete_send(int s
, const char *str
, int pos
)
1120 int arg
= get_cmd_arg_num(str
, pos
);
1125 res
= os_calloc(5, sizeof(char *));
1128 res
[0] = os_strdup("normal");
1131 res
[1] = os_strdup("protected");
1134 res
[2] = os_strdup("unprotected");
1137 res
[3] = os_strdup("incorrect");
1147 static int cmd_version(int s
, int argc
, char *argv
[])
1149 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1155 WPA_PUT_BE32(buf
, WLANTEST_CTRL_VERSION
);
1156 rlen
= cmd_send_and_recv(s
, buf
, sizeof(buf
), resp
, sizeof(resp
));
1160 version
= (char *) attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_VERSION
,
1162 if (version
== NULL
)
1165 for (i
= 0; i
< len
; i
++)
1166 putchar(version
[i
]);
1173 static int cmd_add_passphrase(int s
, int argc
, char *argv
[])
1175 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1176 u8 buf
[100], *pos
, *end
;
1181 printf("add_passphrase needs one argument: passphrase\n");
1185 len
= os_strlen(argv
[0]);
1186 if (len
< 8 || len
> 63) {
1187 printf("Invalid passphrase '%s'\n", argv
[0]);
1191 end
= buf
+ sizeof(buf
);
1192 WPA_PUT_BE32(pos
, WLANTEST_CTRL_ADD_PASSPHRASE
);
1194 pos
= attr_add_str(pos
, end
, WLANTEST_ATTR_PASSPHRASE
,
1197 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1198 if (hwaddr_aton(argv
[1], pos
) < 0) {
1199 printf("Invalid BSSID '%s'\n", argv
[3]);
1205 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1214 enum wlantest_sta_info num
;
1217 static const struct sta_infos sta_infos
[] = {
1218 { "proto", WLANTEST_STA_INFO_PROTO
},
1219 { "pairwise", WLANTEST_STA_INFO_PAIRWISE
},
1220 { "key_mgmt", WLANTEST_STA_INFO_KEY_MGMT
},
1221 { "rsn_capab", WLANTEST_STA_INFO_RSN_CAPAB
},
1222 { "state", WLANTEST_STA_INFO_STATE
},
1223 { "gtk", WLANTEST_STA_INFO_GTK
},
1227 static int cmd_info_sta(int s
, int argc
, char *argv
[])
1229 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1230 u8 buf
[100], *end
, *pos
;
1236 printf("sta_info needs at three arguments: "
1237 "counter name, BSSID, and STA address\n");
1242 end
= buf
+ sizeof(buf
);
1243 WPA_PUT_BE32(pos
, WLANTEST_CTRL_INFO_STA
);
1246 for (i
= 0; sta_infos
[i
].name
; i
++) {
1247 if (os_strcasecmp(sta_infos
[i
].name
, argv
[0]) == 0)
1250 if (sta_infos
[i
].name
== NULL
) {
1251 printf("Unknown STA info '%s'\n", argv
[0]);
1252 printf("Info fields:");
1253 for (i
= 0; sta_infos
[i
].name
; i
++)
1254 printf(" %s", sta_infos
[i
].name
);
1259 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_STA_INFO
,
1261 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1262 if (hwaddr_aton(argv
[1], pos
) < 0) {
1263 printf("Invalid BSSID '%s'\n", argv
[1]);
1268 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_STA_ADDR
, ETH_ALEN
);
1269 if (hwaddr_aton(argv
[2], pos
) < 0) {
1270 printf("Invalid STA address '%s'\n", argv
[2]);
1275 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1279 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_INFO
, &len
);
1282 if (len
>= sizeof(info
))
1283 len
= sizeof(info
) - 1;
1284 os_memcpy(info
, pos
, len
);
1286 printf("%s\n", info
);
1291 static char ** complete_info_sta(int s
, const char *str
, int pos
)
1293 int arg
= get_cmd_arg_num(str
, pos
);
1301 count
= sizeof(sta_infos
) / sizeof(sta_infos
[0]);
1302 res
= os_calloc(count
, sizeof(char *));
1305 for (i
= 0; sta_infos
[i
].name
; i
++) {
1306 res
[i
] = os_strdup(sta_infos
[i
].name
);
1312 res
= get_bssid_list(s
);
1315 if (hwaddr_aton(&str
[get_prev_arg_pos(str
, pos
)], addr
) < 0)
1317 res
= get_sta_list(s
, addr
, 0);
1327 enum wlantest_bss_info num
;
1330 static const struct bss_infos bss_infos
[] = {
1331 { "proto", WLANTEST_BSS_INFO_PROTO
},
1332 { "pairwise", WLANTEST_BSS_INFO_PAIRWISE
},
1333 { "group", WLANTEST_BSS_INFO_GROUP
},
1334 { "group_mgmt", WLANTEST_BSS_INFO_GROUP_MGMT
},
1335 { "key_mgmt", WLANTEST_BSS_INFO_KEY_MGMT
},
1336 { "rsn_capab", WLANTEST_BSS_INFO_RSN_CAPAB
},
1340 static int cmd_info_bss(int s
, int argc
, char *argv
[])
1342 u8 resp
[WLANTEST_CTRL_MAX_RESP_LEN
];
1343 u8 buf
[100], *end
, *pos
;
1349 printf("bss_info needs at two arguments: "
1350 "field name and BSSID\n");
1355 end
= buf
+ sizeof(buf
);
1356 WPA_PUT_BE32(pos
, WLANTEST_CTRL_INFO_BSS
);
1359 for (i
= 0; bss_infos
[i
].name
; i
++) {
1360 if (os_strcasecmp(bss_infos
[i
].name
, argv
[0]) == 0)
1363 if (bss_infos
[i
].name
== NULL
) {
1364 printf("Unknown BSS info '%s'\n", argv
[0]);
1365 printf("Info fields:");
1366 for (i
= 0; bss_infos
[i
].name
; i
++)
1367 printf(" %s", bss_infos
[i
].name
);
1372 pos
= attr_add_be32(pos
, end
, WLANTEST_ATTR_BSS_INFO
,
1374 pos
= attr_hdr_add(pos
, end
, WLANTEST_ATTR_BSSID
, ETH_ALEN
);
1375 if (hwaddr_aton(argv
[1], pos
) < 0) {
1376 printf("Invalid BSSID '%s'\n", argv
[1]);
1381 rlen
= cmd_send_and_recv(s
, buf
, pos
- buf
, resp
, sizeof(resp
));
1385 pos
= attr_get(resp
+ 4, rlen
- 4, WLANTEST_ATTR_INFO
, &len
);
1388 if (len
>= sizeof(info
))
1389 len
= sizeof(info
) - 1;
1390 os_memcpy(info
, pos
, len
);
1392 printf("%s\n", info
);
1397 static char ** complete_info_bss(int s
, const char *str
, int pos
)
1399 int arg
= get_cmd_arg_num(str
, pos
);
1406 count
= sizeof(bss_infos
) / sizeof(bss_infos
[0]);
1407 res
= os_calloc(count
, sizeof(char *));
1410 for (i
= 0; bss_infos
[i
].name
; i
++) {
1411 res
[i
] = os_strdup(bss_infos
[i
].name
);
1417 res
= get_bssid_list(s
);
1425 struct wlantest_cli_cmd
{
1427 int (*handler
)(int s
, int argc
, char *argv
[]);
1429 char ** (*complete
)(int s
, const char *str
, int pos
);
1432 static const struct wlantest_cli_cmd wlantest_cli_commands
[] = {
1433 { "ping", cmd_ping
, "= test connection to wlantest", NULL
},
1434 { "terminate", cmd_terminate
, "= terminate wlantest", NULL
},
1435 { "list_bss", cmd_list_bss
, "= get BSS list", NULL
},
1436 { "list_sta", cmd_list_sta
, "<BSSID> = get STA list",
1437 complete_list_sta
},
1438 { "flush", cmd_flush
, "= drop all collected BSS data", NULL
},
1439 { "clear_sta_counters", cmd_clear_sta_counters
,
1440 "<BSSID> <STA> = clear STA counters", complete_clear_sta_counters
},
1441 { "clear_bss_counters", cmd_clear_bss_counters
,
1442 "<BSSID> = clear BSS counters", complete_clear_bss_counters
},
1443 { "get_sta_counter", cmd_get_sta_counter
,
1444 "<counter> <BSSID> <STA> = get STA counter value",
1445 complete_get_sta_counter
},
1446 { "get_bss_counter", cmd_get_bss_counter
,
1447 "<counter> <BSSID> = get BSS counter value",
1448 complete_get_bss_counter
},
1449 { "inject", cmd_inject
,
1450 "<frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff>",
1453 "<prot> <raw frame as hex dump>",
1455 { "version", cmd_version
, "= get wlantest version", NULL
},
1456 { "add_passphrase", cmd_add_passphrase
,
1457 "<passphrase> = add a known passphrase", NULL
},
1458 { "info_sta", cmd_info_sta
,
1459 "<field> <BSSID> <STA> = get STA information",
1460 complete_info_sta
},
1461 { "info_bss", cmd_info_bss
,
1462 "<field> <BSSID> = get BSS information",
1463 complete_info_bss
},
1464 { "clear_tdls_counters", cmd_clear_tdls_counters
,
1465 "<BSSID> <STA1> <STA2> = clear TDLS counters",
1466 complete_clear_tdls_counters
},
1467 { "get_tdls_counter", cmd_get_tdls_counter
,
1468 "<counter> <BSSID> <STA1> <STA2> = get TDLS counter value",
1469 complete_get_tdls_counter
},
1470 { "get_bss_counter", cmd_get_bss_counter
,
1471 "<counter> <BSSID> = get BSS counter value",
1472 complete_get_bss_counter
},
1473 { NULL
, NULL
, NULL
, NULL
}
1477 static int ctrl_command(int s
, int argc
, char *argv
[])
1479 const struct wlantest_cli_cmd
*cmd
, *match
= NULL
;
1483 for (cmd
= wlantest_cli_commands
; cmd
->cmd
; cmd
++) {
1484 if (os_strncasecmp(cmd
->cmd
, argv
[0], os_strlen(argv
[0])) == 0)
1487 if (os_strcasecmp(cmd
->cmd
, argv
[0]) == 0) {
1497 printf("Ambiguous command '%s'; possible commands:", argv
[0]);
1498 for (cmd
= wlantest_cli_commands
; cmd
->cmd
; cmd
++) {
1499 if (os_strncasecmp(cmd
->cmd
, argv
[0],
1500 os_strlen(argv
[0])) == 0) {
1501 printf(" %s", cmd
->cmd
);
1506 } else if (count
== 0) {
1507 printf("Unknown command '%s'\n", argv
[0]);
1510 ret
= match
->handler(s
, argc
- 1, &argv
[1]);
1517 struct wlantest_cli
{
1524 static int tokenize_cmd(char *cmd
, char *argv
[])
1537 if (argc
== max_args
)
1540 char *pos2
= os_strrchr(pos
, '"');
1544 while (*pos
!= '\0' && *pos
!= ' ')
1554 static void wlantest_cli_edit_cmd_cb(void *ctx
, char *cmd
)
1556 struct wlantest_cli
*cli
= ctx
;
1557 char *argv
[max_args
];
1559 argc
= tokenize_cmd(cmd
, argv
);
1561 int ret
= ctrl_command(cli
->s
, argc
, argv
);
1568 static void wlantest_cli_eloop_terminate(int sig
, void *signal_ctx
)
1574 static void wlantest_cli_edit_eof_cb(void *ctx
)
1580 static char ** wlantest_cli_cmd_list(void)
1585 count
= sizeof(wlantest_cli_commands
) /
1586 sizeof(wlantest_cli_commands
[0]);
1587 res
= os_calloc(count
, sizeof(char *));
1591 for (i
= 0; wlantest_cli_commands
[i
].cmd
; i
++) {
1592 res
[i
] = os_strdup(wlantest_cli_commands
[i
].cmd
);
1601 static char ** wlantest_cli_cmd_completion(struct wlantest_cli
*cli
,
1602 const char *cmd
, const char *str
,
1607 for (i
= 0; wlantest_cli_commands
[i
].cmd
; i
++) {
1608 const struct wlantest_cli_cmd
*c
= &wlantest_cli_commands
[i
];
1609 if (os_strcasecmp(c
->cmd
, cmd
) == 0) {
1611 printf("\r%s\n", c
->usage
);
1614 return c
->complete(cli
->s
, str
, pos
);
1623 static char ** wlantest_cli_edit_completion_cb(void *ctx
, const char *str
,
1626 struct wlantest_cli
*cli
= ctx
;
1631 end
= os_strchr(str
, ' ');
1632 if (end
== NULL
|| str
+ pos
< end
)
1633 return wlantest_cli_cmd_list();
1635 cmd
= os_malloc(pos
+ 1);
1638 os_memcpy(cmd
, str
, pos
);
1639 cmd
[end
- str
] = '\0';
1640 res
= wlantest_cli_cmd_completion(cli
, cmd
, str
, pos
);
1646 static void wlantest_cli_interactive(int s
)
1648 struct wlantest_cli cli
;
1649 char *home
, *hfile
= NULL
;
1654 home
= getenv("HOME");
1656 const char *fname
= ".wlantest_cli_history";
1657 int hfile_len
= os_strlen(home
) + 1 + os_strlen(fname
) + 1;
1658 hfile
= os_malloc(hfile_len
);
1660 os_snprintf(hfile
, hfile_len
, "%s/%s", home
, fname
);
1664 eloop_register_signal_terminate(wlantest_cli_eloop_terminate
, &cli
);
1665 edit_init(wlantest_cli_edit_cmd_cb
, wlantest_cli_edit_eof_cb
,
1666 wlantest_cli_edit_completion_cb
, &cli
, hfile
, NULL
);
1670 edit_deinit(hfile
, NULL
);
1676 int main(int argc
, char *argv
[])
1679 struct sockaddr_un addr
;
1682 if (os_program_init())
1685 s
= socket(AF_UNIX
, SOCK_SEQPACKET
, 0);
1691 os_memset(&addr
, 0, sizeof(addr
));
1692 addr
.sun_family
= AF_UNIX
;
1693 os_strlcpy(addr
.sun_path
+ 1, WLANTEST_SOCK_NAME
,
1694 sizeof(addr
.sun_path
) - 1);
1695 if (connect(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1702 ret
= ctrl_command(s
, argc
- 1, &argv
[1]);
1706 wlantest_cli_interactive(s
);
1711 os_program_deinit();