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
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry 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;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *ssid = params->ssids[0].ssid;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t ssid_len = params->ssids[0].ssid_len;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv);
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_priv_cmd(drv, PRIVSEP_CMD_SCAN, ssid, ssid_len,
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    NULL, NULL);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_scan_results *
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_privsep_get_scan_results2(void *priv)
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res, num;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *buf, *pos, *end;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t reply_len = 60000;
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_results *results;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res *r;
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(reply_len);
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SCAN_RESULTS,
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   NULL, 0, buf, &reply_len);
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "privsep: Received %lu bytes of scan results",
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned long) reply_len);
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (reply_len < sizeof(int)) {
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "privsep: Invalid scan result len %lu",
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) reply_len);
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + reply_len;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&num, pos, sizeof(int));
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num < 0 || num > 1000) {
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += sizeof(int);
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	results = os_zalloc(sizeof(*results));
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (results == NULL) {
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	results->res = os_calloc(num, sizeof(struct wpa_scan_res *));
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (results->res == NULL) {
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(results);
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (results->num < (size_t) num && pos + sizeof(int) < end) {
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int len;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&len, pos, sizeof(int));
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += sizeof(int);
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 0 || len > 10000 || pos + len > end)
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = os_malloc(len);
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (r == NULL)
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(r, pos, len);
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += len;
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sizeof(*r) + r->ie_len > (size_t) len) {
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(r);
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		results->res[results->num++] = r;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return results;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_set_key(const char *ifname, void *priv,
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      enum wpa_alg alg, const u8 *addr,
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      int key_idx, int set_tx,
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *seq, size_t seq_len,
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *key, size_t key_len)
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct privsep_cmd_set_key cmd;
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d",
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   __func__, priv, alg, key_idx, set_tx);
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&cmd, 0, sizeof(cmd));
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmd.alg = alg;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(cmd.addr, addr, ETH_ALEN);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(cmd.addr, 0xff, ETH_ALEN);
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmd.key_idx = key_idx;
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmd.set_tx = set_tx;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) {
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(cmd.seq, seq, seq_len);
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmd.seq_len = seq_len;
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key && key_len > 0 && key_len < sizeof(cmd.key)) {
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(cmd.key, key, key_len);
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmd.key_len = key_len;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_KEY, &cmd, sizeof(cmd),
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    NULL, NULL);
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_associate(
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *priv, struct wpa_driver_associate_params *params)
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct privsep_cmd_associate *data;
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t buflen;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
2336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		   __func__, priv, params->freq.freq, params->pairwise_suite,
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   params->group_suite, params->key_mgmt_suite,
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   params->auth_alg, params->mode);
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buflen = sizeof(*data) + params->wpa_ie_len;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data = os_zalloc(buflen);
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->bssid)
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(data->bssid, params->bssid, ETH_ALEN);
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(data->ssid, params->ssid, params->ssid_len);
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->ssid_len = params->ssid_len;
2466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	data->hwmode = params->freq.mode;
2476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	data->freq = params->freq.freq;
2486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	data->channel = params->freq.channel;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->pairwise_suite = params->pairwise_suite;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->group_suite = params->group_suite;
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->key_mgmt_suite = params->key_mgmt_suite;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->auth_alg = params->auth_alg;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->mode = params->mode;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->wpa_ie_len = params->wpa_ie_len;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->wpa_ie)
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(data + 1, params->wpa_ie, params->wpa_ie_len);
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add support for other assoc parameters */
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_ASSOCIATE, data, buflen,
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   NULL, NULL);
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data);
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_get_bssid(void *priv, u8 *bssid)
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len = ETH_ALEN;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_BSSID, NULL, 0, bssid, &len);
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || len != ETH_ALEN)
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid)
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res, ssid_len;
2849d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt	u8 reply[sizeof(int) + SSID_MAX_LEN];
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len = sizeof(reply);
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SSID, NULL, 0, reply, &len);
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || len < sizeof(int))
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ssid_len, reply, sizeof(int));
2919d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt	if (ssid_len < 0 || ssid_len > SSID_MAX_LEN ||
2929d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt	    sizeof(int) + ssid_len > len) {
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "privsep: Invalid get SSID reply");
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ssid, &reply[sizeof(int)], ssid_len);
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ssid_len;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr,
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  int reason_code)
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	//struct wpa_driver_privsep_data *drv = priv;
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   __func__, MAC2STR(addr), reason_code);
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s - TODO", __func__);
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_assoc(void *ctx,
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   enum wpa_event_type event,
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   u8 *buf, size_t len)
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int inc_data = 0;
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos, *end;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ie_len;
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + len;
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < (int) sizeof(int))
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ie_len, pos, sizeof(int));
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += sizeof(int);
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie_len < 0 || ie_len > end - pos)
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie_len) {
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data.assoc_info.req_ies = pos;
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data.assoc_info.req_ies_len = ie_len;
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ie_len;
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		inc_data = 1;
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(ctx, event, inc_data ? &data : NULL);
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_interface_status(void *ctx, u8 *buf,
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      size_t len)
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ievent;
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(int) ||
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    len - sizeof(int) > sizeof(data.interface_status.ifname))
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ievent, buf, sizeof(int));
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.interface_status.ievent = ievent;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(data.interface_status.ifname, buf + sizeof(int),
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  len - sizeof(int));
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &data);
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_michael_mic_failure(
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *ctx, u8 *buf, size_t len)
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len != sizeof(int))
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&data.michael_mic_failure.unicast, buf, sizeof(int));
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_pmkid_candidate(void *ctx, u8 *buf,
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     size_t len)
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len != sizeof(struct pmkid_candidate))
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&data.pmkid_candidate, buf, len);
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(ctx, EVENT_PMKID_CANDIDATE, &data);
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_stkstart(void *ctx, u8 *buf, size_t len)
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len != ETH_ALEN)
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(data.stkstart.peer, buf, ETH_ALEN);
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_ft_response(void *ctx, u8 *buf,
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 size_t len)
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(int) + ETH_ALEN)
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&data.ft_ies.ft_action, buf, sizeof(int));
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(data.ft_ies.target_ap, buf + sizeof(int), ETH_ALEN);
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.ft_ies.ies = buf + sizeof(int) + ETH_ALEN;
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.ft_ies.ies_len = len - sizeof(int) - ETH_ALEN;
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(ctx, EVENT_FT_RESPONSE, &data);
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_event_rx_eapol(void *ctx, u8 *buf, size_t len)
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < ETH_ALEN)
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv_event_eapol_rx(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN);
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_receive(int sock, void *eloop_ctx,
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       void *sock_ctx)
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = eloop_ctx;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *buf, *event_buf;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t event_len;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res, event;
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum privsep_event e;
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un from;
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	socklen_t fromlen = sizeof(from);
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const size_t buflen = 2000;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(buflen);
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = recvfrom(sock, buf, buflen, 0,
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       (struct sockaddr *) &from, &fromlen);
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
4476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR, "recvfrom(priv_socket): %s",
4486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   strerror(errno));
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "privsep_driver: received %u bytes", res);
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < (int) sizeof(int)) {
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Too short event message (len=%d)", res);
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&event, buf, sizeof(int));
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	event_buf = &buf[sizeof(int)];
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	event_len = res - sizeof(int);
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "privsep: Event %d received (len=%lu)",
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   event, (unsigned long) event_len);
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e = event;
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (e) {
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_SCAN_RESULTS:
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL);
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_ASSOC:
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOC,
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       event_buf, event_len);
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_DISASSOC:
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_ASSOCINFO:
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOCINFO,
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       event_buf, event_len);
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_MICHAEL_MIC_FAILURE:
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_michael_mic_failure(
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->ctx, event_buf, event_len);
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_INTERFACE_STATUS:
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_interface_status(drv->ctx, event_buf,
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							  event_len);
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_PMKID_CANDIDATE:
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_pmkid_candidate(drv->ctx, event_buf,
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 event_len);
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_STKSTART:
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_stkstart(drv->ctx, event_buf,
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  event_len);
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_FT_RESPONSE:
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_ft_response(drv->ctx, event_buf,
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     event_len);
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case PRIVSEP_EVENT_RX_EAPOL:
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf,
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  event_len);
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * wpa_driver_privsep_init(void *ctx, const char *ifname)
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv = os_zalloc(sizeof(*drv));
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv == NULL)
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->ctx = ctx;
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->priv_socket = -1;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->cmd_socket = -1;
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return drv;
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_privsep_deinit(void *priv)
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->priv_socket >= 0) {
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_priv_reg_cmd(drv, PRIVSEP_CMD_UNREGISTER);
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_read_sock(drv->priv_socket);
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(drv->priv_socket);
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->own_socket_path) {
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(drv->own_socket_path);
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_socket_path);
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->cmd_socket >= 0) {
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_read_sock(drv->cmd_socket);
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(drv->cmd_socket);
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->own_cmd_path) {
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(drv->own_cmd_path);
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_cmd_path);
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(drv);
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_set_param(void *priv, const char *param)
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *pos;
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *own_dir, *priv_dir;
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static unsigned int counter = 0;
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un addr;
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (param == NULL)
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = NULL;
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strstr(param, "own_dir=");
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos) {
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char *end;
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		own_dir = os_strdup(pos + 8);
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (own_dir == NULL)
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = os_strchr(own_dir, ' ');
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end)
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*end = '\0';
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		own_dir = os_strdup("/tmp");
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (own_dir == NULL)
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (param == NULL)
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = NULL;
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strstr(param, "priv_dir=");
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos) {
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char *end;
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv_dir = os_strdup(pos + 9);
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (priv_dir == NULL) {
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(own_dir);
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = os_strchr(priv_dir, ' ');
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end)
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*end = '\0';
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv_dir = os_strdup("/var/run/wpa_priv");
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (priv_dir == NULL) {
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(own_dir);
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_strlen(own_dir) + 50;
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->own_socket_path = os_malloc(len);
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->own_socket_path == NULL) {
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(priv_dir);
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(own_dir);
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(drv->own_socket_path, len, "%s/wpa_privsep-%d-%d",
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    own_dir, getpid(), counter++);
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_strlen(own_dir) + 50;
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->own_cmd_path = os_malloc(len);
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->own_cmd_path == NULL) {
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_socket_path);
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->own_socket_path = NULL;
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(priv_dir);
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(own_dir);
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(drv->own_cmd_path, len, "%s/wpa_privsep-%d-%d",
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    own_dir, getpid(), counter++);
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(own_dir);
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->priv_addr.sun_family = AF_UNIX;
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(drv->priv_addr.sun_path, sizeof(drv->priv_addr.sun_path),
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    "%s/%s", priv_dir, drv->ifname);
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(priv_dir);
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->priv_socket < 0) {
6386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_socket_path);
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->own_socket_path = NULL;
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path));
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) <
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
6496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR,
6506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "privsep-set-params priv-sock: bind(PF_UNIX): %s",
6516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   strerror(errno));
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(drv->priv_socket);
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->priv_socket = -1;
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(drv->own_socket_path);
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_socket_path);
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->own_socket_path = NULL;
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_read_sock(drv->priv_socket, wpa_driver_privsep_receive,
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 drv, NULL);
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->cmd_socket < 0) {
6656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_cmd_path);
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->own_cmd_path = NULL;
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path));
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0)
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
6766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR,
6776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "privsep-set-params cmd-sock: bind(PF_UNIX): %s",
6786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   strerror(errno));
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(drv->cmd_socket);
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->cmd_socket = -1;
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(drv->own_cmd_path);
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv->own_cmd_path);
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->own_cmd_path = NULL;
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_priv_reg_cmd(drv, PRIVSEP_CMD_REGISTER) < 0) {
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to register with wpa_priv");
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_get_capa(void *priv,
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct wpa_driver_capa *capa)
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len = sizeof(*capa);
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_CAPA, NULL, 0, capa, &len);
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || len != sizeof(*capa))
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * wpa_driver_privsep_get_mac_addr(void *priv)
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s", __func__);
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return drv->own_addr;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_privsep_set_country(void *priv, const char *alpha2)
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_privsep_data *drv = priv;
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s country='%s'", __func__, alpha2);
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_COUNTRY, alpha2,
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    os_strlen(alpha2), NULL, NULL);
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_driver_ops wpa_driver_privsep_ops = {
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	"privsep",
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	"wpa_supplicant privilege separated driver",
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.get_bssid = wpa_driver_privsep_get_bssid,
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.get_ssid = wpa_driver_privsep_get_ssid,
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.set_key = wpa_driver_privsep_set_key,
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.init = wpa_driver_privsep_init,
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.deinit = wpa_driver_privsep_deinit,
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.set_param = wpa_driver_privsep_set_param,
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.scan2 = wpa_driver_privsep_scan,
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.deauthenticate = wpa_driver_privsep_deauthenticate,
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.associate = wpa_driver_privsep_associate,
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.get_capa = wpa_driver_privsep_get_capa,
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.get_mac_addr = wpa_driver_privsep_get_mac_addr,
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.get_scan_results2 = wpa_driver_privsep_get_scan_results2,
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.set_country = wpa_driver_privsep_set_country,
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7461d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtconst struct wpa_driver_ops *const wpa_drivers[] =
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	&wpa_driver_privsep_ops,
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NULL
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
751