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; DWORD thread_id; l2 = os_zalloc(sizeof(struct l2_packet_data)); if (l2 == NULL) return NULL; if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0) os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); else os_snprintf(l2->ifname, sizeof(l2->ifname), "\\Device\\NPF_%s", 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_packet_init_libpcap(l2, protocol)) { os_free(l2); return NULL; } l2->rx_avail = CreateEvent(NULL, TRUE, FALSE, NULL); l2->rx_done = CreateEvent(NULL, TRUE, FALSE, NULL); l2->rx_notify = CreateEvent(NULL, TRUE, FALSE, NULL); if (l2->rx_avail == NULL || l2->rx_done == NULL || l2->rx_notify == NULL) { CloseHandle(l2->rx_avail); CloseHandle(l2->rx_done); CloseHandle(l2->rx_notify); pcap_close(l2->pcap); os_free(l2); return NULL; } eloop_register_event(l2->rx_avail, sizeof(l2->rx_avail), l2_packet_rx_event, l2, NULL); l2->running = 1; l2->rx_thread = CreateThread(NULL, 0, l2_packet_receive_thread, l2, 0, &thread_id); return l2; }
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; }
static int global_open_pipe(struct ctrl_iface_global_priv *priv) { struct wpa_global_dst *dst; DWORD err; dst = os_zalloc(sizeof(*dst)); if (dst == NULL) return -1; wpa_printf(MSG_DEBUG, "CTRL: Open pipe %p", dst); dst->priv = priv; dst->pipe = INVALID_HANDLE_VALUE; dst->overlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); if (dst->overlap.hEvent == NULL) { wpa_printf(MSG_ERROR, "CTRL: CreateEvent failed: %d", (int) GetLastError()); goto fail; } eloop_register_event(dst->overlap.hEvent, sizeof(dst->overlap.hEvent), wpa_supplicant_global_iface_receive, dst, NULL); /* TODO: add support for configuring access list for the pipe */ dst->pipe = CreateNamedPipe(NAMED_PIPE_PREFIX, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 10, REPLY_BUFSIZE, REQUEST_BUFSIZE, 1000, NULL); if (dst->pipe == INVALID_HANDLE_VALUE) { wpa_printf(MSG_ERROR, "CTRL: CreateNamedPipe failed: %d", (int) GetLastError()); goto fail; } if (ConnectNamedPipe(dst->pipe, &dst->overlap)) { wpa_printf(MSG_ERROR, "CTRL: ConnectNamedPipe failed: %d", (int) GetLastError()); CloseHandle(dst->pipe); os_free(dst); return -1; } err = GetLastError(); switch (err) { case ERROR_IO_PENDING: wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: connection in " "progress"); break; case ERROR_PIPE_CONNECTED: wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: already " "connected"); if (SetEvent(dst->overlap.hEvent)) break; /* fall through */ default: wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe error: %d", (int) err); CloseHandle(dst->pipe); os_free(dst); return -1; } dst->next = priv->ctrl_dst; if (dst->next) dst->next->prev = dst; priv->ctrl_dst = dst; return 0; fail: global_close_pipe(dst); return -1; }