2 * wpa_supplicant/hostapd control interface library
3 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
11 #ifdef CONFIG_CTRL_IFACE
13 #ifdef CONFIG_CTRL_IFACE_UNIX
19 #endif /* CONFIG_CTRL_IFACE_UNIX */
20 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
22 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
27 #include <cutils/sockets.h>
28 #include "private/android_filesystem_config.h"
31 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
33 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
39 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
40 #define CTRL_IFACE_SOCKET
41 #endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
45 * struct wpa_ctrl - Internal structure for control interface library
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.
54 #ifdef CONFIG_CTRL_IFACE_UDP
56 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
57 struct sockaddr_in6 local
;
58 struct sockaddr_in6 dest
;
59 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
60 struct sockaddr_in local
;
61 struct sockaddr_in dest
;
62 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
66 #endif /* CONFIG_CTRL_IFACE_UDP */
67 #ifdef CONFIG_CTRL_IFACE_UNIX
69 struct sockaddr_un local
;
70 struct sockaddr_un dest
;
71 #endif /* CONFIG_CTRL_IFACE_UNIX */
72 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
74 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
78 #ifdef CONFIG_CTRL_IFACE_UNIX
80 #ifndef CONFIG_CTRL_IFACE_CLIENT_DIR
81 #define CONFIG_CTRL_IFACE_CLIENT_DIR "/tmp"
82 #endif /* CONFIG_CTRL_IFACE_CLIENT_DIR */
83 #ifndef CONFIG_CTRL_IFACE_CLIENT_PREFIX
84 #define CONFIG_CTRL_IFACE_CLIENT_PREFIX "wpa_ctrl_"
85 #endif /* CONFIG_CTRL_IFACE_CLIENT_PREFIX */
88 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
90 return wpa_ctrl_open2(ctrl_path
, NULL
);
94 struct wpa_ctrl
* wpa_ctrl_open2(const char *ctrl_path
,
97 struct wpa_ctrl
*ctrl
;
98 static int counter
= 0;
104 if (ctrl_path
== NULL
)
107 ctrl
= os_zalloc(sizeof(*ctrl
));
111 ctrl
->s
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
117 ctrl
->local
.sun_family
= AF_UNIX
;
120 if (cli_path
&& cli_path
[0] == '/') {
121 ret
= os_snprintf(ctrl
->local
.sun_path
,
122 sizeof(ctrl
->local
.sun_path
),
123 "%s/" CONFIG_CTRL_IFACE_CLIENT_PREFIX
"%d-%d",
124 cli_path
, (int) getpid(), counter
);
126 ret
= os_snprintf(ctrl
->local
.sun_path
,
127 sizeof(ctrl
->local
.sun_path
),
128 CONFIG_CTRL_IFACE_CLIENT_DIR
"/"
129 CONFIG_CTRL_IFACE_CLIENT_PREFIX
"%d-%d",
130 (int) getpid(), counter
);
132 if (os_snprintf_error(sizeof(ctrl
->local
.sun_path
), ret
)) {
139 /* Set client socket file permissions so that bind() creates the client
140 * socket with these permissions and there is no need to try to change
141 * them with chmod() after bind() which would have potential issues with
142 * race conditions. These permissions are needed to make sure the server
143 * side (wpa_supplicant or hostapd) can reply to the control interface
146 * The lchown() calls below after bind() are also part of the needed
147 * operations to allow the response to go through. Those are using the
148 * no-deference-symlinks version to avoid races. */
149 fchmod(ctrl
->s
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
151 if (bind(ctrl
->s
, (struct sockaddr
*) &ctrl
->local
,
152 sizeof(ctrl
->local
)) < 0) {
153 if (errno
== EADDRINUSE
&& tries
< 2) {
155 * getpid() returns unique identifier for this instance
156 * of wpa_ctrl, so the existing socket file must have
157 * been left by unclean termination of an earlier run.
158 * Remove the file and try again.
160 unlink(ctrl
->local
.sun_path
);
169 /* Set group even if we do not have privileges to change owner */
170 lchown(ctrl
->local
.sun_path
, -1, AID_WIFI
);
171 lchown(ctrl
->local
.sun_path
, AID_SYSTEM
, AID_WIFI
);
173 if (os_strncmp(ctrl_path
, "@android:", 9) == 0) {
174 if (socket_local_client_connect(
175 ctrl
->s
, ctrl_path
+ 9,
176 ANDROID_SOCKET_NAMESPACE_RESERVED
,
179 unlink(ctrl
->local
.sun_path
);
187 * If the ctrl_path isn't an absolute pathname, assume that
188 * it's the name of a socket in the Android reserved namespace.
189 * Otherwise, it's a normal UNIX domain socket appearing in the
192 if (*ctrl_path
!= '/') {
194 os_snprintf(buf
, sizeof(buf
), "wpa_%s", ctrl_path
);
195 if (socket_local_client_connect(
197 ANDROID_SOCKET_NAMESPACE_RESERVED
,
200 unlink(ctrl
->local
.sun_path
);
208 ctrl
->dest
.sun_family
= AF_UNIX
;
209 if (os_strncmp(ctrl_path
, "@abstract:", 10) == 0) {
210 ctrl
->dest
.sun_path
[0] = '\0';
211 os_strlcpy(ctrl
->dest
.sun_path
+ 1, ctrl_path
+ 10,
212 sizeof(ctrl
->dest
.sun_path
) - 1);
214 res
= os_strlcpy(ctrl
->dest
.sun_path
, ctrl_path
,
215 sizeof(ctrl
->dest
.sun_path
));
216 if (res
>= sizeof(ctrl
->dest
.sun_path
)) {
222 if (connect(ctrl
->s
, (struct sockaddr
*) &ctrl
->dest
,
223 sizeof(ctrl
->dest
)) < 0) {
225 unlink(ctrl
->local
.sun_path
);
231 * Make socket non-blocking so that we don't hang forever if
232 * target dies unexpectedly.
234 flags
= fcntl(ctrl
->s
, F_GETFL
);
237 if (fcntl(ctrl
->s
, F_SETFL
, flags
) < 0) {
238 perror("fcntl(ctrl->s, O_NONBLOCK)");
239 /* Not fatal, continue on.*/
247 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
251 unlink(ctrl
->local
.sun_path
);
260 * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
261 * may be left over from clients that were previously connected to
262 * wpa_supplicant. This keeps these files from being orphaned in the
263 * event of crashes that prevented them from being removed as part
264 * of the normal orderly shutdown.
266 void wpa_ctrl_cleanup(void)
269 struct dirent
*result
;
272 char pathname
[PATH_MAX
];
275 if ((dir
= opendir(CONFIG_CTRL_IFACE_CLIENT_DIR
)) == NULL
)
278 dirnamelen
= (size_t) os_snprintf(pathname
, sizeof(pathname
), "%s/",
279 CONFIG_CTRL_IFACE_CLIENT_DIR
);
280 if (dirnamelen
>= sizeof(pathname
)) {
284 namep
= pathname
+ dirnamelen
;
285 maxcopy
= PATH_MAX
- dirnamelen
;
286 while ((result
= readdir(dir
)) != NULL
) {
287 if (os_strlcpy(namep
, result
->d_name
, maxcopy
) < maxcopy
)
294 #else /* CONFIG_CTRL_IFACE_UNIX */
297 void wpa_ctrl_cleanup(void)
302 #endif /* CONFIG_CTRL_IFACE_UNIX */
305 #ifdef CONFIG_CTRL_IFACE_UDP
307 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
309 struct wpa_ctrl
*ctrl
;
312 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
314 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
316 ctrl
= os_zalloc(sizeof(*ctrl
));
320 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
321 ctrl
->s
= socket(PF_INET6
, SOCK_DGRAM
, 0);
322 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
323 ctrl
->s
= socket(PF_INET
, SOCK_DGRAM
, 0);
324 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
331 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
332 ctrl
->local
.sin6_family
= AF_INET6
;
333 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
334 ctrl
->local
.sin6_addr
= in6addr_any
;
335 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
336 inet_pton(AF_INET6
, "::1", &ctrl
->local
.sin6_addr
);
337 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
338 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
339 ctrl
->local
.sin_family
= AF_INET
;
340 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
341 ctrl
->local
.sin_addr
.s_addr
= INADDR_ANY
;
342 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
343 ctrl
->local
.sin_addr
.s_addr
= htonl((127 << 24) | 1);
344 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
345 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
347 if (bind(ctrl
->s
, (struct sockaddr
*) &ctrl
->local
,
348 sizeof(ctrl
->local
)) < 0) {
354 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
355 ctrl
->dest
.sin6_family
= AF_INET6
;
356 inet_pton(AF_INET6
, "::1", &ctrl
->dest
.sin6_addr
);
357 ctrl
->dest
.sin6_port
= htons(WPA_CTRL_IFACE_PORT
);
358 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
359 ctrl
->dest
.sin_family
= AF_INET
;
360 ctrl
->dest
.sin_addr
.s_addr
= htonl((127 << 24) | 1);
361 ctrl
->dest
.sin_port
= htons(WPA_CTRL_IFACE_PORT
);
362 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
364 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
368 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
371 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
373 name
= os_strdup(ctrl_path
);
379 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
380 port
= os_strchr(name
, ',');
381 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
382 port
= os_strchr(name
, ':');
383 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
386 port_id
= atoi(&port
[1]);
389 port_id
= WPA_CTRL_IFACE_PORT
;
391 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
392 scope
= os_strchr(name
, '%');
394 scope_id
= if_nametoindex(&scope
[1]);
397 h
= gethostbyname2(name
, AF_INET6
);
398 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
399 h
= gethostbyname(name
);
400 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
401 ctrl
->remote_ip
= os_strdup(name
);
404 perror("gethostbyname");
406 os_free(ctrl
->remote_ip
);
410 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
411 ctrl
->dest
.sin6_scope_id
= scope_id
;
412 ctrl
->dest
.sin6_port
= htons(port_id
);
413 os_memcpy(&ctrl
->dest
.sin6_addr
, h
->h_addr
, h
->h_length
);
414 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
415 ctrl
->dest
.sin_port
= htons(port_id
);
416 os_memcpy(&ctrl
->dest
.sin_addr
.s_addr
, h
->h_addr
, h
->h_length
);
417 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
419 ctrl
->remote_ip
= os_strdup("localhost");
420 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
422 if (connect(ctrl
->s
, (struct sockaddr
*) &ctrl
->dest
,
423 sizeof(ctrl
->dest
)) < 0) {
424 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
425 char addr
[INET6_ADDRSTRLEN
];
426 wpa_printf(MSG_ERROR
, "connect(%s:%d) failed: %s",
427 inet_ntop(AF_INET6
, &ctrl
->dest
.sin6_addr
, addr
,
429 ntohs(ctrl
->dest
.sin6_port
),
431 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
432 wpa_printf(MSG_ERROR
, "connect(%s:%d) failed: %s",
433 inet_ntoa(ctrl
->dest
.sin_addr
),
434 ntohs(ctrl
->dest
.sin_port
),
436 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
438 os_free(ctrl
->remote_ip
);
443 len
= sizeof(buf
) - 1;
444 if (wpa_ctrl_request(ctrl
, "GET_COOKIE", 10, buf
, &len
, NULL
) == 0) {
446 ctrl
->cookie
= os_strdup(buf
);
449 if (wpa_ctrl_request(ctrl
, "IFNAME", 6, buf
, &len
, NULL
) == 0) {
451 ctrl
->remote_ifname
= os_strdup(buf
);
458 char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl
*ctrl
)
460 #define WPA_CTRL_MAX_PS_NAME 100
461 static char ps
[WPA_CTRL_MAX_PS_NAME
] = {};
462 os_snprintf(ps
, WPA_CTRL_MAX_PS_NAME
, "%s/%s",
463 ctrl
->remote_ip
, ctrl
->remote_ifname
);
468 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
471 os_free(ctrl
->cookie
);
472 os_free(ctrl
->remote_ifname
);
473 os_free(ctrl
->remote_ip
);
477 #endif /* CONFIG_CTRL_IFACE_UDP */
480 #ifdef CTRL_IFACE_SOCKET
481 int wpa_ctrl_request(struct wpa_ctrl
*ctrl
, const char *cmd
, size_t cmd_len
,
482 char *reply
, size_t *reply_len
,
483 void (*msg_cb
)(char *msg
, size_t len
))
486 struct os_reltime started_at
;
490 char *cmd_buf
= NULL
;
493 #ifdef CONFIG_CTRL_IFACE_UDP
496 _cmd_len
= os_strlen(ctrl
->cookie
) + 1 + cmd_len
;
497 cmd_buf
= os_malloc(_cmd_len
);
502 os_strlcpy(pos
, ctrl
->cookie
, _cmd_len
);
503 pos
+= os_strlen(ctrl
->cookie
);
505 os_memcpy(pos
, cmd
, cmd_len
);
507 #endif /* CONFIG_CTRL_IFACE_UDP */
517 if (send(ctrl
->s
, _cmd
, _cmd_len
, 0) < 0) {
518 if (errno
== EAGAIN
|| errno
== EBUSY
|| errno
== EWOULDBLOCK
)
521 * Must be a non-blocking socket... Try for a bit
522 * longer before giving up.
524 if (started_at
.sec
== 0)
525 os_get_reltime(&started_at
);
529 /* Try for a few seconds. */
530 if (os_reltime_expired(&n
, &started_at
, 5))
546 FD_SET(ctrl
->s
, &rfds
);
547 res
= select(ctrl
->s
+ 1, &rfds
, NULL
, NULL
, &tv
);
548 if (res
< 0 && errno
== EINTR
)
552 if (FD_ISSET(ctrl
->s
, &rfds
)) {
553 res
= recv(ctrl
->s
, reply
, *reply_len
, 0);
556 if ((res
> 0 && reply
[0] == '<') ||
557 (res
> 6 && strncmp(reply
, "IFNAME=", 7) == 0)) {
558 /* This is an unsolicited message from
559 * wpa_supplicant, not the reply to the
560 * request. Use msg_cb to report this to the
563 /* Make sure the message is nul
565 if ((size_t) res
== *reply_len
)
566 res
= (*reply_len
) - 1;
580 #endif /* CTRL_IFACE_SOCKET */
583 static int wpa_ctrl_attach_helper(struct wpa_ctrl
*ctrl
, int attach
)
589 ret
= wpa_ctrl_request(ctrl
, attach
? "ATTACH" : "DETACH", 6,
593 if (len
== 3 && os_memcmp(buf
, "OK\n", 3) == 0)
599 int wpa_ctrl_attach(struct wpa_ctrl
*ctrl
)
601 return wpa_ctrl_attach_helper(ctrl
, 1);
605 int wpa_ctrl_detach(struct wpa_ctrl
*ctrl
)
607 return wpa_ctrl_attach_helper(ctrl
, 0);
611 #ifdef CTRL_IFACE_SOCKET
613 int wpa_ctrl_recv(struct wpa_ctrl
*ctrl
, char *reply
, size_t *reply_len
)
617 res
= recv(ctrl
->s
, reply
, *reply_len
, 0);
625 int wpa_ctrl_pending(struct wpa_ctrl
*ctrl
)
632 FD_SET(ctrl
->s
, &rfds
);
633 select(ctrl
->s
+ 1, &rfds
, NULL
, NULL
, &tv
);
634 return FD_ISSET(ctrl
->s
, &rfds
);
638 int wpa_ctrl_get_fd(struct wpa_ctrl
*ctrl
)
643 #endif /* CTRL_IFACE_SOCKET */
646 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
648 #ifndef WPA_SUPPLICANT_NAMED_PIPE
649 #define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
651 #define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
653 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
655 struct wpa_ctrl
*ctrl
;
660 ctrl
= os_malloc(sizeof(*ctrl
));
663 os_memset(ctrl
, 0, sizeof(*ctrl
));
666 if (ctrl_path
== NULL
)
667 ret
= _snwprintf(name
, 256, NAMED_PIPE_PREFIX
);
669 ret
= _snwprintf(name
, 256, NAMED_PIPE_PREFIX
TEXT("-%S"),
672 if (ctrl_path
== NULL
)
673 ret
= os_snprintf(name
, 256, NAMED_PIPE_PREFIX
);
675 ret
= os_snprintf(name
, 256, NAMED_PIPE_PREFIX
"-%s",
678 if (os_snprintf_error(256, ret
)) {
683 for (i
= 0; i
< 10; i
++) {
684 ctrl
->pipe
= CreateFile(name
, GENERIC_READ
| GENERIC_WRITE
, 0,
685 NULL
, OPEN_EXISTING
, 0, NULL
);
687 * Current named pipe server side in wpa_supplicant is
688 * re-opening the pipe for new clients only after the previous
689 * one is taken into use. This leaves a small window for race
690 * conditions when two connections are being opened at almost
691 * the same time. Retry if that was the case.
693 if (ctrl
->pipe
!= INVALID_HANDLE_VALUE
||
694 GetLastError() != ERROR_PIPE_BUSY
)
696 WaitNamedPipe(name
, 1000);
698 if (ctrl
->pipe
== INVALID_HANDLE_VALUE
) {
703 mode
= PIPE_READMODE_MESSAGE
;
704 if (!SetNamedPipeHandleState(ctrl
->pipe
, &mode
, NULL
, NULL
)) {
705 CloseHandle(ctrl
->pipe
);
714 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
716 CloseHandle(ctrl
->pipe
);
721 int wpa_ctrl_request(struct wpa_ctrl
*ctrl
, const char *cmd
, size_t cmd_len
,
722 char *reply
, size_t *reply_len
,
723 void (*msg_cb
)(char *msg
, size_t len
))
726 DWORD readlen
= *reply_len
;
728 if (!WriteFile(ctrl
->pipe
, cmd
, cmd_len
, &written
, NULL
))
731 if (!ReadFile(ctrl
->pipe
, reply
, *reply_len
, &readlen
, NULL
))
733 *reply_len
= readlen
;
739 int wpa_ctrl_recv(struct wpa_ctrl
*ctrl
, char *reply
, size_t *reply_len
)
741 DWORD len
= *reply_len
;
742 if (!ReadFile(ctrl
->pipe
, reply
, *reply_len
, &len
, NULL
))
749 int wpa_ctrl_pending(struct wpa_ctrl
*ctrl
)
753 if (!PeekNamedPipe(ctrl
->pipe
, NULL
, 0, NULL
, &left
, NULL
))
759 int wpa_ctrl_get_fd(struct wpa_ctrl
*ctrl
)
764 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
766 #endif /* CONFIG_CTRL_IFACE */