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