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