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