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