1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * WPA Supplicant - privilege separated driver interface
3e5b75505Sopenharmony_ci * Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci *
5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
6e5b75505Sopenharmony_ci * See README for more details.
7e5b75505Sopenharmony_ci */
8e5b75505Sopenharmony_ci
9e5b75505Sopenharmony_ci#include "includes.h"
10e5b75505Sopenharmony_ci#include <sys/un.h>
11e5b75505Sopenharmony_ci
12e5b75505Sopenharmony_ci#include "common.h"
13e5b75505Sopenharmony_ci#include "driver.h"
14e5b75505Sopenharmony_ci#include "eloop.h"
15e5b75505Sopenharmony_ci#include "common/privsep_commands.h"
16e5b75505Sopenharmony_ci
17e5b75505Sopenharmony_ci
18e5b75505Sopenharmony_cistruct wpa_driver_privsep_data {
19e5b75505Sopenharmony_ci	void *ctx;
20e5b75505Sopenharmony_ci	u8 own_addr[ETH_ALEN];
21e5b75505Sopenharmony_ci	int priv_socket;
22e5b75505Sopenharmony_ci	char *own_socket_path;
23e5b75505Sopenharmony_ci	int cmd_socket;
24e5b75505Sopenharmony_ci	char *own_cmd_path;
25e5b75505Sopenharmony_ci	struct sockaddr_un priv_addr;
26e5b75505Sopenharmony_ci	char ifname[16];
27e5b75505Sopenharmony_ci};
28e5b75505Sopenharmony_ci
29e5b75505Sopenharmony_ci
30e5b75505Sopenharmony_cistatic int wpa_priv_reg_cmd(struct wpa_driver_privsep_data *drv, int cmd)
31e5b75505Sopenharmony_ci{
32e5b75505Sopenharmony_ci	int res;
33e5b75505Sopenharmony_ci
34e5b75505Sopenharmony_ci	res = sendto(drv->priv_socket, &cmd, sizeof(cmd), 0,
35e5b75505Sopenharmony_ci		     (struct sockaddr *) &drv->priv_addr,
36e5b75505Sopenharmony_ci		     sizeof(drv->priv_addr));
37e5b75505Sopenharmony_ci	if (res < 0)
38e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "sendto: %s", strerror(errno));
39e5b75505Sopenharmony_ci	return res < 0 ? -1 : 0;
40e5b75505Sopenharmony_ci}
41e5b75505Sopenharmony_ci
42e5b75505Sopenharmony_ci
43e5b75505Sopenharmony_cistatic int wpa_priv_cmd(struct wpa_driver_privsep_data *drv, int cmd,
44e5b75505Sopenharmony_ci			const void *data, size_t data_len,
45e5b75505Sopenharmony_ci			void *reply, size_t *reply_len)
46e5b75505Sopenharmony_ci{
47e5b75505Sopenharmony_ci	struct msghdr msg;
48e5b75505Sopenharmony_ci	struct iovec io[2];
49e5b75505Sopenharmony_ci
50e5b75505Sopenharmony_ci	io[0].iov_base = &cmd;
51e5b75505Sopenharmony_ci	io[0].iov_len = sizeof(cmd);
52e5b75505Sopenharmony_ci	io[1].iov_base = (u8 *) data;
53e5b75505Sopenharmony_ci	io[1].iov_len = data_len;
54e5b75505Sopenharmony_ci
55e5b75505Sopenharmony_ci	os_memset(&msg, 0, sizeof(msg));
56e5b75505Sopenharmony_ci	msg.msg_iov = io;
57e5b75505Sopenharmony_ci	msg.msg_iovlen = data ? 2 : 1;
58e5b75505Sopenharmony_ci	msg.msg_name = &drv->priv_addr;
59e5b75505Sopenharmony_ci	msg.msg_namelen = sizeof(drv->priv_addr);
60e5b75505Sopenharmony_ci
61e5b75505Sopenharmony_ci	if (sendmsg(drv->cmd_socket, &msg, 0) < 0) {
62e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "sendmsg(cmd_socket): %s",
63e5b75505Sopenharmony_ci			   strerror(errno));
64e5b75505Sopenharmony_ci		return -1;
65e5b75505Sopenharmony_ci	}
66e5b75505Sopenharmony_ci
67e5b75505Sopenharmony_ci	if (reply) {
68e5b75505Sopenharmony_ci		fd_set rfds;
69e5b75505Sopenharmony_ci		struct timeval tv;
70e5b75505Sopenharmony_ci		int res;
71e5b75505Sopenharmony_ci
72e5b75505Sopenharmony_ci		FD_ZERO(&rfds);
73e5b75505Sopenharmony_ci		FD_SET(drv->cmd_socket, &rfds);
74e5b75505Sopenharmony_ci		tv.tv_sec = 5;
75e5b75505Sopenharmony_ci		tv.tv_usec = 0;
76e5b75505Sopenharmony_ci		res = select(drv->cmd_socket + 1, &rfds, NULL, NULL, &tv);
77e5b75505Sopenharmony_ci		if (res < 0 && errno != EINTR) {
78e5b75505Sopenharmony_ci			wpa_printf(MSG_ERROR, "select: %s", strerror(errno));
79e5b75505Sopenharmony_ci			return -1;
80e5b75505Sopenharmony_ci		}
81e5b75505Sopenharmony_ci
82e5b75505Sopenharmony_ci		if (FD_ISSET(drv->cmd_socket, &rfds)) {
83e5b75505Sopenharmony_ci			res = recv(drv->cmd_socket, reply, *reply_len, 0);
84e5b75505Sopenharmony_ci			if (res < 0) {
85e5b75505Sopenharmony_ci				wpa_printf(MSG_ERROR, "recv: %s",
86e5b75505Sopenharmony_ci					   strerror(errno));
87e5b75505Sopenharmony_ci				return -1;
88e5b75505Sopenharmony_ci			}
89e5b75505Sopenharmony_ci			*reply_len = res;
90e5b75505Sopenharmony_ci		} else {
91e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "PRIVSEP: Timeout while waiting "
92e5b75505Sopenharmony_ci				   "for reply (cmd=%d)", cmd);
93e5b75505Sopenharmony_ci			return -1;
94e5b75505Sopenharmony_ci		}
95e5b75505Sopenharmony_ci	}
96e5b75505Sopenharmony_ci
97e5b75505Sopenharmony_ci	return 0;
98e5b75505Sopenharmony_ci}
99e5b75505Sopenharmony_ci
100e5b75505Sopenharmony_ci
101e5b75505Sopenharmony_cistatic int wpa_driver_privsep_scan(void *priv,
102e5b75505Sopenharmony_ci				   struct wpa_driver_scan_params *params)
103e5b75505Sopenharmony_ci{
104e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = priv;
105e5b75505Sopenharmony_ci	struct privsep_cmd_scan scan;
106e5b75505Sopenharmony_ci	size_t i;
107e5b75505Sopenharmony_ci
108e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv);
109e5b75505Sopenharmony_ci	os_memset(&scan, 0, sizeof(scan));
110e5b75505Sopenharmony_ci	scan.num_ssids = params->num_ssids;
111e5b75505Sopenharmony_ci	for (i = 0; i < params->num_ssids; i++) {
112e5b75505Sopenharmony_ci		if (!params->ssids[i].ssid)
113e5b75505Sopenharmony_ci			continue;
114e5b75505Sopenharmony_ci		scan.ssid_lens[i] = params->ssids[i].ssid_len;
115e5b75505Sopenharmony_ci		os_memcpy(scan.ssids[i], params->ssids[i].ssid,
116e5b75505Sopenharmony_ci			  scan.ssid_lens[i]);
117e5b75505Sopenharmony_ci	}
118e5b75505Sopenharmony_ci
119e5b75505Sopenharmony_ci	for (i = 0; i < PRIVSEP_MAX_SCAN_FREQS &&
120e5b75505Sopenharmony_ci		     params->freqs && params->freqs[i]; i++)
121e5b75505Sopenharmony_ci		scan.freqs[i] = params->freqs[i];
122e5b75505Sopenharmony_ci	scan.num_freqs = i;
123e5b75505Sopenharmony_ci
124e5b75505Sopenharmony_ci	return wpa_priv_cmd(drv, PRIVSEP_CMD_SCAN, &scan, sizeof(scan),
125e5b75505Sopenharmony_ci			    NULL, NULL);
126e5b75505Sopenharmony_ci}
127e5b75505Sopenharmony_ci
128e5b75505Sopenharmony_ci
129e5b75505Sopenharmony_cistatic struct wpa_scan_results *
130e5b75505Sopenharmony_ciwpa_driver_privsep_get_scan_results2(void *priv)
131e5b75505Sopenharmony_ci{
132e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = priv;
133e5b75505Sopenharmony_ci	int res, num;
134e5b75505Sopenharmony_ci	u8 *buf, *pos, *end;
135e5b75505Sopenharmony_ci	size_t reply_len = 60000;
136e5b75505Sopenharmony_ci	struct wpa_scan_results *results;
137e5b75505Sopenharmony_ci	struct wpa_scan_res *r;
138e5b75505Sopenharmony_ci
139e5b75505Sopenharmony_ci	buf = os_malloc(reply_len);
140e5b75505Sopenharmony_ci	if (buf == NULL)
141e5b75505Sopenharmony_ci		return NULL;
142e5b75505Sopenharmony_ci	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SCAN_RESULTS,
143e5b75505Sopenharmony_ci			   NULL, 0, buf, &reply_len);
144e5b75505Sopenharmony_ci	if (res < 0) {
145e5b75505Sopenharmony_ci		os_free(buf);
146e5b75505Sopenharmony_ci		return NULL;
147e5b75505Sopenharmony_ci	}
148e5b75505Sopenharmony_ci
149e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "privsep: Received %lu bytes of scan results",
150e5b75505Sopenharmony_ci		   (unsigned long) reply_len);
151e5b75505Sopenharmony_ci	if (reply_len < sizeof(int)) {
152e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "privsep: Invalid scan result len %lu",
153e5b75505Sopenharmony_ci			   (unsigned long) reply_len);
154e5b75505Sopenharmony_ci		os_free(buf);
155e5b75505Sopenharmony_ci		return NULL;
156e5b75505Sopenharmony_ci	}
157e5b75505Sopenharmony_ci
158e5b75505Sopenharmony_ci	pos = buf;
159e5b75505Sopenharmony_ci	end = buf + reply_len;
160e5b75505Sopenharmony_ci	os_memcpy(&num, pos, sizeof(int));
161e5b75505Sopenharmony_ci	if (num < 0 || num > 1000) {
162e5b75505Sopenharmony_ci		os_free(buf);
163e5b75505Sopenharmony_ci		return NULL;
164e5b75505Sopenharmony_ci	}
165e5b75505Sopenharmony_ci	pos += sizeof(int);
166e5b75505Sopenharmony_ci
167e5b75505Sopenharmony_ci	results = os_zalloc(sizeof(*results));
168e5b75505Sopenharmony_ci	if (results == NULL) {
169e5b75505Sopenharmony_ci		os_free(buf);
170e5b75505Sopenharmony_ci		return NULL;
171e5b75505Sopenharmony_ci	}
172e5b75505Sopenharmony_ci
173e5b75505Sopenharmony_ci	results->res = os_calloc(num, sizeof(struct wpa_scan_res *));
174e5b75505Sopenharmony_ci	if (results->res == NULL) {
175e5b75505Sopenharmony_ci		os_free(results);
176e5b75505Sopenharmony_ci		os_free(buf);
177e5b75505Sopenharmony_ci		return NULL;
178e5b75505Sopenharmony_ci	}
179e5b75505Sopenharmony_ci
180e5b75505Sopenharmony_ci	while (results->num < (size_t) num && end - pos > (int) sizeof(int)) {
181e5b75505Sopenharmony_ci		int len;
182e5b75505Sopenharmony_ci		os_memcpy(&len, pos, sizeof(int));
183e5b75505Sopenharmony_ci		pos += sizeof(int);
184e5b75505Sopenharmony_ci		if (len < 0 || len > 10000 || len > end - pos)
185e5b75505Sopenharmony_ci			break;
186e5b75505Sopenharmony_ci
187e5b75505Sopenharmony_ci		r = os_memdup(pos, len);
188e5b75505Sopenharmony_ci		if (r == NULL)
189e5b75505Sopenharmony_ci			break;
190e5b75505Sopenharmony_ci		pos += len;
191e5b75505Sopenharmony_ci		if (sizeof(*r) + r->ie_len + r->beacon_ie_len > (size_t) len) {
192e5b75505Sopenharmony_ci			wpa_printf(MSG_ERROR,
193e5b75505Sopenharmony_ci				   "privsep: Invalid scan result len (%d + %d + %d > %d)",
194e5b75505Sopenharmony_ci				   (int) sizeof(*r), (int) r->ie_len,
195e5b75505Sopenharmony_ci				   (int) r->beacon_ie_len, len);
196e5b75505Sopenharmony_ci			os_free(r);
197e5b75505Sopenharmony_ci			break;
198e5b75505Sopenharmony_ci		}
199e5b75505Sopenharmony_ci
200e5b75505Sopenharmony_ci		results->res[results->num++] = r;
201e5b75505Sopenharmony_ci	}
202e5b75505Sopenharmony_ci
203e5b75505Sopenharmony_ci	os_free(buf);
204e5b75505Sopenharmony_ci	return results;
205e5b75505Sopenharmony_ci}
206e5b75505Sopenharmony_ci
207e5b75505Sopenharmony_ci
208e5b75505Sopenharmony_cistatic int wpa_driver_privsep_set_key(const char *ifname, void *priv,
209e5b75505Sopenharmony_ci				      enum wpa_alg alg, const u8 *addr,
210e5b75505Sopenharmony_ci				      int key_idx, int set_tx,
211e5b75505Sopenharmony_ci				      const u8 *seq, size_t seq_len,
212e5b75505Sopenharmony_ci				      const u8 *key, size_t key_len)
213e5b75505Sopenharmony_ci{
214e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = priv;
215e5b75505Sopenharmony_ci	struct privsep_cmd_set_key cmd;
216e5b75505Sopenharmony_ci
217e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d",
218e5b75505Sopenharmony_ci		   __func__, priv, alg, key_idx, set_tx);
219e5b75505Sopenharmony_ci
220e5b75505Sopenharmony_ci	os_memset(&cmd, 0, sizeof(cmd));
221e5b75505Sopenharmony_ci	cmd.alg = alg;
222e5b75505Sopenharmony_ci	if (addr)
223e5b75505Sopenharmony_ci		os_memcpy(cmd.addr, addr, ETH_ALEN);
224e5b75505Sopenharmony_ci	else
225e5b75505Sopenharmony_ci		os_memset(cmd.addr, 0xff, ETH_ALEN);
226e5b75505Sopenharmony_ci	cmd.key_idx = key_idx;
227e5b75505Sopenharmony_ci	cmd.set_tx = set_tx;
228e5b75505Sopenharmony_ci	if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) {
229e5b75505Sopenharmony_ci		os_memcpy(cmd.seq, seq, seq_len);
230e5b75505Sopenharmony_ci		cmd.seq_len = seq_len;
231e5b75505Sopenharmony_ci	}
232e5b75505Sopenharmony_ci	if (key && key_len > 0 && key_len < sizeof(cmd.key)) {
233e5b75505Sopenharmony_ci		os_memcpy(cmd.key, key, key_len);
234e5b75505Sopenharmony_ci		cmd.key_len = key_len;
235e5b75505Sopenharmony_ci	}
236e5b75505Sopenharmony_ci
237e5b75505Sopenharmony_ci	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_KEY, &cmd, sizeof(cmd),
238e5b75505Sopenharmony_ci			    NULL, NULL);
239e5b75505Sopenharmony_ci}
240e5b75505Sopenharmony_ci
241e5b75505Sopenharmony_ci
242e5b75505Sopenharmony_cistatic int wpa_driver_privsep_authenticate(
243e5b75505Sopenharmony_ci	void *priv, struct wpa_driver_auth_params *params)
244e5b75505Sopenharmony_ci{
245e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = priv;
246e5b75505Sopenharmony_ci	struct privsep_cmd_authenticate *data;
247e5b75505Sopenharmony_ci	int i, res;
248e5b75505Sopenharmony_ci	size_t buflen;
249e5b75505Sopenharmony_ci	u8 *pos;
250e5b75505Sopenharmony_ci
251e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d bssid=" MACSTR
252e5b75505Sopenharmony_ci		   " auth_alg=%d local_state_change=%d p2p=%d",
253e5b75505Sopenharmony_ci		   __func__, priv, params->freq, MAC2STR(params->bssid),
254e5b75505Sopenharmony_ci		   params->auth_alg, params->local_state_change, params->p2p);
255e5b75505Sopenharmony_ci
256e5b75505Sopenharmony_ci	buflen = sizeof(*data) + params->ie_len + params->auth_data_len;
257e5b75505Sopenharmony_ci	data = os_zalloc(buflen);
258e5b75505Sopenharmony_ci	if (data == NULL)
259e5b75505Sopenharmony_ci		return -1;
260e5b75505Sopenharmony_ci
261e5b75505Sopenharmony_ci	data->freq = params->freq;
262e5b75505Sopenharmony_ci	os_memcpy(data->bssid, params->bssid, ETH_ALEN);
263e5b75505Sopenharmony_ci	os_memcpy(data->ssid, params->ssid, params->ssid_len);
264e5b75505Sopenharmony_ci	data->ssid_len = params->ssid_len;
265e5b75505Sopenharmony_ci	data->auth_alg = params->auth_alg;
266e5b75505Sopenharmony_ci	data->ie_len = params->ie_len;
267e5b75505Sopenharmony_ci	for (i = 0; i < 4; i++) {
268e5b75505Sopenharmony_ci		if (params->wep_key[i])
269e5b75505Sopenharmony_ci			os_memcpy(data->wep_key[i], params->wep_key[i],
270e5b75505Sopenharmony_ci				  params->wep_key_len[i]);
271e5b75505Sopenharmony_ci		data->wep_key_len[i] = params->wep_key_len[i];
272e5b75505Sopenharmony_ci	}
273e5b75505Sopenharmony_ci	data->wep_tx_keyidx = params->wep_tx_keyidx;
274e5b75505Sopenharmony_ci	data->local_state_change = params->local_state_change;
275e5b75505Sopenharmony_ci	data->p2p = params->p2p;
276e5b75505Sopenharmony_ci	pos = (u8 *) (data + 1);
277e5b75505Sopenharmony_ci	if (params->ie_len) {
278e5b75505Sopenharmony_ci		os_memcpy(pos, params->ie, params->ie_len);
279e5b75505Sopenharmony_ci		pos += params->ie_len;
280e5b75505Sopenharmony_ci	}
281e5b75505Sopenharmony_ci	if (params->auth_data_len)
282e5b75505Sopenharmony_ci		os_memcpy(pos, params->auth_data, params->auth_data_len);
283e5b75505Sopenharmony_ci
284e5b75505Sopenharmony_ci	res = wpa_priv_cmd(drv, PRIVSEP_CMD_AUTHENTICATE, data, buflen,
285e5b75505Sopenharmony_ci			   NULL, NULL);
286e5b75505Sopenharmony_ci	os_free(data);
287e5b75505Sopenharmony_ci
288e5b75505Sopenharmony_ci	return res;
289e5b75505Sopenharmony_ci}
290e5b75505Sopenharmony_ci
291e5b75505Sopenharmony_ci
292e5b75505Sopenharmony_cistatic int wpa_driver_privsep_associate(
293e5b75505Sopenharmony_ci	void *priv, struct wpa_driver_associate_params *params)
294e5b75505Sopenharmony_ci{
295e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = priv;
296e5b75505Sopenharmony_ci	struct privsep_cmd_associate *data;
297e5b75505Sopenharmony_ci	int res;
298e5b75505Sopenharmony_ci	size_t buflen;
299e5b75505Sopenharmony_ci
300e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
301e5b75505Sopenharmony_ci		   "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
302e5b75505Sopenharmony_ci		   __func__, priv, params->freq.freq, params->pairwise_suite,
303e5b75505Sopenharmony_ci		   params->group_suite, params->key_mgmt_suite,
304e5b75505Sopenharmony_ci		   params->auth_alg, params->mode);
305e5b75505Sopenharmony_ci
306e5b75505Sopenharmony_ci	buflen = sizeof(*data) + params->wpa_ie_len;
307e5b75505Sopenharmony_ci	data = os_zalloc(buflen);
308e5b75505Sopenharmony_ci	if (data == NULL)
309e5b75505Sopenharmony_ci		return -1;
310e5b75505Sopenharmony_ci
311e5b75505Sopenharmony_ci	if (params->bssid)
312e5b75505Sopenharmony_ci		os_memcpy(data->bssid, params->bssid, ETH_ALEN);
313e5b75505Sopenharmony_ci	os_memcpy(data->ssid, params->ssid, params->ssid_len);
314e5b75505Sopenharmony_ci	data->ssid_len = params->ssid_len;
315e5b75505Sopenharmony_ci	data->hwmode = params->freq.mode;
316e5b75505Sopenharmony_ci	data->freq = params->freq.freq;
317e5b75505Sopenharmony_ci	data->channel = params->freq.channel;
318e5b75505Sopenharmony_ci	data->pairwise_suite = params->pairwise_suite;
319e5b75505Sopenharmony_ci	data->group_suite = params->group_suite;
320e5b75505Sopenharmony_ci	data->key_mgmt_suite = params->key_mgmt_suite;
321e5b75505Sopenharmony_ci	data->auth_alg = params->auth_alg;
322e5b75505Sopenharmony_ci	data->mode = params->mode;
323e5b75505Sopenharmony_ci	data->wpa_ie_len = params->wpa_ie_len;
324e5b75505Sopenharmony_ci	if (params->wpa_ie)
325e5b75505Sopenharmony_ci		os_memcpy(data + 1, params->wpa_ie, params->wpa_ie_len);
326e5b75505Sopenharmony_ci	/* TODO: add support for other assoc parameters */
327e5b75505Sopenharmony_ci
328e5b75505Sopenharmony_ci	res = wpa_priv_cmd(drv, PRIVSEP_CMD_ASSOCIATE, data, buflen,
329e5b75505Sopenharmony_ci			   NULL, NULL);
330e5b75505Sopenharmony_ci	os_free(data);
331e5b75505Sopenharmony_ci
332e5b75505Sopenharmony_ci	return res;
333e5b75505Sopenharmony_ci}
334e5b75505Sopenharmony_ci
335e5b75505Sopenharmony_ci
336e5b75505Sopenharmony_cistatic int wpa_driver_privsep_get_bssid(void *priv, u8 *bssid)
337e5b75505Sopenharmony_ci{
338e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = priv;
339e5b75505Sopenharmony_ci	int res;
340e5b75505Sopenharmony_ci	size_t len = ETH_ALEN;
341e5b75505Sopenharmony_ci
342e5b75505Sopenharmony_ci	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_BSSID, NULL, 0, bssid, &len);
343e5b75505Sopenharmony_ci	if (res < 0 || len != ETH_ALEN)
344e5b75505Sopenharmony_ci		return -1;
345e5b75505Sopenharmony_ci	return 0;
346e5b75505Sopenharmony_ci}
347e5b75505Sopenharmony_ci
348e5b75505Sopenharmony_ci
349e5b75505Sopenharmony_cistatic int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid)
350e5b75505Sopenharmony_ci{
351e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = priv;
352e5b75505Sopenharmony_ci	int res, ssid_len;
353e5b75505Sopenharmony_ci	u8 reply[sizeof(int) + SSID_MAX_LEN];
354e5b75505Sopenharmony_ci	size_t len = sizeof(reply);
355e5b75505Sopenharmony_ci
356e5b75505Sopenharmony_ci	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SSID, NULL, 0, reply, &len);
357e5b75505Sopenharmony_ci	if (res < 0 || len < sizeof(int))
358e5b75505Sopenharmony_ci		return -1;
359e5b75505Sopenharmony_ci	os_memcpy(&ssid_len, reply, sizeof(int));
360e5b75505Sopenharmony_ci	if (ssid_len < 0 || ssid_len > SSID_MAX_LEN ||
361e5b75505Sopenharmony_ci	    sizeof(int) + ssid_len > len) {
362e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "privsep: Invalid get SSID reply");
363e5b75505Sopenharmony_ci		return -1;
364e5b75505Sopenharmony_ci	}
365e5b75505Sopenharmony_ci	os_memcpy(ssid, &reply[sizeof(int)], ssid_len);
366e5b75505Sopenharmony_ci	return ssid_len;
367e5b75505Sopenharmony_ci}
368e5b75505Sopenharmony_ci
369e5b75505Sopenharmony_ci
370e5b75505Sopenharmony_cistatic int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr,
371e5b75505Sopenharmony_ci					     u16 reason_code)
372e5b75505Sopenharmony_ci{
373e5b75505Sopenharmony_ci	//struct wpa_driver_privsep_data *drv = priv;
374e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
375e5b75505Sopenharmony_ci		   __func__, MAC2STR(addr), reason_code);
376e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%s - TODO", __func__);
377e5b75505Sopenharmony_ci	return 0;
378e5b75505Sopenharmony_ci}
379e5b75505Sopenharmony_ci
380e5b75505Sopenharmony_ci
381e5b75505Sopenharmony_cistatic void wpa_driver_privsep_event_auth(void *ctx, u8 *buf, size_t len)
382e5b75505Sopenharmony_ci{
383e5b75505Sopenharmony_ci	union wpa_event_data data;
384e5b75505Sopenharmony_ci	struct privsep_event_auth *auth;
385e5b75505Sopenharmony_ci
386e5b75505Sopenharmony_ci	os_memset(&data, 0, sizeof(data));
387e5b75505Sopenharmony_ci	if (len < sizeof(*auth))
388e5b75505Sopenharmony_ci		return;
389e5b75505Sopenharmony_ci	auth = (struct privsep_event_auth *) buf;
390e5b75505Sopenharmony_ci	if (len < sizeof(*auth) + auth->ies_len)
391e5b75505Sopenharmony_ci		return;
392e5b75505Sopenharmony_ci
393e5b75505Sopenharmony_ci	os_memcpy(data.auth.peer, auth->peer, ETH_ALEN);
394e5b75505Sopenharmony_ci	os_memcpy(data.auth.bssid, auth->bssid, ETH_ALEN);
395e5b75505Sopenharmony_ci	data.auth.auth_type = auth->auth_type;
396e5b75505Sopenharmony_ci	data.auth.auth_transaction = auth->auth_transaction;
397e5b75505Sopenharmony_ci	data.auth.status_code = auth->status_code;
398e5b75505Sopenharmony_ci	if (auth->ies_len) {
399e5b75505Sopenharmony_ci		data.auth.ies = (u8 *) (auth + 1);
400e5b75505Sopenharmony_ci		data.auth.ies_len = auth->ies_len;
401e5b75505Sopenharmony_ci	}
402e5b75505Sopenharmony_ci
403e5b75505Sopenharmony_ci	wpa_supplicant_event(ctx, EVENT_AUTH, &data);
404e5b75505Sopenharmony_ci}
405e5b75505Sopenharmony_ci
406e5b75505Sopenharmony_ci
407e5b75505Sopenharmony_cistatic void wpa_driver_privsep_event_assoc(void *ctx,
408e5b75505Sopenharmony_ci					   enum wpa_event_type event,
409e5b75505Sopenharmony_ci					   u8 *buf, size_t len)
410e5b75505Sopenharmony_ci{
411e5b75505Sopenharmony_ci	union wpa_event_data data;
412e5b75505Sopenharmony_ci	int inc_data = 0;
413e5b75505Sopenharmony_ci	u8 *pos, *end;
414e5b75505Sopenharmony_ci	int ie_len;
415e5b75505Sopenharmony_ci
416e5b75505Sopenharmony_ci	os_memset(&data, 0, sizeof(data));
417e5b75505Sopenharmony_ci
418e5b75505Sopenharmony_ci	pos = buf;
419e5b75505Sopenharmony_ci	end = buf + len;
420e5b75505Sopenharmony_ci
421e5b75505Sopenharmony_ci	if (end - pos < (int) sizeof(int))
422e5b75505Sopenharmony_ci		return;
423e5b75505Sopenharmony_ci	os_memcpy(&ie_len, pos, sizeof(int));
424e5b75505Sopenharmony_ci	pos += sizeof(int);
425e5b75505Sopenharmony_ci	if (ie_len < 0 || ie_len > end - pos)
426e5b75505Sopenharmony_ci		return;
427e5b75505Sopenharmony_ci	if (ie_len) {
428e5b75505Sopenharmony_ci		data.assoc_info.req_ies = pos;
429e5b75505Sopenharmony_ci		data.assoc_info.req_ies_len = ie_len;
430e5b75505Sopenharmony_ci		pos += ie_len;
431e5b75505Sopenharmony_ci		inc_data = 1;
432e5b75505Sopenharmony_ci	}
433e5b75505Sopenharmony_ci
434e5b75505Sopenharmony_ci	wpa_supplicant_event(ctx, event, inc_data ? &data : NULL);
435e5b75505Sopenharmony_ci}
436e5b75505Sopenharmony_ci
437e5b75505Sopenharmony_ci
438e5b75505Sopenharmony_cistatic void wpa_driver_privsep_event_interface_status(void *ctx, u8 *buf,
439e5b75505Sopenharmony_ci						      size_t len)
440e5b75505Sopenharmony_ci{
441e5b75505Sopenharmony_ci	union wpa_event_data data;
442e5b75505Sopenharmony_ci	int ievent;
443e5b75505Sopenharmony_ci
444e5b75505Sopenharmony_ci	if (len < sizeof(int) ||
445e5b75505Sopenharmony_ci	    len - sizeof(int) > sizeof(data.interface_status.ifname))
446e5b75505Sopenharmony_ci		return;
447e5b75505Sopenharmony_ci
448e5b75505Sopenharmony_ci	os_memcpy(&ievent, buf, sizeof(int));
449e5b75505Sopenharmony_ci
450e5b75505Sopenharmony_ci	os_memset(&data, 0, sizeof(data));
451e5b75505Sopenharmony_ci	data.interface_status.ievent = ievent;
452e5b75505Sopenharmony_ci	os_memcpy(data.interface_status.ifname, buf + sizeof(int),
453e5b75505Sopenharmony_ci		  len - sizeof(int));
454e5b75505Sopenharmony_ci	wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &data);
455e5b75505Sopenharmony_ci}
456e5b75505Sopenharmony_ci
457e5b75505Sopenharmony_ci
458e5b75505Sopenharmony_cistatic void wpa_driver_privsep_event_michael_mic_failure(
459e5b75505Sopenharmony_ci	void *ctx, u8 *buf, size_t len)
460e5b75505Sopenharmony_ci{
461e5b75505Sopenharmony_ci	union wpa_event_data data;
462e5b75505Sopenharmony_ci
463e5b75505Sopenharmony_ci	if (len != sizeof(int))
464e5b75505Sopenharmony_ci		return;
465e5b75505Sopenharmony_ci
466e5b75505Sopenharmony_ci	os_memset(&data, 0, sizeof(data));
467e5b75505Sopenharmony_ci	os_memcpy(&data.michael_mic_failure.unicast, buf, sizeof(int));
468e5b75505Sopenharmony_ci	wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
469e5b75505Sopenharmony_ci}
470e5b75505Sopenharmony_ci
471e5b75505Sopenharmony_ci
472e5b75505Sopenharmony_cistatic void wpa_driver_privsep_event_pmkid_candidate(void *ctx, u8 *buf,
473e5b75505Sopenharmony_ci						     size_t len)
474e5b75505Sopenharmony_ci{
475e5b75505Sopenharmony_ci	union wpa_event_data data;
476e5b75505Sopenharmony_ci
477e5b75505Sopenharmony_ci	if (len != sizeof(struct pmkid_candidate))
478e5b75505Sopenharmony_ci		return;
479e5b75505Sopenharmony_ci
480e5b75505Sopenharmony_ci	os_memset(&data, 0, sizeof(data));
481e5b75505Sopenharmony_ci	os_memcpy(&data.pmkid_candidate, buf, len);
482e5b75505Sopenharmony_ci	wpa_supplicant_event(ctx, EVENT_PMKID_CANDIDATE, &data);
483e5b75505Sopenharmony_ci}
484e5b75505Sopenharmony_ci
485e5b75505Sopenharmony_ci
486e5b75505Sopenharmony_cistatic void wpa_driver_privsep_event_ft_response(void *ctx, u8 *buf,
487e5b75505Sopenharmony_ci						 size_t len)
488e5b75505Sopenharmony_ci{
489e5b75505Sopenharmony_ci	union wpa_event_data data;
490e5b75505Sopenharmony_ci
491e5b75505Sopenharmony_ci	if (len < sizeof(int) + ETH_ALEN)
492e5b75505Sopenharmony_ci		return;
493e5b75505Sopenharmony_ci
494e5b75505Sopenharmony_ci	os_memset(&data, 0, sizeof(data));
495e5b75505Sopenharmony_ci	os_memcpy(&data.ft_ies.ft_action, buf, sizeof(int));
496e5b75505Sopenharmony_ci	os_memcpy(data.ft_ies.target_ap, buf + sizeof(int), ETH_ALEN);
497e5b75505Sopenharmony_ci	data.ft_ies.ies = buf + sizeof(int) + ETH_ALEN;
498e5b75505Sopenharmony_ci	data.ft_ies.ies_len = len - sizeof(int) - ETH_ALEN;
499e5b75505Sopenharmony_ci	wpa_supplicant_event(ctx, EVENT_FT_RESPONSE, &data);
500e5b75505Sopenharmony_ci}
501e5b75505Sopenharmony_ci
502e5b75505Sopenharmony_ci
503e5b75505Sopenharmony_cistatic void wpa_driver_privsep_event_rx_eapol(void *ctx, u8 *buf, size_t len)
504e5b75505Sopenharmony_ci{
505e5b75505Sopenharmony_ci	if (len < ETH_ALEN)
506e5b75505Sopenharmony_ci		return;
507e5b75505Sopenharmony_ci	drv_event_eapol_rx(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN);
508e5b75505Sopenharmony_ci}
509e5b75505Sopenharmony_ci
510e5b75505Sopenharmony_ci
511e5b75505Sopenharmony_cistatic void wpa_driver_privsep_receive(int sock, void *eloop_ctx,
512e5b75505Sopenharmony_ci				       void *sock_ctx)
513e5b75505Sopenharmony_ci{
514e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = eloop_ctx;
515e5b75505Sopenharmony_ci	u8 *buf, *event_buf;
516e5b75505Sopenharmony_ci	size_t event_len;
517e5b75505Sopenharmony_ci	int res, event;
518e5b75505Sopenharmony_ci	enum privsep_event e;
519e5b75505Sopenharmony_ci	struct sockaddr_un from;
520e5b75505Sopenharmony_ci	socklen_t fromlen = sizeof(from);
521e5b75505Sopenharmony_ci	const size_t buflen = 2000;
522e5b75505Sopenharmony_ci
523e5b75505Sopenharmony_ci	buf = os_malloc(buflen);
524e5b75505Sopenharmony_ci	if (buf == NULL)
525e5b75505Sopenharmony_ci		return;
526e5b75505Sopenharmony_ci	res = recvfrom(sock, buf, buflen, 0,
527e5b75505Sopenharmony_ci		       (struct sockaddr *) &from, &fromlen);
528e5b75505Sopenharmony_ci	if (res < 0) {
529e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "recvfrom(priv_socket): %s",
530e5b75505Sopenharmony_ci			   strerror(errno));
531e5b75505Sopenharmony_ci		os_free(buf);
532e5b75505Sopenharmony_ci		return;
533e5b75505Sopenharmony_ci	}
534e5b75505Sopenharmony_ci
535e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "privsep_driver: received %u bytes", res);
536e5b75505Sopenharmony_ci
537e5b75505Sopenharmony_ci	if (res < (int) sizeof(int)) {
538e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "Too short event message (len=%d)", res);
539e5b75505Sopenharmony_ci		return;
540e5b75505Sopenharmony_ci	}
541e5b75505Sopenharmony_ci
542e5b75505Sopenharmony_ci	os_memcpy(&event, buf, sizeof(int));
543e5b75505Sopenharmony_ci	event_buf = &buf[sizeof(int)];
544e5b75505Sopenharmony_ci	event_len = res - sizeof(int);
545e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "privsep: Event %d received (len=%lu)",
546e5b75505Sopenharmony_ci		   event, (unsigned long) event_len);
547e5b75505Sopenharmony_ci
548e5b75505Sopenharmony_ci	e = event;
549e5b75505Sopenharmony_ci	switch (e) {
550e5b75505Sopenharmony_ci	case PRIVSEP_EVENT_SCAN_RESULTS:
551e5b75505Sopenharmony_ci		wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL);
552e5b75505Sopenharmony_ci		break;
553e5b75505Sopenharmony_ci	case PRIVSEP_EVENT_SCAN_STARTED:
554e5b75505Sopenharmony_ci		wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
555e5b75505Sopenharmony_ci		break;
556e5b75505Sopenharmony_ci	case PRIVSEP_EVENT_ASSOC:
557e5b75505Sopenharmony_ci		wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOC,
558e5b75505Sopenharmony_ci					       event_buf, event_len);
559e5b75505Sopenharmony_ci		break;
560e5b75505Sopenharmony_ci	case PRIVSEP_EVENT_DISASSOC:
561e5b75505Sopenharmony_ci		wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
562e5b75505Sopenharmony_ci		break;
563e5b75505Sopenharmony_ci	case PRIVSEP_EVENT_ASSOCINFO:
564e5b75505Sopenharmony_ci		wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOCINFO,
565e5b75505Sopenharmony_ci					       event_buf, event_len);
566e5b75505Sopenharmony_ci		break;
567e5b75505Sopenharmony_ci	case PRIVSEP_EVENT_MICHAEL_MIC_FAILURE:
568e5b75505Sopenharmony_ci		wpa_driver_privsep_event_michael_mic_failure(
569e5b75505Sopenharmony_ci			drv->ctx, event_buf, event_len);
570e5b75505Sopenharmony_ci		break;
571e5b75505Sopenharmony_ci	case PRIVSEP_EVENT_INTERFACE_STATUS:
572e5b75505Sopenharmony_ci		wpa_driver_privsep_event_interface_status(drv->ctx, event_buf,
573e5b75505Sopenharmony_ci							  event_len);
574e5b75505Sopenharmony_ci		break;
575e5b75505Sopenharmony_ci	case PRIVSEP_EVENT_PMKID_CANDIDATE:
576e5b75505Sopenharmony_ci		wpa_driver_privsep_event_pmkid_candidate(drv->ctx, event_buf,
577e5b75505Sopenharmony_ci							 event_len);
578e5b75505Sopenharmony_ci		break;
579e5b75505Sopenharmony_ci	case PRIVSEP_EVENT_FT_RESPONSE:
580e5b75505Sopenharmony_ci		wpa_driver_privsep_event_ft_response(drv->ctx, event_buf,
581e5b75505Sopenharmony_ci						     event_len);
582e5b75505Sopenharmony_ci		break;
583e5b75505Sopenharmony_ci	case PRIVSEP_EVENT_RX_EAPOL:
584e5b75505Sopenharmony_ci		wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf,
585e5b75505Sopenharmony_ci						  event_len);
586e5b75505Sopenharmony_ci		break;
587e5b75505Sopenharmony_ci	case PRIVSEP_EVENT_AUTH:
588e5b75505Sopenharmony_ci		wpa_driver_privsep_event_auth(drv->ctx, event_buf, event_len);
589e5b75505Sopenharmony_ci		break;
590e5b75505Sopenharmony_ci	}
591e5b75505Sopenharmony_ci
592e5b75505Sopenharmony_ci	os_free(buf);
593e5b75505Sopenharmony_ci}
594e5b75505Sopenharmony_ci
595e5b75505Sopenharmony_ci
596e5b75505Sopenharmony_cistatic void * wpa_driver_privsep_init(void *ctx, const char *ifname)
597e5b75505Sopenharmony_ci{
598e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv;
599e5b75505Sopenharmony_ci
600e5b75505Sopenharmony_ci	drv = os_zalloc(sizeof(*drv));
601e5b75505Sopenharmony_ci	if (drv == NULL)
602e5b75505Sopenharmony_ci		return NULL;
603e5b75505Sopenharmony_ci	drv->ctx = ctx;
604e5b75505Sopenharmony_ci	drv->priv_socket = -1;
605e5b75505Sopenharmony_ci	drv->cmd_socket = -1;
606e5b75505Sopenharmony_ci	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
607e5b75505Sopenharmony_ci
608e5b75505Sopenharmony_ci	return drv;
609e5b75505Sopenharmony_ci}
610e5b75505Sopenharmony_ci
611e5b75505Sopenharmony_ci
612e5b75505Sopenharmony_cistatic void wpa_driver_privsep_deinit(void *priv)
613e5b75505Sopenharmony_ci{
614e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = priv;
615e5b75505Sopenharmony_ci
616e5b75505Sopenharmony_ci	if (drv->priv_socket >= 0) {
617e5b75505Sopenharmony_ci		wpa_priv_reg_cmd(drv, PRIVSEP_CMD_UNREGISTER);
618e5b75505Sopenharmony_ci		eloop_unregister_read_sock(drv->priv_socket);
619e5b75505Sopenharmony_ci		close(drv->priv_socket);
620e5b75505Sopenharmony_ci	}
621e5b75505Sopenharmony_ci
622e5b75505Sopenharmony_ci	if (drv->own_socket_path) {
623e5b75505Sopenharmony_ci		unlink(drv->own_socket_path);
624e5b75505Sopenharmony_ci		os_free(drv->own_socket_path);
625e5b75505Sopenharmony_ci	}
626e5b75505Sopenharmony_ci
627e5b75505Sopenharmony_ci	if (drv->cmd_socket >= 0) {
628e5b75505Sopenharmony_ci		eloop_unregister_read_sock(drv->cmd_socket);
629e5b75505Sopenharmony_ci		close(drv->cmd_socket);
630e5b75505Sopenharmony_ci	}
631e5b75505Sopenharmony_ci
632e5b75505Sopenharmony_ci	if (drv->own_cmd_path) {
633e5b75505Sopenharmony_ci		unlink(drv->own_cmd_path);
634e5b75505Sopenharmony_ci		os_free(drv->own_cmd_path);
635e5b75505Sopenharmony_ci	}
636e5b75505Sopenharmony_ci
637e5b75505Sopenharmony_ci	os_free(drv);
638e5b75505Sopenharmony_ci}
639e5b75505Sopenharmony_ci
640e5b75505Sopenharmony_ci
641e5b75505Sopenharmony_cistatic int wpa_driver_privsep_set_param(void *priv, const char *param)
642e5b75505Sopenharmony_ci{
643e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = priv;
644e5b75505Sopenharmony_ci	const char *pos;
645e5b75505Sopenharmony_ci	char *own_dir, *priv_dir;
646e5b75505Sopenharmony_ci	static unsigned int counter = 0;
647e5b75505Sopenharmony_ci	size_t len;
648e5b75505Sopenharmony_ci	struct sockaddr_un addr;
649e5b75505Sopenharmony_ci
650e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
651e5b75505Sopenharmony_ci	if (param == NULL)
652e5b75505Sopenharmony_ci		pos = NULL;
653e5b75505Sopenharmony_ci	else
654e5b75505Sopenharmony_ci		pos = os_strstr(param, "own_dir=");
655e5b75505Sopenharmony_ci	if (pos) {
656e5b75505Sopenharmony_ci		char *end;
657e5b75505Sopenharmony_ci		own_dir = os_strdup(pos + 8);
658e5b75505Sopenharmony_ci		if (own_dir == NULL)
659e5b75505Sopenharmony_ci			return -1;
660e5b75505Sopenharmony_ci		end = os_strchr(own_dir, ' ');
661e5b75505Sopenharmony_ci		if (end)
662e5b75505Sopenharmony_ci			*end = '\0';
663e5b75505Sopenharmony_ci	} else {
664e5b75505Sopenharmony_ci		own_dir = os_strdup("/tmp");
665e5b75505Sopenharmony_ci		if (own_dir == NULL)
666e5b75505Sopenharmony_ci			return -1;
667e5b75505Sopenharmony_ci	}
668e5b75505Sopenharmony_ci
669e5b75505Sopenharmony_ci	if (param == NULL)
670e5b75505Sopenharmony_ci		pos = NULL;
671e5b75505Sopenharmony_ci	else
672e5b75505Sopenharmony_ci		pos = os_strstr(param, "priv_dir=");
673e5b75505Sopenharmony_ci	if (pos) {
674e5b75505Sopenharmony_ci		char *end;
675e5b75505Sopenharmony_ci		priv_dir = os_strdup(pos + 9);
676e5b75505Sopenharmony_ci		if (priv_dir == NULL) {
677e5b75505Sopenharmony_ci			os_free(own_dir);
678e5b75505Sopenharmony_ci			return -1;
679e5b75505Sopenharmony_ci		}
680e5b75505Sopenharmony_ci		end = os_strchr(priv_dir, ' ');
681e5b75505Sopenharmony_ci		if (end)
682e5b75505Sopenharmony_ci			*end = '\0';
683e5b75505Sopenharmony_ci	} else {
684e5b75505Sopenharmony_ci		priv_dir = os_strdup("/var/run/wpa_priv");
685e5b75505Sopenharmony_ci		if (priv_dir == NULL) {
686e5b75505Sopenharmony_ci			os_free(own_dir);
687e5b75505Sopenharmony_ci			return -1;
688e5b75505Sopenharmony_ci		}
689e5b75505Sopenharmony_ci	}
690e5b75505Sopenharmony_ci
691e5b75505Sopenharmony_ci	len = os_strlen(own_dir) + 50;
692e5b75505Sopenharmony_ci	drv->own_socket_path = os_malloc(len);
693e5b75505Sopenharmony_ci	if (drv->own_socket_path == NULL) {
694e5b75505Sopenharmony_ci		os_free(priv_dir);
695e5b75505Sopenharmony_ci		os_free(own_dir);
696e5b75505Sopenharmony_ci		return -1;
697e5b75505Sopenharmony_ci	}
698e5b75505Sopenharmony_ci	os_snprintf(drv->own_socket_path, len, "%s/wpa_privsep-%d-%d",
699e5b75505Sopenharmony_ci		    own_dir, getpid(), counter++);
700e5b75505Sopenharmony_ci
701e5b75505Sopenharmony_ci	len = os_strlen(own_dir) + 50;
702e5b75505Sopenharmony_ci	drv->own_cmd_path = os_malloc(len);
703e5b75505Sopenharmony_ci	if (drv->own_cmd_path == NULL) {
704e5b75505Sopenharmony_ci		os_free(drv->own_socket_path);
705e5b75505Sopenharmony_ci		drv->own_socket_path = NULL;
706e5b75505Sopenharmony_ci		os_free(priv_dir);
707e5b75505Sopenharmony_ci		os_free(own_dir);
708e5b75505Sopenharmony_ci		return -1;
709e5b75505Sopenharmony_ci	}
710e5b75505Sopenharmony_ci	os_snprintf(drv->own_cmd_path, len, "%s/wpa_privsep-%d-%d",
711e5b75505Sopenharmony_ci		    own_dir, getpid(), counter++);
712e5b75505Sopenharmony_ci
713e5b75505Sopenharmony_ci	os_free(own_dir);
714e5b75505Sopenharmony_ci
715e5b75505Sopenharmony_ci	drv->priv_addr.sun_family = AF_UNIX;
716e5b75505Sopenharmony_ci	os_snprintf(drv->priv_addr.sun_path, sizeof(drv->priv_addr.sun_path),
717e5b75505Sopenharmony_ci		    "%s/%s", priv_dir, drv->ifname);
718e5b75505Sopenharmony_ci	os_free(priv_dir);
719e5b75505Sopenharmony_ci
720e5b75505Sopenharmony_ci	drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
721e5b75505Sopenharmony_ci	if (drv->priv_socket < 0) {
722e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
723e5b75505Sopenharmony_ci		os_free(drv->own_socket_path);
724e5b75505Sopenharmony_ci		drv->own_socket_path = NULL;
725e5b75505Sopenharmony_ci		return -1;
726e5b75505Sopenharmony_ci	}
727e5b75505Sopenharmony_ci
728e5b75505Sopenharmony_ci	os_memset(&addr, 0, sizeof(addr));
729e5b75505Sopenharmony_ci	addr.sun_family = AF_UNIX;
730e5b75505Sopenharmony_ci	os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path));
731e5b75505Sopenharmony_ci	if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) <
732e5b75505Sopenharmony_ci	    0) {
733e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR,
734e5b75505Sopenharmony_ci			   "privsep-set-params priv-sock: bind(PF_UNIX): %s",
735e5b75505Sopenharmony_ci			   strerror(errno));
736e5b75505Sopenharmony_ci		close(drv->priv_socket);
737e5b75505Sopenharmony_ci		drv->priv_socket = -1;
738e5b75505Sopenharmony_ci		unlink(drv->own_socket_path);
739e5b75505Sopenharmony_ci		os_free(drv->own_socket_path);
740e5b75505Sopenharmony_ci		drv->own_socket_path = NULL;
741e5b75505Sopenharmony_ci		return -1;
742e5b75505Sopenharmony_ci	}
743e5b75505Sopenharmony_ci
744e5b75505Sopenharmony_ci	eloop_register_read_sock(drv->priv_socket, wpa_driver_privsep_receive,
745e5b75505Sopenharmony_ci				 drv, NULL);
746e5b75505Sopenharmony_ci
747e5b75505Sopenharmony_ci	drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
748e5b75505Sopenharmony_ci	if (drv->cmd_socket < 0) {
749e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
750e5b75505Sopenharmony_ci		os_free(drv->own_cmd_path);
751e5b75505Sopenharmony_ci		drv->own_cmd_path = NULL;
752e5b75505Sopenharmony_ci		return -1;
753e5b75505Sopenharmony_ci	}
754e5b75505Sopenharmony_ci
755e5b75505Sopenharmony_ci	os_memset(&addr, 0, sizeof(addr));
756e5b75505Sopenharmony_ci	addr.sun_family = AF_UNIX;
757e5b75505Sopenharmony_ci	os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path));
758e5b75505Sopenharmony_ci	if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0)
759e5b75505Sopenharmony_ci	{
760e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR,
761e5b75505Sopenharmony_ci			   "privsep-set-params cmd-sock: bind(PF_UNIX): %s",
762e5b75505Sopenharmony_ci			   strerror(errno));
763e5b75505Sopenharmony_ci		close(drv->cmd_socket);
764e5b75505Sopenharmony_ci		drv->cmd_socket = -1;
765e5b75505Sopenharmony_ci		unlink(drv->own_cmd_path);
766e5b75505Sopenharmony_ci		os_free(drv->own_cmd_path);
767e5b75505Sopenharmony_ci		drv->own_cmd_path = NULL;
768e5b75505Sopenharmony_ci		return -1;
769e5b75505Sopenharmony_ci	}
770e5b75505Sopenharmony_ci
771e5b75505Sopenharmony_ci	if (wpa_priv_reg_cmd(drv, PRIVSEP_CMD_REGISTER) < 0) {
772e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR, "Failed to register with wpa_priv");
773e5b75505Sopenharmony_ci		return -1;
774e5b75505Sopenharmony_ci	}
775e5b75505Sopenharmony_ci
776e5b75505Sopenharmony_ci	return 0;
777e5b75505Sopenharmony_ci}
778e5b75505Sopenharmony_ci
779e5b75505Sopenharmony_ci
780e5b75505Sopenharmony_cistatic int wpa_driver_privsep_get_capa(void *priv,
781e5b75505Sopenharmony_ci				       struct wpa_driver_capa *capa)
782e5b75505Sopenharmony_ci{
783e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = priv;
784e5b75505Sopenharmony_ci	int res;
785e5b75505Sopenharmony_ci	size_t len = sizeof(*capa);
786e5b75505Sopenharmony_ci
787e5b75505Sopenharmony_ci	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_CAPA, NULL, 0, capa, &len);
788e5b75505Sopenharmony_ci	if (res < 0 || len != sizeof(*capa))
789e5b75505Sopenharmony_ci		return -1;
790e5b75505Sopenharmony_ci	/* For now, no support for passing extended_capa pointers */
791e5b75505Sopenharmony_ci	capa->extended_capa = NULL;
792e5b75505Sopenharmony_ci	capa->extended_capa_mask = NULL;
793e5b75505Sopenharmony_ci	capa->extended_capa_len = 0;
794e5b75505Sopenharmony_ci	return 0;
795e5b75505Sopenharmony_ci}
796e5b75505Sopenharmony_ci
797e5b75505Sopenharmony_ci
798e5b75505Sopenharmony_cistatic const u8 * wpa_driver_privsep_get_mac_addr(void *priv)
799e5b75505Sopenharmony_ci{
800e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = priv;
801e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%s", __func__);
802e5b75505Sopenharmony_ci	return drv->own_addr;
803e5b75505Sopenharmony_ci}
804e5b75505Sopenharmony_ci
805e5b75505Sopenharmony_ci
806e5b75505Sopenharmony_cistatic int wpa_driver_privsep_set_country(void *priv, const char *alpha2)
807e5b75505Sopenharmony_ci{
808e5b75505Sopenharmony_ci	struct wpa_driver_privsep_data *drv = priv;
809e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "%s country='%s'", __func__, alpha2);
810e5b75505Sopenharmony_ci	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_COUNTRY, alpha2,
811e5b75505Sopenharmony_ci			    os_strlen(alpha2), NULL, NULL);
812e5b75505Sopenharmony_ci}
813e5b75505Sopenharmony_ci
814e5b75505Sopenharmony_ci
815e5b75505Sopenharmony_cistruct wpa_driver_ops wpa_driver_privsep_ops = {
816e5b75505Sopenharmony_ci	"privsep",
817e5b75505Sopenharmony_ci	"wpa_supplicant privilege separated driver",
818e5b75505Sopenharmony_ci	.get_bssid = wpa_driver_privsep_get_bssid,
819e5b75505Sopenharmony_ci	.get_ssid = wpa_driver_privsep_get_ssid,
820e5b75505Sopenharmony_ci	.set_key = wpa_driver_privsep_set_key,
821e5b75505Sopenharmony_ci	.init = wpa_driver_privsep_init,
822e5b75505Sopenharmony_ci	.deinit = wpa_driver_privsep_deinit,
823e5b75505Sopenharmony_ci	.set_param = wpa_driver_privsep_set_param,
824e5b75505Sopenharmony_ci	.scan2 = wpa_driver_privsep_scan,
825e5b75505Sopenharmony_ci	.deauthenticate = wpa_driver_privsep_deauthenticate,
826e5b75505Sopenharmony_ci	.authenticate = wpa_driver_privsep_authenticate,
827e5b75505Sopenharmony_ci	.associate = wpa_driver_privsep_associate,
828e5b75505Sopenharmony_ci	.get_capa = wpa_driver_privsep_get_capa,
829e5b75505Sopenharmony_ci	.get_mac_addr = wpa_driver_privsep_get_mac_addr,
830e5b75505Sopenharmony_ci	.get_scan_results2 = wpa_driver_privsep_get_scan_results2,
831e5b75505Sopenharmony_ci	.set_country = wpa_driver_privsep_set_country,
832e5b75505Sopenharmony_ci};
833e5b75505Sopenharmony_ci
834e5b75505Sopenharmony_ci
835e5b75505Sopenharmony_ciconst struct wpa_driver_ops *const wpa_drivers[] =
836e5b75505Sopenharmony_ci{
837e5b75505Sopenharmony_ci	&wpa_driver_privsep_ops,
838e5b75505Sopenharmony_ci	NULL
839e5b75505Sopenharmony_ci};
840