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