18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant / Windows Named Pipe -based control interface 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-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 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ctrl_iface.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_ctrl.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __MINGW32_VERSION 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* mingw-w32api v3.1 does not yet include sddl.h, so define needed parts here 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define SDDL_REVISION_1 1 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtBOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA( 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LPCSTR, DWORD, PSECURITY_DESCRIPTOR *, PULONG); 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtBOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW( 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LPCWSTR, DWORD, PSECURITY_DESCRIPTOR *, PULONG); 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define ConvertStringSecurityDescriptorToSecurityDescriptor \ 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtConvertStringSecurityDescriptorToSecurityDescriptorW 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define ConvertStringSecurityDescriptorToSecurityDescriptor \ 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtConvertStringSecurityDescriptorToSecurityDescriptorA 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* __MINGW32_VERSION */ 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WINNT 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _WIN32_WINNT 0x0500 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sddl.h> 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __MINGW32_VERSION */ 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef WPA_SUPPLICANT_NAMED_PIPE 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant" 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE) 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Per-interface ctrl_iface */ 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define REQUEST_BUFSIZE 256 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define REPLY_BUFSIZE 4096 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_priv; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct wpa_ctrl_dst - Internal data structure of control interface clients 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This structure is used to store information about registered control 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * interface monitors into struct wpa_supplicant. This data is private to 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ctrl_iface_named_pipe.c and should not be touched directly from other files. 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_ctrl_dst { 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Note: OVERLAPPED must be the first member of struct wpa_ctrl_dst */ 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt OVERLAPPED overlap; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *next, *prev; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_priv *priv; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HANDLE pipe; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int attached; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int debug_level; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int errors; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char req_buf[REQUEST_BUFSIZE]; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *rsp_buf; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int used; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_priv { 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *ctrl_dst; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SECURITY_ATTRIBUTES attr; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sec_attr_set; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int level, const char *buf, 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ctrl_close_pipe(struct wpa_ctrl_dst *dst); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_receive(void *, void *); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic VOID WINAPI ctrl_iface_read_completed(DWORD err, DWORD bytes, 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LPOVERLAPPED overlap); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_global_dst; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void global_close_pipe(struct wpa_global_dst *dst); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_global_iface_receive(void *eloop_data, 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *user_ctx); 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic VOID WINAPI global_iface_read_completed(DWORD err, DWORD bytes, 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LPOVERLAPPED overlap); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ctrl_broken_pipe(HANDLE pipe, int used) 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD err; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (PeekNamedPipe(pipe, NULL, 0, NULL, NULL, NULL)) 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = GetLastError(); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err == ERROR_BROKEN_PIPE || (err == ERROR_BAD_PIPE && used)) 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ctrl_flush_broken_pipes(struct ctrl_iface_priv *priv) 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst, *next; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = priv->ctrl_dst; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (dst) { 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next = dst->next; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctrl_broken_pipe(dst->pipe, dst->used)) { 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: closing broken pipe %p", 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctrl_close_pipe(dst); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = next; 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ctrl_open_pipe(struct ctrl_iface_priv *priv) 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD err; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TCHAR name[256]; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = os_zalloc(sizeof(*dst)); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst == NULL) 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Open pipe %p", dst); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->priv = priv; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->debug_level = MSG_INFO; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->pipe = INVALID_HANDLE_VALUE; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->overlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->overlap.hEvent == NULL) { 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "CTRL: CreateEvent failed: %d", 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_event(dst->overlap.hEvent, 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(dst->overlap.hEvent), 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_ctrl_iface_receive, dst, NULL); 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"), 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->wpa_s->ifname); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* UNICODE */ 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s", 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->wpa_s->ifname); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* UNICODE */ 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add support for configuring access list for the pipe */ 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->pipe = CreateNamedPipe(name, 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PIPE_TYPE_MESSAGE | 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PIPE_READMODE_MESSAGE | 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PIPE_WAIT, 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15, REPLY_BUFSIZE, REQUEST_BUFSIZE, 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1000, 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sec_attr_set ? &priv->attr : NULL); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->pipe == INVALID_HANDLE_VALUE) { 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "CTRL: CreateNamedPipe failed: %d", 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ConnectNamedPipe(dst->pipe, &dst->overlap)) { 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "CTRL: ConnectNamedPipe failed: %d", 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(dst->pipe); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = GetLastError(); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (err) { 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ERROR_IO_PENDING: 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: connection in " 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "progress"); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ERROR_PIPE_CONNECTED: 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: already " 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "connected"); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SetEvent(dst->overlap.hEvent)) 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* fall through */ 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe error: %d", 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) err); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(dst->pipe); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->next = priv->ctrl_dst; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->next) 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->next->prev = dst; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->ctrl_dst = dst; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctrl_close_pipe(dst); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ctrl_close_pipe(struct wpa_ctrl_dst *dst) 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: close pipe %p", dst); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->overlap.hEvent) { 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_event(dst->overlap.hEvent, 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(dst->overlap.hEvent)); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(dst->overlap.hEvent); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->pipe != INVALID_HANDLE_VALUE) { 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Could use FlushFileBuffers() here to guarantee that all data 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * gets delivered to the client, but that can block, so let's 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not do this for now. 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FlushFileBuffers(dst->pipe); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(dst->pipe); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->prev) 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->prev->next = dst->next; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->priv->ctrl_dst = dst->next; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->next) 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->next->prev = dst->prev; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst->rsp_buf); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst); 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic VOID WINAPI ctrl_iface_write_completed(DWORD err, DWORD bytes, 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LPOVERLAPPED overlap) 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst = (struct wpa_ctrl_dst *) overlap; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Overlapped write completed: dst=%p " 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "err=%d bytes=%d", dst, (int) err, (int) bytes); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err) { 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctrl_close_pipe(dst); 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst->rsp_buf); 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->rsp_buf = NULL; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ReadFileEx(dst->pipe, dst->req_buf, sizeof(dst->req_buf), 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &dst->overlap, ctrl_iface_read_completed)) { 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: ReadFileEx failed: %d", 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctrl_close_pipe(dst); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Overlapped read started for %p", dst); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_rx(struct wpa_ctrl_dst *dst, size_t len) 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s = dst->priv->wpa_s; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *reply = NULL, *send_buf; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t reply_len = 0, send_len; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int new_attached = 0; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf = dst->req_buf; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->used = 1; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len >= REQUEST_BUFSIZE) 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = REQUEST_BUFSIZE - 1; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[len] = '\0'; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(buf, "ATTACH") == 0) { 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->attached = 1; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached"); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_attached = 1; 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 2; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strcmp(buf, "DETACH") == 0) { 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->attached = 0; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached"); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 2; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", buf + 6); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->debug_level = atoi(buf + 6); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 2; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf, 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &reply_len); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply) { 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_buf = reply; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = reply_len; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (reply_len == 2) { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_buf = "OK\n"; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = 3; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_buf = "FAIL\n"; 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = 5; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst->rsp_buf); 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->rsp_buf = os_malloc(send_len); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->rsp_buf == NULL) { 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctrl_close_pipe(dst); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(reply); 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(dst->rsp_buf, send_buf, send_len); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(reply); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!WriteFileEx(dst->pipe, dst->rsp_buf, send_len, &dst->overlap, 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctrl_iface_write_completed)) { 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: WriteFileEx failed: %d", 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctrl_close_pipe(dst); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Overlapped write started for %p", 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (new_attached) 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_ctrl_attached(wpa_s->eapol); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic VOID WINAPI ctrl_iface_read_completed(DWORD err, DWORD bytes, 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LPOVERLAPPED overlap) 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst = (struct wpa_ctrl_dst *) overlap; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Overlapped read completed: dst=%p err=%d " 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "bytes=%d", dst, (int) err, (int) bytes); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err == 0 && bytes > 0) 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_ctrl_iface_rx(dst, bytes); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_receive(void *eloop_data, void *user_ctx) 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst = eloop_data; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_priv *priv = dst->priv; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD bytes; 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: wpa_supplicant_ctrl_iface_receive"); 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ResetEvent(dst->overlap.hEvent); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!GetOverlappedResult(dst->pipe, &dst->overlap, &bytes, FALSE)) { 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult failed: %d", 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult: New client " 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "connected"); 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Open a new named pipe for the next client. */ 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctrl_open_pipe(priv); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Use write completion function to start reading a command */ 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctrl_iface_write_completed(0, 0, &dst->overlap); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctrl_flush_broken_pipes(priv); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ctrl_iface_parse(struct ctrl_iface_priv *priv, const char *params) 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *sddl = NULL; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TCHAR *t_sddl; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(params, "SDDL=", 5) == 0) 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sddl = params + 5; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sddl) { 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sddl = os_strstr(params, " SDDL="); 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sddl) 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sddl += 6; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sddl) 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: SDDL='%s'", sddl); 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&priv->attr, 0, sizeof(priv->attr)); 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->attr.nLength = sizeof(priv->attr); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->attr.bInheritHandle = FALSE; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t_sddl = wpa_strdup_tchar(sddl); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (t_sddl == NULL) 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ConvertStringSecurityDescriptorToSecurityDescriptor( 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t_sddl, SDDL_REVISION_1, 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (PSECURITY_DESCRIPTOR *) (void *) 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &priv->attr.lpSecurityDescriptor, 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL)) { 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(t_sddl); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "CTRL: SDDL='%s' - could not convert to " 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "security descriptor: %d", 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sddl, (int) GetLastError()); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(t_sddl); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sec_attr_set = 1; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *txt, size_t len) 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s == NULL || wpa_s->ctrl_iface == NULL) 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_priv * 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_priv *priv; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv = os_zalloc(sizeof(*priv)); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv == NULL) 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->wpa_s = wpa_s; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->conf->ctrl_interface == NULL) 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctrl_iface_parse(priv, wpa_s->conf->ctrl_interface) < 0) { 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctrl_open_pipe(priv) < 0) { 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (priv->ctrl_dst) 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctrl_close_pipe(priv->ctrl_dst); 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sec_attr_set) 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LocalFree(priv->attr.lpSecurityDescriptor); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int level, const char *buf, 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst, *next; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char levelstr[10]; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int idx; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *sbuf; 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int llen; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD written; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = priv->ctrl_dst; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst == NULL) 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt llen = os_strlen(levelstr); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sbuf = os_malloc(llen + len); 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sbuf == NULL) 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sbuf, levelstr, llen); 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sbuf + llen, buf, len); 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx = 0; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (dst) { 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next = dst->next; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->attached && level >= dst->debug_level) { 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %p", 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst); 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!WriteFile(dst->pipe, sbuf, llen + len, &written, 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL)) { 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: WriteFile to dst " 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%p failed: %d", 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst, (int) GetLastError()); 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->errors++; 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->errors > 10) 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctrl_close_pipe(dst); 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->errors = 0; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx++; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = next; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sbuf); 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor", 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->wpa_s->ifname); 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->ctrl_dst == NULL) 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WaitForSingleObject(priv->ctrl_dst->pipe, INFINITE); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Global ctrl_iface */ 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_global_priv; 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_global_dst { 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Note: OVERLAPPED must be the first member of struct wpa_global_dst 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt OVERLAPPED overlap; 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_global_dst *next, *prev; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_global_priv *priv; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HANDLE pipe; 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char req_buf[REQUEST_BUFSIZE]; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *rsp_buf; 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int used; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_global_priv { 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_global *global; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_global_dst *ctrl_dst; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void global_flush_broken_pipes(struct ctrl_iface_global_priv *priv) 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_global_dst *dst, *next; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = priv->ctrl_dst; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (dst) { 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next = dst->next; 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctrl_broken_pipe(dst->pipe, dst->used)) { 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: closing broken pipe %p", 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global_close_pipe(dst); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = next; 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int global_open_pipe(struct ctrl_iface_global_priv *priv) 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_global_dst *dst; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD err; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = os_zalloc(sizeof(*dst)); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst == NULL) 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Open pipe %p", dst); 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->priv = priv; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->pipe = INVALID_HANDLE_VALUE; 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->overlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->overlap.hEvent == NULL) { 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "CTRL: CreateEvent failed: %d", 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_event(dst->overlap.hEvent, 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(dst->overlap.hEvent), 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_global_iface_receive, dst, NULL); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add support for configuring access list for the pipe */ 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->pipe = CreateNamedPipe(NAMED_PIPE_PREFIX, 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PIPE_TYPE_MESSAGE | 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PIPE_READMODE_MESSAGE | 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PIPE_WAIT, 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10, REPLY_BUFSIZE, REQUEST_BUFSIZE, 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1000, NULL); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->pipe == INVALID_HANDLE_VALUE) { 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "CTRL: CreateNamedPipe failed: %d", 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ConnectNamedPipe(dst->pipe, &dst->overlap)) { 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "CTRL: ConnectNamedPipe failed: %d", 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(dst->pipe); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = GetLastError(); 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (err) { 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ERROR_IO_PENDING: 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: connection in " 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "progress"); 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ERROR_PIPE_CONNECTED: 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: already " 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "connected"); 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SetEvent(dst->overlap.hEvent)) 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* fall through */ 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe error: %d", 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) err); 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(dst->pipe); 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst); 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->next = priv->ctrl_dst; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->next) 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->next->prev = dst; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->ctrl_dst = dst; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global_close_pipe(dst); 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void global_close_pipe(struct wpa_global_dst *dst) 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: close pipe %p", dst); 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->overlap.hEvent) { 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_event(dst->overlap.hEvent, 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(dst->overlap.hEvent)); 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(dst->overlap.hEvent); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->pipe != INVALID_HANDLE_VALUE) { 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Could use FlushFileBuffers() here to guarantee that all data 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * gets delivered to the client, but that can block, so let's 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not do this for now. 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FlushFileBuffers(dst->pipe); 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CloseHandle(dst->pipe); 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->prev) 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->prev->next = dst->next; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->priv->ctrl_dst = dst->next; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->next) 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->next->prev = dst->prev; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst->rsp_buf); 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst); 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic VOID WINAPI global_iface_write_completed(DWORD err, DWORD bytes, 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LPOVERLAPPED overlap) 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_global_dst *dst = (struct wpa_global_dst *) overlap; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Overlapped write completed: dst=%p " 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "err=%d bytes=%d", dst, (int) err, (int) bytes); 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err) { 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global_close_pipe(dst); 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst->rsp_buf); 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->rsp_buf = NULL; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ReadFileEx(dst->pipe, dst->req_buf, sizeof(dst->req_buf), 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &dst->overlap, global_iface_read_completed)) { 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: ReadFileEx failed: %d", 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global_close_pipe(dst); 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: if this was the pipe waiting for new global 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * connections, at this point there are no open global pipes.. 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Should try to open a new pipe.. */ 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Overlapped read started for %p", dst); 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_global_iface_rx(struct wpa_global_dst *dst, 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_global *global = dst->priv->global; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *reply = NULL, *send_buf; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t reply_len = 0, send_len; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf = dst->req_buf; 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->used = 1; 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len >= REQUEST_BUFSIZE) 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = REQUEST_BUFSIZE - 1; 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[len] = '\0'; 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = wpa_supplicant_global_ctrl_iface_process(global, buf, 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &reply_len); 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply) { 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_buf = reply; 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = reply_len; 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (reply_len) { 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_buf = "FAIL\n"; 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = 5; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst->rsp_buf); 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->rsp_buf = NULL; 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst->rsp_buf); 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->rsp_buf = os_malloc(send_len); 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->rsp_buf == NULL) { 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global_close_pipe(dst); 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(reply); 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(dst->rsp_buf, send_buf, send_len); 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(reply); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!WriteFileEx(dst->pipe, dst->rsp_buf, send_len, &dst->overlap, 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global_iface_write_completed)) { 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: WriteFileEx failed: %d", 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global_close_pipe(dst); 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Overlapped write started for %p", 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst); 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic VOID WINAPI global_iface_read_completed(DWORD err, DWORD bytes, 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LPOVERLAPPED overlap) 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_global_dst *dst = (struct wpa_global_dst *) overlap; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Overlapped read completed: dst=%p err=%d " 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "bytes=%d", dst, (int) err, (int) bytes); 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err == 0 && bytes > 0) 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_global_iface_rx(dst, bytes); 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_global_iface_receive(void *eloop_data, 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *user_ctx) 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_global_dst *dst = eloop_data; 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_global_priv *priv = dst->priv; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DWORD bytes; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: wpa_supplicant_global_iface_receive"); 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ResetEvent(dst->overlap.hEvent); 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!GetOverlappedResult(dst->pipe, &dst->overlap, &bytes, FALSE)) { 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult failed: %d", 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) GetLastError()); 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult: New client " 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "connected"); 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Open a new named pipe for the next client. */ 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global_open_pipe(priv) < 0) { 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: global_open_pipe failed"); 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Use write completion function to start reading a command */ 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global_iface_write_completed(0, 0, &dst->overlap); 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global_flush_broken_pipes(priv); 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_global_priv * 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_global_priv *priv; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv = os_zalloc(sizeof(*priv)); 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv == NULL) 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->global = global; 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global_open_pipe(priv) < 0) { 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (priv->ctrl_dst) 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global_close_pipe(priv->ctrl_dst); 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 830