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