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