xref: /freebsd/contrib/wpa/src/drivers/driver_privsep.c (revision f05cddf940dbfc5b657f5e9beb9de2c31e509e5b)
1*f05cddf9SRui Paulo /*
2*f05cddf9SRui Paulo  * WPA Supplicant - privilege separated driver interface
3*f05cddf9SRui Paulo  * Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
4*f05cddf9SRui Paulo  *
5*f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6*f05cddf9SRui Paulo  * See README for more details.
7*f05cddf9SRui Paulo  */
8*f05cddf9SRui Paulo 
9*f05cddf9SRui Paulo #include "includes.h"
10*f05cddf9SRui Paulo #include <sys/un.h>
11*f05cddf9SRui Paulo 
12*f05cddf9SRui Paulo #include "common.h"
13*f05cddf9SRui Paulo #include "driver.h"
14*f05cddf9SRui Paulo #include "eloop.h"
15*f05cddf9SRui Paulo #include "common/privsep_commands.h"
16*f05cddf9SRui Paulo 
17*f05cddf9SRui Paulo 
18*f05cddf9SRui Paulo struct wpa_driver_privsep_data {
19*f05cddf9SRui Paulo 	void *ctx;
20*f05cddf9SRui Paulo 	u8 own_addr[ETH_ALEN];
21*f05cddf9SRui Paulo 	int priv_socket;
22*f05cddf9SRui Paulo 	char *own_socket_path;
23*f05cddf9SRui Paulo 	int cmd_socket;
24*f05cddf9SRui Paulo 	char *own_cmd_path;
25*f05cddf9SRui Paulo 	struct sockaddr_un priv_addr;
26*f05cddf9SRui Paulo 	char ifname[16];
27*f05cddf9SRui Paulo };
28*f05cddf9SRui Paulo 
29*f05cddf9SRui Paulo 
30*f05cddf9SRui Paulo static int wpa_priv_reg_cmd(struct wpa_driver_privsep_data *drv, int cmd)
31*f05cddf9SRui Paulo {
32*f05cddf9SRui Paulo 	int res;
33*f05cddf9SRui Paulo 
34*f05cddf9SRui Paulo 	res = sendto(drv->priv_socket, &cmd, sizeof(cmd), 0,
35*f05cddf9SRui Paulo 		     (struct sockaddr *) &drv->priv_addr,
36*f05cddf9SRui Paulo 		     sizeof(drv->priv_addr));
37*f05cddf9SRui Paulo 	if (res < 0)
38*f05cddf9SRui Paulo 		perror("sendto");
39*f05cddf9SRui Paulo 	return res < 0 ? -1 : 0;
40*f05cddf9SRui Paulo }
41*f05cddf9SRui Paulo 
42*f05cddf9SRui Paulo 
43*f05cddf9SRui Paulo static int wpa_priv_cmd(struct wpa_driver_privsep_data *drv, int cmd,
44*f05cddf9SRui Paulo 			const void *data, size_t data_len,
45*f05cddf9SRui Paulo 			void *reply, size_t *reply_len)
46*f05cddf9SRui Paulo {
47*f05cddf9SRui Paulo 	struct msghdr msg;
48*f05cddf9SRui Paulo 	struct iovec io[2];
49*f05cddf9SRui Paulo 
50*f05cddf9SRui Paulo 	io[0].iov_base = &cmd;
51*f05cddf9SRui Paulo 	io[0].iov_len = sizeof(cmd);
52*f05cddf9SRui Paulo 	io[1].iov_base = (u8 *) data;
53*f05cddf9SRui Paulo 	io[1].iov_len = data_len;
54*f05cddf9SRui Paulo 
55*f05cddf9SRui Paulo 	os_memset(&msg, 0, sizeof(msg));
56*f05cddf9SRui Paulo 	msg.msg_iov = io;
57*f05cddf9SRui Paulo 	msg.msg_iovlen = data ? 2 : 1;
58*f05cddf9SRui Paulo 	msg.msg_name = &drv->priv_addr;
59*f05cddf9SRui Paulo 	msg.msg_namelen = sizeof(drv->priv_addr);
60*f05cddf9SRui Paulo 
61*f05cddf9SRui Paulo 	if (sendmsg(drv->cmd_socket, &msg, 0) < 0) {
62*f05cddf9SRui Paulo 		perror("sendmsg(cmd_socket)");
63*f05cddf9SRui Paulo 		return -1;
64*f05cddf9SRui Paulo 	}
65*f05cddf9SRui Paulo 
66*f05cddf9SRui Paulo 	if (reply) {
67*f05cddf9SRui Paulo 		fd_set rfds;
68*f05cddf9SRui Paulo 		struct timeval tv;
69*f05cddf9SRui Paulo 		int res;
70*f05cddf9SRui Paulo 
71*f05cddf9SRui Paulo 		FD_ZERO(&rfds);
72*f05cddf9SRui Paulo 		FD_SET(drv->cmd_socket, &rfds);
73*f05cddf9SRui Paulo 		tv.tv_sec = 5;
74*f05cddf9SRui Paulo 		tv.tv_usec = 0;
75*f05cddf9SRui Paulo 		res = select(drv->cmd_socket + 1, &rfds, NULL, NULL, &tv);
76*f05cddf9SRui Paulo 		if (res < 0 && errno != EINTR) {
77*f05cddf9SRui Paulo 			perror("select");
78*f05cddf9SRui Paulo 			return -1;
79*f05cddf9SRui Paulo 		}
80*f05cddf9SRui Paulo 
81*f05cddf9SRui Paulo 		if (FD_ISSET(drv->cmd_socket, &rfds)) {
82*f05cddf9SRui Paulo 			res = recv(drv->cmd_socket, reply, *reply_len, 0);
83*f05cddf9SRui Paulo 			if (res < 0) {
84*f05cddf9SRui Paulo 				perror("recv");
85*f05cddf9SRui Paulo 				return -1;
86*f05cddf9SRui Paulo 			}
87*f05cddf9SRui Paulo 			*reply_len = res;
88*f05cddf9SRui Paulo 		} else {
89*f05cddf9SRui Paulo 			wpa_printf(MSG_DEBUG, "PRIVSEP: Timeout while waiting "
90*f05cddf9SRui Paulo 				   "for reply (cmd=%d)", cmd);
91*f05cddf9SRui Paulo 			return -1;
92*f05cddf9SRui Paulo 		}
93*f05cddf9SRui Paulo 	}
94*f05cddf9SRui Paulo 
95*f05cddf9SRui Paulo 	return 0;
96*f05cddf9SRui Paulo }
97*f05cddf9SRui Paulo 
98*f05cddf9SRui Paulo 
99*f05cddf9SRui Paulo static int wpa_driver_privsep_scan(void *priv,
100*f05cddf9SRui Paulo 				   struct wpa_driver_scan_params *params)
101*f05cddf9SRui Paulo {
102*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv = priv;
103*f05cddf9SRui Paulo 	const u8 *ssid = params->ssids[0].ssid;
104*f05cddf9SRui Paulo 	size_t ssid_len = params->ssids[0].ssid_len;
105*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv);
106*f05cddf9SRui Paulo 	return wpa_priv_cmd(drv, PRIVSEP_CMD_SCAN, ssid, ssid_len,
107*f05cddf9SRui Paulo 			    NULL, NULL);
108*f05cddf9SRui Paulo }
109*f05cddf9SRui Paulo 
110*f05cddf9SRui Paulo 
111*f05cddf9SRui Paulo static struct wpa_scan_results *
112*f05cddf9SRui Paulo wpa_driver_privsep_get_scan_results2(void *priv)
113*f05cddf9SRui Paulo {
114*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv = priv;
115*f05cddf9SRui Paulo 	int res, num;
116*f05cddf9SRui Paulo 	u8 *buf, *pos, *end;
117*f05cddf9SRui Paulo 	size_t reply_len = 60000;
118*f05cddf9SRui Paulo 	struct wpa_scan_results *results;
119*f05cddf9SRui Paulo 	struct wpa_scan_res *r;
120*f05cddf9SRui Paulo 
121*f05cddf9SRui Paulo 	buf = os_malloc(reply_len);
122*f05cddf9SRui Paulo 	if (buf == NULL)
123*f05cddf9SRui Paulo 		return NULL;
124*f05cddf9SRui Paulo 	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SCAN_RESULTS,
125*f05cddf9SRui Paulo 			   NULL, 0, buf, &reply_len);
126*f05cddf9SRui Paulo 	if (res < 0) {
127*f05cddf9SRui Paulo 		os_free(buf);
128*f05cddf9SRui Paulo 		return NULL;
129*f05cddf9SRui Paulo 	}
130*f05cddf9SRui Paulo 
131*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "privsep: Received %lu bytes of scan results",
132*f05cddf9SRui Paulo 		   (unsigned long) reply_len);
133*f05cddf9SRui Paulo 	if (reply_len < sizeof(int)) {
134*f05cddf9SRui Paulo 		wpa_printf(MSG_DEBUG, "privsep: Invalid scan result len %lu",
135*f05cddf9SRui Paulo 			   (unsigned long) reply_len);
136*f05cddf9SRui Paulo 		os_free(buf);
137*f05cddf9SRui Paulo 		return NULL;
138*f05cddf9SRui Paulo 	}
139*f05cddf9SRui Paulo 
140*f05cddf9SRui Paulo 	pos = buf;
141*f05cddf9SRui Paulo 	end = buf + reply_len;
142*f05cddf9SRui Paulo 	os_memcpy(&num, pos, sizeof(int));
143*f05cddf9SRui Paulo 	if (num < 0 || num > 1000) {
144*f05cddf9SRui Paulo 		os_free(buf);
145*f05cddf9SRui Paulo 		return NULL;
146*f05cddf9SRui Paulo 	}
147*f05cddf9SRui Paulo 	pos += sizeof(int);
148*f05cddf9SRui Paulo 
149*f05cddf9SRui Paulo 	results = os_zalloc(sizeof(*results));
150*f05cddf9SRui Paulo 	if (results == NULL) {
151*f05cddf9SRui Paulo 		os_free(buf);
152*f05cddf9SRui Paulo 		return NULL;
153*f05cddf9SRui Paulo 	}
154*f05cddf9SRui Paulo 
155*f05cddf9SRui Paulo 	results->res = os_calloc(num, sizeof(struct wpa_scan_res *));
156*f05cddf9SRui Paulo 	if (results->res == NULL) {
157*f05cddf9SRui Paulo 		os_free(results);
158*f05cddf9SRui Paulo 		os_free(buf);
159*f05cddf9SRui Paulo 		return NULL;
160*f05cddf9SRui Paulo 	}
161*f05cddf9SRui Paulo 
162*f05cddf9SRui Paulo 	while (results->num < (size_t) num && pos + sizeof(int) < end) {
163*f05cddf9SRui Paulo 		int len;
164*f05cddf9SRui Paulo 		os_memcpy(&len, pos, sizeof(int));
165*f05cddf9SRui Paulo 		pos += sizeof(int);
166*f05cddf9SRui Paulo 		if (len < 0 || len > 10000 || pos + len > end)
167*f05cddf9SRui Paulo 			break;
168*f05cddf9SRui Paulo 
169*f05cddf9SRui Paulo 		r = os_malloc(len);
170*f05cddf9SRui Paulo 		if (r == NULL)
171*f05cddf9SRui Paulo 			break;
172*f05cddf9SRui Paulo 		os_memcpy(r, pos, len);
173*f05cddf9SRui Paulo 		pos += len;
174*f05cddf9SRui Paulo 		if (sizeof(*r) + r->ie_len > (size_t) len) {
175*f05cddf9SRui Paulo 			os_free(r);
176*f05cddf9SRui Paulo 			break;
177*f05cddf9SRui Paulo 		}
178*f05cddf9SRui Paulo 
179*f05cddf9SRui Paulo 		results->res[results->num++] = r;
180*f05cddf9SRui Paulo 	}
181*f05cddf9SRui Paulo 
182*f05cddf9SRui Paulo 	os_free(buf);
183*f05cddf9SRui Paulo 	return results;
184*f05cddf9SRui Paulo }
185*f05cddf9SRui Paulo 
186*f05cddf9SRui Paulo 
187*f05cddf9SRui Paulo static int wpa_driver_privsep_set_key(const char *ifname, void *priv,
188*f05cddf9SRui Paulo 				      enum wpa_alg alg, const u8 *addr,
189*f05cddf9SRui Paulo 				      int key_idx, int set_tx,
190*f05cddf9SRui Paulo 				      const u8 *seq, size_t seq_len,
191*f05cddf9SRui Paulo 				      const u8 *key, size_t key_len)
192*f05cddf9SRui Paulo {
193*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv = priv;
194*f05cddf9SRui Paulo 	struct privsep_cmd_set_key cmd;
195*f05cddf9SRui Paulo 
196*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d",
197*f05cddf9SRui Paulo 		   __func__, priv, alg, key_idx, set_tx);
198*f05cddf9SRui Paulo 
199*f05cddf9SRui Paulo 	os_memset(&cmd, 0, sizeof(cmd));
200*f05cddf9SRui Paulo 	cmd.alg = alg;
201*f05cddf9SRui Paulo 	if (addr)
202*f05cddf9SRui Paulo 		os_memcpy(cmd.addr, addr, ETH_ALEN);
203*f05cddf9SRui Paulo 	else
204*f05cddf9SRui Paulo 		os_memset(cmd.addr, 0xff, ETH_ALEN);
205*f05cddf9SRui Paulo 	cmd.key_idx = key_idx;
206*f05cddf9SRui Paulo 	cmd.set_tx = set_tx;
207*f05cddf9SRui Paulo 	if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) {
208*f05cddf9SRui Paulo 		os_memcpy(cmd.seq, seq, seq_len);
209*f05cddf9SRui Paulo 		cmd.seq_len = seq_len;
210*f05cddf9SRui Paulo 	}
211*f05cddf9SRui Paulo 	if (key && key_len > 0 && key_len < sizeof(cmd.key)) {
212*f05cddf9SRui Paulo 		os_memcpy(cmd.key, key, key_len);
213*f05cddf9SRui Paulo 		cmd.key_len = key_len;
214*f05cddf9SRui Paulo 	}
215*f05cddf9SRui Paulo 
216*f05cddf9SRui Paulo 	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_KEY, &cmd, sizeof(cmd),
217*f05cddf9SRui Paulo 			    NULL, NULL);
218*f05cddf9SRui Paulo }
219*f05cddf9SRui Paulo 
220*f05cddf9SRui Paulo 
221*f05cddf9SRui Paulo static int wpa_driver_privsep_associate(
222*f05cddf9SRui Paulo 	void *priv, struct wpa_driver_associate_params *params)
223*f05cddf9SRui Paulo {
224*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv = priv;
225*f05cddf9SRui Paulo 	struct privsep_cmd_associate *data;
226*f05cddf9SRui Paulo 	int res;
227*f05cddf9SRui Paulo 	size_t buflen;
228*f05cddf9SRui Paulo 
229*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
230*f05cddf9SRui Paulo 		   "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
231*f05cddf9SRui Paulo 		   __func__, priv, params->freq, params->pairwise_suite,
232*f05cddf9SRui Paulo 		   params->group_suite, params->key_mgmt_suite,
233*f05cddf9SRui Paulo 		   params->auth_alg, params->mode);
234*f05cddf9SRui Paulo 
235*f05cddf9SRui Paulo 	buflen = sizeof(*data) + params->wpa_ie_len;
236*f05cddf9SRui Paulo 	data = os_zalloc(buflen);
237*f05cddf9SRui Paulo 	if (data == NULL)
238*f05cddf9SRui Paulo 		return -1;
239*f05cddf9SRui Paulo 
240*f05cddf9SRui Paulo 	if (params->bssid)
241*f05cddf9SRui Paulo 		os_memcpy(data->bssid, params->bssid, ETH_ALEN);
242*f05cddf9SRui Paulo 	os_memcpy(data->ssid, params->ssid, params->ssid_len);
243*f05cddf9SRui Paulo 	data->ssid_len = params->ssid_len;
244*f05cddf9SRui Paulo 	data->freq = params->freq;
245*f05cddf9SRui Paulo 	data->pairwise_suite = params->pairwise_suite;
246*f05cddf9SRui Paulo 	data->group_suite = params->group_suite;
247*f05cddf9SRui Paulo 	data->key_mgmt_suite = params->key_mgmt_suite;
248*f05cddf9SRui Paulo 	data->auth_alg = params->auth_alg;
249*f05cddf9SRui Paulo 	data->mode = params->mode;
250*f05cddf9SRui Paulo 	data->wpa_ie_len = params->wpa_ie_len;
251*f05cddf9SRui Paulo 	if (params->wpa_ie)
252*f05cddf9SRui Paulo 		os_memcpy(data + 1, params->wpa_ie, params->wpa_ie_len);
253*f05cddf9SRui Paulo 	/* TODO: add support for other assoc parameters */
254*f05cddf9SRui Paulo 
255*f05cddf9SRui Paulo 	res = wpa_priv_cmd(drv, PRIVSEP_CMD_ASSOCIATE, data, buflen,
256*f05cddf9SRui Paulo 			   NULL, NULL);
257*f05cddf9SRui Paulo 	os_free(data);
258*f05cddf9SRui Paulo 
259*f05cddf9SRui Paulo 	return res;
260*f05cddf9SRui Paulo }
261*f05cddf9SRui Paulo 
262*f05cddf9SRui Paulo 
263*f05cddf9SRui Paulo static int wpa_driver_privsep_get_bssid(void *priv, u8 *bssid)
264*f05cddf9SRui Paulo {
265*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv = priv;
266*f05cddf9SRui Paulo 	int res;
267*f05cddf9SRui Paulo 	size_t len = ETH_ALEN;
268*f05cddf9SRui Paulo 
269*f05cddf9SRui Paulo 	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_BSSID, NULL, 0, bssid, &len);
270*f05cddf9SRui Paulo 	if (res < 0 || len != ETH_ALEN)
271*f05cddf9SRui Paulo 		return -1;
272*f05cddf9SRui Paulo 	return 0;
273*f05cddf9SRui Paulo }
274*f05cddf9SRui Paulo 
275*f05cddf9SRui Paulo 
276*f05cddf9SRui Paulo static int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid)
277*f05cddf9SRui Paulo {
278*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv = priv;
279*f05cddf9SRui Paulo 	int res, ssid_len;
280*f05cddf9SRui Paulo 	u8 reply[sizeof(int) + 32];
281*f05cddf9SRui Paulo 	size_t len = sizeof(reply);
282*f05cddf9SRui Paulo 
283*f05cddf9SRui Paulo 	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SSID, NULL, 0, reply, &len);
284*f05cddf9SRui Paulo 	if (res < 0 || len < sizeof(int))
285*f05cddf9SRui Paulo 		return -1;
286*f05cddf9SRui Paulo 	os_memcpy(&ssid_len, reply, sizeof(int));
287*f05cddf9SRui Paulo 	if (ssid_len < 0 || ssid_len > 32 || sizeof(int) + ssid_len > len) {
288*f05cddf9SRui Paulo 		wpa_printf(MSG_DEBUG, "privsep: Invalid get SSID reply");
289*f05cddf9SRui Paulo 		return -1;
290*f05cddf9SRui Paulo 	}
291*f05cddf9SRui Paulo 	os_memcpy(ssid, &reply[sizeof(int)], ssid_len);
292*f05cddf9SRui Paulo 	return ssid_len;
293*f05cddf9SRui Paulo }
294*f05cddf9SRui Paulo 
295*f05cddf9SRui Paulo 
296*f05cddf9SRui Paulo static int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr,
297*f05cddf9SRui Paulo 					  int reason_code)
298*f05cddf9SRui Paulo {
299*f05cddf9SRui Paulo 	//struct wpa_driver_privsep_data *drv = priv;
300*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
301*f05cddf9SRui Paulo 		   __func__, MAC2STR(addr), reason_code);
302*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "%s - TODO", __func__);
303*f05cddf9SRui Paulo 	return 0;
304*f05cddf9SRui Paulo }
305*f05cddf9SRui Paulo 
306*f05cddf9SRui Paulo 
307*f05cddf9SRui Paulo static void wpa_driver_privsep_event_assoc(void *ctx,
308*f05cddf9SRui Paulo 					   enum wpa_event_type event,
309*f05cddf9SRui Paulo 					   u8 *buf, size_t len)
310*f05cddf9SRui Paulo {
311*f05cddf9SRui Paulo 	union wpa_event_data data;
312*f05cddf9SRui Paulo 	int inc_data = 0;
313*f05cddf9SRui Paulo 	u8 *pos, *end;
314*f05cddf9SRui Paulo 	int ie_len;
315*f05cddf9SRui Paulo 
316*f05cddf9SRui Paulo 	os_memset(&data, 0, sizeof(data));
317*f05cddf9SRui Paulo 
318*f05cddf9SRui Paulo 	pos = buf;
319*f05cddf9SRui Paulo 	end = buf + len;
320*f05cddf9SRui Paulo 
321*f05cddf9SRui Paulo 	if (end - pos < (int) sizeof(int))
322*f05cddf9SRui Paulo 		return;
323*f05cddf9SRui Paulo 	os_memcpy(&ie_len, pos, sizeof(int));
324*f05cddf9SRui Paulo 	pos += sizeof(int);
325*f05cddf9SRui Paulo 	if (ie_len < 0 || ie_len > end - pos)
326*f05cddf9SRui Paulo 		return;
327*f05cddf9SRui Paulo 	if (ie_len) {
328*f05cddf9SRui Paulo 		data.assoc_info.req_ies = pos;
329*f05cddf9SRui Paulo 		data.assoc_info.req_ies_len = ie_len;
330*f05cddf9SRui Paulo 		pos += ie_len;
331*f05cddf9SRui Paulo 		inc_data = 1;
332*f05cddf9SRui Paulo 	}
333*f05cddf9SRui Paulo 
334*f05cddf9SRui Paulo 	wpa_supplicant_event(ctx, event, inc_data ? &data : NULL);
335*f05cddf9SRui Paulo }
336*f05cddf9SRui Paulo 
337*f05cddf9SRui Paulo 
338*f05cddf9SRui Paulo static void wpa_driver_privsep_event_interface_status(void *ctx, u8 *buf,
339*f05cddf9SRui Paulo 						      size_t len)
340*f05cddf9SRui Paulo {
341*f05cddf9SRui Paulo 	union wpa_event_data data;
342*f05cddf9SRui Paulo 	int ievent;
343*f05cddf9SRui Paulo 
344*f05cddf9SRui Paulo 	if (len < sizeof(int) ||
345*f05cddf9SRui Paulo 	    len - sizeof(int) > sizeof(data.interface_status.ifname))
346*f05cddf9SRui Paulo 		return;
347*f05cddf9SRui Paulo 
348*f05cddf9SRui Paulo 	os_memcpy(&ievent, buf, sizeof(int));
349*f05cddf9SRui Paulo 
350*f05cddf9SRui Paulo 	os_memset(&data, 0, sizeof(data));
351*f05cddf9SRui Paulo 	data.interface_status.ievent = ievent;
352*f05cddf9SRui Paulo 	os_memcpy(data.interface_status.ifname, buf + sizeof(int),
353*f05cddf9SRui Paulo 		  len - sizeof(int));
354*f05cddf9SRui Paulo 	wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &data);
355*f05cddf9SRui Paulo }
356*f05cddf9SRui Paulo 
357*f05cddf9SRui Paulo 
358*f05cddf9SRui Paulo static void wpa_driver_privsep_event_michael_mic_failure(
359*f05cddf9SRui Paulo 	void *ctx, u8 *buf, size_t len)
360*f05cddf9SRui Paulo {
361*f05cddf9SRui Paulo 	union wpa_event_data data;
362*f05cddf9SRui Paulo 
363*f05cddf9SRui Paulo 	if (len != sizeof(int))
364*f05cddf9SRui Paulo 		return;
365*f05cddf9SRui Paulo 
366*f05cddf9SRui Paulo 	os_memset(&data, 0, sizeof(data));
367*f05cddf9SRui Paulo 	os_memcpy(&data.michael_mic_failure.unicast, buf, sizeof(int));
368*f05cddf9SRui Paulo 	wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
369*f05cddf9SRui Paulo }
370*f05cddf9SRui Paulo 
371*f05cddf9SRui Paulo 
372*f05cddf9SRui Paulo static void wpa_driver_privsep_event_pmkid_candidate(void *ctx, u8 *buf,
373*f05cddf9SRui Paulo 						     size_t len)
374*f05cddf9SRui Paulo {
375*f05cddf9SRui Paulo 	union wpa_event_data data;
376*f05cddf9SRui Paulo 
377*f05cddf9SRui Paulo 	if (len != sizeof(struct pmkid_candidate))
378*f05cddf9SRui Paulo 		return;
379*f05cddf9SRui Paulo 
380*f05cddf9SRui Paulo 	os_memset(&data, 0, sizeof(data));
381*f05cddf9SRui Paulo 	os_memcpy(&data.pmkid_candidate, buf, len);
382*f05cddf9SRui Paulo 	wpa_supplicant_event(ctx, EVENT_PMKID_CANDIDATE, &data);
383*f05cddf9SRui Paulo }
384*f05cddf9SRui Paulo 
385*f05cddf9SRui Paulo 
386*f05cddf9SRui Paulo static void wpa_driver_privsep_event_stkstart(void *ctx, u8 *buf, size_t len)
387*f05cddf9SRui Paulo {
388*f05cddf9SRui Paulo 	union wpa_event_data data;
389*f05cddf9SRui Paulo 
390*f05cddf9SRui Paulo 	if (len != ETH_ALEN)
391*f05cddf9SRui Paulo 		return;
392*f05cddf9SRui Paulo 
393*f05cddf9SRui Paulo 	os_memset(&data, 0, sizeof(data));
394*f05cddf9SRui Paulo 	os_memcpy(data.stkstart.peer, buf, ETH_ALEN);
395*f05cddf9SRui Paulo 	wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
396*f05cddf9SRui Paulo }
397*f05cddf9SRui Paulo 
398*f05cddf9SRui Paulo 
399*f05cddf9SRui Paulo static void wpa_driver_privsep_event_ft_response(void *ctx, u8 *buf,
400*f05cddf9SRui Paulo 						 size_t len)
401*f05cddf9SRui Paulo {
402*f05cddf9SRui Paulo 	union wpa_event_data data;
403*f05cddf9SRui Paulo 
404*f05cddf9SRui Paulo 	if (len < sizeof(int) + ETH_ALEN)
405*f05cddf9SRui Paulo 		return;
406*f05cddf9SRui Paulo 
407*f05cddf9SRui Paulo 	os_memset(&data, 0, sizeof(data));
408*f05cddf9SRui Paulo 	os_memcpy(&data.ft_ies.ft_action, buf, sizeof(int));
409*f05cddf9SRui Paulo 	os_memcpy(data.ft_ies.target_ap, buf + sizeof(int), ETH_ALEN);
410*f05cddf9SRui Paulo 	data.ft_ies.ies = buf + sizeof(int) + ETH_ALEN;
411*f05cddf9SRui Paulo 	data.ft_ies.ies_len = len - sizeof(int) - ETH_ALEN;
412*f05cddf9SRui Paulo 	wpa_supplicant_event(ctx, EVENT_FT_RESPONSE, &data);
413*f05cddf9SRui Paulo }
414*f05cddf9SRui Paulo 
415*f05cddf9SRui Paulo 
416*f05cddf9SRui Paulo static void wpa_driver_privsep_event_rx_eapol(void *ctx, u8 *buf, size_t len)
417*f05cddf9SRui Paulo {
418*f05cddf9SRui Paulo 	if (len < ETH_ALEN)
419*f05cddf9SRui Paulo 		return;
420*f05cddf9SRui Paulo 	drv_event_eapol_rx(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN);
421*f05cddf9SRui Paulo }
422*f05cddf9SRui Paulo 
423*f05cddf9SRui Paulo 
424*f05cddf9SRui Paulo static void wpa_driver_privsep_receive(int sock, void *eloop_ctx,
425*f05cddf9SRui Paulo 				       void *sock_ctx)
426*f05cddf9SRui Paulo {
427*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv = eloop_ctx;
428*f05cddf9SRui Paulo 	u8 *buf, *event_buf;
429*f05cddf9SRui Paulo 	size_t event_len;
430*f05cddf9SRui Paulo 	int res, event;
431*f05cddf9SRui Paulo 	enum privsep_event e;
432*f05cddf9SRui Paulo 	struct sockaddr_un from;
433*f05cddf9SRui Paulo 	socklen_t fromlen = sizeof(from);
434*f05cddf9SRui Paulo 	const size_t buflen = 2000;
435*f05cddf9SRui Paulo 
436*f05cddf9SRui Paulo 	buf = os_malloc(buflen);
437*f05cddf9SRui Paulo 	if (buf == NULL)
438*f05cddf9SRui Paulo 		return;
439*f05cddf9SRui Paulo 	res = recvfrom(sock, buf, buflen, 0,
440*f05cddf9SRui Paulo 		       (struct sockaddr *) &from, &fromlen);
441*f05cddf9SRui Paulo 	if (res < 0) {
442*f05cddf9SRui Paulo 		perror("recvfrom(priv_socket)");
443*f05cddf9SRui Paulo 		os_free(buf);
444*f05cddf9SRui Paulo 		return;
445*f05cddf9SRui Paulo 	}
446*f05cddf9SRui Paulo 
447*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "privsep_driver: received %u bytes", res);
448*f05cddf9SRui Paulo 
449*f05cddf9SRui Paulo 	if (res < (int) sizeof(int)) {
450*f05cddf9SRui Paulo 		wpa_printf(MSG_DEBUG, "Too short event message (len=%d)", res);
451*f05cddf9SRui Paulo 		return;
452*f05cddf9SRui Paulo 	}
453*f05cddf9SRui Paulo 
454*f05cddf9SRui Paulo 	os_memcpy(&event, buf, sizeof(int));
455*f05cddf9SRui Paulo 	event_buf = &buf[sizeof(int)];
456*f05cddf9SRui Paulo 	event_len = res - sizeof(int);
457*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "privsep: Event %d received (len=%lu)",
458*f05cddf9SRui Paulo 		   event, (unsigned long) event_len);
459*f05cddf9SRui Paulo 
460*f05cddf9SRui Paulo 	e = event;
461*f05cddf9SRui Paulo 	switch (e) {
462*f05cddf9SRui Paulo 	case PRIVSEP_EVENT_SCAN_RESULTS:
463*f05cddf9SRui Paulo 		wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL);
464*f05cddf9SRui Paulo 		break;
465*f05cddf9SRui Paulo 	case PRIVSEP_EVENT_ASSOC:
466*f05cddf9SRui Paulo 		wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOC,
467*f05cddf9SRui Paulo 					       event_buf, event_len);
468*f05cddf9SRui Paulo 		break;
469*f05cddf9SRui Paulo 	case PRIVSEP_EVENT_DISASSOC:
470*f05cddf9SRui Paulo 		wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
471*f05cddf9SRui Paulo 		break;
472*f05cddf9SRui Paulo 	case PRIVSEP_EVENT_ASSOCINFO:
473*f05cddf9SRui Paulo 		wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOCINFO,
474*f05cddf9SRui Paulo 					       event_buf, event_len);
475*f05cddf9SRui Paulo 		break;
476*f05cddf9SRui Paulo 	case PRIVSEP_EVENT_MICHAEL_MIC_FAILURE:
477*f05cddf9SRui Paulo 		wpa_driver_privsep_event_michael_mic_failure(
478*f05cddf9SRui Paulo 			drv->ctx, event_buf, event_len);
479*f05cddf9SRui Paulo 		break;
480*f05cddf9SRui Paulo 	case PRIVSEP_EVENT_INTERFACE_STATUS:
481*f05cddf9SRui Paulo 		wpa_driver_privsep_event_interface_status(drv->ctx, event_buf,
482*f05cddf9SRui Paulo 							  event_len);
483*f05cddf9SRui Paulo 		break;
484*f05cddf9SRui Paulo 	case PRIVSEP_EVENT_PMKID_CANDIDATE:
485*f05cddf9SRui Paulo 		wpa_driver_privsep_event_pmkid_candidate(drv->ctx, event_buf,
486*f05cddf9SRui Paulo 							 event_len);
487*f05cddf9SRui Paulo 		break;
488*f05cddf9SRui Paulo 	case PRIVSEP_EVENT_STKSTART:
489*f05cddf9SRui Paulo 		wpa_driver_privsep_event_stkstart(drv->ctx, event_buf,
490*f05cddf9SRui Paulo 						  event_len);
491*f05cddf9SRui Paulo 		break;
492*f05cddf9SRui Paulo 	case PRIVSEP_EVENT_FT_RESPONSE:
493*f05cddf9SRui Paulo 		wpa_driver_privsep_event_ft_response(drv->ctx, event_buf,
494*f05cddf9SRui Paulo 						     event_len);
495*f05cddf9SRui Paulo 		break;
496*f05cddf9SRui Paulo 	case PRIVSEP_EVENT_RX_EAPOL:
497*f05cddf9SRui Paulo 		wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf,
498*f05cddf9SRui Paulo 						  event_len);
499*f05cddf9SRui Paulo 		break;
500*f05cddf9SRui Paulo 	}
501*f05cddf9SRui Paulo 
502*f05cddf9SRui Paulo 	os_free(buf);
503*f05cddf9SRui Paulo }
504*f05cddf9SRui Paulo 
505*f05cddf9SRui Paulo 
506*f05cddf9SRui Paulo static void * wpa_driver_privsep_init(void *ctx, const char *ifname)
507*f05cddf9SRui Paulo {
508*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv;
509*f05cddf9SRui Paulo 
510*f05cddf9SRui Paulo 	drv = os_zalloc(sizeof(*drv));
511*f05cddf9SRui Paulo 	if (drv == NULL)
512*f05cddf9SRui Paulo 		return NULL;
513*f05cddf9SRui Paulo 	drv->ctx = ctx;
514*f05cddf9SRui Paulo 	drv->priv_socket = -1;
515*f05cddf9SRui Paulo 	drv->cmd_socket = -1;
516*f05cddf9SRui Paulo 	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
517*f05cddf9SRui Paulo 
518*f05cddf9SRui Paulo 	return drv;
519*f05cddf9SRui Paulo }
520*f05cddf9SRui Paulo 
521*f05cddf9SRui Paulo 
522*f05cddf9SRui Paulo static void wpa_driver_privsep_deinit(void *priv)
523*f05cddf9SRui Paulo {
524*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv = priv;
525*f05cddf9SRui Paulo 
526*f05cddf9SRui Paulo 	if (drv->priv_socket >= 0) {
527*f05cddf9SRui Paulo 		wpa_priv_reg_cmd(drv, PRIVSEP_CMD_UNREGISTER);
528*f05cddf9SRui Paulo 		eloop_unregister_read_sock(drv->priv_socket);
529*f05cddf9SRui Paulo 		close(drv->priv_socket);
530*f05cddf9SRui Paulo 	}
531*f05cddf9SRui Paulo 
532*f05cddf9SRui Paulo 	if (drv->own_socket_path) {
533*f05cddf9SRui Paulo 		unlink(drv->own_socket_path);
534*f05cddf9SRui Paulo 		os_free(drv->own_socket_path);
535*f05cddf9SRui Paulo 	}
536*f05cddf9SRui Paulo 
537*f05cddf9SRui Paulo 	if (drv->cmd_socket >= 0) {
538*f05cddf9SRui Paulo 		eloop_unregister_read_sock(drv->cmd_socket);
539*f05cddf9SRui Paulo 		close(drv->cmd_socket);
540*f05cddf9SRui Paulo 	}
541*f05cddf9SRui Paulo 
542*f05cddf9SRui Paulo 	if (drv->own_cmd_path) {
543*f05cddf9SRui Paulo 		unlink(drv->own_cmd_path);
544*f05cddf9SRui Paulo 		os_free(drv->own_cmd_path);
545*f05cddf9SRui Paulo 	}
546*f05cddf9SRui Paulo 
547*f05cddf9SRui Paulo 	os_free(drv);
548*f05cddf9SRui Paulo }
549*f05cddf9SRui Paulo 
550*f05cddf9SRui Paulo 
551*f05cddf9SRui Paulo static int wpa_driver_privsep_set_param(void *priv, const char *param)
552*f05cddf9SRui Paulo {
553*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv = priv;
554*f05cddf9SRui Paulo 	const char *pos;
555*f05cddf9SRui Paulo 	char *own_dir, *priv_dir;
556*f05cddf9SRui Paulo 	static unsigned int counter = 0;
557*f05cddf9SRui Paulo 	size_t len;
558*f05cddf9SRui Paulo 	struct sockaddr_un addr;
559*f05cddf9SRui Paulo 
560*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
561*f05cddf9SRui Paulo 	if (param == NULL)
562*f05cddf9SRui Paulo 		pos = NULL;
563*f05cddf9SRui Paulo 	else
564*f05cddf9SRui Paulo 		pos = os_strstr(param, "own_dir=");
565*f05cddf9SRui Paulo 	if (pos) {
566*f05cddf9SRui Paulo 		char *end;
567*f05cddf9SRui Paulo 		own_dir = os_strdup(pos + 8);
568*f05cddf9SRui Paulo 		if (own_dir == NULL)
569*f05cddf9SRui Paulo 			return -1;
570*f05cddf9SRui Paulo 		end = os_strchr(own_dir, ' ');
571*f05cddf9SRui Paulo 		if (end)
572*f05cddf9SRui Paulo 			*end = '\0';
573*f05cddf9SRui Paulo 	} else {
574*f05cddf9SRui Paulo 		own_dir = os_strdup("/tmp");
575*f05cddf9SRui Paulo 		if (own_dir == NULL)
576*f05cddf9SRui Paulo 			return -1;
577*f05cddf9SRui Paulo 	}
578*f05cddf9SRui Paulo 
579*f05cddf9SRui Paulo 	if (param == NULL)
580*f05cddf9SRui Paulo 		pos = NULL;
581*f05cddf9SRui Paulo 	else
582*f05cddf9SRui Paulo 		pos = os_strstr(param, "priv_dir=");
583*f05cddf9SRui Paulo 	if (pos) {
584*f05cddf9SRui Paulo 		char *end;
585*f05cddf9SRui Paulo 		priv_dir = os_strdup(pos + 9);
586*f05cddf9SRui Paulo 		if (priv_dir == NULL) {
587*f05cddf9SRui Paulo 			os_free(own_dir);
588*f05cddf9SRui Paulo 			return -1;
589*f05cddf9SRui Paulo 		}
590*f05cddf9SRui Paulo 		end = os_strchr(priv_dir, ' ');
591*f05cddf9SRui Paulo 		if (end)
592*f05cddf9SRui Paulo 			*end = '\0';
593*f05cddf9SRui Paulo 	} else {
594*f05cddf9SRui Paulo 		priv_dir = os_strdup("/var/run/wpa_priv");
595*f05cddf9SRui Paulo 		if (priv_dir == NULL) {
596*f05cddf9SRui Paulo 			os_free(own_dir);
597*f05cddf9SRui Paulo 			return -1;
598*f05cddf9SRui Paulo 		}
599*f05cddf9SRui Paulo 	}
600*f05cddf9SRui Paulo 
601*f05cddf9SRui Paulo 	len = os_strlen(own_dir) + 50;
602*f05cddf9SRui Paulo 	drv->own_socket_path = os_malloc(len);
603*f05cddf9SRui Paulo 	if (drv->own_socket_path == NULL) {
604*f05cddf9SRui Paulo 		os_free(priv_dir);
605*f05cddf9SRui Paulo 		os_free(own_dir);
606*f05cddf9SRui Paulo 		return -1;
607*f05cddf9SRui Paulo 	}
608*f05cddf9SRui Paulo 	os_snprintf(drv->own_socket_path, len, "%s/wpa_privsep-%d-%d",
609*f05cddf9SRui Paulo 		    own_dir, getpid(), counter++);
610*f05cddf9SRui Paulo 
611*f05cddf9SRui Paulo 	len = os_strlen(own_dir) + 50;
612*f05cddf9SRui Paulo 	drv->own_cmd_path = os_malloc(len);
613*f05cddf9SRui Paulo 	if (drv->own_cmd_path == NULL) {
614*f05cddf9SRui Paulo 		os_free(drv->own_socket_path);
615*f05cddf9SRui Paulo 		drv->own_socket_path = NULL;
616*f05cddf9SRui Paulo 		os_free(priv_dir);
617*f05cddf9SRui Paulo 		os_free(own_dir);
618*f05cddf9SRui Paulo 		return -1;
619*f05cddf9SRui Paulo 	}
620*f05cddf9SRui Paulo 	os_snprintf(drv->own_cmd_path, len, "%s/wpa_privsep-%d-%d",
621*f05cddf9SRui Paulo 		    own_dir, getpid(), counter++);
622*f05cddf9SRui Paulo 
623*f05cddf9SRui Paulo 	os_free(own_dir);
624*f05cddf9SRui Paulo 
625*f05cddf9SRui Paulo 	drv->priv_addr.sun_family = AF_UNIX;
626*f05cddf9SRui Paulo 	os_snprintf(drv->priv_addr.sun_path, sizeof(drv->priv_addr.sun_path),
627*f05cddf9SRui Paulo 		    "%s/%s", priv_dir, drv->ifname);
628*f05cddf9SRui Paulo 	os_free(priv_dir);
629*f05cddf9SRui Paulo 
630*f05cddf9SRui Paulo 	drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
631*f05cddf9SRui Paulo 	if (drv->priv_socket < 0) {
632*f05cddf9SRui Paulo 		perror("socket(PF_UNIX)");
633*f05cddf9SRui Paulo 		os_free(drv->own_socket_path);
634*f05cddf9SRui Paulo 		drv->own_socket_path = NULL;
635*f05cddf9SRui Paulo 		return -1;
636*f05cddf9SRui Paulo 	}
637*f05cddf9SRui Paulo 
638*f05cddf9SRui Paulo 	os_memset(&addr, 0, sizeof(addr));
639*f05cddf9SRui Paulo 	addr.sun_family = AF_UNIX;
640*f05cddf9SRui Paulo 	os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path));
641*f05cddf9SRui Paulo 	if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) <
642*f05cddf9SRui Paulo 	    0) {
643*f05cddf9SRui Paulo 		perror("privsep-set-params priv-sock: bind(PF_UNIX)");
644*f05cddf9SRui Paulo 		close(drv->priv_socket);
645*f05cddf9SRui Paulo 		drv->priv_socket = -1;
646*f05cddf9SRui Paulo 		unlink(drv->own_socket_path);
647*f05cddf9SRui Paulo 		os_free(drv->own_socket_path);
648*f05cddf9SRui Paulo 		drv->own_socket_path = NULL;
649*f05cddf9SRui Paulo 		return -1;
650*f05cddf9SRui Paulo 	}
651*f05cddf9SRui Paulo 
652*f05cddf9SRui Paulo 	eloop_register_read_sock(drv->priv_socket, wpa_driver_privsep_receive,
653*f05cddf9SRui Paulo 				 drv, NULL);
654*f05cddf9SRui Paulo 
655*f05cddf9SRui Paulo 	drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
656*f05cddf9SRui Paulo 	if (drv->cmd_socket < 0) {
657*f05cddf9SRui Paulo 		perror("socket(PF_UNIX)");
658*f05cddf9SRui Paulo 		os_free(drv->own_cmd_path);
659*f05cddf9SRui Paulo 		drv->own_cmd_path = NULL;
660*f05cddf9SRui Paulo 		return -1;
661*f05cddf9SRui Paulo 	}
662*f05cddf9SRui Paulo 
663*f05cddf9SRui Paulo 	os_memset(&addr, 0, sizeof(addr));
664*f05cddf9SRui Paulo 	addr.sun_family = AF_UNIX;
665*f05cddf9SRui Paulo 	os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path));
666*f05cddf9SRui Paulo 	if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0)
667*f05cddf9SRui Paulo 	{
668*f05cddf9SRui Paulo 		perror("privsep-set-params cmd-sock: bind(PF_UNIX)");
669*f05cddf9SRui Paulo 		close(drv->cmd_socket);
670*f05cddf9SRui Paulo 		drv->cmd_socket = -1;
671*f05cddf9SRui Paulo 		unlink(drv->own_cmd_path);
672*f05cddf9SRui Paulo 		os_free(drv->own_cmd_path);
673*f05cddf9SRui Paulo 		drv->own_cmd_path = NULL;
674*f05cddf9SRui Paulo 		return -1;
675*f05cddf9SRui Paulo 	}
676*f05cddf9SRui Paulo 
677*f05cddf9SRui Paulo 	if (wpa_priv_reg_cmd(drv, PRIVSEP_CMD_REGISTER) < 0) {
678*f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "Failed to register with wpa_priv");
679*f05cddf9SRui Paulo 		return -1;
680*f05cddf9SRui Paulo 	}
681*f05cddf9SRui Paulo 
682*f05cddf9SRui Paulo 	return 0;
683*f05cddf9SRui Paulo }
684*f05cddf9SRui Paulo 
685*f05cddf9SRui Paulo 
686*f05cddf9SRui Paulo static int wpa_driver_privsep_get_capa(void *priv,
687*f05cddf9SRui Paulo 				       struct wpa_driver_capa *capa)
688*f05cddf9SRui Paulo {
689*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv = priv;
690*f05cddf9SRui Paulo 	int res;
691*f05cddf9SRui Paulo 	size_t len = sizeof(*capa);
692*f05cddf9SRui Paulo 
693*f05cddf9SRui Paulo 	res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_CAPA, NULL, 0, capa, &len);
694*f05cddf9SRui Paulo 	if (res < 0 || len != sizeof(*capa))
695*f05cddf9SRui Paulo 		return -1;
696*f05cddf9SRui Paulo 	return 0;
697*f05cddf9SRui Paulo }
698*f05cddf9SRui Paulo 
699*f05cddf9SRui Paulo 
700*f05cddf9SRui Paulo static const u8 * wpa_driver_privsep_get_mac_addr(void *priv)
701*f05cddf9SRui Paulo {
702*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv = priv;
703*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "%s", __func__);
704*f05cddf9SRui Paulo 	return drv->own_addr;
705*f05cddf9SRui Paulo }
706*f05cddf9SRui Paulo 
707*f05cddf9SRui Paulo 
708*f05cddf9SRui Paulo static int wpa_driver_privsep_set_country(void *priv, const char *alpha2)
709*f05cddf9SRui Paulo {
710*f05cddf9SRui Paulo 	struct wpa_driver_privsep_data *drv = priv;
711*f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "%s country='%s'", __func__, alpha2);
712*f05cddf9SRui Paulo 	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_COUNTRY, alpha2,
713*f05cddf9SRui Paulo 			    os_strlen(alpha2), NULL, NULL);
714*f05cddf9SRui Paulo }
715*f05cddf9SRui Paulo 
716*f05cddf9SRui Paulo 
717*f05cddf9SRui Paulo struct wpa_driver_ops wpa_driver_privsep_ops = {
718*f05cddf9SRui Paulo 	"privsep",
719*f05cddf9SRui Paulo 	"wpa_supplicant privilege separated driver",
720*f05cddf9SRui Paulo 	.get_bssid = wpa_driver_privsep_get_bssid,
721*f05cddf9SRui Paulo 	.get_ssid = wpa_driver_privsep_get_ssid,
722*f05cddf9SRui Paulo 	.set_key = wpa_driver_privsep_set_key,
723*f05cddf9SRui Paulo 	.init = wpa_driver_privsep_init,
724*f05cddf9SRui Paulo 	.deinit = wpa_driver_privsep_deinit,
725*f05cddf9SRui Paulo 	.set_param = wpa_driver_privsep_set_param,
726*f05cddf9SRui Paulo 	.scan2 = wpa_driver_privsep_scan,
727*f05cddf9SRui Paulo 	.deauthenticate = wpa_driver_privsep_deauthenticate,
728*f05cddf9SRui Paulo 	.associate = wpa_driver_privsep_associate,
729*f05cddf9SRui Paulo 	.get_capa = wpa_driver_privsep_get_capa,
730*f05cddf9SRui Paulo 	.get_mac_addr = wpa_driver_privsep_get_mac_addr,
731*f05cddf9SRui Paulo 	.get_scan_results2 = wpa_driver_privsep_get_scan_results2,
732*f05cddf9SRui Paulo 	.set_country = wpa_driver_privsep_set_country,
733*f05cddf9SRui Paulo };
734*f05cddf9SRui Paulo 
735*f05cddf9SRui Paulo 
736*f05cddf9SRui Paulo struct wpa_driver_ops *wpa_drivers[] =
737*f05cddf9SRui Paulo {
738*f05cddf9SRui Paulo 	&wpa_driver_privsep_ops,
739*f05cddf9SRui Paulo 	NULL
740*f05cddf9SRui Paulo };
741