2 * wpa_supplicant/hostapd control interface library
3 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.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.
19 #include <sys/types.h>
21 #ifndef CONFIG_NATIVE_WINDOWS
22 #include <sys/socket.h>
23 #include <netinet/in.h>
25 #endif /* CONFIG_NATIVE_WINDOWS */
28 #ifdef CONFIG_NATIVE_WINDOWS
30 #endif /* CONFIG_NATIVE_WINDOWS */
34 * struct wpa_ctrl - Internal structure for control interface library
36 * This structure is used by the wpa_supplicant/hostapd control interface
37 * library to store internal data. Programs using the library should not touch
38 * this data directly. They can only use the pointer to the data structure as
39 * an identifier for the control interface connection and use this as one of
40 * the arguments for most of the control interface library functions.
44 #ifdef CONFIG_CTRL_IFACE_UDP
45 struct sockaddr_in local
;
46 struct sockaddr_in dest
;
47 #else /* CONFIG_CTRL_IFACE_UDP */
48 struct sockaddr_un local
;
49 struct sockaddr_un dest
;
50 #endif /* CONFIG_CTRL_IFACE_UDP */
54 struct wpa_ctrl
* wpa_ctrl_open(const char *ctrl_path
)
56 struct wpa_ctrl
*ctrl
;
57 #ifndef CONFIG_CTRL_IFACE_UDP
58 static int counter
= 0;
59 #endif /* CONFIG_CTRL_IFACE_UDP */
61 ctrl
= malloc(sizeof(*ctrl
));
64 memset(ctrl
, 0, sizeof(*ctrl
));
66 #ifdef CONFIG_CTRL_IFACE_UDP
67 ctrl
->s
= socket(PF_INET
, SOCK_DGRAM
, 0);
74 ctrl
->local
.sin_family
= AF_INET
;
75 ctrl
->local
.sin_addr
.s_addr
= htonl((127 << 24) | 1);
76 if (bind(ctrl
->s
, (struct sockaddr
*) &ctrl
->local
,
77 sizeof(ctrl
->local
)) < 0) {
83 ctrl
->dest
.sin_family
= AF_INET
;
84 ctrl
->dest
.sin_addr
.s_addr
= htonl((127 << 24) | 1);
85 ctrl
->dest
.sin_port
= htons(WPA_CTRL_IFACE_PORT
);
86 if (connect(ctrl
->s
, (struct sockaddr
*) &ctrl
->dest
,
87 sizeof(ctrl
->dest
)) < 0) {
93 #else /* CONFIG_CTRL_IFACE_UDP */
94 ctrl
->s
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
100 ctrl
->local
.sun_family
= AF_UNIX
;
101 snprintf(ctrl
->local
.sun_path
, sizeof(ctrl
->local
.sun_path
),
102 "/tmp/wpa_ctrl_%d-%d", getpid(), counter
++);
103 if (bind(ctrl
->s
, (struct sockaddr
*) &ctrl
->local
,
104 sizeof(ctrl
->local
)) < 0) {
110 ctrl
->dest
.sun_family
= AF_UNIX
;
111 snprintf(ctrl
->dest
.sun_path
, sizeof(ctrl
->dest
.sun_path
), "%s",
113 if (connect(ctrl
->s
, (struct sockaddr
*) &ctrl
->dest
,
114 sizeof(ctrl
->dest
)) < 0) {
116 unlink(ctrl
->local
.sun_path
);
120 #endif /* CONFIG_CTRL_IFACE_UDP */
126 void wpa_ctrl_close(struct wpa_ctrl
*ctrl
)
128 #ifndef CONFIG_CTRL_IFACE_UDP
129 unlink(ctrl
->local
.sun_path
);
130 #endif /* CONFIG_CTRL_IFACE_UDP */
136 int wpa_ctrl_request(struct wpa_ctrl
*ctrl
, const char *cmd
, size_t cmd_len
,
137 char *reply
, size_t *reply_len
,
138 void (*msg_cb
)(char *msg
, size_t len
))
144 if (send(ctrl
->s
, cmd
, cmd_len
, 0) < 0)
151 FD_SET(ctrl
->s
, &rfds
);
152 res
= select(ctrl
->s
+ 1, &rfds
, NULL
, NULL
, &tv
);
153 if (FD_ISSET(ctrl
->s
, &rfds
)) {
154 res
= recv(ctrl
->s
, reply
, *reply_len
, 0);
157 if (res
> 0 && reply
[0] == '<') {
158 /* This is an unsolicited message from
159 * wpa_supplicant, not the reply to the
160 * request. Use msg_cb to report this to the
163 /* Make sure the message is nul
165 if ((size_t) res
== *reply_len
)
166 res
= (*reply_len
) - 1;
182 static int wpa_ctrl_attach_helper(struct wpa_ctrl
*ctrl
, int attach
)
188 ret
= wpa_ctrl_request(ctrl
, attach
? "ATTACH" : "DETACH", 6,
192 if (len
== 3 && memcmp(buf
, "OK\n", 3) == 0)
198 int wpa_ctrl_attach(struct wpa_ctrl
*ctrl
)
200 return wpa_ctrl_attach_helper(ctrl
, 1);
204 int wpa_ctrl_detach(struct wpa_ctrl
*ctrl
)
206 return wpa_ctrl_attach_helper(ctrl
, 0);
210 int wpa_ctrl_recv(struct wpa_ctrl
*ctrl
, char *reply
, size_t *reply_len
)
214 res
= recv(ctrl
->s
, reply
, *reply_len
, 0);
222 int wpa_ctrl_pending(struct wpa_ctrl
*ctrl
)
230 FD_SET(ctrl
->s
, &rfds
);
231 res
= select(ctrl
->s
+ 1, &rfds
, NULL
, NULL
, &tv
);
232 return FD_ISSET(ctrl
->s
, &rfds
);
236 int wpa_ctrl_get_fd(struct wpa_ctrl
*ctrl
)