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