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