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