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