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 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