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