18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - privilege separated driver interface
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/un.h>
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/privsep_commands.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_driver_privsep_data {
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *ctx;
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 own_addr[ETH_ALEN];
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int priv_socket;
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *own_socket_path;
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int cmd_socket;
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *own_cmd_path;
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un priv_addr;
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char ifname[16];
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_priv_reg_cmd(struct wpa_driver_privsep_data *drv, int cmd)
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = sendto(drv->priv_socket, &cmd, sizeof(cmd), 0,
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     (struct sockaddr *) &drv->priv_addr,
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     sizeof(drv->priv_addr));
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0)
386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR, "sendto: %s", strerror(errno));
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res < 0 ? -1 : 0;
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_priv_cmd(struct wpa_driver_privsep_data *drv, int cmd,
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const void *data, size_t data_len,
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			void *reply, size_t *reply_len)
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct msghdr msg;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct iovec io[2];
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	io[0].iov_base = &cmd;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	io[0].iov_len = sizeof(cmd);
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	io[1].iov_base = (u8 *) data;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	io[1].iov_len = data_len;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg.msg_iov = io;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg.msg_iovlen = data ? 2 : 1;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg.msg_name = &drv->priv_addr;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg.msg_namelen = sizeof(drv->priv_addr);
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sendmsg(drv->cmd_socket, &msg, 0) < 0) {
626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR, "sendmsg(cmd_socket): %s",
636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   strerror(errno));
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (reply) {
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fd_set rfds;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct timeval tv;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res;
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		FD_ZERO(&rfds);
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		FD_SET(drv->cmd_socket, &rfds);
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tv.tv_sec = 5;
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tv.tv_usec = 0;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = select(drv->cmd_socket + 1, &rfds, NULL, NULL, &tv);
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 && errno != EINTR) {
786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			wpa_printf(MSG_ERROR, "select: %s", strerror(errno));
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (FD_ISSET(drv->cmd_socket, &rfds)) {
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = recv(drv->cmd_socket, reply, *reply_len, 0);
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (res < 0) {
856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				wpa_printf(MSG_ERROR, "recv: %s",
866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt					   strerror(errno));
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*reply_len = res;
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "PRIVSEP: Timeout while waiting "
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "for reply (cmd=%d)", cmd);
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
100293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_scan(void *priv,
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct wpa_driver_scan_params *params)
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
105abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	struct privsep_cmd_scan scan;
106abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	size_t i;
107abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv);
109abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_memset(&scan, 0, sizeof(scan));
110abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	scan.num_ssids = params->num_ssids;
111abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	for (i = 0; i < params->num_ssids; i++) {
112abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		if (!params->ssids[i].ssid)
113abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			continue;
114abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		scan.ssid_lens[i] = params->ssids[i].ssid_len;
115abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		os_memcpy(scan.ssids[i], params->ssids[i].ssid,
116abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			  scan.ssid_lens[i]);
117abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
118abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
119abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	for (i = 0; i < PRIVSEP_MAX_SCAN_FREQS &&
120abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		     params->freqs && params->freqs[i]; i++)
121abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		scan.freqs[i] = params->freqs[i];
122abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	scan.num_freqs = i;
123abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
124abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	return wpa_priv_cmd(drv, PRIVSEP_CMD_SCAN, &scan, sizeof(scan),
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    NULL, NULL);
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_scan_results *
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_privsep_get_scan_results2(void *priv)
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res, num;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *buf, *pos, *end;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t reply_len = 60000;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_results *results;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res *r;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(reply_len);
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SCAN_RESULTS,
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   NULL, 0, buf, &reply_len);
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "privsep: Received %lu bytes of scan results",
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned long) reply_len);
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (reply_len < sizeof(int)) {
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "privsep: Invalid scan result len %lu",
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) reply_len);
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + reply_len;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&num, pos, sizeof(int));
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num < 0 || num > 1000) {
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += sizeof(int);
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	results = os_zalloc(sizeof(*results));
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (results == NULL) {
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	results->res = os_calloc(num, sizeof(struct wpa_scan_res *));
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (results->res == NULL) {
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(results);
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
180e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	while (results->num < (size_t) num && end - pos > (int) sizeof(int)) {
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int len;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&len, pos, sizeof(int));
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += sizeof(int);
184d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (len < 0 || len > 10000 || len > end - pos)
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = os_malloc(len);
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (r == NULL)
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(r, pos, len);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += len;
192abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		if (sizeof(*r) + r->ie_len + r->beacon_ie_len > (size_t) len) {
193abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			wpa_printf(MSG_ERROR,
194abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt				   "privsep: Invalid scan result len (%d + %d + %d > %d)",
195abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt				   (int) sizeof(*r), (int) r->ie_len,
196abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt				   (int) r->beacon_ie_len, len);
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(r);
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		results->res[results->num++] = r;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return results;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_set_key(const char *ifname, void *priv,
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      enum wpa_alg alg, const u8 *addr,
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      int key_idx, int set_tx,
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *seq, size_t seq_len,
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *key, size_t key_len)
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct privsep_cmd_set_key cmd;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d",
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   __func__, priv, alg, key_idx, set_tx);
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&cmd, 0, sizeof(cmd));
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmd.alg = alg;
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(cmd.addr, addr, ETH_ALEN);
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(cmd.addr, 0xff, ETH_ALEN);
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmd.key_idx = key_idx;
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmd.set_tx = set_tx;
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) {
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(cmd.seq, seq, seq_len);
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmd.seq_len = seq_len;
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key && key_len > 0 && key_len < sizeof(cmd.key)) {
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(cmd.key, key, key_len);
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmd.key_len = key_len;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_KEY, &cmd, sizeof(cmd),
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    NULL, NULL);
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
243d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int wpa_driver_privsep_authenticate(
244d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	void *priv, struct wpa_driver_auth_params *params)
245d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
246d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
247d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct privsep_cmd_authenticate *data;
248d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int i, res;
249d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	size_t buflen;
250d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u8 *pos;
251d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
252d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d bssid=" MACSTR
253d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   " auth_alg=%d local_state_change=%d p2p=%d",
254d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   __func__, priv, params->freq, MAC2STR(params->bssid),
255d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   params->auth_alg, params->local_state_change, params->p2p);
256d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
2579839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	buflen = sizeof(*data) + params->ie_len + params->auth_data_len;
258d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data = os_zalloc(buflen);
259d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (data == NULL)
260d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
261d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
262d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data->freq = params->freq;
263d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memcpy(data->bssid, params->bssid, ETH_ALEN);
264d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memcpy(data->ssid, params->ssid, params->ssid_len);
265d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data->ssid_len = params->ssid_len;
266d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data->auth_alg = params->auth_alg;
267d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data->ie_len = params->ie_len;
268d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	for (i = 0; i < 4; i++) {
269d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (params->wep_key[i])
270d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			os_memcpy(data->wep_key[i], params->wep_key[i],
271d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  params->wep_key_len[i]);
272d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		data->wep_key_len[i] = params->wep_key_len[i];
273d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
274d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data->wep_tx_keyidx = params->wep_tx_keyidx;
275d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data->local_state_change = params->local_state_change;
276d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data->p2p = params->p2p;
277d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	pos = (u8 *) (data + 1);
278d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (params->ie_len) {
279d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		os_memcpy(pos, params->ie, params->ie_len);
280d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		pos += params->ie_len;
281d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
2829839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	if (params->auth_data_len)
2839839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		os_memcpy(pos, params->auth_data, params->auth_data_len);
284d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
285d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_AUTHENTICATE, data, buflen,
286d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   NULL, NULL);
287d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_free(data);
288d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
289d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return res;
290d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
291d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
292d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_associate(
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *priv, struct wpa_driver_associate_params *params)
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct privsep_cmd_associate *data;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t buflen;
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
3036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		   __func__, priv, params->freq.freq, params->pairwise_suite,
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   params->group_suite, params->key_mgmt_suite,
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   params->auth_alg, params->mode);
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buflen = sizeof(*data) + params->wpa_ie_len;
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data = os_zalloc(buflen);
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->bssid)
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(data->bssid, params->bssid, ETH_ALEN);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(data->ssid, params->ssid, params->ssid_len);
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->ssid_len = params->ssid_len;
3166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	data->hwmode = params->freq.mode;
3176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	data->freq = params->freq.freq;
3186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	data->channel = params->freq.channel;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->pairwise_suite = params->pairwise_suite;
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->group_suite = params->group_suite;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->key_mgmt_suite = params->key_mgmt_suite;
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->auth_alg = params->auth_alg;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->mode = params->mode;
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->wpa_ie_len = params->wpa_ie_len;
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->wpa_ie)
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(data + 1, params->wpa_ie, params->wpa_ie_len);
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add support for other assoc parameters */
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_ASSOCIATE, data, buflen,
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   NULL, NULL);
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data);
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_get_bssid(void *priv, u8 *bssid)
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len = ETH_ALEN;
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_BSSID, NULL, 0, bssid, &len);
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || len != ETH_ALEN)
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid)
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res, ssid_len;
3549d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt	u8 reply[sizeof(int) + SSID_MAX_LEN];
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len = sizeof(reply);
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SSID, NULL, 0, reply, &len);
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || len < sizeof(int))
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ssid_len, reply, sizeof(int));
3619d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt	if (ssid_len < 0 || ssid_len > SSID_MAX_LEN ||
3629d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt	    sizeof(int) + ssid_len > len) {
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "privsep: Invalid get SSID reply");
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ssid, &reply[sizeof(int)], ssid_len);
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ssid_len;
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr,
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  int reason_code)
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	//struct wpa_driver_privsep_data *drv = priv;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   __func__, MAC2STR(addr), reason_code);
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s - TODO", __func__);
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
382d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void wpa_driver_privsep_event_auth(void *ctx, u8 *buf, size_t len)
383d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
384d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	union wpa_event_data data;
385d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct privsep_event_auth *auth;
386d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
387d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
388d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (len < sizeof(*auth))
389d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return;
390d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	auth = (struct privsep_event_auth *) buf;
391d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (len < sizeof(*auth) + auth->ies_len)
392d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return;
393d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
394d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memcpy(data.auth.peer, auth->peer, ETH_ALEN);
395d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memcpy(data.auth.bssid, auth->bssid, ETH_ALEN);
396d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data.auth.auth_type = auth->auth_type;
397d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data.auth.auth_transaction = auth->auth_transaction;
398d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data.auth.status_code = auth->status_code;
399d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (auth->ies_len) {
400d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		data.auth.ies = (u8 *) (auth + 1);
401d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		data.auth.ies_len = auth->ies_len;
402d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
403d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
404d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_supplicant_event(ctx, EVENT_AUTH, &data);
405d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
406d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
407d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_assoc(void *ctx,
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   enum wpa_event_type event,
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   u8 *buf, size_t len)
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int inc_data = 0;
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos, *end;
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ie_len;
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + len;
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < (int) sizeof(int))
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ie_len, pos, sizeof(int));
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += sizeof(int);
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie_len < 0 || ie_len > end - pos)
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie_len) {
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data.assoc_info.req_ies = pos;
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data.assoc_info.req_ies_len = ie_len;
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ie_len;
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		inc_data = 1;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(ctx, event, inc_data ? &data : NULL);
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_interface_status(void *ctx, u8 *buf,
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      size_t len)
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ievent;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(int) ||
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    len - sizeof(int) > sizeof(data.interface_status.ifname))
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ievent, buf, sizeof(int));
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.interface_status.ievent = ievent;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(data.interface_status.ifname, buf + sizeof(int),
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  len - sizeof(int));
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &data);
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_michael_mic_failure(
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *ctx, u8 *buf, size_t len)
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len != sizeof(int))
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&data.michael_mic_failure.unicast, buf, sizeof(int));
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_pmkid_candidate(void *ctx, u8 *buf,
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     size_t len)
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len != sizeof(struct pmkid_candidate))
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&data.pmkid_candidate, buf, len);
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(ctx, EVENT_PMKID_CANDIDATE, &data);
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_stkstart(void *ctx, u8 *buf, size_t len)
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len != ETH_ALEN)
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(data.stkstart.peer, buf, ETH_ALEN);
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_ft_response(void *ctx, u8 *buf,
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 size_t len)
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(int) + ETH_ALEN)
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&data.ft_ies.ft_action, buf, sizeof(int));
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(data.ft_ies.target_ap, buf + sizeof(int), ETH_ALEN);
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.ft_ies.ies = buf + sizeof(int) + ETH_ALEN;
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.ft_ies.ies_len = len - sizeof(int) - ETH_ALEN;
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(ctx, EVENT_FT_RESPONSE, &data);
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_rx_eapol(void *ctx, u8 *buf, size_t len)
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < ETH_ALEN)
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv_event_eapol_rx(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN);
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_receive(int sock, void *eloop_ctx,
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       void *sock_ctx)
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = eloop_ctx;
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *buf, *event_buf;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t event_len;
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res, event;
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum privsep_event e;
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un from;
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	socklen_t fromlen = sizeof(from);
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const size_t buflen = 2000;
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(buflen);
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = recvfrom(sock, buf, buflen, 0,
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       (struct sockaddr *) &from, &fromlen);
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
5436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR, "recvfrom(priv_socket): %s",
5446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   strerror(errno));
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "privsep_driver: received %u bytes", res);
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < (int) sizeof(int)) {
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Too short event message (len=%d)", res);
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&event, buf, sizeof(int));
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	event_buf = &buf[sizeof(int)];
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	event_len = res - sizeof(int);
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "privsep: Event %d received (len=%lu)",
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   event, (unsigned long) event_len);
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e = event;
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (e) {
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_SCAN_RESULTS:
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL);
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
567d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case PRIVSEP_EVENT_SCAN_STARTED:
568d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
569d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_ASSOC:
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOC,
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       event_buf, event_len);
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_DISASSOC:
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_ASSOCINFO:
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOCINFO,
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       event_buf, event_len);
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_MICHAEL_MIC_FAILURE:
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_michael_mic_failure(
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->ctx, event_buf, event_len);
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_INTERFACE_STATUS:
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_interface_status(drv->ctx, event_buf,
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							  event_len);
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_PMKID_CANDIDATE:
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_pmkid_candidate(drv->ctx, event_buf,
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 event_len);
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_STKSTART:
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_stkstart(drv->ctx, event_buf,
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  event_len);
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_FT_RESPONSE:
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_ft_response(drv->ctx, event_buf,
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     event_len);
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_RX_EAPOL:
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf,
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  event_len);
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
605d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case PRIVSEP_EVENT_AUTH:
606d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_driver_privsep_event_auth(drv->ctx, event_buf, event_len);
607d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * wpa_driver_privsep_init(void *ctx, const char *ifname)
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv;
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv = os_zalloc(sizeof(*drv));
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv == NULL)
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->ctx = ctx;
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->priv_socket = -1;
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->cmd_socket = -1;
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return drv;
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_deinit(void *priv)
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->priv_socket >= 0) {
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_priv_reg_cmd(drv, PRIVSEP_CMD_UNREGISTER);
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_read_sock(drv->priv_socket);
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(drv->priv_socket);
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->own_socket_path) {
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(drv->own_socket_path);
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_socket_path);
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->cmd_socket >= 0) {
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_read_sock(drv->cmd_socket);
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(drv->cmd_socket);
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->own_cmd_path) {
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(drv->own_cmd_path);
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_cmd_path);
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(drv);
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_set_param(void *priv, const char *param)
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *pos;
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *own_dir, *priv_dir;
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static unsigned int counter = 0;
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un addr;
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (param == NULL)
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = NULL;
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strstr(param, "own_dir=");
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos) {
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char *end;
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		own_dir = os_strdup(pos + 8);
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (own_dir == NULL)
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = os_strchr(own_dir, ' ');
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end)
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*end = '\0';
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		own_dir = os_strdup("/tmp");
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (own_dir == NULL)
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (param == NULL)
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = NULL;
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strstr(param, "priv_dir=");
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos) {
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char *end;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv_dir = os_strdup(pos + 9);
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (priv_dir == NULL) {
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(own_dir);
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = os_strchr(priv_dir, ' ');
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end)
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*end = '\0';
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv_dir = os_strdup("/var/run/wpa_priv");
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (priv_dir == NULL) {
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(own_dir);
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_strlen(own_dir) + 50;
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->own_socket_path = os_malloc(len);
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->own_socket_path == NULL) {
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(priv_dir);
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(own_dir);
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(drv->own_socket_path, len, "%s/wpa_privsep-%d-%d",
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    own_dir, getpid(), counter++);
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_strlen(own_dir) + 50;
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->own_cmd_path = os_malloc(len);
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->own_cmd_path == NULL) {
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_socket_path);
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->own_socket_path = NULL;
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(priv_dir);
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(own_dir);
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(drv->own_cmd_path, len, "%s/wpa_privsep-%d-%d",
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    own_dir, getpid(), counter++);
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(own_dir);
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->priv_addr.sun_family = AF_UNIX;
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(drv->priv_addr.sun_path, sizeof(drv->priv_addr.sun_path),
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    "%s/%s", priv_dir, drv->ifname);
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(priv_dir);
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->priv_socket < 0) {
7406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_socket_path);
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->own_socket_path = NULL;
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path));
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) <
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
7516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR,
7526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "privsep-set-params priv-sock: bind(PF_UNIX): %s",
7536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   strerror(errno));
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(drv->priv_socket);
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->priv_socket = -1;
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(drv->own_socket_path);
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_socket_path);
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->own_socket_path = NULL;
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_read_sock(drv->priv_socket, wpa_driver_privsep_receive,
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 drv, NULL);
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->cmd_socket < 0) {
7676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_cmd_path);
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->own_cmd_path = NULL;
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path));
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0)
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
7786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR,
7796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "privsep-set-params cmd-sock: bind(PF_UNIX): %s",
7806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   strerror(errno));
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(drv->cmd_socket);
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->cmd_socket = -1;
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(drv->own_cmd_path);
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_cmd_path);
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->own_cmd_path = NULL;
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_priv_reg_cmd(drv, PRIVSEP_CMD_REGISTER) < 0) {
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to register with wpa_priv");
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_get_capa(void *priv,
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct wpa_driver_capa *capa)
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len = sizeof(*capa);
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_CAPA, NULL, 0, capa, &len);
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || len != sizeof(*capa))
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
808d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	/* For now, no support for passing extended_capa pointers */
809d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	capa->extended_capa = NULL;
810d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	capa->extended_capa_mask = NULL;
811d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	capa->extended_capa_len = 0;
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * wpa_driver_privsep_get_mac_addr(void *priv)
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s", __func__);
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return drv->own_addr;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_set_country(void *priv, const char *alpha2)
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s country='%s'", __func__, alpha2);
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_COUNTRY, alpha2,
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    os_strlen(alpha2), NULL, NULL);
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_driver_ops wpa_driver_privsep_ops = {
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	"privsep",
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	"wpa_supplicant privilege separated driver",
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.get_bssid = wpa_driver_privsep_get_bssid,
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.get_ssid = wpa_driver_privsep_get_ssid,
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.set_key = wpa_driver_privsep_set_key,
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.init = wpa_driver_privsep_init,
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.deinit = wpa_driver_privsep_deinit,
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.set_param = wpa_driver_privsep_set_param,
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.scan2 = wpa_driver_privsep_scan,
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.deauthenticate = wpa_driver_privsep_deauthenticate,
844d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	.authenticate = wpa_driver_privsep_authenticate,
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.associate = wpa_driver_privsep_associate,
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.get_capa = wpa_driver_privsep_get_capa,
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.get_mac_addr = wpa_driver_privsep_get_mac_addr,
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.get_scan_results2 = wpa_driver_privsep_get_scan_results2,
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.set_country = wpa_driver_privsep_set_country,
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8531d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtconst struct wpa_driver_ops *const wpa_drivers[] =
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	&wpa_driver_privsep_ops,
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NULL
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
858