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