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