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