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