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