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