driver_test.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176
  1. /*
  2. * WPA Supplicant - testing driver interface
  3. * Copyright (c) 2004-2008, 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. /* Make dure we get winsock2.h for Windows build to get sockaddr_storage */
  15. #include "build_config.h"
  16. #ifdef CONFIG_NATIVE_WINDOWS
  17. #include <winsock2.h>
  18. #endif /* CONFIG_NATIVE_WINDOWS */
  19. #include "includes.h"
  20. #ifndef CONFIG_NATIVE_WINDOWS
  21. #include <sys/un.h>
  22. #include <dirent.h>
  23. #include <sys/stat.h>
  24. #define DRIVER_TEST_UNIX
  25. #endif /* CONFIG_NATIVE_WINDOWS */
  26. #include "common.h"
  27. #include "driver.h"
  28. #include "l2_packet/l2_packet.h"
  29. #include "eloop.h"
  30. #include "sha1.h"
  31. #include "ieee802_11_defs.h"
  32. struct wpa_driver_test_data {
  33. void *ctx;
  34. u8 own_addr[ETH_ALEN];
  35. int test_socket;
  36. #ifdef DRIVER_TEST_UNIX
  37. struct sockaddr_un hostapd_addr;
  38. #endif /* DRIVER_TEST_UNIX */
  39. int hostapd_addr_set;
  40. struct sockaddr_in hostapd_addr_udp;
  41. int hostapd_addr_udp_set;
  42. char *own_socket_path;
  43. char *test_dir;
  44. u8 bssid[ETH_ALEN];
  45. u8 ssid[32];
  46. size_t ssid_len;
  47. #define MAX_SCAN_RESULTS 30
  48. struct wpa_scan_res *scanres[MAX_SCAN_RESULTS];
  49. size_t num_scanres;
  50. int use_associnfo;
  51. u8 assoc_wpa_ie[80];
  52. size_t assoc_wpa_ie_len;
  53. int use_mlme;
  54. int associated;
  55. u8 *probe_req_ie;
  56. size_t probe_req_ie_len;
  57. };
  58. static void wpa_driver_test_poll(void *eloop_ctx, void *timeout_ctx)
  59. {
  60. struct wpa_driver_test_data *drv = eloop_ctx;
  61. #ifdef DRIVER_TEST_UNIX
  62. if (drv->associated && drv->hostapd_addr_set) {
  63. struct stat st;
  64. if (stat(drv->hostapd_addr.sun_path, &st) < 0) {
  65. wpa_printf(MSG_DEBUG, "%s: lost connection to AP: %s",
  66. __func__, strerror(errno));
  67. drv->associated = 0;
  68. wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
  69. }
  70. }
  71. #endif /* DRIVER_TEST_UNIX */
  72. eloop_register_timeout(1, 0, wpa_driver_test_poll, drv, NULL);
  73. }
  74. static int wpa_driver_test_set_wpa(void *priv, int enabled)
  75. {
  76. wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
  77. return 0;
  78. }
  79. static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx)
  80. {
  81. wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
  82. wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
  83. }
  84. #ifdef DRIVER_TEST_UNIX
  85. static void wpa_driver_scan_dir(struct wpa_driver_test_data *drv,
  86. const char *path)
  87. {
  88. struct dirent *dent;
  89. DIR *dir;
  90. struct sockaddr_un addr;
  91. char cmd[512], *pos, *end;
  92. int ret;
  93. dir = opendir(path);
  94. if (dir == NULL)
  95. return;
  96. end = cmd + sizeof(cmd);
  97. pos = cmd;
  98. ret = os_snprintf(pos, end - pos, "SCAN " MACSTR,
  99. MAC2STR(drv->own_addr));
  100. if (ret >= 0 && ret < end - pos)
  101. pos += ret;
  102. if (drv->probe_req_ie) {
  103. ret = os_snprintf(pos, end - pos, " ");
  104. if (ret >= 0 && ret < end - pos)
  105. pos += ret;
  106. pos += wpa_snprintf_hex(pos, end - pos, drv->probe_req_ie,
  107. drv->probe_req_ie_len);
  108. }
  109. end[-1] = '\0';
  110. while ((dent = readdir(dir))) {
  111. if (os_strncmp(dent->d_name, "AP-", 3) != 0)
  112. continue;
  113. wpa_printf(MSG_DEBUG, "%s: SCAN %s", __func__, dent->d_name);
  114. os_memset(&addr, 0, sizeof(addr));
  115. addr.sun_family = AF_UNIX;
  116. os_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s",
  117. path, dent->d_name);
  118. if (sendto(drv->test_socket, cmd, os_strlen(cmd), 0,
  119. (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  120. perror("sendto(test_socket)");
  121. }
  122. }
  123. closedir(dir);
  124. }
  125. #endif /* DRIVER_TEST_UNIX */
  126. static int wpa_driver_test_scan(void *priv, const u8 *ssid, size_t ssid_len)
  127. {
  128. struct wpa_driver_test_data *drv = priv;
  129. wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv);
  130. drv->num_scanres = 0;
  131. #ifdef DRIVER_TEST_UNIX
  132. if (drv->test_socket >= 0 && drv->test_dir)
  133. wpa_driver_scan_dir(drv, drv->test_dir);
  134. if (drv->test_socket >= 0 && drv->hostapd_addr_set &&
  135. sendto(drv->test_socket, "SCAN", 4, 0,
  136. (struct sockaddr *) &drv->hostapd_addr,
  137. sizeof(drv->hostapd_addr)) < 0) {
  138. perror("sendto(test_socket)");
  139. }
  140. #endif /* DRIVER_TEST_UNIX */
  141. if (drv->test_socket >= 0 && drv->hostapd_addr_udp_set &&
  142. sendto(drv->test_socket, "SCAN", 4, 0,
  143. (struct sockaddr *) &drv->hostapd_addr_udp,
  144. sizeof(drv->hostapd_addr_udp)) < 0) {
  145. perror("sendto(test_socket)");
  146. }
  147. eloop_cancel_timeout(wpa_driver_test_scan_timeout, drv, drv->ctx);
  148. eloop_register_timeout(1, 0, wpa_driver_test_scan_timeout, drv,
  149. drv->ctx);
  150. return 0;
  151. }
  152. static struct wpa_scan_results * wpa_driver_test_get_scan_results2(void *priv)
  153. {
  154. struct wpa_driver_test_data *drv = priv;
  155. struct wpa_scan_results *res;
  156. size_t i;
  157. res = os_zalloc(sizeof(*res));
  158. if (res == NULL)
  159. return NULL;
  160. res->res = os_zalloc(drv->num_scanres * sizeof(struct wpa_scan_res *));
  161. if (res->res == NULL) {
  162. os_free(res);
  163. return NULL;
  164. }
  165. for (i = 0; i < drv->num_scanres; i++) {
  166. struct wpa_scan_res *r;
  167. if (drv->scanres[i] == NULL)
  168. continue;
  169. r = os_malloc(sizeof(*r) + drv->scanres[i]->ie_len);
  170. if (r == NULL)
  171. break;
  172. os_memcpy(r, drv->scanres[i],
  173. sizeof(*r) + drv->scanres[i]->ie_len);
  174. res->res[res->num++] = r;
  175. }
  176. return res;
  177. }
  178. static int wpa_driver_test_set_key(void *priv, wpa_alg alg, const u8 *addr,
  179. int key_idx, int set_tx,
  180. const u8 *seq, size_t seq_len,
  181. const u8 *key, size_t key_len)
  182. {
  183. wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d",
  184. __func__, priv, alg, key_idx, set_tx);
  185. if (addr) {
  186. wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr));
  187. }
  188. if (seq) {
  189. wpa_hexdump(MSG_DEBUG, " seq", seq, seq_len);
  190. }
  191. if (key) {
  192. wpa_hexdump(MSG_DEBUG, " key", key, key_len);
  193. }
  194. return 0;
  195. }
  196. static int wpa_driver_test_associate(
  197. void *priv, struct wpa_driver_associate_params *params)
  198. {
  199. struct wpa_driver_test_data *drv = priv;
  200. wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
  201. "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
  202. __func__, priv, params->freq, params->pairwise_suite,
  203. params->group_suite, params->key_mgmt_suite,
  204. params->auth_alg, params->mode);
  205. if (params->bssid) {
  206. wpa_printf(MSG_DEBUG, " bssid=" MACSTR,
  207. MAC2STR(params->bssid));
  208. }
  209. if (params->ssid) {
  210. wpa_hexdump_ascii(MSG_DEBUG, " ssid",
  211. params->ssid, params->ssid_len);
  212. }
  213. if (params->wpa_ie) {
  214. wpa_hexdump(MSG_DEBUG, " wpa_ie",
  215. params->wpa_ie, params->wpa_ie_len);
  216. drv->assoc_wpa_ie_len = params->wpa_ie_len;
  217. if (drv->assoc_wpa_ie_len > sizeof(drv->assoc_wpa_ie))
  218. drv->assoc_wpa_ie_len = sizeof(drv->assoc_wpa_ie);
  219. os_memcpy(drv->assoc_wpa_ie, params->wpa_ie,
  220. drv->assoc_wpa_ie_len);
  221. } else
  222. drv->assoc_wpa_ie_len = 0;
  223. #ifdef DRIVER_TEST_UNIX
  224. if (drv->test_dir && params->bssid) {
  225. os_memset(&drv->hostapd_addr, 0, sizeof(drv->hostapd_addr));
  226. drv->hostapd_addr.sun_family = AF_UNIX;
  227. os_snprintf(drv->hostapd_addr.sun_path,
  228. sizeof(drv->hostapd_addr.sun_path),
  229. "%s/AP-" MACSTR,
  230. drv->test_dir, MAC2STR(params->bssid));
  231. drv->hostapd_addr_set = 1;
  232. }
  233. #endif /* DRIVER_TEST_UNIX */
  234. if (drv->test_socket >= 0 &&
  235. (drv->hostapd_addr_set || drv->hostapd_addr_udp_set)) {
  236. char cmd[200], *pos, *end;
  237. int ret;
  238. end = cmd + sizeof(cmd);
  239. pos = cmd;
  240. ret = os_snprintf(pos, end - pos, "ASSOC " MACSTR " ",
  241. MAC2STR(drv->own_addr));
  242. if (ret >= 0 && ret < end - pos)
  243. pos += ret;
  244. pos += wpa_snprintf_hex(pos, end - pos, params->ssid,
  245. params->ssid_len);
  246. ret = os_snprintf(pos, end - pos, " ");
  247. if (ret >= 0 && ret < end - pos)
  248. pos += ret;
  249. pos += wpa_snprintf_hex(pos, end - pos, params->wpa_ie,
  250. params->wpa_ie_len);
  251. end[-1] = '\0';
  252. #ifdef DRIVER_TEST_UNIX
  253. if (drv->hostapd_addr_set &&
  254. sendto(drv->test_socket, cmd, os_strlen(cmd), 0,
  255. (struct sockaddr *) &drv->hostapd_addr,
  256. sizeof(drv->hostapd_addr)) < 0) {
  257. perror("sendto(test_socket)");
  258. return -1;
  259. }
  260. #endif /* DRIVER_TEST_UNIX */
  261. if (drv->hostapd_addr_udp_set &&
  262. sendto(drv->test_socket, cmd, os_strlen(cmd), 0,
  263. (struct sockaddr *) &drv->hostapd_addr_udp,
  264. sizeof(drv->hostapd_addr_udp)) < 0) {
  265. perror("sendto(test_socket)");
  266. return -1;
  267. }
  268. os_memcpy(drv->ssid, params->ssid, params->ssid_len);
  269. drv->ssid_len = params->ssid_len;
  270. } else {
  271. drv->associated = 1;
  272. wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
  273. }
  274. return 0;
  275. }
  276. static int wpa_driver_test_get_bssid(void *priv, u8 *bssid)
  277. {
  278. struct wpa_driver_test_data *drv = priv;
  279. os_memcpy(bssid, drv->bssid, ETH_ALEN);
  280. return 0;
  281. }
  282. static int wpa_driver_test_get_ssid(void *priv, u8 *ssid)
  283. {
  284. struct wpa_driver_test_data *drv = priv;
  285. os_memcpy(ssid, drv->ssid, 32);
  286. return drv->ssid_len;
  287. }
  288. static int wpa_driver_test_send_disassoc(struct wpa_driver_test_data *drv)
  289. {
  290. #ifdef DRIVER_TEST_UNIX
  291. if (drv->test_socket >= 0 &&
  292. sendto(drv->test_socket, "DISASSOC", 8, 0,
  293. (struct sockaddr *) &drv->hostapd_addr,
  294. sizeof(drv->hostapd_addr)) < 0) {
  295. perror("sendto(test_socket)");
  296. return -1;
  297. }
  298. #endif /* DRIVER_TEST_UNIX */
  299. if (drv->test_socket >= 0 && drv->hostapd_addr_udp_set &&
  300. sendto(drv->test_socket, "DISASSOC", 8, 0,
  301. (struct sockaddr *) &drv->hostapd_addr_udp,
  302. sizeof(drv->hostapd_addr_udp)) < 0) {
  303. perror("sendto(test_socket)");
  304. return -1;
  305. }
  306. return 0;
  307. }
  308. static int wpa_driver_test_deauthenticate(void *priv, const u8 *addr,
  309. int reason_code)
  310. {
  311. struct wpa_driver_test_data *drv = priv;
  312. wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
  313. __func__, MAC2STR(addr), reason_code);
  314. os_memset(drv->bssid, 0, ETH_ALEN);
  315. drv->associated = 0;
  316. wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
  317. return wpa_driver_test_send_disassoc(drv);
  318. }
  319. static int wpa_driver_test_disassociate(void *priv, const u8 *addr,
  320. int reason_code)
  321. {
  322. struct wpa_driver_test_data *drv = priv;
  323. wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
  324. __func__, MAC2STR(addr), reason_code);
  325. os_memset(drv->bssid, 0, ETH_ALEN);
  326. drv->associated = 0;
  327. wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
  328. return wpa_driver_test_send_disassoc(drv);
  329. }
  330. static void wpa_driver_test_scanresp(struct wpa_driver_test_data *drv,
  331. struct sockaddr *from,
  332. socklen_t fromlen,
  333. const char *data)
  334. {
  335. struct wpa_scan_res *res;
  336. const char *pos, *pos2;
  337. size_t len;
  338. u8 *ie_pos, *ie_start, *ie_end;
  339. #define MAX_IE_LEN 1000
  340. wpa_printf(MSG_DEBUG, "test_driver: SCANRESP %s", data);
  341. if (drv->num_scanres >= MAX_SCAN_RESULTS) {
  342. wpa_printf(MSG_DEBUG, "test_driver: No room for the new scan "
  343. "result");
  344. return;
  345. }
  346. /* SCANRESP BSSID SSID IEs */
  347. res = os_zalloc(sizeof(*res) + MAX_IE_LEN);
  348. if (res == NULL)
  349. return;
  350. ie_start = ie_pos = (u8 *) (res + 1);
  351. ie_end = ie_pos + MAX_IE_LEN;
  352. if (hwaddr_aton(data, res->bssid)) {
  353. wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in scanres");
  354. os_free(res);
  355. return;
  356. }
  357. pos = data + 17;
  358. while (*pos == ' ')
  359. pos++;
  360. pos2 = os_strchr(pos, ' ');
  361. if (pos2 == NULL) {
  362. wpa_printf(MSG_DEBUG, "test_driver: invalid SSID termination "
  363. "in scanres");
  364. os_free(res);
  365. return;
  366. }
  367. len = (pos2 - pos) / 2;
  368. if (len > 32)
  369. len = 32;
  370. /*
  371. * Generate SSID IE from the SSID field since this IE is not included
  372. * in the main IE field.
  373. */
  374. *ie_pos++ = WLAN_EID_SSID;
  375. *ie_pos++ = len;
  376. if (hexstr2bin(pos, ie_pos, len) < 0) {
  377. wpa_printf(MSG_DEBUG, "test_driver: invalid SSID in scanres");
  378. os_free(res);
  379. return;
  380. }
  381. ie_pos += len;
  382. pos = pos2 + 1;
  383. pos2 = os_strchr(pos, ' ');
  384. if (pos2 == NULL)
  385. len = os_strlen(pos) / 2;
  386. else
  387. len = (pos2 - pos) / 2;
  388. if ((int) len > ie_end - ie_pos)
  389. len = ie_end - ie_pos;
  390. if (hexstr2bin(pos, ie_pos, len) < 0) {
  391. wpa_printf(MSG_DEBUG, "test_driver: invalid IEs in scanres");
  392. os_free(res);
  393. return;
  394. }
  395. ie_pos += len;
  396. res->ie_len = ie_pos - ie_start;
  397. if (pos2) {
  398. pos = pos2 + 1;
  399. while (*pos == ' ')
  400. pos++;
  401. if (os_strncmp(pos, "PRIVACY", 7) == 0)
  402. res->caps |= IEEE80211_CAP_PRIVACY;
  403. }
  404. os_free(drv->scanres[drv->num_scanres]);
  405. drv->scanres[drv->num_scanres++] = res;
  406. }
  407. static void wpa_driver_test_assocresp(struct wpa_driver_test_data *drv,
  408. struct sockaddr *from,
  409. socklen_t fromlen,
  410. const char *data)
  411. {
  412. /* ASSOCRESP BSSID <res> */
  413. if (hwaddr_aton(data, drv->bssid)) {
  414. wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in "
  415. "assocresp");
  416. }
  417. if (drv->use_associnfo) {
  418. union wpa_event_data event;
  419. os_memset(&event, 0, sizeof(event));
  420. event.assoc_info.req_ies = drv->assoc_wpa_ie;
  421. event.assoc_info.req_ies_len = drv->assoc_wpa_ie_len;
  422. wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &event);
  423. }
  424. drv->associated = 1;
  425. wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
  426. }
  427. static void wpa_driver_test_disassoc(struct wpa_driver_test_data *drv,
  428. struct sockaddr *from,
  429. socklen_t fromlen)
  430. {
  431. drv->associated = 0;
  432. wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
  433. }
  434. static void wpa_driver_test_eapol(struct wpa_driver_test_data *drv,
  435. struct sockaddr *from,
  436. socklen_t fromlen,
  437. const u8 *data, size_t data_len)
  438. {
  439. const u8 *src = drv->bssid;
  440. if (data_len > 14) {
  441. /* Skip Ethernet header */
  442. src = data + ETH_ALEN;
  443. data += 14;
  444. data_len -= 14;
  445. }
  446. wpa_supplicant_rx_eapol(drv->ctx, src, data, data_len);
  447. }
  448. static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv,
  449. struct sockaddr *from,
  450. socklen_t fromlen,
  451. const u8 *data, size_t data_len)
  452. {
  453. #ifdef CONFIG_CLIENT_MLME
  454. struct ieee80211_rx_status rx_status;
  455. os_memset(&rx_status, 0, sizeof(rx_status));
  456. wpa_supplicant_sta_rx(drv->ctx, data, data_len, &rx_status);
  457. #endif /* CONFIG_CLIENT_MLME */
  458. }
  459. static void wpa_driver_test_receive_unix(int sock, void *eloop_ctx,
  460. void *sock_ctx)
  461. {
  462. struct wpa_driver_test_data *drv = eloop_ctx;
  463. char *buf;
  464. int res;
  465. struct sockaddr_storage from;
  466. socklen_t fromlen = sizeof(from);
  467. const size_t buflen = 2000;
  468. buf = os_malloc(buflen);
  469. if (buf == NULL)
  470. return;
  471. res = recvfrom(sock, buf, buflen - 1, 0,
  472. (struct sockaddr *) &from, &fromlen);
  473. if (res < 0) {
  474. perror("recvfrom(test_socket)");
  475. os_free(buf);
  476. return;
  477. }
  478. buf[res] = '\0';
  479. wpa_printf(MSG_DEBUG, "test_driver: received %u bytes", res);
  480. if (os_strncmp(buf, "SCANRESP ", 9) == 0) {
  481. wpa_driver_test_scanresp(drv, (struct sockaddr *) &from,
  482. fromlen, buf + 9);
  483. } else if (os_strncmp(buf, "ASSOCRESP ", 10) == 0) {
  484. wpa_driver_test_assocresp(drv, (struct sockaddr *) &from,
  485. fromlen, buf + 10);
  486. } else if (os_strcmp(buf, "DISASSOC") == 0) {
  487. wpa_driver_test_disassoc(drv, (struct sockaddr *) &from,
  488. fromlen);
  489. } else if (os_strcmp(buf, "DEAUTH") == 0) {
  490. wpa_driver_test_disassoc(drv, (struct sockaddr *) &from,
  491. fromlen);
  492. } else if (os_strncmp(buf, "EAPOL ", 6) == 0) {
  493. wpa_driver_test_eapol(drv, (struct sockaddr *) &from, fromlen,
  494. (const u8 *) buf + 6, res - 6);
  495. } else if (os_strncmp(buf, "MLME ", 5) == 0) {
  496. wpa_driver_test_mlme(drv, (struct sockaddr *) &from, fromlen,
  497. (const u8 *) buf + 5, res - 5);
  498. } else {
  499. wpa_hexdump_ascii(MSG_DEBUG, "Unknown test_socket command",
  500. (u8 *) buf, res);
  501. }
  502. os_free(buf);
  503. }
  504. static void * wpa_driver_test_init(void *ctx, const char *ifname)
  505. {
  506. struct wpa_driver_test_data *drv;
  507. drv = os_zalloc(sizeof(*drv));
  508. if (drv == NULL)
  509. return NULL;
  510. drv->ctx = ctx;
  511. drv->test_socket = -1;
  512. /* Set dummy BSSID and SSID for testing. */
  513. drv->bssid[0] = 0x02;
  514. drv->bssid[1] = 0x00;
  515. drv->bssid[2] = 0x00;
  516. drv->bssid[3] = 0x00;
  517. drv->bssid[4] = 0x00;
  518. drv->bssid[5] = 0x01;
  519. os_memcpy(drv->ssid, "test", 5);
  520. drv->ssid_len = 4;
  521. /* Generate a MAC address to help testing with multiple STAs */
  522. drv->own_addr[0] = 0x02; /* locally administered */
  523. sha1_prf((const u8 *) ifname, os_strlen(ifname),
  524. "wpa_supplicant test mac addr generation",
  525. NULL, 0, drv->own_addr + 1, ETH_ALEN - 1);
  526. eloop_register_timeout(1, 0, wpa_driver_test_poll, drv, NULL);
  527. return drv;
  528. }
  529. static void wpa_driver_test_close_test_socket(struct wpa_driver_test_data *drv)
  530. {
  531. if (drv->test_socket >= 0) {
  532. eloop_unregister_read_sock(drv->test_socket);
  533. close(drv->test_socket);
  534. drv->test_socket = -1;
  535. }
  536. if (drv->own_socket_path) {
  537. unlink(drv->own_socket_path);
  538. os_free(drv->own_socket_path);
  539. drv->own_socket_path = NULL;
  540. }
  541. }
  542. static void wpa_driver_test_deinit(void *priv)
  543. {
  544. struct wpa_driver_test_data *drv = priv;
  545. int i;
  546. wpa_driver_test_close_test_socket(drv);
  547. eloop_cancel_timeout(wpa_driver_test_scan_timeout, drv, drv->ctx);
  548. eloop_cancel_timeout(wpa_driver_test_poll, drv, NULL);
  549. os_free(drv->test_dir);
  550. for (i = 0; i < MAX_SCAN_RESULTS; i++)
  551. os_free(drv->scanres[i]);
  552. os_free(drv->probe_req_ie);
  553. os_free(drv);
  554. }
  555. static int wpa_driver_test_attach(struct wpa_driver_test_data *drv,
  556. const char *dir)
  557. {
  558. #ifdef DRIVER_TEST_UNIX
  559. static unsigned int counter = 0;
  560. struct sockaddr_un addr;
  561. size_t len;
  562. os_free(drv->own_socket_path);
  563. if (dir) {
  564. len = os_strlen(dir) + 30;
  565. drv->own_socket_path = os_malloc(len);
  566. if (drv->own_socket_path == NULL)
  567. return -1;
  568. os_snprintf(drv->own_socket_path, len, "%s/STA-" MACSTR,
  569. dir, MAC2STR(drv->own_addr));
  570. } else {
  571. drv->own_socket_path = os_malloc(100);
  572. if (drv->own_socket_path == NULL)
  573. return -1;
  574. os_snprintf(drv->own_socket_path, 100,
  575. "/tmp/wpa_supplicant_test-%d-%d",
  576. getpid(), counter++);
  577. }
  578. drv->test_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
  579. if (drv->test_socket < 0) {
  580. perror("socket(PF_UNIX)");
  581. os_free(drv->own_socket_path);
  582. drv->own_socket_path = NULL;
  583. return -1;
  584. }
  585. os_memset(&addr, 0, sizeof(addr));
  586. addr.sun_family = AF_UNIX;
  587. os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path));
  588. if (bind(drv->test_socket, (struct sockaddr *) &addr,
  589. sizeof(addr)) < 0) {
  590. perror("bind(PF_UNIX)");
  591. close(drv->test_socket);
  592. unlink(drv->own_socket_path);
  593. os_free(drv->own_socket_path);
  594. drv->own_socket_path = NULL;
  595. return -1;
  596. }
  597. eloop_register_read_sock(drv->test_socket,
  598. wpa_driver_test_receive_unix, drv, NULL);
  599. return 0;
  600. #else /* DRIVER_TEST_UNIX */
  601. return -1;
  602. #endif /* DRIVER_TEST_UNIX */
  603. }
  604. static int wpa_driver_test_attach_udp(struct wpa_driver_test_data *drv,
  605. char *dst)
  606. {
  607. char *pos;
  608. pos = os_strchr(dst, ':');
  609. if (pos == NULL)
  610. return -1;
  611. *pos++ = '\0';
  612. wpa_printf(MSG_DEBUG, "%s: addr=%s port=%s", __func__, dst, pos);
  613. drv->test_socket = socket(PF_INET, SOCK_DGRAM, 0);
  614. if (drv->test_socket < 0) {
  615. perror("socket(PF_INET)");
  616. return -1;
  617. }
  618. os_memset(&drv->hostapd_addr_udp, 0, sizeof(drv->hostapd_addr_udp));
  619. drv->hostapd_addr_udp.sin_family = AF_INET;
  620. #if defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ANSI_C_EXTRA)
  621. {
  622. int a[4];
  623. u8 *pos;
  624. sscanf(dst, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]);
  625. pos = (u8 *) &drv->hostapd_addr_udp.sin_addr;
  626. *pos++ = a[0];
  627. *pos++ = a[1];
  628. *pos++ = a[2];
  629. *pos++ = a[3];
  630. }
  631. #else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
  632. inet_aton(dst, &drv->hostapd_addr_udp.sin_addr);
  633. #endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
  634. drv->hostapd_addr_udp.sin_port = htons(atoi(pos));
  635. drv->hostapd_addr_udp_set = 1;
  636. eloop_register_read_sock(drv->test_socket,
  637. wpa_driver_test_receive_unix, drv, NULL);
  638. return 0;
  639. }
  640. static int wpa_driver_test_set_param(void *priv, const char *param)
  641. {
  642. struct wpa_driver_test_data *drv = priv;
  643. const char *pos;
  644. wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
  645. if (param == NULL)
  646. return 0;
  647. wpa_driver_test_close_test_socket(drv);
  648. #ifdef DRIVER_TEST_UNIX
  649. pos = os_strstr(param, "test_socket=");
  650. if (pos) {
  651. const char *pos2;
  652. size_t len;
  653. pos += 12;
  654. pos2 = os_strchr(pos, ' ');
  655. if (pos2)
  656. len = pos2 - pos;
  657. else
  658. len = os_strlen(pos);
  659. if (len > sizeof(drv->hostapd_addr.sun_path))
  660. return -1;
  661. os_memset(&drv->hostapd_addr, 0, sizeof(drv->hostapd_addr));
  662. drv->hostapd_addr.sun_family = AF_UNIX;
  663. os_memcpy(drv->hostapd_addr.sun_path, pos, len);
  664. drv->hostapd_addr_set = 1;
  665. }
  666. #endif /* DRIVER_TEST_UNIX */
  667. pos = os_strstr(param, "test_dir=");
  668. if (pos) {
  669. char *end;
  670. os_free(drv->test_dir);
  671. drv->test_dir = os_strdup(pos + 9);
  672. if (drv->test_dir == NULL)
  673. return -1;
  674. end = os_strchr(drv->test_dir, ' ');
  675. if (end)
  676. *end = '\0';
  677. if (wpa_driver_test_attach(drv, drv->test_dir))
  678. return -1;
  679. } else {
  680. pos = os_strstr(param, "test_udp=");
  681. if (pos) {
  682. char *dst, *epos;
  683. dst = os_strdup(pos + 9);
  684. if (dst == NULL)
  685. return -1;
  686. epos = os_strchr(dst, ' ');
  687. if (epos)
  688. *epos = '\0';
  689. if (wpa_driver_test_attach_udp(drv, dst))
  690. return -1;
  691. os_free(dst);
  692. } else if (wpa_driver_test_attach(drv, NULL))
  693. return -1;
  694. }
  695. if (os_strstr(param, "use_associnfo=1")) {
  696. wpa_printf(MSG_DEBUG, "test_driver: Use AssocInfo events");
  697. drv->use_associnfo = 1;
  698. }
  699. #ifdef CONFIG_CLIENT_MLME
  700. if (os_strstr(param, "use_mlme=1")) {
  701. wpa_printf(MSG_DEBUG, "test_driver: Use internal MLME");
  702. drv->use_mlme = 1;
  703. }
  704. #endif /* CONFIG_CLIENT_MLME */
  705. return 0;
  706. }
  707. static const u8 * wpa_driver_test_get_mac_addr(void *priv)
  708. {
  709. struct wpa_driver_test_data *drv = priv;
  710. wpa_printf(MSG_DEBUG, "%s", __func__);
  711. return drv->own_addr;
  712. }
  713. static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto,
  714. const u8 *data, size_t data_len)
  715. {
  716. struct wpa_driver_test_data *drv = priv;
  717. char *msg;
  718. size_t msg_len;
  719. struct l2_ethhdr eth;
  720. struct sockaddr *addr;
  721. socklen_t alen;
  722. wpa_hexdump(MSG_MSGDUMP, "test_send_eapol TX frame", data, data_len);
  723. os_memset(&eth, 0, sizeof(eth));
  724. os_memcpy(eth.h_dest, dest, ETH_ALEN);
  725. os_memcpy(eth.h_source, drv->own_addr, ETH_ALEN);
  726. eth.h_proto = host_to_be16(proto);
  727. msg_len = 6 + sizeof(eth) + data_len;
  728. msg = os_malloc(msg_len);
  729. if (msg == NULL)
  730. return -1;
  731. os_memcpy(msg, "EAPOL ", 6);
  732. os_memcpy(msg + 6, &eth, sizeof(eth));
  733. os_memcpy(msg + 6 + sizeof(eth), data, data_len);
  734. if (os_memcmp(dest, drv->bssid, ETH_ALEN) == 0 ||
  735. drv->test_dir == NULL) {
  736. if (drv->hostapd_addr_udp_set) {
  737. addr = (struct sockaddr *) &drv->hostapd_addr_udp;
  738. alen = sizeof(drv->hostapd_addr_udp);
  739. } else {
  740. #ifdef DRIVER_TEST_UNIX
  741. addr = (struct sockaddr *) &drv->hostapd_addr;
  742. alen = sizeof(drv->hostapd_addr);
  743. #else /* DRIVER_TEST_UNIX */
  744. os_free(msg);
  745. return -1;
  746. #endif /* DRIVER_TEST_UNIX */
  747. }
  748. } else {
  749. #ifdef DRIVER_TEST_UNIX
  750. struct sockaddr_un addr_un;
  751. struct stat st;
  752. os_memset(&addr_un, 0, sizeof(addr_un));
  753. addr_un.sun_family = AF_UNIX;
  754. os_snprintf(addr_un.sun_path, sizeof(addr_un.sun_path),
  755. "%s/STA-" MACSTR, drv->test_dir, MAC2STR(dest));
  756. if (stat(addr_un.sun_path, &st) < 0) {
  757. os_snprintf(addr_un.sun_path, sizeof(addr_un.sun_path),
  758. "%s/AP-" MACSTR,
  759. drv->test_dir, MAC2STR(dest));
  760. }
  761. addr = (struct sockaddr *) &addr_un;
  762. alen = sizeof(addr_un);
  763. #else /* DRIVER_TEST_UNIX */
  764. os_free(msg);
  765. return -1;
  766. #endif /* DRIVER_TEST_UNIX */
  767. }
  768. if (sendto(drv->test_socket, msg, msg_len, 0, addr, alen) < 0) {
  769. perror("sendmsg(test_socket)");
  770. os_free(msg);
  771. return -1;
  772. }
  773. os_free(msg);
  774. return 0;
  775. }
  776. static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa)
  777. {
  778. struct wpa_driver_test_data *drv = priv;
  779. os_memset(capa, 0, sizeof(*capa));
  780. capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
  781. WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
  782. WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
  783. WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
  784. WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE |
  785. WPA_DRIVER_CAPA_KEY_MGMT_FT |
  786. WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
  787. capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 |
  788. WPA_DRIVER_CAPA_ENC_WEP104 |
  789. WPA_DRIVER_CAPA_ENC_TKIP |
  790. WPA_DRIVER_CAPA_ENC_CCMP;
  791. capa->auth = WPA_DRIVER_AUTH_OPEN |
  792. WPA_DRIVER_AUTH_SHARED |
  793. WPA_DRIVER_AUTH_LEAP;
  794. if (drv->use_mlme)
  795. capa->flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME;
  796. return 0;
  797. }
  798. static int wpa_driver_test_mlme_setprotection(void *priv, const u8 *addr,
  799. int protect_type,
  800. int key_type)
  801. {
  802. wpa_printf(MSG_DEBUG, "%s: protect_type=%d key_type=%d",
  803. __func__, protect_type, key_type);
  804. if (addr) {
  805. wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR,
  806. __func__, MAC2STR(addr));
  807. }
  808. return 0;
  809. }
  810. #ifdef CONFIG_CLIENT_MLME
  811. static struct wpa_hw_modes *
  812. wpa_driver_test_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
  813. {
  814. struct wpa_hw_modes *modes;
  815. *num_modes = 1;
  816. *flags = 0;
  817. modes = os_zalloc(*num_modes * sizeof(struct wpa_hw_modes));
  818. if (modes == NULL)
  819. return NULL;
  820. modes[0].mode = WPA_MODE_IEEE80211G;
  821. modes[0].num_channels = 1;
  822. modes[0].num_rates = 1;
  823. modes[0].channels = os_zalloc(sizeof(struct wpa_channel_data));
  824. modes[0].rates = os_zalloc(sizeof(struct wpa_rate_data));
  825. if (modes[0].channels == NULL || modes[0].rates == NULL) {
  826. wpa_supplicant_sta_free_hw_features(modes, *num_modes);
  827. return NULL;
  828. }
  829. modes[0].channels[0].chan = 1;
  830. modes[0].channels[0].freq = 2412;
  831. modes[0].channels[0].flag = WPA_CHAN_W_SCAN | WPA_CHAN_W_ACTIVE_SCAN;
  832. modes[0].rates[0].rate = 10;
  833. modes[0].rates[0].flags = WPA_RATE_BASIC | WPA_RATE_SUPPORTED |
  834. WPA_RATE_CCK | WPA_RATE_MANDATORY;
  835. return modes;
  836. }
  837. int wpa_driver_test_set_channel(void *priv, wpa_hw_mode phymode, int chan,
  838. int freq)
  839. {
  840. wpa_printf(MSG_DEBUG, "%s: phymode=%d chan=%d freq=%d",
  841. __func__, phymode, chan, freq);
  842. return 0;
  843. }
  844. static int wpa_driver_test_send_mlme(void *priv, const u8 *data,
  845. size_t data_len)
  846. {
  847. struct wpa_driver_test_data *drv = priv;
  848. struct msghdr msg;
  849. struct iovec io[2];
  850. struct sockaddr_un addr;
  851. const u8 *dest;
  852. struct dirent *dent;
  853. DIR *dir;
  854. wpa_hexdump(MSG_MSGDUMP, "test_send_mlme", data, data_len);
  855. if (data_len < 10)
  856. return -1;
  857. dest = data + 4;
  858. io[0].iov_base = "MLME ";
  859. io[0].iov_len = 5;
  860. io[1].iov_base = (u8 *) data;
  861. io[1].iov_len = data_len;
  862. os_memset(&msg, 0, sizeof(msg));
  863. msg.msg_iov = io;
  864. msg.msg_iovlen = 2;
  865. if (os_memcmp(dest, drv->bssid, ETH_ALEN) == 0 ||
  866. drv->test_dir == NULL) {
  867. if (drv->hostapd_addr_udp_set) {
  868. msg.msg_name = &drv->hostapd_addr_udp;
  869. msg.msg_namelen = sizeof(drv->hostapd_addr_udp);
  870. } else {
  871. #ifdef DRIVER_TEST_UNIX
  872. msg.msg_name = &drv->hostapd_addr;
  873. msg.msg_namelen = sizeof(drv->hostapd_addr);
  874. #endif /* DRIVER_TEST_UNIX */
  875. }
  876. } else if (os_memcmp(dest, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
  877. {
  878. dir = opendir(drv->test_dir);
  879. if (dir == NULL)
  880. return -1;
  881. while ((dent = readdir(dir))) {
  882. #ifdef _DIRENT_HAVE_D_TYPE
  883. /* Skip the file if it is not a socket.
  884. * Also accept DT_UNKNOWN (0) in case
  885. * the C library or underlying file
  886. * system does not support d_type. */
  887. if (dent->d_type != DT_SOCK &&
  888. dent->d_type != DT_UNKNOWN)
  889. continue;
  890. #endif /* _DIRENT_HAVE_D_TYPE */
  891. if (os_strcmp(dent->d_name, ".") == 0 ||
  892. os_strcmp(dent->d_name, "..") == 0)
  893. continue;
  894. wpa_printf(MSG_DEBUG, "%s: Send broadcast MLME to %s",
  895. __func__, dent->d_name);
  896. os_memset(&addr, 0, sizeof(addr));
  897. addr.sun_family = AF_UNIX;
  898. os_snprintf(addr.sun_path, sizeof(addr.sun_path),
  899. "%s/%s", drv->test_dir, dent->d_name);
  900. msg.msg_name = &addr;
  901. msg.msg_namelen = sizeof(addr);
  902. if (sendmsg(drv->test_socket, &msg, 0) < 0)
  903. perror("sendmsg(test_socket)");
  904. }
  905. closedir(dir);
  906. return 0;
  907. } else {
  908. struct stat st;
  909. os_memset(&addr, 0, sizeof(addr));
  910. addr.sun_family = AF_UNIX;
  911. os_snprintf(addr.sun_path, sizeof(addr.sun_path),
  912. "%s/AP-" MACSTR, drv->test_dir, MAC2STR(dest));
  913. if (stat(addr.sun_path, &st) < 0) {
  914. os_snprintf(addr.sun_path, sizeof(addr.sun_path),
  915. "%s/STA-" MACSTR,
  916. drv->test_dir, MAC2STR(dest));
  917. }
  918. msg.msg_name = &addr;
  919. msg.msg_namelen = sizeof(addr);
  920. }
  921. if (sendmsg(drv->test_socket, &msg, 0) < 0) {
  922. perror("sendmsg(test_socket)");
  923. return -1;
  924. }
  925. return 0;
  926. }
  927. static int wpa_driver_test_mlme_add_sta(void *priv, const u8 *addr,
  928. const u8 *supp_rates,
  929. size_t supp_rates_len)
  930. {
  931. wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr));
  932. return 0;
  933. }
  934. static int wpa_driver_test_mlme_remove_sta(void *priv, const u8 *addr)
  935. {
  936. wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr));
  937. return 0;
  938. }
  939. int wpa_driver_test_set_ssid(void *priv, const u8 *ssid, size_t ssid_len)
  940. {
  941. wpa_printf(MSG_DEBUG, "%s", __func__);
  942. return 0;
  943. }
  944. int wpa_driver_test_set_bssid(void *priv, const u8 *bssid)
  945. {
  946. wpa_printf(MSG_DEBUG, "%s: bssid=" MACSTR, __func__, MAC2STR(bssid));
  947. return 0;
  948. }
  949. #endif /* CONFIG_CLIENT_MLME */
  950. int wpa_driver_set_probe_req_ie(void *priv, const u8 *ies, size_t ies_len)
  951. {
  952. struct wpa_driver_test_data *drv = priv;
  953. os_free(drv->probe_req_ie);
  954. if (ies) {
  955. drv->probe_req_ie = os_malloc(ies_len);
  956. if (drv->probe_req_ie == NULL) {
  957. drv->probe_req_ie_len = 0;
  958. return -1;
  959. }
  960. os_memcpy(drv->probe_req_ie, ies, ies_len);
  961. drv->probe_req_ie_len = ies_len;
  962. } else {
  963. drv->probe_req_ie = NULL;
  964. drv->probe_req_ie_len = 0;
  965. }
  966. return 0;
  967. }
  968. const struct wpa_driver_ops wpa_driver_test_ops = {
  969. "test",
  970. "wpa_supplicant test driver",
  971. wpa_driver_test_get_bssid,
  972. wpa_driver_test_get_ssid,
  973. wpa_driver_test_set_wpa,
  974. wpa_driver_test_set_key,
  975. wpa_driver_test_init,
  976. wpa_driver_test_deinit,
  977. wpa_driver_test_set_param,
  978. NULL /* set_countermeasures */,
  979. NULL /* set_drop_unencrypted */,
  980. wpa_driver_test_scan,
  981. NULL /* get_scan_results */,
  982. wpa_driver_test_deauthenticate,
  983. wpa_driver_test_disassociate,
  984. wpa_driver_test_associate,
  985. NULL /* set_auth_alg */,
  986. NULL /* add_pmkid */,
  987. NULL /* remove_pmkid */,
  988. NULL /* flush_pmkid */,
  989. wpa_driver_test_get_capa,
  990. NULL /* poll */,
  991. NULL /* get_ifname */,
  992. wpa_driver_test_get_mac_addr,
  993. wpa_driver_test_send_eapol,
  994. NULL /* set_operstate */,
  995. wpa_driver_test_mlme_setprotection,
  996. #ifdef CONFIG_CLIENT_MLME
  997. wpa_driver_test_get_hw_feature_data,
  998. wpa_driver_test_set_channel,
  999. wpa_driver_test_set_ssid,
  1000. wpa_driver_test_set_bssid,
  1001. wpa_driver_test_send_mlme,
  1002. wpa_driver_test_mlme_add_sta,
  1003. wpa_driver_test_mlme_remove_sta,
  1004. #else /* CONFIG_CLIENT_MLME */
  1005. NULL /* get_hw_feature_data */,
  1006. NULL /* set_channel */,
  1007. NULL /* set_ssid */,
  1008. NULL /* set_bssid */,
  1009. NULL /* send_mlme */,
  1010. NULL /* mlme_add_sta */,
  1011. NULL /* mlme_remove_sta */,
  1012. #endif /* CONFIG_CLIENT_MLME */
  1013. NULL /* update_ft_ies */,
  1014. NULL /* send_ft_action */,
  1015. wpa_driver_test_get_scan_results2,
  1016. wpa_driver_set_probe_req_ie,
  1017. NULL /* set_mode */,
  1018. NULL /* set_country */
  1019. };