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