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 (res < 0)
    336 			return res;
    337 		if (FD_ISSET(ctrl->s, &rfds)) {
    338 			res = recv(ctrl->s, reply, *reply_len, 0);
    339 			if (res < 0)
    340 				return res;
    341 			if (res > 0 && reply[0] == '<') {
    342 				/* This is an unsolicited message from
    343 				 * wpa_supplicant, not the reply to the
    344 				 * request. Use msg_cb to report this to the
    345 				 * caller. */
    346 				if (msg_cb) {
    347 					/* Make sure the message is nul
    348 					 * terminated. */
    349 					if ((size_t) res == *reply_len)
    350 						res = (*reply_len) - 1;
    351 					reply[res] = '\0';
    352 					msg_cb(reply, res);
    353 				}
    354 				continue;
    355 			}
    356 			*reply_len = res;
    357 			break;
    358 		} else {
    359 			return -2;
    360 		}
    361 	}
    362 	return 0;
    363 }
    364 #endif /* CTRL_IFACE_SOCKET */
    365 
    366 
    367 static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
    368 {
    369 	char buf[10];
    370 	int ret;
    371 	size_t len = 10;
    372 
    373 	ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
    374 			       buf, &len, NULL);
    375 	if (ret < 0)
    376 		return ret;
    377 	if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0)
    378 		return 0;
    379 	return -1;
    380 }
    381 
    382 
    383 int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
    384 {
    385 	return wpa_ctrl_attach_helper(ctrl, 1);
    386 }
    387 
    388 
    389 int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
    390 {
    391 	return wpa_ctrl_attach_helper(ctrl, 0);
    392 }
    393 
    394 
    395 #ifdef CTRL_IFACE_SOCKET
    396 
    397 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
    398 {
    399 	int res;
    400 
    401 	res = recv(ctrl->s, reply, *reply_len, 0);
    402 	if (res < 0)
    403 		return res;
    404 	*reply_len = res;
    405 	return 0;
    406 }
    407 
    408 
    409 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
    410 {
    411 	struct timeval tv;
    412 	fd_set rfds;
    413 	tv.tv_sec = 0;
    414 	tv.tv_usec = 0;
    415 	FD_ZERO(&rfds);
    416 	FD_SET(ctrl->s, &rfds);
    417 	select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
    418 	return FD_ISSET(ctrl->s, &rfds);
    419 }
    420 
    421 
    422 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
    423 {
    424 	return ctrl->s;
    425 }
    426 
    427 #endif /* CTRL_IFACE_SOCKET */
    428 
    429 
    430 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
    431 
    432 #ifndef WPA_SUPPLICANT_NAMED_PIPE
    433 #define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
    434 #endif
    435 #define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
    436 
    437 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
    438 {
    439 	struct wpa_ctrl *ctrl;
    440 	DWORD mode;
    441 	TCHAR name[256];
    442 	int i, ret;
    443 
    444 	ctrl = os_malloc(sizeof(*ctrl));
    445 	if (ctrl == NULL)
    446 		return NULL;
    447 	os_memset(ctrl, 0, sizeof(*ctrl));
    448 
    449 #ifdef UNICODE
    450 	if (ctrl_path == NULL)
    451 		ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX);
    452 	else
    453 		ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
    454 				 ctrl_path);
    455 #else /* UNICODE */
    456 	if (ctrl_path == NULL)
    457 		ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX);
    458 	else
    459 		ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
    460 				  ctrl_path);
    461 #endif /* UNICODE */
    462 	if (ret < 0 || ret >= 256) {
    463 		os_free(ctrl);
    464 		return NULL;
    465 	}
    466 
    467 	for (i = 0; i < 10; i++) {
    468 		ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
    469 					NULL, OPEN_EXISTING, 0, NULL);
    470 		/*
    471 		 * Current named pipe server side in wpa_supplicant is
    472 		 * re-opening the pipe for new clients only after the previous
    473 		 * one is taken into use. This leaves a small window for race
    474 		 * conditions when two connections are being opened at almost
    475 		 * the same time. Retry if that was the case.
    476 		 */
    477 		if (ctrl->pipe != INVALID_HANDLE_VALUE ||
    478 		    GetLastError() != ERROR_PIPE_BUSY)
    479 			break;
    480 		WaitNamedPipe(name, 1000);
    481 	}
    482 	if (ctrl->pipe == INVALID_HANDLE_VALUE) {
    483 		os_free(ctrl);
    484 		return NULL;
    485 	}
    486 
    487 	mode = PIPE_READMODE_MESSAGE;
    488 	if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
    489 		CloseHandle(ctrl->pipe);
    490 		os_free(ctrl);
    491 		return NULL;
    492 	}
    493 
    494 	return ctrl;
    495 }
    496 
    497 
    498 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
    499 {
    500 	CloseHandle(ctrl->pipe);
    501 	os_free(ctrl);
    502 }
    503 
    504 
    505 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
    506 		     char *reply, size_t *reply_len,
    507 		     void (*msg_cb)(char *msg, size_t len))
    508 {
    509 	DWORD written;
    510 	DWORD readlen = *reply_len;
    511 
    512 	if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL))
    513 		return -1;
    514 
    515 	if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL))
    516 		return -1;
    517 	*reply_len = readlen;
    518 
    519 	return 0;
    520 }
    521 
    522 
    523 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
    524 {
    525 	DWORD len = *reply_len;
    526 	if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL))
    527 		return -1;
    528 	*reply_len = len;
    529 	return 0;
    530 }
    531 
    532 
    533 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
    534 {
    535 	DWORD left;
    536 
    537 	if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL))
    538 		return -1;
    539 	return left ? 1 : 0;
    540 }
    541 
    542 
    543 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
    544 {
    545 	return ctrl->pipe;
    546 }
    547 
    548 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
    549 
    550 #endif /* CONFIG_CTRL_IFACE */
    551