wlantest_cli.c 19 KB

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