blob: 043cf1954326519ddf8d65713b40ec8234e1f8e4 [file] [log] [blame]
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001/*
2 * wpa_supplicant/hostapd control interface library
3 * Copyright (c) 2004-2007, 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 <stdlib.h>
10#include <stdio.h>
11#include <string.h>
12#include <unistd.h>
13#include <errno.h>
14#include <sys/types.h>
15#include <sys/socket.h>
16#ifdef __QNXNTO__
17#include <sys/select.h>
18#endif /* __QNXNTO__ */
19#include <sys/stat.h>
20
21#define CONFIG_CTRL_IFACE
22#define CONFIG_CTRL_IFACE_UNIX
23#define os_malloc malloc
24#define os_free free
25#define os_memset memset
26#define os_memcmp memcmp
27#define os_snprintf snprintf
28#define os_strlen strlen
29#define os_strncmp strncmp
30
31static size_t os_strlcpy(char *dest, const char *src, size_t siz)
32{
33 const char *s = src;
34 size_t left = siz;
35
36 if (left) {
37 /* Copy string up to the maximum size of the dest buffer */
38 while (--left != 0) {
39 if ((*dest++ = *s++) == '\0')
40 break;
41 }
42 }
43
44 if (left == 0) {
45 /* Not enough room for the string; force NUL-termination */
46 if (siz != 0)
47 *dest = '\0';
48 while (*s++)
49 ; /* determine total src string length */
50 }
51
52 return s - src - 1;
53}
54
55#ifdef CONFIG_CTRL_IFACE
56
57#ifdef CONFIG_CTRL_IFACE_UNIX
58#include <sys/un.h>
59#endif /* CONFIG_CTRL_IFACE_UNIX */
60
61#ifdef ANDROID
62#include <dirent.h>
63#include <cutils/sockets.h>
64#include "private/android_filesystem_config.h"
65#endif /* ANDROID */
66
67#include "wpa_ctrl.h"
68
69
70#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
71#define CTRL_IFACE_SOCKET
72#endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
73
74
75/**
76 * struct wpa_ctrl - Internal structure for control interface library
77 *
78 * This structure is used by the wpa_supplicant/hostapd control interface
79 * library to store internal data. Programs using the library should not touch
80 * this data directly. They can only use the pointer to the data structure as
81 * an identifier for the control interface connection and use this as one of
82 * the arguments for most of the control interface library functions.
83 */
84struct wpa_ctrl {
85#ifdef CONFIG_CTRL_IFACE_UDP
86 int s;
87 struct sockaddr_in local;
88 struct sockaddr_in dest;
89 char *cookie;
90#endif /* CONFIG_CTRL_IFACE_UDP */
91#ifdef CONFIG_CTRL_IFACE_UNIX
92 int s;
93 struct sockaddr_un local;
94 struct sockaddr_un dest;
95#endif /* CONFIG_CTRL_IFACE_UNIX */
96#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
97 HANDLE pipe;
98#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
99};
100
101
102#ifdef CONFIG_CTRL_IFACE_UNIX
103
104#ifndef CONFIG_CTRL_IFACE_CLIENT_DIR
105#define CONFIG_CTRL_IFACE_CLIENT_DIR "/tmp"
106#endif /* CONFIG_CTRL_IFACE_CLIENT_DIR */
107#ifndef CONFIG_CTRL_IFACE_CLIENT_PREFIX
108#define CONFIG_CTRL_IFACE_CLIENT_PREFIX "wpa_ctrl_"
109#endif /* CONFIG_CTRL_IFACE_CLIENT_PREFIX */
110
111
112struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
113{
114 struct wpa_ctrl *ctrl;
115 static int counter = 0;
116 int ret;
117 size_t res;
118 int tries = 0;
119
Pradeep Reddy POTTETI5df800e2016-01-29 13:21:41 +0530120 if (ctrl_path == NULL)
121 return NULL;
122
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200123 ctrl = os_malloc(sizeof(*ctrl));
124 if (ctrl == NULL)
125 return NULL;
126 os_memset(ctrl, 0, sizeof(*ctrl));
127
128 ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
129 if (ctrl->s < 0) {
130 os_free(ctrl);
131 return NULL;
132 }
133
134 ctrl->local.sun_family = AF_UNIX;
135 counter++;
136try_again:
137 ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
138 CONFIG_CTRL_IFACE_CLIENT_DIR "/"
139 CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d",
140 (int) getpid(), counter);
141 if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
142 close(ctrl->s);
143 os_free(ctrl);
144 return NULL;
145 }
146 tries++;
147 if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
148 sizeof(ctrl->local)) < 0) {
149 if (errno == EADDRINUSE && tries < 2) {
150 /*
151 * getpid() returns unique identifier for this instance
152 * of wpa_ctrl, so the existing socket file must have
153 * been left by unclean termination of an earlier run.
154 * Remove the file and try again.
155 */
156 unlink(ctrl->local.sun_path);
157 goto try_again;
158 }
159 close(ctrl->s);
160 os_free(ctrl);
161 return NULL;
162 }
163
164#ifdef ANDROID
165 chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
166 chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
167 /*
168 * If the ctrl_path isn't an absolute pathname, assume that
169 * it's the name of a socket in the Android reserved namespace.
170 * Otherwise, it's a normal UNIX domain socket appearing in the
171 * filesystem.
172 */
Pradeep Reddy POTTETI5df800e2016-01-29 13:21:41 +0530173 if (*ctrl_path != '/') {
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200174 char buf[21];
175 os_snprintf(buf, sizeof(buf), "wpa_%s", ctrl_path);
176 if (socket_local_client_connect(
177 ctrl->s, buf,
178 ANDROID_SOCKET_NAMESPACE_RESERVED,
179 SOCK_DGRAM) < 0) {
180 close(ctrl->s);
181 unlink(ctrl->local.sun_path);
182 os_free(ctrl);
183 return NULL;
184 }
185 return ctrl;
186 }
187#endif /* ANDROID */
188
189 ctrl->dest.sun_family = AF_UNIX;
190 res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
191 sizeof(ctrl->dest.sun_path));
192 if (res >= sizeof(ctrl->dest.sun_path)) {
193 close(ctrl->s);
194 os_free(ctrl);
195 return NULL;
196 }
197 if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
198 sizeof(ctrl->dest)) < 0) {
199 close(ctrl->s);
200 unlink(ctrl->local.sun_path);
201 os_free(ctrl);
202 return NULL;
203 }
204
205 return ctrl;
206}
207
208
209void wpa_ctrl_close(struct wpa_ctrl *ctrl)
210{
211 if (ctrl == NULL)
212 return;
213 unlink(ctrl->local.sun_path);
214 if (ctrl->s >= 0)
215 close(ctrl->s);
216 os_free(ctrl);
217}
218
219
220#ifdef ANDROID
221/**
222 * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
223 * may be left over from clients that were previously connected to
224 * wpa_supplicant. This keeps these files from being orphaned in the
225 * event of crashes that prevented them from being removed as part
226 * of the normal orderly shutdown.
227 */
228void wpa_ctrl_cleanup(void)
229{
230 DIR *dir;
231 struct dirent entry;
232 struct dirent *result;
233 size_t dirnamelen;
234 int prefixlen = os_strlen(CONFIG_CTRL_IFACE_CLIENT_PREFIX);
235 size_t maxcopy;
236 char pathname[PATH_MAX];
237 char *namep;
238
239 if ((dir = opendir(CONFIG_CTRL_IFACE_CLIENT_DIR)) == NULL)
240 return;
241
242 dirnamelen = (size_t) os_snprintf(pathname, sizeof(pathname), "%s/",
243 CONFIG_CTRL_IFACE_CLIENT_DIR);
244 if (dirnamelen >= sizeof(pathname)) {
245 closedir(dir);
246 return;
247 }
248 namep = pathname + dirnamelen;
249 maxcopy = PATH_MAX - dirnamelen;
250 while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
251 if (os_strncmp(entry.d_name, CONFIG_CTRL_IFACE_CLIENT_PREFIX,
252 prefixlen) == 0) {
253 if (os_strlcpy(namep, entry.d_name, maxcopy) < maxcopy)
254 unlink(pathname);
255 }
256 }
257 closedir(dir);
258}
259#endif /* ANDROID */
260
261#else /* CONFIG_CTRL_IFACE_UNIX */
262
263#ifdef ANDROID
264void wpa_ctrl_cleanup(void)
265{
266}
267#endif /* ANDROID */
268
269#endif /* CONFIG_CTRL_IFACE_UNIX */
270
271
272#ifdef CONFIG_CTRL_IFACE_UDP
273
274struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
275{
276 struct wpa_ctrl *ctrl;
277 char buf[128];
278 size_t len;
279
280 ctrl = os_malloc(sizeof(*ctrl));
281 if (ctrl == NULL)
282 return NULL;
283 os_memset(ctrl, 0, sizeof(*ctrl));
284
285 ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
286 if (ctrl->s < 0) {
287 perror("socket");
288 os_free(ctrl);
289 return NULL;
290 }
291
292 ctrl->local.sin_family = AF_INET;
293 ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
294 if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
295 sizeof(ctrl->local)) < 0) {
296 close(ctrl->s);
297 os_free(ctrl);
298 return NULL;
299 }
300
301 ctrl->dest.sin_family = AF_INET;
302 ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
303 ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
304 if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
305 sizeof(ctrl->dest)) < 0) {
306 perror("connect");
307 close(ctrl->s);
308 os_free(ctrl);
309 return NULL;
310 }
311
312 len = sizeof(buf) - 1;
313 if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
314 buf[len] = '\0';
315 ctrl->cookie = os_strdup(buf);
316 }
317
318 return ctrl;
319}
320
321
322void wpa_ctrl_close(struct wpa_ctrl *ctrl)
323{
324 close(ctrl->s);
325 os_free(ctrl->cookie);
326 os_free(ctrl);
327}
328
329#endif /* CONFIG_CTRL_IFACE_UDP */
330
331
332#ifdef CTRL_IFACE_SOCKET
333int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
334 char *reply, size_t *reply_len,
335 void (*msg_cb)(char *msg, size_t len))
336{
337 struct timeval tv;
338 int res;
339 fd_set rfds;
340 const char *_cmd;
341 char *cmd_buf = NULL;
342 size_t _cmd_len;
343
344#ifdef CONFIG_CTRL_IFACE_UDP
345 if (ctrl->cookie) {
346 char *pos;
347 _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len;
348 cmd_buf = os_malloc(_cmd_len);
349 if (cmd_buf == NULL)
350 return -1;
351 _cmd = cmd_buf;
352 pos = cmd_buf;
353 os_strlcpy(pos, ctrl->cookie, _cmd_len);
354 pos += os_strlen(ctrl->cookie);
355 *pos++ = ' ';
356 os_memcpy(pos, cmd, cmd_len);
357 } else
358#endif /* CONFIG_CTRL_IFACE_UDP */
359 {
360 _cmd = cmd;
361 _cmd_len = cmd_len;
362 }
363
364 if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
365 os_free(cmd_buf);
366 return -1;
367 }
368 os_free(cmd_buf);
369
370 for (;;) {
371 tv.tv_sec = 10;
372 tv.tv_usec = 0;
373 FD_ZERO(&rfds);
374 FD_SET(ctrl->s, &rfds);
375 res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
376 if (res < 0)
377 return res;
378 if (FD_ISSET(ctrl->s, &rfds)) {
379 res = recv(ctrl->s, reply, *reply_len, 0);
380 if (res < 0)
381 return res;
382 if (res > 0 && reply[0] == '<') {
383 /* This is an unsolicited message from
384 * wpa_supplicant, not the reply to the
385 * request. Use msg_cb to report this to the
386 * caller. */
387 if (msg_cb) {
388 /* Make sure the message is nul
389 * terminated. */
390 if ((size_t) res == *reply_len)
391 res = (*reply_len) - 1;
392 reply[res] = '\0';
393 msg_cb(reply, res);
394 }
395 continue;
396 }
397 *reply_len = res;
398 break;
399 } else {
400 return -2;
401 }
402 }
403 return 0;
404}
405#endif /* CTRL_IFACE_SOCKET */
406
407
408static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
409{
410 char buf[10];
411 int ret;
412 size_t len = 10;
413
414 ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
415 buf, &len, NULL);
416 if (ret < 0)
417 return ret;
418 if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0)
419 return 0;
420 return -1;
421}
422
423
424int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
425{
426 return wpa_ctrl_attach_helper(ctrl, 1);
427}
428
429
430int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
431{
432 return wpa_ctrl_attach_helper(ctrl, 0);
433}
434
435
436#ifdef CTRL_IFACE_SOCKET
437
438int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
439{
440 int res;
441
442 res = recv(ctrl->s, reply, *reply_len, 0);
443 if (res < 0)
444 return res;
445 *reply_len = res;
446 return 0;
447}
448
449
450int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
451{
452 struct timeval tv;
453 fd_set rfds;
454 tv.tv_sec = 0;
455 tv.tv_usec = 0;
456 FD_ZERO(&rfds);
457 FD_SET(ctrl->s, &rfds);
458 select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
459 return FD_ISSET(ctrl->s, &rfds);
460}
461
462
463int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
464{
465 return ctrl->s;
466}
467
468#endif /* CTRL_IFACE_SOCKET */
469
470
471#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
472
473#ifndef WPA_SUPPLICANT_NAMED_PIPE
474#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
475#endif
476#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
477
478struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
479{
480 struct wpa_ctrl *ctrl;
481 DWORD mode;
482 TCHAR name[256];
483 int i, ret;
484
485 ctrl = os_malloc(sizeof(*ctrl));
486 if (ctrl == NULL)
487 return NULL;
488 os_memset(ctrl, 0, sizeof(*ctrl));
489
490#ifdef UNICODE
491 if (ctrl_path == NULL)
492 ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX);
493 else
494 ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
495 ctrl_path);
496#else /* UNICODE */
497 if (ctrl_path == NULL)
498 ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX);
499 else
500 ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
501 ctrl_path);
502#endif /* UNICODE */
503 if (ret < 0 || ret >= 256) {
504 os_free(ctrl);
505 return NULL;
506 }
507
508 for (i = 0; i < 10; i++) {
509 ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
510 NULL, OPEN_EXISTING, 0, NULL);
511 /*
512 * Current named pipe server side in wpa_supplicant is
513 * re-opening the pipe for new clients only after the previous
514 * one is taken into use. This leaves a small window for race
515 * conditions when two connections are being opened at almost
516 * the same time. Retry if that was the case.
517 */
518 if (ctrl->pipe != INVALID_HANDLE_VALUE ||
519 GetLastError() != ERROR_PIPE_BUSY)
520 break;
521 WaitNamedPipe(name, 1000);
522 }
523 if (ctrl->pipe == INVALID_HANDLE_VALUE) {
524 os_free(ctrl);
525 return NULL;
526 }
527
528 mode = PIPE_READMODE_MESSAGE;
529 if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
530 CloseHandle(ctrl->pipe);
531 os_free(ctrl);
532 return NULL;
533 }
534
535 return ctrl;
536}
537
538
539void wpa_ctrl_close(struct wpa_ctrl *ctrl)
540{
541 CloseHandle(ctrl->pipe);
542 os_free(ctrl);
543}
544
545
546int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
547 char *reply, size_t *reply_len,
548 void (*msg_cb)(char *msg, size_t len))
549{
550 DWORD written;
551 DWORD readlen = *reply_len;
552
553 if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL))
554 return -1;
555
556 if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL))
557 return -1;
558 *reply_len = readlen;
559
560 return 0;
561}
562
563
564int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
565{
566 DWORD len = *reply_len;
567 if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL))
568 return -1;
569 *reply_len = len;
570 return 0;
571}
572
573
574int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
575{
576 DWORD left;
577
578 if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL))
579 return -1;
580 return left ? 1 : 0;
581}
582
583
584int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
585{
586 return -1;
587}
588
589#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
590
591#endif /* CONFIG_CTRL_IFACE */