blob: cdd7ef9de1515ea1e050356d08c0bc64ce881f7b [file] [log] [blame]
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001/*
2 * Sigma Control API DUT (wlantest)
3 * Copyright (c) 2010-2011, Atheros Communications, Inc.
Jouni Malinen9d7e31d2017-12-22 18:55:04 +02004 * Copyright (c) 2011-2013, 2017, Qualcomm Atheros, Inc.
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005 * All Rights Reserved.
6 * Licensed under the Clear BSD license. See README for more details.
7 */
8
9#include "sigma_dut.h"
10#include <sys/un.h>
11#include "wlantest_ctrl.h"
12
13
14#ifndef ETH_ALEN
15#define ETH_ALEN 6
16#endif
17
18int hwaddr_aton(const char *txt, unsigned char *addr);
19
20
21static u8 * attr_get(u8 *buf, size_t buflen, enum wlantest_ctrl_attr attr,
22 size_t *len)
23{
24 u8 *pos = buf;
25
26 while (pos + 8 <= buf + buflen) {
27 enum wlantest_ctrl_attr a;
28 size_t alen;
29 a = WPA_GET_BE32(pos);
30 pos += 4;
31 alen = WPA_GET_BE32(pos);
32 pos += 4;
33 if (pos + alen > buf + buflen)
34 return NULL;
35 if (a == attr) {
36 *len = alen;
37 return pos;
38 }
39 pos += alen;
40 }
41
42 return NULL;
43}
44
45
46static u8 * attr_hdr_add(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
47 size_t len)
48{
49 if (pos == NULL || end - pos < (int) (8 + len))
50 return NULL;
51 WPA_PUT_BE32(pos, attr);
52 pos += 4;
53 WPA_PUT_BE32(pos, len);
54 pos += 4;
55 return pos;
56}
57
58
59static u8 * attr_add_str(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
60 const char *str)
61{
62 size_t len = strlen(str);
63
64 if (pos == NULL || end - pos < (int) (8 + len))
65 return NULL;
66 WPA_PUT_BE32(pos, attr);
67 pos += 4;
68 WPA_PUT_BE32(pos, len);
69 pos += 4;
70 memcpy(pos, str, len);
71 pos += len;
72 return pos;
73}
74
75
76static u8 * attr_add_be32(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
77 u32 val)
78{
79 if (pos == NULL || end - pos < 12)
80 return NULL;
81 WPA_PUT_BE32(pos, attr);
82 pos += 4;
83 WPA_PUT_BE32(pos, 4);
84 pos += 4;
85 WPA_PUT_BE32(pos, val);
86 pos += 4;
87 return pos;
88}
89
90
91static int open_wlantest(void)
92{
93 int s;
94 struct sockaddr_un addr;
95
96 s = socket(AF_UNIX, SOCK_SEQPACKET, 0);
97 if (s < 0) {
98 perror("socket");
99 return -1;
100 }
101
102 memset(&addr, 0, sizeof(addr));
103 addr.sun_family = AF_UNIX;
Peng Xub8fc5cc2017-05-10 17:27:28 -0700104 strlcpy(addr.sun_path + 1, WLANTEST_SOCK_NAME,
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200105 sizeof(addr.sun_path) - 1);
106 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
107 perror("connect");
108 close(s);
109 return -1;
110 }
111
112 return s;
113}
114
115
116static int cmd_send_and_recv(int s, const u8 *cmd, size_t cmd_len,
117 u8 *resp, size_t max_resp_len)
118{
119 int res;
120 enum wlantest_ctrl_cmd cmd_resp;
121
122 if (send(s, cmd, cmd_len, 0) < 0)
123 return -1;
124 res = recv(s, resp, max_resp_len, 0);
125 if (res < 4)
126 return -1;
127
128 cmd_resp = WPA_GET_BE32(resp);
129 if (cmd_resp == WLANTEST_CTRL_SUCCESS)
130 return res;
131
132 return -1;
133}
134
135
136static int cmd_simple(int s, enum wlantest_ctrl_cmd cmd)
137{
138 u8 buf[4];
139 int res;
140 WPA_PUT_BE32(buf, cmd);
141 res = cmd_send_and_recv(s, buf, sizeof(buf), buf, sizeof(buf));
142 return res < 0 ? -1 : 0;
143}
144
145
146static int run_wlantest_simple(struct sigma_dut *dut, struct sigma_conn *conn,
147 enum wlantest_ctrl_cmd cmd)
148{
149 int s, ret;
150
151 s = open_wlantest();
152 if (s < 0) {
153 send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
154 "available");
155 return 0;
156 }
157
158 ret = cmd_simple(s, cmd);
159 close(s);
160
161 return ret < 0 ? -2 : 1;
162}
163
164
165static int cmd_wlantest_version(struct sigma_dut *dut, struct sigma_conn *conn,
166 struct sigma_cmd *cmd)
167{
168 int s;
169 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
170 u8 buf[4];
171 char *version;
172 size_t len;
173 int rlen;
174 char *rbuf;
175
176 s = open_wlantest();
177 if (s < 0) {
178 send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
179 "available");
180 return 0;
181 }
182
183 WPA_PUT_BE32(buf, WLANTEST_CTRL_VERSION);
184 rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
185 close(s);
186 if (rlen < 0)
187 return -2;
188
189 version = (char *) attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_VERSION,
190 &len);
191 if (version == NULL)
192 return -2;
193
194 rbuf = malloc(9 + len);
195 if (rbuf == NULL)
196 return -2;
197 memcpy(rbuf, "version,", 8);
198 memcpy(rbuf + 8, version, len);
199 rbuf[8 + len] = '\0';
200 send_resp(dut, conn, SIGMA_COMPLETE, rbuf);
201 free(rbuf);
202 return 0;
203}
204
205
206int cmd_wlantest_set_channel(struct sigma_dut *dut, struct sigma_conn *conn,
207 struct sigma_cmd *cmd)
208{
209 char buf[100];
210 const char *chan;
211
212 if (dut->sniffer_ifname == NULL) {
213 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Sniffer "
214 "interface not available");
215 return 0;
216 }
217
218 chan = get_param(cmd, "channel");
219 if (chan == NULL)
220 return -1;
221
222 snprintf(buf, sizeof(buf), "iw dev %s set type monitor",
223 dut->sniffer_ifname);
224 if (system(buf) != 0) {
225 snprintf(buf, sizeof(buf), "ifconfig %s down",
226 dut->sniffer_ifname);
227 if (system(buf) != 0) {
228 sigma_dut_print(dut, DUT_MSG_INFO,
229 "Failed to run '%s'", buf);
230 return -2;
231 }
232
233 snprintf(buf, sizeof(buf), "iw dev %s set type monitor",
234 dut->sniffer_ifname);
235 if (system(buf) != 0) {
236 sigma_dut_print(dut, DUT_MSG_INFO,
237 "Failed to run '%s'", buf);
238 return -2;
239 }
240 }
241
242 snprintf(buf, sizeof(buf), "iw dev %s set channel %d HT20",
243 dut->sniffer_ifname, atoi(chan));
244 if (system(buf) != 0) {
245 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to run '%s'", buf);
246 return -2;
247 }
248
249 snprintf(buf, sizeof(buf), "ifconfig %s up", dut->sniffer_ifname);
250 if (system(buf) != 0) {
251 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to run '%s'", buf);
252 return -2;
253 }
254
255 dut->mode = SIGMA_MODE_SNIFFER;
256
257 return 1;
258}
259
260
261static int cmd_wlantest_flush(struct sigma_dut *dut, struct sigma_conn *conn,
262 struct sigma_cmd *cmd)
263{
264 return run_wlantest_simple(dut, conn, WLANTEST_CTRL_FLUSH);
265}
266
267
268int cmd_wlantest_send_frame(struct sigma_dut *dut, struct sigma_conn *conn,
269 struct sigma_cmd *cmd)
270{
271 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
272 u8 buf[100], *end, *pos;
273 int rlen;
274 enum wlantest_inject_frame frame;
275 enum wlantest_inject_protection prot;
276 const char *val;
277 int s;
278
279 /* wlantest_send_frame,PMFFrameType,disassoc,PMFProtected,Unprotected,sender,AP,bssid,00:11:22:33:44:55,stationID,00:66:77:88:99:aa */
280
281 if (dut->mode == SIGMA_MODE_STATION) {
282 sigma_dut_print(dut, DUT_MSG_DEBUG, "Convert "
283 "wlantest_send_frame to sta_send_frame");
284 return cmd_sta_send_frame(dut, conn, cmd);
285 }
286
287 if (dut->mode == SIGMA_MODE_AP) {
288 sigma_dut_print(dut, DUT_MSG_DEBUG, "Convert "
289 "wlantest_send_frame to ap_send_frame");
290 return cmd_ap_send_frame(dut, conn, cmd);
291 }
292
293 pos = buf;
294 end = buf + sizeof(buf);
295 WPA_PUT_BE32(pos, WLANTEST_CTRL_INJECT);
296 pos += 4;
297
298 val = get_param(cmd, "Type");
299 if (val == NULL)
300 val = get_param(cmd, "PMFFrameType");
301 if (val == NULL)
302 return -1;
303 if (strcasecmp(val, "disassoc") == 0)
304 frame = WLANTEST_FRAME_DISASSOC;
305 else if (strcasecmp(val, "deauth") == 0)
306 frame = WLANTEST_FRAME_DEAUTH;
307 else if (strcasecmp(val, "saquery") == 0)
308 frame = WLANTEST_FRAME_SAQUERYREQ;
309 else if (strcasecmp(val, "auth") == 0)
310 frame = WLANTEST_FRAME_AUTH;
311 else if (strcasecmp(val, "assocreq") == 0)
312 frame = WLANTEST_FRAME_ASSOCREQ;
313 else if (strcasecmp(val, "reassocreq") == 0)
314 frame = WLANTEST_FRAME_REASSOCREQ;
315 else {
316 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
317 "PMFFrameType");
318 return 0;
319 }
320 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_FRAME, frame);
321
322 val = get_param(cmd, "Protected");
323 if (val == NULL)
324 val = get_param(cmd, "PMFProtected");
325 if (val == NULL)
326 return -1;
327 if (strcasecmp(val, "CorrectKey") == 0)
328 prot = WLANTEST_INJECT_PROTECTED;
329 else if (strcasecmp(val, "IncorrectKey") == 0)
330 prot = WLANTEST_INJECT_INCORRECT_KEY;
331 else if (strcasecmp(val, "Unprotected") == 0)
332 prot = WLANTEST_INJECT_UNPROTECTED;
333 else {
334 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
335 "PMFProtected");
336 return 0;
337 }
338 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot);
339
340 val = get_param(cmd, "sender");
341 if (val == NULL)
342 return -1;
343 if (strcasecmp(val, "ap") == 0) {
344 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
345 1);
346 } else if (strcasecmp(val, "sta") == 0) {
347 pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
348 0);
349 } else {
350 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
351 "sender");
352 return 0;
353 }
354
355 val = get_param(cmd, "bssid");
356 if (val == NULL)
357 return -1;
358 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
359 if (hwaddr_aton(val, pos) < 0) {
360 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid bssid");
361 return 0;
362 }
363 pos += ETH_ALEN;
364
365 val = get_param(cmd, "stationID");
366 if (val == NULL)
367 return -1;
368 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
369 if (hwaddr_aton(val, pos) < 0) {
370 send_resp(dut, conn, SIGMA_INVALID,
371 "errorCode,Invalid stationID");
372 return 0;
373 }
374 pos += ETH_ALEN;
375
376 s = open_wlantest();
377 if (s < 0) {
378 send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
379 "available");
380 return 0;
381 }
382 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
383 close(s);
384 if (rlen < 0)
385 return -2;
386 return 1;
387}
388
389
390static int cmd_wlantest_add_passphrase(struct sigma_dut *dut,
391 struct sigma_conn *conn,
392 struct sigma_cmd *cmd)
393{
394 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
395 u8 buf[100], *end, *pos;
396 int rlen;
397 const char *val;
398 int s;
399
400 pos = buf;
401 end = buf + sizeof(buf);
402 WPA_PUT_BE32(pos, WLANTEST_CTRL_ADD_PASSPHRASE);
403 pos += 4;
404
405 val = get_param(cmd, "passphrase");
406 if (val) {
407 if (strlen(val) < 8 || strlen(val) > 63)
408 return -1;
409 pos = attr_add_str(pos, end, WLANTEST_ATTR_PASSPHRASE, val);
410 } else {
411 val = get_param(cmd, "wepkey");
412 if (!val)
413 return -1;
414 pos = attr_add_str(pos, end, WLANTEST_ATTR_WEPKEY, val);
415 }
416 val = get_param(cmd, "bssid");
417 if (val) {
418 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
419 if (hwaddr_aton(val, pos) < 0) {
420 send_resp(dut, conn, SIGMA_INVALID,
421 "errorCode,Invalid bssid");
422 return 0;
423 }
424 pos += ETH_ALEN;
425 }
426
427 s = open_wlantest();
428 if (s < 0) {
429 send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
430 "available");
431 return 0;
432 }
433 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
434 close(s);
435 if (rlen < 0)
436 return -2;
437 return 1;
438}
439
440
441static int cmd_wlantest_clear_sta_counters(struct sigma_dut *dut,
442 struct sigma_conn *conn,
443 struct sigma_cmd *cmd)
444{
445 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
446 u8 buf[100], *end, *pos;
447 int rlen;
448 const char *val;
449 int s;
450
451 pos = buf;
452 end = buf + sizeof(buf);
453 WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_STA_COUNTERS);
454 pos += 4;
455
456 val = get_param(cmd, "bssid");
457 if (val == NULL)
458 return -1;
459 if (val) {
460 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
461 if (hwaddr_aton(val, pos) < 0) {
462 send_resp(dut, conn, SIGMA_INVALID,
463 "errorCode,Invalid bssid");
464 return 0;
465 }
466 pos += ETH_ALEN;
467 }
468
469 val = get_param(cmd, "stationID");
470 if (val == NULL)
471 return -1;
472 if (val) {
473 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
474 if (hwaddr_aton(val, pos) < 0) {
475 send_resp(dut, conn, SIGMA_INVALID,
476 "errorCode,Invalid stationID");
477 return 0;
478 }
479 pos += ETH_ALEN;
480 }
481
482 s = open_wlantest();
483 if (s < 0) {
484 send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
485 "available");
486 return 0;
487 }
488 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
489 close(s);
490 if (rlen < 0)
491 return -2;
492 return 1;
493}
494
495
496static int cmd_wlantest_clear_bss_counters(struct sigma_dut *dut,
497 struct sigma_conn *conn,
498 struct sigma_cmd *cmd)
499{
500 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
501 u8 buf[100], *end, *pos;
502 int rlen;
503 const char *val;
504 int s;
505
506 pos = buf;
507 end = buf + sizeof(buf);
508 WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_BSS_COUNTERS);
509 pos += 4;
510
511 val = get_param(cmd, "bssid");
512 if (val == NULL)
513 return -1;
514 if (val) {
515 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
516 if (hwaddr_aton(val, pos) < 0) {
517 send_resp(dut, conn, SIGMA_INVALID,
518 "errorCode,Invalid bssid");
519 return 0;
520 }
521 pos += ETH_ALEN;
522 }
523
524 s = open_wlantest();
525 if (s < 0) {
526 send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
527 "available");
528 return 0;
529 }
530 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
531 close(s);
532 if (rlen < 0)
533 return -2;
534 return 1;
535}
536
537
538static int cmd_wlantest_clear_tdls_counters(struct sigma_dut *dut,
539 struct sigma_conn *conn,
540 struct sigma_cmd *cmd)
541{
542 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
543 u8 buf[100], *end, *pos;
544 int rlen;
545 const char *val;
546 int s;
547
548 pos = buf;
549 end = buf + sizeof(buf);
550 WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_TDLS_COUNTERS);
551 pos += 4;
552
553 val = get_param(cmd, "bssid");
554 if (val == NULL)
555 return -1;
556 if (val) {
557 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
558 if (hwaddr_aton(val, pos) < 0) {
559 send_resp(dut, conn, SIGMA_INVALID,
560 "errorCode,Invalid bssid");
561 return 0;
562 }
563 pos += ETH_ALEN;
564 }
565
566 val = get_param(cmd, "stationID");
567 if (val == NULL)
568 return -1;
569 if (val) {
570 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
571 if (hwaddr_aton(val, pos) < 0) {
572 send_resp(dut, conn, SIGMA_INVALID,
573 "errorCode,Invalid stationID");
574 return 0;
575 }
576 pos += ETH_ALEN;
577 }
578
579 val = get_param(cmd, "stationID2");
580 if (val == NULL)
581 return -1;
582 if (val) {
583 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA2_ADDR,
584 ETH_ALEN);
585 if (hwaddr_aton(val, pos) < 0) {
586 send_resp(dut, conn, SIGMA_INVALID,
587 "errorCode,Invalid stationID2");
588 return 0;
589 }
590 pos += ETH_ALEN;
591 }
592
593 s = open_wlantest();
594 if (s < 0) {
595 send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
596 "available");
597 return 0;
598 }
599 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
600 close(s);
601 if (rlen < 0)
602 return -2;
603 return 1;
604}
605
606
607struct sta_counters {
608 const char *name;
609 enum wlantest_sta_counter num;
610};
611
612static const struct sta_counters sta_counters[] = {
613 { "auth_tx", WLANTEST_STA_COUNTER_AUTH_TX },
614 { "auth_rx", WLANTEST_STA_COUNTER_AUTH_RX },
615 { "assocreq_tx", WLANTEST_STA_COUNTER_ASSOCREQ_TX },
616 { "reassocreq_tx", WLANTEST_STA_COUNTER_REASSOCREQ_TX },
617 { "ptk_learned", WLANTEST_STA_COUNTER_PTK_LEARNED },
618 { "valid_deauth_tx", WLANTEST_STA_COUNTER_VALID_DEAUTH_TX },
619 { "valid_deauth_rx", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX },
620 { "invalid_deauth_tx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX },
621 { "invalid_deauth_rx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX },
622 { "valid_disassoc_tx", WLANTEST_STA_COUNTER_VALID_DISASSOC_TX },
623 { "valid_disassoc_rx", WLANTEST_STA_COUNTER_VALID_DISASSOC_RX },
624 { "invalid_disassoc_tx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX },
625 { "invalid_disassoc_rx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX },
626 { "valid_saqueryreq_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX },
627 { "valid_saqueryreq_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX },
628 { "invalid_saqueryreq_tx",
629 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX },
630 { "invalid_saqueryreq_rx",
631 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX },
632 { "valid_saqueryresp_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX },
633 { "valid_saqueryresp_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX },
634 { "invalid_saqueryresp_tx",
635 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX },
636 { "invalid_saqueryresp_rx",
637 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX },
638 { "ping_ok", WLANTEST_STA_COUNTER_PING_OK },
639 { "assocresp_comeback", WLANTEST_STA_COUNTER_ASSOCRESP_COMEBACK },
640 { "reassocresp_comeback", WLANTEST_STA_COUNTER_REASSOCRESP_COMEBACK },
641 { "ping_ok_first_assoc", WLANTEST_STA_COUNTER_PING_OK_FIRST_ASSOC },
642 { "valid_deauth_rx_ack", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX_ACK },
643 { "valid_disassoc_rx_ack",
644 WLANTEST_STA_COUNTER_VALID_DISASSOC_RX_ACK },
645 { "invalid_deauth_rx_ack",
646 WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX_ACK },
647 { "invalid_disassoc_rx_ack",
648 WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX_ACK },
649 { "deauth_rx_asleep", WLANTEST_STA_COUNTER_DEAUTH_RX_ASLEEP },
650 { "deauth_rx_awake", WLANTEST_STA_COUNTER_DEAUTH_RX_AWAKE },
651 { "disassoc_rx_asleep", WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP },
652 { "disassoc_rx_awake", WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE },
653 { "prot_data_tx", WLANTEST_STA_COUNTER_PROT_DATA_TX },
654 { "deauth_rx_rc6", WLANTEST_STA_COUNTER_DEAUTH_RX_RC6 },
655 { "deauth_rx_rc7", WLANTEST_STA_COUNTER_DEAUTH_RX_RC7 },
656 { "disassoc_rx_rc6", WLANTEST_STA_COUNTER_DISASSOC_RX_RC6 },
657 { "disassoc_rx_rc7", WLANTEST_STA_COUNTER_DISASSOC_RX_RC7 },
658 { NULL, 0 }
659};
660
661static int cmd_wlantest_get_sta_counter(struct sigma_dut *dut,
662 struct sigma_conn *conn,
663 struct sigma_cmd *cmd)
664{
665 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
666 u8 buf[100], *end, *pos;
667 int rlen;
668 const char *val;
669 int s, i;
670 char ret[100];
671 size_t len;
672
673 pos = buf;
674 end = buf + sizeof(buf);
675 WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_STA_COUNTER);
676 pos += 4;
677
678 val = get_param(cmd, "bssid");
679 if (val == NULL)
680 return -1;
681 if (val) {
682 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
683 if (hwaddr_aton(val, pos) < 0) {
684 send_resp(dut, conn, SIGMA_INVALID,
685 "errorCode,Invalid bssid");
686 return 0;
687 }
688 pos += ETH_ALEN;
689 }
690
691 val = get_param(cmd, "stationID");
692 if (val == NULL)
693 return -1;
694 if (val) {
695 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
696 if (hwaddr_aton(val, pos) < 0) {
697 send_resp(dut, conn, SIGMA_INVALID,
698 "errorCode,Invalid stationID");
699 return 0;
700 }
701 pos += ETH_ALEN;
702 }
703
704 val = get_param(cmd, "field");
705 if (val == NULL)
706 return -1;
707 for (i = 0; sta_counters[i].name; i++) {
708 if (strcasecmp(sta_counters[i].name, val) == 0)
709 break;
710 }
711 if (sta_counters[i].name == NULL) {
712 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid field");
713 return 0;
714 }
715 pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_COUNTER,
716 sta_counters[i].num);
717
718 s = open_wlantest();
719 if (s < 0) {
720 send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
721 "available");
722 return 0;
723 }
724 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
725 close(s);
726
727
728 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
729 if (pos == NULL || len != 4)
730 return -2;
731 snprintf(ret, sizeof(ret), "counter,%u", WPA_GET_BE32(pos));
732 send_resp(dut, conn, SIGMA_COMPLETE, ret);
733 return 0;
734}
735
736
737struct bss_counters {
738 const char *name;
739 enum wlantest_bss_counter num;
740};
741
742static const struct bss_counters bss_counters[] = {
743 { "valid_bip_mmie", WLANTEST_BSS_COUNTER_VALID_BIP_MMIE },
744 { "invalid_bip_mmie", WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE },
745 { "missing_bip_mmie", WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE },
746 { "bip_deauth", WLANTEST_BSS_COUNTER_BIP_DEAUTH },
747 { "bip_disassoc", WLANTEST_BSS_COUNTER_BIP_DISASSOC },
748 { NULL, 0 }
749};
750
751static int cmd_wlantest_get_bss_counter(struct sigma_dut *dut,
752 struct sigma_conn *conn,
753 struct sigma_cmd *cmd)
754{
755 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
756 u8 buf[100], *end, *pos;
757 int rlen;
758 const char *val;
759 int s, i;
760 char ret[100];
761 size_t len;
762
763 pos = buf;
764 end = buf + sizeof(buf);
765 WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_BSS_COUNTER);
766 pos += 4;
767
768 val = get_param(cmd, "bssid");
769 if (val == NULL)
770 return -1;
771 if (val) {
772 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
773 if (hwaddr_aton(val, pos) < 0) {
774 send_resp(dut, conn, SIGMA_INVALID,
775 "errorCode,Invalid bssid");
776 return 0;
777 }
778 pos += ETH_ALEN;
779 }
780
781 val = get_param(cmd, "field");
782 if (val == NULL)
783 return -1;
784 for (i = 0; bss_counters[i].name; i++) {
785 if (strcasecmp(bss_counters[i].name, val) == 0)
786 break;
787 }
788 if (bss_counters[i].name == NULL) {
789 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid field");
790 return 0;
791 }
792 pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_COUNTER,
793 bss_counters[i].num);
794
795 s = open_wlantest();
796 if (s < 0) {
797 send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
798 "available");
799 return 0;
800 }
801 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
802 close(s);
803
804 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
805 if (pos == NULL || len != 4)
806 return -2;
807 snprintf(ret, sizeof(ret), "counter,%u", WPA_GET_BE32(pos));
808 send_resp(dut, conn, SIGMA_COMPLETE, ret);
809 return 0;
810}
811
812
813struct tdls_counters {
814 const char *name;
815 enum wlantest_tdls_counter num;
816};
817
818static const struct tdls_counters tdls_counters[] = {
819 { "valid_direct_link", WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK },
820 { "invalid_direct_link", WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK },
821 { "valid_ap_path", WLANTEST_TDLS_COUNTER_VALID_AP_PATH },
822 { "invalid_ap_path", WLANTEST_TDLS_COUNTER_INVALID_AP_PATH },
823 { "setup_req", WLANTEST_TDLS_COUNTER_SETUP_REQ },
824 { "setup_resp_ok", WLANTEST_TDLS_COUNTER_SETUP_RESP_OK },
825 { "setup_resp_fail", WLANTEST_TDLS_COUNTER_SETUP_RESP_FAIL },
826 { "setup_conf_ok", WLANTEST_TDLS_COUNTER_SETUP_CONF_OK },
827 { "setup_conf_fail", WLANTEST_TDLS_COUNTER_SETUP_CONF_FAIL },
828 { "teardown", WLANTEST_TDLS_COUNTER_TEARDOWN },
829 { NULL, 0 }
830};
831
832static int cmd_wlantest_get_tdls_counter(struct sigma_dut *dut,
833 struct sigma_conn *conn,
834 struct sigma_cmd *cmd)
835{
836 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
837 u8 buf[100], *end, *pos;
838 int rlen;
839 const char *val;
840 int s, i;
841 char ret[100];
842 size_t len;
843
844 pos = buf;
845 end = buf + sizeof(buf);
846 WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_TDLS_COUNTER);
847 pos += 4;
848
849 val = get_param(cmd, "bssid");
850 if (val == NULL)
851 return -1;
852 if (val) {
853 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
854 if (hwaddr_aton(val, pos) < 0) {
855 send_resp(dut, conn, SIGMA_INVALID,
856 "errorCode,Invalid bssid");
857 return 0;
858 }
859 pos += ETH_ALEN;
860 }
861
862 val = get_param(cmd, "stationID");
863 if (val == NULL)
864 return -1;
865 if (val) {
866 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
867 if (hwaddr_aton(val, pos) < 0) {
868 send_resp(dut, conn, SIGMA_INVALID,
869 "errorCode,Invalid stationID");
870 return 0;
871 }
872 pos += ETH_ALEN;
873 }
874
875 val = get_param(cmd, "stationID2");
876 if (val == NULL)
877 return -1;
878 if (val) {
879 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA2_ADDR,
880 ETH_ALEN);
881 if (hwaddr_aton(val, pos) < 0) {
882 send_resp(dut, conn, SIGMA_INVALID,
883 "errorCode,Invalid stationID");
884 return 0;
885 }
886 pos += ETH_ALEN;
887 }
888
889 val = get_param(cmd, "field");
890 if (val == NULL)
891 return -1;
892 for (i = 0; tdls_counters[i].name; i++) {
893 if (strcasecmp(tdls_counters[i].name, val) == 0)
894 break;
895 }
896 if (tdls_counters[i].name == NULL) {
897 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid field");
898 return 0;
899 }
900 pos = attr_add_be32(pos, end, WLANTEST_ATTR_TDLS_COUNTER,
901 tdls_counters[i].num);
902
903 s = open_wlantest();
904 if (s < 0) {
905 send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
906 "available");
907 return 0;
908 }
909 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
910 close(s);
911
912
913 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
914 if (pos == NULL || len != 4)
915 return -2;
916 snprintf(ret, sizeof(ret), "counter,%u", WPA_GET_BE32(pos));
917 send_resp(dut, conn, SIGMA_COMPLETE, ret);
918 return 0;
919}
920
921
922struct sta_infos {
923 const char *name;
924 enum wlantest_sta_info num;
925};
926
927static const struct sta_infos sta_infos[] = {
928 { "proto", WLANTEST_STA_INFO_PROTO },
929 { "pairwise", WLANTEST_STA_INFO_PAIRWISE },
930 { "key_mgmt", WLANTEST_STA_INFO_KEY_MGMT },
931 { "rsn_capab", WLANTEST_STA_INFO_RSN_CAPAB },
932 { "state", WLANTEST_STA_INFO_STATE },
933 { NULL, 0 }
934};
935
936static int cmd_wlantest_info_sta(struct sigma_dut *dut,
937 struct sigma_conn *conn,
938 struct sigma_cmd *cmd)
939{
940 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
941 u8 buf[100], *end, *pos;
942 int rlen;
943 const char *val;
944 int s, i;
945 char ret[120];
946 size_t len;
947 char info[100];
948
949 pos = buf;
950 end = buf + sizeof(buf);
951 WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_STA);
952 pos += 4;
953
954 val = get_param(cmd, "bssid");
955 if (val == NULL)
956 return -1;
957 if (val) {
958 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
959 if (hwaddr_aton(val, pos) < 0) {
960 send_resp(dut, conn, SIGMA_INVALID,
961 "errorCode,Invalid bssid");
962 return 0;
963 }
964 pos += ETH_ALEN;
965 }
966
967 val = get_param(cmd, "stationID");
968 if (val == NULL)
969 return -1;
970 if (val) {
971 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
972 if (hwaddr_aton(val, pos) < 0) {
973 send_resp(dut, conn, SIGMA_INVALID,
974 "errorCode,Invalid stationID");
975 return 0;
976 }
977 pos += ETH_ALEN;
978 }
979
980 val = get_param(cmd, "field");
981 if (val == NULL)
982 return -1;
983 for (i = 0; sta_infos[i].name; i++) {
984 if (strcasecmp(sta_infos[i].name, val) == 0)
985 break;
986 }
987 if (sta_infos[i].name == NULL) {
988 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid field");
989 return 0;
990 }
991 pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_INFO,
992 sta_infos[i].num);
993
994 s = open_wlantest();
995 if (s < 0) {
996 send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
997 "available");
998 return 0;
999 }
1000 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1001 close(s);
1002
1003
1004 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len);
1005 if (pos == NULL)
1006 return -2;
1007 if (len >= sizeof(info))
1008 len = sizeof(info) - 1;
1009 memcpy(info, pos, len);
1010 info[len] = '\0';
1011 snprintf(ret, sizeof(ret), "info,%s", info);
1012 send_resp(dut, conn, SIGMA_COMPLETE, ret);
1013 return 0;
1014}
1015
1016
1017struct bss_infos {
1018 const char *name;
1019 enum wlantest_bss_info num;
1020};
1021
1022static const struct bss_infos bss_infos[] = {
1023 { "proto", WLANTEST_BSS_INFO_PROTO },
1024 { "pairwise", WLANTEST_BSS_INFO_PAIRWISE },
1025 { "group", WLANTEST_BSS_INFO_GROUP },
1026 { "group_mgmt", WLANTEST_BSS_INFO_GROUP_MGMT },
1027 { "key_mgmt", WLANTEST_BSS_INFO_KEY_MGMT },
1028 { "rsn_capab", WLANTEST_BSS_INFO_RSN_CAPAB },
1029 { NULL, 0 }
1030};
1031
1032static int cmd_wlantest_info_bss(struct sigma_dut *dut,
1033 struct sigma_conn *conn,
1034 struct sigma_cmd *cmd)
1035{
1036 u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1037 u8 buf[100], *end, *pos;
1038 int rlen;
1039 const char *val;
1040 int s, i;
1041 char ret[120];
1042 size_t len;
1043 char info[100];
1044
1045 pos = buf;
1046 end = buf + sizeof(buf);
1047 WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_BSS);
1048 pos += 4;
1049
1050 val = get_param(cmd, "bssid");
1051 if (val == NULL)
1052 return -1;
1053 if (val) {
1054 pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1055 if (hwaddr_aton(val, pos) < 0) {
1056 send_resp(dut, conn, SIGMA_INVALID,
1057 "errorCode,Invalid bssid");
1058 return 0;
1059 }
1060 pos += ETH_ALEN;
1061 }
1062
1063 val = get_param(cmd, "field");
1064 if (val == NULL)
1065 return -1;
1066 for (i = 0; bss_infos[i].name; i++) {
1067 if (strcasecmp(bss_infos[i].name, val) == 0)
1068 break;
1069 }
1070 if (bss_infos[i].name == NULL) {
1071 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid field");
1072 return 0;
1073 }
1074 pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_INFO,
1075 bss_infos[i].num);
1076
1077 s = open_wlantest();
1078 if (s < 0) {
1079 send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
1080 "available");
1081 return 0;
1082 }
1083 rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1084 close(s);
1085
1086
1087 pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len);
1088 if (pos == NULL)
1089 return -2;
1090 if (len >= sizeof(info))
1091 len = sizeof(info) - 1;
1092 memcpy(info, pos, len);
1093 info[len] = '\0';
1094 snprintf(ret, sizeof(ret), "info,%s", info);
1095 send_resp(dut, conn, SIGMA_COMPLETE, ret);
1096 return 0;
1097}
1098
1099
1100void wlantest_register_cmds(void)
1101{
1102 sigma_dut_reg_cmd("wlantest_version", NULL, cmd_wlantest_version);
1103 sigma_dut_reg_cmd("wlantest_set_channel", NULL,
1104 cmd_wlantest_set_channel);
1105 sigma_dut_reg_cmd("wlantest_flush", NULL, cmd_wlantest_flush);
1106 sigma_dut_reg_cmd("wlantest_send_frame", NULL,
1107 cmd_wlantest_send_frame);
1108 sigma_dut_reg_cmd("wlantest_add_passphrase", NULL,
1109 cmd_wlantest_add_passphrase);
1110 sigma_dut_reg_cmd("wlantest_clear_sta_counters", NULL,
1111 cmd_wlantest_clear_sta_counters);
1112 sigma_dut_reg_cmd("wlantest_clear_bss_counters", NULL,
1113 cmd_wlantest_clear_bss_counters);
1114 sigma_dut_reg_cmd("wlantest_clear_tdls_counters", NULL,
1115 cmd_wlantest_clear_tdls_counters);
1116 sigma_dut_reg_cmd("wlantest_get_sta_counter", NULL,
1117 cmd_wlantest_get_sta_counter);
1118 sigma_dut_reg_cmd("wlantest_get_bss_counter", NULL,
1119 cmd_wlantest_get_bss_counter);
1120 sigma_dut_reg_cmd("wlantest_get_tdls_counter", NULL,
1121 cmd_wlantest_get_tdls_counter);
1122 sigma_dut_reg_cmd("wlantest_info_sta", NULL, cmd_wlantest_info_sta);
1123 sigma_dut_reg_cmd("wlantest_info_bss", NULL, cmd_wlantest_info_bss);
1124}