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