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 <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 */ 46struct 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 76struct 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++; 98try_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 184void 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 */ 203void 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 239void 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 249struct 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 347char * 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 357void 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 370int 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; 405retry_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 469static 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 485int wpa_ctrl_attach(struct wpa_ctrl *ctrl) 486{ 487 return wpa_ctrl_attach_helper(ctrl, 1); 488} 489 490 491int 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 499int 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 511int 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 524int 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 539struct 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 600void wpa_ctrl_close(struct wpa_ctrl *ctrl) 601{ 602 CloseHandle(ctrl->pipe); 603 os_free(ctrl); 604} 605 606 607int 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 625int 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 635int 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 645int 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