]> git.ipfire.org Git - thirdparty/hostap.git/blob - src/drivers/driver_test.c
Merge wpa_supplicant and hostapd driver wrapper implementations
[thirdparty/hostap.git] / src / drivers / driver_test.c
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
15 /* Make sure we get winsock2.h for Windows build to get sockaddr_storage */
16 #include "build_config.h"
17 #ifdef CONFIG_NATIVE_WINDOWS
18 #include <winsock2.h>
19 #endif /* CONFIG_NATIVE_WINDOWS */
20
21 #include "includes.h"
22
23 #ifndef CONFIG_NATIVE_WINDOWS
24 #include <sys/un.h>
25 #include <dirent.h>
26 #include <sys/stat.h>
27 #define DRIVER_TEST_UNIX
28 #endif /* CONFIG_NATIVE_WINDOWS */
29
30 #include "common.h"
31 #include "driver.h"
32 #include "l2_packet/l2_packet.h"
33 #include "eloop.h"
34 #include "sha1.h"
35 #include "ieee802_11_defs.h"
36
37
38 #ifdef HOSTAPD
39
40 #include "../../hostapd/hostapd.h"
41 #include "../../hostapd/config.h"
42 #include "../../hostapd/wpa.h"
43 #include "../../hostapd/hw_features.h"
44 #include "../../hostapd/wps_hostapd.h"
45
46
47 struct test_client_socket {
48 struct test_client_socket *next;
49 u8 addr[ETH_ALEN];
50 struct sockaddr_un un;
51 socklen_t unlen;
52 struct test_driver_bss *bss;
53 };
54
55 struct test_driver_bss {
56 struct test_driver_bss *next;
57 char ifname[IFNAMSIZ + 1];
58 u8 bssid[ETH_ALEN];
59 u8 *ie;
60 size_t ielen;
61 u8 *wps_beacon_ie;
62 size_t wps_beacon_ie_len;
63 u8 *wps_probe_resp_ie;
64 size_t wps_probe_resp_ie_len;
65 u8 ssid[32];
66 size_t ssid_len;
67 int privacy;
68 };
69
70 struct test_driver_data {
71 struct hostapd_data *hapd;
72 struct test_client_socket *cli;
73 int test_socket;
74 struct test_driver_bss *bss;
75 char *socket_dir;
76 char *own_socket_path;
77 int udp_port;
78 };
79
80
81 static void test_driver_free_bss(struct test_driver_bss *bss)
82 {
83 free(bss->ie);
84 free(bss->wps_beacon_ie);
85 free(bss->wps_probe_resp_ie);
86 free(bss);
87 }
88
89
90 static void test_driver_free_priv(struct test_driver_data *drv)
91 {
92 struct test_driver_bss *bss, *prev;
93
94 if (drv == NULL)
95 return;
96
97 bss = drv->bss;
98 while (bss) {
99 prev = bss;
100 bss = bss->next;
101 test_driver_free_bss(prev);
102 }
103 free(drv->own_socket_path);
104 free(drv->socket_dir);
105 free(drv);
106 }
107
108
109 static struct test_client_socket *
110 test_driver_get_cli(struct test_driver_data *drv, struct sockaddr_un *from,
111 socklen_t fromlen)
112 {
113 struct test_client_socket *cli = drv->cli;
114
115 while (cli) {
116 if (cli->unlen == fromlen &&
117 strncmp(cli->un.sun_path, from->sun_path,
118 fromlen - sizeof(cli->un.sun_family)) == 0)
119 return cli;
120 cli = cli->next;
121 }
122
123 return NULL;
124 }
125
126
127 static int test_driver_send_eapol(void *priv, const u8 *addr, const u8 *data,
128 size_t data_len, int encrypt,
129 const u8 *own_addr)
130 {
131 struct test_driver_data *drv = priv;
132 struct test_client_socket *cli;
133 struct msghdr msg;
134 struct iovec io[3];
135 struct l2_ethhdr eth;
136
137 if (drv->test_socket < 0)
138 return -1;
139
140 cli = drv->cli;
141 while (cli) {
142 if (memcmp(cli->addr, addr, ETH_ALEN) == 0)
143 break;
144 cli = cli->next;
145 }
146
147 if (!cli) {
148 wpa_printf(MSG_DEBUG, "%s: no destination client entry",
149 __func__);
150 return -1;
151 }
152
153 memcpy(eth.h_dest, addr, ETH_ALEN);
154 memcpy(eth.h_source, own_addr, ETH_ALEN);
155 eth.h_proto = host_to_be16(ETH_P_EAPOL);
156
157 io[0].iov_base = "EAPOL ";
158 io[0].iov_len = 6;
159 io[1].iov_base = &eth;
160 io[1].iov_len = sizeof(eth);
161 io[2].iov_base = (u8 *) data;
162 io[2].iov_len = data_len;
163
164 memset(&msg, 0, sizeof(msg));
165 msg.msg_iov = io;
166 msg.msg_iovlen = 3;
167 msg.msg_name = &cli->un;
168 msg.msg_namelen = cli->unlen;
169 return sendmsg(drv->test_socket, &msg, 0);
170 }
171
172
173 static int test_driver_send_ether(void *priv, const u8 *dst, const u8 *src,
174 u16 proto, const u8 *data, size_t data_len)
175 {
176 struct test_driver_data *drv = priv;
177 struct msghdr msg;
178 struct iovec io[3];
179 struct l2_ethhdr eth;
180 char desttxt[30];
181 struct sockaddr_un addr;
182 struct dirent *dent;
183 DIR *dir;
184 int ret = 0, broadcast = 0, count = 0;
185
186 if (drv->test_socket < 0 || drv->socket_dir == NULL) {
187 wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d "
188 "socket_dir=%p)",
189 __func__, drv->test_socket, drv->socket_dir);
190 return -1;
191 }
192
193 broadcast = memcmp(dst, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0;
194 snprintf(desttxt, sizeof(desttxt), MACSTR, MAC2STR(dst));
195
196 memcpy(eth.h_dest, dst, ETH_ALEN);
197 memcpy(eth.h_source, src, ETH_ALEN);
198 eth.h_proto = host_to_be16(proto);
199
200 io[0].iov_base = "ETHER ";
201 io[0].iov_len = 6;
202 io[1].iov_base = &eth;
203 io[1].iov_len = sizeof(eth);
204 io[2].iov_base = (u8 *) data;
205 io[2].iov_len = data_len;
206
207 memset(&msg, 0, sizeof(msg));
208 msg.msg_iov = io;
209 msg.msg_iovlen = 3;
210
211 dir = opendir(drv->socket_dir);
212 if (dir == NULL) {
213 perror("test_driver: opendir");
214 return -1;
215 }
216 while ((dent = readdir(dir))) {
217 #ifdef _DIRENT_HAVE_D_TYPE
218 /* Skip the file if it is not a socket. Also accept
219 * DT_UNKNOWN (0) in case the C library or underlying file
220 * system does not support d_type. */
221 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
222 continue;
223 #endif /* _DIRENT_HAVE_D_TYPE */
224 if (strcmp(dent->d_name, ".") == 0 ||
225 strcmp(dent->d_name, "..") == 0)
226 continue;
227
228 memset(&addr, 0, sizeof(addr));
229 addr.sun_family = AF_UNIX;
230 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s",
231 drv->socket_dir, dent->d_name);
232
233 if (strcmp(addr.sun_path, drv->own_socket_path) == 0)
234 continue;
235 if (!broadcast && strstr(dent->d_name, desttxt) == NULL)
236 continue;
237
238 wpa_printf(MSG_DEBUG, "%s: Send ether frame to %s",
239 __func__, dent->d_name);
240
241 msg.msg_name = &addr;
242 msg.msg_namelen = sizeof(addr);
243 ret = sendmsg(drv->test_socket, &msg, 0);
244 if (ret < 0)
245 perror("driver_test: sendmsg");
246 count++;
247 }
248 closedir(dir);
249
250 if (!broadcast && count == 0) {
251 wpa_printf(MSG_DEBUG, "%s: Destination " MACSTR " not found",
252 __func__, MAC2STR(dst));
253 return -1;
254 }
255
256 return ret;
257 }
258
259
260 static int test_driver_send_mgmt_frame(void *priv, const void *buf,
261 size_t len, int flags)
262 {
263 struct test_driver_data *drv = priv;
264 struct msghdr msg;
265 struct iovec io[2];
266 const u8 *dest;
267 int ret = 0, broadcast = 0;
268 char desttxt[30];
269 struct sockaddr_un addr;
270 struct dirent *dent;
271 DIR *dir;
272 struct ieee80211_hdr *hdr;
273 u16 fc;
274
275 if (drv->test_socket < 0 || len < 10 || drv->socket_dir == NULL) {
276 wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d len=%lu"
277 " socket_dir=%p)",
278 __func__, drv->test_socket, (unsigned long) len,
279 drv->socket_dir);
280 return -1;
281 }
282
283 dest = buf;
284 dest += 4;
285 broadcast = memcmp(dest, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0;
286 snprintf(desttxt, sizeof(desttxt), MACSTR, MAC2STR(dest));
287
288 io[0].iov_base = "MLME ";
289 io[0].iov_len = 5;
290 io[1].iov_base = (void *) buf;
291 io[1].iov_len = len;
292
293 memset(&msg, 0, sizeof(msg));
294 msg.msg_iov = io;
295 msg.msg_iovlen = 2;
296
297 dir = opendir(drv->socket_dir);
298 if (dir == NULL) {
299 perror("test_driver: opendir");
300 return -1;
301 }
302 while ((dent = readdir(dir))) {
303 #ifdef _DIRENT_HAVE_D_TYPE
304 /* Skip the file if it is not a socket. Also accept
305 * DT_UNKNOWN (0) in case the C library or underlying file
306 * system does not support d_type. */
307 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
308 continue;
309 #endif /* _DIRENT_HAVE_D_TYPE */
310 if (strcmp(dent->d_name, ".") == 0 ||
311 strcmp(dent->d_name, "..") == 0)
312 continue;
313
314 memset(&addr, 0, sizeof(addr));
315 addr.sun_family = AF_UNIX;
316 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s",
317 drv->socket_dir, dent->d_name);
318
319 if (strcmp(addr.sun_path, drv->own_socket_path) == 0)
320 continue;
321 if (!broadcast && strstr(dent->d_name, desttxt) == NULL)
322 continue;
323
324 wpa_printf(MSG_DEBUG, "%s: Send management frame to %s",
325 __func__, dent->d_name);
326
327 msg.msg_name = &addr;
328 msg.msg_namelen = sizeof(addr);
329 ret = sendmsg(drv->test_socket, &msg, 0);
330 if (ret < 0)
331 perror("driver_test: sendmsg");
332 }
333 closedir(dir);
334
335 hdr = (struct ieee80211_hdr *) buf;
336 fc = le_to_host16(hdr->frame_control);
337 hostapd_mgmt_tx_cb(drv->hapd, (u8 *) buf, len, WLAN_FC_GET_STYPE(fc),
338 ret >= 0);
339
340 return ret;
341 }
342
343
344 static void test_driver_scan(struct test_driver_data *drv,
345 struct sockaddr_un *from, socklen_t fromlen,
346 char *data)
347 {
348 char buf[512], *pos, *end;
349 int ret;
350 struct test_driver_bss *bss;
351 u8 sa[ETH_ALEN];
352 u8 ie[512];
353 size_t ielen;
354
355 /* data: optional [ ' ' | STA-addr | ' ' | IEs(hex) ] */
356
357 wpa_printf(MSG_DEBUG, "test_driver: SCAN");
358
359 if (*data) {
360 if (*data != ' ' ||
361 hwaddr_aton(data + 1, sa)) {
362 wpa_printf(MSG_DEBUG, "test_driver: Unexpected SCAN "
363 "command format");
364 return;
365 }
366
367 data += 18;
368 while (*data == ' ')
369 data++;
370 ielen = os_strlen(data) / 2;
371 if (ielen > sizeof(ie))
372 ielen = sizeof(ie);
373 if (hexstr2bin(data, ie, ielen) < 0)
374 ielen = 0;
375
376 wpa_printf(MSG_DEBUG, "test_driver: Scan from " MACSTR,
377 MAC2STR(sa));
378 wpa_hexdump(MSG_MSGDUMP, "test_driver: scan IEs", ie, ielen);
379
380 hostapd_wps_probe_req_rx(drv->hapd, sa, ie, ielen);
381 }
382
383 for (bss = drv->bss; bss; bss = bss->next) {
384 pos = buf;
385 end = buf + sizeof(buf);
386
387 /* reply: SCANRESP BSSID SSID IEs */
388 ret = snprintf(pos, end - pos, "SCANRESP " MACSTR " ",
389 MAC2STR(bss->bssid));
390 if (ret < 0 || ret >= end - pos)
391 return;
392 pos += ret;
393 pos += wpa_snprintf_hex(pos, end - pos,
394 bss->ssid, bss->ssid_len);
395 ret = snprintf(pos, end - pos, " ");
396 if (ret < 0 || ret >= end - pos)
397 return;
398 pos += ret;
399 pos += wpa_snprintf_hex(pos, end - pos, bss->ie, bss->ielen);
400 pos += wpa_snprintf_hex(pos, end - pos, bss->wps_probe_resp_ie,
401 bss->wps_probe_resp_ie_len);
402
403 if (bss->privacy) {
404 ret = snprintf(pos, end - pos, " PRIVACY");
405 if (ret < 0 || ret >= end - pos)
406 return;
407 pos += ret;
408 }
409
410 sendto(drv->test_socket, buf, pos - buf, 0,
411 (struct sockaddr *) from, fromlen);
412 }
413 }
414
415
416 static struct hostapd_data * test_driver_get_hapd(struct test_driver_data *drv,
417 struct test_driver_bss *bss)
418 {
419 struct hostapd_iface *iface = drv->hapd->iface;
420 struct hostapd_data *hapd = NULL;
421 size_t i;
422
423 if (bss == NULL) {
424 wpa_printf(MSG_DEBUG, "%s: bss == NULL", __func__);
425 return NULL;
426 }
427
428 for (i = 0; i < iface->num_bss; i++) {
429 hapd = iface->bss[i];
430 if (memcmp(hapd->own_addr, bss->bssid, ETH_ALEN) == 0)
431 break;
432 }
433 if (i == iface->num_bss) {
434 wpa_printf(MSG_DEBUG, "%s: no matching interface entry found "
435 "for BSSID " MACSTR, __func__, MAC2STR(bss->bssid));
436 return NULL;
437 }
438
439 return hapd;
440 }
441
442
443 static int test_driver_new_sta(struct test_driver_data *drv,
444 struct test_driver_bss *bss, const u8 *addr,
445 const u8 *ie, size_t ielen)
446 {
447 struct hostapd_data *hapd;
448
449 hapd = test_driver_get_hapd(drv, bss);
450 if (hapd == NULL)
451 return -1;
452
453 return hostapd_notif_assoc(hapd, addr, ie, ielen);
454 }
455
456
457 static void test_driver_assoc(struct test_driver_data *drv,
458 struct sockaddr_un *from, socklen_t fromlen,
459 char *data)
460 {
461 struct test_client_socket *cli;
462 u8 ie[256], ssid[32];
463 size_t ielen, ssid_len = 0;
464 char *pos, *pos2, cmd[50];
465 struct test_driver_bss *bss;
466
467 /* data: STA-addr SSID(hex) IEs(hex) */
468
469 cli = os_zalloc(sizeof(*cli));
470 if (cli == NULL)
471 return;
472
473 if (hwaddr_aton(data, cli->addr)) {
474 printf("test_socket: Invalid MAC address '%s' in ASSOC\n",
475 data);
476 free(cli);
477 return;
478 }
479 pos = data + 17;
480 while (*pos == ' ')
481 pos++;
482 pos2 = strchr(pos, ' ');
483 ielen = 0;
484 if (pos2) {
485 ssid_len = (pos2 - pos) / 2;
486 if (hexstr2bin(pos, ssid, ssid_len) < 0) {
487 wpa_printf(MSG_DEBUG, "%s: Invalid SSID", __func__);
488 free(cli);
489 return;
490 }
491 wpa_hexdump_ascii(MSG_DEBUG, "test_driver_assoc: SSID",
492 ssid, ssid_len);
493
494 pos = pos2 + 1;
495 ielen = strlen(pos) / 2;
496 if (ielen > sizeof(ie))
497 ielen = sizeof(ie);
498 if (hexstr2bin(pos, ie, ielen) < 0)
499 ielen = 0;
500 }
501
502 for (bss = drv->bss; bss; bss = bss->next) {
503 if (bss->ssid_len == ssid_len &&
504 memcmp(bss->ssid, ssid, ssid_len) == 0)
505 break;
506 }
507 if (bss == NULL) {
508 wpa_printf(MSG_DEBUG, "%s: No matching SSID found from "
509 "configured BSSes", __func__);
510 free(cli);
511 return;
512 }
513
514 cli->bss = bss;
515 memcpy(&cli->un, from, sizeof(cli->un));
516 cli->unlen = fromlen;
517 cli->next = drv->cli;
518 drv->cli = cli;
519 wpa_hexdump_ascii(MSG_DEBUG, "test_socket: ASSOC sun_path",
520 (const u8 *) cli->un.sun_path,
521 cli->unlen - sizeof(cli->un.sun_family));
522
523 snprintf(cmd, sizeof(cmd), "ASSOCRESP " MACSTR " 0",
524 MAC2STR(bss->bssid));
525 sendto(drv->test_socket, cmd, strlen(cmd), 0,
526 (struct sockaddr *) from, fromlen);
527
528 if (test_driver_new_sta(drv, bss, cli->addr, ie, ielen) < 0) {
529 wpa_printf(MSG_DEBUG, "test_driver: failed to add new STA");
530 }
531 }
532
533
534 static void test_driver_disassoc(struct test_driver_data *drv,
535 struct sockaddr_un *from, socklen_t fromlen)
536 {
537 struct test_client_socket *cli;
538
539 cli = test_driver_get_cli(drv, from, fromlen);
540 if (!cli)
541 return;
542
543 hostapd_notif_disassoc(drv->hapd, cli->addr);
544 }
545
546
547 static void test_driver_eapol(struct test_driver_data *drv,
548 struct sockaddr_un *from, socklen_t fromlen,
549 u8 *data, size_t datalen)
550 {
551 struct test_client_socket *cli;
552 if (datalen > 14) {
553 /* Skip Ethernet header */
554 wpa_printf(MSG_DEBUG, "test_driver: dst=" MACSTR " src="
555 MACSTR " proto=%04x",
556 MAC2STR(data), MAC2STR(data + ETH_ALEN),
557 WPA_GET_BE16(data + 2 * ETH_ALEN));
558 data += 14;
559 datalen -= 14;
560 }
561 cli = test_driver_get_cli(drv, from, fromlen);
562 if (cli) {
563 struct hostapd_data *hapd;
564 hapd = test_driver_get_hapd(drv, cli->bss);
565 if (hapd == NULL)
566 return;
567 hostapd_eapol_receive(hapd, cli->addr, data, datalen);
568 } else {
569 wpa_printf(MSG_DEBUG, "test_socket: EAPOL from unknown "
570 "client");
571 }
572 }
573
574
575 static void test_driver_ether(struct test_driver_data *drv,
576 struct sockaddr_un *from, socklen_t fromlen,
577 u8 *data, size_t datalen)
578 {
579 struct l2_ethhdr *eth;
580
581 if (datalen < sizeof(*eth))
582 return;
583
584 eth = (struct l2_ethhdr *) data;
585 wpa_printf(MSG_DEBUG, "test_driver: RX ETHER dst=" MACSTR " src="
586 MACSTR " proto=%04x",
587 MAC2STR(eth->h_dest), MAC2STR(eth->h_source),
588 be_to_host16(eth->h_proto));
589
590 #ifdef CONFIG_IEEE80211R
591 if (be_to_host16(eth->h_proto) == ETH_P_RRB) {
592 wpa_ft_rrb_rx(drv->hapd->wpa_auth, eth->h_source,
593 data + sizeof(*eth), datalen - sizeof(*eth));
594 }
595 #endif /* CONFIG_IEEE80211R */
596 }
597
598
599 static void test_driver_mlme(struct test_driver_data *drv,
600 struct sockaddr_un *from, socklen_t fromlen,
601 u8 *data, size_t datalen)
602 {
603 struct ieee80211_hdr *hdr;
604 u16 fc;
605
606 hdr = (struct ieee80211_hdr *) data;
607
608 if (test_driver_get_cli(drv, from, fromlen) == NULL && datalen >= 16) {
609 struct test_client_socket *cli;
610 cli = os_zalloc(sizeof(*cli));
611 if (cli == NULL)
612 return;
613 wpa_printf(MSG_DEBUG, "Adding client entry for " MACSTR,
614 MAC2STR(hdr->addr2));
615 memcpy(cli->addr, hdr->addr2, ETH_ALEN);
616 memcpy(&cli->un, from, sizeof(cli->un));
617 cli->unlen = fromlen;
618 cli->next = drv->cli;
619 drv->cli = cli;
620 }
621
622 wpa_hexdump(MSG_MSGDUMP, "test_driver_mlme: received frame",
623 data, datalen);
624 fc = le_to_host16(hdr->frame_control);
625 if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT) {
626 wpa_printf(MSG_ERROR, "%s: received non-mgmt frame",
627 __func__);
628 return;
629 }
630 hostapd_mgmt_rx(drv->hapd, data, datalen, WLAN_FC_GET_STYPE(fc), NULL);
631 }
632
633
634 static void test_driver_receive_unix(int sock, void *eloop_ctx, void *sock_ctx)
635 {
636 struct test_driver_data *drv = eloop_ctx;
637 char buf[2000];
638 int res;
639 struct sockaddr_un from;
640 socklen_t fromlen = sizeof(from);
641
642 res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
643 (struct sockaddr *) &from, &fromlen);
644 if (res < 0) {
645 perror("recvfrom(test_socket)");
646 return;
647 }
648 buf[res] = '\0';
649
650 wpa_printf(MSG_DEBUG, "test_driver: received %u bytes", res);
651
652 if (strncmp(buf, "SCAN", 4) == 0) {
653 test_driver_scan(drv, &from, fromlen, buf + 4);
654 } else if (strncmp(buf, "ASSOC ", 6) == 0) {
655 test_driver_assoc(drv, &from, fromlen, buf + 6);
656 } else if (strcmp(buf, "DISASSOC") == 0) {
657 test_driver_disassoc(drv, &from, fromlen);
658 } else if (strncmp(buf, "EAPOL ", 6) == 0) {
659 test_driver_eapol(drv, &from, fromlen, (u8 *) buf + 6,
660 res - 6);
661 } else if (strncmp(buf, "ETHER ", 6) == 0) {
662 test_driver_ether(drv, &from, fromlen, (u8 *) buf + 6,
663 res - 6);
664 } else if (strncmp(buf, "MLME ", 5) == 0) {
665 test_driver_mlme(drv, &from, fromlen, (u8 *) buf + 5, res - 5);
666 } else {
667 wpa_hexdump_ascii(MSG_DEBUG, "Unknown test_socket command",
668 (u8 *) buf, res);
669 }
670 }
671
672
673 static struct test_driver_bss *
674 test_driver_get_bss(struct test_driver_data *drv, const char *ifname)
675 {
676 struct test_driver_bss *bss;
677
678 for (bss = drv->bss; bss; bss = bss->next) {
679 if (strcmp(bss->ifname, ifname) == 0)
680 return bss;
681 }
682 return NULL;
683 }
684
685
686 static int test_driver_set_generic_elem(const char *ifname, void *priv,
687 const u8 *elem, size_t elem_len)
688 {
689 struct test_driver_data *drv = priv;
690 struct test_driver_bss *bss;
691
692 bss = test_driver_get_bss(drv, ifname);
693 if (bss == NULL)
694 return -1;
695
696 free(bss->ie);
697
698 if (elem == NULL) {
699 bss->ie = NULL;
700 bss->ielen = 0;
701 return 0;
702 }
703
704 bss->ie = malloc(elem_len);
705 if (bss->ie == NULL) {
706 bss->ielen = 0;
707 return -1;
708 }
709
710 memcpy(bss->ie, elem, elem_len);
711 bss->ielen = elem_len;
712 return 0;
713 }
714
715
716 static int test_driver_set_wps_beacon_ie(const char *ifname, void *priv,
717 const u8 *ie, size_t len)
718 {
719 struct test_driver_data *drv = priv;
720 struct test_driver_bss *bss;
721
722 wpa_hexdump(MSG_DEBUG, "test_driver: Beacon WPS IE", ie, len);
723 bss = test_driver_get_bss(drv, ifname);
724 if (bss == NULL)
725 return -1;
726
727 free(bss->wps_beacon_ie);
728
729 if (ie == NULL) {
730 bss->wps_beacon_ie = NULL;
731 bss->wps_beacon_ie_len = 0;
732 return 0;
733 }
734
735 bss->wps_beacon_ie = malloc(len);
736 if (bss->wps_beacon_ie == NULL) {
737 bss->wps_beacon_ie_len = 0;
738 return -1;
739 }
740
741 memcpy(bss->wps_beacon_ie, ie, len);
742 bss->wps_beacon_ie_len = len;
743 return 0;
744 }
745
746
747 static int test_driver_set_wps_probe_resp_ie(const char *ifname, void *priv,
748 const u8 *ie, size_t len)
749 {
750 struct test_driver_data *drv = priv;
751 struct test_driver_bss *bss;
752
753 wpa_hexdump(MSG_DEBUG, "test_driver: ProbeResp WPS IE", ie, len);
754 bss = test_driver_get_bss(drv, ifname);
755 if (bss == NULL)
756 return -1;
757
758 free(bss->wps_probe_resp_ie);
759
760 if (ie == NULL) {
761 bss->wps_probe_resp_ie = NULL;
762 bss->wps_probe_resp_ie_len = 0;
763 return 0;
764 }
765
766 bss->wps_probe_resp_ie = malloc(len);
767 if (bss->wps_probe_resp_ie == NULL) {
768 bss->wps_probe_resp_ie_len = 0;
769 return -1;
770 }
771
772 memcpy(bss->wps_probe_resp_ie, ie, len);
773 bss->wps_probe_resp_ie_len = len;
774 return 0;
775 }
776
777
778 static int test_driver_sta_deauth(void *priv, const u8 *addr, int reason)
779 {
780 struct test_driver_data *drv = priv;
781 struct test_client_socket *cli;
782
783 if (drv->test_socket < 0)
784 return -1;
785
786 cli = drv->cli;
787 while (cli) {
788 if (memcmp(cli->addr, addr, ETH_ALEN) == 0)
789 break;
790 cli = cli->next;
791 }
792
793 if (!cli)
794 return -1;
795
796 return sendto(drv->test_socket, "DEAUTH", 6, 0,
797 (struct sockaddr *) &cli->un, cli->unlen);
798 }
799
800
801 static int test_driver_sta_disassoc(void *priv, const u8 *addr, int reason)
802 {
803 struct test_driver_data *drv = priv;
804 struct test_client_socket *cli;
805
806 if (drv->test_socket < 0)
807 return -1;
808
809 cli = drv->cli;
810 while (cli) {
811 if (memcmp(cli->addr, addr, ETH_ALEN) == 0)
812 break;
813 cli = cli->next;
814 }
815
816 if (!cli)
817 return -1;
818
819 return sendto(drv->test_socket, "DISASSOC", 8, 0,
820 (struct sockaddr *) &cli->un, cli->unlen);
821 }
822
823
824 static struct hostapd_hw_modes *
825 test_driver_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
826 {
827 struct hostapd_hw_modes *modes;
828
829 *num_modes = 3;
830 *flags = 0;
831 modes = os_zalloc(*num_modes * sizeof(struct hostapd_hw_modes));
832 if (modes == NULL)
833 return NULL;
834 modes[0].mode = HOSTAPD_MODE_IEEE80211G;
835 modes[0].num_channels = 1;
836 modes[0].num_rates = 1;
837 modes[0].channels = os_zalloc(sizeof(struct hostapd_channel_data));
838 modes[0].rates = os_zalloc(sizeof(struct hostapd_rate_data));
839 if (modes[0].channels == NULL || modes[0].rates == NULL) {
840 hostapd_free_hw_features(modes, *num_modes);
841 return NULL;
842 }
843 modes[0].channels[0].chan = 1;
844 modes[0].channels[0].freq = 2412;
845 modes[0].channels[0].flag = 0;
846 modes[0].rates[0].rate = 10;
847 modes[0].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED |
848 HOSTAPD_RATE_CCK | HOSTAPD_RATE_MANDATORY;
849
850 modes[1].mode = HOSTAPD_MODE_IEEE80211B;
851 modes[1].num_channels = 1;
852 modes[1].num_rates = 1;
853 modes[1].channels = os_zalloc(sizeof(struct hostapd_channel_data));
854 modes[1].rates = os_zalloc(sizeof(struct hostapd_rate_data));
855 if (modes[1].channels == NULL || modes[1].rates == NULL) {
856 hostapd_free_hw_features(modes, *num_modes);
857 return NULL;
858 }
859 modes[1].channels[0].chan = 1;
860 modes[1].channels[0].freq = 2412;
861 modes[1].channels[0].flag = 0;
862 modes[1].rates[0].rate = 10;
863 modes[1].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED |
864 HOSTAPD_RATE_CCK | HOSTAPD_RATE_MANDATORY;
865
866 modes[2].mode = HOSTAPD_MODE_IEEE80211A;
867 modes[2].num_channels = 1;
868 modes[2].num_rates = 1;
869 modes[2].channels = os_zalloc(sizeof(struct hostapd_channel_data));
870 modes[2].rates = os_zalloc(sizeof(struct hostapd_rate_data));
871 if (modes[2].channels == NULL || modes[2].rates == NULL) {
872 hostapd_free_hw_features(modes, *num_modes);
873 return NULL;
874 }
875 modes[2].channels[0].chan = 60;
876 modes[2].channels[0].freq = 5300;
877 modes[2].channels[0].flag = 0;
878 modes[2].rates[0].rate = 60;
879 modes[2].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED |
880 HOSTAPD_RATE_MANDATORY;
881
882 return modes;
883 }
884
885
886 static int test_driver_bss_add(void *priv, const char *ifname, const u8 *bssid)
887 {
888 struct test_driver_data *drv = priv;
889 struct test_driver_bss *bss;
890
891 wpa_printf(MSG_DEBUG, "%s(ifname=%s bssid=" MACSTR ")",
892 __func__, ifname, MAC2STR(bssid));
893
894 bss = os_zalloc(sizeof(*bss));
895 if (bss == NULL)
896 return -1;
897
898 os_strlcpy(bss->ifname, ifname, IFNAMSIZ);
899 memcpy(bss->bssid, bssid, ETH_ALEN);
900
901 bss->next = drv->bss;
902 drv->bss = bss;
903
904 return 0;
905 }
906
907
908 static int test_driver_bss_remove(void *priv, const char *ifname)
909 {
910 struct test_driver_data *drv = priv;
911 struct test_driver_bss *bss, *prev;
912 struct test_client_socket *cli, *prev_c;
913
914 wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, ifname);
915
916 for (prev = NULL, bss = drv->bss; bss; prev = bss, bss = bss->next) {
917 if (strcmp(bss->ifname, ifname) != 0)
918 continue;
919
920 if (prev)
921 prev->next = bss->next;
922 else
923 drv->bss = bss->next;
924
925 for (prev_c = NULL, cli = drv->cli; cli;
926 prev_c = cli, cli = cli->next) {
927 if (cli->bss != bss)
928 continue;
929 if (prev_c)
930 prev_c->next = cli->next;
931 else
932 drv->cli = cli->next;
933 free(cli);
934 break;
935 }
936
937 test_driver_free_bss(bss);
938 return 0;
939 }
940
941 return -1;
942 }
943
944
945 static int test_driver_if_add(const char *iface, void *priv,
946 enum hostapd_driver_if_type type, char *ifname,
947 const u8 *addr)
948 {
949 wpa_printf(MSG_DEBUG, "%s(iface=%s type=%d ifname=%s)",
950 __func__, iface, type, ifname);
951 return 0;
952 }
953
954
955 static int test_driver_if_update(void *priv, enum hostapd_driver_if_type type,
956 char *ifname, const u8 *addr)
957 {
958 wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname);
959 return 0;
960 }
961
962
963 static int test_driver_if_remove(void *priv, enum hostapd_driver_if_type type,
964 const char *ifname, const u8 *addr)
965 {
966 wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname);
967 return 0;
968 }
969
970
971 static int test_driver_valid_bss_mask(void *priv, const u8 *addr,
972 const u8 *mask)
973 {
974 return 0;
975 }
976
977
978 static int test_driver_set_ssid(const char *ifname, void *priv, const u8 *buf,
979 int len)
980 {
981 struct test_driver_data *drv = priv;
982 struct test_driver_bss *bss;
983
984 wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, ifname);
985 wpa_hexdump_ascii(MSG_DEBUG, "test_driver_set_ssid: SSID", buf, len);
986
987 for (bss = drv->bss; bss; bss = bss->next) {
988 if (strcmp(bss->ifname, ifname) != 0)
989 continue;
990
991 if (len < 0 || (size_t) len > sizeof(bss->ssid))
992 return -1;
993
994 memcpy(bss->ssid, buf, len);
995 bss->ssid_len = len;
996
997 return 0;
998 }
999
1000 return -1;
1001 }
1002
1003
1004 static int test_driver_set_privacy(const char *ifname, void *priv, int enabled)
1005 {
1006 struct test_driver_data *drv = priv;
1007 struct test_driver_bss *bss;
1008
1009 wpa_printf(MSG_DEBUG, "%s(ifname=%s enabled=%d)",
1010 __func__, ifname, enabled);
1011
1012 for (bss = drv->bss; bss; bss = bss->next) {
1013 if (strcmp(bss->ifname, ifname) != 0)
1014 continue;
1015
1016 bss->privacy = enabled;
1017
1018 return 0;
1019 }
1020
1021 return -1;
1022 }
1023
1024
1025 static int test_driver_set_key(const char *iface, void *priv, wpa_alg alg,
1026 const u8 *addr, int key_idx, int set_tx,
1027 const u8 *seq, size_t seq_len,
1028 const u8 *key, size_t key_len)
1029 {
1030 wpa_printf(MSG_DEBUG, "%s(iface=%s alg=%d idx=%d set_tx=%d)",
1031 __func__, iface, alg, key_idx, set_tx);
1032 if (addr)
1033 wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr));
1034 if (key)
1035 wpa_hexdump_key(MSG_DEBUG, " key", key, key_len);
1036 return 0;
1037 }
1038
1039
1040 static int test_driver_set_sta_vlan(void *priv, const u8 *addr,
1041 const char *ifname, int vlan_id)
1042 {
1043 wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " ifname=%s vlan_id=%d)",
1044 __func__, MAC2STR(addr), ifname, vlan_id);
1045 return 0;
1046 }
1047
1048
1049 static int test_driver_sta_add(const char *ifname, void *priv,
1050 struct hostapd_sta_add_params *params)
1051 {
1052 struct test_driver_data *drv = priv;
1053 struct test_client_socket *cli;
1054 struct test_driver_bss *bss;
1055
1056 wpa_printf(MSG_DEBUG, "%s(ifname=%s addr=" MACSTR " aid=%d "
1057 "capability=0x%x flags=0x%x listen_interval=%d)",
1058 __func__, ifname, MAC2STR(params->addr), params->aid,
1059 params->capability, params->flags,
1060 params->listen_interval);
1061 wpa_hexdump(MSG_DEBUG, "test_driver_sta_add - supp_rates",
1062 params->supp_rates, params->supp_rates_len);
1063
1064 cli = drv->cli;
1065 while (cli) {
1066 if (os_memcmp(cli->addr, params->addr, ETH_ALEN) == 0)
1067 break;
1068 cli = cli->next;
1069 }
1070 if (!cli) {
1071 wpa_printf(MSG_DEBUG, "%s: no matching client entry",
1072 __func__);
1073 return -1;
1074 }
1075
1076 for (bss = drv->bss; bss; bss = bss->next) {
1077 if (strcmp(ifname, bss->ifname) == 0)
1078 break;
1079 }
1080 if (bss == NULL) {
1081 wpa_printf(MSG_DEBUG, "%s: No matching interface found from "
1082 "configured BSSes", __func__);
1083 return -1;
1084 }
1085
1086 cli->bss = bss;
1087
1088 return 0;
1089 }
1090
1091
1092 static void * test_driver_init(struct hostapd_data *hapd)
1093 {
1094 struct test_driver_data *drv;
1095 struct sockaddr_un addr_un;
1096 struct sockaddr_in addr_in;
1097 struct sockaddr *addr;
1098 socklen_t alen;
1099
1100 drv = os_zalloc(sizeof(struct test_driver_data));
1101 if (drv == NULL) {
1102 printf("Could not allocate memory for test driver data\n");
1103 return NULL;
1104 }
1105 drv->bss = os_zalloc(sizeof(*drv->bss));
1106 if (drv->bss == NULL) {
1107 printf("Could not allocate memory for test driver BSS data\n");
1108 free(drv);
1109 return NULL;
1110 }
1111
1112 drv->hapd = hapd;
1113
1114 /* Generate a MAC address to help testing with multiple APs */
1115 hapd->own_addr[0] = 0x02; /* locally administered */
1116 sha1_prf((const u8 *) hapd->conf->iface, strlen(hapd->conf->iface),
1117 "hostapd test bssid generation",
1118 (const u8 *) hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len,
1119 hapd->own_addr + 1, ETH_ALEN - 1);
1120
1121 os_strlcpy(drv->bss->ifname, hapd->conf->iface, IFNAMSIZ);
1122 memcpy(drv->bss->bssid, hapd->own_addr, ETH_ALEN);
1123
1124 if (hapd->conf->test_socket) {
1125 if (strlen(hapd->conf->test_socket) >=
1126 sizeof(addr_un.sun_path)) {
1127 printf("Too long test_socket path\n");
1128 test_driver_free_priv(drv);
1129 return NULL;
1130 }
1131 if (strncmp(hapd->conf->test_socket, "DIR:", 4) == 0) {
1132 size_t len = strlen(hapd->conf->test_socket) + 30;
1133 drv->socket_dir = strdup(hapd->conf->test_socket + 4);
1134 drv->own_socket_path = malloc(len);
1135 if (drv->own_socket_path) {
1136 snprintf(drv->own_socket_path, len,
1137 "%s/AP-" MACSTR,
1138 hapd->conf->test_socket + 4,
1139 MAC2STR(hapd->own_addr));
1140 }
1141 } else if (strncmp(hapd->conf->test_socket, "UDP:", 4) == 0) {
1142 drv->udp_port = atoi(hapd->conf->test_socket + 4);
1143 } else {
1144 drv->own_socket_path = strdup(hapd->conf->test_socket);
1145 }
1146 if (drv->own_socket_path == NULL && drv->udp_port == 0) {
1147 test_driver_free_priv(drv);
1148 return NULL;
1149 }
1150
1151 drv->test_socket = socket(drv->udp_port ? PF_INET : PF_UNIX,
1152 SOCK_DGRAM, 0);
1153 if (drv->test_socket < 0) {
1154 perror("socket");
1155 test_driver_free_priv(drv);
1156 return NULL;
1157 }
1158
1159 if (drv->udp_port) {
1160 os_memset(&addr_in, 0, sizeof(addr_in));
1161 addr_in.sin_family = AF_INET;
1162 addr_in.sin_port = htons(drv->udp_port);
1163 addr = (struct sockaddr *) &addr_in;
1164 alen = sizeof(addr_in);
1165 } else {
1166 os_memset(&addr_un, 0, sizeof(addr_un));
1167 addr_un.sun_family = AF_UNIX;
1168 os_strlcpy(addr_un.sun_path, drv->own_socket_path,
1169 sizeof(addr_un.sun_path));
1170 addr = (struct sockaddr *) &addr_un;
1171 alen = sizeof(addr_un);
1172 }
1173 if (bind(drv->test_socket, addr, alen) < 0) {
1174 perror("bind(PF_UNIX)");
1175 close(drv->test_socket);
1176 if (drv->own_socket_path)
1177 unlink(drv->own_socket_path);
1178 test_driver_free_priv(drv);
1179 return NULL;
1180 }
1181 eloop_register_read_sock(drv->test_socket,
1182 test_driver_receive_unix, drv, NULL);
1183 } else
1184 drv->test_socket = -1;
1185
1186 return drv;
1187 }
1188
1189
1190 static void test_driver_deinit(void *priv)
1191 {
1192 struct test_driver_data *drv = priv;
1193 struct test_client_socket *cli, *prev;
1194
1195 cli = drv->cli;
1196 while (cli) {
1197 prev = cli;
1198 cli = cli->next;
1199 free(prev);
1200 }
1201
1202 if (drv->test_socket >= 0) {
1203 eloop_unregister_read_sock(drv->test_socket);
1204 close(drv->test_socket);
1205 if (drv->own_socket_path)
1206 unlink(drv->own_socket_path);
1207 }
1208
1209 /* There should be only one BSS remaining at this point. */
1210 if (drv->bss == NULL)
1211 wpa_printf(MSG_ERROR, "%s: drv->bss == NULL", __func__);
1212 else if (drv->bss->next)
1213 wpa_printf(MSG_ERROR, "%s: drv->bss->next != NULL", __func__);
1214
1215 test_driver_free_priv(drv);
1216 }
1217
1218
1219 const struct wpa_driver_ops wpa_driver_test_ops = {
1220 .name = "test",
1221 .hapd_init = test_driver_init,
1222 .hapd_deinit = test_driver_deinit,
1223 .hapd_send_eapol = test_driver_send_eapol,
1224 .send_mgmt_frame = test_driver_send_mgmt_frame,
1225 .set_generic_elem = test_driver_set_generic_elem,
1226 .sta_deauth = test_driver_sta_deauth,
1227 .sta_disassoc = test_driver_sta_disassoc,
1228 .get_hw_feature_data = test_driver_get_hw_feature_data,
1229 .bss_add = test_driver_bss_add,
1230 .bss_remove = test_driver_bss_remove,
1231 .if_add = test_driver_if_add,
1232 .if_update = test_driver_if_update,
1233 .if_remove = test_driver_if_remove,
1234 .valid_bss_mask = test_driver_valid_bss_mask,
1235 .hapd_set_ssid = test_driver_set_ssid,
1236 .set_privacy = test_driver_set_privacy,
1237 .hapd_set_key = test_driver_set_key,
1238 .set_sta_vlan = test_driver_set_sta_vlan,
1239 .sta_add = test_driver_sta_add,
1240 .send_ether = test_driver_send_ether,
1241 .set_wps_beacon_ie = test_driver_set_wps_beacon_ie,
1242 .set_wps_probe_resp_ie = test_driver_set_wps_probe_resp_ie,
1243 };
1244
1245 #else /* HOSTAPD */
1246
1247 struct wpa_driver_test_global {
1248 int dummy;
1249 };
1250
1251 struct wpa_driver_test_data {
1252 struct wpa_driver_test_global *global;
1253 void *ctx;
1254 u8 own_addr[ETH_ALEN];
1255 int test_socket;
1256 #ifdef DRIVER_TEST_UNIX
1257 struct sockaddr_un hostapd_addr;
1258 #endif /* DRIVER_TEST_UNIX */
1259 int hostapd_addr_set;
1260 struct sockaddr_in hostapd_addr_udp;
1261 int hostapd_addr_udp_set;
1262 char *own_socket_path;
1263 char *test_dir;
1264 u8 bssid[ETH_ALEN];
1265 u8 ssid[32];
1266 size_t ssid_len;
1267 #define MAX_SCAN_RESULTS 30
1268 struct wpa_scan_res *scanres[MAX_SCAN_RESULTS];
1269 size_t num_scanres;
1270 int use_associnfo;
1271 u8 assoc_wpa_ie[80];
1272 size_t assoc_wpa_ie_len;
1273 int use_mlme;
1274 int associated;
1275 u8 *probe_req_ie;
1276 size_t probe_req_ie_len;
1277 int ibss;
1278 int privacy;
1279 };
1280
1281
1282 static void wpa_driver_test_poll(void *eloop_ctx, void *timeout_ctx)
1283 {
1284 struct wpa_driver_test_data *drv = eloop_ctx;
1285
1286 #ifdef DRIVER_TEST_UNIX
1287 if (drv->associated && drv->hostapd_addr_set) {
1288 struct stat st;
1289 if (stat(drv->hostapd_addr.sun_path, &st) < 0) {
1290 wpa_printf(MSG_DEBUG, "%s: lost connection to AP: %s",
1291 __func__, strerror(errno));
1292 drv->associated = 0;
1293 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
1294 }
1295 }
1296 #endif /* DRIVER_TEST_UNIX */
1297
1298 eloop_register_timeout(1, 0, wpa_driver_test_poll, drv, NULL);
1299 }
1300
1301
1302 static int wpa_driver_test_set_wpa(void *priv, int enabled)
1303 {
1304 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
1305 return 0;
1306 }
1307
1308
1309 static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx)
1310 {
1311 wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
1312 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
1313 }
1314
1315
1316 #ifdef DRIVER_TEST_UNIX
1317 static void wpa_driver_scan_dir(struct wpa_driver_test_data *drv,
1318 const char *path)
1319 {
1320 struct dirent *dent;
1321 DIR *dir;
1322 struct sockaddr_un addr;
1323 char cmd[512], *pos, *end;
1324 int ret;
1325
1326 dir = opendir(path);
1327 if (dir == NULL)
1328 return;
1329
1330 end = cmd + sizeof(cmd);
1331 pos = cmd;
1332 ret = os_snprintf(pos, end - pos, "SCAN " MACSTR,
1333 MAC2STR(drv->own_addr));
1334 if (ret >= 0 && ret < end - pos)
1335 pos += ret;
1336 if (drv->probe_req_ie) {
1337 ret = os_snprintf(pos, end - pos, " ");
1338 if (ret >= 0 && ret < end - pos)
1339 pos += ret;
1340 pos += wpa_snprintf_hex(pos, end - pos, drv->probe_req_ie,
1341 drv->probe_req_ie_len);
1342 }
1343 end[-1] = '\0';
1344
1345 while ((dent = readdir(dir))) {
1346 if (os_strncmp(dent->d_name, "AP-", 3) != 0 &&
1347 os_strncmp(dent->d_name, "STA-", 4) != 0)
1348 continue;
1349 if (drv->own_socket_path) {
1350 size_t olen, dlen;
1351 olen = os_strlen(drv->own_socket_path);
1352 dlen = os_strlen(dent->d_name);
1353 if (olen >= dlen &&
1354 os_strcmp(dent->d_name,
1355 drv->own_socket_path + olen - dlen) == 0)
1356 continue;
1357 }
1358 wpa_printf(MSG_DEBUG, "%s: SCAN %s", __func__, dent->d_name);
1359
1360 os_memset(&addr, 0, sizeof(addr));
1361 addr.sun_family = AF_UNIX;
1362 os_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s",
1363 path, dent->d_name);
1364
1365 if (sendto(drv->test_socket, cmd, os_strlen(cmd), 0,
1366 (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1367 perror("sendto(test_socket)");
1368 }
1369 }
1370 closedir(dir);
1371 }
1372 #endif /* DRIVER_TEST_UNIX */
1373
1374
1375 static int wpa_driver_test_scan(void *priv,
1376 struct wpa_driver_scan_params *params)
1377 {
1378 struct wpa_driver_test_data *drv = priv;
1379 size_t i;
1380
1381 wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv);
1382 for (i = 0; i < params->num_ssids; i++)
1383 wpa_hexdump(MSG_DEBUG, "Scan SSID",
1384 params->ssids[i].ssid, params->ssids[i].ssid_len);
1385 wpa_hexdump(MSG_DEBUG, "Scan extra IE(s)",
1386 params->extra_ies, params->extra_ies_len);
1387
1388 drv->num_scanres = 0;
1389
1390 #ifdef DRIVER_TEST_UNIX
1391 if (drv->test_socket >= 0 && drv->test_dir)
1392 wpa_driver_scan_dir(drv, drv->test_dir);
1393
1394 if (drv->test_socket >= 0 && drv->hostapd_addr_set &&
1395 sendto(drv->test_socket, "SCAN", 4, 0,
1396 (struct sockaddr *) &drv->hostapd_addr,
1397 sizeof(drv->hostapd_addr)) < 0) {
1398 perror("sendto(test_socket)");
1399 }
1400 #endif /* DRIVER_TEST_UNIX */
1401
1402 if (drv->test_socket >= 0 && drv->hostapd_addr_udp_set &&
1403 sendto(drv->test_socket, "SCAN", 4, 0,
1404 (struct sockaddr *) &drv->hostapd_addr_udp,
1405 sizeof(drv->hostapd_addr_udp)) < 0) {
1406 perror("sendto(test_socket)");
1407 }
1408
1409 eloop_cancel_timeout(wpa_driver_test_scan_timeout, drv, drv->ctx);
1410 eloop_register_timeout(1, 0, wpa_driver_test_scan_timeout, drv,
1411 drv->ctx);
1412 return 0;
1413 }
1414
1415
1416 static struct wpa_scan_results * wpa_driver_test_get_scan_results2(void *priv)
1417 {
1418 struct wpa_driver_test_data *drv = priv;
1419 struct wpa_scan_results *res;
1420 size_t i;
1421
1422 res = os_zalloc(sizeof(*res));
1423 if (res == NULL)
1424 return NULL;
1425
1426 res->res = os_zalloc(drv->num_scanres * sizeof(struct wpa_scan_res *));
1427 if (res->res == NULL) {
1428 os_free(res);
1429 return NULL;
1430 }
1431
1432 for (i = 0; i < drv->num_scanres; i++) {
1433 struct wpa_scan_res *r;
1434 if (drv->scanres[i] == NULL)
1435 continue;
1436 r = os_malloc(sizeof(*r) + drv->scanres[i]->ie_len);
1437 if (r == NULL)
1438 break;
1439 os_memcpy(r, drv->scanres[i],
1440 sizeof(*r) + drv->scanres[i]->ie_len);
1441 res->res[res->num++] = r;
1442 }
1443
1444 return res;
1445 }
1446
1447
1448 static int wpa_driver_test_set_key(void *priv, wpa_alg alg, const u8 *addr,
1449 int key_idx, int set_tx,
1450 const u8 *seq, size_t seq_len,
1451 const u8 *key, size_t key_len)
1452 {
1453 wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d",
1454 __func__, priv, alg, key_idx, set_tx);
1455 if (addr) {
1456 wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr));
1457 }
1458 if (seq) {
1459 wpa_hexdump(MSG_DEBUG, " seq", seq, seq_len);
1460 }
1461 if (key) {
1462 wpa_hexdump(MSG_DEBUG, " key", key, key_len);
1463 }
1464 return 0;
1465 }
1466
1467
1468 static int wpa_driver_test_associate(
1469 void *priv, struct wpa_driver_associate_params *params)
1470 {
1471 struct wpa_driver_test_data *drv = priv;
1472 wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
1473 "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
1474 __func__, priv, params->freq, params->pairwise_suite,
1475 params->group_suite, params->key_mgmt_suite,
1476 params->auth_alg, params->mode);
1477 if (params->bssid) {
1478 wpa_printf(MSG_DEBUG, " bssid=" MACSTR,
1479 MAC2STR(params->bssid));
1480 }
1481 if (params->ssid) {
1482 wpa_hexdump_ascii(MSG_DEBUG, " ssid",
1483 params->ssid, params->ssid_len);
1484 }
1485 if (params->wpa_ie) {
1486 wpa_hexdump(MSG_DEBUG, " wpa_ie",
1487 params->wpa_ie, params->wpa_ie_len);
1488 drv->assoc_wpa_ie_len = params->wpa_ie_len;
1489 if (drv->assoc_wpa_ie_len > sizeof(drv->assoc_wpa_ie))
1490 drv->assoc_wpa_ie_len = sizeof(drv->assoc_wpa_ie);
1491 os_memcpy(drv->assoc_wpa_ie, params->wpa_ie,
1492 drv->assoc_wpa_ie_len);
1493 } else
1494 drv->assoc_wpa_ie_len = 0;
1495
1496 drv->ibss = params->mode == IEEE80211_MODE_IBSS;
1497 drv->privacy = params->key_mgmt_suite &
1498 (WPA_KEY_MGMT_IEEE8021X |
1499 WPA_KEY_MGMT_PSK |
1500 WPA_KEY_MGMT_WPA_NONE |
1501 WPA_KEY_MGMT_FT_IEEE8021X |
1502 WPA_KEY_MGMT_FT_PSK |
1503 WPA_KEY_MGMT_IEEE8021X_SHA256 |
1504 WPA_KEY_MGMT_PSK_SHA256);
1505 if (params->wep_key_len[params->wep_tx_keyidx])
1506 drv->privacy = 1;
1507
1508 #ifdef DRIVER_TEST_UNIX
1509 if (drv->test_dir && params->bssid &&
1510 params->mode != IEEE80211_MODE_IBSS) {
1511 os_memset(&drv->hostapd_addr, 0, sizeof(drv->hostapd_addr));
1512 drv->hostapd_addr.sun_family = AF_UNIX;
1513 os_snprintf(drv->hostapd_addr.sun_path,
1514 sizeof(drv->hostapd_addr.sun_path),
1515 "%s/AP-" MACSTR,
1516 drv->test_dir, MAC2STR(params->bssid));
1517 drv->hostapd_addr_set = 1;
1518 }
1519 #endif /* DRIVER_TEST_UNIX */
1520
1521 if (drv->test_socket >= 0 &&
1522 (drv->hostapd_addr_set || drv->hostapd_addr_udp_set)) {
1523 char cmd[200], *pos, *end;
1524 int ret;
1525 end = cmd + sizeof(cmd);
1526 pos = cmd;
1527 ret = os_snprintf(pos, end - pos, "ASSOC " MACSTR " ",
1528 MAC2STR(drv->own_addr));
1529 if (ret >= 0 && ret < end - pos)
1530 pos += ret;
1531 pos += wpa_snprintf_hex(pos, end - pos, params->ssid,
1532 params->ssid_len);
1533 ret = os_snprintf(pos, end - pos, " ");
1534 if (ret >= 0 && ret < end - pos)
1535 pos += ret;
1536 pos += wpa_snprintf_hex(pos, end - pos, params->wpa_ie,
1537 params->wpa_ie_len);
1538 end[-1] = '\0';
1539 #ifdef DRIVER_TEST_UNIX
1540 if (drv->hostapd_addr_set &&
1541 sendto(drv->test_socket, cmd, os_strlen(cmd), 0,
1542 (struct sockaddr *) &drv->hostapd_addr,
1543 sizeof(drv->hostapd_addr)) < 0) {
1544 perror("sendto(test_socket)");
1545 return -1;
1546 }
1547 #endif /* DRIVER_TEST_UNIX */
1548 if (drv->hostapd_addr_udp_set &&
1549 sendto(drv->test_socket, cmd, os_strlen(cmd), 0,
1550 (struct sockaddr *) &drv->hostapd_addr_udp,
1551 sizeof(drv->hostapd_addr_udp)) < 0) {
1552 perror("sendto(test_socket)");
1553 return -1;
1554 }
1555
1556 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
1557 drv->ssid_len = params->ssid_len;
1558 } else {
1559 drv->associated = 1;
1560 if (params->mode == IEEE80211_MODE_IBSS) {
1561 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
1562 drv->ssid_len = params->ssid_len;
1563 if (params->bssid)
1564 os_memcpy(drv->bssid, params->bssid, ETH_ALEN);
1565 else {
1566 os_get_random(drv->bssid, ETH_ALEN);
1567 drv->bssid[0] &= ~0x01;
1568 drv->bssid[0] |= 0x02;
1569 }
1570 }
1571 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
1572 }
1573
1574 return 0;
1575 }
1576
1577
1578 static int wpa_driver_test_get_bssid(void *priv, u8 *bssid)
1579 {
1580 struct wpa_driver_test_data *drv = priv;
1581 os_memcpy(bssid, drv->bssid, ETH_ALEN);
1582 return 0;
1583 }
1584
1585
1586 static int wpa_driver_test_get_ssid(void *priv, u8 *ssid)
1587 {
1588 struct wpa_driver_test_data *drv = priv;
1589 os_memcpy(ssid, drv->ssid, 32);
1590 return drv->ssid_len;
1591 }
1592
1593
1594 static int wpa_driver_test_send_disassoc(struct wpa_driver_test_data *drv)
1595 {
1596 #ifdef DRIVER_TEST_UNIX
1597 if (drv->test_socket >= 0 &&
1598 sendto(drv->test_socket, "DISASSOC", 8, 0,
1599 (struct sockaddr *) &drv->hostapd_addr,
1600 sizeof(drv->hostapd_addr)) < 0) {
1601 perror("sendto(test_socket)");
1602 return -1;
1603 }
1604 #endif /* DRIVER_TEST_UNIX */
1605 if (drv->test_socket >= 0 && drv->hostapd_addr_udp_set &&
1606 sendto(drv->test_socket, "DISASSOC", 8, 0,
1607 (struct sockaddr *) &drv->hostapd_addr_udp,
1608 sizeof(drv->hostapd_addr_udp)) < 0) {
1609 perror("sendto(test_socket)");
1610 return -1;
1611 }
1612 return 0;
1613 }
1614
1615
1616 static int wpa_driver_test_deauthenticate(void *priv, const u8 *addr,
1617 int reason_code)
1618 {
1619 struct wpa_driver_test_data *drv = priv;
1620 wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
1621 __func__, MAC2STR(addr), reason_code);
1622 os_memset(drv->bssid, 0, ETH_ALEN);
1623 drv->associated = 0;
1624 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
1625 return wpa_driver_test_send_disassoc(drv);
1626 }
1627
1628
1629 static int wpa_driver_test_disassociate(void *priv, const u8 *addr,
1630 int reason_code)
1631 {
1632 struct wpa_driver_test_data *drv = priv;
1633 wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
1634 __func__, MAC2STR(addr), reason_code);
1635 os_memset(drv->bssid, 0, ETH_ALEN);
1636 drv->associated = 0;
1637 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
1638 return wpa_driver_test_send_disassoc(drv);
1639 }
1640
1641
1642 static void wpa_driver_test_scanresp(struct wpa_driver_test_data *drv,
1643 struct sockaddr *from,
1644 socklen_t fromlen,
1645 const char *data)
1646 {
1647 struct wpa_scan_res *res;
1648 const char *pos, *pos2;
1649 size_t len;
1650 u8 *ie_pos, *ie_start, *ie_end;
1651 #define MAX_IE_LEN 1000
1652
1653 wpa_printf(MSG_DEBUG, "test_driver: SCANRESP %s", data);
1654 if (drv->num_scanres >= MAX_SCAN_RESULTS) {
1655 wpa_printf(MSG_DEBUG, "test_driver: No room for the new scan "
1656 "result");
1657 return;
1658 }
1659
1660 /* SCANRESP BSSID SSID IEs */
1661
1662 res = os_zalloc(sizeof(*res) + MAX_IE_LEN);
1663 if (res == NULL)
1664 return;
1665 ie_start = ie_pos = (u8 *) (res + 1);
1666 ie_end = ie_pos + MAX_IE_LEN;
1667
1668 if (hwaddr_aton(data, res->bssid)) {
1669 wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in scanres");
1670 os_free(res);
1671 return;
1672 }
1673
1674 pos = data + 17;
1675 while (*pos == ' ')
1676 pos++;
1677 pos2 = os_strchr(pos, ' ');
1678 if (pos2 == NULL) {
1679 wpa_printf(MSG_DEBUG, "test_driver: invalid SSID termination "
1680 "in scanres");
1681 os_free(res);
1682 return;
1683 }
1684 len = (pos2 - pos) / 2;
1685 if (len > 32)
1686 len = 32;
1687 /*
1688 * Generate SSID IE from the SSID field since this IE is not included
1689 * in the main IE field.
1690 */
1691 *ie_pos++ = WLAN_EID_SSID;
1692 *ie_pos++ = len;
1693 if (hexstr2bin(pos, ie_pos, len) < 0) {
1694 wpa_printf(MSG_DEBUG, "test_driver: invalid SSID in scanres");
1695 os_free(res);
1696 return;
1697 }
1698 ie_pos += len;
1699
1700 pos = pos2 + 1;
1701 pos2 = os_strchr(pos, ' ');
1702 if (pos2 == NULL)
1703 len = os_strlen(pos) / 2;
1704 else
1705 len = (pos2 - pos) / 2;
1706 if ((int) len > ie_end - ie_pos)
1707 len = ie_end - ie_pos;
1708 if (hexstr2bin(pos, ie_pos, len) < 0) {
1709 wpa_printf(MSG_DEBUG, "test_driver: invalid IEs in scanres");
1710 os_free(res);
1711 return;
1712 }
1713 ie_pos += len;
1714 res->ie_len = ie_pos - ie_start;
1715
1716 if (pos2) {
1717 pos = pos2 + 1;
1718 while (*pos == ' ')
1719 pos++;
1720 if (os_strstr(pos, "PRIVACY"))
1721 res->caps |= IEEE80211_CAP_PRIVACY;
1722 if (os_strstr(pos, "IBSS"))
1723 res->caps |= IEEE80211_CAP_IBSS;
1724 }
1725
1726 os_free(drv->scanres[drv->num_scanres]);
1727 drv->scanres[drv->num_scanres++] = res;
1728 }
1729
1730
1731 static void wpa_driver_test_assocresp(struct wpa_driver_test_data *drv,
1732 struct sockaddr *from,
1733 socklen_t fromlen,
1734 const char *data)
1735 {
1736 /* ASSOCRESP BSSID <res> */
1737 if (hwaddr_aton(data, drv->bssid)) {
1738 wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in "
1739 "assocresp");
1740 }
1741 if (drv->use_associnfo) {
1742 union wpa_event_data event;
1743 os_memset(&event, 0, sizeof(event));
1744 event.assoc_info.req_ies = drv->assoc_wpa_ie;
1745 event.assoc_info.req_ies_len = drv->assoc_wpa_ie_len;
1746 wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &event);
1747 }
1748 drv->associated = 1;
1749 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
1750 }
1751
1752
1753 static void wpa_driver_test_disassoc(struct wpa_driver_test_data *drv,
1754 struct sockaddr *from,
1755 socklen_t fromlen)
1756 {
1757 drv->associated = 0;
1758 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
1759 }
1760
1761
1762 static void wpa_driver_test_eapol(struct wpa_driver_test_data *drv,
1763 struct sockaddr *from,
1764 socklen_t fromlen,
1765 const u8 *data, size_t data_len)
1766 {
1767 const u8 *src = drv->bssid;
1768
1769 if (data_len > 14) {
1770 /* Skip Ethernet header */
1771 src = data + ETH_ALEN;
1772 data += 14;
1773 data_len -= 14;
1774 }
1775 wpa_supplicant_rx_eapol(drv->ctx, src, data, data_len);
1776 }
1777
1778
1779 static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv,
1780 struct sockaddr *from,
1781 socklen_t fromlen,
1782 const u8 *data, size_t data_len)
1783 {
1784 #ifdef CONFIG_CLIENT_MLME
1785 struct ieee80211_rx_status rx_status;
1786 os_memset(&rx_status, 0, sizeof(rx_status));
1787 wpa_supplicant_sta_rx(drv->ctx, data, data_len, &rx_status);
1788 #endif /* CONFIG_CLIENT_MLME */
1789 }
1790
1791
1792 static void wpa_driver_test_scan_cmd(struct wpa_driver_test_data *drv,
1793 struct sockaddr *from,
1794 socklen_t fromlen,
1795 const u8 *data, size_t data_len)
1796 {
1797 char buf[512], *pos, *end;
1798 int ret;
1799
1800 /* data: optional [ STA-addr | ' ' | IEs(hex) ] */
1801
1802 if (!drv->ibss)
1803 return;
1804
1805 pos = buf;
1806 end = buf + sizeof(buf);
1807
1808 /* reply: SCANRESP BSSID SSID IEs */
1809 ret = snprintf(pos, end - pos, "SCANRESP " MACSTR " ",
1810 MAC2STR(drv->bssid));
1811 if (ret < 0 || ret >= end - pos)
1812 return;
1813 pos += ret;
1814 pos += wpa_snprintf_hex(pos, end - pos,
1815 drv->ssid, drv->ssid_len);
1816 ret = snprintf(pos, end - pos, " ");
1817 if (ret < 0 || ret >= end - pos)
1818 return;
1819 pos += ret;
1820 pos += wpa_snprintf_hex(pos, end - pos, drv->assoc_wpa_ie,
1821 drv->assoc_wpa_ie_len);
1822
1823 if (drv->privacy) {
1824 ret = snprintf(pos, end - pos, " PRIVACY");
1825 if (ret < 0 || ret >= end - pos)
1826 return;
1827 pos += ret;
1828 }
1829
1830 ret = snprintf(pos, end - pos, " IBSS");
1831 if (ret < 0 || ret >= end - pos)
1832 return;
1833 pos += ret;
1834
1835 sendto(drv->test_socket, buf, pos - buf, 0,
1836 (struct sockaddr *) from, fromlen);
1837 }
1838
1839
1840 static void wpa_driver_test_receive_unix(int sock, void *eloop_ctx,
1841 void *sock_ctx)
1842 {
1843 struct wpa_driver_test_data *drv = eloop_ctx;
1844 char *buf;
1845 int res;
1846 struct sockaddr_storage from;
1847 socklen_t fromlen = sizeof(from);
1848 const size_t buflen = 2000;
1849
1850 buf = os_malloc(buflen);
1851 if (buf == NULL)
1852 return;
1853 res = recvfrom(sock, buf, buflen - 1, 0,
1854 (struct sockaddr *) &from, &fromlen);
1855 if (res < 0) {
1856 perror("recvfrom(test_socket)");
1857 os_free(buf);
1858 return;
1859 }
1860 buf[res] = '\0';
1861
1862 wpa_printf(MSG_DEBUG, "test_driver: received %u bytes", res);
1863
1864 if (os_strncmp(buf, "SCANRESP ", 9) == 0) {
1865 wpa_driver_test_scanresp(drv, (struct sockaddr *) &from,
1866 fromlen, buf + 9);
1867 } else if (os_strncmp(buf, "ASSOCRESP ", 10) == 0) {
1868 wpa_driver_test_assocresp(drv, (struct sockaddr *) &from,
1869 fromlen, buf + 10);
1870 } else if (os_strcmp(buf, "DISASSOC") == 0) {
1871 wpa_driver_test_disassoc(drv, (struct sockaddr *) &from,
1872 fromlen);
1873 } else if (os_strcmp(buf, "DEAUTH") == 0) {
1874 wpa_driver_test_disassoc(drv, (struct sockaddr *) &from,
1875 fromlen);
1876 } else if (os_strncmp(buf, "EAPOL ", 6) == 0) {
1877 wpa_driver_test_eapol(drv, (struct sockaddr *) &from, fromlen,
1878 (const u8 *) buf + 6, res - 6);
1879 } else if (os_strncmp(buf, "MLME ", 5) == 0) {
1880 wpa_driver_test_mlme(drv, (struct sockaddr *) &from, fromlen,
1881 (const u8 *) buf + 5, res - 5);
1882 } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
1883 wpa_driver_test_scan_cmd(drv, (struct sockaddr *) &from,
1884 fromlen,
1885 (const u8 *) buf + 5, res - 5);
1886 } else {
1887 wpa_hexdump_ascii(MSG_DEBUG, "Unknown test_socket command",
1888 (u8 *) buf, res);
1889 }
1890 os_free(buf);
1891 }
1892
1893
1894 static void * wpa_driver_test_init2(void *ctx, const char *ifname,
1895 void *global_priv)
1896 {
1897 struct wpa_driver_test_data *drv;
1898
1899 drv = os_zalloc(sizeof(*drv));
1900 if (drv == NULL)
1901 return NULL;
1902 drv->global = global_priv;
1903 drv->ctx = ctx;
1904 drv->test_socket = -1;
1905
1906 /* Set dummy BSSID and SSID for testing. */
1907 drv->bssid[0] = 0x02;
1908 drv->bssid[1] = 0x00;
1909 drv->bssid[2] = 0x00;
1910 drv->bssid[3] = 0x00;
1911 drv->bssid[4] = 0x00;
1912 drv->bssid[5] = 0x01;
1913 os_memcpy(drv->ssid, "test", 5);
1914 drv->ssid_len = 4;
1915
1916 /* Generate a MAC address to help testing with multiple STAs */
1917 drv->own_addr[0] = 0x02; /* locally administered */
1918 sha1_prf((const u8 *) ifname, os_strlen(ifname),
1919 "wpa_supplicant test mac addr generation",
1920 NULL, 0, drv->own_addr + 1, ETH_ALEN - 1);
1921 eloop_register_timeout(1, 0, wpa_driver_test_poll, drv, NULL);
1922
1923 return drv;
1924 }
1925
1926
1927 static void wpa_driver_test_close_test_socket(struct wpa_driver_test_data *drv)
1928 {
1929 if (drv->test_socket >= 0) {
1930 eloop_unregister_read_sock(drv->test_socket);
1931 close(drv->test_socket);
1932 drv->test_socket = -1;
1933 }
1934
1935 if (drv->own_socket_path) {
1936 unlink(drv->own_socket_path);
1937 os_free(drv->own_socket_path);
1938 drv->own_socket_path = NULL;
1939 }
1940 }
1941
1942
1943 static void wpa_driver_test_deinit(void *priv)
1944 {
1945 struct wpa_driver_test_data *drv = priv;
1946 int i;
1947 wpa_driver_test_close_test_socket(drv);
1948 eloop_cancel_timeout(wpa_driver_test_scan_timeout, drv, drv->ctx);
1949 eloop_cancel_timeout(wpa_driver_test_poll, drv, NULL);
1950 os_free(drv->test_dir);
1951 for (i = 0; i < MAX_SCAN_RESULTS; i++)
1952 os_free(drv->scanres[i]);
1953 os_free(drv->probe_req_ie);
1954 os_free(drv);
1955 }
1956
1957
1958 static int wpa_driver_test_attach(struct wpa_driver_test_data *drv,
1959 const char *dir)
1960 {
1961 #ifdef DRIVER_TEST_UNIX
1962 static unsigned int counter = 0;
1963 struct sockaddr_un addr;
1964 size_t len;
1965
1966 os_free(drv->own_socket_path);
1967 if (dir) {
1968 len = os_strlen(dir) + 30;
1969 drv->own_socket_path = os_malloc(len);
1970 if (drv->own_socket_path == NULL)
1971 return -1;
1972 os_snprintf(drv->own_socket_path, len, "%s/STA-" MACSTR,
1973 dir, MAC2STR(drv->own_addr));
1974 } else {
1975 drv->own_socket_path = os_malloc(100);
1976 if (drv->own_socket_path == NULL)
1977 return -1;
1978 os_snprintf(drv->own_socket_path, 100,
1979 "/tmp/wpa_supplicant_test-%d-%d",
1980 getpid(), counter++);
1981 }
1982
1983 drv->test_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
1984 if (drv->test_socket < 0) {
1985 perror("socket(PF_UNIX)");
1986 os_free(drv->own_socket_path);
1987 drv->own_socket_path = NULL;
1988 return -1;
1989 }
1990
1991 os_memset(&addr, 0, sizeof(addr));
1992 addr.sun_family = AF_UNIX;
1993 os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path));
1994 if (bind(drv->test_socket, (struct sockaddr *) &addr,
1995 sizeof(addr)) < 0) {
1996 perror("bind(PF_UNIX)");
1997 close(drv->test_socket);
1998 unlink(drv->own_socket_path);
1999 os_free(drv->own_socket_path);
2000 drv->own_socket_path = NULL;
2001 return -1;
2002 }
2003
2004 eloop_register_read_sock(drv->test_socket,
2005 wpa_driver_test_receive_unix, drv, NULL);
2006
2007 return 0;
2008 #else /* DRIVER_TEST_UNIX */
2009 return -1;
2010 #endif /* DRIVER_TEST_UNIX */
2011 }
2012
2013
2014 static int wpa_driver_test_attach_udp(struct wpa_driver_test_data *drv,
2015 char *dst)
2016 {
2017 char *pos;
2018
2019 pos = os_strchr(dst, ':');
2020 if (pos == NULL)
2021 return -1;
2022 *pos++ = '\0';
2023 wpa_printf(MSG_DEBUG, "%s: addr=%s port=%s", __func__, dst, pos);
2024
2025 drv->test_socket = socket(PF_INET, SOCK_DGRAM, 0);
2026 if (drv->test_socket < 0) {
2027 perror("socket(PF_INET)");
2028 return -1;
2029 }
2030
2031 os_memset(&drv->hostapd_addr_udp, 0, sizeof(drv->hostapd_addr_udp));
2032 drv->hostapd_addr_udp.sin_family = AF_INET;
2033 #if defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ANSI_C_EXTRA)
2034 {
2035 int a[4];
2036 u8 *pos;
2037 sscanf(dst, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]);
2038 pos = (u8 *) &drv->hostapd_addr_udp.sin_addr;
2039 *pos++ = a[0];
2040 *pos++ = a[1];
2041 *pos++ = a[2];
2042 *pos++ = a[3];
2043 }
2044 #else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
2045 inet_aton(dst, &drv->hostapd_addr_udp.sin_addr);
2046 #endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
2047 drv->hostapd_addr_udp.sin_port = htons(atoi(pos));
2048
2049 drv->hostapd_addr_udp_set = 1;
2050
2051 eloop_register_read_sock(drv->test_socket,
2052 wpa_driver_test_receive_unix, drv, NULL);
2053
2054 return 0;
2055 }
2056
2057
2058 static int wpa_driver_test_set_param(void *priv, const char *param)
2059 {
2060 struct wpa_driver_test_data *drv = priv;
2061 const char *pos;
2062
2063 wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
2064 if (param == NULL)
2065 return 0;
2066
2067 wpa_driver_test_close_test_socket(drv);
2068
2069 #ifdef DRIVER_TEST_UNIX
2070 pos = os_strstr(param, "test_socket=");
2071 if (pos) {
2072 const char *pos2;
2073 size_t len;
2074
2075 pos += 12;
2076 pos2 = os_strchr(pos, ' ');
2077 if (pos2)
2078 len = pos2 - pos;
2079 else
2080 len = os_strlen(pos);
2081 if (len > sizeof(drv->hostapd_addr.sun_path))
2082 return -1;
2083 os_memset(&drv->hostapd_addr, 0, sizeof(drv->hostapd_addr));
2084 drv->hostapd_addr.sun_family = AF_UNIX;
2085 os_memcpy(drv->hostapd_addr.sun_path, pos, len);
2086 drv->hostapd_addr_set = 1;
2087 }
2088 #endif /* DRIVER_TEST_UNIX */
2089
2090 pos = os_strstr(param, "test_dir=");
2091 if (pos) {
2092 char *end;
2093 os_free(drv->test_dir);
2094 drv->test_dir = os_strdup(pos + 9);
2095 if (drv->test_dir == NULL)
2096 return -1;
2097 end = os_strchr(drv->test_dir, ' ');
2098 if (end)
2099 *end = '\0';
2100 if (wpa_driver_test_attach(drv, drv->test_dir))
2101 return -1;
2102 } else {
2103 pos = os_strstr(param, "test_udp=");
2104 if (pos) {
2105 char *dst, *epos;
2106 dst = os_strdup(pos + 9);
2107 if (dst == NULL)
2108 return -1;
2109 epos = os_strchr(dst, ' ');
2110 if (epos)
2111 *epos = '\0';
2112 if (wpa_driver_test_attach_udp(drv, dst))
2113 return -1;
2114 os_free(dst);
2115 } else if (wpa_driver_test_attach(drv, NULL))
2116 return -1;
2117 }
2118
2119 if (os_strstr(param, "use_associnfo=1")) {
2120 wpa_printf(MSG_DEBUG, "test_driver: Use AssocInfo events");
2121 drv->use_associnfo = 1;
2122 }
2123
2124 #ifdef CONFIG_CLIENT_MLME
2125 if (os_strstr(param, "use_mlme=1")) {
2126 wpa_printf(MSG_DEBUG, "test_driver: Use internal MLME");
2127 drv->use_mlme = 1;
2128 }
2129 #endif /* CONFIG_CLIENT_MLME */
2130
2131 return 0;
2132 }
2133
2134
2135 static const u8 * wpa_driver_test_get_mac_addr(void *priv)
2136 {
2137 struct wpa_driver_test_data *drv = priv;
2138 wpa_printf(MSG_DEBUG, "%s", __func__);
2139 return drv->own_addr;
2140 }
2141
2142
2143 static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto,
2144 const u8 *data, size_t data_len)
2145 {
2146 struct wpa_driver_test_data *drv = priv;
2147 char *msg;
2148 size_t msg_len;
2149 struct l2_ethhdr eth;
2150 struct sockaddr *addr;
2151 socklen_t alen;
2152 #ifdef DRIVER_TEST_UNIX
2153 struct sockaddr_un addr_un;
2154 #endif /* DRIVER_TEST_UNIX */
2155
2156 wpa_hexdump(MSG_MSGDUMP, "test_send_eapol TX frame", data, data_len);
2157
2158 os_memset(&eth, 0, sizeof(eth));
2159 os_memcpy(eth.h_dest, dest, ETH_ALEN);
2160 os_memcpy(eth.h_source, drv->own_addr, ETH_ALEN);
2161 eth.h_proto = host_to_be16(proto);
2162
2163 msg_len = 6 + sizeof(eth) + data_len;
2164 msg = os_malloc(msg_len);
2165 if (msg == NULL)
2166 return -1;
2167 os_memcpy(msg, "EAPOL ", 6);
2168 os_memcpy(msg + 6, &eth, sizeof(eth));
2169 os_memcpy(msg + 6 + sizeof(eth), data, data_len);
2170
2171 if (os_memcmp(dest, drv->bssid, ETH_ALEN) == 0 ||
2172 drv->test_dir == NULL) {
2173 if (drv->hostapd_addr_udp_set) {
2174 addr = (struct sockaddr *) &drv->hostapd_addr_udp;
2175 alen = sizeof(drv->hostapd_addr_udp);
2176 } else {
2177 #ifdef DRIVER_TEST_UNIX
2178 addr = (struct sockaddr *) &drv->hostapd_addr;
2179 alen = sizeof(drv->hostapd_addr);
2180 #else /* DRIVER_TEST_UNIX */
2181 os_free(msg);
2182 return -1;
2183 #endif /* DRIVER_TEST_UNIX */
2184 }
2185 } else {
2186 #ifdef DRIVER_TEST_UNIX
2187 struct stat st;
2188 os_memset(&addr_un, 0, sizeof(addr_un));
2189 addr_un.sun_family = AF_UNIX;
2190 os_snprintf(addr_un.sun_path, sizeof(addr_un.sun_path),
2191 "%s/STA-" MACSTR, drv->test_dir, MAC2STR(dest));
2192 if (stat(addr_un.sun_path, &st) < 0) {
2193 os_snprintf(addr_un.sun_path, sizeof(addr_un.sun_path),
2194 "%s/AP-" MACSTR,
2195 drv->test_dir, MAC2STR(dest));
2196 }
2197 addr = (struct sockaddr *) &addr_un;
2198 alen = sizeof(addr_un);
2199 #else /* DRIVER_TEST_UNIX */
2200 os_free(msg);
2201 return -1;
2202 #endif /* DRIVER_TEST_UNIX */
2203 }
2204
2205 if (sendto(drv->test_socket, msg, msg_len, 0, addr, alen) < 0) {
2206 perror("sendmsg(test_socket)");
2207 os_free(msg);
2208 return -1;
2209 }
2210
2211 os_free(msg);
2212 return 0;
2213 }
2214
2215
2216 static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa)
2217 {
2218 struct wpa_driver_test_data *drv = priv;
2219 os_memset(capa, 0, sizeof(*capa));
2220 capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2221 WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2222 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2223 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
2224 WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE |
2225 WPA_DRIVER_CAPA_KEY_MGMT_FT |
2226 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
2227 capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 |
2228 WPA_DRIVER_CAPA_ENC_WEP104 |
2229 WPA_DRIVER_CAPA_ENC_TKIP |
2230 WPA_DRIVER_CAPA_ENC_CCMP;
2231 capa->auth = WPA_DRIVER_AUTH_OPEN |
2232 WPA_DRIVER_AUTH_SHARED |
2233 WPA_DRIVER_AUTH_LEAP;
2234 if (drv->use_mlme)
2235 capa->flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME;
2236 capa->max_scan_ssids = 2;
2237
2238 return 0;
2239 }
2240
2241
2242 static int wpa_driver_test_mlme_setprotection(void *priv, const u8 *addr,
2243 int protect_type,
2244 int key_type)
2245 {
2246 wpa_printf(MSG_DEBUG, "%s: protect_type=%d key_type=%d",
2247 __func__, protect_type, key_type);
2248
2249 if (addr) {
2250 wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR,
2251 __func__, MAC2STR(addr));
2252 }
2253
2254 return 0;
2255 }
2256
2257
2258 #ifdef CONFIG_CLIENT_MLME
2259 static struct hostapd_hw_modes *
2260 wpa_driver_test_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
2261 {
2262 struct hostapd_hw_modes *modes;
2263
2264 *num_modes = 1;
2265 *flags = 0;
2266 modes = os_zalloc(*num_modes * sizeof(struct hostapd_hw_modes));
2267 if (modes == NULL)
2268 return NULL;
2269 modes[0].mode = HOSTAPD_MODE_IEEE80211G;
2270 modes[0].num_channels = 1;
2271 modes[0].num_rates = 1;
2272 modes[0].channels = os_zalloc(sizeof(struct hostapd_channel_data));
2273 modes[0].rates = os_zalloc(sizeof(struct hostapd_rate_data));
2274 if (modes[0].channels == NULL || modes[0].rates == NULL) {
2275 wpa_supplicant_sta_free_hw_features(modes, *num_modes);
2276 return NULL;
2277 }
2278 modes[0].channels[0].chan = 1;
2279 modes[0].channels[0].freq = 2412;
2280 modes[0].channels[0].flag = 0;
2281 modes[0].rates[0].rate = 10;
2282 modes[0].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED |
2283 HOSTAPD_RATE_CCK | HOSTAPD_RATE_MANDATORY;
2284
2285 return modes;
2286 }
2287
2288
2289 static int wpa_driver_test_set_channel(void *priv, hostapd_hw_mode phymode,
2290 int chan, int freq)
2291 {
2292 wpa_printf(MSG_DEBUG, "%s: phymode=%d chan=%d freq=%d",
2293 __func__, phymode, chan, freq);
2294 return 0;
2295 }
2296
2297
2298 static int wpa_driver_test_send_mlme(void *priv, const u8 *data,
2299 size_t data_len)
2300 {
2301 struct wpa_driver_test_data *drv = priv;
2302 struct msghdr msg;
2303 struct iovec io[2];
2304 struct sockaddr_un addr;
2305 const u8 *dest;
2306 struct dirent *dent;
2307 DIR *dir;
2308
2309 wpa_hexdump(MSG_MSGDUMP, "test_send_mlme", data, data_len);
2310 if (data_len < 10)
2311 return -1;
2312 dest = data + 4;
2313
2314 io[0].iov_base = "MLME ";
2315 io[0].iov_len = 5;
2316 io[1].iov_base = (u8 *) data;
2317 io[1].iov_len = data_len;
2318
2319 os_memset(&msg, 0, sizeof(msg));
2320 msg.msg_iov = io;
2321 msg.msg_iovlen = 2;
2322 if (os_memcmp(dest, drv->bssid, ETH_ALEN) == 0 ||
2323 drv->test_dir == NULL) {
2324 if (drv->hostapd_addr_udp_set) {
2325 msg.msg_name = &drv->hostapd_addr_udp;
2326 msg.msg_namelen = sizeof(drv->hostapd_addr_udp);
2327 } else {
2328 #ifdef DRIVER_TEST_UNIX
2329 msg.msg_name = &drv->hostapd_addr;
2330 msg.msg_namelen = sizeof(drv->hostapd_addr);
2331 #endif /* DRIVER_TEST_UNIX */
2332 }
2333 } else if (os_memcmp(dest, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
2334 {
2335 dir = opendir(drv->test_dir);
2336 if (dir == NULL)
2337 return -1;
2338 while ((dent = readdir(dir))) {
2339 #ifdef _DIRENT_HAVE_D_TYPE
2340 /* Skip the file if it is not a socket.
2341 * Also accept DT_UNKNOWN (0) in case
2342 * the C library or underlying file
2343 * system does not support d_type. */
2344 if (dent->d_type != DT_SOCK &&
2345 dent->d_type != DT_UNKNOWN)
2346 continue;
2347 #endif /* _DIRENT_HAVE_D_TYPE */
2348 if (os_strcmp(dent->d_name, ".") == 0 ||
2349 os_strcmp(dent->d_name, "..") == 0)
2350 continue;
2351 wpa_printf(MSG_DEBUG, "%s: Send broadcast MLME to %s",
2352 __func__, dent->d_name);
2353 os_memset(&addr, 0, sizeof(addr));
2354 addr.sun_family = AF_UNIX;
2355 os_snprintf(addr.sun_path, sizeof(addr.sun_path),
2356 "%s/%s", drv->test_dir, dent->d_name);
2357
2358 msg.msg_name = &addr;
2359 msg.msg_namelen = sizeof(addr);
2360
2361 if (sendmsg(drv->test_socket, &msg, 0) < 0)
2362 perror("sendmsg(test_socket)");
2363 }
2364 closedir(dir);
2365 return 0;
2366 } else {
2367 struct stat st;
2368 os_memset(&addr, 0, sizeof(addr));
2369 addr.sun_family = AF_UNIX;
2370 os_snprintf(addr.sun_path, sizeof(addr.sun_path),
2371 "%s/AP-" MACSTR, drv->test_dir, MAC2STR(dest));
2372 if (stat(addr.sun_path, &st) < 0) {
2373 os_snprintf(addr.sun_path, sizeof(addr.sun_path),
2374 "%s/STA-" MACSTR,
2375 drv->test_dir, MAC2STR(dest));
2376 }
2377 msg.msg_name = &addr;
2378 msg.msg_namelen = sizeof(addr);
2379 }
2380
2381 if (sendmsg(drv->test_socket, &msg, 0) < 0) {
2382 perror("sendmsg(test_socket)");
2383 return -1;
2384 }
2385
2386 return 0;
2387 }
2388
2389
2390 static int wpa_driver_test_mlme_add_sta(void *priv, const u8 *addr,
2391 const u8 *supp_rates,
2392 size_t supp_rates_len)
2393 {
2394 wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr));
2395 return 0;
2396 }
2397
2398
2399 static int wpa_driver_test_mlme_remove_sta(void *priv, const u8 *addr)
2400 {
2401 wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr));
2402 return 0;
2403 }
2404
2405
2406 static int wpa_driver_test_set_ssid(void *priv, const u8 *ssid,
2407 size_t ssid_len)
2408 {
2409 wpa_printf(MSG_DEBUG, "%s", __func__);
2410 return 0;
2411 }
2412
2413
2414 static int wpa_driver_test_set_bssid(void *priv, const u8 *bssid)
2415 {
2416 wpa_printf(MSG_DEBUG, "%s: bssid=" MACSTR, __func__, MAC2STR(bssid));
2417 return 0;
2418 }
2419 #endif /* CONFIG_CLIENT_MLME */
2420
2421
2422 static int wpa_driver_test_set_probe_req_ie(void *priv, const u8 *ies,
2423 size_t ies_len)
2424 {
2425 struct wpa_driver_test_data *drv = priv;
2426
2427 os_free(drv->probe_req_ie);
2428 if (ies) {
2429 drv->probe_req_ie = os_malloc(ies_len);
2430 if (drv->probe_req_ie == NULL) {
2431 drv->probe_req_ie_len = 0;
2432 return -1;
2433 }
2434 os_memcpy(drv->probe_req_ie, ies, ies_len);
2435 drv->probe_req_ie_len = ies_len;
2436 } else {
2437 drv->probe_req_ie = NULL;
2438 drv->probe_req_ie_len = 0;
2439 }
2440 return 0;
2441 }
2442
2443
2444 static void * wpa_driver_test_global_init(void)
2445 {
2446 struct wpa_driver_test_global *global;
2447
2448 global = os_zalloc(sizeof(*global));
2449 return global;
2450 }
2451
2452
2453 static void wpa_driver_test_global_deinit(void *priv)
2454 {
2455 struct wpa_driver_test_global *global = priv;
2456 os_free(global);
2457 }
2458
2459
2460 static struct wpa_interface_info *
2461 wpa_driver_test_get_interfaces(void *global_priv)
2462 {
2463 /* struct wpa_driver_test_global *global = priv; */
2464 struct wpa_interface_info *iface;
2465
2466 iface = os_zalloc(sizeof(*iface));
2467 if (iface == NULL)
2468 return iface;
2469 iface->ifname = os_strdup("sta0");
2470 iface->desc = os_strdup("test interface 0");
2471 iface->drv_name = "test";
2472 iface->next = os_zalloc(sizeof(*iface));
2473 if (iface->next) {
2474 iface->next->ifname = os_strdup("sta1");
2475 iface->next->desc = os_strdup("test interface 1");
2476 iface->next->drv_name = "test";
2477 }
2478
2479 return iface;
2480 }
2481
2482
2483 const struct wpa_driver_ops wpa_driver_test_ops = {
2484 "test",
2485 "wpa_supplicant test driver",
2486 wpa_driver_test_get_bssid,
2487 wpa_driver_test_get_ssid,
2488 wpa_driver_test_set_wpa,
2489 wpa_driver_test_set_key,
2490 NULL /* init */,
2491 wpa_driver_test_deinit,
2492 wpa_driver_test_set_param,
2493 NULL /* set_countermeasures */,
2494 NULL /* set_drop_unencrypted */,
2495 NULL /* scan */,
2496 NULL /* get_scan_results */,
2497 wpa_driver_test_deauthenticate,
2498 wpa_driver_test_disassociate,
2499 wpa_driver_test_associate,
2500 NULL /* set_auth_alg */,
2501 NULL /* add_pmkid */,
2502 NULL /* remove_pmkid */,
2503 NULL /* flush_pmkid */,
2504 wpa_driver_test_get_capa,
2505 NULL /* poll */,
2506 NULL /* get_ifname */,
2507 wpa_driver_test_get_mac_addr,
2508 wpa_driver_test_send_eapol,
2509 NULL /* set_operstate */,
2510 wpa_driver_test_mlme_setprotection,
2511 #ifdef CONFIG_CLIENT_MLME
2512 wpa_driver_test_get_hw_feature_data,
2513 wpa_driver_test_set_channel,
2514 wpa_driver_test_set_ssid,
2515 wpa_driver_test_set_bssid,
2516 wpa_driver_test_send_mlme,
2517 wpa_driver_test_mlme_add_sta,
2518 wpa_driver_test_mlme_remove_sta,
2519 #else /* CONFIG_CLIENT_MLME */
2520 NULL /* get_hw_feature_data */,
2521 NULL /* set_channel */,
2522 NULL /* set_ssid */,
2523 NULL /* set_bssid */,
2524 NULL /* send_mlme */,
2525 NULL /* mlme_add_sta */,
2526 NULL /* mlme_remove_sta */,
2527 #endif /* CONFIG_CLIENT_MLME */
2528 NULL /* update_ft_ies */,
2529 NULL /* send_ft_action */,
2530 wpa_driver_test_get_scan_results2,
2531 wpa_driver_test_set_probe_req_ie,
2532 NULL /* set_mode */,
2533 NULL /* set_country */,
2534 wpa_driver_test_global_init,
2535 wpa_driver_test_global_deinit,
2536 wpa_driver_test_init2,
2537 wpa_driver_test_get_interfaces,
2538 wpa_driver_test_scan,
2539 NULL /* authenticate */,
2540 NULL /* set_beacon */,
2541 NULL /* set_beacon_int */,
2542 NULL /* hapd_init */,
2543 NULL /* init_bssid */,
2544 NULL /* hapd_deinit */,
2545 NULL /* set_ieee8021x */,
2546 NULL /* set_privacy */,
2547 NULL /* hapd_set_key */,
2548 NULL /* get_seqnum */,
2549 NULL /* get_seqnum_igtk */,
2550 NULL /* flush */,
2551 NULL /* set_generic_elem */,
2552 NULL /* read_sta_data */,
2553 NULL /* hapd_send_eapol */,
2554 NULL /* sta_deauth */,
2555 NULL /* sta_disassoc */,
2556 NULL /* sta_remove */,
2557 NULL /* hapd_get_ssid */,
2558 NULL /* hapd_set_ssid */,
2559 NULL /* hapd_set_countermeasures */,
2560 NULL /* send_mgmt_frame */,
2561 NULL /* sta_add */,
2562 NULL /* get_inact_sec */,
2563 NULL /* sta_clear_stats */,
2564 NULL /* set_freq */,
2565 NULL /* set_rts */,
2566 NULL /* set_frag */,
2567 NULL /* set_retry */,
2568 NULL /* sta_set_flags */,
2569 NULL /* set_rate_sets */,
2570 NULL /* hapd_set_country */,
2571 NULL /* set_ieee80211d */,
2572 NULL /* hapd_set_beacon */,
2573 NULL /* set_internal_bridge */,
2574 NULL /* hapd_set_beacon_int */,
2575 NULL /* set_broadcast_ssid */,
2576 NULL /* set_cts_protect */,
2577 NULL /* set_preamble */,
2578 NULL /* set_short_slot_time */,
2579 NULL /* set_tx_queue_params */,
2580 NULL /* bss_add */,
2581 NULL /* bss_remove */,
2582 NULL /* valid_bss_mask */,
2583 NULL /* passive_scan */,
2584 NULL /* hapd_get_hw_feature_data */,
2585 NULL /* if_add */,
2586 NULL /* if_update */,
2587 NULL /* if_remove */,
2588 NULL /* set_sta_vlan */,
2589 NULL /* commit */,
2590 NULL /* send_ether */,
2591 NULL /* set_radius_acl_auth */,
2592 NULL /* set_radius_acl_expire */,
2593 NULL /* set_ht_params */,
2594 NULL /* set_wps_beacon_ie */,
2595 NULL /* set_wps_probe_resp_ie */,
2596 NULL /* get_neighbor_bss */
2597 };
2598
2599 #endif /* HOSTAPD */