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