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 */ 50 struct 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 85 struct 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++; 109 try_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 215 void 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 */ 234 void 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 266 void 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 276 struct 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 427 char * 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 437 void 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 450 int 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; 485 retry_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 549 static 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 565 int wpa_ctrl_attach(struct wpa_ctrl *ctrl) 566 { 567 return wpa_ctrl_attach_helper(ctrl, 1); 568 } 569 570 571 int 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 579 int 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 591 int 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 604 int 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 619 struct 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 680 void wpa_ctrl_close(struct wpa_ctrl *ctrl) 681 { 682 CloseHandle(ctrl->pipe); 683 os_free(ctrl); 684 } 685 686 687 int 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 705 int 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 715 int 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 725 int 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