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
17 #endif /* CONFIG_CTRL_IFACE_UNIX */
18 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
20 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
24 #include <cutils/sockets.h>
25 #include "private/android_filesystem_config.h"
32 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
33 #define CTRL_IFACE_SOCKET
34 #endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
38 * struct wpa_ctrl - Internal structure for control interface library
40 * This structure is used by the wpa_supplicant/hostapd control interface
41 * library to store internal data. Programs using the library should not touch
42 * this data directly. They can only use the pointer to the data structure as
43 * an identifier for the control interface connection and use this as one of
44 * the arguments for most of the control interface library functions.
47 #ifdef CONFIG_CTRL_IFACE_UDP
49 struct sockaddr_in local
;
50 struct sockaddr_in dest
;
54 #endif /* CONFIG_CTRL_IFACE_UDP */
55 #ifdef CONFIG_CTRL_IFACE_UNIX
57 struct sockaddr_un local
;
58 struct sockaddr_un dest
;
59 #endif /* CONFIG_CTRL_IFACE_UNIX */
60 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
62 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
66 #ifdef CONFIG_CTRL_IFACE_UNIX
68 #ifndef CONFIG_CTRL_IFACE_CLIENT_DIR
69 #define CONFIG_CTRL_IFACE_CLIENT_DIR "/tmp"
70 #endif /* CONFIG_CTRL_IFACE_CLIENT_DIR */
71 #ifndef CONFIG_CTRL_IFACE_CLIENT_PREFIX
72 #define CONFIG_CTRL_IFACE_CLIENT_PREFIX "wpa_ctrl_"
73 #endif /* CONFIG_CTRL_IFACE_CLIENT_PREFIX */
76 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
78 struct wpa_ctrl
*ctrl
;
79 static int counter
= 0;
85 if (ctrl_path
== NULL
)
88 ctrl
= os_malloc(sizeof(*ctrl
));
91 os_memset(ctrl
, 0, sizeof(*ctrl
));
93 ctrl
->s
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
99 ctrl
->local
.sun_family
= AF_UNIX
;
102 ret
= os_snprintf(ctrl
->local
.sun_path
, sizeof(ctrl
->local
.sun_path
),
103 CONFIG_CTRL_IFACE_CLIENT_DIR
"/"
104 CONFIG_CTRL_IFACE_CLIENT_PREFIX
"%d-%d",
105 (int) getpid(), counter
);
106 if (ret
< 0 || (size_t) ret
>= sizeof(ctrl
->local
.sun_path
)) {
112 if (bind(ctrl
->s
, (struct sockaddr
*) &ctrl
->local
,
113 sizeof(ctrl
->local
)) < 0) {
114 if (errno
== EADDRINUSE
&& tries
< 2) {
116 * getpid() returns unique identifier for this instance
117 * of wpa_ctrl, so the existing socket file must have
118 * been left by unclean termination of an earlier run.
119 * Remove the file and try again.
121 unlink(ctrl
->local
.sun_path
);
130 chmod(ctrl
->local
.sun_path
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
131 chown(ctrl
->local
.sun_path
, AID_SYSTEM
, AID_WIFI
);
133 if (os_strncmp(ctrl_path
, "@android:", 9) == 0) {
134 if (socket_local_client_connect(
135 ctrl
->s
, ctrl_path
+ 9,
136 ANDROID_SOCKET_NAMESPACE_RESERVED
,
139 unlink(ctrl
->local
.sun_path
);
147 * If the ctrl_path isn't an absolute pathname, assume that
148 * it's the name of a socket in the Android reserved namespace.
149 * Otherwise, it's a normal UNIX domain socket appearing in the
152 if (*ctrl_path
!= '/') {
154 os_snprintf(buf
, sizeof(buf
), "wpa_%s", ctrl_path
);
155 if (socket_local_client_connect(
157 ANDROID_SOCKET_NAMESPACE_RESERVED
,
160 unlink(ctrl
->local
.sun_path
);
168 ctrl
->dest
.sun_family
= AF_UNIX
;
169 if (os_strncmp(ctrl_path
, "@abstract:", 10) == 0) {
170 ctrl
->dest
.sun_path
[0] = '\0';
171 os_strlcpy(ctrl
->dest
.sun_path
+ 1, ctrl_path
+ 10,
172 sizeof(ctrl
->dest
.sun_path
) - 1);
174 res
= os_strlcpy(ctrl
->dest
.sun_path
, ctrl_path
,
175 sizeof(ctrl
->dest
.sun_path
));
176 if (res
>= sizeof(ctrl
->dest
.sun_path
)) {
182 if (connect(ctrl
->s
, (struct sockaddr
*) &ctrl
->dest
,
183 sizeof(ctrl
->dest
)) < 0) {
185 unlink(ctrl
->local
.sun_path
);
191 * Make socket non-blocking so that we don't hang forever if
192 * target dies unexpectedly.
194 flags
= fcntl(ctrl
->s
, F_GETFL
);
197 if (fcntl(ctrl
->s
, F_SETFL
, flags
) < 0) {
198 perror("fcntl(ctrl->s, O_NONBLOCK)");
199 /* Not fatal, continue on.*/
207 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
211 unlink(ctrl
->local
.sun_path
);
220 * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
221 * may be left over from clients that were previously connected to
222 * wpa_supplicant. This keeps these files from being orphaned in the
223 * event of crashes that prevented them from being removed as part
224 * of the normal orderly shutdown.
226 void wpa_ctrl_cleanup(void)
230 struct dirent
*result
;
233 char pathname
[PATH_MAX
];
236 if ((dir
= opendir(CONFIG_CTRL_IFACE_CLIENT_DIR
)) == NULL
)
239 dirnamelen
= (size_t) os_snprintf(pathname
, sizeof(pathname
), "%s/",
240 CONFIG_CTRL_IFACE_CLIENT_DIR
);
241 if (dirnamelen
>= sizeof(pathname
)) {
245 namep
= pathname
+ dirnamelen
;
246 maxcopy
= PATH_MAX
- dirnamelen
;
247 while (readdir_r(dir
, &entry
, &result
) == 0 && result
!= NULL
) {
248 if (os_strlcpy(namep
, entry
.d_name
, maxcopy
) < maxcopy
)
255 #else /* CONFIG_CTRL_IFACE_UNIX */
258 void wpa_ctrl_cleanup(void)
263 #endif /* CONFIG_CTRL_IFACE_UNIX */
266 #ifdef CONFIG_CTRL_IFACE_UDP
268 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
270 struct wpa_ctrl
*ctrl
;
273 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
275 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
277 ctrl
= os_malloc(sizeof(*ctrl
));
280 os_memset(ctrl
, 0, sizeof(*ctrl
));
282 ctrl
->s
= socket(PF_INET
, SOCK_DGRAM
, 0);
289 ctrl
->local
.sin_family
= AF_INET
;
290 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
291 ctrl
->local
.sin_addr
.s_addr
= INADDR_ANY
;
292 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
293 ctrl
->local
.sin_addr
.s_addr
= htonl((127 << 24) | 1);
294 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
295 if (bind(ctrl
->s
, (struct sockaddr
*) &ctrl
->local
,
296 sizeof(ctrl
->local
)) < 0) {
302 ctrl
->dest
.sin_family
= AF_INET
;
303 ctrl
->dest
.sin_addr
.s_addr
= htonl((127 << 24) | 1);
304 ctrl
->dest
.sin_port
= htons(WPA_CTRL_IFACE_PORT
);
306 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
311 name
= os_strdup(ctrl_path
);
317 port
= os_strchr(name
, ':');
320 port_id
= atoi(&port
[1]);
323 port_id
= WPA_CTRL_IFACE_PORT
;
325 h
= gethostbyname(name
);
326 ctrl
->remote_ip
= os_strdup(name
);
329 perror("gethostbyname");
331 os_free(ctrl
->remote_ip
);
335 ctrl
->dest
.sin_port
= htons(port_id
);
336 os_memcpy(h
->h_addr
, (char *) &ctrl
->dest
.sin_addr
.s_addr
,
339 ctrl
->remote_ip
= os_strdup("localhost");
340 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
342 if (connect(ctrl
->s
, (struct sockaddr
*) &ctrl
->dest
,
343 sizeof(ctrl
->dest
)) < 0) {
346 os_free(ctrl
->remote_ip
);
351 len
= sizeof(buf
) - 1;
352 if (wpa_ctrl_request(ctrl
, "GET_COOKIE", 10, buf
, &len
, NULL
) == 0) {
354 ctrl
->cookie
= os_strdup(buf
);
357 if (wpa_ctrl_request(ctrl
, "IFNAME", 6, buf
, &len
, NULL
) == 0) {
359 ctrl
->remote_ifname
= os_strdup(buf
);
366 char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl
*ctrl
)
368 #define WPA_CTRL_MAX_PS_NAME 100
369 static char ps
[WPA_CTRL_MAX_PS_NAME
] = {};
370 os_snprintf(ps
, WPA_CTRL_MAX_PS_NAME
, "%s/%s",
371 ctrl
->remote_ip
, ctrl
->remote_ifname
);
376 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
379 os_free(ctrl
->cookie
);
380 os_free(ctrl
->remote_ifname
);
381 os_free(ctrl
->remote_ip
);
385 #endif /* CONFIG_CTRL_IFACE_UDP */
388 #ifdef CTRL_IFACE_SOCKET
389 int wpa_ctrl_request(struct wpa_ctrl
*ctrl
, const char *cmd
, size_t cmd_len
,
390 char *reply
, size_t *reply_len
,
391 void (*msg_cb
)(char *msg
, size_t len
))
394 struct os_reltime started_at
;
398 char *cmd_buf
= NULL
;
401 #ifdef CONFIG_CTRL_IFACE_UDP
404 _cmd_len
= os_strlen(ctrl
->cookie
) + 1 + cmd_len
;
405 cmd_buf
= os_malloc(_cmd_len
);
410 os_strlcpy(pos
, ctrl
->cookie
, _cmd_len
);
411 pos
+= os_strlen(ctrl
->cookie
);
413 os_memcpy(pos
, cmd
, cmd_len
);
415 #endif /* CONFIG_CTRL_IFACE_UDP */
425 if (send(ctrl
->s
, _cmd
, _cmd_len
, 0) < 0) {
426 if (errno
== EAGAIN
|| errno
== EBUSY
|| errno
== EWOULDBLOCK
)
429 * Must be a non-blocking socket... Try for a bit
430 * longer before giving up.
432 if (started_at
.sec
== 0)
433 os_get_reltime(&started_at
);
437 /* Try for a few seconds. */
438 if (os_reltime_expired(&n
, &started_at
, 5))
454 FD_SET(ctrl
->s
, &rfds
);
455 res
= select(ctrl
->s
+ 1, &rfds
, NULL
, NULL
, &tv
);
458 if (FD_ISSET(ctrl
->s
, &rfds
)) {
459 res
= recv(ctrl
->s
, reply
, *reply_len
, 0);
462 if (res
> 0 && reply
[0] == '<') {
463 /* This is an unsolicited message from
464 * wpa_supplicant, not the reply to the
465 * request. Use msg_cb to report this to the
468 /* Make sure the message is nul
470 if ((size_t) res
== *reply_len
)
471 res
= (*reply_len
) - 1;
485 #endif /* CTRL_IFACE_SOCKET */
488 static int wpa_ctrl_attach_helper(struct wpa_ctrl
*ctrl
, int attach
)
494 ret
= wpa_ctrl_request(ctrl
, attach
? "ATTACH" : "DETACH", 6,
498 if (len
== 3 && os_memcmp(buf
, "OK\n", 3) == 0)
504 int wpa_ctrl_attach(struct wpa_ctrl
*ctrl
)
506 return wpa_ctrl_attach_helper(ctrl
, 1);
510 int wpa_ctrl_detach(struct wpa_ctrl
*ctrl
)
512 return wpa_ctrl_attach_helper(ctrl
, 0);
516 #ifdef CTRL_IFACE_SOCKET
518 int wpa_ctrl_recv(struct wpa_ctrl
*ctrl
, char *reply
, size_t *reply_len
)
522 res
= recv(ctrl
->s
, reply
, *reply_len
, 0);
530 int wpa_ctrl_pending(struct wpa_ctrl
*ctrl
)
537 FD_SET(ctrl
->s
, &rfds
);
538 select(ctrl
->s
+ 1, &rfds
, NULL
, NULL
, &tv
);
539 return FD_ISSET(ctrl
->s
, &rfds
);
543 int wpa_ctrl_get_fd(struct wpa_ctrl
*ctrl
)
548 #endif /* CTRL_IFACE_SOCKET */
551 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
553 #ifndef WPA_SUPPLICANT_NAMED_PIPE
554 #define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
556 #define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
558 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
560 struct wpa_ctrl
*ctrl
;
565 ctrl
= os_malloc(sizeof(*ctrl
));
568 os_memset(ctrl
, 0, sizeof(*ctrl
));
571 if (ctrl_path
== NULL
)
572 ret
= _snwprintf(name
, 256, NAMED_PIPE_PREFIX
);
574 ret
= _snwprintf(name
, 256, NAMED_PIPE_PREFIX
TEXT("-%S"),
577 if (ctrl_path
== NULL
)
578 ret
= os_snprintf(name
, 256, NAMED_PIPE_PREFIX
);
580 ret
= os_snprintf(name
, 256, NAMED_PIPE_PREFIX
"-%s",
583 if (ret
< 0 || ret
>= 256) {
588 for (i
= 0; i
< 10; i
++) {
589 ctrl
->pipe
= CreateFile(name
, GENERIC_READ
| GENERIC_WRITE
, 0,
590 NULL
, OPEN_EXISTING
, 0, NULL
);
592 * Current named pipe server side in wpa_supplicant is
593 * re-opening the pipe for new clients only after the previous
594 * one is taken into use. This leaves a small window for race
595 * conditions when two connections are being opened at almost
596 * the same time. Retry if that was the case.
598 if (ctrl
->pipe
!= INVALID_HANDLE_VALUE
||
599 GetLastError() != ERROR_PIPE_BUSY
)
601 WaitNamedPipe(name
, 1000);
603 if (ctrl
->pipe
== INVALID_HANDLE_VALUE
) {
608 mode
= PIPE_READMODE_MESSAGE
;
609 if (!SetNamedPipeHandleState(ctrl
->pipe
, &mode
, NULL
, NULL
)) {
610 CloseHandle(ctrl
->pipe
);
619 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
621 CloseHandle(ctrl
->pipe
);
626 int wpa_ctrl_request(struct wpa_ctrl
*ctrl
, const char *cmd
, size_t cmd_len
,
627 char *reply
, size_t *reply_len
,
628 void (*msg_cb
)(char *msg
, size_t len
))
631 DWORD readlen
= *reply_len
;
633 if (!WriteFile(ctrl
->pipe
, cmd
, cmd_len
, &written
, NULL
))
636 if (!ReadFile(ctrl
->pipe
, reply
, *reply_len
, &readlen
, NULL
))
638 *reply_len
= readlen
;
644 int wpa_ctrl_recv(struct wpa_ctrl
*ctrl
, char *reply
, size_t *reply_len
)
646 DWORD len
= *reply_len
;
647 if (!ReadFile(ctrl
->pipe
, reply
, *reply_len
, &len
, NULL
))
654 int wpa_ctrl_pending(struct wpa_ctrl
*ctrl
)
658 if (!PeekNamedPipe(ctrl
->pipe
, NULL
, 0, NULL
, &left
, NULL
))
664 int wpa_ctrl_get_fd(struct wpa_ctrl
*ctrl
)
669 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
671 #endif /* CONFIG_CTRL_IFACE */