1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA Supplicant / Windows Named Pipe -based control interface
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation.
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license.
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details.
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h"
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eloop.h"
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "config.h"
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eapol_supp/eapol_supp_sm.h"
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wpa_supplicant_i.h"
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "ctrl_iface.h"
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wpa_ctrl.h"
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef __MINGW32_VERSION
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* mingw-w32api v3.1 does not yet include sddl.h, so define needed parts here
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define SDDL_REVISION_1 1
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtBOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LPCSTR, DWORD, PSECURITY_DESCRIPTOR *, PULONG);
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtBOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LPCWSTR, DWORD, PSECURITY_DESCRIPTOR *, PULONG);
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef UNICODE
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define ConvertStringSecurityDescriptorToSecurityDescriptor \
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtConvertStringSecurityDescriptorToSecurityDescriptorW
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define ConvertStringSecurityDescriptorToSecurityDescriptor \
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtConvertStringSecurityDescriptorToSecurityDescriptorA
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* __MINGW32_VERSION */
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef _WIN32_WINNT
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define _WIN32_WINNT 0x0500
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <sddl.h>
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* __MINGW32_VERSION */
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef WPA_SUPPLICANT_NAMED_PIPE
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* Per-interface ctrl_iface */
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define REQUEST_BUFSIZE 256
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define REPLY_BUFSIZE 4096
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ctrl_iface_priv;
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/**
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * struct wpa_ctrl_dst - Internal data structure of control interface clients
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This structure is used to store information about registered control
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * interface monitors into struct wpa_supplicant. This data is private to
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * ctrl_iface_named_pipe.c and should not be touched directly from other files.
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_ctrl_dst {
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Note: OVERLAPPED must be the first member of struct wpa_ctrl_dst */
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	OVERLAPPED overlap;
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ctrl_dst *next, *prev;
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ctrl_iface_priv *priv;
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HANDLE pipe;
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int attached;
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int debug_level;
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int errors;
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char req_buf[REQUEST_BUFSIZE];
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *rsp_buf;
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int used;
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ctrl_iface_priv {
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_supplicant *wpa_s;
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ctrl_dst *ctrl_dst;
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SECURITY_ATTRIBUTES attr;
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int sec_attr_set;
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   int level, const char *buf,
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   size_t len);
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void ctrl_close_pipe(struct wpa_ctrl_dst *dst);
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_ctrl_iface_receive(void *, void *);
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic VOID WINAPI ctrl_iface_read_completed(DWORD err, DWORD bytes,
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					     LPOVERLAPPED overlap);
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_global_dst;
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void global_close_pipe(struct wpa_global_dst *dst);
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_global_iface_receive(void *eloop_data,
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						void *user_ctx);
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic VOID WINAPI global_iface_read_completed(DWORD err, DWORD bytes,
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					       LPOVERLAPPED overlap);
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ctrl_broken_pipe(HANDLE pipe, int used)
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD err;
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (PeekNamedPipe(pipe, NULL, 0, NULL, NULL, NULL))
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	err = GetLastError();
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (err == ERROR_BROKEN_PIPE || (err == ERROR_BAD_PIPE && used))
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 1;
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void ctrl_flush_broken_pipes(struct ctrl_iface_priv *priv)
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ctrl_dst *dst, *next;
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst = priv->ctrl_dst;
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (dst) {
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		next = dst->next;
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ctrl_broken_pipe(dst->pipe, dst->used)) {
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "CTRL: closing broken pipe %p",
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   dst);
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ctrl_close_pipe(dst);
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst = next;
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ctrl_open_pipe(struct ctrl_iface_priv *priv)
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ctrl_dst *dst;
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD err;
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	TCHAR name[256];
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst = os_zalloc(sizeof(*dst));
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst == NULL)
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: Open pipe %p", dst);
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->priv = priv;
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->debug_level = MSG_INFO;
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->pipe = INVALID_HANDLE_VALUE;
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->overlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->overlap.hEvent == NULL) {
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "CTRL: CreateEvent failed: %d",
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		goto fail;
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eloop_register_event(dst->overlap.hEvent,
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			     sizeof(dst->overlap.hEvent),
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			     wpa_supplicant_ctrl_iface_receive, dst, NULL);
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef UNICODE
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	_snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   priv->wpa_s->ifname);
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* UNICODE */
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    priv->wpa_s->ifname);
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* UNICODE */
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* TODO: add support for configuring access list for the pipe */
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->pipe = CreateNamedPipe(name,
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    PIPE_TYPE_MESSAGE |
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    PIPE_READMODE_MESSAGE |
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    PIPE_WAIT,
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    15, REPLY_BUFSIZE, REQUEST_BUFSIZE,
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    1000,
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    priv->sec_attr_set ? &priv->attr : NULL);
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->pipe == INVALID_HANDLE_VALUE) {
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "CTRL: CreateNamedPipe failed: %d",
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		goto fail;
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ConnectNamedPipe(dst->pipe, &dst->overlap)) {
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "CTRL: ConnectNamedPipe failed: %d",
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CloseHandle(dst->pipe);
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(dst);
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	err = GetLastError();
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (err) {
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case ERROR_IO_PENDING:
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: connection in "
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "progress");
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case ERROR_PIPE_CONNECTED:
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: already "
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "connected");
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (SetEvent(dst->overlap.hEvent))
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* fall through */
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe error: %d",
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) err);
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CloseHandle(dst->pipe);
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(dst);
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->next = priv->ctrl_dst;
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->next)
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst->next->prev = dst;
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	priv->ctrl_dst = dst;
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtfail:
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctrl_close_pipe(dst);
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void ctrl_close_pipe(struct wpa_ctrl_dst *dst)
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: close pipe %p", dst);
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->overlap.hEvent) {
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		eloop_unregister_event(dst->overlap.hEvent,
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       sizeof(dst->overlap.hEvent));
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CloseHandle(dst->overlap.hEvent);
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->pipe != INVALID_HANDLE_VALUE) {
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/*
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * Could use FlushFileBuffers() here to guarantee that all data
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * gets delivered to the client, but that can block, so let's
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * not do this for now.
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * FlushFileBuffers(dst->pipe);
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 */
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CloseHandle(dst->pipe);
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->prev)
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst->prev->next = dst->next;
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst->priv->ctrl_dst = dst->next;
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->next)
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst->next->prev = dst->prev;
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(dst->rsp_buf);
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(dst);
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic VOID WINAPI ctrl_iface_write_completed(DWORD err, DWORD bytes,
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					      LPOVERLAPPED overlap)
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ctrl_dst *dst = (struct wpa_ctrl_dst *) overlap;
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: Overlapped write completed: dst=%p "
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "err=%d bytes=%d", dst, (int) err, (int) bytes);
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (err) {
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctrl_close_pipe(dst);
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(dst->rsp_buf);
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->rsp_buf = NULL;
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!ReadFileEx(dst->pipe, dst->req_buf, sizeof(dst->req_buf),
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			&dst->overlap, ctrl_iface_read_completed)) {
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: ReadFileEx failed: %d",
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctrl_close_pipe(dst);
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: Overlapped read started for %p", dst);
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_ctrl_iface_rx(struct wpa_ctrl_dst *dst, size_t len)
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_supplicant *wpa_s = dst->priv->wpa_s;
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *reply = NULL, *send_buf;
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t reply_len = 0, send_len;
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int new_attached = 0;
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *buf = dst->req_buf;
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->used = 1;
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (len >= REQUEST_BUFSIZE)
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		len = REQUEST_BUFSIZE - 1;
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf[len] = '\0';
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (os_strcmp(buf, "ATTACH") == 0) {
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst->attached = 1;
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached");
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		new_attached = 1;
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		reply_len = 2;
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else if (os_strcmp(buf, "DETACH") == 0) {
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst->attached = 0;
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached");
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		reply_len = 2;
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", buf + 6);
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst->debug_level = atoi(buf + 6);
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		reply_len = 2;
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf,
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt							  &reply_len);
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (reply) {
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		send_buf = reply;
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		send_len = reply_len;
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else if (reply_len == 2) {
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		send_buf = "OK\n";
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		send_len = 3;
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		send_buf = "FAIL\n";
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		send_len = 5;
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(dst->rsp_buf);
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->rsp_buf = os_malloc(send_len);
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->rsp_buf == NULL) {
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctrl_close_pipe(dst);
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(reply);
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(dst->rsp_buf, send_buf, send_len);
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(reply);
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!WriteFileEx(dst->pipe, dst->rsp_buf, send_len, &dst->overlap,
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			 ctrl_iface_write_completed)) {
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: WriteFileEx failed: %d",
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctrl_close_pipe(dst);
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: Overlapped write started for %p",
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   dst);
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (new_attached)
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		eapol_sm_notify_ctrl_attached(wpa_s->eapol);
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic VOID WINAPI ctrl_iface_read_completed(DWORD err, DWORD bytes,
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					     LPOVERLAPPED overlap)
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ctrl_dst *dst = (struct wpa_ctrl_dst *) overlap;
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: Overlapped read completed: dst=%p err=%d "
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "bytes=%d", dst, (int) err, (int) bytes);
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (err == 0 && bytes > 0)
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_supplicant_ctrl_iface_rx(dst, bytes);
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_ctrl_iface_receive(void *eloop_data, void *user_ctx)
364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ctrl_dst *dst = eloop_data;
366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ctrl_iface_priv *priv = dst->priv;
367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD bytes;
368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: wpa_supplicant_ctrl_iface_receive");
370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ResetEvent(dst->overlap.hEvent);
371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!GetOverlappedResult(dst->pipe, &dst->overlap, &bytes, FALSE)) {
373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult failed: %d",
374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult: New client "
378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "connected");
379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Open a new named pipe for the next client. */
381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctrl_open_pipe(priv);
382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Use write completion function to start reading a command */
384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctrl_iface_write_completed(0, 0, &dst->overlap);
385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctrl_flush_broken_pipes(priv);
387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ctrl_iface_parse(struct ctrl_iface_priv *priv, const char *params)
391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const char *sddl = NULL;
393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	TCHAR *t_sddl;
394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (os_strncmp(params, "SDDL=", 5) == 0)
396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sddl = params + 5;
397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!sddl) {
398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sddl = os_strstr(params, " SDDL=");
399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sddl)
400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sddl += 6;
401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!sddl)
404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: SDDL='%s'", sddl);
407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&priv->attr, 0, sizeof(priv->attr));
408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	priv->attr.nLength = sizeof(priv->attr);
409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	priv->attr.bInheritHandle = FALSE;
410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	t_sddl = wpa_strdup_tchar(sddl);
411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (t_sddl == NULL)
412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    t_sddl, SDDL_REVISION_1,
415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    (PSECURITY_DESCRIPTOR *) (void *)
416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    &priv->attr.lpSecurityDescriptor,
417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    NULL)) {
418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(t_sddl);
419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "CTRL: SDDL='%s' - could not convert to "
420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "security descriptor: %d",
421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   sddl, (int) GetLastError());
422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(t_sddl);
425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	priv->sec_attr_set = 1;
427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					     const char *txt, size_t len)
434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa_s == NULL || wpa_s->ctrl_iface == NULL)
437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len);
439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ctrl_iface_priv *
443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ctrl_iface_priv *priv;
446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	priv = os_zalloc(sizeof(*priv));
448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (priv == NULL)
449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	priv->wpa_s = wpa_s;
451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa_s->conf->ctrl_interface == NULL)
453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return priv;
454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ctrl_iface_parse(priv, wpa_s->conf->ctrl_interface) < 0) {
456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(priv);
457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ctrl_open_pipe(priv) < 0) {
461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(priv);
462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return priv;
468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (priv->ctrl_dst)
474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctrl_close_pipe(priv->ctrl_dst);
475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (priv->sec_attr_set)
476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		LocalFree(priv->attr.lpSecurityDescriptor);
477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(priv);
478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   int level, const char *buf,
483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   size_t len)
484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ctrl_dst *dst, *next;
486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char levelstr[10];
487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int idx;
488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *sbuf;
489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int llen;
490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD written;
491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst = priv->ctrl_dst;
493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst == NULL)
494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	llen = os_strlen(levelstr);
499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sbuf = os_malloc(llen + len);
500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sbuf == NULL)
501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(sbuf, levelstr, llen);
504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(sbuf + llen, buf, len);
505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	idx = 0;
507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (dst) {
508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		next = dst->next;
509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (dst->attached && level >= dst->debug_level) {
510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %p",
511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   dst);
512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (!WriteFile(dst->pipe, sbuf, llen + len, &written,
513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       NULL)) {
514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				wpa_printf(MSG_DEBUG, "CTRL: WriteFile to dst "
515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   "%p failed: %d",
516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   dst, (int) GetLastError());
517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				dst->errors++;
518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				if (dst->errors > 10)
519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					ctrl_close_pipe(dst);
520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			} else
521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				dst->errors = 0;
522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		idx++;
524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst = next;
525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(sbuf);
527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   priv->wpa_s->ifname);
534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (priv->ctrl_dst == NULL)
535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	WaitForSingleObject(priv->ctrl_dst->pipe, INFINITE);
537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* Global ctrl_iface */
541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ctrl_iface_global_priv;
543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_global_dst {
545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Note: OVERLAPPED must be the first member of struct wpa_global_dst
546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 */
547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	OVERLAPPED overlap;
548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_global_dst *next, *prev;
549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ctrl_iface_global_priv *priv;
550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HANDLE pipe;
551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char req_buf[REQUEST_BUFSIZE];
552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *rsp_buf;
553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int used;
554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ctrl_iface_global_priv {
557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_global *global;
558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_global_dst *ctrl_dst;
559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void global_flush_broken_pipes(struct ctrl_iface_global_priv *priv)
563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_global_dst *dst, *next;
565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst = priv->ctrl_dst;
567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (dst) {
569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		next = dst->next;
570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ctrl_broken_pipe(dst->pipe, dst->used)) {
571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "CTRL: closing broken pipe %p",
572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   dst);
573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			global_close_pipe(dst);
574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst = next;
576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int global_open_pipe(struct ctrl_iface_global_priv *priv)
581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_global_dst *dst;
583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD err;
584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst = os_zalloc(sizeof(*dst));
586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst == NULL)
587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: Open pipe %p", dst);
589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->priv = priv;
591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->pipe = INVALID_HANDLE_VALUE;
592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->overlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->overlap.hEvent == NULL) {
595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "CTRL: CreateEvent failed: %d",
596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		goto fail;
598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eloop_register_event(dst->overlap.hEvent,
601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			     sizeof(dst->overlap.hEvent),
602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			     wpa_supplicant_global_iface_receive, dst, NULL);
603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* TODO: add support for configuring access list for the pipe */
605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->pipe = CreateNamedPipe(NAMED_PIPE_PREFIX,
606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    PIPE_TYPE_MESSAGE |
608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    PIPE_READMODE_MESSAGE |
609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    PIPE_WAIT,
610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    10, REPLY_BUFSIZE, REQUEST_BUFSIZE,
611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    1000, NULL);
612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->pipe == INVALID_HANDLE_VALUE) {
613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "CTRL: CreateNamedPipe failed: %d",
614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		goto fail;
616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ConnectNamedPipe(dst->pipe, &dst->overlap)) {
619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "CTRL: ConnectNamedPipe failed: %d",
620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CloseHandle(dst->pipe);
622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(dst);
623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	err = GetLastError();
627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (err) {
628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case ERROR_IO_PENDING:
629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: connection in "
630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "progress");
631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case ERROR_PIPE_CONNECTED:
633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: already "
634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "connected");
635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (SetEvent(dst->overlap.hEvent))
636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* fall through */
638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe error: %d",
640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) err);
641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CloseHandle(dst->pipe);
642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(dst);
643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->next = priv->ctrl_dst;
647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->next)
648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst->next->prev = dst;
649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	priv->ctrl_dst = dst;
650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtfail:
654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	global_close_pipe(dst);
655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void global_close_pipe(struct wpa_global_dst *dst)
660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: close pipe %p", dst);
662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->overlap.hEvent) {
664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		eloop_unregister_event(dst->overlap.hEvent,
665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       sizeof(dst->overlap.hEvent));
666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CloseHandle(dst->overlap.hEvent);
667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->pipe != INVALID_HANDLE_VALUE) {
670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/*
671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * Could use FlushFileBuffers() here to guarantee that all data
672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * gets delivered to the client, but that can block, so let's
673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * not do this for now.
674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * FlushFileBuffers(dst->pipe);
675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 */
676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CloseHandle(dst->pipe);
677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->prev)
680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst->prev->next = dst->next;
681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else
682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst->priv->ctrl_dst = dst->next;
683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->next)
684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst->next->prev = dst->prev;
685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(dst->rsp_buf);
687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(dst);
688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic VOID WINAPI global_iface_write_completed(DWORD err, DWORD bytes,
692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						LPOVERLAPPED overlap)
693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_global_dst *dst = (struct wpa_global_dst *) overlap;
695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: Overlapped write completed: dst=%p "
696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "err=%d bytes=%d", dst, (int) err, (int) bytes);
697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (err) {
698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		global_close_pipe(dst);
699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(dst->rsp_buf);
703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->rsp_buf = NULL;
704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!ReadFileEx(dst->pipe, dst->req_buf, sizeof(dst->req_buf),
706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			&dst->overlap, global_iface_read_completed)) {
707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: ReadFileEx failed: %d",
708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		global_close_pipe(dst);
710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* FIX: if this was the pipe waiting for new global
711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * connections, at this point there are no open global pipes..
712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * Should try to open a new pipe.. */
713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: Overlapped read started for %p", dst);
716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_global_iface_rx(struct wpa_global_dst *dst,
720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   size_t len)
721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_global *global = dst->priv->global;
723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *reply = NULL, *send_buf;
724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t reply_len = 0, send_len;
725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *buf = dst->req_buf;
726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->used = 1;
728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (len >= REQUEST_BUFSIZE)
729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		len = REQUEST_BUFSIZE - 1;
730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf[len] = '\0';
731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	reply = wpa_supplicant_global_ctrl_iface_process(global, buf,
733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt							 &reply_len);
734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (reply) {
735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		send_buf = reply;
736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		send_len = reply_len;
737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else if (reply_len) {
738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		send_buf = "FAIL\n";
739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		send_len = 5;
740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(dst->rsp_buf);
742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		dst->rsp_buf = NULL;
743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(dst->rsp_buf);
747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst->rsp_buf = os_malloc(send_len);
748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (dst->rsp_buf == NULL) {
749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		global_close_pipe(dst);
750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(reply);
751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(dst->rsp_buf, send_buf, send_len);
754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(reply);
755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!WriteFileEx(dst->pipe, dst->rsp_buf, send_len, &dst->overlap,
757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			 global_iface_write_completed)) {
758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: WriteFileEx failed: %d",
759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		global_close_pipe(dst);
761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: Overlapped write started for %p",
763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   dst);
764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic VOID WINAPI global_iface_read_completed(DWORD err, DWORD bytes,
769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					       LPOVERLAPPED overlap)
770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_global_dst *dst = (struct wpa_global_dst *) overlap;
772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: Overlapped read completed: dst=%p err=%d "
773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "bytes=%d", dst, (int) err, (int) bytes);
774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (err == 0 && bytes > 0)
775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_supplicant_global_iface_rx(dst, bytes);
776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_global_iface_receive(void *eloop_data,
780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						void *user_ctx)
781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_global_dst *dst = eloop_data;
783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ctrl_iface_global_priv *priv = dst->priv;
784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD bytes;
785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: wpa_supplicant_global_iface_receive");
787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ResetEvent(dst->overlap.hEvent);
788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!GetOverlappedResult(dst->pipe, &dst->overlap, &bytes, FALSE)) {
790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult failed: %d",
791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult: New client "
795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "connected");
796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Open a new named pipe for the next client. */
798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (global_open_pipe(priv) < 0) {
799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL: global_open_pipe failed");
800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Use write completion function to start reading a command */
804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	global_iface_write_completed(0, 0, &dst->overlap);
805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	global_flush_broken_pipes(priv);
807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ctrl_iface_global_priv *
811526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
812526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
813526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ctrl_iface_global_priv *priv;
814526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
815526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	priv = os_zalloc(sizeof(*priv));
816526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (priv == NULL)
817526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
818526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	priv->global = global;
819526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
820526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (global_open_pipe(priv) < 0) {
821526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(priv);
822526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
823526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
824526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
825526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return priv;
826526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
827526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
828526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
829526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid
830526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
831526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
832526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (priv->ctrl_dst)
833526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		global_close_pipe(priv->ctrl_dst);
834526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(priv);
835526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
836