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