2 * wpa_supplicant/hostapd control interface library
3 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
17 #ifdef CONFIG_CTRL_IFACE
19 #ifdef CONFIG_CTRL_IFACE_UNIX
21 #endif /* CONFIG_CTRL_IFACE_UNIX */
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
;
52 #endif /* CONFIG_CTRL_IFACE_UDP */
53 #ifdef CONFIG_CTRL_IFACE_UNIX
55 struct sockaddr_un local
;
56 struct sockaddr_un dest
;
57 #endif /* CONFIG_CTRL_IFACE_UNIX */
58 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
60 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
64 #ifdef CONFIG_CTRL_IFACE_UNIX
66 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
68 struct wpa_ctrl
*ctrl
;
69 static int counter
= 0;
74 ctrl
= os_malloc(sizeof(*ctrl
));
77 os_memset(ctrl
, 0, sizeof(*ctrl
));
79 ctrl
->s
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
85 ctrl
->local
.sun_family
= AF_UNIX
;
88 ret
= os_snprintf(ctrl
->local
.sun_path
, sizeof(ctrl
->local
.sun_path
),
89 "/tmp/wpa_ctrl_%d-%d", (int) getpid(), counter
);
90 if (ret
< 0 || (size_t) ret
>= sizeof(ctrl
->local
.sun_path
)) {
96 if (bind(ctrl
->s
, (struct sockaddr
*) &ctrl
->local
,
97 sizeof(ctrl
->local
)) < 0) {
98 if (errno
== EADDRINUSE
&& tries
< 2) {
100 * getpid() returns unique identifier for this instance
101 * of wpa_ctrl, so the existing socket file must have
102 * been left by unclean termination of an earlier run.
103 * Remove the file and try again.
105 unlink(ctrl
->local
.sun_path
);
114 chmod(ctrl
->local
.sun_path
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
115 chown(ctrl
->local
.sun_path
, AID_SYSTEM
, AID_WIFI
);
117 * If the ctrl_path isn't an absolute pathname, assume that
118 * it's the name of a socket in the Android reserved namespace.
119 * Otherwise, it's a normal UNIX domain socket appearing in the
122 if (ctrl_path
!= NULL
&& *ctrl_path
!= '/') {
124 os_snprintf(buf
, sizeof(buf
), "wpa_%s", ctrl_path
);
125 if (socket_local_client_connect(
127 ANDROID_SOCKET_NAMESPACE_RESERVED
,
130 unlink(ctrl
->local
.sun_path
);
138 ctrl
->dest
.sun_family
= AF_UNIX
;
139 res
= os_strlcpy(ctrl
->dest
.sun_path
, ctrl_path
,
140 sizeof(ctrl
->dest
.sun_path
));
141 if (res
>= sizeof(ctrl
->dest
.sun_path
)) {
146 if (connect(ctrl
->s
, (struct sockaddr
*) &ctrl
->dest
,
147 sizeof(ctrl
->dest
)) < 0) {
149 unlink(ctrl
->local
.sun_path
);
158 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
162 unlink(ctrl
->local
.sun_path
);
168 #endif /* CONFIG_CTRL_IFACE_UNIX */
171 #ifdef CONFIG_CTRL_IFACE_UDP
173 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
175 struct wpa_ctrl
*ctrl
;
179 ctrl
= os_malloc(sizeof(*ctrl
));
182 os_memset(ctrl
, 0, sizeof(*ctrl
));
184 ctrl
->s
= socket(PF_INET
, SOCK_DGRAM
, 0);
191 ctrl
->local
.sin_family
= AF_INET
;
192 ctrl
->local
.sin_addr
.s_addr
= htonl((127 << 24) | 1);
193 if (bind(ctrl
->s
, (struct sockaddr
*) &ctrl
->local
,
194 sizeof(ctrl
->local
)) < 0) {
200 ctrl
->dest
.sin_family
= AF_INET
;
201 ctrl
->dest
.sin_addr
.s_addr
= htonl((127 << 24) | 1);
202 ctrl
->dest
.sin_port
= htons(WPA_CTRL_IFACE_PORT
);
203 if (connect(ctrl
->s
, (struct sockaddr
*) &ctrl
->dest
,
204 sizeof(ctrl
->dest
)) < 0) {
211 len
= sizeof(buf
) - 1;
212 if (wpa_ctrl_request(ctrl
, "GET_COOKIE", 10, buf
, &len
, NULL
) == 0) {
214 ctrl
->cookie
= os_strdup(buf
);
221 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
224 os_free(ctrl
->cookie
);
228 #endif /* CONFIG_CTRL_IFACE_UDP */
231 #ifdef CTRL_IFACE_SOCKET
232 int wpa_ctrl_request(struct wpa_ctrl
*ctrl
, const char *cmd
, size_t cmd_len
,
233 char *reply
, size_t *reply_len
,
234 void (*msg_cb
)(char *msg
, size_t len
))
240 char *cmd_buf
= NULL
;
243 #ifdef CONFIG_CTRL_IFACE_UDP
246 _cmd_len
= os_strlen(ctrl
->cookie
) + 1 + cmd_len
;
247 cmd_buf
= os_malloc(_cmd_len
);
252 os_strlcpy(pos
, ctrl
->cookie
, _cmd_len
);
253 pos
+= os_strlen(ctrl
->cookie
);
255 os_memcpy(pos
, cmd
, cmd_len
);
257 #endif /* CONFIG_CTRL_IFACE_UDP */
263 if (send(ctrl
->s
, _cmd
, _cmd_len
, 0) < 0) {
273 FD_SET(ctrl
->s
, &rfds
);
274 res
= select(ctrl
->s
+ 1, &rfds
, NULL
, NULL
, &tv
);
275 if (FD_ISSET(ctrl
->s
, &rfds
)) {
276 res
= recv(ctrl
->s
, reply
, *reply_len
, 0);
279 if (res
> 0 && reply
[0] == '<') {
280 /* This is an unsolicited message from
281 * wpa_supplicant, not the reply to the
282 * request. Use msg_cb to report this to the
285 /* Make sure the message is nul
287 if ((size_t) res
== *reply_len
)
288 res
= (*reply_len
) - 1;
302 #endif /* CTRL_IFACE_SOCKET */
305 static int wpa_ctrl_attach_helper(struct wpa_ctrl
*ctrl
, int attach
)
311 ret
= wpa_ctrl_request(ctrl
, attach
? "ATTACH" : "DETACH", 6,
315 if (len
== 3 && os_memcmp(buf
, "OK\n", 3) == 0)
321 int wpa_ctrl_attach(struct wpa_ctrl
*ctrl
)
323 return wpa_ctrl_attach_helper(ctrl
, 1);
327 int wpa_ctrl_detach(struct wpa_ctrl
*ctrl
)
329 return wpa_ctrl_attach_helper(ctrl
, 0);
333 #ifdef CTRL_IFACE_SOCKET
335 int wpa_ctrl_recv(struct wpa_ctrl
*ctrl
, char *reply
, size_t *reply_len
)
339 res
= recv(ctrl
->s
, reply
, *reply_len
, 0);
347 int wpa_ctrl_pending(struct wpa_ctrl
*ctrl
)
354 FD_SET(ctrl
->s
, &rfds
);
355 select(ctrl
->s
+ 1, &rfds
, NULL
, NULL
, &tv
);
356 return FD_ISSET(ctrl
->s
, &rfds
);
360 int wpa_ctrl_get_fd(struct wpa_ctrl
*ctrl
)
365 #endif /* CTRL_IFACE_SOCKET */
368 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
370 #ifndef WPA_SUPPLICANT_NAMED_PIPE
371 #define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
373 #define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
375 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
377 struct wpa_ctrl
*ctrl
;
382 ctrl
= os_malloc(sizeof(*ctrl
));
385 os_memset(ctrl
, 0, sizeof(*ctrl
));
388 if (ctrl_path
== NULL
)
389 ret
= _snwprintf(name
, 256, NAMED_PIPE_PREFIX
);
391 ret
= _snwprintf(name
, 256, NAMED_PIPE_PREFIX
TEXT("-%S"),
394 if (ctrl_path
== NULL
)
395 ret
= os_snprintf(name
, 256, NAMED_PIPE_PREFIX
);
397 ret
= os_snprintf(name
, 256, NAMED_PIPE_PREFIX
"-%s",
400 if (ret
< 0 || ret
>= 256) {
405 for (i
= 0; i
< 10; i
++) {
406 ctrl
->pipe
= CreateFile(name
, GENERIC_READ
| GENERIC_WRITE
, 0,
407 NULL
, OPEN_EXISTING
, 0, NULL
);
409 * Current named pipe server side in wpa_supplicant is
410 * re-opening the pipe for new clients only after the previous
411 * one is taken into use. This leaves a small window for race
412 * conditions when two connections are being opened at almost
413 * the same time. Retry if that was the case.
415 if (ctrl
->pipe
!= INVALID_HANDLE_VALUE
||
416 GetLastError() != ERROR_PIPE_BUSY
)
418 WaitNamedPipe(name
, 1000);
420 if (ctrl
->pipe
== INVALID_HANDLE_VALUE
) {
425 mode
= PIPE_READMODE_MESSAGE
;
426 if (!SetNamedPipeHandleState(ctrl
->pipe
, &mode
, NULL
, NULL
)) {
427 CloseHandle(ctrl
->pipe
);
436 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
438 CloseHandle(ctrl
->pipe
);
443 int wpa_ctrl_request(struct wpa_ctrl
*ctrl
, const char *cmd
, size_t cmd_len
,
444 char *reply
, size_t *reply_len
,
445 void (*msg_cb
)(char *msg
, size_t len
))
448 DWORD readlen
= *reply_len
;
450 if (!WriteFile(ctrl
->pipe
, cmd
, cmd_len
, &written
, NULL
))
453 if (!ReadFile(ctrl
->pipe
, reply
, *reply_len
, &readlen
, NULL
))
455 *reply_len
= readlen
;
461 int wpa_ctrl_recv(struct wpa_ctrl
*ctrl
, char *reply
, size_t *reply_len
)
463 DWORD len
= *reply_len
;
464 if (!ReadFile(ctrl
->pipe
, reply
, *reply_len
, &len
, NULL
))
471 int wpa_ctrl_pending(struct wpa_ctrl
*ctrl
)
475 if (!PeekNamedPipe(ctrl
->pipe
, NULL
, 0, NULL
, &left
, NULL
))
481 int wpa_ctrl_get_fd(struct wpa_ctrl
*ctrl
)
486 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
488 #endif /* CONFIG_CTRL_IFACE */