wlantest_cli.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /*
  2. * wlantest controller
  3. * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "utils/includes.h"
  15. #include <sys/un.h>
  16. #include "utils/common.h"
  17. #include "wlantest_ctrl.h"
  18. static u8 * attr_get(u8 *buf, size_t buflen, enum wlantest_ctrl_attr attr,
  19. size_t *len)
  20. {
  21. u8 *pos = buf;
  22. while (pos + 8 <= buf + buflen) {
  23. enum wlantest_ctrl_attr a;
  24. size_t alen;
  25. a = WPA_GET_BE32(pos);
  26. pos += 4;
  27. alen = WPA_GET_BE32(pos);
  28. pos += 4;
  29. if (pos + alen > buf + buflen) {
  30. printf("Invalid control message attribute\n");
  31. return NULL;
  32. }
  33. if (a == attr) {
  34. *len = alen;
  35. return pos;
  36. }
  37. pos += alen;
  38. }
  39. return NULL;
  40. }
  41. static u8 * attr_hdr_add(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
  42. size_t len)
  43. {
  44. if (pos == NULL || end - pos < 8 + len)
  45. return NULL;
  46. WPA_PUT_BE32(pos, attr);
  47. pos += 4;
  48. WPA_PUT_BE32(pos, len);
  49. pos += 4;
  50. return pos;
  51. }
  52. static u8 * attr_add_str(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
  53. const char *str)
  54. {
  55. size_t len = os_strlen(str);
  56. if (pos == NULL || end - pos < 8 + len)
  57. return NULL;
  58. WPA_PUT_BE32(pos, attr);
  59. pos += 4;
  60. WPA_PUT_BE32(pos, len);
  61. pos += 4;
  62. os_memcpy(pos, str, len);
  63. pos += len;
  64. return pos;
  65. }
  66. static u8 * attr_add_be32(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
  67. u32 val)
  68. {
  69. if (pos == NULL || end - pos < 12)
  70. return NULL;
  71. WPA_PUT_BE32(pos, attr);
  72. pos += 4;
  73. WPA_PUT_BE32(pos, 4);
  74. pos += 4;
  75. WPA_PUT_BE32(pos, val);
  76. pos += 4;
  77. return pos;
  78. }
  79. static int cmd_send_and_recv(int s, const u8 *cmd, size_t cmd_len,
  80. u8 *resp, size_t max_resp_len)
  81. {
  82. int res;
  83. enum wlantest_ctrl_cmd cmd_resp;
  84. if (send(s, cmd, cmd_len, 0) < 0)
  85. return -1;
  86. res = recv(s, resp, max_resp_len, 0);
  87. if (res < 4)
  88. return -1;
  89. cmd_resp = WPA_GET_BE32(resp);
  90. if (cmd_resp == WLANTEST_CTRL_SUCCESS)
  91. return res;
  92. if (cmd_resp == WLANTEST_CTRL_UNKNOWN_CMD)
  93. printf("Unknown command\n");
  94. else if (cmd_resp == WLANTEST_CTRL_INVALID_CMD)
  95. printf("Invalid command\n");
  96. return -1;
  97. }
  98. static int cmd_simple(int s, enum wlantest_ctrl_cmd cmd)
  99. {
  100. u8 buf[4];
  101. int res;
  102. WPA_PUT_BE32(buf, cmd);
  103. res = cmd_send_and_recv(s, buf, sizeof(buf), buf, sizeof(buf));
  104. return res < 0 ? -1 : 0;
  105. }
  106. static int cmd_ping(int s, int argc, char *argv[])
  107. {
  108. int res = cmd_simple(s, WLANTEST_CTRL_PING);
  109. if (res == 0)
  110. printf("PONG\n");
  111. return res == 0;
  112. }
  113. static int cmd_terminate(int s, int argc, char *argv[])
  114. {
  115. return cmd_simple(s, WLANTEST_CTRL_TERMINATE);
  116. }
  117. static int cmd_list_bss(int s, int argc, char *argv[])
  118. {
  119. u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
  120. u8 buf[4];
  121. u8 *bssid;
  122. size_t len;
  123. int rlen, i;
  124. WPA_PUT_BE32(buf, WLANTEST_CTRL_LIST_BSS);
  125. rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
  126. if (rlen < 0)
  127. return -1;
  128. bssid = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_BSSID, &len);
  129. if (bssid == NULL)
  130. return -1;
  131. for (i = 0; i < len / ETH_ALEN; i++)
  132. printf(MACSTR " ", MAC2STR(bssid + ETH_ALEN * i));
  133. printf("\n");
  134. return 0;
  135. }
  136. static int cmd_list_sta(int s, int argc, char *argv[])
  137. {
  138. u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
  139. u8 buf[100], *pos;
  140. u8 *addr;
  141. size_t len;
  142. int rlen, i;
  143. if (argc < 1) {
  144. printf("list_sta needs one argument: BSSID\n");
  145. return -1;
  146. }
  147. pos = buf;
  148. WPA_PUT_BE32(pos, WLANTEST_CTRL_LIST_STA);
  149. pos += 4;
  150. WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
  151. pos += 4;
  152. WPA_PUT_BE32(pos, ETH_ALEN);
  153. pos += 4;
  154. if (hwaddr_aton(argv[0], pos) < 0) {
  155. printf("Invalid BSSID '%s'\n", argv[0]);
  156. return -1;
  157. }
  158. pos += ETH_ALEN;
  159. rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
  160. if (rlen < 0)
  161. return -1;
  162. addr = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_STA_ADDR, &len);
  163. if (addr == NULL)
  164. return -1;
  165. for (i = 0; i < len / ETH_ALEN; i++)
  166. printf(MACSTR " ", MAC2STR(addr + ETH_ALEN * i));
  167. printf("\n");
  168. return 0;
  169. }
  170. static int cmd_flush(int s, int argc, char *argv[])
  171. {
  172. return cmd_simple(s, WLANTEST_CTRL_FLUSH);
  173. }
  174. static int cmd_clear_sta_counters(int s, int argc, char *argv[])
  175. {
  176. u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
  177. u8 buf[100], *pos;
  178. int rlen;
  179. if (argc < 2) {
  180. printf("clear_sta_counters needs two arguments: BSSID and "
  181. "STA address\n");
  182. return -1;
  183. }
  184. pos = buf;
  185. WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_STA_COUNTERS);
  186. pos += 4;
  187. WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
  188. pos += 4;
  189. WPA_PUT_BE32(pos, ETH_ALEN);
  190. pos += 4;
  191. if (hwaddr_aton(argv[0], pos) < 0) {
  192. printf("Invalid BSSID '%s'\n", argv[0]);
  193. return -1;
  194. }
  195. pos += ETH_ALEN;
  196. WPA_PUT_BE32(pos, WLANTEST_ATTR_STA_ADDR);
  197. pos += 4;
  198. WPA_PUT_BE32(pos, ETH_ALEN);
  199. pos += 4;
  200. if (hwaddr_aton(argv[1], pos) < 0) {
  201. printf("Invalid STA address '%s'\n", argv[1]);
  202. return -1;
  203. }
  204. pos += ETH_ALEN;
  205. rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
  206. if (rlen < 0)
  207. return -1;
  208. printf("OK\n");
  209. return 0;
  210. }
  211. static int cmd_clear_bss_counters(int s, int argc, char *argv[])
  212. {
  213. u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
  214. u8 buf[100], *pos;
  215. int rlen;
  216. if (argc < 1) {
  217. printf("clear_bss_counters needs one argument: BSSID\n");
  218. return -1;
  219. }
  220. pos = buf;
  221. WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_BSS_COUNTERS);
  222. pos += 4;
  223. WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
  224. pos += 4;
  225. WPA_PUT_BE32(pos, ETH_ALEN);
  226. pos += 4;
  227. if (hwaddr_aton(argv[0], pos) < 0) {
  228. printf("Invalid BSSID '%s'\n", argv[0]);
  229. return -1;
  230. }
  231. pos += ETH_ALEN;
  232. rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
  233. if (rlen < 0)
  234. return -1;
  235. printf("OK\n");
  236. return 0;
  237. }
  238. struct sta_counters {
  239. const char *name;
  240. enum wlantest_sta_counter num;
  241. };
  242. static const struct sta_counters sta_counters[] = {
  243. { "auth_tx", WLANTEST_STA_COUNTER_AUTH_TX },
  244. { "auth_rx", WLANTEST_STA_COUNTER_AUTH_RX },
  245. { "assocreq_tx", WLANTEST_STA_COUNTER_ASSOCREQ_TX },
  246. { "reassocreq_tx", WLANTEST_STA_COUNTER_REASSOCREQ_TX },
  247. { "ptk_learned", WLANTEST_STA_COUNTER_PTK_LEARNED },
  248. { "valid_deauth_tx", WLANTEST_STA_COUNTER_VALID_DEAUTH_TX },
  249. { "valid_deauth_rx", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX },
  250. { "invalid_deauth_tx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX },
  251. { "invalid_deauth_rx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX },
  252. { "valid_disassoc_tx", WLANTEST_STA_COUNTER_VALID_DISASSOC_TX },
  253. { "valid_disassoc_rx", WLANTEST_STA_COUNTER_VALID_DISASSOC_RX },
  254. { "invalid_disassoc_tx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX },
  255. { "invalid_disassoc_rx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX },
  256. { "valid_saqueryreq_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX },
  257. { "valid_saqueryreq_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX },
  258. { "invalid_saqueryreq_tx",
  259. WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX },
  260. { "invalid_saqueryreq_rx",
  261. WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX },
  262. { "valid_saqueryresp_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX },
  263. { "valid_saqueryresp_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX },
  264. { "invalid_saqueryresp_tx",
  265. WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX },
  266. { "invalid_saqueryresp_rx",
  267. WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX },
  268. { NULL, 0 }
  269. };
  270. static int cmd_get_sta_counter(int s, int argc, char *argv[])
  271. {
  272. u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
  273. u8 buf[100], *end, *pos;
  274. int rlen, i;
  275. size_t len;
  276. if (argc != 3) {
  277. printf("get_sta_counter needs at three arguments: "
  278. "counter name, BSSID, and STA address\n");
  279. return -1;
  280. }
  281. pos = buf;
  282. end = buf + sizeof(buf);
  283. WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_STA_COUNTER);
  284. pos += 4;
  285. for (i = 0; sta_counters[i].name; i++) {
  286. if (os_strcasecmp(sta_counters[i].name, argv[0]) == 0)
  287. break;
  288. }
  289. if (sta_counters[i].name == NULL) {
  290. printf("Unknown STA counter '%s'\n", argv[0]);
  291. printf("Counters:");
  292. for (i = 0; sta_counters[i].name; i++)
  293. printf(" %s", sta_counters[i].name);
  294. printf("\n");
  295. return -1;
  296. }
  297. pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_COUNTER,
  298. sta_counters[i].num);
  299. pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
  300. if (hwaddr_aton(argv[1], pos) < 0) {
  301. printf("Invalid BSSID '%s'\n", argv[1]);
  302. return -1;
  303. }
  304. pos += ETH_ALEN;
  305. pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
  306. if (hwaddr_aton(argv[2], pos) < 0) {
  307. printf("Invalid STA address '%s'\n", argv[2]);
  308. return -1;
  309. }
  310. pos += ETH_ALEN;
  311. rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
  312. if (rlen < 0)
  313. return -1;
  314. pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
  315. if (pos == NULL || len != 4)
  316. return -1;
  317. printf("%u\n", WPA_GET_BE32(pos));
  318. return 0;
  319. }
  320. struct bss_counters {
  321. const char *name;
  322. enum wlantest_bss_counter num;
  323. };
  324. static const struct bss_counters bss_counters[] = {
  325. { "valid_bip_mmie", WLANTEST_BSS_COUNTER_VALID_BIP_MMIE },
  326. { "invalid_bip_mmie", WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE },
  327. { "missing_bip_mmie", WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE },
  328. { NULL, 0 }
  329. };
  330. static int cmd_get_bss_counter(int s, int argc, char *argv[])
  331. {
  332. u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
  333. u8 buf[100], *end, *pos;
  334. int rlen, i;
  335. size_t len;
  336. if (argc != 2) {
  337. printf("get_bss_counter needs at three arguments: "
  338. "counter name and BSSID\n");
  339. return -1;
  340. }
  341. pos = buf;
  342. end = buf + sizeof(buf);
  343. WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_BSS_COUNTER);
  344. pos += 4;
  345. for (i = 0; bss_counters[i].name; i++) {
  346. if (os_strcasecmp(bss_counters[i].name, argv[0]) == 0)
  347. break;
  348. }
  349. if (bss_counters[i].name == NULL) {
  350. printf("Unknown BSS counter '%s'\n", argv[0]);
  351. printf("Counters:");
  352. for (i = 0; bss_counters[i].name; i++)
  353. printf(" %s", bss_counters[i].name);
  354. printf("\n");
  355. return -1;
  356. }
  357. pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_COUNTER,
  358. bss_counters[i].num);
  359. pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
  360. if (hwaddr_aton(argv[1], pos) < 0) {
  361. printf("Invalid BSSID '%s'\n", argv[1]);
  362. return -1;
  363. }
  364. pos += ETH_ALEN;
  365. rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
  366. if (rlen < 0)
  367. return -1;
  368. pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
  369. if (pos == NULL || len != 4)
  370. return -1;
  371. printf("%u\n", WPA_GET_BE32(pos));
  372. return 0;
  373. }
  374. struct inject_frames {
  375. const char *name;
  376. enum wlantest_inject_frame frame;
  377. };
  378. static const struct inject_frames inject_frames[] = {
  379. { "auth", WLANTEST_FRAME_AUTH },
  380. { "assocreq", WLANTEST_FRAME_ASSOCREQ },
  381. { "reassocreq", WLANTEST_FRAME_REASSOCREQ },
  382. { "deauth", WLANTEST_FRAME_DEAUTH },
  383. { "disassoc", WLANTEST_FRAME_DISASSOC },
  384. { "saqueryreq", WLANTEST_FRAME_SAQUERYREQ },
  385. { NULL, 0 }
  386. };
  387. static int cmd_inject(int s, int argc, char *argv[])
  388. {
  389. u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
  390. u8 buf[100], *end, *pos;
  391. int rlen, i;
  392. enum wlantest_inject_protection prot;
  393. /* <frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff> */
  394. if (argc < 5) {
  395. printf("inject needs five arguments: frame, protection, "
  396. "sender, BSSID, STA/ff:ff:ff:ff:ff:ff\n");
  397. return -1;
  398. }
  399. pos = buf;
  400. end = buf + sizeof(buf);
  401. WPA_PUT_BE32(pos, WLANTEST_CTRL_INJECT);
  402. pos += 4;
  403. for (i = 0; inject_frames[i].name; i++) {
  404. if (os_strcasecmp(inject_frames[i].name, argv[0]) == 0)
  405. break;
  406. }
  407. if (inject_frames[i].name == NULL) {
  408. printf("Unknown inject frame '%s'\n", argv[0]);
  409. printf("Frames:");
  410. for (i = 0; inject_frames[i].name; i++)
  411. printf(" %s", inject_frames[i].name);
  412. printf("\n");
  413. return -1;
  414. }
  415. pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_FRAME,
  416. inject_frames[i].frame);
  417. if (os_strcasecmp(argv[1], "normal") == 0)
  418. prot = WLANTEST_INJECT_NORMAL;
  419. else if (os_strcasecmp(argv[1], "protected") == 0)
  420. prot = WLANTEST_INJECT_PROTECTED;
  421. else if (os_strcasecmp(argv[1], "unprotected") == 0)
  422. prot = WLANTEST_INJECT_UNPROTECTED;
  423. else if (os_strcasecmp(argv[1], "incorrect") == 0)
  424. prot = WLANTEST_INJECT_INCORRECT_KEY;
  425. else {
  426. printf("Unknown protection type '%s'\n", argv[1]);
  427. printf("Protection types: normal protected unprotected "
  428. "incorrect\n");
  429. return -1;
  430. }
  431. pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot);
  432. if (os_strcasecmp(argv[2], "ap") == 0) {
  433. pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
  434. 1);
  435. } else if (os_strcasecmp(argv[2], "sta") == 0) {
  436. pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
  437. 0);
  438. } else {
  439. printf("Unknown sender '%s'\n", argv[2]);
  440. printf("Sender types: ap sta\n");
  441. return -1;
  442. }
  443. pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
  444. if (hwaddr_aton(argv[3], pos) < 0) {
  445. printf("Invalid BSSID '%s'\n", argv[3]);
  446. return -1;
  447. }
  448. pos += ETH_ALEN;
  449. pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
  450. if (hwaddr_aton(argv[4], pos) < 0) {
  451. printf("Invalid STA '%s'\n", argv[4]);
  452. return -1;
  453. }
  454. pos += ETH_ALEN;
  455. rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
  456. if (rlen < 0)
  457. return -1;
  458. printf("OK\n");
  459. return 0;
  460. }
  461. static int cmd_version(int s, int argc, char *argv[])
  462. {
  463. u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
  464. u8 buf[4];
  465. char *version;
  466. size_t len;
  467. int rlen, i;
  468. WPA_PUT_BE32(buf, WLANTEST_CTRL_VERSION);
  469. rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
  470. if (rlen < 0)
  471. return -1;
  472. version = (char *) attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_VERSION,
  473. &len);
  474. if (version == NULL)
  475. return -1;
  476. for (i = 0; i < len; i++)
  477. putchar(version[i]);
  478. printf("\n");
  479. return 0;
  480. }
  481. static int cmd_add_passphrase(int s, int argc, char *argv[])
  482. {
  483. u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
  484. u8 buf[100], *pos, *end;
  485. size_t len;
  486. int rlen;
  487. if (argc < 1) {
  488. printf("add_passphrase needs one argument: passphrase\n");
  489. return -1;
  490. }
  491. len = os_strlen(argv[0]);
  492. if (len < 8 || len > 63) {
  493. printf("Invalid passphrase '%s'\n", argv[0]);
  494. return -1;
  495. }
  496. pos = buf;
  497. end = buf + sizeof(buf);
  498. WPA_PUT_BE32(pos, WLANTEST_CTRL_ADD_PASSPHRASE);
  499. pos += 4;
  500. pos = attr_add_str(pos, end, WLANTEST_ATTR_PASSPHRASE,
  501. argv[0]);
  502. if (argc > 1) {
  503. pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
  504. if (hwaddr_aton(argv[1], pos) < 0) {
  505. printf("Invalid BSSID '%s'\n", argv[3]);
  506. return -1;
  507. }
  508. pos += ETH_ALEN;
  509. }
  510. rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
  511. if (rlen < 0)
  512. return -1;
  513. return 0;
  514. }
  515. struct wlantest_cli_cmd {
  516. const char *cmd;
  517. int (*handler)(int s, int argc, char *argv[]);
  518. const char *usage;
  519. };
  520. static const struct wlantest_cli_cmd wlantest_cli_commands[] = {
  521. { "ping", cmd_ping, "= test connection to wlantest" },
  522. { "terminate", cmd_terminate, "= terminate wlantest" },
  523. { "list_bss", cmd_list_bss, "= get BSS list" },
  524. { "list_sta", cmd_list_sta, "<BSSID> = get STA list" },
  525. { "flush", cmd_flush, "= drop all collected BSS data" },
  526. { "clear_sta_counters", cmd_clear_sta_counters,
  527. "<BSSID> <STA> = clear STA counters" },
  528. { "clear_bss_counters", cmd_clear_bss_counters,
  529. "<BSSID> = clear BSS counters" },
  530. { "get_sta_counter", cmd_get_sta_counter,
  531. "<counter> <BSSID> <STA> = get STA counter value" },
  532. { "get_bss_counter", cmd_get_bss_counter,
  533. "<counter> <BSSID> = get BSS counter value" },
  534. { "inject", cmd_inject,
  535. "<frame> <prot> <sender> <BSSID> <STA/ff:ff:ff:ff:ff:ff>" },
  536. { "version", cmd_version, "= get wlantest version" },
  537. { "add_passphrase", cmd_add_passphrase,
  538. "<passphrase> = add a known passphrase" },
  539. { NULL, NULL, NULL }
  540. };
  541. static int ctrl_command(int s, int argc, char *argv[])
  542. {
  543. const struct wlantest_cli_cmd *cmd, *match = NULL;
  544. int count = 0;
  545. int ret = 0;
  546. for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) {
  547. if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
  548. {
  549. match = cmd;
  550. if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
  551. /* exact match */
  552. count = 1;
  553. break;
  554. }
  555. count++;
  556. }
  557. }
  558. if (count > 1) {
  559. printf("Ambiguous command '%s'; possible commands:", argv[0]);
  560. for (cmd = wlantest_cli_commands; cmd->cmd; cmd++) {
  561. if (os_strncasecmp(cmd->cmd, argv[0],
  562. os_strlen(argv[0])) == 0) {
  563. printf(" %s", cmd->cmd);
  564. }
  565. }
  566. printf("\n");
  567. ret = 1;
  568. } else if (count == 0) {
  569. printf("Unknown command '%s'\n", argv[0]);
  570. ret = 1;
  571. } else {
  572. ret = match->handler(s, argc - 1, &argv[1]);
  573. }
  574. return ret;
  575. }
  576. int main(int argc, char *argv[])
  577. {
  578. int s;
  579. struct sockaddr_un addr;
  580. int ret = 0;
  581. s = socket(AF_UNIX, SOCK_SEQPACKET, 0);
  582. if (s < 0) {
  583. perror("socket");
  584. return -1;
  585. }
  586. os_memset(&addr, 0, sizeof(addr));
  587. addr.sun_family = AF_UNIX;
  588. os_strlcpy(addr.sun_path + 1, WLANTEST_SOCK_NAME,
  589. sizeof(addr.sun_path) - 1);
  590. if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  591. perror("connect");
  592. close(s);
  593. return -1;
  594. }
  595. if (argc > 1) {
  596. ret = ctrl_command(s, argc - 1, &argv[1]);
  597. if (ret < 0)
  598. printf("FAIL\n");
  599. } else {
  600. /* TODO: interactive */
  601. }
  602. close(s);
  603. return ret;
  604. }