wpa_ctrl.c revision 281806
1/* 2 * wpa_supplicant/hostapd control interface library 3 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9#include "includes.h" 10 11#ifdef CONFIG_CTRL_IFACE 12 13#ifdef CONFIG_CTRL_IFACE_UNIX 14#include <sys/un.h> 15#include <unistd.h> 16#include <fcntl.h> 17#endif /* CONFIG_CTRL_IFACE_UNIX */ 18#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 19#include <netdb.h> 20#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 21 22#ifdef ANDROID 23#include <dirent.h> 24#include <cutils/sockets.h> 25#include "private/android_filesystem_config.h" 26#endif /* ANDROID */ 27 28#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 29#include <net/if.h> 30#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 31 32#include "wpa_ctrl.h" 33#include "common.h" 34 35 36#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) 37#define CTRL_IFACE_SOCKET 38#endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */ 39 40 41/** 42 * struct wpa_ctrl - Internal structure for control interface library 43 * 44 * This structure is used by the wpa_supplicant/hostapd control interface 45 * library to store internal data. Programs using the library should not touch 46 * this data directly. They can only use the pointer to the data structure as 47 * an identifier for the control interface connection and use this as one of 48 * the arguments for most of the control interface library functions. 49 */ 50struct wpa_ctrl { 51#ifdef CONFIG_CTRL_IFACE_UDP 52 int s; 53#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 54 struct sockaddr_in6 local; 55 struct sockaddr_in6 dest; 56#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 57 struct sockaddr_in local; 58 struct sockaddr_in dest; 59#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 60 char *cookie; 61 char *remote_ifname; 62 char *remote_ip; 63#endif /* CONFIG_CTRL_IFACE_UDP */ 64#ifdef CONFIG_CTRL_IFACE_UNIX 65 int s; 66 struct sockaddr_un local; 67 struct sockaddr_un dest; 68#endif /* CONFIG_CTRL_IFACE_UNIX */ 69#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 70 HANDLE pipe; 71#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 72}; 73 74 75#ifdef CONFIG_CTRL_IFACE_UNIX 76 77#ifndef CONFIG_CTRL_IFACE_CLIENT_DIR 78#define CONFIG_CTRL_IFACE_CLIENT_DIR "/tmp" 79#endif /* CONFIG_CTRL_IFACE_CLIENT_DIR */ 80#ifndef CONFIG_CTRL_IFACE_CLIENT_PREFIX 81#define CONFIG_CTRL_IFACE_CLIENT_PREFIX "wpa_ctrl_" 82#endif /* CONFIG_CTRL_IFACE_CLIENT_PREFIX */ 83 84 85struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) 86{ 87 struct wpa_ctrl *ctrl; 88 static int counter = 0; 89 int ret; 90 size_t res; 91 int tries = 0; 92 int flags; 93 94 if (ctrl_path == NULL) 95 return NULL; 96 97 ctrl = os_zalloc(sizeof(*ctrl)); 98 if (ctrl == NULL) 99 return NULL; 100 101 ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0); 102 if (ctrl->s < 0) { 103 os_free(ctrl); 104 return NULL; 105 } 106 107 ctrl->local.sun_family = AF_UNIX; 108 counter++; 109try_again: 110 ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), 111 CONFIG_CTRL_IFACE_CLIENT_DIR "/" 112 CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d", 113 (int) getpid(), counter); 114 if (os_snprintf_error(sizeof(ctrl->local.sun_path), ret)) { 115 close(ctrl->s); 116 os_free(ctrl); 117 return NULL; 118 } 119 tries++; 120 if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, 121 sizeof(ctrl->local)) < 0) { 122 if (errno == EADDRINUSE && tries < 2) { 123 /* 124 * getpid() returns unique identifier for this instance 125 * of wpa_ctrl, so the existing socket file must have 126 * been left by unclean termination of an earlier run. 127 * Remove the file and try again. 128 */ 129 unlink(ctrl->local.sun_path); 130 goto try_again; 131 } 132 close(ctrl->s); 133 os_free(ctrl); 134 return NULL; 135 } 136 137#ifdef ANDROID 138 chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 139 chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI); 140 141 if (os_strncmp(ctrl_path, "@android:", 9) == 0) { 142 if (socket_local_client_connect( 143 ctrl->s, ctrl_path + 9, 144 ANDROID_SOCKET_NAMESPACE_RESERVED, 145 SOCK_DGRAM) < 0) { 146 close(ctrl->s); 147 unlink(ctrl->local.sun_path); 148 os_free(ctrl); 149 return NULL; 150 } 151 return ctrl; 152 } 153 154 /* 155 * If the ctrl_path isn't an absolute pathname, assume that 156 * it's the name of a socket in the Android reserved namespace. 157 * Otherwise, it's a normal UNIX domain socket appearing in the 158 * filesystem. 159 */ 160 if (*ctrl_path != '/') { 161 char buf[21]; 162 os_snprintf(buf, sizeof(buf), "wpa_%s", ctrl_path); 163 if (socket_local_client_connect( 164 ctrl->s, buf, 165 ANDROID_SOCKET_NAMESPACE_RESERVED, 166 SOCK_DGRAM) < 0) { 167 close(ctrl->s); 168 unlink(ctrl->local.sun_path); 169 os_free(ctrl); 170 return NULL; 171 } 172 return ctrl; 173 } 174#endif /* ANDROID */ 175 176 ctrl->dest.sun_family = AF_UNIX; 177 if (os_strncmp(ctrl_path, "@abstract:", 10) == 0) { 178 ctrl->dest.sun_path[0] = '\0'; 179 os_strlcpy(ctrl->dest.sun_path + 1, ctrl_path + 10, 180 sizeof(ctrl->dest.sun_path) - 1); 181 } else { 182 res = os_strlcpy(ctrl->dest.sun_path, ctrl_path, 183 sizeof(ctrl->dest.sun_path)); 184 if (res >= sizeof(ctrl->dest.sun_path)) { 185 close(ctrl->s); 186 os_free(ctrl); 187 return NULL; 188 } 189 } 190 if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, 191 sizeof(ctrl->dest)) < 0) { 192 close(ctrl->s); 193 unlink(ctrl->local.sun_path); 194 os_free(ctrl); 195 return NULL; 196 } 197 198 /* 199 * Make socket non-blocking so that we don't hang forever if 200 * target dies unexpectedly. 201 */ 202 flags = fcntl(ctrl->s, F_GETFL); 203 if (flags >= 0) { 204 flags |= O_NONBLOCK; 205 if (fcntl(ctrl->s, F_SETFL, flags) < 0) { 206 perror("fcntl(ctrl->s, O_NONBLOCK)"); 207 /* Not fatal, continue on.*/ 208 } 209 } 210 211 return ctrl; 212} 213 214 215void wpa_ctrl_close(struct wpa_ctrl *ctrl) 216{ 217 if (ctrl == NULL) 218 return; 219 unlink(ctrl->local.sun_path); 220 if (ctrl->s >= 0) 221 close(ctrl->s); 222 os_free(ctrl); 223} 224 225 226#ifdef ANDROID 227/** 228 * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that 229 * may be left over from clients that were previously connected to 230 * wpa_supplicant. This keeps these files from being orphaned in the 231 * event of crashes that prevented them from being removed as part 232 * of the normal orderly shutdown. 233 */ 234void wpa_ctrl_cleanup(void) 235{ 236 DIR *dir; 237 struct dirent entry; 238 struct dirent *result; 239 size_t dirnamelen; 240 size_t maxcopy; 241 char pathname[PATH_MAX]; 242 char *namep; 243 244 if ((dir = opendir(CONFIG_CTRL_IFACE_CLIENT_DIR)) == NULL) 245 return; 246 247 dirnamelen = (size_t) os_snprintf(pathname, sizeof(pathname), "%s/", 248 CONFIG_CTRL_IFACE_CLIENT_DIR); 249 if (dirnamelen >= sizeof(pathname)) { 250 closedir(dir); 251 return; 252 } 253 namep = pathname + dirnamelen; 254 maxcopy = PATH_MAX - dirnamelen; 255 while (readdir_r(dir, &entry, &result) == 0 && result != NULL) { 256 if (os_strlcpy(namep, entry.d_name, maxcopy) < maxcopy) 257 unlink(pathname); 258 } 259 closedir(dir); 260} 261#endif /* ANDROID */ 262 263#else /* CONFIG_CTRL_IFACE_UNIX */ 264 265#ifdef ANDROID 266void wpa_ctrl_cleanup(void) 267{ 268} 269#endif /* ANDROID */ 270 271#endif /* CONFIG_CTRL_IFACE_UNIX */ 272 273 274#ifdef CONFIG_CTRL_IFACE_UDP 275 276struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) 277{ 278 struct wpa_ctrl *ctrl; 279 char buf[128]; 280 size_t len; 281#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 282 struct hostent *h; 283#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 284 285 ctrl = os_zalloc(sizeof(*ctrl)); 286 if (ctrl == NULL) 287 return NULL; 288 289#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 290 ctrl->s = socket(PF_INET6, SOCK_DGRAM, 0); 291#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 292 ctrl->s = socket(PF_INET, SOCK_DGRAM, 0); 293#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 294 if (ctrl->s < 0) { 295 perror("socket"); 296 os_free(ctrl); 297 return NULL; 298 } 299 300#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 301 ctrl->local.sin6_family = AF_INET6; 302#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 303 ctrl->local.sin6_addr = in6addr_any; 304#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 305 inet_pton(AF_INET6, "::1", &ctrl->local.sin6_addr); 306#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 307#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 308 ctrl->local.sin_family = AF_INET; 309#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 310 ctrl->local.sin_addr.s_addr = INADDR_ANY; 311#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 312 ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1); 313#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 314#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 315 316 if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, 317 sizeof(ctrl->local)) < 0) { 318 close(ctrl->s); 319 os_free(ctrl); 320 return NULL; 321 } 322 323#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 324 ctrl->dest.sin6_family = AF_INET6; 325 inet_pton(AF_INET6, "::1", &ctrl->dest.sin6_addr); 326 ctrl->dest.sin6_port = htons(WPA_CTRL_IFACE_PORT); 327#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 328 ctrl->dest.sin_family = AF_INET; 329 ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1); 330 ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT); 331#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 332 333#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 334 if (ctrl_path) { 335 char *port, *name; 336 int port_id; 337#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 338 char *scope; 339 int scope_id = 0; 340#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 341 342 name = os_strdup(ctrl_path); 343 if (name == NULL) { 344 close(ctrl->s); 345 os_free(ctrl); 346 return NULL; 347 } 348#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 349 port = os_strchr(name, ','); 350#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 351 port = os_strchr(name, ':'); 352#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 353 354 if (port) { 355 port_id = atoi(&port[1]); 356 port[0] = '\0'; 357 } else 358 port_id = WPA_CTRL_IFACE_PORT; 359 360#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 361 scope = os_strchr(name, '%'); 362 if (scope) { 363 scope_id = if_nametoindex(&scope[1]); 364 scope[0] = '\0'; 365 } 366 h = gethostbyname2(name, AF_INET6); 367#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 368 h = gethostbyname(name); 369#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 370 ctrl->remote_ip = os_strdup(name); 371 os_free(name); 372 if (h == NULL) { 373 perror("gethostbyname"); 374 close(ctrl->s); 375 os_free(ctrl->remote_ip); 376 os_free(ctrl); 377 return NULL; 378 } 379#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 380 ctrl->dest.sin6_scope_id = scope_id; 381 ctrl->dest.sin6_port = htons(port_id); 382 os_memcpy(&ctrl->dest.sin6_addr, h->h_addr, h->h_length); 383#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 384 ctrl->dest.sin_port = htons(port_id); 385 os_memcpy(&ctrl->dest.sin_addr.s_addr, h->h_addr, h->h_length); 386#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 387 } else 388 ctrl->remote_ip = os_strdup("localhost"); 389#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 390 391 if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, 392 sizeof(ctrl->dest)) < 0) { 393#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 394 char addr[INET6_ADDRSTRLEN]; 395 wpa_printf(MSG_ERROR, "connect(%s:%d) failed: %s", 396 inet_ntop(AF_INET6, &ctrl->dest.sin6_addr, addr, 397 sizeof(ctrl->dest)), 398 ntohs(ctrl->dest.sin6_port), 399 strerror(errno)); 400#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 401 wpa_printf(MSG_ERROR, "connect(%s:%d) failed: %s", 402 inet_ntoa(ctrl->dest.sin_addr), 403 ntohs(ctrl->dest.sin_port), 404 strerror(errno)); 405#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 406 close(ctrl->s); 407 os_free(ctrl->remote_ip); 408 os_free(ctrl); 409 return NULL; 410 } 411 412 len = sizeof(buf) - 1; 413 if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) { 414 buf[len] = '\0'; 415 ctrl->cookie = os_strdup(buf); 416 } 417 418 if (wpa_ctrl_request(ctrl, "IFNAME", 6, buf, &len, NULL) == 0) { 419 buf[len] = '\0'; 420 ctrl->remote_ifname = os_strdup(buf); 421 } 422 423 return ctrl; 424} 425 426 427char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl) 428{ 429#define WPA_CTRL_MAX_PS_NAME 100 430 static char ps[WPA_CTRL_MAX_PS_NAME] = {}; 431 os_snprintf(ps, WPA_CTRL_MAX_PS_NAME, "%s/%s", 432 ctrl->remote_ip, ctrl->remote_ifname); 433 return ps; 434} 435 436 437void wpa_ctrl_close(struct wpa_ctrl *ctrl) 438{ 439 close(ctrl->s); 440 os_free(ctrl->cookie); 441 os_free(ctrl->remote_ifname); 442 os_free(ctrl->remote_ip); 443 os_free(ctrl); 444} 445 446#endif /* CONFIG_CTRL_IFACE_UDP */ 447 448 449#ifdef CTRL_IFACE_SOCKET 450int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, 451 char *reply, size_t *reply_len, 452 void (*msg_cb)(char *msg, size_t len)) 453{ 454 struct timeval tv; 455 struct os_reltime started_at; 456 int res; 457 fd_set rfds; 458 const char *_cmd; 459 char *cmd_buf = NULL; 460 size_t _cmd_len; 461 462#ifdef CONFIG_CTRL_IFACE_UDP 463 if (ctrl->cookie) { 464 char *pos; 465 _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len; 466 cmd_buf = os_malloc(_cmd_len); 467 if (cmd_buf == NULL) 468 return -1; 469 _cmd = cmd_buf; 470 pos = cmd_buf; 471 os_strlcpy(pos, ctrl->cookie, _cmd_len); 472 pos += os_strlen(ctrl->cookie); 473 *pos++ = ' '; 474 os_memcpy(pos, cmd, cmd_len); 475 } else 476#endif /* CONFIG_CTRL_IFACE_UDP */ 477 { 478 _cmd = cmd; 479 _cmd_len = cmd_len; 480 } 481 482 errno = 0; 483 started_at.sec = 0; 484 started_at.usec = 0; 485retry_send: 486 if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) { 487 if (errno == EAGAIN || errno == EBUSY || errno == EWOULDBLOCK) 488 { 489 /* 490 * Must be a non-blocking socket... Try for a bit 491 * longer before giving up. 492 */ 493 if (started_at.sec == 0) 494 os_get_reltime(&started_at); 495 else { 496 struct os_reltime n; 497 os_get_reltime(&n); 498 /* Try for a few seconds. */ 499 if (os_reltime_expired(&n, &started_at, 5)) 500 goto send_err; 501 } 502 os_sleep(1, 0); 503 goto retry_send; 504 } 505 send_err: 506 os_free(cmd_buf); 507 return -1; 508 } 509 os_free(cmd_buf); 510 511 for (;;) { 512 tv.tv_sec = 10; 513 tv.tv_usec = 0; 514 FD_ZERO(&rfds); 515 FD_SET(ctrl->s, &rfds); 516 res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv); 517 if (res < 0) 518 return res; 519 if (FD_ISSET(ctrl->s, &rfds)) { 520 res = recv(ctrl->s, reply, *reply_len, 0); 521 if (res < 0) 522 return res; 523 if (res > 0 && reply[0] == '<') { 524 /* This is an unsolicited message from 525 * wpa_supplicant, not the reply to the 526 * request. Use msg_cb to report this to the 527 * caller. */ 528 if (msg_cb) { 529 /* Make sure the message is nul 530 * terminated. */ 531 if ((size_t) res == *reply_len) 532 res = (*reply_len) - 1; 533 reply[res] = '\0'; 534 msg_cb(reply, res); 535 } 536 continue; 537 } 538 *reply_len = res; 539 break; 540 } else { 541 return -2; 542 } 543 } 544 return 0; 545} 546#endif /* CTRL_IFACE_SOCKET */ 547 548 549static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach) 550{ 551 char buf[10]; 552 int ret; 553 size_t len = 10; 554 555 ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6, 556 buf, &len, NULL); 557 if (ret < 0) 558 return ret; 559 if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0) 560 return 0; 561 return -1; 562} 563 564 565int wpa_ctrl_attach(struct wpa_ctrl *ctrl) 566{ 567 return wpa_ctrl_attach_helper(ctrl, 1); 568} 569 570 571int wpa_ctrl_detach(struct wpa_ctrl *ctrl) 572{ 573 return wpa_ctrl_attach_helper(ctrl, 0); 574} 575 576 577#ifdef CTRL_IFACE_SOCKET 578 579int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) 580{ 581 int res; 582 583 res = recv(ctrl->s, reply, *reply_len, 0); 584 if (res < 0) 585 return res; 586 *reply_len = res; 587 return 0; 588} 589 590 591int wpa_ctrl_pending(struct wpa_ctrl *ctrl) 592{ 593 struct timeval tv; 594 fd_set rfds; 595 tv.tv_sec = 0; 596 tv.tv_usec = 0; 597 FD_ZERO(&rfds); 598 FD_SET(ctrl->s, &rfds); 599 select(ctrl->s + 1, &rfds, NULL, NULL, &tv); 600 return FD_ISSET(ctrl->s, &rfds); 601} 602 603 604int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) 605{ 606 return ctrl->s; 607} 608 609#endif /* CTRL_IFACE_SOCKET */ 610 611 612#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 613 614#ifndef WPA_SUPPLICANT_NAMED_PIPE 615#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant" 616#endif 617#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE) 618 619struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) 620{ 621 struct wpa_ctrl *ctrl; 622 DWORD mode; 623 TCHAR name[256]; 624 int i, ret; 625 626 ctrl = os_malloc(sizeof(*ctrl)); 627 if (ctrl == NULL) 628 return NULL; 629 os_memset(ctrl, 0, sizeof(*ctrl)); 630 631#ifdef UNICODE 632 if (ctrl_path == NULL) 633 ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX); 634 else 635 ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"), 636 ctrl_path); 637#else /* UNICODE */ 638 if (ctrl_path == NULL) 639 ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX); 640 else 641 ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s", 642 ctrl_path); 643#endif /* UNICODE */ 644 if (os_snprintf_error(256, ret)) { 645 os_free(ctrl); 646 return NULL; 647 } 648 649 for (i = 0; i < 10; i++) { 650 ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, 651 NULL, OPEN_EXISTING, 0, NULL); 652 /* 653 * Current named pipe server side in wpa_supplicant is 654 * re-opening the pipe for new clients only after the previous 655 * one is taken into use. This leaves a small window for race 656 * conditions when two connections are being opened at almost 657 * the same time. Retry if that was the case. 658 */ 659 if (ctrl->pipe != INVALID_HANDLE_VALUE || 660 GetLastError() != ERROR_PIPE_BUSY) 661 break; 662 WaitNamedPipe(name, 1000); 663 } 664 if (ctrl->pipe == INVALID_HANDLE_VALUE) { 665 os_free(ctrl); 666 return NULL; 667 } 668 669 mode = PIPE_READMODE_MESSAGE; 670 if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) { 671 CloseHandle(ctrl->pipe); 672 os_free(ctrl); 673 return NULL; 674 } 675 676 return ctrl; 677} 678 679 680void wpa_ctrl_close(struct wpa_ctrl *ctrl) 681{ 682 CloseHandle(ctrl->pipe); 683 os_free(ctrl); 684} 685 686 687int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, 688 char *reply, size_t *reply_len, 689 void (*msg_cb)(char *msg, size_t len)) 690{ 691 DWORD written; 692 DWORD readlen = *reply_len; 693 694 if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL)) 695 return -1; 696 697 if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL)) 698 return -1; 699 *reply_len = readlen; 700 701 return 0; 702} 703 704 705int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) 706{ 707 DWORD len = *reply_len; 708 if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL)) 709 return -1; 710 *reply_len = len; 711 return 0; 712} 713 714 715int wpa_ctrl_pending(struct wpa_ctrl *ctrl) 716{ 717 DWORD left; 718 719 if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL)) 720 return -1; 721 return left ? 1 : 0; 722} 723 724 725int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) 726{ 727 return -1; 728} 729 730#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 731 732#endif /* CONFIG_CTRL_IFACE */ 733