X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=libeap%2Fsrc%2Fl2_packet%2Fl2_packet_ndis.c;fp=libeap%2Fsrc%2Fl2_packet%2Fl2_packet_ndis.c;h=0000000000000000000000000000000000000000;hb=38791e2c8e2c94ed906593931831bda6577d5346;hp=6ce29aa20ec93cd66f2791e7ad8120f6acbd3a4e;hpb=1d91db0ace57f0b63665c0303eae0b347debaef7;p=mech_eap.git diff --git a/libeap/src/l2_packet/l2_packet_ndis.c b/libeap/src/l2_packet/l2_packet_ndis.c deleted file mode 100644 index 6ce29aa..0000000 --- a/libeap/src/l2_packet/l2_packet_ndis.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with Microsoft NDISUIO - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This implementation requires Windows specific event loop implementation, - * i.e., eloop_win.c. In addition, the NDISUIO connection is shared with - * driver_ndis.c, so only that driver interface can be used and - * CONFIG_USE_NDISUIO must be defined. - * - * WinXP version of the code uses overlapped I/O and a single threaded design - * with callback functions from I/O code. WinCE version uses a separate RX - * thread that blocks on ReadFile() whenever the media status is connected. - */ - -#include "includes.h" -#include -#include - -#ifdef _WIN32_WCE -#include -#include -#endif /* _WIN32_WCE */ - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - -#ifndef _WIN32_WCE -/* from nuiouser.h */ -#define FSCTL_NDISUIO_BASE FILE_DEVICE_NETWORK -#define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \ - CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access) -#define IOCTL_NDISUIO_SET_ETHER_TYPE \ - _NDISUIO_CTL_CODE(0x202, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) -#endif /* _WIN32_WCE */ - -/* From driver_ndis.c to shared the handle to NDISUIO */ -HANDLE driver_ndis_get_ndisuio_handle(void); - -/* - * NDISUIO supports filtering of only one ethertype at the time, so we must - * fake support for two (EAPOL and RSN pre-auth) by switching to pre-auth - * whenever wpa_supplicant is trying to pre-authenticate and then switching - * back to EAPOL when pre-authentication has been completed. - */ - -struct l2_packet_data; - -struct l2_packet_ndisuio_global { - int refcount; - unsigned short first_proto; - struct l2_packet_data *l2[2]; -#ifdef _WIN32_WCE - HANDLE rx_thread; - HANDLE stop_request; - HANDLE ready_for_read; - HANDLE rx_processed; -#endif /* _WIN32_WCE */ -}; - -static struct l2_packet_ndisuio_global *l2_ndisuio_global = NULL; - -struct l2_packet_data { - char ifname[100]; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header in calls to - * rx_callback and l2_packet_send() */ - HANDLE rx_avail; -#ifndef _WIN32_WCE - OVERLAPPED rx_overlapped; -#endif /* _WIN32_WCE */ - u8 rx_buf[1514]; - DWORD rx_written; -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - BOOL res; - DWORD written; - struct l2_ethhdr *eth; -#ifndef _WIN32_WCE - OVERLAPPED overlapped; -#endif /* _WIN32_WCE */ - OVERLAPPED *o; - - if (l2 == NULL) - return -1; - -#ifdef _WIN32_WCE - o = NULL; -#else /* _WIN32_WCE */ - os_memset(&overlapped, 0, sizeof(overlapped)); - o = &overlapped; -#endif /* _WIN32_WCE */ - - if (l2->l2_hdr) { - res = WriteFile(driver_ndis_get_ndisuio_handle(), buf, len, - &written, o); - } else { - size_t mlen = sizeof(*eth) + len; - eth = os_malloc(mlen); - if (eth == NULL) - return -1; - - os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); - os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); - eth->h_proto = htons(proto); - os_memcpy(eth + 1, buf, len); - res = WriteFile(driver_ndis_get_ndisuio_handle(), eth, mlen, - &written, o); - os_free(eth); - } - - if (!res) { - DWORD err = GetLastError(); -#ifndef _WIN32_WCE - if (err == ERROR_IO_PENDING) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): Wait for pending " - "write to complete"); - res = GetOverlappedResult( - driver_ndis_get_ndisuio_handle(), &overlapped, - &written, TRUE); - if (!res) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): " - "GetOverlappedResult failed: %d", - (int) GetLastError()); - return -1; - } - return 0; - } -#endif /* _WIN32_WCE */ - wpa_printf(MSG_DEBUG, "L2(NDISUIO): WriteFile failed: %d", - (int) GetLastError()); - return -1; - } - - return 0; -} - - -static void l2_packet_callback(struct l2_packet_data *l2); - -#ifdef _WIN32_WCE -static void l2_packet_rx_thread_try_read(struct l2_packet_data *l2) -{ - HANDLE handles[2]; - - wpa_printf(MSG_MSGDUMP, "l2_packet_rx_thread: -> ReadFile"); - if (!ReadFile(driver_ndis_get_ndisuio_handle(), l2->rx_buf, - sizeof(l2->rx_buf), &l2->rx_written, NULL)) { - DWORD err = GetLastError(); - wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: ReadFile failed: " - "%d", (int) err); - /* - * ReadFile on NDISUIO/WinCE returns ERROR_DEVICE_NOT_CONNECTED - * error whenever the connection is not up. Yield the thread to - * avoid triggering a busy loop. Connection event should stop - * us from looping for long, but we need to allow enough CPU - * for the main thread to process the media disconnection. - */ - Sleep(100); - return; - } - - wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: Read %d byte packet", - (int) l2->rx_written); - - /* - * Notify the main thread about the availability of a frame and wait - * for the frame to be processed. - */ - SetEvent(l2->rx_avail); - handles[0] = l2_ndisuio_global->stop_request; - handles[1] = l2_ndisuio_global->rx_processed; - WaitForMultipleObjects(2, handles, FALSE, INFINITE); - ResetEvent(l2_ndisuio_global->rx_processed); -} - - -static DWORD WINAPI l2_packet_rx_thread(LPVOID arg) -{ - struct l2_packet_data *l2 = arg; - DWORD res; - HANDLE handles[2]; - int run = 1; - - wpa_printf(MSG_DEBUG, "L2(NDISUIO): RX thread started"); - handles[0] = l2_ndisuio_global->stop_request; - handles[1] = l2_ndisuio_global->ready_for_read; - - /* - * Unfortunately, NDISUIO on WinCE does not seem to support waiting - * on the handle. There do not seem to be anything else that we could - * wait for either. If one were to modify NDISUIO to set a named event - * whenever packets are available, this event could be used here to - * avoid having to poll for new packets or we could even move to use a - * single threaded design. - * - * In addition, NDISUIO on WinCE is returning - * ERROR_DEVICE_NOT_CONNECTED whenever ReadFile() is attempted while - * the adapter is not in connected state. For now, we are just using a - * local event to allow ReadFile calls only after having received NDIS - * media connect event. This event could be easily converted to handle - * another event if the protocol driver is replaced with somewhat more - * useful design. - */ - - while (l2_ndisuio_global && run) { - res = WaitForMultipleObjects(2, handles, FALSE, INFINITE); - switch (res) { - case WAIT_OBJECT_0: - wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: Received " - "request to stop RX thread"); - run = 0; - break; - case WAIT_OBJECT_0 + 1: - l2_packet_rx_thread_try_read(l2); - break; - case WAIT_FAILED: - default: - wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: " - "WaitForMultipleObjects failed: %d", - (int) GetLastError()); - run = 0; - break; - } - } - - wpa_printf(MSG_DEBUG, "L2(NDISUIO): RX thread stopped"); - - return 0; -} -#else /* _WIN32_WCE */ -static int l2_ndisuio_start_read(struct l2_packet_data *l2, int recursive) -{ - os_memset(&l2->rx_overlapped, 0, sizeof(l2->rx_overlapped)); - l2->rx_overlapped.hEvent = l2->rx_avail; - if (!ReadFile(driver_ndis_get_ndisuio_handle(), l2->rx_buf, - sizeof(l2->rx_buf), &l2->rx_written, &l2->rx_overlapped)) - { - DWORD err = GetLastError(); - if (err != ERROR_IO_PENDING) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): ReadFile failed: " - "%d", (int) err); - return -1; - } - /* - * Once read is completed, l2_packet_rx_event() will be - * called. - */ - } else { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): ReadFile returned data " - "without wait for completion"); - if (!recursive) - l2_packet_callback(l2); - } - - return 0; -} -#endif /* _WIN32_WCE */ - - -static void l2_packet_callback(struct l2_packet_data *l2) -{ - const u8 *rx_buf, *rx_src; - size_t rx_len; - struct l2_ethhdr *ethhdr = (struct l2_ethhdr *) l2->rx_buf; - - wpa_printf(MSG_DEBUG, "L2(NDISUIO): Read %d bytes", - (int) l2->rx_written); - - if (l2->l2_hdr || l2->rx_written < sizeof(*ethhdr)) { - rx_buf = (u8 *) ethhdr; - rx_len = l2->rx_written; - } else { - rx_buf = (u8 *) (ethhdr + 1); - rx_len = l2->rx_written - sizeof(*ethhdr); - } - rx_src = ethhdr->h_source; - - l2->rx_callback(l2->rx_callback_ctx, rx_src, rx_buf, rx_len); -#ifndef _WIN32_WCE - l2_ndisuio_start_read(l2, 1); -#endif /* _WIN32_WCE */ -} - - -static void l2_packet_rx_event(void *eloop_data, void *user_data) -{ - struct l2_packet_data *l2 = eloop_data; - - if (l2_ndisuio_global) - l2 = l2_ndisuio_global->l2[l2_ndisuio_global->refcount - 1]; - - ResetEvent(l2->rx_avail); - -#ifndef _WIN32_WCE - if (!GetOverlappedResult(driver_ndis_get_ndisuio_handle(), - &l2->rx_overlapped, &l2->rx_written, FALSE)) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): GetOverlappedResult " - "failed: %d", (int) GetLastError()); - return; - } -#endif /* _WIN32_WCE */ - - l2_packet_callback(l2); - -#ifdef _WIN32_WCE - SetEvent(l2_ndisuio_global->rx_processed); -#endif /* _WIN32_WCE */ -} - - -static int l2_ndisuio_set_ether_type(unsigned short protocol) -{ - USHORT proto = htons(protocol); - DWORD written; - - if (!DeviceIoControl(driver_ndis_get_ndisuio_handle(), - IOCTL_NDISUIO_SET_ETHER_TYPE, &proto, - sizeof(proto), NULL, 0, &written, NULL)) { - wpa_printf(MSG_ERROR, "L2(NDISUIO): " - "IOCTL_NDISUIO_SET_ETHER_TYPE failed: %d", - (int) GetLastError()); - return -1; - } - - return 0; -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - - if (l2_ndisuio_global == NULL) { - l2_ndisuio_global = os_zalloc(sizeof(*l2_ndisuio_global)); - if (l2_ndisuio_global == NULL) - return NULL; - l2_ndisuio_global->first_proto = protocol; - } - if (l2_ndisuio_global->refcount >= 2) { - wpa_printf(MSG_ERROR, "L2(NDISUIO): Not more than two " - "simultaneous connections allowed"); - return NULL; - } - l2_ndisuio_global->refcount++; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - l2_ndisuio_global->l2[l2_ndisuio_global->refcount - 1] = l2; - - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - - if (own_addr) - os_memcpy(l2->own_addr, own_addr, ETH_ALEN); - - if (l2_ndisuio_set_ether_type(protocol) < 0) { - os_free(l2); - return NULL; - } - - if (l2_ndisuio_global->refcount > 1) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): Temporarily setting " - "filtering ethertype to %04x", protocol); - if (l2_ndisuio_global->l2[0]) - l2->rx_avail = l2_ndisuio_global->l2[0]->rx_avail; - return l2; - } - - l2->rx_avail = CreateEvent(NULL, TRUE, FALSE, NULL); - if (l2->rx_avail == NULL) { - os_free(l2); - return NULL; - } - - eloop_register_event(l2->rx_avail, sizeof(l2->rx_avail), - l2_packet_rx_event, l2, NULL); - -#ifdef _WIN32_WCE - l2_ndisuio_global->stop_request = CreateEvent(NULL, TRUE, FALSE, NULL); - /* - * This event is being set based on media connect/disconnect - * notifications in driver_ndis.c. - */ - l2_ndisuio_global->ready_for_read = - CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected")); - l2_ndisuio_global->rx_processed = CreateEvent(NULL, TRUE, FALSE, NULL); - if (l2_ndisuio_global->stop_request == NULL || - l2_ndisuio_global->ready_for_read == NULL || - l2_ndisuio_global->rx_processed == NULL) { - if (l2_ndisuio_global->stop_request) { - CloseHandle(l2_ndisuio_global->stop_request); - l2_ndisuio_global->stop_request = NULL; - } - if (l2_ndisuio_global->ready_for_read) { - CloseHandle(l2_ndisuio_global->ready_for_read); - l2_ndisuio_global->ready_for_read = NULL; - } - if (l2_ndisuio_global->rx_processed) { - CloseHandle(l2_ndisuio_global->rx_processed); - l2_ndisuio_global->rx_processed = NULL; - } - eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); - os_free(l2); - return NULL; - } - - l2_ndisuio_global->rx_thread = CreateThread(NULL, 0, - l2_packet_rx_thread, l2, 0, - NULL); - if (l2_ndisuio_global->rx_thread == NULL) { - wpa_printf(MSG_INFO, "L2(NDISUIO): Failed to create RX " - "thread: %d", (int) GetLastError()); - eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); - CloseHandle(l2_ndisuio_global->stop_request); - l2_ndisuio_global->stop_request = NULL; - os_free(l2); - return NULL; - } -#else /* _WIN32_WCE */ - l2_ndisuio_start_read(l2, 0); -#endif /* _WIN32_WCE */ - - return l2; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - - if (l2_ndisuio_global) { - l2_ndisuio_global->refcount--; - l2_ndisuio_global->l2[l2_ndisuio_global->refcount] = NULL; - if (l2_ndisuio_global->refcount) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): restore filtering " - "ethertype to %04x", - l2_ndisuio_global->first_proto); - l2_ndisuio_set_ether_type( - l2_ndisuio_global->first_proto); - return; - } - -#ifdef _WIN32_WCE - wpa_printf(MSG_DEBUG, "L2(NDISUIO): Waiting for RX thread to " - "stop"); - SetEvent(l2_ndisuio_global->stop_request); - /* - * Cancel pending ReadFile() in the RX thread (if we were still - * connected at this point). - */ - if (!DeviceIoControl(driver_ndis_get_ndisuio_handle(), - IOCTL_CANCEL_READ, NULL, 0, NULL, 0, NULL, - NULL)) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): IOCTL_CANCEL_READ " - "failed: %d", (int) GetLastError()); - /* RX thread will exit blocking ReadFile once NDISUIO - * notices that the adapter is disconnected. */ - } - WaitForSingleObject(l2_ndisuio_global->rx_thread, INFINITE); - wpa_printf(MSG_DEBUG, "L2(NDISUIO): RX thread exited"); - CloseHandle(l2_ndisuio_global->rx_thread); - CloseHandle(l2_ndisuio_global->stop_request); - CloseHandle(l2_ndisuio_global->ready_for_read); - CloseHandle(l2_ndisuio_global->rx_processed); -#endif /* _WIN32_WCE */ - - os_free(l2_ndisuio_global); - l2_ndisuio_global = NULL; - } - -#ifndef _WIN32_WCE - CancelIo(driver_ndis_get_ndisuio_handle()); -#endif /* _WIN32_WCE */ - - eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); - CloseHandle(l2->rx_avail); - os_free(l2); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - return -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ -}