1/* 2 * wpa_supplicant/hostapd control interface library 3 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15#include "includes.h" 16 17#ifdef CONFIG_CTRL_IFACE 18 19#ifdef CONFIG_CTRL_IFACE_UNIX 20#include <sys/un.h> 21#endif /* CONFIG_CTRL_IFACE_UNIX */ 22 23#ifdef ANDROID 24#include <dirent.h> 25#include <linux/limits.h> 26#include <cutils/sockets.h> 27#include <cutils/memory.h> 28#include "private/android_filesystem_config.h" 29#endif 30 31#include "wpa_ctrl.h" 32#include "common.h" 33 34 35#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) 36#define CTRL_IFACE_SOCKET 37#ifdef ANDROID 38static const char *local_socket_dir = "/data/misc/wifi/sockets"; 39static const char *local_socket_prefix = "wpa_ctrl_"; 40#endif /* ANDROID */ 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 */ 53struct wpa_ctrl { 54#ifdef CONFIG_CTRL_IFACE_UDP 55 int s; 56 struct sockaddr_in local; 57 struct sockaddr_in dest; 58 char *cookie; 59#endif /* CONFIG_CTRL_IFACE_UDP */ 60#ifdef CONFIG_CTRL_IFACE_UNIX 61 int s; 62 struct sockaddr_un local; 63 struct sockaddr_un dest; 64#endif /* CONFIG_CTRL_IFACE_UNIX */ 65#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 66 HANDLE pipe; 67#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 68}; 69 70 71#ifdef CONFIG_CTRL_IFACE_UNIX 72 73struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) 74{ 75 struct wpa_ctrl *ctrl; 76 static int counter = 0; 77 int ret; 78 size_t res; 79 int tries = 0; 80 81 ctrl = os_malloc(sizeof(*ctrl)); 82 if (ctrl == NULL) 83 return NULL; 84 os_memset(ctrl, 0, sizeof(*ctrl)); 85 86 ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0); 87 if (ctrl->s < 0) { 88 os_free(ctrl); 89 return NULL; 90 } 91 92 ctrl->local.sun_family = AF_UNIX; 93 counter++; 94try_again: 95 ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), 96#ifdef ANDROID 97 "%s/%s%d-%d", local_socket_dir, local_socket_prefix, 98 getpid(), counter); 99#else /* ANDROID */ 100 "/tmp/wpa_ctrl_%d-%d", getpid(), counter); 101#endif 102 if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) { 103 close(ctrl->s); 104 os_free(ctrl); 105 return NULL; 106 } 107 tries++; 108 if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, 109 sizeof(ctrl->local)) < 0) { 110 if (errno == EADDRINUSE && tries < 2) { 111 /* 112 * getpid() returns unique identifier for this instance 113 * of wpa_ctrl, so the existing socket file must have 114 * been left by unclean termination of an earlier run. 115 * Remove the file and try again. 116 */ 117 unlink(ctrl->local.sun_path); 118 goto try_again; 119 } 120 close(ctrl->s); 121 os_free(ctrl); 122 return NULL; 123 } 124 125#ifdef ANDROID 126 chmod(ctrl->local.sun_path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); 127 chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI); 128 /* 129 * If the ctrl_path isn't an absolute pathname, assume that 130 * it's the name of a socket in the Android reserved namespace. 131 * Otherwise, it's a normal UNIX domain socket appearing in the 132 * filesystem. 133 */ 134 if (ctrl_path != NULL && *ctrl_path != '/') { 135 os_snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "wpa_%s", 136 ctrl_path); 137 if (socket_local_client_connect(ctrl->s, 138 ctrl->dest.sun_path, 139 ANDROID_SOCKET_NAMESPACE_RESERVED, 140 SOCK_DGRAM) < 0) { 141 close(ctrl->s); 142 unlink(ctrl->local.sun_path); 143 os_free(ctrl); 144 return NULL; 145 } 146 return ctrl; 147 } 148#endif 149 ctrl->dest.sun_family = AF_UNIX; 150 res = os_strlcpy(ctrl->dest.sun_path, ctrl_path, 151 sizeof(ctrl->dest.sun_path)); 152 if (res >= sizeof(ctrl->dest.sun_path)) { 153 close(ctrl->s); 154 os_free(ctrl); 155 return NULL; 156 } 157 if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, 158 sizeof(ctrl->dest)) < 0) { 159 close(ctrl->s); 160 unlink(ctrl->local.sun_path); 161 os_free(ctrl); 162 return NULL; 163 } 164 165 return ctrl; 166} 167 168 169void wpa_ctrl_close(struct wpa_ctrl *ctrl) 170{ 171 if (ctrl == NULL) 172 return; 173 unlink(ctrl->local.sun_path); 174 if (ctrl->s >= 0) 175 close(ctrl->s); 176 os_free(ctrl); 177} 178 179#ifdef ANDROID 180/** 181 * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that 182 * may be left over from clients that were previously connected to 183 * wpa_supplicant. This keeps these files from being orphaned in the 184 * event of crashes that prevented them from being removed as part 185 * of the normal orderly shutdown. 186 */ 187void wpa_ctrl_cleanup(void) 188{ 189 DIR *dir; 190 struct dirent entry; 191 struct dirent *result; 192 size_t dirnamelen; 193 int prefixlen = strlen(local_socket_prefix); 194 size_t maxcopy; 195 char pathname[PATH_MAX]; 196 char *namep; 197 198 if ((dir = opendir(local_socket_dir)) == NULL) 199 return; 200 201 dirnamelen = (size_t)snprintf(pathname, sizeof(pathname), "%s/", local_socket_dir); 202 if (dirnamelen >= sizeof(pathname)) { 203 closedir(dir); 204 return; 205 } 206 namep = pathname + dirnamelen; 207 maxcopy = PATH_MAX-dirnamelen; 208 while (readdir_r(dir, &entry, &result) == 0 && result != NULL) { 209 if (strncmp(entry.d_name, local_socket_prefix, prefixlen) == 0) { 210 if (strlcpy(namep, entry.d_name, maxcopy) < maxcopy) { 211 unlink(pathname); 212 } 213 } 214 } 215 closedir(dir); 216} 217#endif /* ANDROID */ 218 219#else /* CONFIG_CTRL_IFACE_UNIX */ 220#ifdef ANDROID 221void wpa_ctrl_cleanup(void) 222{ 223} 224#endif /* ANDROID */ 225#endif /* CONFIG_CTRL_IFACE_UNIX */ 226 227#ifdef CONFIG_CTRL_IFACE_UDP 228 229struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) 230{ 231 struct wpa_ctrl *ctrl; 232 char buf[128]; 233 size_t len; 234 235 ctrl = os_malloc(sizeof(*ctrl)); 236 if (ctrl == NULL) 237 return NULL; 238 os_memset(ctrl, 0, sizeof(*ctrl)); 239 240 ctrl->s = socket(PF_INET, SOCK_DGRAM, 0); 241 if (ctrl->s < 0) { 242 perror("socket"); 243 os_free(ctrl); 244 return NULL; 245 } 246 247 ctrl->local.sin_family = AF_INET; 248 ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1); 249 if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, 250 sizeof(ctrl->local)) < 0) { 251 close(ctrl->s); 252 os_free(ctrl); 253 return NULL; 254 } 255 256 ctrl->dest.sin_family = AF_INET; 257 ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1); 258 ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT); 259 if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, 260 sizeof(ctrl->dest)) < 0) { 261 perror("connect"); 262 close(ctrl->s); 263 os_free(ctrl); 264 return NULL; 265 } 266 267 len = sizeof(buf) - 1; 268 if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) { 269 buf[len] = '\0'; 270 ctrl->cookie = os_strdup(buf); 271 } 272 273 return ctrl; 274} 275 276 277void wpa_ctrl_close(struct wpa_ctrl *ctrl) 278{ 279 close(ctrl->s); 280 os_free(ctrl->cookie); 281 os_free(ctrl); 282} 283 284#endif /* CONFIG_CTRL_IFACE_UDP */ 285 286 287#ifdef CTRL_IFACE_SOCKET 288int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, 289 char *reply, size_t *reply_len, 290 void (*msg_cb)(char *msg, size_t len)) 291{ 292 struct timeval tv; 293 int res; 294 fd_set rfds; 295 const char *_cmd; 296 char *cmd_buf = NULL; 297 size_t _cmd_len; 298 299#ifdef CONFIG_CTRL_IFACE_UDP 300 if (ctrl->cookie) { 301 char *pos; 302 _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len; 303 cmd_buf = os_malloc(_cmd_len); 304 if (cmd_buf == NULL) 305 return -1; 306 _cmd = cmd_buf; 307 pos = cmd_buf; 308 os_strlcpy(pos, ctrl->cookie, _cmd_len); 309 pos += os_strlen(ctrl->cookie); 310 *pos++ = ' '; 311 os_memcpy(pos, cmd, cmd_len); 312 } else 313#endif /* CONFIG_CTRL_IFACE_UDP */ 314 { 315 _cmd = cmd; 316 _cmd_len = cmd_len; 317 } 318 319 if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) { 320 os_free(cmd_buf); 321 return -1; 322 } 323 os_free(cmd_buf); 324 325 for (;;) { 326#ifdef ANDROID 327 tv.tv_sec = 10; 328#else 329 tv.tv_sec = 2; 330#endif 331 tv.tv_usec = 0; 332 FD_ZERO(&rfds); 333 FD_SET(ctrl->s, &rfds); 334 res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv); 335 if (FD_ISSET(ctrl->s, &rfds)) { 336 res = recv(ctrl->s, reply, *reply_len, 0); 337 if (res < 0) 338 return res; 339 if (res > 0 && reply[0] == '<') { 340 /* This is an unsolicited message from 341 * wpa_supplicant, not the reply to the 342 * request. Use msg_cb to report this to the 343 * caller. */ 344 if (msg_cb) { 345 /* Make sure the message is nul 346 * terminated. */ 347 if ((size_t) res == *reply_len) 348 res = (*reply_len) - 1; 349 reply[res] = '\0'; 350 msg_cb(reply, res); 351 } 352 continue; 353 } 354 *reply_len = res; 355 break; 356 } else { 357 return -2; 358 } 359 } 360 return 0; 361} 362#endif /* CTRL_IFACE_SOCKET */ 363 364 365static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach) 366{ 367 char buf[10]; 368 int ret; 369 size_t len = 10; 370 371 ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6, 372 buf, &len, NULL); 373 if (ret < 0) 374 return ret; 375 if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0) 376 return 0; 377 return -1; 378} 379 380 381int wpa_ctrl_attach(struct wpa_ctrl *ctrl) 382{ 383 return wpa_ctrl_attach_helper(ctrl, 1); 384} 385 386 387int wpa_ctrl_detach(struct wpa_ctrl *ctrl) 388{ 389 return wpa_ctrl_attach_helper(ctrl, 0); 390} 391 392 393#ifdef CTRL_IFACE_SOCKET 394 395int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) 396{ 397 int res; 398 399 res = recv(ctrl->s, reply, *reply_len, 0); 400 if (res < 0) 401 return res; 402 *reply_len = res; 403 return 0; 404} 405 406 407int wpa_ctrl_pending(struct wpa_ctrl *ctrl) 408{ 409 struct timeval tv; 410 fd_set rfds; 411 tv.tv_sec = 0; 412 tv.tv_usec = 0; 413 FD_ZERO(&rfds); 414 FD_SET(ctrl->s, &rfds); 415 select(ctrl->s + 1, &rfds, NULL, NULL, &tv); 416 return FD_ISSET(ctrl->s, &rfds); 417} 418 419 420int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) 421{ 422 return ctrl->s; 423} 424 425#endif /* CTRL_IFACE_SOCKET */ 426 427 428#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 429 430#ifndef WPA_SUPPLICANT_NAMED_PIPE 431#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant" 432#endif 433#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE) 434 435struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) 436{ 437 struct wpa_ctrl *ctrl; 438 DWORD mode; 439 TCHAR name[256]; 440 int i, ret; 441 442 ctrl = os_malloc(sizeof(*ctrl)); 443 if (ctrl == NULL) 444 return NULL; 445 os_memset(ctrl, 0, sizeof(*ctrl)); 446 447#ifdef UNICODE 448 if (ctrl_path == NULL) 449 ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX); 450 else 451 ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"), 452 ctrl_path); 453#else /* UNICODE */ 454 if (ctrl_path == NULL) 455 ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX); 456 else 457 ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s", 458 ctrl_path); 459#endif /* UNICODE */ 460 if (ret < 0 || ret >= 256) { 461 os_free(ctrl); 462 return NULL; 463 } 464 465 for (i = 0; i < 10; i++) { 466 ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, 467 NULL, OPEN_EXISTING, 0, NULL); 468 /* 469 * Current named pipe server side in wpa_supplicant is 470 * re-opening the pipe for new clients only after the previous 471 * one is taken into use. This leaves a small window for race 472 * conditions when two connections are being opened at almost 473 * the same time. Retry if that was the case. 474 */ 475 if (ctrl->pipe != INVALID_HANDLE_VALUE || 476 GetLastError() != ERROR_PIPE_BUSY) 477 break; 478 WaitNamedPipe(name, 1000); 479 } 480 if (ctrl->pipe == INVALID_HANDLE_VALUE) { 481 os_free(ctrl); 482 return NULL; 483 } 484 485 mode = PIPE_READMODE_MESSAGE; 486 if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) { 487 CloseHandle(ctrl->pipe); 488 os_free(ctrl); 489 return NULL; 490 } 491 492 return ctrl; 493} 494 495 496void wpa_ctrl_close(struct wpa_ctrl *ctrl) 497{ 498 CloseHandle(ctrl->pipe); 499 os_free(ctrl); 500} 501 502 503int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, 504 char *reply, size_t *reply_len, 505 void (*msg_cb)(char *msg, size_t len)) 506{ 507 DWORD written; 508 DWORD readlen = *reply_len; 509 510 if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL)) 511 return -1; 512 513 if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL)) 514 return -1; 515 *reply_len = readlen; 516 517 return 0; 518} 519 520 521int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) 522{ 523 DWORD len = *reply_len; 524 if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL)) 525 return -1; 526 *reply_len = len; 527 return 0; 528} 529 530 531int wpa_ctrl_pending(struct wpa_ctrl *ctrl) 532{ 533 DWORD left; 534 535 if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL)) 536 return -1; 537 return left ? 1 : 0; 538} 539 540 541int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) 542{ 543 return ctrl->pipe; 544} 545 546#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 547 548#endif /* CONFIG_CTRL_IFACE */ 549