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