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 */
21 #include <cutils/sockets.h>
22 #include "private/android_filesystem_config.h"
29 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
30 #define CTRL_IFACE_SOCKET
31 #endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
35 * struct wpa_ctrl - Internal structure for control interface library
37 * This structure is used by the wpa_supplicant/hostapd control interface
38 * library to store internal data. Programs using the library should not touch
39 * this data directly. They can only use the pointer to the data structure as
40 * an identifier for the control interface connection and use this as one of
41 * the arguments for most of the control interface library functions.
44 #ifdef CONFIG_CTRL_IFACE_UDP
46 struct sockaddr_in local
;
47 struct sockaddr_in dest
;
49 #endif /* CONFIG_CTRL_IFACE_UDP */
50 #ifdef CONFIG_CTRL_IFACE_UNIX
52 struct sockaddr_un local
;
53 struct sockaddr_un dest
;
54 #endif /* CONFIG_CTRL_IFACE_UNIX */
55 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
57 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
61 #ifdef CONFIG_CTRL_IFACE_UNIX
63 #ifndef CONFIG_CTRL_IFACE_CLIENT_DIR
64 #define CONFIG_CTRL_IFACE_CLIENT_DIR "/tmp"
65 #endif /* CONFIG_CTRL_IFACE_CLIENT_DIR */
66 #ifndef CONFIG_CTRL_IFACE_CLIENT_PREFIX
67 #define CONFIG_CTRL_IFACE_CLIENT_PREFIX "wpa_ctrl_"
68 #endif /* CONFIG_CTRL_IFACE_CLIENT_PREFIX */
71 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
73 struct wpa_ctrl
*ctrl
;
74 static int counter
= 0;
80 ctrl
= os_malloc(sizeof(*ctrl
));
83 os_memset(ctrl
, 0, sizeof(*ctrl
));
85 ctrl
->s
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
91 ctrl
->local
.sun_family
= AF_UNIX
;
94 ret
= os_snprintf(ctrl
->local
.sun_path
, sizeof(ctrl
->local
.sun_path
),
95 CONFIG_CTRL_IFACE_CLIENT_DIR
"/"
96 CONFIG_CTRL_IFACE_CLIENT_PREFIX
"%d-%d",
97 (int) getpid(), counter
);
98 if (ret
< 0 || (size_t) ret
>= sizeof(ctrl
->local
.sun_path
)) {
104 if (bind(ctrl
->s
, (struct sockaddr
*) &ctrl
->local
,
105 sizeof(ctrl
->local
)) < 0) {
106 if (errno
== EADDRINUSE
&& tries
< 2) {
108 * getpid() returns unique identifier for this instance
109 * of wpa_ctrl, so the existing socket file must have
110 * been left by unclean termination of an earlier run.
111 * Remove the file and try again.
113 unlink(ctrl
->local
.sun_path
);
122 chmod(ctrl
->local
.sun_path
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
123 chown(ctrl
->local
.sun_path
, AID_SYSTEM
, AID_WIFI
);
125 * If the ctrl_path isn't an absolute pathname, assume that
126 * it's the name of a socket in the Android reserved namespace.
127 * Otherwise, it's a normal UNIX domain socket appearing in the
130 if (ctrl_path
!= NULL
&& *ctrl_path
!= '/') {
132 os_snprintf(buf
, sizeof(buf
), "wpa_%s", ctrl_path
);
133 if (socket_local_client_connect(
135 ANDROID_SOCKET_NAMESPACE_RESERVED
,
138 unlink(ctrl
->local
.sun_path
);
146 ctrl
->dest
.sun_family
= AF_UNIX
;
147 res
= os_strlcpy(ctrl
->dest
.sun_path
, ctrl_path
,
148 sizeof(ctrl
->dest
.sun_path
));
149 if (res
>= sizeof(ctrl
->dest
.sun_path
)) {
154 if (connect(ctrl
->s
, (struct sockaddr
*) &ctrl
->dest
,
155 sizeof(ctrl
->dest
)) < 0) {
157 unlink(ctrl
->local
.sun_path
);
163 * Make socket non-blocking so that we don't hang forever if
164 * target dies unexpectedly.
166 flags
= fcntl(ctrl
->s
, F_GETFL
);
169 if (fcntl(ctrl
->s
, F_SETFL
, flags
) < 0) {
170 perror("fcntl(ctrl->s, O_NONBLOCK)");
171 /* Not fatal, continue on.*/
179 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
183 unlink(ctrl
->local
.sun_path
);
192 * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
193 * may be left over from clients that were previously connected to
194 * wpa_supplicant. This keeps these files from being orphaned in the
195 * event of crashes that prevented them from being removed as part
196 * of the normal orderly shutdown.
198 void wpa_ctrl_cleanup(void)
202 struct dirent
*result
;
204 int prefixlen
= os_strlen(CONFIG_CTRL_IFACE_CLIENT_PREFIX
);
206 char pathname
[PATH_MAX
];
209 if ((dir
= opendir(CONFIG_CTRL_IFACE_CLIENT_DIR
)) == NULL
)
212 dirnamelen
= (size_t) os_snprintf(pathname
, sizeof(pathname
), "%s/",
213 CONFIG_CTRL_IFACE_CLIENT_DIR
);
214 if (dirnamelen
>= sizeof(pathname
)) {
218 namep
= pathname
+ dirnamelen
;
219 maxcopy
= PATH_MAX
- dirnamelen
;
220 while (readdir_r(dir
, &entry
, &result
) == 0 && result
!= NULL
) {
221 if (os_strncmp(entry
.d_name
, CONFIG_CTRL_IFACE_CLIENT_PREFIX
,
223 if (os_strlcpy(namep
, entry
.d_name
, maxcopy
) < maxcopy
)
231 #else /* CONFIG_CTRL_IFACE_UNIX */
234 void wpa_ctrl_cleanup(void)
239 #endif /* CONFIG_CTRL_IFACE_UNIX */
242 #ifdef CONFIG_CTRL_IFACE_UDP
244 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
246 struct wpa_ctrl
*ctrl
;
250 ctrl
= os_malloc(sizeof(*ctrl
));
253 os_memset(ctrl
, 0, sizeof(*ctrl
));
255 ctrl
->s
= socket(PF_INET
, SOCK_DGRAM
, 0);
262 ctrl
->local
.sin_family
= AF_INET
;
263 ctrl
->local
.sin_addr
.s_addr
= htonl((127 << 24) | 1);
264 if (bind(ctrl
->s
, (struct sockaddr
*) &ctrl
->local
,
265 sizeof(ctrl
->local
)) < 0) {
271 ctrl
->dest
.sin_family
= AF_INET
;
272 ctrl
->dest
.sin_addr
.s_addr
= htonl((127 << 24) | 1);
273 ctrl
->dest
.sin_port
= htons(WPA_CTRL_IFACE_PORT
);
274 if (connect(ctrl
->s
, (struct sockaddr
*) &ctrl
->dest
,
275 sizeof(ctrl
->dest
)) < 0) {
282 len
= sizeof(buf
) - 1;
283 if (wpa_ctrl_request(ctrl
, "GET_COOKIE", 10, buf
, &len
, NULL
) == 0) {
285 ctrl
->cookie
= os_strdup(buf
);
292 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
295 os_free(ctrl
->cookie
);
299 #endif /* CONFIG_CTRL_IFACE_UDP */
302 #ifdef CTRL_IFACE_SOCKET
303 int wpa_ctrl_request(struct wpa_ctrl
*ctrl
, const char *cmd
, size_t cmd_len
,
304 char *reply
, size_t *reply_len
,
305 void (*msg_cb
)(char *msg
, size_t len
))
308 struct os_time started_at
;
312 char *cmd_buf
= NULL
;
315 #ifdef CONFIG_CTRL_IFACE_UDP
318 _cmd_len
= os_strlen(ctrl
->cookie
) + 1 + cmd_len
;
319 cmd_buf
= os_malloc(_cmd_len
);
324 os_strlcpy(pos
, ctrl
->cookie
, _cmd_len
);
325 pos
+= os_strlen(ctrl
->cookie
);
327 os_memcpy(pos
, cmd
, cmd_len
);
329 #endif /* CONFIG_CTRL_IFACE_UDP */
339 if (send(ctrl
->s
, _cmd
, _cmd_len
, 0) < 0) {
340 if (errno
== EAGAIN
|| errno
== EBUSY
|| errno
== EWOULDBLOCK
)
343 * Must be a non-blocking socket... Try for a bit
344 * longer before giving up.
346 if (started_at
.sec
== 0)
347 os_get_time(&started_at
);
351 /* Try for a few seconds. */
352 if (n
.sec
> started_at
.sec
+ 5)
368 FD_SET(ctrl
->s
, &rfds
);
369 res
= select(ctrl
->s
+ 1, &rfds
, NULL
, NULL
, &tv
);
372 if (FD_ISSET(ctrl
->s
, &rfds
)) {
373 res
= recv(ctrl
->s
, reply
, *reply_len
, 0);
376 if (res
> 0 && reply
[0] == '<') {
377 /* This is an unsolicited message from
378 * wpa_supplicant, not the reply to the
379 * request. Use msg_cb to report this to the
382 /* Make sure the message is nul
384 if ((size_t) res
== *reply_len
)
385 res
= (*reply_len
) - 1;
399 #endif /* CTRL_IFACE_SOCKET */
402 static int wpa_ctrl_attach_helper(struct wpa_ctrl
*ctrl
, int attach
)
408 ret
= wpa_ctrl_request(ctrl
, attach
? "ATTACH" : "DETACH", 6,
412 if (len
== 3 && os_memcmp(buf
, "OK\n", 3) == 0)
418 int wpa_ctrl_attach(struct wpa_ctrl
*ctrl
)
420 return wpa_ctrl_attach_helper(ctrl
, 1);
424 int wpa_ctrl_detach(struct wpa_ctrl
*ctrl
)
426 return wpa_ctrl_attach_helper(ctrl
, 0);
430 #ifdef CTRL_IFACE_SOCKET
432 int wpa_ctrl_recv(struct wpa_ctrl
*ctrl
, char *reply
, size_t *reply_len
)
436 res
= recv(ctrl
->s
, reply
, *reply_len
, 0);
444 int wpa_ctrl_pending(struct wpa_ctrl
*ctrl
)
451 FD_SET(ctrl
->s
, &rfds
);
452 select(ctrl
->s
+ 1, &rfds
, NULL
, NULL
, &tv
);
453 return FD_ISSET(ctrl
->s
, &rfds
);
457 int wpa_ctrl_get_fd(struct wpa_ctrl
*ctrl
)
462 #endif /* CTRL_IFACE_SOCKET */
465 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
467 #ifndef WPA_SUPPLICANT_NAMED_PIPE
468 #define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
470 #define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
472 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
474 struct wpa_ctrl
*ctrl
;
479 ctrl
= os_malloc(sizeof(*ctrl
));
482 os_memset(ctrl
, 0, sizeof(*ctrl
));
485 if (ctrl_path
== NULL
)
486 ret
= _snwprintf(name
, 256, NAMED_PIPE_PREFIX
);
488 ret
= _snwprintf(name
, 256, NAMED_PIPE_PREFIX
TEXT("-%S"),
491 if (ctrl_path
== NULL
)
492 ret
= os_snprintf(name
, 256, NAMED_PIPE_PREFIX
);
494 ret
= os_snprintf(name
, 256, NAMED_PIPE_PREFIX
"-%s",
497 if (ret
< 0 || ret
>= 256) {
502 for (i
= 0; i
< 10; i
++) {
503 ctrl
->pipe
= CreateFile(name
, GENERIC_READ
| GENERIC_WRITE
, 0,
504 NULL
, OPEN_EXISTING
, 0, NULL
);
506 * Current named pipe server side in wpa_supplicant is
507 * re-opening the pipe for new clients only after the previous
508 * one is taken into use. This leaves a small window for race
509 * conditions when two connections are being opened at almost
510 * the same time. Retry if that was the case.
512 if (ctrl
->pipe
!= INVALID_HANDLE_VALUE
||
513 GetLastError() != ERROR_PIPE_BUSY
)
515 WaitNamedPipe(name
, 1000);
517 if (ctrl
->pipe
== INVALID_HANDLE_VALUE
) {
522 mode
= PIPE_READMODE_MESSAGE
;
523 if (!SetNamedPipeHandleState(ctrl
->pipe
, &mode
, NULL
, NULL
)) {
524 CloseHandle(ctrl
->pipe
);
533 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
535 CloseHandle(ctrl
->pipe
);
540 int wpa_ctrl_request(struct wpa_ctrl
*ctrl
, const char *cmd
, size_t cmd_len
,
541 char *reply
, size_t *reply_len
,
542 void (*msg_cb
)(char *msg
, size_t len
))
545 DWORD readlen
= *reply_len
;
547 if (!WriteFile(ctrl
->pipe
, cmd
, cmd_len
, &written
, NULL
))
550 if (!ReadFile(ctrl
->pipe
, reply
, *reply_len
, &readlen
, NULL
))
552 *reply_len
= readlen
;
558 int wpa_ctrl_recv(struct wpa_ctrl
*ctrl
, char *reply
, size_t *reply_len
)
560 DWORD len
= *reply_len
;
561 if (!ReadFile(ctrl
->pipe
, reply
, *reply_len
, &len
, NULL
))
568 int wpa_ctrl_pending(struct wpa_ctrl
*ctrl
)
572 if (!PeekNamedPipe(ctrl
->pipe
, NULL
, 0, NULL
, &left
, NULL
))
578 int wpa_ctrl_get_fd(struct wpa_ctrl
*ctrl
)
583 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
585 #endif /* CONFIG_CTRL_IFACE */