wlantest: Add TDLS entry on TDLS Setup Request
[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         { "valid_deauth_rx_ack", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX_ACK },
544         { "valid_disassoc_rx_ack",
545           WLANTEST_STA_COUNTER_VALID_DISASSOC_RX_ACK },
546         { "invalid_deauth_rx_ack",
547           WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX_ACK },
548         { "invalid_disassoc_rx_ack",
549           WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX_ACK },
550         { "deauth_rx_asleep", WLANTEST_STA_COUNTER_DEAUTH_RX_ASLEEP },
551         { "deauth_rx_awake", WLANTEST_STA_COUNTER_DEAUTH_RX_AWAKE },
552         { "disassoc_rx_asleep", WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP },
553         { "disassoc_rx_awake", WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE },
554         { "prot_data_tx", WLANTEST_STA_COUNTER_PROT_DATA_TX },
555         { NULL, 0 }
556 };
557
558 static int cmd_get_sta_counter(int s, int argc, char *argv[])
559 {
560         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
561         u8 buf[100], *end, *pos;
562         int rlen, i;
563         size_t len;
564
565         if (argc != 3) {
566                 printf("get_sta_counter needs at three arguments: "
567                        "counter name, BSSID, and STA address\n");
568                 return -1;
569         }
570
571         pos = buf;
572         end = buf + sizeof(buf);
573         WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_STA_COUNTER);
574         pos += 4;
575
576         for (i = 0; sta_counters[i].name; i++) {
577                 if (os_strcasecmp(sta_counters[i].name, argv[0]) == 0)
578                         break;
579         }
580         if (sta_counters[i].name == NULL) {
581                 printf("Unknown STA counter '%s'\n", argv[0]);
582                 printf("Counters:");
583                 for (i = 0; sta_counters[i].name; i++)
584                         printf(" %s", sta_counters[i].name);
585                 printf("\n");
586                 return -1;
587         }
588
589         pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_COUNTER,
590                             sta_counters[i].num);
591         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
592         if (hwaddr_aton(argv[1], pos) < 0) {
593                 printf("Invalid BSSID '%s'\n", argv[1]);
594                 return -1;
595         }
596         pos += ETH_ALEN;
597
598         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
599         if (hwaddr_aton(argv[2], pos) < 0) {
600                 printf("Invalid STA address '%s'\n", argv[2]);
601                 return -1;
602         }
603         pos += ETH_ALEN;
604
605         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
606         if (rlen < 0)
607                 return -1;
608
609         pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
610         if (pos == NULL || len != 4)
611                 return -1;
612         printf("%u\n", WPA_GET_BE32(pos));
613         return 0;
614 }
615
616
617 static char ** complete_get_sta_counter(int s, const char *str, int pos)
618 {
619         int arg = get_cmd_arg_num(str, pos);
620         char **res = NULL;
621         int i, count;
622         u8 addr[ETH_ALEN];
623
624         switch (arg) {
625         case 1:
626                 /* counter list */
627                 count = sizeof(sta_counters) / sizeof(sta_counters[0]);
628                 res = os_zalloc(count * sizeof(char *));
629                 if (res == NULL)
630                         return NULL;
631                 for (i = 0; sta_counters[i].name; i++) {
632                         res[i] = os_strdup(sta_counters[i].name);
633                         if (res[i] == NULL)
634                                 break;
635                 }
636                 break;
637         case 2:
638                 res = get_bssid_list(s);
639                 break;
640         case 3:
641                 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
642                         break;
643                 res = get_sta_list(s, addr, 0);
644                 break;
645         }
646
647         return res;
648 }
649
650
651 struct bss_counters {
652         const char *name;
653         enum wlantest_bss_counter num;
654 };
655
656 static const struct bss_counters bss_counters[] = {
657         { "valid_bip_mmie", WLANTEST_BSS_COUNTER_VALID_BIP_MMIE },
658         { "invalid_bip_mmie", WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE },
659         { "missing_bip_mmie", WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE },
660         { "bip_deauth", WLANTEST_BSS_COUNTER_BIP_DEAUTH },
661         { "bip_disassoc", WLANTEST_BSS_COUNTER_BIP_DISASSOC },
662         { NULL, 0 }
663 };
664
665 static int cmd_get_bss_counter(int s, int argc, char *argv[])
666 {
667         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
668         u8 buf[100], *end, *pos;
669         int rlen, i;
670         size_t len;
671
672         if (argc != 2) {
673                 printf("get_bss_counter needs at two arguments: "
674                        "counter name and BSSID\n");
675                 return -1;
676         }
677
678         pos = buf;
679         end = buf + sizeof(buf);
680         WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_BSS_COUNTER);
681         pos += 4;
682
683         for (i = 0; bss_counters[i].name; i++) {
684                 if (os_strcasecmp(bss_counters[i].name, argv[0]) == 0)
685                         break;
686         }
687         if (bss_counters[i].name == NULL) {
688                 printf("Unknown BSS counter '%s'\n", argv[0]);
689                 printf("Counters:");
690                 for (i = 0; bss_counters[i].name; i++)
691                         printf(" %s", bss_counters[i].name);
692                 printf("\n");
693                 return -1;
694         }
695
696         pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_COUNTER,
697                             bss_counters[i].num);
698         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
699         if (hwaddr_aton(argv[1], pos) < 0) {
700                 printf("Invalid BSSID '%s'\n", argv[1]);
701                 return -1;
702         }
703         pos += ETH_ALEN;
704
705         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
706         if (rlen < 0)
707                 return -1;
708
709         pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
710         if (pos == NULL || len != 4)
711                 return -1;
712         printf("%u\n", WPA_GET_BE32(pos));
713         return 0;
714 }
715
716
717 static char ** complete_get_bss_counter(int s, const char *str, int pos)
718 {
719         int arg = get_cmd_arg_num(str, pos);
720         char **res = NULL;
721         int i, count;
722
723         switch (arg) {
724         case 1:
725                 /* counter list */
726                 count = sizeof(bss_counters) / sizeof(bss_counters[0]);
727                 res = os_zalloc(count * sizeof(char *));
728                 if (res == NULL)
729                         return NULL;
730                 for (i = 0; bss_counters[i].name; i++) {
731                         res[i] = os_strdup(bss_counters[i].name);
732                         if (res[i] == NULL)
733                                 break;
734                 }
735                 break;
736         case 2:
737                 res = get_bssid_list(s);
738                 break;
739         }
740
741         return res;
742 }
743
744
745 struct tdls_counters {
746         const char *name;
747         enum wlantest_tdls_counter num;
748 };
749
750 static const struct tdls_counters tdls_counters[] = {
751         { "valid_direct_link", WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK },
752         { "invalid_direct_link", WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK },
753         { "valid_ap_path", WLANTEST_TDLS_COUNTER_VALID_AP_PATH },
754         { "invalid_ap_path", WLANTEST_TDLS_COUNTER_INVALID_AP_PATH },
755         { NULL, 0 }
756 };
757
758 static int cmd_get_tdls_counter(int s, int argc, char *argv[])
759 {
760         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
761         u8 buf[100], *end, *pos;
762         int rlen, i;
763         size_t len;
764
765         if (argc != 4) {
766                 printf("get_tdls_counter needs four arguments: "
767                        "counter name, BSSID, STA1 address, STA2 address\n");
768                 return -1;
769         }
770
771         pos = buf;
772         end = buf + sizeof(buf);
773         WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_TDLS_COUNTER);
774         pos += 4;
775
776         for (i = 0; tdls_counters[i].name; i++) {
777                 if (os_strcasecmp(tdls_counters[i].name, argv[0]) == 0)
778                         break;
779         }
780         if (tdls_counters[i].name == NULL) {
781                 printf("Unknown TDLS counter '%s'\n", argv[0]);
782                 printf("Counters:");
783                 for (i = 0; tdls_counters[i].name; i++)
784                         printf(" %s", tdls_counters[i].name);
785                 printf("\n");
786                 return -1;
787         }
788
789         pos = attr_add_be32(pos, end, WLANTEST_ATTR_TDLS_COUNTER,
790                             tdls_counters[i].num);
791         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
792         if (hwaddr_aton(argv[1], pos) < 0) {
793                 printf("Invalid BSSID '%s'\n", argv[1]);
794                 return -1;
795         }
796         pos += ETH_ALEN;
797
798         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
799         if (hwaddr_aton(argv[2], pos) < 0) {
800                 printf("Invalid STA1 address '%s'\n", argv[2]);
801                 return -1;
802         }
803         pos += ETH_ALEN;
804
805         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA2_ADDR, ETH_ALEN);
806         if (hwaddr_aton(argv[3], pos) < 0) {
807                 printf("Invalid STA2 address '%s'\n", argv[3]);
808                 return -1;
809         }
810         pos += ETH_ALEN;
811
812         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
813         if (rlen < 0)
814                 return -1;
815
816         pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
817         if (pos == NULL || len != 4)
818                 return -1;
819         printf("%u\n", WPA_GET_BE32(pos));
820         return 0;
821 }
822
823
824 static char ** complete_get_tdls_counter(int s, const char *str, int pos)
825 {
826         int arg = get_cmd_arg_num(str, pos);
827         char **res = NULL;
828         int i, count;
829         u8 addr[ETH_ALEN];
830
831         switch (arg) {
832         case 1:
833                 /* counter list */
834                 count = sizeof(tdls_counters) / sizeof(tdls_counters[0]);
835                 res = os_zalloc(count * sizeof(char *));
836                 if (res == NULL)
837                         return NULL;
838                 for (i = 0; tdls_counters[i].name; i++) {
839                         res[i] = os_strdup(tdls_counters[i].name);
840                         if (res[i] == NULL)
841                                 break;
842                 }
843                 break;
844         case 2:
845                 res = get_bssid_list(s);
846                 break;
847         case 3:
848         case 4:
849                 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
850                         break;
851                 res = get_sta_list(s, addr, 0);
852                 break;
853         }
854
855         return res;
856 }
857
858
859 struct inject_frames {
860         const char *name;
861         enum wlantest_inject_frame frame;
862 };
863
864 static const struct inject_frames inject_frames[] = {
865         { "auth", WLANTEST_FRAME_AUTH },
866         { "assocreq", WLANTEST_FRAME_ASSOCREQ },
867         { "reassocreq", WLANTEST_FRAME_REASSOCREQ },
868         { "deauth", WLANTEST_FRAME_DEAUTH },
869         { "disassoc", WLANTEST_FRAME_DISASSOC },
870         { "saqueryreq", WLANTEST_FRAME_SAQUERYREQ },
871         { NULL, 0 }
872 };
873
874 static int cmd_inject(int s, int argc, char *argv[])
875 {
876         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
877         u8 buf[100], *end, *pos;
878         int rlen, i;
879         enum wlantest_inject_protection prot;
880
881         /* <frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff> */
882
883         if (argc < 5) {
884                 printf("inject needs five arguments: frame, protection, "
885                        "sender, BSSID, STA/ff:ff:ff:ff:ff:ff\n");
886                 return -1;
887         }
888
889         pos = buf;
890         end = buf + sizeof(buf);
891         WPA_PUT_BE32(pos, WLANTEST_CTRL_INJECT);
892         pos += 4;
893
894         for (i = 0; inject_frames[i].name; i++) {
895                 if (os_strcasecmp(inject_frames[i].name, argv[0]) == 0)
896                         break;
897         }
898         if (inject_frames[i].name == NULL) {
899                 printf("Unknown inject frame '%s'\n", argv[0]);
900                 printf("Frames:");
901                 for (i = 0; inject_frames[i].name; i++)
902                         printf(" %s", inject_frames[i].name);
903                 printf("\n");
904                 return -1;
905         }
906
907         pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_FRAME,
908                             inject_frames[i].frame);
909
910         if (os_strcasecmp(argv[1], "normal") == 0)
911                 prot = WLANTEST_INJECT_NORMAL;
912         else if (os_strcasecmp(argv[1], "protected") == 0)
913                 prot = WLANTEST_INJECT_PROTECTED;
914         else if (os_strcasecmp(argv[1], "unprotected") == 0)
915                 prot = WLANTEST_INJECT_UNPROTECTED;
916         else if (os_strcasecmp(argv[1], "incorrect") == 0)
917                 prot = WLANTEST_INJECT_INCORRECT_KEY;
918         else {
919                 printf("Unknown protection type '%s'\n", argv[1]);
920                 printf("Protection types: normal protected unprotected "
921                        "incorrect\n");
922                 return -1;
923         }
924         pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot);
925
926         if (os_strcasecmp(argv[2], "ap") == 0) {
927                 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
928                                     1);
929         } else if (os_strcasecmp(argv[2], "sta") == 0) {
930                 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
931                                     0);
932         } else {
933                 printf("Unknown sender '%s'\n", argv[2]);
934                 printf("Sender types: ap sta\n");
935                 return -1;
936         }
937
938         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
939         if (hwaddr_aton(argv[3], pos) < 0) {
940                 printf("Invalid BSSID '%s'\n", argv[3]);
941                 return -1;
942         }
943         pos += ETH_ALEN;
944
945         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
946         if (hwaddr_aton(argv[4], pos) < 0) {
947                 printf("Invalid STA '%s'\n", argv[4]);
948                 return -1;
949         }
950         pos += ETH_ALEN;
951
952         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
953         if (rlen < 0)
954                 return -1;
955         printf("OK\n");
956         return 0;
957 }
958
959
960 static char ** complete_inject(int s, const char *str, int pos)
961 {
962         int arg = get_cmd_arg_num(str, pos);
963         char **res = NULL;
964         int i, count;
965         u8 addr[ETH_ALEN];
966
967         switch (arg) {
968         case 1:
969                 /* frame list */
970                 count = sizeof(inject_frames) / sizeof(inject_frames[0]);
971                 res = os_zalloc(count * sizeof(char *));
972                 if (res == NULL)
973                         break;
974                 for (i = 0; inject_frames[i].name; i++) {
975                         res[i] = os_strdup(inject_frames[i].name);
976                         if (res[i] == NULL)
977                                 break;
978                 }
979                 break;
980         case 2:
981                 res = os_zalloc(5 * sizeof(char *));
982                 if (res == NULL)
983                         break;
984                 res[0] = os_strdup("normal");
985                 if (res[0] == NULL)
986                         break;
987                 res[1] = os_strdup("protected");
988                 if (res[1] == NULL)
989                         break;
990                 res[2] = os_strdup("unprotected");
991                 if (res[2] == NULL)
992                         break;
993                 res[3] = os_strdup("incorrect");
994                 if (res[3] == NULL)
995                         break;
996                 break;
997         case 3:
998                 res = os_zalloc(3 * sizeof(char *));
999                 if (res == NULL)
1000                         break;
1001                 res[0] = os_strdup("ap");
1002                 if (res[0] == NULL)
1003                         break;
1004                 res[1] = os_strdup("sta");
1005                 if (res[1] == NULL)
1006                         break;
1007                 break;
1008         case 4:
1009                 res = get_bssid_list(s);
1010                 break;
1011         case 5:
1012                 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
1013                         break;
1014                 res = get_sta_list(s, addr, 1);
1015                 break;
1016         }
1017
1018         return res;
1019 }
1020
1021
1022 static u8 * add_hex(u8 *pos, u8 *end, const char *str)
1023 {
1024         const char *s;
1025         int val;
1026
1027         s = str;
1028         while (*s) {
1029                 while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n' ||
1030                        *s == ':')
1031                         s++;
1032                 if (*s == '\0')
1033                         break;
1034                 if (*s == '#') {
1035                         while (*s != '\0' && *s != '\r' && *s != '\n')
1036                                 s++;
1037                         continue;
1038                 }
1039
1040                 val = hex2byte(s);
1041                 if (val < 0) {
1042                         printf("Invalid hex encoding '%s'\n", s);
1043                         return NULL;
1044                 }
1045                 if (pos == end) {
1046                         printf("Too long frame\n");
1047                         return NULL;
1048                 }
1049                 *pos++ = val;
1050                 s += 2;
1051         }
1052
1053         return pos;
1054 }
1055
1056
1057 static int cmd_send(int s, int argc, char *argv[])
1058 {
1059         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1060         u8 buf[WLANTEST_CTRL_MAX_CMD_LEN], *end, *pos, *len_pos;
1061         int rlen;
1062         enum wlantest_inject_protection prot;
1063         int arg;
1064
1065         /* <prot> <raw frame as hex dump> */
1066
1067         if (argc < 2) {
1068                 printf("send needs two arguments: protected/unprotected, "
1069                        "raw frame as hex dump\n");
1070                 return -1;
1071         }
1072
1073         pos = buf;
1074         end = buf + sizeof(buf);
1075         WPA_PUT_BE32(pos, WLANTEST_CTRL_SEND);
1076         pos += 4;
1077
1078         if (os_strcasecmp(argv[0], "normal") == 0)
1079                 prot = WLANTEST_INJECT_NORMAL;
1080         else if (os_strcasecmp(argv[0], "protected") == 0)
1081                 prot = WLANTEST_INJECT_PROTECTED;
1082         else if (os_strcasecmp(argv[0], "unprotected") == 0)
1083                 prot = WLANTEST_INJECT_UNPROTECTED;
1084         else if (os_strcasecmp(argv[0], "incorrect") == 0)
1085                 prot = WLANTEST_INJECT_INCORRECT_KEY;
1086         else {
1087                 printf("Unknown protection type '%s'\n", argv[1]);
1088                 printf("Protection types: normal protected unprotected "
1089                        "incorrect\n");
1090                 return -1;
1091         }
1092         pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot);
1093
1094         WPA_PUT_BE32(pos, WLANTEST_ATTR_FRAME);
1095         pos += 4;
1096         len_pos = pos;
1097         pos += 4;
1098
1099         for (arg = 1; pos && arg < argc; arg++)
1100                 pos = add_hex(pos, end, argv[arg]);
1101         if (pos == NULL)
1102                 return -1;
1103
1104         WPA_PUT_BE32(len_pos, pos - len_pos - 4);
1105
1106         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1107         if (rlen < 0)
1108                 return -1;
1109         printf("OK\n");
1110         return 0;
1111 }
1112
1113
1114 static char ** complete_send(int s, const char *str, int pos)
1115 {
1116         int arg = get_cmd_arg_num(str, pos);
1117         char **res = NULL;
1118
1119         switch (arg) {
1120         case 1:
1121                 res = os_zalloc(5 * sizeof(char *));
1122                 if (res == NULL)
1123                         break;
1124                 res[0] = os_strdup("normal");
1125                 if (res[0] == NULL)
1126                         break;
1127                 res[1] = os_strdup("protected");
1128                 if (res[1] == NULL)
1129                         break;
1130                 res[2] = os_strdup("unprotected");
1131                 if (res[2] == NULL)
1132                         break;
1133                 res[3] = os_strdup("incorrect");
1134                 if (res[3] == NULL)
1135                         break;
1136                 break;
1137         }
1138
1139         return res;
1140 }
1141
1142
1143 static int cmd_version(int s, int argc, char *argv[])
1144 {
1145         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1146         u8 buf[4];
1147         char *version;
1148         size_t len;
1149         int rlen, i;
1150
1151         WPA_PUT_BE32(buf, WLANTEST_CTRL_VERSION);
1152         rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
1153         if (rlen < 0)
1154                 return -1;
1155
1156         version = (char *) attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_VERSION,
1157                                     &len);
1158         if (version == NULL)
1159                 return -1;
1160
1161         for (i = 0; i < len; i++)
1162                 putchar(version[i]);
1163         printf("\n");
1164
1165         return 0;
1166 }
1167
1168
1169 static int cmd_add_passphrase(int s, int argc, char *argv[])
1170 {
1171         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1172         u8 buf[100], *pos, *end;
1173         size_t len;
1174         int rlen;
1175
1176         if (argc < 1) {
1177                 printf("add_passphrase needs one argument: passphrase\n");
1178                 return -1;
1179         }
1180
1181         len = os_strlen(argv[0]);
1182         if (len < 8 || len > 63) {
1183                 printf("Invalid passphrase '%s'\n", argv[0]);
1184                 return -1;
1185         }
1186         pos = buf;
1187         end = buf + sizeof(buf);
1188         WPA_PUT_BE32(pos, WLANTEST_CTRL_ADD_PASSPHRASE);
1189         pos += 4;
1190         pos = attr_add_str(pos, end, WLANTEST_ATTR_PASSPHRASE,
1191                            argv[0]);
1192         if (argc > 1) {
1193                 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1194                 if (hwaddr_aton(argv[1], pos) < 0) {
1195                         printf("Invalid BSSID '%s'\n", argv[3]);
1196                         return -1;
1197                 }
1198                 pos += ETH_ALEN;
1199         }
1200
1201         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1202         if (rlen < 0)
1203                 return -1;
1204         return 0;
1205 }
1206
1207
1208 struct sta_infos {
1209         const char *name;
1210         enum wlantest_sta_info num;
1211 };
1212
1213 static const struct sta_infos sta_infos[] = {
1214         { "proto", WLANTEST_STA_INFO_PROTO },
1215         { "pairwise", WLANTEST_STA_INFO_PAIRWISE },
1216         { "key_mgmt", WLANTEST_STA_INFO_KEY_MGMT },
1217         { "rsn_capab", WLANTEST_STA_INFO_RSN_CAPAB },
1218         { "state", WLANTEST_STA_INFO_STATE },
1219         { NULL, 0 }
1220 };
1221
1222 static int cmd_info_sta(int s, int argc, char *argv[])
1223 {
1224         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1225         u8 buf[100], *end, *pos;
1226         int rlen, i;
1227         size_t len;
1228         char info[100];
1229
1230         if (argc != 3) {
1231                 printf("sta_info needs at three arguments: "
1232                        "counter name, BSSID, and STA address\n");
1233                 return -1;
1234         }
1235
1236         pos = buf;
1237         end = buf + sizeof(buf);
1238         WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_STA);
1239         pos += 4;
1240
1241         for (i = 0; sta_infos[i].name; i++) {
1242                 if (os_strcasecmp(sta_infos[i].name, argv[0]) == 0)
1243                         break;
1244         }
1245         if (sta_infos[i].name == NULL) {
1246                 printf("Unknown STA info '%s'\n", argv[0]);
1247                 printf("Info fields:");
1248                 for (i = 0; sta_infos[i].name; i++)
1249                         printf(" %s", sta_infos[i].name);
1250                 printf("\n");
1251                 return -1;
1252         }
1253
1254         pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_INFO,
1255                             sta_infos[i].num);
1256         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1257         if (hwaddr_aton(argv[1], pos) < 0) {
1258                 printf("Invalid BSSID '%s'\n", argv[1]);
1259                 return -1;
1260         }
1261         pos += ETH_ALEN;
1262
1263         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
1264         if (hwaddr_aton(argv[2], pos) < 0) {
1265                 printf("Invalid STA address '%s'\n", argv[2]);
1266                 return -1;
1267         }
1268         pos += ETH_ALEN;
1269
1270         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1271         if (rlen < 0)
1272                 return -1;
1273
1274         pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len);
1275         if (pos == NULL)
1276                 return -1;
1277         if (len >= sizeof(info))
1278                 len = sizeof(info) - 1;
1279         os_memcpy(info, pos, len);
1280         info[len] = '\0';
1281         printf("%s\n", info);
1282         return 0;
1283 }
1284
1285
1286 static char ** complete_info_sta(int s, const char *str, int pos)
1287 {
1288         int arg = get_cmd_arg_num(str, pos);
1289         char **res = NULL;
1290         int i, count;
1291         u8 addr[ETH_ALEN];
1292
1293         switch (arg) {
1294         case 1:
1295                 /* counter list */
1296                 count = sizeof(sta_infos) / sizeof(sta_infos[0]);
1297                 res = os_zalloc(count * sizeof(char *));
1298                 if (res == NULL)
1299                         return NULL;
1300                 for (i = 0; sta_infos[i].name; i++) {
1301                         res[i] = os_strdup(sta_infos[i].name);
1302                         if (res[i] == NULL)
1303                                 break;
1304                 }
1305                 break;
1306         case 2:
1307                 res = get_bssid_list(s);
1308                 break;
1309         case 3:
1310                 if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
1311                         break;
1312                 res = get_sta_list(s, addr, 0);
1313                 break;
1314         }
1315
1316         return res;
1317 }
1318
1319
1320 struct bss_infos {
1321         const char *name;
1322         enum wlantest_bss_info num;
1323 };
1324
1325 static const struct bss_infos bss_infos[] = {
1326         { "proto", WLANTEST_BSS_INFO_PROTO },
1327         { "pairwise", WLANTEST_BSS_INFO_PAIRWISE },
1328         { "group", WLANTEST_BSS_INFO_GROUP },
1329         { "group_mgmt", WLANTEST_BSS_INFO_GROUP_MGMT },
1330         { "key_mgmt", WLANTEST_BSS_INFO_KEY_MGMT },
1331         { "rsn_capab", WLANTEST_BSS_INFO_RSN_CAPAB },
1332         { NULL, 0 }
1333 };
1334
1335 static int cmd_info_bss(int s, int argc, char *argv[])
1336 {
1337         u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1338         u8 buf[100], *end, *pos;
1339         int rlen, i;
1340         size_t len;
1341         char info[100];
1342
1343         if (argc != 2) {
1344                 printf("bss_info needs at two arguments: "
1345                        "field name and BSSID\n");
1346                 return -1;
1347         }
1348
1349         pos = buf;
1350         end = buf + sizeof(buf);
1351         WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_BSS);
1352         pos += 4;
1353
1354         for (i = 0; bss_infos[i].name; i++) {
1355                 if (os_strcasecmp(bss_infos[i].name, argv[0]) == 0)
1356                         break;
1357         }
1358         if (bss_infos[i].name == NULL) {
1359                 printf("Unknown BSS info '%s'\n", argv[0]);
1360                 printf("Info fields:");
1361                 for (i = 0; bss_infos[i].name; i++)
1362                         printf(" %s", bss_infos[i].name);
1363                 printf("\n");
1364                 return -1;
1365         }
1366
1367         pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_INFO,
1368                             bss_infos[i].num);
1369         pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1370         if (hwaddr_aton(argv[1], pos) < 0) {
1371                 printf("Invalid BSSID '%s'\n", argv[1]);
1372                 return -1;
1373         }
1374         pos += ETH_ALEN;
1375
1376         rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1377         if (rlen < 0)
1378                 return -1;
1379
1380         pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len);
1381         if (pos == NULL)
1382                 return -1;
1383         if (len >= sizeof(info))
1384                 len = sizeof(info) - 1;
1385         os_memcpy(info, pos, len);
1386         info[len] = '\0';
1387         printf("%s\n", info);
1388         return 0;
1389 }
1390
1391
1392 static char ** complete_info_bss(int s, const char *str, int pos)
1393 {
1394         int arg = get_cmd_arg_num(str, pos);
1395         char **res = NULL;
1396         int i, count;
1397
1398         switch (arg) {
1399         case 1:
1400                 /* counter list */
1401                 count = sizeof(bss_infos) / sizeof(bss_infos[0]);
1402                 res = os_zalloc(count * sizeof(char *));
1403                 if (res == NULL)
1404                         return NULL;
1405                 for (i = 0; bss_infos[i].name; i++) {
1406                         res[i] = os_strdup(bss_infos[i].name);
1407                         if (res[i] == NULL)
1408                                 break;
1409                 }
1410                 break;
1411         case 2:
1412                 res = get_bssid_list(s);
1413                 break;
1414         }
1415
1416         return res;
1417 }
1418
1419
1420 struct wlantest_cli_cmd {
1421         const char *cmd;
1422         int (*handler)(int s, int argc, char *argv[]);
1423         const char *usage;
1424         char ** (*complete)(int s, const char *str, int pos);
1425 };
1426
1427 static const struct wlantest_cli_cmd wlantest_cli_commands[] = {
1428         { "ping", cmd_ping, "= test connection to wlantest", NULL },
1429         { "terminate", cmd_terminate, "= terminate wlantest", NULL },
1430         { "list_bss", cmd_list_bss, "= get BSS list", NULL },
1431         { "list_sta", cmd_list_sta, "<BSSID> = get STA list",
1432           complete_list_sta },
1433         { "flush", cmd_flush, "= drop all collected BSS data", NULL },
1434         { "clear_sta_counters", cmd_clear_sta_counters,
1435           "<BSSID> <STA> = clear STA counters", complete_clear_sta_counters },
1436         { "clear_bss_counters", cmd_clear_bss_counters,
1437           "<BSSID> = clear BSS counters", complete_clear_bss_counters },
1438         { "get_sta_counter", cmd_get_sta_counter,
1439           "<counter> <BSSID> <STA> = get STA counter value",
1440           complete_get_sta_counter },
1441         { "get_bss_counter", cmd_get_bss_counter,
1442           "<counter> <BSSID> = get BSS counter value",
1443           complete_get_bss_counter },
1444         { "inject", cmd_inject,
1445           "<frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff>",
1446           complete_inject },
1447         { "send", cmd_send,
1448           "<prot> <raw frame as hex dump>",
1449           complete_send },
1450         { "version", cmd_version, "= get wlantest version", NULL },
1451         { "add_passphrase", cmd_add_passphrase,
1452           "<passphrase> = add a known passphrase", NULL },
1453         { "info_sta", cmd_info_sta,
1454           "<field> <BSSID> <STA> = get STA information",
1455           complete_info_sta },
1456         { "info_bss", cmd_info_bss,
1457           "<field> <BSSID> = get BSS information",
1458           complete_info_bss },
1459         { "clear_tdls_counters", cmd_clear_tdls_counters,
1460           "<BSSID> <STA1> <STA2> = clear TDLS counters",
1461           complete_clear_tdls_counters },
1462         { "get_tdls_counter", cmd_get_tdls_counter,
1463           "<counter> <BSSID> <STA1> <STA2> = get TDLS counter value",
1464           complete_get_tdls_counter },
1465         { "get_bss_counter", cmd_get_bss_counter,
1466           "<counter> <BSSID> = get BSS counter value",
1467           complete_get_bss_counter },
1468         { NULL, NULL, NULL, NULL }
1469 };
1470
1471
1472 static int ctrl_command(int s, int argc, char *argv[])
1473 {
1474         const struct wlantest_cli_cmd *cmd, *match = NULL;
1475         int count = 0;
1476         int ret = 0;
1477
1478         for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) {
1479                 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1480                 {
1481                         match = cmd;
1482                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1483                                 /* exact match */
1484                                 count = 1;
1485                                 break;
1486                         }
1487                         count++;
1488                 }
1489         }
1490
1491         if (count > 1) {
1492                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1493                 for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) {
1494                         if (os_strncasecmp(cmd->cmd, argv[0],
1495                                            os_strlen(argv[0])) == 0) {
1496                                 printf(" %s", cmd->cmd);
1497                         }
1498                 }
1499                 printf("\n");
1500                 ret = 1;
1501         } else if (count == 0) {
1502                 printf("Unknown command '%s'\n", argv[0]);
1503                 ret = 1;
1504         } else {
1505                 ret = match->handler(s, argc - 1, &argv[1]);
1506         }
1507
1508         return ret;
1509 }
1510
1511
1512 struct wlantest_cli {
1513         int s;
1514 };
1515
1516
1517 #define max_args 10
1518
1519 static int tokenize_cmd(char *cmd, char *argv[])
1520 {
1521         char *pos;
1522         int argc = 0;
1523
1524         pos = cmd;
1525         for (;;) {
1526                 while (*pos == ' ')
1527                         pos++;
1528                 if (*pos == '\0')
1529                         break;
1530                 argv[argc] = pos;
1531                 argc++;
1532                 if (argc == max_args)
1533                         break;
1534                 if (*pos == '"') {
1535                         char *pos2 = os_strrchr(pos, '"');
1536                         if (pos2)
1537                                 pos = pos2 + 1;
1538                 }
1539                 while (*pos != '\0' && *pos != ' ')
1540                         pos++;
1541                 if (*pos == ' ')
1542                         *pos++ = '\0';
1543         }
1544
1545         return argc;
1546 }
1547
1548
1549 static void wlantest_cli_edit_cmd_cb(void *ctx, char *cmd)
1550 {
1551         struct wlantest_cli *cli = ctx;
1552         char *argv[max_args];
1553         int argc;
1554         argc = tokenize_cmd(cmd, argv);
1555         if (argc) {
1556                 int ret = ctrl_command(cli->s, argc, argv);
1557                 if (ret < 0)
1558                         printf("FAIL\n");
1559         }
1560 }
1561
1562
1563 static void wlantest_cli_eloop_terminate(int sig, void *signal_ctx)
1564 {
1565         eloop_terminate();
1566 }
1567
1568
1569 static void wlantest_cli_edit_eof_cb(void *ctx)
1570 {
1571         eloop_terminate();
1572 }
1573
1574
1575 static char ** wlantest_cli_cmd_list(void)
1576 {
1577         char **res;
1578         int i, count;
1579
1580         count = sizeof(wlantest_cli_commands) /
1581                 sizeof(wlantest_cli_commands[0]);
1582         res = os_zalloc(count * sizeof(char *));
1583         if (res == NULL)
1584                 return NULL;
1585
1586         for (i = 0; wlantest_cli_commands[i].cmd; i++) {
1587                 res[i] = os_strdup(wlantest_cli_commands[i].cmd);
1588                 if (res[i] == NULL)
1589                         break;
1590         }
1591
1592         return res;
1593 }
1594
1595
1596 static char ** wlantest_cli_cmd_completion(struct wlantest_cli *cli,
1597                                            const char *cmd, const char *str,
1598                                            int pos)
1599 {
1600         int i;
1601
1602         for (i = 0; wlantest_cli_commands[i].cmd; i++) {
1603                 const struct wlantest_cli_cmd *c = &wlantest_cli_commands[i];
1604                 if (os_strcasecmp(c->cmd, cmd) == 0) {
1605                         edit_clear_line();
1606                         printf("\r%s\n", c->usage);
1607                         edit_redraw();
1608                         if (c->complete)
1609                                 return c->complete(cli->s, str, pos);
1610                         break;
1611                 }
1612         }
1613
1614         return NULL;
1615 }
1616
1617
1618 static char ** wlantest_cli_edit_completion_cb(void *ctx, const char *str,
1619                                                int pos)
1620 {
1621         struct wlantest_cli *cli = ctx;
1622         char **res;
1623         const char *end;
1624         char *cmd;
1625
1626         end = os_strchr(str, ' ');
1627         if (end == NULL || str + pos < end)
1628                 return wlantest_cli_cmd_list();
1629
1630         cmd = os_malloc(pos + 1);
1631         if (cmd == NULL)
1632                 return NULL;
1633         os_memcpy(cmd, str, pos);
1634         cmd[end - str] = '\0';
1635         res = wlantest_cli_cmd_completion(cli, cmd, str, pos);
1636         os_free(cmd);
1637         return res;
1638 }
1639
1640
1641 static void wlantest_cli_interactive(int s)
1642 {
1643         struct wlantest_cli cli;
1644         char *home, *hfile = NULL;
1645
1646         if (eloop_init())
1647                 return;
1648
1649         home = getenv("HOME");
1650         if (home) {
1651                 const char *fname = ".wlantest_cli_history";
1652                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1653                 hfile = os_malloc(hfile_len);
1654                 if (hfile)
1655                         os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
1656         }
1657
1658         cli.s = s;
1659         eloop_register_signal_terminate(wlantest_cli_eloop_terminate, &cli);
1660         edit_init(wlantest_cli_edit_cmd_cb, wlantest_cli_edit_eof_cb,
1661                   wlantest_cli_edit_completion_cb, &cli, hfile);
1662
1663         eloop_run();
1664
1665         edit_deinit(hfile, NULL);
1666         os_free(hfile);
1667         eloop_destroy();
1668 }
1669
1670
1671 int main(int argc, char *argv[])
1672 {
1673         int s;
1674         struct sockaddr_un addr;
1675         int ret = 0;
1676
1677         if (os_program_init())
1678                 return -1;
1679
1680         s = socket(AF_UNIX, SOCK_SEQPACKET, 0);
1681         if (s < 0) {
1682                 perror("socket");
1683                 return -1;
1684         }
1685
1686         os_memset(&addr, 0, sizeof(addr));
1687         addr.sun_family = AF_UNIX;
1688         os_strlcpy(addr.sun_path + 1, WLANTEST_SOCK_NAME,
1689                    sizeof(addr.sun_path) - 1);
1690         if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1691                 perror("connect");
1692                 close(s);
1693                 return -1;
1694         }
1695
1696         if (argc > 1) {
1697                 ret = ctrl_command(s, argc - 1, &argv[1]);
1698                 if (ret < 0)
1699                         printf("FAIL\n");
1700         } else {
1701                 wlantest_cli_interactive(s);
1702         }
1703
1704         close(s);
1705
1706         os_program_deinit();
1707
1708         return ret;
1709 }