ctrl_iface_unix.c revision 0dc7a27a4d3b8328028ced3a71bd331e77981166
1/* 2 * WPA Supplicant / UNIX domain socket -based control interface 3 * Copyright (c) 2004-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#include <sys/stat.h> 18#include <grp.h> 19#include <stddef.h> 20#ifdef ANDROID 21#include <cutils/sockets.h> 22#endif /* ANDROID */ 23 24#include "utils/common.h" 25#include "utils/eloop.h" 26#include "utils/list.h" 27#include "eapol_supp/eapol_supp_sm.h" 28#include "config.h" 29#include "wpa_supplicant_i.h" 30#include "ctrl_iface.h" 31 32/* Per-interface ctrl_iface */ 33 34/** 35 * struct wpa_ctrl_dst - Internal data structure of control interface monitors 36 * 37 * This structure is used to store information about registered control 38 * interface monitors into struct wpa_supplicant. This data is private to 39 * ctrl_iface_unix.c and should not be touched directly from other files. 40 */ 41struct wpa_ctrl_dst { 42 struct dl_list list; 43 struct sockaddr_un addr; 44 socklen_t addrlen; 45 int debug_level; 46 int errors; 47}; 48 49 50struct ctrl_iface_priv { 51 struct wpa_supplicant *wpa_s; 52 int sock; 53 struct dl_list ctrl_dst; 54}; 55 56 57static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 58 int level, const char *buf, 59 size_t len); 60 61 62static int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv, 63 struct sockaddr_un *from, 64 socklen_t fromlen) 65{ 66 struct wpa_ctrl_dst *dst; 67 68 dst = os_zalloc(sizeof(*dst)); 69 if (dst == NULL) 70 return -1; 71 os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); 72 dst->addrlen = fromlen; 73 dst->debug_level = MSG_INFO; 74 dl_list_add(&priv->ctrl_dst, &dst->list); 75 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", 76 (u8 *) from->sun_path, 77 fromlen - offsetof(struct sockaddr_un, sun_path)); 78 return 0; 79} 80 81 82static int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv, 83 struct sockaddr_un *from, 84 socklen_t fromlen) 85{ 86 struct wpa_ctrl_dst *dst; 87 88 dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) { 89 if (fromlen == dst->addrlen && 90 os_memcmp(from->sun_path, dst->addr.sun_path, 91 fromlen - offsetof(struct sockaddr_un, sun_path)) 92 == 0) { 93 dl_list_del(&dst->list); 94 os_free(dst); 95 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", 96 (u8 *) from->sun_path, 97 fromlen - 98 offsetof(struct sockaddr_un, sun_path)); 99 return 0; 100 } 101 } 102 return -1; 103} 104 105 106static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv, 107 struct sockaddr_un *from, 108 socklen_t fromlen, 109 char *level) 110{ 111 struct wpa_ctrl_dst *dst; 112 113 wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 114 115 dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) { 116 if (fromlen == dst->addrlen && 117 os_memcmp(from->sun_path, dst->addr.sun_path, 118 fromlen - offsetof(struct sockaddr_un, sun_path)) 119 == 0) { 120 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " 121 "level", (u8 *) from->sun_path, 122 fromlen - 123 offsetof(struct sockaddr_un, sun_path)); 124 dst->debug_level = atoi(level); 125 return 0; 126 } 127 } 128 129 return -1; 130} 131 132 133static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, 134 void *sock_ctx) 135{ 136 struct wpa_supplicant *wpa_s = eloop_ctx; 137 struct ctrl_iface_priv *priv = sock_ctx; 138 char buf[4096]; 139 int res; 140 struct sockaddr_un from; 141 socklen_t fromlen = sizeof(from); 142 char *reply = NULL; 143 size_t reply_len = 0; 144 int new_attached = 0; 145 146 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 147 (struct sockaddr *) &from, &fromlen); 148 if (res < 0) { 149 perror("recvfrom(ctrl_iface)"); 150 return; 151 } 152 buf[res] = '\0'; 153 154 if (os_strcmp(buf, "ATTACH") == 0) { 155 if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen)) 156 reply_len = 1; 157 else { 158 new_attached = 1; 159 reply_len = 2; 160 } 161 } else if (os_strcmp(buf, "DETACH") == 0) { 162 if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen)) 163 reply_len = 1; 164 else 165 reply_len = 2; 166 } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 167 if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen, 168 buf + 6)) 169 reply_len = 1; 170 else 171 reply_len = 2; 172 } else { 173 reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf, 174 &reply_len); 175 } 176 177 if (reply) { 178 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 179 fromlen); 180 os_free(reply); 181 } else if (reply_len == 1) { 182 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 183 fromlen); 184 } else if (reply_len == 2) { 185 sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, 186 fromlen); 187 } 188 189 if (new_attached) 190 eapol_sm_notify_ctrl_attached(wpa_s->eapol); 191} 192 193 194static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s) 195{ 196 char *buf; 197 size_t len; 198 char *pbuf, *dir = NULL, *gid_str = NULL; 199 int res; 200 201 if (wpa_s->conf->ctrl_interface == NULL) 202 return NULL; 203 204 pbuf = os_strdup(wpa_s->conf->ctrl_interface); 205 if (pbuf == NULL) 206 return NULL; 207 if (os_strncmp(pbuf, "DIR=", 4) == 0) { 208 dir = pbuf + 4; 209 gid_str = os_strstr(dir, " GROUP="); 210 if (gid_str) { 211 *gid_str = '\0'; 212 gid_str += 7; 213 } 214 } else 215 dir = pbuf; 216 217 len = os_strlen(dir) + os_strlen(wpa_s->ifname) + 2; 218 buf = os_malloc(len); 219 if (buf == NULL) { 220 os_free(pbuf); 221 return NULL; 222 } 223 224 res = os_snprintf(buf, len, "%s/%s", dir, wpa_s->ifname); 225 if (res < 0 || (size_t) res >= len) { 226 os_free(pbuf); 227 os_free(buf); 228 return NULL; 229 } 230#ifdef __CYGWIN__ 231 { 232 /* Windows/WinPcap uses interface names that are not suitable 233 * as a file name - convert invalid chars to underscores */ 234 char *pos = buf; 235 while (*pos) { 236 if (*pos == '\\') 237 *pos = '_'; 238 pos++; 239 } 240 } 241#endif /* __CYGWIN__ */ 242 os_free(pbuf); 243 return buf; 244} 245 246 247static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, 248 const char *txt, size_t len) 249{ 250 struct wpa_supplicant *wpa_s = ctx; 251 if (wpa_s == NULL || wpa_s->ctrl_iface == NULL) 252 return; 253 wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len); 254} 255 256 257struct ctrl_iface_priv * 258wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) 259{ 260 struct ctrl_iface_priv *priv; 261 struct sockaddr_un addr; 262 char *fname = NULL; 263 gid_t gid = 0; 264 int gid_set = 0; 265 char *buf, *dir = NULL, *gid_str = NULL; 266 struct group *grp; 267 char *endp; 268 269 priv = os_zalloc(sizeof(*priv)); 270 if (priv == NULL) 271 return NULL; 272 dl_list_init(&priv->ctrl_dst); 273 priv->wpa_s = wpa_s; 274 priv->sock = -1; 275 276 if (wpa_s->conf->ctrl_interface == NULL) 277 return priv; 278 279 buf = os_strdup(wpa_s->conf->ctrl_interface); 280 if (buf == NULL) 281 goto fail; 282#ifdef ANDROID 283 os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s", 284 wpa_s->ifname); 285 priv->sock = android_get_control_socket(addr.sun_path); 286 if (priv->sock >= 0) 287 goto havesock; 288#endif /* ANDROID */ 289 if (os_strncmp(buf, "DIR=", 4) == 0) { 290 dir = buf + 4; 291 gid_str = os_strstr(dir, " GROUP="); 292 if (gid_str) { 293 *gid_str = '\0'; 294 gid_str += 7; 295 } 296 } else { 297 dir = buf; 298 gid_str = wpa_s->conf->ctrl_interface_group; 299 } 300 301 if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) { 302 if (errno == EEXIST) { 303 wpa_printf(MSG_DEBUG, "Using existing control " 304 "interface directory."); 305 } else { 306 perror("mkdir[ctrl_interface]"); 307 goto fail; 308 } 309 } 310 311 if (gid_str) { 312 grp = getgrnam(gid_str); 313 if (grp) { 314 gid = grp->gr_gid; 315 gid_set = 1; 316 wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" 317 " (from group name '%s')", 318 (int) gid, gid_str); 319 } else { 320 /* Group name not found - try to parse this as gid */ 321 gid = strtol(gid_str, &endp, 10); 322 if (*gid_str == '\0' || *endp != '\0') { 323 wpa_printf(MSG_ERROR, "CTRL: Invalid group " 324 "'%s'", gid_str); 325 goto fail; 326 } 327 gid_set = 1; 328 wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", 329 (int) gid); 330 } 331 } 332 333 if (gid_set && chown(dir, -1, gid) < 0) { 334 perror("chown[ctrl_interface]"); 335 goto fail; 336 } 337 338 /* Make sure the group can enter and read the directory */ 339 if (gid_set && 340 chmod(dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP) < 0) { 341 wpa_printf(MSG_ERROR, "CTRL: chmod[ctrl_interface]: %s", 342 strerror(errno)); 343 goto fail; 344 } 345 346 if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >= 347 sizeof(addr.sun_path)) { 348 wpa_printf(MSG_ERROR, "ctrl_iface path limit exceeded"); 349 goto fail; 350 } 351 352 priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); 353 if (priv->sock < 0) { 354 perror("socket(PF_UNIX)"); 355 goto fail; 356 } 357 358 os_memset(&addr, 0, sizeof(addr)); 359#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 360 addr.sun_len = sizeof(addr); 361#endif /* __FreeBSD__ */ 362 addr.sun_family = AF_UNIX; 363 fname = wpa_supplicant_ctrl_iface_path(wpa_s); 364 if (fname == NULL) 365 goto fail; 366 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 367 if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 368 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 369 strerror(errno)); 370 if (connect(priv->sock, (struct sockaddr *) &addr, 371 sizeof(addr)) < 0) { 372 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 373 " allow connections - assuming it was left" 374 "over from forced program termination"); 375 if (unlink(fname) < 0) { 376 perror("unlink[ctrl_iface]"); 377 wpa_printf(MSG_ERROR, "Could not unlink " 378 "existing ctrl_iface socket '%s'", 379 fname); 380 goto fail; 381 } 382 if (bind(priv->sock, (struct sockaddr *) &addr, 383 sizeof(addr)) < 0) { 384 perror("bind(PF_UNIX)"); 385 goto fail; 386 } 387 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 388 "ctrl_iface socket '%s'", fname); 389 } else { 390 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 391 "be in use - cannot override it"); 392 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 393 "not used anymore", fname); 394 os_free(fname); 395 fname = NULL; 396 goto fail; 397 } 398 } 399 400 if (gid_set && chown(fname, -1, gid) < 0) { 401 perror("chown[ctrl_interface/ifname]"); 402 goto fail; 403 } 404 405 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 406 perror("chmod[ctrl_interface/ifname]"); 407 goto fail; 408 } 409 os_free(fname); 410 411#ifdef ANDROID 412havesock: 413#endif /* ANDROID */ 414 eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, 415 wpa_s, priv); 416 wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 417 418 os_free(buf); 419 return priv; 420 421fail: 422 if (priv->sock >= 0) 423 close(priv->sock); 424 os_free(priv); 425 if (fname) { 426 unlink(fname); 427 os_free(fname); 428 } 429 os_free(buf); 430 return NULL; 431} 432 433 434void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) 435{ 436 struct wpa_ctrl_dst *dst, *prev; 437 438 if (priv->sock > -1) { 439 char *fname; 440 char *buf, *dir = NULL, *gid_str = NULL; 441 eloop_unregister_read_sock(priv->sock); 442 if (!dl_list_empty(&priv->ctrl_dst)) { 443 /* 444 * Wait a second before closing the control socket if 445 * there are any attached monitors in order to allow 446 * them to receive any pending messages. 447 */ 448 wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " 449 "monitors to receive messages"); 450 os_sleep(1, 0); 451 } 452 close(priv->sock); 453 priv->sock = -1; 454 fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s); 455 if (fname) { 456 unlink(fname); 457 os_free(fname); 458 } 459 460 buf = os_strdup(priv->wpa_s->conf->ctrl_interface); 461 if (buf == NULL) 462 goto free_dst; 463 if (os_strncmp(buf, "DIR=", 4) == 0) { 464 dir = buf + 4; 465 gid_str = os_strstr(dir, " GROUP="); 466 if (gid_str) { 467 *gid_str = '\0'; 468 gid_str += 7; 469 } 470 } else 471 dir = buf; 472 473 if (rmdir(dir) < 0) { 474 if (errno == ENOTEMPTY) { 475 wpa_printf(MSG_DEBUG, "Control interface " 476 "directory not empty - leaving it " 477 "behind"); 478 } else { 479 perror("rmdir[ctrl_interface]"); 480 } 481 } 482 os_free(buf); 483 } 484 485free_dst: 486 dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst, 487 list) 488 os_free(dst); 489 os_free(priv); 490} 491 492 493/** 494 * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors 495 * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init() 496 * @level: Priority level of the message 497 * @buf: Message data 498 * @len: Message length 499 * 500 * Send a packet to all monitor programs attached to the control interface. 501 */ 502static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 503 int level, const char *buf, 504 size_t len) 505{ 506 struct wpa_ctrl_dst *dst, *next; 507 char levelstr[10]; 508 int idx, res; 509 struct msghdr msg; 510 struct iovec io[2]; 511 512 if (priv->sock < 0 || dl_list_empty(&priv->ctrl_dst)) 513 return; 514 515 res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 516 if (res < 0 || (size_t) res >= sizeof(levelstr)) 517 return; 518 io[0].iov_base = levelstr; 519 io[0].iov_len = os_strlen(levelstr); 520 io[1].iov_base = (char *) buf; 521 io[1].iov_len = len; 522 os_memset(&msg, 0, sizeof(msg)); 523 msg.msg_iov = io; 524 msg.msg_iovlen = 2; 525 526 idx = 0; 527 dl_list_for_each_safe(dst, next, &priv->ctrl_dst, struct wpa_ctrl_dst, 528 list) { 529 if (level >= dst->debug_level) { 530 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", 531 (u8 *) dst->addr.sun_path, dst->addrlen - 532 offsetof(struct sockaddr_un, sun_path)); 533 msg.msg_name = (void *) &dst->addr; 534 msg.msg_namelen = dst->addrlen; 535 if (sendmsg(priv->sock, &msg, 0) < 0) { 536 int _errno = errno; 537 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " 538 "%d - %s", 539 idx, errno, strerror(errno)); 540 dst->errors++; 541 if (dst->errors > 1000 || 542 (_errno != ENOBUFS && dst->errors > 10) || 543 _errno == ENOENT) { 544 wpa_supplicant_ctrl_iface_detach( 545 priv, &dst->addr, 546 dst->addrlen); 547 } 548 } else 549 dst->errors = 0; 550 } 551 idx++; 552 } 553} 554 555 556void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) 557{ 558 char buf[256]; 559 int res; 560 struct sockaddr_un from; 561 socklen_t fromlen = sizeof(from); 562 563 for (;;) { 564 wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to " 565 "attach", priv->wpa_s->ifname); 566 eloop_wait_for_read_sock(priv->sock); 567 568 res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0, 569 (struct sockaddr *) &from, &fromlen); 570 if (res < 0) { 571 perror("recvfrom(ctrl_iface)"); 572 continue; 573 } 574 buf[res] = '\0'; 575 576 if (os_strcmp(buf, "ATTACH") == 0) { 577 /* handle ATTACH signal of first monitor interface */ 578 if (!wpa_supplicant_ctrl_iface_attach(priv, &from, 579 fromlen)) { 580 sendto(priv->sock, "OK\n", 3, 0, 581 (struct sockaddr *) &from, fromlen); 582 /* OK to continue */ 583 return; 584 } else { 585 sendto(priv->sock, "FAIL\n", 5, 0, 586 (struct sockaddr *) &from, fromlen); 587 } 588 } else { 589 /* return FAIL for all other signals */ 590 sendto(priv->sock, "FAIL\n", 5, 0, 591 (struct sockaddr *) &from, fromlen); 592 } 593 } 594} 595 596 597/* Global ctrl_iface */ 598 599struct ctrl_iface_global_priv { 600 struct wpa_global *global; 601 int sock; 602}; 603 604 605static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, 606 void *sock_ctx) 607{ 608 struct wpa_global *global = eloop_ctx; 609 char buf[256]; 610 int res; 611 struct sockaddr_un from; 612 socklen_t fromlen = sizeof(from); 613 char *reply; 614 size_t reply_len; 615 616 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 617 (struct sockaddr *) &from, &fromlen); 618 if (res < 0) { 619 perror("recvfrom(ctrl_iface)"); 620 return; 621 } 622 buf[res] = '\0'; 623 624 reply = wpa_supplicant_global_ctrl_iface_process(global, buf, 625 &reply_len); 626 627 if (reply) { 628 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 629 fromlen); 630 os_free(reply); 631 } else if (reply_len) { 632 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 633 fromlen); 634 } 635} 636 637 638struct ctrl_iface_global_priv * 639wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) 640{ 641 struct ctrl_iface_global_priv *priv; 642 struct sockaddr_un addr; 643 644 priv = os_zalloc(sizeof(*priv)); 645 if (priv == NULL) 646 return NULL; 647 priv->global = global; 648 priv->sock = -1; 649 650 if (global->params.ctrl_interface == NULL) 651 return priv; 652 653#ifdef ANDROID 654 priv->sock = android_get_control_socket(global->params.ctrl_interface); 655 if (priv->sock >= 0) 656 goto havesock; 657#endif /* ANDROID */ 658 659 wpa_printf(MSG_DEBUG, "Global control interface '%s'", 660 global->params.ctrl_interface); 661 662 priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); 663 if (priv->sock < 0) { 664 perror("socket(PF_UNIX)"); 665 goto fail; 666 } 667 668 os_memset(&addr, 0, sizeof(addr)); 669#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 670 addr.sun_len = sizeof(addr); 671#endif /* __FreeBSD__ */ 672 addr.sun_family = AF_UNIX; 673 os_strlcpy(addr.sun_path, global->params.ctrl_interface, 674 sizeof(addr.sun_path)); 675 if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 676 perror("bind(PF_UNIX)"); 677 if (connect(priv->sock, (struct sockaddr *) &addr, 678 sizeof(addr)) < 0) { 679 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 680 " allow connections - assuming it was left" 681 "over from forced program termination"); 682 if (unlink(global->params.ctrl_interface) < 0) { 683 perror("unlink[ctrl_iface]"); 684 wpa_printf(MSG_ERROR, "Could not unlink " 685 "existing ctrl_iface socket '%s'", 686 global->params.ctrl_interface); 687 goto fail; 688 } 689 if (bind(priv->sock, (struct sockaddr *) &addr, 690 sizeof(addr)) < 0) { 691 perror("bind(PF_UNIX)"); 692 goto fail; 693 } 694 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 695 "ctrl_iface socket '%s'", 696 global->params.ctrl_interface); 697 } else { 698 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 699 "be in use - cannot override it"); 700 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 701 "not used anymore", 702 global->params.ctrl_interface); 703 goto fail; 704 } 705 } 706 707#ifdef ANDROID 708havesock: 709#endif /* ANDROID */ 710 eloop_register_read_sock(priv->sock, 711 wpa_supplicant_global_ctrl_iface_receive, 712 global, NULL); 713 714 return priv; 715 716fail: 717 if (priv->sock >= 0) 718 close(priv->sock); 719 os_free(priv); 720 return NULL; 721} 722 723 724void 725wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) 726{ 727 if (priv->sock >= 0) { 728 eloop_unregister_read_sock(priv->sock); 729 close(priv->sock); 730 } 731 if (priv->global->params.ctrl_interface) 732 unlink(priv->global->params.ctrl_interface); 733 os_free(priv); 734} 735