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