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