Home | History | Annotate | Download | only in common
      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 #include <unistd.h>
     16 #include <fcntl.h>
     17 #endif /* CONFIG_CTRL_IFACE_UNIX */
     18 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
     19 #include <netdb.h>
     20 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
     21 
     22 #ifdef ANDROID
     23 #include <dirent.h>
     24 #include <cutils/sockets.h>
     25 #include "private/android_filesystem_config.h"
     26 #endif /* ANDROID */
     27 
     28 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
     29 #include <net/if.h>
     30 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
     31 
     32 #include "wpa_ctrl.h"
     33 #include "common.h"
     34 
     35 
     36 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
     37 #define CTRL_IFACE_SOCKET
     38 #endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
     39 
     40 
     41 /**
     42  * struct wpa_ctrl - Internal structure for control interface library
     43  *
     44  * This structure is used by the wpa_supplicant/hostapd control interface
     45  * library to store internal data. Programs using the library should not touch
     46  * this data directly. They can only use the pointer to the data structure as
     47  * an identifier for the control interface connection and use this as one of
     48  * the arguments for most of the control interface library functions.
     49  */
     50 struct wpa_ctrl {
     51 #ifdef CONFIG_CTRL_IFACE_UDP
     52 	int s;
     53 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
     54 	struct sockaddr_in6 local;
     55 	struct sockaddr_in6 dest;
     56 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
     57 	struct sockaddr_in local;
     58 	struct sockaddr_in dest;
     59 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
     60 	char *cookie;
     61 	char *remote_ifname;
     62 	char *remote_ip;
     63 #endif /* CONFIG_CTRL_IFACE_UDP */
     64 #ifdef CONFIG_CTRL_IFACE_UNIX
     65 	int s;
     66 	struct sockaddr_un local;
     67 	struct sockaddr_un dest;
     68 #endif /* CONFIG_CTRL_IFACE_UNIX */
     69 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
     70 	HANDLE pipe;
     71 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
     72 };
     73 
     74 
     75 #ifdef CONFIG_CTRL_IFACE_UNIX
     76 
     77 #ifndef CONFIG_CTRL_IFACE_CLIENT_DIR
     78 #define CONFIG_CTRL_IFACE_CLIENT_DIR "/tmp"
     79 #endif /* CONFIG_CTRL_IFACE_CLIENT_DIR */
     80 #ifndef CONFIG_CTRL_IFACE_CLIENT_PREFIX
     81 #define CONFIG_CTRL_IFACE_CLIENT_PREFIX "wpa_ctrl_"
     82 #endif /* CONFIG_CTRL_IFACE_CLIENT_PREFIX */
     83 
     84 
     85 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
     86 {
     87 	struct wpa_ctrl *ctrl;
     88 	static int counter = 0;
     89 	int ret;
     90 	size_t res;
     91 	int tries = 0;
     92 	int flags;
     93 
     94 	if (ctrl_path == NULL)
     95 		return NULL;
     96 
     97 	ctrl = os_malloc(sizeof(*ctrl));
     98 	if (ctrl == NULL)
     99 		return NULL;
    100 	os_memset(ctrl, 0, sizeof(*ctrl));
    101 
    102 	ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
    103 	if (ctrl->s < 0) {
    104 		os_free(ctrl);
    105 		return NULL;
    106 	}
    107 
    108 	ctrl->local.sun_family = AF_UNIX;
    109 	counter++;
    110 try_again:
    111 	ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
    112 			  CONFIG_CTRL_IFACE_CLIENT_DIR "/"
    113 			  CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d",
    114 			  (int) getpid(), counter);
    115 	if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
    116 		close(ctrl->s);
    117 		os_free(ctrl);
    118 		return NULL;
    119 	}
    120 	tries++;
    121 	if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
    122 		    sizeof(ctrl->local)) < 0) {
    123 		if (errno == EADDRINUSE && tries < 2) {
    124 			/*
    125 			 * getpid() returns unique identifier for this instance
    126 			 * of wpa_ctrl, so the existing socket file must have
    127 			 * been left by unclean termination of an earlier run.
    128 			 * Remove the file and try again.
    129 			 */
    130 			unlink(ctrl->local.sun_path);
    131 			goto try_again;
    132 		}
    133 		close(ctrl->s);
    134 		os_free(ctrl);
    135 		return NULL;
    136 	}
    137 
    138 #ifdef ANDROID
    139 	chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
    140 	chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
    141 
    142 	if (os_strncmp(ctrl_path, "@android:", 9) == 0) {
    143 		if (socket_local_client_connect(
    144 			    ctrl->s, ctrl_path + 9,
    145 			    ANDROID_SOCKET_NAMESPACE_RESERVED,
    146 			    SOCK_DGRAM) < 0) {
    147 			close(ctrl->s);
    148 			unlink(ctrl->local.sun_path);
    149 			os_free(ctrl);
    150 			return NULL;
    151 		}
    152 		return ctrl;
    153 	}
    154 
    155 	/*
    156 	 * If the ctrl_path isn't an absolute pathname, assume that
    157 	 * it's the name of a socket in the Android reserved namespace.
    158 	 * Otherwise, it's a normal UNIX domain socket appearing in the
    159 	 * filesystem.
    160 	 */
    161 	if (*ctrl_path != '/') {
    162 		char buf[21];
    163 		os_snprintf(buf, sizeof(buf), "wpa_%s", ctrl_path);
    164 		if (socket_local_client_connect(
    165 			    ctrl->s, buf,
    166 			    ANDROID_SOCKET_NAMESPACE_RESERVED,
    167 			    SOCK_DGRAM) < 0) {
    168 			close(ctrl->s);
    169 			unlink(ctrl->local.sun_path);
    170 			os_free(ctrl);
    171 			return NULL;
    172 		}
    173 		return ctrl;
    174 	}
    175 #endif /* ANDROID */
    176 
    177 	ctrl->dest.sun_family = AF_UNIX;
    178 	if (os_strncmp(ctrl_path, "@abstract:", 10) == 0) {
    179 		ctrl->dest.sun_path[0] = '\0';
    180 		os_strlcpy(ctrl->dest.sun_path + 1, ctrl_path + 10,
    181 			   sizeof(ctrl->dest.sun_path) - 1);
    182 	} else {
    183 		res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
    184 				 sizeof(ctrl->dest.sun_path));
    185 		if (res >= sizeof(ctrl->dest.sun_path)) {
    186 			close(ctrl->s);
    187 			os_free(ctrl);
    188 			return NULL;
    189 		}
    190 	}
    191 	if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
    192 		    sizeof(ctrl->dest)) < 0) {
    193 		close(ctrl->s);
    194 		unlink(ctrl->local.sun_path);
    195 		os_free(ctrl);
    196 		return NULL;
    197 	}
    198 
    199 	/*
    200 	 * Make socket non-blocking so that we don't hang forever if
    201 	 * target dies unexpectedly.
    202 	 */
    203 	flags = fcntl(ctrl->s, F_GETFL);
    204 	if (flags >= 0) {
    205 		flags |= O_NONBLOCK;
    206 		if (fcntl(ctrl->s, F_SETFL, flags) < 0) {
    207 			perror("fcntl(ctrl->s, O_NONBLOCK)");
    208 			/* Not fatal, continue on.*/
    209 		}
    210 	}
    211 
    212 	return ctrl;
    213 }
    214 
    215 
    216 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
    217 {
    218 	if (ctrl == NULL)
    219 		return;
    220 	unlink(ctrl->local.sun_path);
    221 	if (ctrl->s >= 0)
    222 		close(ctrl->s);
    223 	os_free(ctrl);
    224 }
    225 
    226 
    227 #ifdef ANDROID
    228 /**
    229  * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
    230  * may be left over from clients that were previously connected to
    231  * wpa_supplicant. This keeps these files from being orphaned in the
    232  * event of crashes that prevented them from being removed as part
    233  * of the normal orderly shutdown.
    234  */
    235 void wpa_ctrl_cleanup(void)
    236 {
    237 	DIR *dir;
    238 	struct dirent entry;
    239 	struct dirent *result;
    240 	size_t dirnamelen;
    241 	size_t maxcopy;
    242 	char pathname[PATH_MAX];
    243 	char *namep;
    244 
    245 	if ((dir = opendir(CONFIG_CTRL_IFACE_CLIENT_DIR)) == NULL)
    246 		return;
    247 
    248 	dirnamelen = (size_t) os_snprintf(pathname, sizeof(pathname), "%s/",
    249 					  CONFIG_CTRL_IFACE_CLIENT_DIR);
    250 	if (dirnamelen >= sizeof(pathname)) {
    251 		closedir(dir);
    252 		return;
    253 	}
    254 	namep = pathname + dirnamelen;
    255 	maxcopy = PATH_MAX - dirnamelen;
    256 	while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
    257 		if (os_strlcpy(namep, entry.d_name, maxcopy) < maxcopy)
    258 			unlink(pathname);
    259 	}
    260 	closedir(dir);
    261 }
    262 #endif /* ANDROID */
    263 
    264 #else /* CONFIG_CTRL_IFACE_UNIX */
    265 
    266 #ifdef ANDROID
    267 void wpa_ctrl_cleanup(void)
    268 {
    269 }
    270 #endif /* ANDROID */
    271 
    272 #endif /* CONFIG_CTRL_IFACE_UNIX */
    273 
    274 
    275 #ifdef CONFIG_CTRL_IFACE_UDP
    276 
    277 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
    278 {
    279 	struct wpa_ctrl *ctrl;
    280 	char buf[128];
    281 	size_t len;
    282 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
    283 	struct hostent *h;
    284 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    285 
    286 	ctrl = os_malloc(sizeof(*ctrl));
    287 	if (ctrl == NULL)
    288 		return NULL;
    289 	os_memset(ctrl, 0, sizeof(*ctrl));
    290 
    291 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    292 	ctrl->s = socket(PF_INET6, SOCK_DGRAM, 0);
    293 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    294 	ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
    295 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    296 	if (ctrl->s < 0) {
    297 		perror("socket");
    298 		os_free(ctrl);
    299 		return NULL;
    300 	}
    301 
    302 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    303 	ctrl->local.sin6_family = AF_INET6;
    304 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
    305 	ctrl->local.sin6_addr = in6addr_any;
    306 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    307 	inet_pton(AF_INET6, "::1", &ctrl->local.sin6_addr);
    308 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    309 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    310 	ctrl->local.sin_family = AF_INET;
    311 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
    312 	ctrl->local.sin_addr.s_addr = INADDR_ANY;
    313 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    314 	ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
    315 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    316 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    317 
    318 	if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
    319 		 sizeof(ctrl->local)) < 0) {
    320 		close(ctrl->s);
    321 		os_free(ctrl);
    322 		return NULL;
    323 	}
    324 
    325 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    326 	ctrl->dest.sin6_family = AF_INET6;
    327 	inet_pton(AF_INET6, "::1", &ctrl->dest.sin6_addr);
    328 	ctrl->dest.sin6_port = htons(WPA_CTRL_IFACE_PORT);
    329 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    330 	ctrl->dest.sin_family = AF_INET;
    331 	ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
    332 	ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
    333 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    334 
    335 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
    336 	if (ctrl_path) {
    337 		char *port, *name;
    338 		int port_id;
    339 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    340 		char *scope;
    341 		int scope_id = 0;
    342 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    343 
    344 		name = os_strdup(ctrl_path);
    345 		if (name == NULL) {
    346 			close(ctrl->s);
    347 			os_free(ctrl);
    348 			return NULL;
    349 		}
    350 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    351 		port = os_strchr(name, ',');
    352 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    353 		port = os_strchr(name, ':');
    354 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    355 
    356 		if (port) {
    357 			port_id = atoi(&port[1]);
    358 			port[0] = '\0';
    359 		} else
    360 			port_id = WPA_CTRL_IFACE_PORT;
    361 
    362 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    363 		scope = os_strchr(name, '%');
    364 		if (scope) {
    365 			scope_id = if_nametoindex(&scope[1]);
    366 			scope[0] = '\0';
    367 		}
    368 		h = gethostbyname2(name, AF_INET6);
    369 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    370 		h = gethostbyname(name);
    371 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    372 		ctrl->remote_ip = os_strdup(name);
    373 		os_free(name);
    374 		if (h == NULL) {
    375 			perror("gethostbyname");
    376 			close(ctrl->s);
    377 			os_free(ctrl->remote_ip);
    378 			os_free(ctrl);
    379 			return NULL;
    380 		}
    381 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    382 		ctrl->dest.sin6_scope_id = scope_id;
    383 		ctrl->dest.sin6_port = htons(port_id);
    384 		os_memcpy(&ctrl->dest.sin6_addr, h->h_addr, h->h_length);
    385 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    386 		ctrl->dest.sin_port = htons(port_id);
    387 		os_memcpy(&ctrl->dest.sin_addr.s_addr, h->h_addr, h->h_length);
    388 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    389 	} else
    390 		ctrl->remote_ip = os_strdup("localhost");
    391 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    392 
    393 	if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
    394 		    sizeof(ctrl->dest)) < 0) {
    395 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    396 		char addr[INET6_ADDRSTRLEN];
    397 		wpa_printf(MSG_ERROR, "connect(%s:%d) failed: %s",
    398 			   inet_ntop(AF_INET6, &ctrl->dest.sin6_addr, addr,
    399 				     sizeof(ctrl->dest)),
    400 			   ntohs(ctrl->dest.sin6_port),
    401 			   strerror(errno));
    402 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    403 		wpa_printf(MSG_ERROR, "connect(%s:%d) failed: %s",
    404 			   inet_ntoa(ctrl->dest.sin_addr),
    405 			   ntohs(ctrl->dest.sin_port),
    406 			   strerror(errno));
    407 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    408 		close(ctrl->s);
    409 		os_free(ctrl->remote_ip);
    410 		os_free(ctrl);
    411 		return NULL;
    412 	}
    413 
    414 	len = sizeof(buf) - 1;
    415 	if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
    416 		buf[len] = '\0';
    417 		ctrl->cookie = os_strdup(buf);
    418 	}
    419 
    420 	if (wpa_ctrl_request(ctrl, "IFNAME", 6, buf, &len, NULL) == 0) {
    421 		buf[len] = '\0';
    422 		ctrl->remote_ifname = os_strdup(buf);
    423 	}
    424 
    425 	return ctrl;
    426 }
    427 
    428 
    429 char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl)
    430 {
    431 #define WPA_CTRL_MAX_PS_NAME 100
    432 	static char ps[WPA_CTRL_MAX_PS_NAME] = {};
    433 	os_snprintf(ps, WPA_CTRL_MAX_PS_NAME, "%s/%s",
    434 		    ctrl->remote_ip, ctrl->remote_ifname);
    435 	return ps;
    436 }
    437 
    438 
    439 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
    440 {
    441 	close(ctrl->s);
    442 	os_free(ctrl->cookie);
    443 	os_free(ctrl->remote_ifname);
    444 	os_free(ctrl->remote_ip);
    445 	os_free(ctrl);
    446 }
    447 
    448 #endif /* CONFIG_CTRL_IFACE_UDP */
    449 
    450 
    451 #ifdef CTRL_IFACE_SOCKET
    452 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
    453 		     char *reply, size_t *reply_len,
    454 		     void (*msg_cb)(char *msg, size_t len))
    455 {
    456 	struct timeval tv;
    457 	struct os_reltime started_at;
    458 	int res;
    459 	fd_set rfds;
    460 	const char *_cmd;
    461 	char *cmd_buf = NULL;
    462 	size_t _cmd_len;
    463 
    464 #ifdef CONFIG_CTRL_IFACE_UDP
    465 	if (ctrl->cookie) {
    466 		char *pos;
    467 		_cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len;
    468 		cmd_buf = os_malloc(_cmd_len);
    469 		if (cmd_buf == NULL)
    470 			return -1;
    471 		_cmd = cmd_buf;
    472 		pos = cmd_buf;
    473 		os_strlcpy(pos, ctrl->cookie, _cmd_len);
    474 		pos += os_strlen(ctrl->cookie);
    475 		*pos++ = ' ';
    476 		os_memcpy(pos, cmd, cmd_len);
    477 	} else
    478 #endif /* CONFIG_CTRL_IFACE_UDP */
    479 	{
    480 		_cmd = cmd;
    481 		_cmd_len = cmd_len;
    482 	}
    483 
    484 	errno = 0;
    485 	started_at.sec = 0;
    486 	started_at.usec = 0;
    487 retry_send:
    488 	if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
    489 		if (errno == EAGAIN || errno == EBUSY || errno == EWOULDBLOCK)
    490 		{
    491 			/*
    492 			 * Must be a non-blocking socket... Try for a bit
    493 			 * longer before giving up.
    494 			 */
    495 			if (started_at.sec == 0)
    496 				os_get_reltime(&started_at);
    497 			else {
    498 				struct os_reltime n;
    499 				os_get_reltime(&n);
    500 				/* Try for a few seconds. */
    501 				if (os_reltime_expired(&n, &started_at, 5))
    502 					goto send_err;
    503 			}
    504 			os_sleep(1, 0);
    505 			goto retry_send;
    506 		}
    507 	send_err:
    508 		os_free(cmd_buf);
    509 		return -1;
    510 	}
    511 	os_free(cmd_buf);
    512 
    513 	for (;;) {
    514 		tv.tv_sec = 10;
    515 		tv.tv_usec = 0;
    516 		FD_ZERO(&rfds);
    517 		FD_SET(ctrl->s, &rfds);
    518 		res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
    519 		if (res < 0)
    520 			return res;
    521 		if (FD_ISSET(ctrl->s, &rfds)) {
    522 			res = recv(ctrl->s, reply, *reply_len, 0);
    523 			if (res < 0)
    524 				return res;
    525 			if (res > 0 && reply[0] == '<') {
    526 				/* This is an unsolicited message from
    527 				 * wpa_supplicant, not the reply to the
    528 				 * request. Use msg_cb to report this to the
    529 				 * caller. */
    530 				if (msg_cb) {
    531 					/* Make sure the message is nul
    532 					 * terminated. */
    533 					if ((size_t) res == *reply_len)
    534 						res = (*reply_len) - 1;
    535 					reply[res] = '\0';
    536 					msg_cb(reply, res);
    537 				}
    538 				continue;
    539 			}
    540 			*reply_len = res;
    541 			break;
    542 		} else {
    543 			return -2;
    544 		}
    545 	}
    546 	return 0;
    547 }
    548 #endif /* CTRL_IFACE_SOCKET */
    549 
    550 
    551 static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
    552 {
    553 	char buf[10];
    554 	int ret;
    555 	size_t len = 10;
    556 
    557 	ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
    558 			       buf, &len, NULL);
    559 	if (ret < 0)
    560 		return ret;
    561 	if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0)
    562 		return 0;
    563 	return -1;
    564 }
    565 
    566 
    567 int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
    568 {
    569 	return wpa_ctrl_attach_helper(ctrl, 1);
    570 }
    571 
    572 
    573 int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
    574 {
    575 	return wpa_ctrl_attach_helper(ctrl, 0);
    576 }
    577 
    578 
    579 #ifdef CTRL_IFACE_SOCKET
    580 
    581 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
    582 {
    583 	int res;
    584 
    585 	res = recv(ctrl->s, reply, *reply_len, 0);
    586 	if (res < 0)
    587 		return res;
    588 	*reply_len = res;
    589 	return 0;
    590 }
    591 
    592 
    593 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
    594 {
    595 	struct timeval tv;
    596 	fd_set rfds;
    597 	tv.tv_sec = 0;
    598 	tv.tv_usec = 0;
    599 	FD_ZERO(&rfds);
    600 	FD_SET(ctrl->s, &rfds);
    601 	select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
    602 	return FD_ISSET(ctrl->s, &rfds);
    603 }
    604 
    605 
    606 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
    607 {
    608 	return ctrl->s;
    609 }
    610 
    611 #endif /* CTRL_IFACE_SOCKET */
    612 
    613 
    614 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
    615 
    616 #ifndef WPA_SUPPLICANT_NAMED_PIPE
    617 #define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
    618 #endif
    619 #define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
    620 
    621 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
    622 {
    623 	struct wpa_ctrl *ctrl;
    624 	DWORD mode;
    625 	TCHAR name[256];
    626 	int i, ret;
    627 
    628 	ctrl = os_malloc(sizeof(*ctrl));
    629 	if (ctrl == NULL)
    630 		return NULL;
    631 	os_memset(ctrl, 0, sizeof(*ctrl));
    632 
    633 #ifdef UNICODE
    634 	if (ctrl_path == NULL)
    635 		ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX);
    636 	else
    637 		ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
    638 				 ctrl_path);
    639 #else /* UNICODE */
    640 	if (ctrl_path == NULL)
    641 		ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX);
    642 	else
    643 		ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
    644 				  ctrl_path);
    645 #endif /* UNICODE */
    646 	if (ret < 0 || ret >= 256) {
    647 		os_free(ctrl);
    648 		return NULL;
    649 	}
    650 
    651 	for (i = 0; i < 10; i++) {
    652 		ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
    653 					NULL, OPEN_EXISTING, 0, NULL);
    654 		/*
    655 		 * Current named pipe server side in wpa_supplicant is
    656 		 * re-opening the pipe for new clients only after the previous
    657 		 * one is taken into use. This leaves a small window for race
    658 		 * conditions when two connections are being opened at almost
    659 		 * the same time. Retry if that was the case.
    660 		 */
    661 		if (ctrl->pipe != INVALID_HANDLE_VALUE ||
    662 		    GetLastError() != ERROR_PIPE_BUSY)
    663 			break;
    664 		WaitNamedPipe(name, 1000);
    665 	}
    666 	if (ctrl->pipe == INVALID_HANDLE_VALUE) {
    667 		os_free(ctrl);
    668 		return NULL;
    669 	}
    670 
    671 	mode = PIPE_READMODE_MESSAGE;
    672 	if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
    673 		CloseHandle(ctrl->pipe);
    674 		os_free(ctrl);
    675 		return NULL;
    676 	}
    677 
    678 	return ctrl;
    679 }
    680 
    681 
    682 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
    683 {
    684 	CloseHandle(ctrl->pipe);
    685 	os_free(ctrl);
    686 }
    687 
    688 
    689 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
    690 		     char *reply, size_t *reply_len,
    691 		     void (*msg_cb)(char *msg, size_t len))
    692 {
    693 	DWORD written;
    694 	DWORD readlen = *reply_len;
    695 
    696 	if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL))
    697 		return -1;
    698 
    699 	if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL))
    700 		return -1;
    701 	*reply_len = readlen;
    702 
    703 	return 0;
    704 }
    705 
    706 
    707 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
    708 {
    709 	DWORD len = *reply_len;
    710 	if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL))
    711 		return -1;
    712 	*reply_len = len;
    713 	return 0;
    714 }
    715 
    716 
    717 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
    718 {
    719 	DWORD left;
    720 
    721 	if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL))
    722 		return -1;
    723 	return left ? 1 : 0;
    724 }
    725 
    726 
    727 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
    728 {
    729 	return -1;
    730 }
    731 
    732 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
    733 
    734 #endif /* CONFIG_CTRL_IFACE */
    735