1 /*
2 * WPA Supplicant / Zephyr socket pair -based control interface
3 * Copyright (c) 2022, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "ctrl_iface_zephyr.h"
10
wpa_supplicant_ctrl_iface_receive(int sock,void * eloop_ctx,void * sock_ctx)11 static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
12 void *sock_ctx)
13 {
14 struct wpa_supplicant *wpa_s = eloop_ctx;
15 char *buf, *pos;
16 int res;
17 char *reply = NULL;
18 size_t reply_len = 0;
19
20 buf = os_zalloc(CTRL_IFACE_MAX_LEN + 1);
21 if (!buf)
22 return;
23 res = recv(sock, buf, CTRL_IFACE_MAX_LEN, 0);
24 if (res < 0) {
25 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
26 strerror(errno));
27 os_free(buf);
28 return;
29 }
30
31 if ((size_t) res > CTRL_IFACE_MAX_LEN) {
32 wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated");
33 os_free(buf);
34 return;
35 }
36 buf[res] = '\0';
37
38 pos = buf;
39 while (*pos == ' ')
40 pos++;
41
42 reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos,
43 &reply_len);
44
45 if (reply) {
46 send(sock, reply, reply_len, 0);
47 os_free(reply);
48 } else if (reply_len == 1) {
49 send(sock, "FAIL\n", 5, 0);
50 } else if (reply_len == 2) {
51 send(sock, "OK\n", 3, 0);
52 }
53
54 os_free(buf);
55 }
56
57
58 struct ctrl_iface_priv *
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant * wpa_s)59 wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
60 {
61 struct ctrl_iface_priv *priv;
62 int ret;
63
64 priv = os_zalloc(sizeof(*priv));
65 if (priv == NULL)
66 return NULL;
67 priv->wpa_s = wpa_s;
68 memset(priv->sock_pair, -1, sizeof(priv->sock_pair));
69
70 if (wpa_s->conf->ctrl_interface == NULL)
71 return priv;
72
73 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, priv->sock_pair);
74 if (ret != 0) {
75 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
76 goto fail;
77 }
78
79 os_free(wpa_s->conf->ctrl_interface);
80 wpa_s->conf->ctrl_interface = os_strdup("zephyr:");
81 if (!wpa_s->conf->ctrl_interface) {
82 wpa_msg(wpa_s, MSG_ERROR, "Failed to malloc ctrl_interface");
83 goto fail;
84 }
85
86 eloop_register_read_sock(priv->sock_pair[1], wpa_supplicant_ctrl_iface_receive,
87 wpa_s, priv);
88
89 return priv;
90
91 fail:
92 if (priv->sock_pair[0] >= 0)
93 close(priv->sock_pair[0]);
94 if (priv->sock_pair[1] >= 0)
95 close(priv->sock_pair[1]);
96 os_free(priv);
97 return NULL;
98 }
99
100
wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant * wpa_s,struct ctrl_iface_priv * priv)101 void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
102 struct ctrl_iface_priv *priv)
103 {
104 if (!priv)
105 return;
106
107 if (priv->sock_pair[0] > -1) {
108 eloop_unregister_read_sock(priv->sock_pair[0]);
109 close(priv->sock_pair[0]);
110 priv->sock_pair[0] = -1;
111 }
112
113 if (priv->sock_pair[1] >= 0)
114 close(priv->sock_pair[1]);
115
116 os_free(priv);
117 }
118
119 void
wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv * priv)120 wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
121 {
122 }
123
124 /* Global control interface */
125
wpa_supplicant_global_ctrl_iface_receive(int sock,void * eloop_ctx,void * sock_ctx)126 static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
127 void *sock_ctx)
128 {
129 struct wpa_global *global = eloop_ctx;
130 char *buf, *pos;
131 int res;
132 char *reply = NULL;
133 size_t reply_len = 0;
134
135 buf = os_zalloc(CTRL_IFACE_MAX_LEN + 1);
136 if (!buf)
137 return;
138 res = recv(sock, buf, CTRL_IFACE_MAX_LEN, 0);
139 if (res < 0) {
140 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
141 strerror(errno));
142 os_free(buf);
143 return;
144 }
145
146 if ((size_t) res > CTRL_IFACE_MAX_LEN) {
147 wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated");
148 os_free(buf);
149 return;
150 }
151 buf[res] = '\0';
152
153 pos = buf;
154 while (*pos == ' ')
155 pos++;
156
157 reply = wpa_supplicant_global_ctrl_iface_process(global, pos,
158 &reply_len);
159
160 if (reply) {
161 send(sock, reply, reply_len, 0);
162 os_free(reply);
163 } else if (reply_len == 1) {
164 send(sock, "FAIL\n", 5, 0);
165 } else if (reply_len == 2) {
166 send(sock, "OK\n", 3, 0);
167 }
168
169 os_free(buf);
170 }
171 struct ctrl_iface_global_priv *
wpa_supplicant_global_ctrl_iface_init(struct wpa_global * global)172 wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
173 {
174 struct ctrl_iface_global_priv *priv;
175 int ret;
176
177 priv = os_zalloc(sizeof(*priv));
178 if (priv == NULL)
179 return NULL;
180 priv->global = global;
181 memset(priv->sock_pair, -1, sizeof(priv->sock_pair));
182
183 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, priv->sock_pair);
184 if (ret != 0) {
185 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
186 goto fail;
187 }
188
189 os_free(global->params.ctrl_interface);
190 global->params.ctrl_interface = os_strdup("g_zephyr:");
191 if (!global->params.ctrl_interface) {
192 wpa_printf(MSG_ERROR, "Failed to malloc global ctrl_interface\n");
193 goto fail;
194 }
195
196 eloop_register_read_sock(priv->sock_pair[1], wpa_supplicant_global_ctrl_iface_receive,
197 global, priv);
198
199 return priv;
200
201 fail:
202 if (priv->sock_pair[0] >= 0)
203 close(priv->sock_pair[0]);
204 if (priv->sock_pair[1] >= 0)
205 close(priv->sock_pair[1]);
206 os_free(priv);
207 return NULL;
208 }
209
210 void
wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv * priv)211 wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
212 {
213 if (!priv)
214 return;
215
216 if (priv->sock_pair[0] > -1) {
217 eloop_unregister_read_sock(priv->sock_pair[0]);
218 close(priv->sock_pair[0]);
219 priv->sock_pair[0] = -1;
220 }
221
222 if (priv->sock_pair[1] >= 0)
223 close(priv->sock_pair[1]);
224
225 os_free(priv);
226 }
227