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