wlantest: Add ping_ok_first_assoc STA counter
[mech_eap.git] / wlantest / wlantest_cli.c
1 /*
2  * wlantest controller
3  * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "utils/includes.h"
16 #include <sys/un.h>
17
18 #include "utils/common.h"
19 #include "utils/eloop.h"
20 #include "utils/edit.h"
21 #include "wlantest_ctrl.h"
22
23
24 static int get_cmd_arg_num(const char *str, int pos)
25 {
26         int arg = 0, i;
27
28         for (i = 0; i <= pos; i++) {
29                 if (str[i] != ' ') {
30                         arg++;
31                         while (i <= pos && str[i] != ' ')
32                                 i++;
33                 }
34         }
35
36         if (arg > 0)
37                 arg--;
38         return arg;
39 }
40
41
42 static int get_prev_arg_pos(const char *str, int pos)
43 {
44         while (pos > 0 && str[pos - 1] != ' ')
45                 pos--;
46         while (pos > 0 && str[pos - 1] == ' ')
47                 pos--;
48         while (pos > 0 && str[pos - 1] != ' ')
49                 pos--;
50         return pos;
51 }
52
53
54 static u8 * attr_get(u8 *buf, size_t buflen, enum wlantest_ctrl_attr attr,
55                      size_t *len)
56 {
57         u8 *pos = buf;
58
59         while (pos + 8 <= buf + buflen) {
60                 enum wlantest_ctrl_attr a;
61                 size_t alen;
62                 a = WPA_GET_BE32(pos);
63                 pos += 4;
64                 alen = WPA_GET_BE32(pos);
65                 pos += 4;
66                 if (pos + alen > buf + buflen) {
67                         printf("Invalid control message attribute\n");
68                         return NULL;
69                 }
70                 if (a == attr) {
71                         *len = alen;
72                         return pos;
73                 }
74                 pos += alen;
75         }
76
77         return NULL;
78 }
79
80
81 static u8 * attr_hdr_add(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
82                          size_t len)
83 {
84         if (pos == NULL || end - pos < 8 + len)
85                 return NULL;
86         WPA_PUT_BE32(pos, attr);
87         pos += 4;
88         WPA_PUT_BE32(pos, len);
89         pos += 4;
90         return pos;
91 }
92
93
94 static u8 * attr_add_str(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
95                          const char *str)
96 {
97         size_t len = os_strlen(str);
98
99         if (pos == NULL || end - pos < 8 + len)
100                 return NULL;
101         WPA_PUT_BE32(pos, attr);
102         pos += 4;
103         WPA_PUT_BE32(pos, len);
104         pos += 4;
105         os_memcpy(pos, str, len);
106         pos += len;
107         return pos;
108 }
109
110
111 static u8 * attr_add_be32(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
112                           u32 val)
113 {
114         if (pos == NULL || end - pos < 12)
115                 return NULL;
116         WPA_PUT_BE32(pos, attr);
117         pos += 4;
118         WPA_PUT_BE32(pos, 4);
119         pos += 4;
120         WPA_PUT_BE32(pos, val);
121         pos += 4;
122         return pos;
123 }
124
125
126 static int cmd_send_and_recv(int s, const u8 *cmd, size_t cmd_len,
127                              u8 *resp, size_t max_resp_len)
128 {
129         int res;
130         enum wlantest_ctrl_cmd cmd_resp;
131
132         if (send(s, cmd, cmd_len, 0) < 0)
133                 return -1;
134         res = recv(s, resp, max_resp_len, 0);
135         if (res < 4)
136                 return -1;
137
138         cmd_resp = WPA_GET_BE32(resp);
139         if (cmd_resp == WLANTEST_CTRL_SUCCESS)
140                 return res;
141
142         if (cmd_resp == WLANTEST_CTRL_UNKNOWN_CMD)
143                 printf("Unknown command\n");
144         else if (cmd_resp == WLANTEST_CTRL_INVALID_CMD)
145                 printf("Invalid command\n");
146
147         return -1;
148 }
149
150
151 static int cmd_simple(int s, enum wlantest_ctrl_cmd cmd)
152 {
153         u8 buf[4];
154         int res;
155         WPA_PUT_BE32(buf, cmd);
156         res = cmd_send_and_recv(s, buf, sizeof(buf), buf, sizeof(buf));
157         return res < 0 ? -1 : 0;
158 }
159
160
161 static char ** get_bssid_list(int s)
162 {
163         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
164         u8 buf[4];
165         u8 *bssid;
166         size_t len;
167         int rlen, i;
168         char **res;
169
170         WPA_PUT_BE32(buf, WLANTEST_CTRL_LIST_BSS);
171         rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
172         if (rlen < 0)
173                 return NULL;
174
175         bssid = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_BSSID, &len);
176         if (bssid == NULL)
177                 return NULL;
178
179         res = os_zalloc((len / ETH_ALEN + 1) * sizeof(char *));
180         if (res == NULL)
181                 return NULL;
182         for (i = 0; i < len / ETH_ALEN; i++) {
183                 res[i] = os_zalloc(18);
184                 if (res[i] == NULL)
185                         break;
186                 os_snprintf(res[i], 18, MACSTR, MAC2STR(bssid + ETH_ALEN * i));
187         }
188
189         return res;
190 }
191
192
193 static char ** get_sta_list(int s, const u8 *bssid, int add_bcast)
194 {
195         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
196         u8 buf[100], *pos, *end;
197         u8 *addr;
198         size_t len;
199         int rlen, i;
200         char **res;
201
202         pos = buf;
203         end = buf + sizeof(buf);
204         WPA_PUT_BE32(pos, WLANTEST_CTRL_LIST_STA);
205         pos += 4;
206         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
207         os_memcpy(pos, bssid, ETH_ALEN);
208         pos += ETH_ALEN;
209         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
210         if (rlen < 0)
211                 return NULL;
212
213         addr = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_STA_ADDR, &len);
214         if (addr == NULL)
215                 return NULL;
216
217         res = os_zalloc((len / ETH_ALEN + 1 + add_bcast) * sizeof(char *));
218         if (res == NULL)
219                 return NULL;
220         for (i = 0; i < len / ETH_ALEN; i++) {
221                 res[i] = os_zalloc(18);
222                 if (res[i] == NULL)
223                         break;
224                 os_snprintf(res[i], 18, MACSTR, MAC2STR(addr + ETH_ALEN * i));
225         }
226         if (add_bcast)
227                 res[i] = os_strdup("ff:ff:ff:ff:ff:ff");
228
229         return res;
230 }
231
232
233 static int cmd_ping(int s, int argc, char *argv[])
234 {
235         int res = cmd_simple(s, WLANTEST_CTRL_PING);
236         if (res == 0)
237                 printf("PONG\n");
238         return res == 0;
239 }
240
241
242 static int cmd_terminate(int s, int argc, char *argv[])
243 {
244         return cmd_simple(s, WLANTEST_CTRL_TERMINATE);
245 }
246
247
248 static int cmd_list_bss(int s, int argc, char *argv[])
249 {
250         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
251         u8 buf[4];
252         u8 *bssid;
253         size_t len;
254         int rlen, i;
255
256         WPA_PUT_BE32(buf, WLANTEST_CTRL_LIST_BSS);
257         rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
258         if (rlen < 0)
259                 return -1;
260
261         bssid = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_BSSID, &len);
262         if (bssid == NULL)
263                 return -1;
264
265         for (i = 0; i < len / ETH_ALEN; i++)
266                 printf(MACSTR " ", MAC2STR(bssid + ETH_ALEN * i));
267         printf("\n");
268
269         return 0;
270 }
271
272
273 static int cmd_list_sta(int s, int argc, char *argv[])
274 {
275         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
276         u8 buf[100], *pos;
277         u8 *addr;
278         size_t len;
279         int rlen, i;
280
281         if (argc < 1) {
282                 printf("list_sta needs one argument: BSSID\n");
283                 return -1;
284         }
285
286         pos = buf;
287         WPA_PUT_BE32(pos, WLANTEST_CTRL_LIST_STA);
288         pos += 4;
289         WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
290         pos += 4;
291         WPA_PUT_BE32(pos, ETH_ALEN);
292         pos += 4;
293         if (hwaddr_aton(argv[0], pos) < 0) {
294                 printf("Invalid BSSID '%s'\n", argv[0]);
295                 return -1;
296         }
297         pos += ETH_ALEN;
298
299         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
300         if (rlen < 0)
301                 return -1;
302
303         addr = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_STA_ADDR, &len);
304         if (addr == NULL)
305                 return -1;
306
307         for (i = 0; i < len / ETH_ALEN; i++)
308                 printf(MACSTR " ", MAC2STR(addr + ETH_ALEN * i));
309         printf("\n");
310
311         return 0;
312 }
313
314
315 static char ** complete_list_sta(int s, const char *str, int pos)
316 {
317         if (get_cmd_arg_num(str, pos) == 1)
318                 return get_bssid_list(s);
319         return NULL;
320 }
321
322
323 static int cmd_flush(int s, int argc, char *argv[])
324 {
325         return cmd_simple(s, WLANTEST_CTRL_FLUSH);
326 }
327
328
329 static int cmd_clear_sta_counters(int s, int argc, char *argv[])
330 {
331         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
332         u8 buf[100], *pos;
333         int rlen;
334
335         if (argc < 2) {
336                 printf("clear_sta_counters needs two arguments: BSSID and "
337                        "STA address\n");
338                 return -1;
339         }
340
341         pos = buf;
342         WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_STA_COUNTERS);
343         pos += 4;
344         WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
345         pos += 4;
346         WPA_PUT_BE32(pos, ETH_ALEN);
347         pos += 4;
348         if (hwaddr_aton(argv[0], pos) < 0) {
349                 printf("Invalid BSSID '%s'\n", argv[0]);
350                 return -1;
351         }
352         pos += ETH_ALEN;
353
354         WPA_PUT_BE32(pos, WLANTEST_ATTR_STA_ADDR);
355         pos += 4;
356         WPA_PUT_BE32(pos, ETH_ALEN);
357         pos += 4;
358         if (hwaddr_aton(argv[1], pos) < 0) {
359                 printf("Invalid STA address '%s'\n", argv[1]);
360                 return -1;
361         }
362         pos += ETH_ALEN;
363
364         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
365         if (rlen < 0)
366                 return -1;
367         printf("OK\n");
368         return 0;
369 }
370
371
372 static char ** complete_clear_sta_counters(int s, const char *str, int pos)
373 {
374         int arg = get_cmd_arg_num(str, pos);
375         char **res = NULL;
376         u8 addr[ETH_ALEN];
377
378         switch (arg) {
379         case 1:
380                 res = get_bssid_list(s);
381                 break;
382         case 2:
383                 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
384                         break;
385                 res = get_sta_list(s, addr, 0);
386                 break;
387         }
388
389         return res;
390 }
391
392
393 static int cmd_clear_bss_counters(int s, int argc, char *argv[])
394 {
395         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
396         u8 buf[100], *pos;
397         int rlen;
398
399         if (argc < 1) {
400                 printf("clear_bss_counters needs one argument: BSSID\n");
401                 return -1;
402         }
403
404         pos = buf;
405         WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_BSS_COUNTERS);
406         pos += 4;
407         WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
408         pos += 4;
409         WPA_PUT_BE32(pos, ETH_ALEN);
410         pos += 4;
411         if (hwaddr_aton(argv[0], pos) < 0) {
412                 printf("Invalid BSSID '%s'\n", argv[0]);
413                 return -1;
414         }
415         pos += ETH_ALEN;
416
417         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
418         if (rlen < 0)
419                 return -1;
420         printf("OK\n");
421         return 0;
422 }
423
424
425 static char ** complete_clear_bss_counters(int s, const char *str, int pos)
426 {
427         if (get_cmd_arg_num(str, pos) == 1)
428                 return get_bssid_list(s);
429         return NULL;
430 }
431
432
433 static int cmd_clear_tdls_counters(int s, int argc, char *argv[])
434 {
435         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
436         u8 buf[100], *pos;
437         int rlen;
438
439         if (argc < 3) {
440                 printf("clear_tdls_counters needs three arguments: BSSID, "
441                        "STA1 address, STA2 address\n");
442                 return -1;
443         }
444
445         pos = buf;
446         WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_TDLS_COUNTERS);
447         pos += 4;
448         WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
449         pos += 4;
450         WPA_PUT_BE32(pos, ETH_ALEN);
451         pos += 4;
452         if (hwaddr_aton(argv[0], pos) < 0) {
453                 printf("Invalid BSSID '%s'\n", argv[0]);
454                 return -1;
455         }
456         pos += ETH_ALEN;
457
458         WPA_PUT_BE32(pos, WLANTEST_ATTR_STA_ADDR);
459         pos += 4;
460         WPA_PUT_BE32(pos, ETH_ALEN);
461         pos += 4;
462         if (hwaddr_aton(argv[1], pos) < 0) {
463                 printf("Invalid STA1 address '%s'\n", argv[1]);
464                 return -1;
465         }
466         pos += ETH_ALEN;
467
468         WPA_PUT_BE32(pos, WLANTEST_ATTR_STA2_ADDR);
469         pos += 4;
470         WPA_PUT_BE32(pos, ETH_ALEN);
471         pos += 4;
472         if (hwaddr_aton(argv[2], pos) < 0) {
473                 printf("Invalid STA2 address '%s'\n", argv[2]);
474                 return -1;
475         }
476         pos += ETH_ALEN;
477
478         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
479         if (rlen < 0)
480                 return -1;
481         printf("OK\n");
482         return 0;
483 }
484
485
486 static char ** complete_clear_tdls_counters(int s, const char *str, int pos)
487 {
488         int arg = get_cmd_arg_num(str, pos);
489         char **res = NULL;
490         u8 addr[ETH_ALEN];
491
492         switch (arg) {
493         case 1:
494                 res = get_bssid_list(s);
495                 break;
496         case 2:
497         case 3:
498                 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
499                         break;
500                 res = get_sta_list(s, addr, 0);
501                 break;
502         }
503
504         return res;
505 }
506
507
508 struct sta_counters {
509         const char *name;
510         enum wlantest_sta_counter num;
511 };
512
513 static const struct sta_counters sta_counters[] = {
514         { "auth_tx", WLANTEST_STA_COUNTER_AUTH_TX },
515         { "auth_rx", WLANTEST_STA_COUNTER_AUTH_RX },
516         { "assocreq_tx", WLANTEST_STA_COUNTER_ASSOCREQ_TX },
517         { "reassocreq_tx", WLANTEST_STA_COUNTER_REASSOCREQ_TX },
518         { "ptk_learned", WLANTEST_STA_COUNTER_PTK_LEARNED },
519         { "valid_deauth_tx", WLANTEST_STA_COUNTER_VALID_DEAUTH_TX },
520         { "valid_deauth_rx", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX },
521         { "invalid_deauth_tx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX },
522         { "invalid_deauth_rx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX },
523         { "valid_disassoc_tx", WLANTEST_STA_COUNTER_VALID_DISASSOC_TX },
524         { "valid_disassoc_rx", WLANTEST_STA_COUNTER_VALID_DISASSOC_RX },
525         { "invalid_disassoc_tx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX },
526         { "invalid_disassoc_rx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX },
527         { "valid_saqueryreq_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX },
528         { "valid_saqueryreq_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX },
529         { "invalid_saqueryreq_tx",
530           WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX },
531         { "invalid_saqueryreq_rx",
532           WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX },
533         { "valid_saqueryresp_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX },
534         { "valid_saqueryresp_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX },
535         { "invalid_saqueryresp_tx",
536           WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX },
537         { "invalid_saqueryresp_rx",
538           WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX },
539         { "ping_ok", WLANTEST_STA_COUNTER_PING_OK },
540         { "assocresp_comeback", WLANTEST_STA_COUNTER_ASSOCRESP_COMEBACK },
541         { "reassocresp_comeback", WLANTEST_STA_COUNTER_REASSOCRESP_COMEBACK },
542         { "ping_ok_first_assoc", WLANTEST_STA_COUNTER_PING_OK_FIRST_ASSOC },
543         { NULL, 0 }
544 };
545
546 static int cmd_get_sta_counter(int s, int argc, char *argv[])
547 {
548         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
549         u8 buf[100], *end, *pos;
550         int rlen, i;
551         size_t len;
552
553         if (argc != 3) {
554                 printf("get_sta_counter needs at three arguments: "
555                        "counter name, BSSID, and STA address\n");
556                 return -1;
557         }
558
559         pos = buf;
560         end = buf + sizeof(buf);
561         WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_STA_COUNTER);
562         pos += 4;
563
564         for (i = 0; sta_counters[i].name; i++) {
565                 if (os_strcasecmp(sta_counters[i].name, argv[0]) == 0)
566                         break;
567         }
568         if (sta_counters[i].name == NULL) {
569                 printf("Unknown STA counter '%s'\n", argv[0]);
570                 printf("Counters:");
571                 for (i = 0; sta_counters[i].name; i++)
572                         printf(" %s", sta_counters[i].name);
573                 printf("\n");
574                 return -1;
575         }
576
577         pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_COUNTER,
578                             sta_counters[i].num);
579         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
580         if (hwaddr_aton(argv[1], pos) < 0) {
581                 printf("Invalid BSSID '%s'\n", argv[1]);
582                 return -1;
583         }
584         pos += ETH_ALEN;
585
586         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
587         if (hwaddr_aton(argv[2], pos) < 0) {
588                 printf("Invalid STA address '%s'\n", argv[2]);
589                 return -1;
590         }
591         pos += ETH_ALEN;
592
593         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
594         if (rlen < 0)
595                 return -1;
596
597         pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
598         if (pos == NULL || len != 4)
599                 return -1;
600         printf("%u\n", WPA_GET_BE32(pos));
601         return 0;
602 }
603
604
605 static char ** complete_get_sta_counter(int s, const char *str, int pos)
606 {
607         int arg = get_cmd_arg_num(str, pos);
608         char **res = NULL;
609         int i, count;
610         u8 addr[ETH_ALEN];
611
612         switch (arg) {
613         case 1:
614                 /* counter list */
615                 count = sizeof(sta_counters) / sizeof(sta_counters[0]);
616                 res = os_zalloc(count * sizeof(char *));
617                 if (res == NULL)
618                         return NULL;
619                 for (i = 0; sta_counters[i].name; i++) {
620                         res[i] = os_strdup(sta_counters[i].name);
621                         if (res[i] == NULL)
622                                 break;
623                 }
624                 break;
625         case 2:
626                 res = get_bssid_list(s);
627                 break;
628         case 3:
629                 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
630                         break;
631                 res = get_sta_list(s, addr, 0);
632                 break;
633         }
634
635         return res;
636 }
637
638
639 struct bss_counters {
640         const char *name;
641         enum wlantest_bss_counter num;
642 };
643
644 static const struct bss_counters bss_counters[] = {
645         { "valid_bip_mmie", WLANTEST_BSS_COUNTER_VALID_BIP_MMIE },
646         { "invalid_bip_mmie", WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE },
647         { "missing_bip_mmie", WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE },
648         { "bip_deauth", WLANTEST_BSS_COUNTER_BIP_DEAUTH },
649         { "bip_disassoc", WLANTEST_BSS_COUNTER_BIP_DISASSOC },
650         { NULL, 0 }
651 };
652
653 static int cmd_get_bss_counter(int s, int argc, char *argv[])
654 {
655         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
656         u8 buf[100], *end, *pos;
657         int rlen, i;
658         size_t len;
659
660         if (argc != 2) {
661                 printf("get_bss_counter needs at two arguments: "
662                        "counter name and BSSID\n");
663                 return -1;
664         }
665
666         pos = buf;
667         end = buf + sizeof(buf);
668         WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_BSS_COUNTER);
669         pos += 4;
670
671         for (i = 0; bss_counters[i].name; i++) {
672                 if (os_strcasecmp(bss_counters[i].name, argv[0]) == 0)
673                         break;
674         }
675         if (bss_counters[i].name == NULL) {
676                 printf("Unknown BSS counter '%s'\n", argv[0]);
677                 printf("Counters:");
678                 for (i = 0; bss_counters[i].name; i++)
679                         printf(" %s", bss_counters[i].name);
680                 printf("\n");
681                 return -1;
682         }
683
684         pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_COUNTER,
685                             bss_counters[i].num);
686         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
687         if (hwaddr_aton(argv[1], pos) < 0) {
688                 printf("Invalid BSSID '%s'\n", argv[1]);
689                 return -1;
690         }
691         pos += ETH_ALEN;
692
693         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
694         if (rlen < 0)
695                 return -1;
696
697         pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
698         if (pos == NULL || len != 4)
699                 return -1;
700         printf("%u\n", WPA_GET_BE32(pos));
701         return 0;
702 }
703
704
705 static char ** complete_get_bss_counter(int s, const char *str, int pos)
706 {
707         int arg = get_cmd_arg_num(str, pos);
708         char **res = NULL;
709         int i, count;
710
711         switch (arg) {
712         case 1:
713                 /* counter list */
714                 count = sizeof(bss_counters) / sizeof(bss_counters[0]);
715                 res = os_zalloc(count * sizeof(char *));
716                 if (res == NULL)
717                         return NULL;
718                 for (i = 0; bss_counters[i].name; i++) {
719                         res[i] = os_strdup(bss_counters[i].name);
720                         if (res[i] == NULL)
721                                 break;
722                 }
723                 break;
724         case 2:
725                 res = get_bssid_list(s);
726                 break;
727         }
728
729         return res;
730 }
731
732
733 struct tdls_counters {
734         const char *name;
735         enum wlantest_tdls_counter num;
736 };
737
738 static const struct tdls_counters tdls_counters[] = {
739         { "valid_direct_link", WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK },
740         { "invalid_direct_link", WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK },
741         { "valid_ap_path", WLANTEST_TDLS_COUNTER_VALID_AP_PATH },
742         { "invalid_ap_path", WLANTEST_TDLS_COUNTER_INVALID_AP_PATH },
743         { NULL, 0 }
744 };
745
746 static int cmd_get_tdls_counter(int s, int argc, char *argv[])
747 {
748         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
749         u8 buf[100], *end, *pos;
750         int rlen, i;
751         size_t len;
752
753         if (argc != 4) {
754                 printf("get_tdls_counter needs four arguments: "
755                        "counter name, BSSID, STA1 address, STA2 address\n");
756                 return -1;
757         }
758
759         pos = buf;
760         end = buf + sizeof(buf);
761         WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_TDLS_COUNTER);
762         pos += 4;
763
764         for (i = 0; tdls_counters[i].name; i++) {
765                 if (os_strcasecmp(tdls_counters[i].name, argv[0]) == 0)
766                         break;
767         }
768         if (tdls_counters[i].name == NULL) {
769                 printf("Unknown TDLS counter '%s'\n", argv[0]);
770                 printf("Counters:");
771                 for (i = 0; tdls_counters[i].name; i++)
772                         printf(" %s", tdls_counters[i].name);
773                 printf("\n");
774                 return -1;
775         }
776
777         pos = attr_add_be32(pos, end, WLANTEST_ATTR_TDLS_COUNTER,
778                             tdls_counters[i].num);
779         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
780         if (hwaddr_aton(argv[1], pos) < 0) {
781                 printf("Invalid BSSID '%s'\n", argv[1]);
782                 return -1;
783         }
784         pos += ETH_ALEN;
785
786         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
787         if (hwaddr_aton(argv[2], pos) < 0) {
788                 printf("Invalid STA1 address '%s'\n", argv[2]);
789                 return -1;
790         }
791         pos += ETH_ALEN;
792
793         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA2_ADDR, ETH_ALEN);
794         if (hwaddr_aton(argv[3], pos) < 0) {
795                 printf("Invalid STA2 address '%s'\n", argv[3]);
796                 return -1;
797         }
798         pos += ETH_ALEN;
799
800         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
801         if (rlen < 0)
802                 return -1;
803
804         pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
805         if (pos == NULL || len != 4)
806                 return -1;
807         printf("%u\n", WPA_GET_BE32(pos));
808         return 0;
809 }
810
811
812 static char ** complete_get_tdls_counter(int s, const char *str, int pos)
813 {
814         int arg = get_cmd_arg_num(str, pos);
815         char **res = NULL;
816         int i, count;
817         u8 addr[ETH_ALEN];
818
819         switch (arg) {
820         case 1:
821                 /* counter list */
822                 count = sizeof(tdls_counters) / sizeof(tdls_counters[0]);
823                 res = os_zalloc(count * sizeof(char *));
824                 if (res == NULL)
825                         return NULL;
826                 for (i = 0; tdls_counters[i].name; i++) {
827                         res[i] = os_strdup(tdls_counters[i].name);
828                         if (res[i] == NULL)
829                                 break;
830                 }
831                 break;
832         case 2:
833                 res = get_bssid_list(s);
834                 break;
835         case 3:
836         case 4:
837                 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
838                         break;
839                 res = get_sta_list(s, addr, 0);
840                 break;
841         }
842
843         return res;
844 }
845
846
847 struct inject_frames {
848         const char *name;
849         enum wlantest_inject_frame frame;
850 };
851
852 static const struct inject_frames inject_frames[] = {
853         { "auth", WLANTEST_FRAME_AUTH },
854         { "assocreq", WLANTEST_FRAME_ASSOCREQ },
855         { "reassocreq", WLANTEST_FRAME_REASSOCREQ },
856         { "deauth", WLANTEST_FRAME_DEAUTH },
857         { "disassoc", WLANTEST_FRAME_DISASSOC },
858         { "saqueryreq", WLANTEST_FRAME_SAQUERYREQ },
859         { NULL, 0 }
860 };
861
862 static int cmd_inject(int s, int argc, char *argv[])
863 {
864         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
865         u8 buf[100], *end, *pos;
866         int rlen, i;
867         enum wlantest_inject_protection prot;
868
869         /* <frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff> */
870
871         if (argc < 5) {
872                 printf("inject needs five arguments: frame, protection, "
873                        "sender, BSSID, STA/ff:ff:ff:ff:ff:ff\n");
874                 return -1;
875         }
876
877         pos = buf;
878         end = buf + sizeof(buf);
879         WPA_PUT_BE32(pos, WLANTEST_CTRL_INJECT);
880         pos += 4;
881
882         for (i = 0; inject_frames[i].name; i++) {
883                 if (os_strcasecmp(inject_frames[i].name, argv[0]) == 0)
884                         break;
885         }
886         if (inject_frames[i].name == NULL) {
887                 printf("Unknown inject frame '%s'\n", argv[0]);
888                 printf("Frames:");
889                 for (i = 0; inject_frames[i].name; i++)
890                         printf(" %s", inject_frames[i].name);
891                 printf("\n");
892                 return -1;
893         }
894
895         pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_FRAME,
896                             inject_frames[i].frame);
897
898         if (os_strcasecmp(argv[1], "normal") == 0)
899                 prot = WLANTEST_INJECT_NORMAL;
900         else if (os_strcasecmp(argv[1], "protected") == 0)
901                 prot = WLANTEST_INJECT_PROTECTED;
902         else if (os_strcasecmp(argv[1], "unprotected") == 0)
903                 prot = WLANTEST_INJECT_UNPROTECTED;
904         else if (os_strcasecmp(argv[1], "incorrect") == 0)
905                 prot = WLANTEST_INJECT_INCORRECT_KEY;
906         else {
907                 printf("Unknown protection type '%s'\n", argv[1]);
908                 printf("Protection types: normal protected unprotected "
909                        "incorrect\n");
910                 return -1;
911         }
912         pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot);
913
914         if (os_strcasecmp(argv[2], "ap") == 0) {
915                 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
916                                     1);
917         } else if (os_strcasecmp(argv[2], "sta") == 0) {
918                 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
919                                     0);
920         } else {
921                 printf("Unknown sender '%s'\n", argv[2]);
922                 printf("Sender types: ap sta\n");
923                 return -1;
924         }
925
926         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
927         if (hwaddr_aton(argv[3], pos) < 0) {
928                 printf("Invalid BSSID '%s'\n", argv[3]);
929                 return -1;
930         }
931         pos += ETH_ALEN;
932
933         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
934         if (hwaddr_aton(argv[4], pos) < 0) {
935                 printf("Invalid STA '%s'\n", argv[4]);
936                 return -1;
937         }
938         pos += ETH_ALEN;
939
940         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
941         if (rlen < 0)
942                 return -1;
943         printf("OK\n");
944         return 0;
945 }
946
947
948 static char ** complete_inject(int s, const char *str, int pos)
949 {
950         int arg = get_cmd_arg_num(str, pos);
951         char **res = NULL;
952         int i, count;
953         u8 addr[ETH_ALEN];
954
955         switch (arg) {
956         case 1:
957                 /* frame list */
958                 count = sizeof(inject_frames) / sizeof(inject_frames[0]);
959                 res = os_zalloc(count * sizeof(char *));
960                 if (res == NULL)
961                         break;
962                 for (i = 0; inject_frames[i].name; i++) {
963                         res[i] = os_strdup(inject_frames[i].name);
964                         if (res[i] == NULL)
965                                 break;
966                 }
967                 break;
968         case 2:
969                 res = os_zalloc(5 * sizeof(char *));
970                 if (res == NULL)
971                         break;
972                 res[0] = os_strdup("normal");
973                 if (res[0] == NULL)
974                         break;
975                 res[1] = os_strdup("protected");
976                 if (res[1] == NULL)
977                         break;
978                 res[2] = os_strdup("unprotected");
979                 if (res[2] == NULL)
980                         break;
981                 res[3] = os_strdup("incorrect");
982                 if (res[3] == NULL)
983                         break;
984                 break;
985         case 3:
986                 res = os_zalloc(3 * sizeof(char *));
987                 if (res == NULL)
988                         break;
989                 res[0] = os_strdup("ap");
990                 if (res[0] == NULL)
991                         break;
992                 res[1] = os_strdup("sta");
993                 if (res[1] == NULL)
994                         break;
995                 break;
996         case 4:
997                 res = get_bssid_list(s);
998                 break;
999         case 5:
1000                 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
1001                         break;
1002                 res = get_sta_list(s, addr, 1);
1003                 break;
1004         }
1005
1006         return res;
1007 }
1008
1009
1010 static u8 * add_hex(u8 *pos, u8 *end, const char *str)
1011 {
1012         const char *s;
1013         int val;
1014
1015         s = str;
1016         while (*s) {
1017                 while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n' ||
1018                        *s == ':')
1019                         s++;
1020                 if (*s == '\0')
1021                         break;
1022                 if (*s == '#') {
1023                         while (*s != '\0' && *s != '\r' && *s != '\n')
1024                                 s++;
1025                         continue;
1026                 }
1027
1028                 val = hex2byte(s);
1029                 if (val < 0) {
1030                         printf("Invalid hex encoding '%s'\n", s);
1031                         return NULL;
1032                 }
1033                 if (pos == end) {
1034                         printf("Too long frame\n");
1035                         return NULL;
1036                 }
1037                 *pos++ = val;
1038                 s += 2;
1039         }
1040
1041         return pos;
1042 }
1043
1044
1045 static int cmd_send(int s, int argc, char *argv[])
1046 {
1047         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1048         u8 buf[WLANTEST_CTRL_MAX_CMD_LEN], *end, *pos, *len_pos;
1049         int rlen;
1050         enum wlantest_inject_protection prot;
1051         int arg;
1052
1053         /* <prot> <raw frame as hex dump> */
1054
1055         if (argc < 2) {
1056                 printf("send needs two arguments: protected/unprotected, "
1057                        "raw frame as hex dump\n");
1058                 return -1;
1059         }
1060
1061         pos = buf;
1062         end = buf + sizeof(buf);
1063         WPA_PUT_BE32(pos, WLANTEST_CTRL_SEND);
1064         pos += 4;
1065
1066         if (os_strcasecmp(argv[0], "normal") == 0)
1067                 prot = WLANTEST_INJECT_NORMAL;
1068         else if (os_strcasecmp(argv[0], "protected") == 0)
1069                 prot = WLANTEST_INJECT_PROTECTED;
1070         else if (os_strcasecmp(argv[0], "unprotected") == 0)
1071                 prot = WLANTEST_INJECT_UNPROTECTED;
1072         else if (os_strcasecmp(argv[0], "incorrect") == 0)
1073                 prot = WLANTEST_INJECT_INCORRECT_KEY;
1074         else {
1075                 printf("Unknown protection type '%s'\n", argv[1]);
1076                 printf("Protection types: normal protected unprotected "
1077                        "incorrect\n");
1078                 return -1;
1079         }
1080         pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot);
1081
1082         WPA_PUT_BE32(pos, WLANTEST_ATTR_FRAME);
1083         pos += 4;
1084         len_pos = pos;
1085         pos += 4;
1086
1087         for (arg = 1; pos && arg < argc; arg++)
1088                 pos = add_hex(pos, end, argv[arg]);
1089         if (pos == NULL)
1090                 return -1;
1091
1092         WPA_PUT_BE32(len_pos, pos - len_pos - 4);
1093
1094         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1095         if (rlen < 0)
1096                 return -1;
1097         printf("OK\n");
1098         return 0;
1099 }
1100
1101
1102 static char ** complete_send(int s, const char *str, int pos)
1103 {
1104         int arg = get_cmd_arg_num(str, pos);
1105         char **res = NULL;
1106
1107         switch (arg) {
1108         case 1:
1109                 res = os_zalloc(5 * sizeof(char *));
1110                 if (res == NULL)
1111                         break;
1112                 res[0] = os_strdup("normal");
1113                 if (res[0] == NULL)
1114                         break;
1115                 res[1] = os_strdup("protected");
1116                 if (res[1] == NULL)
1117                         break;
1118                 res[2] = os_strdup("unprotected");
1119                 if (res[2] == NULL)
1120                         break;
1121                 res[3] = os_strdup("incorrect");
1122                 if (res[3] == NULL)
1123                         break;
1124                 break;
1125         }
1126
1127         return res;
1128 }
1129
1130
1131 static int cmd_version(int s, int argc, char *argv[])
1132 {
1133         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1134         u8 buf[4];
1135         char *version;
1136         size_t len;
1137         int rlen, i;
1138
1139         WPA_PUT_BE32(buf, WLANTEST_CTRL_VERSION);
1140         rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
1141         if (rlen < 0)
1142                 return -1;
1143
1144         version = (char *) attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_VERSION,
1145                                     &len);
1146         if (version == NULL)
1147                 return -1;
1148
1149         for (i = 0; i < len; i++)
1150                 putchar(version[i]);
1151         printf("\n");
1152
1153         return 0;
1154 }
1155
1156
1157 static int cmd_add_passphrase(int s, int argc, char *argv[])
1158 {
1159         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1160         u8 buf[100], *pos, *end;
1161         size_t len;
1162         int rlen;
1163
1164         if (argc < 1) {
1165                 printf("add_passphrase needs one argument: passphrase\n");
1166                 return -1;
1167         }
1168
1169         len = os_strlen(argv[0]);
1170         if (len < 8 || len > 63) {
1171                 printf("Invalid passphrase '%s'\n", argv[0]);
1172                 return -1;
1173         }
1174         pos = buf;
1175         end = buf + sizeof(buf);
1176         WPA_PUT_BE32(pos, WLANTEST_CTRL_ADD_PASSPHRASE);
1177         pos += 4;
1178         pos = attr_add_str(pos, end, WLANTEST_ATTR_PASSPHRASE,
1179                            argv[0]);
1180         if (argc > 1) {
1181                 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1182                 if (hwaddr_aton(argv[1], pos) < 0) {
1183                         printf("Invalid BSSID '%s'\n", argv[3]);
1184                         return -1;
1185                 }
1186                 pos += ETH_ALEN;
1187         }
1188
1189         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1190         if (rlen < 0)
1191                 return -1;
1192         return 0;
1193 }
1194
1195
1196 struct sta_infos {
1197         const char *name;
1198         enum wlantest_sta_info num;
1199 };
1200
1201 static const struct sta_infos sta_infos[] = {
1202         { "proto", WLANTEST_STA_INFO_PROTO },
1203         { "pairwise", WLANTEST_STA_INFO_PAIRWISE },
1204         { "key_mgmt", WLANTEST_STA_INFO_KEY_MGMT },
1205         { "rsn_capab", WLANTEST_STA_INFO_RSN_CAPAB },
1206         { "state", WLANTEST_STA_INFO_STATE },
1207         { NULL, 0 }
1208 };
1209
1210 static int cmd_info_sta(int s, int argc, char *argv[])
1211 {
1212         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1213         u8 buf[100], *end, *pos;
1214         int rlen, i;
1215         size_t len;
1216         char info[100];
1217
1218         if (argc != 3) {
1219                 printf("sta_info needs at three arguments: "
1220                        "counter name, BSSID, and STA address\n");
1221                 return -1;
1222         }
1223
1224         pos = buf;
1225         end = buf + sizeof(buf);
1226         WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_STA);
1227         pos += 4;
1228
1229         for (i = 0; sta_infos[i].name; i++) {
1230                 if (os_strcasecmp(sta_infos[i].name, argv[0]) == 0)
1231                         break;
1232         }
1233         if (sta_infos[i].name == NULL) {
1234                 printf("Unknown STA info '%s'\n", argv[0]);
1235                 printf("Info fields:");
1236                 for (i = 0; sta_infos[i].name; i++)
1237                         printf(" %s", sta_infos[i].name);
1238                 printf("\n");
1239                 return -1;
1240         }
1241
1242         pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_INFO,
1243                             sta_infos[i].num);
1244         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1245         if (hwaddr_aton(argv[1], pos) < 0) {
1246                 printf("Invalid BSSID '%s'\n", argv[1]);
1247                 return -1;
1248         }
1249         pos += ETH_ALEN;
1250
1251         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
1252         if (hwaddr_aton(argv[2], pos) < 0) {
1253                 printf("Invalid STA address '%s'\n", argv[2]);
1254                 return -1;
1255         }
1256         pos += ETH_ALEN;
1257
1258         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1259         if (rlen < 0)
1260                 return -1;
1261
1262         pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len);
1263         if (pos == NULL)
1264                 return -1;
1265         if (len >= sizeof(info))
1266                 len = sizeof(info) - 1;
1267         os_memcpy(info, pos, len);
1268         info[len] = '\0';
1269         printf("%s\n", info);
1270         return 0;
1271 }
1272
1273
1274 static char ** complete_info_sta(int s, const char *str, int pos)
1275 {
1276         int arg = get_cmd_arg_num(str, pos);
1277         char **res = NULL;
1278         int i, count;
1279         u8 addr[ETH_ALEN];
1280
1281         switch (arg) {
1282         case 1:
1283                 /* counter list */
1284                 count = sizeof(sta_infos) / sizeof(sta_infos[0]);
1285                 res = os_zalloc(count * sizeof(char *));
1286                 if (res == NULL)
1287                         return NULL;
1288                 for (i = 0; sta_infos[i].name; i++) {
1289                         res[i] = os_strdup(sta_infos[i].name);
1290                         if (res[i] == NULL)
1291                                 break;
1292                 }
1293                 break;
1294         case 2:
1295                 res = get_bssid_list(s);
1296                 break;
1297         case 3:
1298                 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
1299                         break;
1300                 res = get_sta_list(s, addr, 0);
1301                 break;
1302         }
1303
1304         return res;
1305 }
1306
1307
1308 struct bss_infos {
1309         const char *name;
1310         enum wlantest_bss_info num;
1311 };
1312
1313 static const struct bss_infos bss_infos[] = {
1314         { "proto", WLANTEST_BSS_INFO_PROTO },
1315         { "pairwise", WLANTEST_BSS_INFO_PAIRWISE },
1316         { "group", WLANTEST_BSS_INFO_GROUP },
1317         { "group_mgmt", WLANTEST_BSS_INFO_GROUP_MGMT },
1318         { "key_mgmt", WLANTEST_BSS_INFO_KEY_MGMT },
1319         { "rsn_capab", WLANTEST_BSS_INFO_RSN_CAPAB },
1320         { NULL, 0 }
1321 };
1322
1323 static int cmd_info_bss(int s, int argc, char *argv[])
1324 {
1325         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1326         u8 buf[100], *end, *pos;
1327         int rlen, i;
1328         size_t len;
1329         char info[100];
1330
1331         if (argc != 2) {
1332                 printf("bss_info needs at two arguments: "
1333                        "field name and BSSID\n");
1334                 return -1;
1335         }
1336
1337         pos = buf;
1338         end = buf + sizeof(buf);
1339         WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_BSS);
1340         pos += 4;
1341
1342         for (i = 0; bss_infos[i].name; i++) {
1343                 if (os_strcasecmp(bss_infos[i].name, argv[0]) == 0)
1344                         break;
1345         }
1346         if (bss_infos[i].name == NULL) {
1347                 printf("Unknown BSS info '%s'\n", argv[0]);
1348                 printf("Info fields:");
1349                 for (i = 0; bss_infos[i].name; i++)
1350                         printf(" %s", bss_infos[i].name);
1351                 printf("\n");
1352                 return -1;
1353         }
1354
1355         pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_INFO,
1356                             bss_infos[i].num);
1357         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1358         if (hwaddr_aton(argv[1], pos) < 0) {
1359                 printf("Invalid BSSID '%s'\n", argv[1]);
1360                 return -1;
1361         }
1362         pos += ETH_ALEN;
1363
1364         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1365         if (rlen < 0)
1366                 return -1;
1367
1368         pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len);
1369         if (pos == NULL)
1370                 return -1;
1371         if (len >= sizeof(info))
1372                 len = sizeof(info) - 1;
1373         os_memcpy(info, pos, len);
1374         info[len] = '\0';
1375         printf("%s\n", info);
1376         return 0;
1377 }
1378
1379
1380 static char ** complete_info_bss(int s, const char *str, int pos)
1381 {
1382         int arg = get_cmd_arg_num(str, pos);
1383         char **res = NULL;
1384         int i, count;
1385
1386         switch (arg) {
1387         case 1:
1388                 /* counter list */
1389                 count = sizeof(bss_infos) / sizeof(bss_infos[0]);
1390                 res = os_zalloc(count * sizeof(char *));
1391                 if (res == NULL)
1392                         return NULL;
1393                 for (i = 0; bss_infos[i].name; i++) {
1394                         res[i] = os_strdup(bss_infos[i].name);
1395                         if (res[i] == NULL)
1396                                 break;
1397                 }
1398                 break;
1399         case 2:
1400                 res = get_bssid_list(s);
1401                 break;
1402         }
1403
1404         return res;
1405 }
1406
1407
1408 struct wlantest_cli_cmd {
1409         const char *cmd;
1410         int (*handler)(int s, int argc, char *argv[]);
1411         const char *usage;
1412         char ** (*complete)(int s, const char *str, int pos);
1413 };
1414
1415 static const struct wlantest_cli_cmd wlantest_cli_commands[] = {
1416         { "ping", cmd_ping, "= test connection to wlantest", NULL },
1417         { "terminate", cmd_terminate, "= terminate wlantest", NULL },
1418         { "list_bss", cmd_list_bss, "= get BSS list", NULL },
1419         { "list_sta", cmd_list_sta, "<BSSID> = get STA list",
1420           complete_list_sta },
1421         { "flush", cmd_flush, "= drop all collected BSS data", NULL },
1422         { "clear_sta_counters", cmd_clear_sta_counters,
1423           "<BSSID> <STA> = clear STA counters", complete_clear_sta_counters },
1424         { "clear_bss_counters", cmd_clear_bss_counters,
1425           "<BSSID> = clear BSS counters", complete_clear_bss_counters },
1426         { "get_sta_counter", cmd_get_sta_counter,
1427           "<counter> <BSSID> <STA> = get STA counter value",
1428           complete_get_sta_counter },
1429         { "get_bss_counter", cmd_get_bss_counter,
1430           "<counter> <BSSID> = get BSS counter value",
1431           complete_get_bss_counter },
1432         { "inject", cmd_inject,
1433           "<frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff>",
1434           complete_inject },
1435         { "send", cmd_send,
1436           "<prot> <raw frame as hex dump>",
1437           complete_send },
1438         { "version", cmd_version, "= get wlantest version", NULL },
1439         { "add_passphrase", cmd_add_passphrase,
1440           "<passphrase> = add a known passphrase", NULL },
1441         { "info_sta", cmd_info_sta,
1442           "<field> <BSSID> <STA> = get STA information",
1443           complete_info_sta },
1444         { "info_bss", cmd_info_bss,
1445           "<field> <BSSID> = get BSS information",
1446           complete_info_bss },
1447         { "clear_tdls_counters", cmd_clear_tdls_counters,
1448           "<BSSID> <STA1> <STA2> = clear TDLS counters",
1449           complete_clear_tdls_counters },
1450         { "get_tdls_counter", cmd_get_tdls_counter,
1451           "<counter> <BSSID> <STA1> <STA2> = get TDLS counter value",
1452           complete_get_tdls_counter },
1453         { "get_bss_counter", cmd_get_bss_counter,
1454           "<counter> <BSSID> = get BSS counter value",
1455           complete_get_bss_counter },
1456         { NULL, NULL, NULL, NULL }
1457 };
1458
1459
1460 static int ctrl_command(int s, int argc, char *argv[])
1461 {
1462         const struct wlantest_cli_cmd *cmd, *match = NULL;
1463         int count = 0;
1464         int ret = 0;
1465
1466         for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) {
1467                 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1468                 {
1469                         match = cmd;
1470                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1471                                 /* exact match */
1472                                 count = 1;
1473                                 break;
1474                         }
1475                         count++;
1476                 }
1477         }
1478
1479         if (count > 1) {
1480                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1481                 for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) {
1482                         if (os_strncasecmp(cmd->cmd, argv[0],
1483                                            os_strlen(argv[0])) == 0) {
1484                                 printf(" %s", cmd->cmd);
1485                         }
1486                 }
1487                 printf("\n");
1488                 ret = 1;
1489         } else if (count == 0) {
1490                 printf("Unknown command '%s'\n", argv[0]);
1491                 ret = 1;
1492         } else {
1493                 ret = match->handler(s, argc - 1, &argv[1]);
1494         }
1495
1496         return ret;
1497 }
1498
1499
1500 struct wlantest_cli {
1501         int s;
1502 };
1503
1504
1505 #define max_args 10
1506
1507 static int tokenize_cmd(char *cmd, char *argv[])
1508 {
1509         char *pos;
1510         int argc = 0;
1511
1512         pos = cmd;
1513         for (;;) {
1514                 while (*pos == ' ')
1515                         pos++;
1516                 if (*pos == '\0')
1517                         break;
1518                 argv[argc] = pos;
1519                 argc++;
1520                 if (argc == max_args)
1521                         break;
1522                 if (*pos == '"') {
1523                         char *pos2 = os_strrchr(pos, '"');
1524                         if (pos2)
1525                                 pos = pos2 + 1;
1526                 }
1527                 while (*pos != '\0' && *pos != ' ')
1528                         pos++;
1529                 if (*pos == ' ')
1530                         *pos++ = '\0';
1531         }
1532
1533         return argc;
1534 }
1535
1536
1537 static void wlantest_cli_edit_cmd_cb(void *ctx, char *cmd)
1538 {
1539         struct wlantest_cli *cli = ctx;
1540         char *argv[max_args];
1541         int argc;
1542         argc = tokenize_cmd(cmd, argv);
1543         if (argc) {
1544                 int ret = ctrl_command(cli->s, argc, argv);
1545                 if (ret < 0)
1546                         printf("FAIL\n");
1547         }
1548 }
1549
1550
1551 static void wlantest_cli_eloop_terminate(int sig, void *signal_ctx)
1552 {
1553         eloop_terminate();
1554 }
1555
1556
1557 static void wlantest_cli_edit_eof_cb(void *ctx)
1558 {
1559         eloop_terminate();
1560 }
1561
1562
1563 static char ** wlantest_cli_cmd_list(void)
1564 {
1565         char **res;
1566         int i, count;
1567
1568         count = sizeof(wlantest_cli_commands) /
1569                 sizeof(wlantest_cli_commands[0]);
1570         res = os_zalloc(count * sizeof(char *));
1571         if (res == NULL)
1572                 return NULL;
1573
1574         for (i = 0; wlantest_cli_commands[i].cmd; i++) {
1575                 res[i] = os_strdup(wlantest_cli_commands[i].cmd);
1576                 if (res[i] == NULL)
1577                         break;
1578         }
1579
1580         return res;
1581 }
1582
1583
1584 static char ** wlantest_cli_cmd_completion(struct wlantest_cli *cli,
1585                                            const char *cmd, const char *str,
1586                                            int pos)
1587 {
1588         int i;
1589
1590         for (i = 0; wlantest_cli_commands[i].cmd; i++) {
1591                 const struct wlantest_cli_cmd *c = &wlantest_cli_commands[i];
1592                 if (os_strcasecmp(c->cmd, cmd) == 0) {
1593                         edit_clear_line();
1594                         printf("\r%s\n", c->usage);
1595                         edit_redraw();
1596                         if (c->complete)
1597                                 return c->complete(cli->s, str, pos);
1598                         break;
1599                 }
1600         }
1601
1602         return NULL;
1603 }
1604
1605
1606 static char ** wlantest_cli_edit_completion_cb(void *ctx, const char *str,
1607                                                int pos)
1608 {
1609         struct wlantest_cli *cli = ctx;
1610         char **res;
1611         const char *end;
1612         char *cmd;
1613
1614         end = os_strchr(str, ' ');
1615         if (end == NULL || str + pos < end)
1616                 return wlantest_cli_cmd_list();
1617
1618         cmd = os_malloc(pos + 1);
1619         if (cmd == NULL)
1620                 return NULL;
1621         os_memcpy(cmd, str, pos);
1622         cmd[end - str] = '\0';
1623         res = wlantest_cli_cmd_completion(cli, cmd, str, pos);
1624         os_free(cmd);
1625         return res;
1626 }
1627
1628
1629 static void wlantest_cli_interactive(int s)
1630 {
1631         struct wlantest_cli cli;
1632         char *home, *hfile = NULL;
1633
1634         if (eloop_init())
1635                 return;
1636
1637         home = getenv("HOME");
1638         if (home) {
1639                 const char *fname = ".wlantest_cli_history";
1640                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1641                 hfile = os_malloc(hfile_len);
1642                 if (hfile)
1643                         os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
1644         }
1645
1646         cli.s = s;
1647         eloop_register_signal_terminate(wlantest_cli_eloop_terminate, &cli);
1648         edit_init(wlantest_cli_edit_cmd_cb, wlantest_cli_edit_eof_cb,
1649                   wlantest_cli_edit_completion_cb, &cli, hfile);
1650
1651         eloop_run();
1652
1653         edit_deinit(hfile, NULL);
1654         os_free(hfile);
1655         eloop_destroy();
1656 }
1657
1658
1659 int main(int argc, char *argv[])
1660 {
1661         int s;
1662         struct sockaddr_un addr;
1663         int ret = 0;
1664
1665         if (os_program_init())
1666                 return -1;
1667
1668         s = socket(AF_UNIX, SOCK_SEQPACKET, 0);
1669         if (s < 0) {
1670                 perror("socket");
1671                 return -1;
1672         }
1673
1674         os_memset(&addr, 0, sizeof(addr));
1675         addr.sun_family = AF_UNIX;
1676         os_strlcpy(addr.sun_path + 1, WLANTEST_SOCK_NAME,
1677                    sizeof(addr.sun_path) - 1);
1678         if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1679                 perror("connect");
1680                 close(s);
1681                 return -1;
1682         }
1683
1684         if (argc > 1) {
1685                 ret = ctrl_command(s, argc - 1, &argv[1]);
1686                 if (ret < 0)
1687                         printf("FAIL\n");
1688         } else {
1689                 wlantest_cli_interactive(s);
1690         }
1691
1692         close(s);
1693
1694         os_program_deinit();
1695
1696         return ret;
1697 }