1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA Supplicant - privilege separated driver interface
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2007-2009, 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#include <sys/un.h>
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "driver.h"
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eloop.h"
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "privsep_commands.h"
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_driver_privsep_data {
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	void *ctx;
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 own_addr[ETH_ALEN];
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int priv_socket;
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *own_socket_path;
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int cmd_socket;
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *own_cmd_path;
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct sockaddr_un priv_addr;
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char ifname[16];
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_priv_reg_cmd(struct wpa_driver_privsep_data *drv, int cmd)
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int res;
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	res = sendto(drv->priv_socket, &cmd, sizeof(cmd), 0,
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		     (struct sockaddr *) &drv->priv_addr,
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		     sizeof(drv->priv_addr));
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (res < 0)
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("sendto");
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return res < 0 ? -1 : 0;
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_priv_cmd(struct wpa_driver_privsep_data *drv, int cmd,
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			const void *data, size_t data_len,
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			void *reply, size_t *reply_len)
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct msghdr msg;
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct iovec io[2];
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	io[0].iov_base = &cmd;
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	io[0].iov_len = sizeof(cmd);
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	io[1].iov_base = (u8 *) data;
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	io[1].iov_len = data_len;
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	msg.msg_iov = io;
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	msg.msg_iovlen = data ? 2 : 1;
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	msg.msg_name = &drv->priv_addr;
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	msg.msg_namelen = sizeof(drv->priv_addr);
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sendmsg(drv->cmd_socket, &msg, 0) < 0) {
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("sendmsg(cmd_socket)");
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (reply) {
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fd_set rfds;
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		struct timeval tv;
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		int res;
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		FD_ZERO(&rfds);
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		FD_SET(drv->cmd_socket, &rfds);
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		tv.tv_sec = 5;
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		tv.tv_usec = 0;
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		res = select(drv->cmd_socket + 1, &rfds, NULL, NULL, &tv);
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (res < 0 && errno != EINTR) {
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			perror("select");
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (FD_ISSET(drv->cmd_socket, &rfds)) {
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			res = recv(drv->cmd_socket, reply, *reply_len, 0);
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (res < 0) {
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				perror("recv");
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				return -1;
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			}
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*reply_len = res;
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else {
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "PRIVSEP: Timeout while waiting "
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "for reply (cmd=%d)", cmd);
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_privsep_set_wpa(void *priv, int enabled)
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_WPA, &enabled,
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    sizeof(enabled), NULL, NULL);
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_privsep_scan(void *priv, const u8 *ssid, size_t ssid_len)
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv);
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return wpa_priv_cmd(drv, PRIVSEP_CMD_SCAN, ssid, ssid_len,
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    NULL, NULL);
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpa_scan_results *
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_driver_privsep_get_scan_results2(void *priv)
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int res, num;
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 *buf, *pos, *end;
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t reply_len = 60000;
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_scan_results *results;
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_scan_res *r;
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf = os_malloc(reply_len);
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (buf == NULL)
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SCAN_RESULTS,
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   NULL, 0, buf, &reply_len);
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (res < 0) {
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(buf);
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "privsep: Received %lu bytes of scan results",
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (unsigned long) reply_len);
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (reply_len < sizeof(int)) {
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "privsep: Invalid scan result len %lu",
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned long) reply_len);
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(buf);
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = buf;
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	end = buf + reply_len;
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(&num, pos, sizeof(int));
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (num < 0 || num > 1000) {
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(buf);
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos += sizeof(int);
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	results = os_zalloc(sizeof(*results));
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (results == NULL) {
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(buf);
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	results->res = os_zalloc(num * sizeof(struct wpa_scan_res *));
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (results->res == NULL) {
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(results);
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(buf);
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (results->num < (size_t) num && pos + sizeof(int) < end) {
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		int len;
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(&len, pos, sizeof(int));
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos += sizeof(int);
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (len < 0 || len > 10000 || pos + len > end)
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		r = os_malloc(len);
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (r == NULL)
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(r, pos, len);
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos += len;
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sizeof(*r) + r->ie_len > (size_t) len) {
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(r);
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		results->res[results->num++] = r;
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(buf);
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return results;
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_privsep_set_key(void *priv, wpa_alg alg, const u8 *addr,
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   int key_idx, int set_tx,
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   const u8 *seq, size_t seq_len,
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   const u8 *key, size_t key_len)
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct privsep_cmd_set_key cmd;
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d",
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__, priv, alg, key_idx, set_tx);
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&cmd, 0, sizeof(cmd));
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	cmd.alg = alg;
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (addr)
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(cmd.addr, addr, ETH_ALEN);
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memset(cmd.addr, 0xff, ETH_ALEN);
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	cmd.key_idx = key_idx;
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	cmd.set_tx = set_tx;
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) {
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(cmd.seq, seq, seq_len);
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		cmd.seq_len = seq_len;
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (key && key_len > 0 && key_len < sizeof(cmd.key)) {
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(cmd.key, key, key_len);
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		cmd.key_len = key_len;
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_KEY, &cmd, sizeof(cmd),
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    NULL, NULL);
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_privsep_associate(
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	void *priv, struct wpa_driver_associate_params *params)
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct privsep_cmd_associate *data;
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int res;
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t buflen;
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__, priv, params->freq, params->pairwise_suite,
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   params->group_suite, params->key_mgmt_suite,
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   params->auth_alg, params->mode);
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buflen = sizeof(*data) + params->wpa_ie_len;
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data = os_zalloc(buflen);
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data == NULL)
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (params->bssid)
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(data->bssid, params->bssid, ETH_ALEN);
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(data->ssid, params->ssid, params->ssid_len);
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data->ssid_len = params->ssid_len;
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data->freq = params->freq;
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data->pairwise_suite = params->pairwise_suite;
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data->group_suite = params->group_suite;
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data->key_mgmt_suite = params->key_mgmt_suite;
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data->auth_alg = params->auth_alg;
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data->mode = params->mode;
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data->wpa_ie_len = params->wpa_ie_len;
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (params->wpa_ie)
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(data + 1, params->wpa_ie, params->wpa_ie_len);
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* TODO: add support for other assoc parameters */
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_ASSOCIATE, data, buflen,
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   NULL, NULL);
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(data);
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return res;
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_privsep_get_bssid(void *priv, u8 *bssid)
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int res;
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t len = ETH_ALEN;
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_BSSID, NULL, 0, bssid, &len);
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (res < 0 || len != ETH_ALEN)
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid)
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int res, ssid_len;
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 reply[sizeof(int) + 32];
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t len = sizeof(reply);
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SSID, NULL, 0, reply, &len);
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (res < 0 || len < sizeof(int))
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(&ssid_len, reply, sizeof(int));
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid_len < 0 || ssid_len > 32 || sizeof(int) + ssid_len > len) {
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "privsep: Invalid get SSID reply");
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(ssid, &reply[sizeof(int)], ssid_len);
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ssid_len;
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr,
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  int reason_code)
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	//struct wpa_driver_privsep_data *drv = priv;
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__, MAC2STR(addr), reason_code);
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s - TODO", __func__);
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_privsep_disassociate(void *priv, const u8 *addr,
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					int reason_code)
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	//struct wpa_driver_privsep_data *drv = priv;
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__, MAC2STR(addr), reason_code);
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s - TODO", __func__);
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_privsep_event_assoc(void *ctx, wpa_event_type event,
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   u8 *buf, size_t len)
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	union wpa_event_data data;
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int inc_data = 0;
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 *pos, *end;
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ie_len;
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&data, 0, sizeof(data));
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = buf;
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	end = buf + len;
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (end - pos < (int) sizeof(int))
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(&ie_len, pos, sizeof(int));
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos += sizeof(int);
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ie_len < 0 || ie_len > end - pos)
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ie_len) {
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		data.assoc_info.req_ies = pos;
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		data.assoc_info.req_ies_len = ie_len;
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos += ie_len;
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		inc_data = 1;
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_supplicant_event(ctx, event, inc_data ? &data : NULL);
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_privsep_event_interface_status(void *ctx, u8 *buf,
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						      size_t len)
361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	union wpa_event_data data;
363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ievent;
364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (len < sizeof(int) ||
366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    len - sizeof(int) > sizeof(data.interface_status.ifname))
367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(&ievent, buf, sizeof(int));
370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&data, 0, sizeof(data));
372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data.interface_status.ievent = ievent;
373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(data.interface_status.ifname, buf + sizeof(int),
374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		  len - sizeof(int));
375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &data);
376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_privsep_event_michael_mic_failure(
380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	void *ctx, u8 *buf, size_t len)
381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	union wpa_event_data data;
383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (len != sizeof(int))
385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&data, 0, sizeof(data));
388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(&data.michael_mic_failure.unicast, buf, sizeof(int));
389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_privsep_event_pmkid_candidate(void *ctx, u8 *buf,
394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						     size_t len)
395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	union wpa_event_data data;
397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (len != sizeof(struct pmkid_candidate))
399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&data, 0, sizeof(data));
402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(&data.pmkid_candidate, buf, len);
403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_supplicant_event(ctx, EVENT_PMKID_CANDIDATE, &data);
404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_privsep_event_stkstart(void *ctx, u8 *buf, size_t len)
408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	union wpa_event_data data;
410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (len != ETH_ALEN)
412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&data, 0, sizeof(data));
415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(data.stkstart.peer, buf, ETH_ALEN);
416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_privsep_event_ft_response(void *ctx, u8 *buf,
421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						 size_t len)
422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	union wpa_event_data data;
424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (len < sizeof(int) + ETH_ALEN)
426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&data, 0, sizeof(data));
429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(&data.ft_ies.ft_action, buf, sizeof(int));
430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(data.ft_ies.target_ap, buf + sizeof(int), ETH_ALEN);
431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data.ft_ies.ies = buf + sizeof(int) + ETH_ALEN;
432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data.ft_ies.ies_len = len - sizeof(int) - ETH_ALEN;
433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_supplicant_event(ctx, EVENT_FT_RESPONSE, &data);
434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_privsep_event_rx_eapol(void *ctx, u8 *buf, size_t len)
438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (len < ETH_ALEN)
440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_supplicant_rx_eapol(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN);
443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_privsep_event_sta_rx(void *ctx, u8 *buf, size_t len)
447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CLIENT_MLME
449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ieee80211_rx_status *rx_status;
450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (len < sizeof(*rx_status))
452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	rx_status = (struct ieee80211_rx_status *) buf;
454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf += sizeof(*rx_status);
455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	len -= sizeof(*rx_status);
456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_supplicant_sta_rx(ctx, buf, len, rx_status);
458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CLIENT_MLME */
459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_privsep_receive(int sock, void *eloop_ctx,
463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       void *sock_ctx)
464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = eloop_ctx;
466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 *buf, *event_buf;
467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t event_len;
468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int res, event;
469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	enum privsep_event e;
470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct sockaddr_un from;
471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	socklen_t fromlen = sizeof(from);
472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const size_t buflen = 2000;
473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf = os_malloc(buflen);
475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (buf == NULL)
476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	res = recvfrom(sock, buf, buflen, 0,
478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		       (struct sockaddr *) &from, &fromlen);
479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (res < 0) {
480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("recvfrom(priv_socket)");
481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(buf);
482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "privsep_driver: received %u bytes", res);
486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (res < (int) sizeof(int)) {
488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Too short event message (len=%d)", res);
489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(&event, buf, sizeof(int));
493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	event_buf = &buf[sizeof(int)];
494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	event_len = res - sizeof(int);
495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "privsep: Event %d received (len=%lu)",
496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   event, (unsigned long) event_len);
497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	e = event;
499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (e) {
500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case PRIVSEP_EVENT_SCAN_RESULTS:
501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL);
502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case PRIVSEP_EVENT_ASSOC:
504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOC,
505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					       event_buf, event_len);
506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case PRIVSEP_EVENT_DISASSOC:
508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case PRIVSEP_EVENT_ASSOCINFO:
511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOCINFO,
512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					       event_buf, event_len);
513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case PRIVSEP_EVENT_MICHAEL_MIC_FAILURE:
515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_driver_privsep_event_michael_mic_failure(
516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			drv->ctx, event_buf, event_len);
517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case PRIVSEP_EVENT_INTERFACE_STATUS:
519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_driver_privsep_event_interface_status(drv->ctx, event_buf,
520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt							  event_len);
521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case PRIVSEP_EVENT_PMKID_CANDIDATE:
523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_driver_privsep_event_pmkid_candidate(drv->ctx, event_buf,
524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt							 event_len);
525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case PRIVSEP_EVENT_STKSTART:
527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_driver_privsep_event_stkstart(drv->ctx, event_buf,
528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						  event_len);
529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case PRIVSEP_EVENT_FT_RESPONSE:
531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_driver_privsep_event_ft_response(drv->ctx, event_buf,
532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						     event_len);
533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case PRIVSEP_EVENT_RX_EAPOL:
535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf,
536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						  event_len);
537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case PRIVSEP_EVENT_STA_RX:
539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_driver_privsep_event_sta_rx(drv->ctx, event_buf,
540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						event_len);
541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(buf);
545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void * wpa_driver_privsep_init(void *ctx, const char *ifname)
549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv;
551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv = os_zalloc(sizeof(*drv));
553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (drv == NULL)
554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv->ctx = ctx;
556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv->priv_socket = -1;
557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv->cmd_socket = -1;
558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return drv;
561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_driver_privsep_deinit(void *priv)
565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (drv->priv_socket >= 0) {
569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_priv_reg_cmd(drv, PRIVSEP_CMD_UNREGISTER);
570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		eloop_unregister_read_sock(drv->priv_socket);
571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		close(drv->priv_socket);
572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (drv->own_socket_path) {
575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		unlink(drv->own_socket_path);
576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(drv->own_socket_path);
577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (drv->cmd_socket >= 0) {
580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		eloop_unregister_read_sock(drv->cmd_socket);
581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		close(drv->cmd_socket);
582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (drv->own_cmd_path) {
585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		unlink(drv->own_cmd_path);
586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(drv->own_cmd_path);
587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(drv);
590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_privsep_set_param(void *priv, const char *param)
594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const char *pos;
597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *own_dir, *priv_dir;
598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	static unsigned int counter = 0;
599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t len;
600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct sockaddr_un addr;
601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (param == NULL)
604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = NULL;
605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else
606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = os_strstr(param, "own_dir=");
607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (pos) {
608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		char *end;
609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		own_dir = os_strdup(pos + 8);
610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (own_dir == NULL)
611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		end = os_strchr(own_dir, ' ');
613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (end)
614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*end = '\0';
615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		own_dir = os_strdup("/tmp");
617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (own_dir == NULL)
618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (param == NULL)
622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = NULL;
623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else
624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = os_strstr(param, "priv_dir=");
625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (pos) {
626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		char *end;
627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		priv_dir = os_strdup(pos + 9);
628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (priv_dir == NULL) {
629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(own_dir);
630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		end = os_strchr(priv_dir, ' ');
633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (end)
634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*end = '\0';
635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		priv_dir = os_strdup("/var/run/wpa_priv");
637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (priv_dir == NULL) {
638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(own_dir);
639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	len = os_strlen(own_dir) + 50;
644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv->own_socket_path = os_malloc(len);
645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (drv->own_socket_path == NULL) {
646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(priv_dir);
647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(own_dir);
648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_snprintf(drv->own_socket_path, len, "%s/wpa_privsep-%d-%d",
651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    own_dir, getpid(), counter++);
652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	len = os_strlen(own_dir) + 50;
654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv->own_cmd_path = os_malloc(len);
655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (drv->own_cmd_path == NULL) {
656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(drv->own_socket_path);
657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		drv->own_socket_path = NULL;
658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(priv_dir);
659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(own_dir);
660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_snprintf(drv->own_cmd_path, len, "%s/wpa_privsep-%d-%d",
663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    own_dir, getpid(), counter++);
664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(own_dir);
666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv->priv_addr.sun_family = AF_UNIX;
668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_snprintf(drv->priv_addr.sun_path, sizeof(drv->priv_addr.sun_path),
669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    "%s/%s", priv_dir, drv->ifname);
670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(priv_dir);
671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (drv->priv_socket < 0) {
674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("socket(PF_UNIX)");
675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(drv->own_socket_path);
676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		drv->own_socket_path = NULL;
677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	addr.sun_family = AF_UNIX;
682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path));
683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) <
684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    0) {
685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("bind(PF_UNIX)");
686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		close(drv->priv_socket);
687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		drv->priv_socket = -1;
688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		unlink(drv->own_socket_path);
689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(drv->own_socket_path);
690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		drv->own_socket_path = NULL;
691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eloop_register_read_sock(drv->priv_socket, wpa_driver_privsep_receive,
695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				 drv, NULL);
696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (drv->cmd_socket < 0) {
699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("socket(PF_UNIX)");
700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(drv->own_cmd_path);
701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		drv->own_cmd_path = NULL;
702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	addr.sun_family = AF_UNIX;
707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path));
708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0)
709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{
710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("bind(PF_UNIX)");
711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		close(drv->cmd_socket);
712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		drv->cmd_socket = -1;
713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		unlink(drv->own_cmd_path);
714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(drv->own_cmd_path);
715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		drv->own_cmd_path = NULL;
716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa_priv_reg_cmd(drv, PRIVSEP_CMD_REGISTER) < 0) {
720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to register with wpa_priv");
721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_privsep_get_capa(void *priv,
729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       struct wpa_driver_capa *capa)
730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int res;
733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t len = sizeof(*capa);
734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_CAPA, NULL, 0, capa, &len);
736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (res < 0 || len != sizeof(*capa))
737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic const u8 * wpa_driver_privsep_get_mac_addr(void *priv)
743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s", __func__);
746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return drv->own_addr;
747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_privsep_set_mode(void *priv, int mode)
751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s mode=%d", __func__, mode);
754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_MODE, &mode, sizeof(mode),
755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    NULL, NULL);
756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_privsep_set_country(void *priv, const char *alpha2)
760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s country='%s'", __func__, alpha2);
763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_COUNTRY, alpha2,
764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    os_strlen(alpha2), NULL, NULL);
765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_driver_ops wpa_driver_privsep_ops = {
769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	"privsep",
770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	"wpa_supplicant privilege separated driver",
771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_get_bssid,
772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_get_ssid,
773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_set_wpa,
774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_set_key,
775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_init,
776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_deinit,
777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_set_param,
778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* set_countermeasures */,
779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* set_drop_unencrypted */,
780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_scan,
781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /*  get_scan_results */,
782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_deauthenticate,
783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_disassociate,
784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_associate,
785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* set_auth_alg */,
786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* add_pmkid */,
787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* remove_pmkid */,
788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* flush_pmkid */,
789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_get_capa,
790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* poll */,
791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* get_ifname */,
792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_get_mac_addr,
793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* send_eapol */,
794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* set_operstate */,
795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* mlme_setprotection */,
796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* get_hw_feature_data */,
797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* set_channel */,
798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* set_ssid */,
799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* set_bssid */,
800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* send_mlme */,
801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* mlme_add_sta */,
802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* mlme_remove_sta */,
803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* update_ft_ies */,
804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* send_ft_action */,
805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_get_scan_results2,
806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* set_probe_req_ie */,
807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_set_mode,
808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_driver_privsep_set_country,
809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* global_init */,
810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* global_deinit */,
811526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* init2 */,
812526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL /* get_interfaces */
813526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
814526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
815526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
816526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_driver_ops *wpa_supplicant_drivers[] =
817526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
818526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	&wpa_driver_privsep_ops,
819526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	NULL
820526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
821