18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - Layer2 packet handling with Microsoft NDISUIO 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This implementation requires Windows specific event loop implementation, 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * i.e., eloop_win.c. In addition, the NDISUIO connection is shared with 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * driver_ndis.c, so only that driver interface can be used and 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * CONFIG_USE_NDISUIO must be defined. 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WinXP version of the code uses overlapped I/O and a single threaded design 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with callback functions from I/O code. WinCE version uses a separate RX 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * thread that blocks on ReadFile() whenever the media status is connected. 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <winsock2.h> 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <ntddndis.h> 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <winioctl.h> 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nuiouser.h> 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "l2_packet.h" 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* from nuiouser.h */ 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define FSCTL_NDISUIO_BASE FILE_DEVICE_NETWORK 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \ 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access) 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IOCTL_NDISUIO_SET_ETHER_TYPE \ 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _NDISUIO_CTL_CODE(0x202, METHOD_BUFFERED, \ 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt FILE_READ_ACCESS | FILE_WRITE_ACCESS) 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* From driver_ndis.c to shared the handle to NDISUIO */ 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtHANDLE driver_ndis_get_ndisuio_handle(void); 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * NDISUIO supports filtering of only one ethertype at the time, so we must 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * fake support for two (EAPOL and RSN pre-auth) by switching to pre-auth 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * whenever wpa_supplicant is trying to pre-authenticate and then switching 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * back to EAPOL when pre-authentication has been completed. 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct l2_packet_data; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct l2_packet_ndisuio_global { 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int refcount; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned short first_proto; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct l2_packet_data *l2[2]; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HANDLE rx_thread; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HANDLE stop_request; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HANDLE ready_for_read; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HANDLE rx_processed; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct l2_packet_ndisuio_global *l2_ndisuio_global = NULL; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct l2_packet_data { 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char ifname[100]; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 own_addr[ETH_ALEN]; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void (*rx_callback)(void *ctx, const u8 *src_addr, 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len); 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *rx_callback_ctx; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int l2_hdr; /* whether to include layer 2 (Ethernet) header in calls to 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rx_callback and l2_packet_send() */ 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HANDLE rx_avail; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt OVERLAPPED rx_overlapped; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rx_buf[1514]; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD rx_written; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(addr, l2->own_addr, ETH_ALEN); 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BOOL res; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD written; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct l2_ethhdr *eth; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt OVERLAPPED overlapped; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt OVERLAPPED *o; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2 == NULL) 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt o = NULL; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* _WIN32_WCE */ 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&overlapped, 0, sizeof(overlapped)); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt o = &overlapped; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2->l2_hdr) { 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = WriteFile(driver_ndis_get_ndisuio_handle(), buf, len, 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &written, o); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mlen = sizeof(*eth) + len; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eth = os_malloc(mlen); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eth == NULL) 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eth->h_proto = htons(proto); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(eth + 1, buf, len); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = WriteFile(driver_ndis_get_ndisuio_handle(), eth, mlen, 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &written, o); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eth); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!res) { 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD err = GetLastError(); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err == ERROR_IO_PENDING) { 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): Wait for pending " 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "write to complete"); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = GetOverlappedResult( 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt driver_ndis_get_ndisuio_handle(), &overlapped, 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &written, TRUE); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!res) { 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): " 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GetOverlappedResult failed: %d", 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): WriteFile failed: %d", 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void l2_packet_callback(struct l2_packet_data *l2); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void l2_packet_rx_thread_try_read(struct l2_packet_data *l2) 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HANDLE handles[2]; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "l2_packet_rx_thread: -> ReadFile"); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ReadFile(driver_ndis_get_ndisuio_handle(), l2->rx_buf, 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(l2->rx_buf), &l2->rx_written, NULL)) { 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD err = GetLastError(); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: ReadFile failed: " 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d", (int) err); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ReadFile on NDISUIO/WinCE returns ERROR_DEVICE_NOT_CONNECTED 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * error whenever the connection is not up. Yield the thread to 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * avoid triggering a busy loop. Connection event should stop 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * us from looping for long, but we need to allow enough CPU 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for the main thread to process the media disconnection. 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Sleep(100); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: Read %d byte packet", 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) l2->rx_written); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notify the main thread about the availability of a frame and wait 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for the frame to be processed. 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SetEvent(l2->rx_avail); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handles[0] = l2_ndisuio_global->stop_request; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handles[1] = l2_ndisuio_global->rx_processed; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WaitForMultipleObjects(2, handles, FALSE, INFINITE); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ResetEvent(l2_ndisuio_global->rx_processed); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic DWORD WINAPI l2_packet_rx_thread(LPVOID arg) 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct l2_packet_data *l2 = arg; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD res; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HANDLE handles[2]; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int run = 1; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): RX thread started"); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handles[0] = l2_ndisuio_global->stop_request; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handles[1] = l2_ndisuio_global->ready_for_read; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Unfortunately, NDISUIO on WinCE does not seem to support waiting 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * on the handle. There do not seem to be anything else that we could 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wait for either. If one were to modify NDISUIO to set a named event 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * whenever packets are available, this event could be used here to 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * avoid having to poll for new packets or we could even move to use a 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * single threaded design. 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * In addition, NDISUIO on WinCE is returning 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ERROR_DEVICE_NOT_CONNECTED whenever ReadFile() is attempted while 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the adapter is not in connected state. For now, we are just using a 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * local event to allow ReadFile calls only after having received NDIS 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * media connect event. This event could be easily converted to handle 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * another event if the protocol driver is replaced with somewhat more 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * useful design. 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (l2_ndisuio_global && run) { 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = WaitForMultipleObjects(2, handles, FALSE, INFINITE); 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (res) { 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WAIT_OBJECT_0: 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: Received " 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request to stop RX thread"); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt run = 0; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WAIT_OBJECT_0 + 1: 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_packet_rx_thread_try_read(l2); 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WAIT_FAILED: 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: " 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WaitForMultipleObjects failed: %d", 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt run = 0; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): RX thread stopped"); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* _WIN32_WCE */ 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int l2_ndisuio_start_read(struct l2_packet_data *l2, int recursive) 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&l2->rx_overlapped, 0, sizeof(l2->rx_overlapped)); 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2->rx_overlapped.hEvent = l2->rx_avail; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ReadFile(driver_ndis_get_ndisuio_handle(), l2->rx_buf, 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(l2->rx_buf), &l2->rx_written, &l2->rx_overlapped)) 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD err = GetLastError(); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err != ERROR_IO_PENDING) { 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): ReadFile failed: " 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d", (int) err); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Once read is completed, l2_packet_rx_event() will be 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * called. 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): ReadFile returned data " 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "without wait for completion"); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!recursive) 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_packet_callback(l2); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void l2_packet_callback(struct l2_packet_data *l2) 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *rx_buf, *rx_src; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rx_len; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct l2_ethhdr *ethhdr = (struct l2_ethhdr *) l2->rx_buf; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): Read %d bytes", 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) l2->rx_written); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2->l2_hdr || l2->rx_written < sizeof(*ethhdr)) { 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rx_buf = (u8 *) ethhdr; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rx_len = l2->rx_written; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rx_buf = (u8 *) (ethhdr + 1); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rx_len = l2->rx_written - sizeof(*ethhdr); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rx_src = ethhdr->h_source; 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2->rx_callback(l2->rx_callback_ctx, rx_src, rx_buf, rx_len); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_start_read(l2, 1); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void l2_packet_rx_event(void *eloop_data, void *user_data) 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct l2_packet_data *l2 = eloop_data; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global) 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2 = l2_ndisuio_global->l2[l2_ndisuio_global->refcount - 1]; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ResetEvent(l2->rx_avail); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!GetOverlappedResult(driver_ndis_get_ndisuio_handle(), 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &l2->rx_overlapped, &l2->rx_written, FALSE)) { 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): GetOverlappedResult " 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed: %d", (int) GetLastError()); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_packet_callback(l2); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SetEvent(l2_ndisuio_global->rx_processed); 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int l2_ndisuio_set_ether_type(unsigned short protocol) 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt USHORT proto = htons(protocol); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD written; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!DeviceIoControl(driver_ndis_get_ndisuio_handle(), 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IOCTL_NDISUIO_SET_ETHER_TYPE, &proto, 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(proto), NULL, 0, &written, NULL)) { 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "L2(NDISUIO): " 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IOCTL_NDISUIO_SET_ETHER_TYPE failed: %d", 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct l2_packet_data * l2_packet_init( 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname, const u8 *own_addr, unsigned short protocol, 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void (*rx_callback)(void *ctx, const u8 *src_addr, 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len), 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *rx_callback_ctx, int l2_hdr) 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct l2_packet_data *l2; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global == NULL) { 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global = os_zalloc(sizeof(*l2_ndisuio_global)); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global == NULL) 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->first_proto = protocol; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global->refcount >= 2) { 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "L2(NDISUIO): Not more than two " 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "simultaneous connections allowed"); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->refcount++; 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2 = os_zalloc(sizeof(struct l2_packet_data)); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2 == NULL) 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->l2[l2_ndisuio_global->refcount - 1] = l2; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2->rx_callback = rx_callback; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2->rx_callback_ctx = rx_callback_ctx; 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2->l2_hdr = l2_hdr; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (own_addr) 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(l2->own_addr, own_addr, ETH_ALEN); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_set_ether_type(protocol) < 0) { 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(l2); 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global->refcount > 1) { 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): Temporarily setting " 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "filtering ethertype to %04x", protocol); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global->l2[0]) 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2->rx_avail = l2_ndisuio_global->l2[0]->rx_avail; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return l2; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2->rx_avail = CreateEvent(NULL, TRUE, FALSE, NULL); 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2->rx_avail == NULL) { 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(l2); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_event(l2->rx_avail, sizeof(l2->rx_avail), 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_packet_rx_event, l2, NULL); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->stop_request = CreateEvent(NULL, TRUE, FALSE, NULL); 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This event is being set based on media connect/disconnect 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * notifications in driver_ndis.c. 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->ready_for_read = 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected")); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->rx_processed = CreateEvent(NULL, TRUE, FALSE, NULL); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global->stop_request == NULL || 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->ready_for_read == NULL || 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->rx_processed == NULL) { 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global->stop_request) { 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(l2_ndisuio_global->stop_request); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->stop_request = NULL; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global->ready_for_read) { 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(l2_ndisuio_global->ready_for_read); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->ready_for_read = NULL; 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global->rx_processed) { 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(l2_ndisuio_global->rx_processed); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->rx_processed = NULL; 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(l2); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->rx_thread = CreateThread(NULL, 0, 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_packet_rx_thread, l2, 0, 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global->rx_thread == NULL) { 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "L2(NDISUIO): Failed to create RX " 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "thread: %d", (int) GetLastError()); 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(l2_ndisuio_global->stop_request); 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->stop_request = NULL; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(l2); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* _WIN32_WCE */ 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_start_read(l2, 0); 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return l2; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid l2_packet_deinit(struct l2_packet_data *l2) 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2 == NULL) 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global) { 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->refcount--; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->l2[l2_ndisuio_global->refcount] = NULL; 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (l2_ndisuio_global->refcount) { 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): restore filtering " 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ethertype to %04x", 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->first_proto); 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_set_ether_type( 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global->first_proto); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): Waiting for RX thread to " 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "stop"); 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SetEvent(l2_ndisuio_global->stop_request); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Cancel pending ReadFile() in the RX thread (if we were still 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * connected at this point). 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!DeviceIoControl(driver_ndis_get_ndisuio_handle(), 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IOCTL_CANCEL_READ, NULL, 0, NULL, 0, NULL, 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL)) { 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): IOCTL_CANCEL_READ " 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed: %d", (int) GetLastError()); 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RX thread will exit blocking ReadFile once NDISUIO 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * notices that the adapter is disconnected. */ 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WaitForSingleObject(l2_ndisuio_global->rx_thread, INFINITE); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "L2(NDISUIO): RX thread exited"); 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(l2_ndisuio_global->rx_thread); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(l2_ndisuio_global->stop_request); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(l2_ndisuio_global->ready_for_read); 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(l2_ndisuio_global->rx_processed); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(l2_ndisuio_global); 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_ndisuio_global = NULL; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CancelIo(driver_ndis_get_ndisuio_handle()); 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */ 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(l2->rx_avail); 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(l2); 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid l2_packet_notify_auth_start(struct l2_packet_data *l2) 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 517