OSDN Git Service

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