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