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 chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 163 /* Set group even if we do not have privileges to change owner */ 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 /* This is an unsolicited message from 563 * wpa_supplicant, not the reply to the 564 * request. Use msg_cb to report this to the 565 * caller. */ 566 if (msg_cb) { 567 /* Make sure the message is nul 568 * terminated. */ 569 if ((size_t) res == *reply_len) 570 res = (*reply_len) - 1; 571 reply[res] = '\0'; 572 msg_cb(reply, res); 573 } 574 continue; 575 } 576 *reply_len = res; 577 break; 578 } else { 579 return -2; 580 } 581 } 582 return 0; 583 } 584 #endif /* CTRL_IFACE_SOCKET */ 585 586 587 static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach) 588 { 589 char buf[10]; 590 int ret; 591 size_t len = 10; 592 593 ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6, 594 buf, &len, NULL); 595 if (ret < 0) 596 return ret; 597 if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0) 598 return 0; 599 return -1; 600 } 601 602 603 int wpa_ctrl_attach(struct wpa_ctrl *ctrl) 604 { 605 return wpa_ctrl_attach_helper(ctrl, 1); 606 } 607 608 609 int wpa_ctrl_detach(struct wpa_ctrl *ctrl) 610 { 611 return wpa_ctrl_attach_helper(ctrl, 0); 612 } 613 614 615 #ifdef CTRL_IFACE_SOCKET 616 617 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) 618 { 619 int res; 620 621 res = recv(ctrl->s, reply, *reply_len, 0); 622 if (res < 0) 623 return res; 624 *reply_len = res; 625 return 0; 626 } 627 628 629 int wpa_ctrl_pending(struct wpa_ctrl *ctrl) 630 { 631 struct timeval tv; 632 fd_set rfds; 633 tv.tv_sec = 0; 634 tv.tv_usec = 0; 635 FD_ZERO(&rfds); 636 FD_SET(ctrl->s, &rfds); 637 select(ctrl->s + 1, &rfds, NULL, NULL, &tv); 638 return FD_ISSET(ctrl->s, &rfds); 639 } 640 641 642 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) 643 { 644 return ctrl->s; 645 } 646 647 #endif /* CTRL_IFACE_SOCKET */ 648 649 650 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 651 652 #ifndef WPA_SUPPLICANT_NAMED_PIPE 653 #define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant" 654 #endif 655 #define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE) 656 657 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) 658 { 659 struct wpa_ctrl *ctrl; 660 DWORD mode; 661 TCHAR name[256]; 662 int i, ret; 663 664 ctrl = os_malloc(sizeof(*ctrl)); 665 if (ctrl == NULL) 666 return NULL; 667 os_memset(ctrl, 0, sizeof(*ctrl)); 668 669 #ifdef UNICODE 670 if (ctrl_path == NULL) 671 ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX); 672 else 673 ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"), 674 ctrl_path); 675 #else /* UNICODE */ 676 if (ctrl_path == NULL) 677 ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX); 678 else 679 ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s", 680 ctrl_path); 681 #endif /* UNICODE */ 682 if (os_snprintf_error(256, ret)) { 683 os_free(ctrl); 684 return NULL; 685 } 686 687 for (i = 0; i < 10; i++) { 688 ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, 689 NULL, OPEN_EXISTING, 0, NULL); 690 /* 691 * Current named pipe server side in wpa_supplicant is 692 * re-opening the pipe for new clients only after the previous 693 * one is taken into use. This leaves a small window for race 694 * conditions when two connections are being opened at almost 695 * the same time. Retry if that was the case. 696 */ 697 if (ctrl->pipe != INVALID_HANDLE_VALUE || 698 GetLastError() != ERROR_PIPE_BUSY) 699 break; 700 WaitNamedPipe(name, 1000); 701 } 702 if (ctrl->pipe == INVALID_HANDLE_VALUE) { 703 os_free(ctrl); 704 return NULL; 705 } 706 707 mode = PIPE_READMODE_MESSAGE; 708 if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) { 709 CloseHandle(ctrl->pipe); 710 os_free(ctrl); 711 return NULL; 712 } 713 714 return ctrl; 715 } 716 717 718 void wpa_ctrl_close(struct wpa_ctrl *ctrl) 719 { 720 CloseHandle(ctrl->pipe); 721 os_free(ctrl); 722 } 723 724 725 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, 726 char *reply, size_t *reply_len, 727 void (*msg_cb)(char *msg, size_t len)) 728 { 729 DWORD written; 730 DWORD readlen = *reply_len; 731 732 if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL)) 733 return -1; 734 735 if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL)) 736 return -1; 737 *reply_len = readlen; 738 739 return 0; 740 } 741 742 743 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) 744 { 745 DWORD len = *reply_len; 746 if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL)) 747 return -1; 748 *reply_len = len; 749 return 0; 750 } 751 752 753 int wpa_ctrl_pending(struct wpa_ctrl *ctrl) 754 { 755 DWORD left; 756 757 if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL)) 758 return -1; 759 return left ? 1 : 0; 760 } 761 762 763 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) 764 { 765 return -1; 766 } 767 768 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 769 770 #endif /* CONFIG_CTRL_IFACE */ 771