wifi.c revision 2c52037dd46f066be122b0520b265d55eb4e0470
1/*
2 * Copyright 2008, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <fcntl.h>
19#include <errno.h>
20#include <string.h>
21#include <dirent.h>
22#include <sys/socket.h>
23#include <unistd.h>
24#include <poll.h>
25
26#include "hardware_legacy/wifi.h"
27#include "libwpa_client/wpa_ctrl.h"
28
29#define LOG_TAG "WifiHW"
30#include "cutils/log.h"
31#include "cutils/memory.h"
32#include "cutils/misc.h"
33#include "cutils/properties.h"
34#include "private/android_filesystem_config.h"
35#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
36#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
37#include <sys/_system_properties.h>
38#endif
39
40/* PRIMARY refers to the connection on the primary interface
41 * SECONDARY refers to an optional connection on a p2p interface
42 *
43 * For concurrency, we only support one active p2p connection and
44 * one active STA connection at a time
45 */
46#define PRIMARY     0
47#define SECONDARY   1
48#define MAX_CONNS   2
49
50static struct wpa_ctrl *ctrl_conn[MAX_CONNS];
51static struct wpa_ctrl *monitor_conn[MAX_CONNS];
52
53/* socket pair used to exit from a blocking read */
54static int exit_sockets[MAX_CONNS][2];
55
56extern int do_dhcp();
57extern int ifc_init();
58extern void ifc_close();
59extern char *dhcp_lasterror();
60extern void get_dhcp_info();
61extern int init_module(void *, unsigned long, const char *);
62extern int delete_module(const char *, unsigned int);
63void wifi_close_sockets(int index);
64
65static char primary_iface[PROPERTY_VALUE_MAX];
66// TODO: use new ANDROID_SOCKET mechanism, once support for multiple
67// sockets is in
68
69#ifndef WIFI_DRIVER_MODULE_ARG
70#define WIFI_DRIVER_MODULE_ARG          ""
71#endif
72#ifndef WIFI_FIRMWARE_LOADER
73#define WIFI_FIRMWARE_LOADER		""
74#endif
75#define WIFI_TEST_INTERFACE		"sta"
76
77#ifndef WIFI_DRIVER_FW_PATH_STA
78#define WIFI_DRIVER_FW_PATH_STA		NULL
79#endif
80#ifndef WIFI_DRIVER_FW_PATH_AP
81#define WIFI_DRIVER_FW_PATH_AP		NULL
82#endif
83#ifndef WIFI_DRIVER_FW_PATH_P2P
84#define WIFI_DRIVER_FW_PATH_P2P		NULL
85#endif
86
87#ifndef WIFI_DRIVER_FW_PATH_PARAM
88#define WIFI_DRIVER_FW_PATH_PARAM	"/sys/module/wlan/parameters/fwpath"
89#endif
90
91#define WIFI_DRIVER_LOADER_DELAY	1000000
92
93static const char IFACE_DIR[]           = "/data/system/wpa_supplicant";
94#ifdef WIFI_DRIVER_MODULE_PATH
95static const char DRIVER_MODULE_NAME[]  = WIFI_DRIVER_MODULE_NAME;
96static const char DRIVER_MODULE_TAG[]   = WIFI_DRIVER_MODULE_NAME " ";
97static const char DRIVER_MODULE_PATH[]  = WIFI_DRIVER_MODULE_PATH;
98static const char DRIVER_MODULE_ARG[]   = WIFI_DRIVER_MODULE_ARG;
99#endif
100static const char FIRMWARE_LOADER[]     = WIFI_FIRMWARE_LOADER;
101static const char DRIVER_PROP_NAME[]    = "wlan.driver.status";
102static const char SUPPLICANT_NAME[]     = "wpa_supplicant";
103static const char SUPP_PROP_NAME[]      = "init.svc.wpa_supplicant";
104static const char P2P_SUPPLICANT_NAME[] = "p2p_supplicant";
105static const char P2P_PROP_NAME[]       = "init.svc.p2p_supplicant";
106static const char SUPP_CONFIG_TEMPLATE[]= "/system/etc/wifi/wpa_supplicant.conf";
107static const char SUPP_CONFIG_FILE[]    = "/data/misc/wifi/wpa_supplicant.conf";
108static const char P2P_CONFIG_FILE[]     = "/data/misc/wifi/p2p_supplicant.conf";
109static const char CONTROL_IFACE_PATH[]  = "/data/misc/wifi/sockets";
110static const char MODULE_FILE[]         = "/proc/modules";
111
112static const char SUPP_ENTROPY_FILE[]   = WIFI_ENTROPY_FILE;
113static unsigned char dummy_key[21] = { 0x02, 0x11, 0xbe, 0x33, 0x43, 0x35,
114                                       0x68, 0x47, 0x84, 0x99, 0xa9, 0x2b,
115                                       0x1c, 0xd3, 0xee, 0xff, 0xf1, 0xe2,
116                                       0xf3, 0xf4, 0xf5 };
117
118/* Is either SUPPLICANT_NAME or P2P_SUPPLICANT_NAME */
119static char supplicant_name[PROPERTY_VALUE_MAX];
120/* Is either SUPP_PROP_NAME or P2P_PROP_NAME */
121static char supplicant_prop_name[PROPERTY_KEY_MAX];
122
123static int is_primary_interface(const char *ifname)
124{
125    //Treat NULL as primary interface to allow control
126    //on STA without an interface
127    if (ifname == NULL || !strncmp(ifname, primary_iface, strlen(primary_iface))) {
128        return 1;
129    }
130    return 0;
131}
132
133static int insmod(const char *filename, const char *args)
134{
135    void *module;
136    unsigned int size;
137    int ret;
138
139    module = load_file(filename, &size);
140    if (!module)
141        return -1;
142
143    ret = init_module(module, size, args);
144
145    free(module);
146
147    return ret;
148}
149
150static int rmmod(const char *modname)
151{
152    int ret = -1;
153    int maxtry = 10;
154
155    while (maxtry-- > 0) {
156        ret = delete_module(modname, O_NONBLOCK | O_EXCL);
157        if (ret < 0 && errno == EAGAIN)
158            usleep(500000);
159        else
160            break;
161    }
162
163    if (ret != 0)
164        ALOGD("Unable to unload driver module \"%s\": %s\n",
165             modname, strerror(errno));
166    return ret;
167}
168
169int do_dhcp_request(int *ipaddr, int *gateway, int *mask,
170                    int *dns1, int *dns2, int *server, int *lease) {
171    /* For test driver, always report success */
172    if (strcmp(primary_iface, WIFI_TEST_INTERFACE) == 0)
173        return 0;
174
175    if (ifc_init() < 0)
176        return -1;
177
178    if (do_dhcp(primary_iface) < 0) {
179        ifc_close();
180        return -1;
181    }
182    ifc_close();
183    get_dhcp_info(ipaddr, gateway, mask, dns1, dns2, server, lease);
184    return 0;
185}
186
187const char *get_dhcp_error_string() {
188    return dhcp_lasterror();
189}
190
191int is_wifi_driver_loaded() {
192    char driver_status[PROPERTY_VALUE_MAX];
193#ifdef WIFI_DRIVER_MODULE_PATH
194    FILE *proc;
195    char line[sizeof(DRIVER_MODULE_TAG)+10];
196#endif
197
198    if (!property_get(DRIVER_PROP_NAME, driver_status, NULL)
199            || strcmp(driver_status, "ok") != 0) {
200        return 0;  /* driver not loaded */
201    }
202#ifdef WIFI_DRIVER_MODULE_PATH
203    /*
204     * If the property says the driver is loaded, check to
205     * make sure that the property setting isn't just left
206     * over from a previous manual shutdown or a runtime
207     * crash.
208     */
209    if ((proc = fopen(MODULE_FILE, "r")) == NULL) {
210        ALOGW("Could not open %s: %s", MODULE_FILE, strerror(errno));
211        property_set(DRIVER_PROP_NAME, "unloaded");
212        return 0;
213    }
214    while ((fgets(line, sizeof(line), proc)) != NULL) {
215        if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) {
216            fclose(proc);
217            return 1;
218        }
219    }
220    fclose(proc);
221    property_set(DRIVER_PROP_NAME, "unloaded");
222    return 0;
223#else
224    return 1;
225#endif
226}
227
228int wifi_load_driver()
229{
230#ifdef WIFI_DRIVER_MODULE_PATH
231    char driver_status[PROPERTY_VALUE_MAX];
232    int count = 100; /* wait at most 20 seconds for completion */
233
234    if (is_wifi_driver_loaded()) {
235        return 0;
236    }
237
238    if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
239        return -1;
240
241    if (strcmp(FIRMWARE_LOADER,"") == 0) {
242        /* usleep(WIFI_DRIVER_LOADER_DELAY); */
243        property_set(DRIVER_PROP_NAME, "ok");
244    }
245    else {
246        property_set("ctl.start", FIRMWARE_LOADER);
247    }
248    sched_yield();
249    while (count-- > 0) {
250        if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
251            if (strcmp(driver_status, "ok") == 0)
252                return 0;
253            else if (strcmp(DRIVER_PROP_NAME, "failed") == 0) {
254                wifi_unload_driver();
255                return -1;
256            }
257        }
258        usleep(200000);
259    }
260    property_set(DRIVER_PROP_NAME, "timeout");
261    wifi_unload_driver();
262    return -1;
263#else
264    property_set(DRIVER_PROP_NAME, "ok");
265    return 0;
266#endif
267}
268
269int wifi_unload_driver()
270{
271    usleep(200000); /* allow to finish interface down */
272#ifdef WIFI_DRIVER_MODULE_PATH
273    if (rmmod(DRIVER_MODULE_NAME) == 0) {
274        int count = 20; /* wait at most 10 seconds for completion */
275        while (count-- > 0) {
276            if (!is_wifi_driver_loaded())
277                break;
278            usleep(500000);
279        }
280        usleep(500000); /* allow card removal */
281        if (count) {
282            return 0;
283        }
284        return -1;
285    } else
286        return -1;
287#else
288    property_set(DRIVER_PROP_NAME, "unloaded");
289    return 0;
290#endif
291}
292
293int ensure_entropy_file_exists()
294{
295    int ret;
296    int destfd;
297
298    ret = access(SUPP_ENTROPY_FILE, R_OK|W_OK);
299    if ((ret == 0) || (errno == EACCES)) {
300        if ((ret != 0) &&
301            (chmod(SUPP_ENTROPY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) {
302            ALOGE("Cannot set RW to \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
303            return -1;
304        }
305        return 0;
306    }
307    destfd = TEMP_FAILURE_RETRY(open(SUPP_ENTROPY_FILE, O_CREAT|O_RDWR, 0660));
308    if (destfd < 0) {
309        ALOGE("Cannot create \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
310        return -1;
311    }
312
313    if (TEMP_FAILURE_RETRY(write(destfd, dummy_key, sizeof(dummy_key))) != sizeof(dummy_key)) {
314        ALOGE("Error writing \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
315        close(destfd);
316        return -1;
317    }
318    close(destfd);
319
320    /* chmod is needed because open() didn't set permisions properly */
321    if (chmod(SUPP_ENTROPY_FILE, 0660) < 0) {
322        ALOGE("Error changing permissions of %s to 0660: %s",
323             SUPP_ENTROPY_FILE, strerror(errno));
324        unlink(SUPP_ENTROPY_FILE);
325        return -1;
326    }
327
328    if (chown(SUPP_ENTROPY_FILE, AID_SYSTEM, AID_WIFI) < 0) {
329        ALOGE("Error changing group ownership of %s to %d: %s",
330             SUPP_ENTROPY_FILE, AID_WIFI, strerror(errno));
331        unlink(SUPP_ENTROPY_FILE);
332        return -1;
333    }
334    return 0;
335}
336
337int update_ctrl_interface(const char *config_file) {
338
339    int srcfd, destfd;
340    int nread;
341    char ifc[PROPERTY_VALUE_MAX];
342    char *pbuf;
343    char *sptr;
344    struct stat sb;
345
346    if (stat(config_file, &sb) != 0)
347        return -1;
348
349    pbuf = malloc(sb.st_size + PROPERTY_VALUE_MAX);
350    if (!pbuf)
351        return 0;
352    srcfd = TEMP_FAILURE_RETRY(open(config_file, O_RDONLY));
353    if (srcfd < 0) {
354        ALOGE("Cannot open \"%s\": %s", config_file, strerror(errno));
355        free(pbuf);
356        return 0;
357    }
358    nread = TEMP_FAILURE_RETRY(read(srcfd, pbuf, sb.st_size));
359    close(srcfd);
360    if (nread < 0) {
361        ALOGE("Cannot read \"%s\": %s", config_file, strerror(errno));
362        free(pbuf);
363        return 0;
364    }
365
366    if (!strcmp(config_file, SUPP_CONFIG_FILE)) {
367        property_get("wifi.interface", ifc, WIFI_TEST_INTERFACE);
368    } else {
369        strcpy(ifc, CONTROL_IFACE_PATH);
370    }
371    /*
372     * if there is a "ctrl_interface=<value>" entry, re-write it ONLY if it is
373     * NOT a directory.  The non-directory value option is an Android add-on
374     * that allows the control interface to be exchanged through an environment
375     * variable (initialized by the "init" program when it starts a service
376     * with a "socket" option).
377     *
378     * The <value> is deemed to be a directory if the "DIR=" form is used or
379     * the value begins with "/".
380     */
381    if ((sptr = strstr(pbuf, "ctrl_interface=")) &&
382        (!strstr(pbuf, "ctrl_interface=DIR=")) &&
383        (!strstr(pbuf, "ctrl_interface=/"))) {
384        char *iptr = sptr + strlen("ctrl_interface=");
385        int ilen = 0;
386        int mlen = strlen(ifc);
387        int nwrite;
388        if (strncmp(ifc, iptr, mlen) != 0) {
389            ALOGE("ctrl_interface != %s", ifc);
390            while (((ilen + (iptr - pbuf)) < nread) && (iptr[ilen] != '\n'))
391                ilen++;
392            mlen = ((ilen >= mlen) ? ilen : mlen) + 1;
393            memmove(iptr + mlen, iptr + ilen + 1, nread - (iptr + ilen + 1 - pbuf));
394            memset(iptr, '\n', mlen);
395            memcpy(iptr, ifc, strlen(ifc));
396            destfd = TEMP_FAILURE_RETRY(open(config_file, O_RDWR, 0660));
397            if (destfd < 0) {
398                ALOGE("Cannot update \"%s\": %s", config_file, strerror(errno));
399                free(pbuf);
400                return -1;
401            }
402            TEMP_FAILURE_RETRY(write(destfd, pbuf, nread + mlen - ilen -1));
403            close(destfd);
404        }
405    }
406    free(pbuf);
407    return 0;
408}
409
410int ensure_config_file_exists(const char *config_file)
411{
412    char buf[2048];
413    int srcfd, destfd;
414    struct stat sb;
415    int nread;
416    int ret;
417
418    ret = access(config_file, R_OK|W_OK);
419    if ((ret == 0) || (errno == EACCES)) {
420        if ((ret != 0) &&
421            (chmod(config_file, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) {
422            ALOGE("Cannot set RW to \"%s\": %s", config_file, strerror(errno));
423            return -1;
424        }
425        /* return if filesize is at least 10 bytes */
426        if (stat(config_file, &sb) == 0 && sb.st_size > 10) {
427            return update_ctrl_interface(config_file);
428        }
429    } else if (errno != ENOENT) {
430        ALOGE("Cannot access \"%s\": %s", config_file, strerror(errno));
431        return -1;
432    }
433
434    srcfd = TEMP_FAILURE_RETRY(open(SUPP_CONFIG_TEMPLATE, O_RDONLY));
435    if (srcfd < 0) {
436        ALOGE("Cannot open \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
437        return -1;
438    }
439
440    destfd = TEMP_FAILURE_RETRY(open(config_file, O_CREAT|O_RDWR, 0660));
441    if (destfd < 0) {
442        close(srcfd);
443        ALOGE("Cannot create \"%s\": %s", config_file, strerror(errno));
444        return -1;
445    }
446
447    while ((nread = TEMP_FAILURE_RETRY(read(srcfd, buf, sizeof(buf)))) != 0) {
448        if (nread < 0) {
449            ALOGE("Error reading \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
450            close(srcfd);
451            close(destfd);
452            unlink(config_file);
453            return -1;
454        }
455        TEMP_FAILURE_RETRY(write(destfd, buf, nread));
456    }
457
458    close(destfd);
459    close(srcfd);
460
461    /* chmod is needed because open() didn't set permisions properly */
462    if (chmod(config_file, 0660) < 0) {
463        ALOGE("Error changing permissions of %s to 0660: %s",
464             config_file, strerror(errno));
465        unlink(config_file);
466        return -1;
467    }
468
469    if (chown(config_file, AID_SYSTEM, AID_WIFI) < 0) {
470        ALOGE("Error changing group ownership of %s to %d: %s",
471             config_file, AID_WIFI, strerror(errno));
472        unlink(config_file);
473        return -1;
474    }
475    return update_ctrl_interface(config_file);
476}
477
478/**
479 * wifi_wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
480 * may be left over from clients that were previously connected to
481 * wpa_supplicant. This keeps these files from being orphaned in the
482 * event of crashes that prevented them from being removed as part
483 * of the normal orderly shutdown.
484 */
485void wifi_wpa_ctrl_cleanup(void)
486{
487    DIR *dir;
488    struct dirent entry;
489    struct dirent *result;
490    size_t dirnamelen;
491    size_t maxcopy;
492    char pathname[PATH_MAX];
493    char *namep;
494    char *local_socket_dir = CONFIG_CTRL_IFACE_CLIENT_DIR;
495    char *local_socket_prefix = CONFIG_CTRL_IFACE_CLIENT_PREFIX;
496
497    if ((dir = opendir(local_socket_dir)) == NULL)
498        return;
499
500    dirnamelen = (size_t)snprintf(pathname, sizeof(pathname), "%s/", local_socket_dir);
501    if (dirnamelen >= sizeof(pathname)) {
502        closedir(dir);
503        return;
504    }
505    namep = pathname + dirnamelen;
506    maxcopy = PATH_MAX - dirnamelen;
507    while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
508        if (strncmp(entry.d_name, local_socket_prefix, strlen(local_socket_prefix)) == 0) {
509            if (strlcpy(namep, entry.d_name, maxcopy) < maxcopy) {
510                unlink(pathname);
511            }
512        }
513    }
514    closedir(dir);
515}
516
517int wifi_start_supplicant(int p2p_supported)
518{
519    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
520    int count = 200; /* wait at most 20 seconds for completion */
521#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
522    const prop_info *pi;
523    unsigned serial = 0, i;
524#endif
525
526    if (p2p_supported) {
527        strcpy(supplicant_name, P2P_SUPPLICANT_NAME);
528        strcpy(supplicant_prop_name, P2P_PROP_NAME);
529
530        /* Ensure p2p config file is created */
531        if (ensure_config_file_exists(P2P_CONFIG_FILE) < 0) {
532            ALOGE("Failed to create a p2p config file");
533            return -1;
534        }
535
536    } else {
537        strcpy(supplicant_name, SUPPLICANT_NAME);
538        strcpy(supplicant_prop_name, SUPP_PROP_NAME);
539    }
540
541    /* Check whether already running */
542    if (property_get(supplicant_name, supp_status, NULL)
543            && strcmp(supp_status, "running") == 0) {
544        return 0;
545    }
546
547    /* Before starting the daemon, make sure its config file exists */
548    if (ensure_config_file_exists(SUPP_CONFIG_FILE) < 0) {
549        ALOGE("Wi-Fi will not be enabled");
550        return -1;
551    }
552
553    if (ensure_entropy_file_exists() < 0) {
554        ALOGE("Wi-Fi entropy file was not created");
555    }
556
557    /* Clear out any stale socket files that might be left over. */
558    wifi_wpa_ctrl_cleanup();
559
560    /* Reset sockets used for exiting from hung state */
561    for (i=0; i<MAX_CONNS; i++) {
562        exit_sockets[i][0] = exit_sockets[i][1] = -1;
563    }
564
565#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
566    /*
567     * Get a reference to the status property, so we can distinguish
568     * the case where it goes stopped => running => stopped (i.e.,
569     * it start up, but fails right away) from the case in which
570     * it starts in the stopped state and never manages to start
571     * running at all.
572     */
573    pi = __system_property_find(supplicant_prop_name);
574    if (pi != NULL) {
575        serial = pi->serial;
576    }
577#endif
578    property_get("wifi.interface", primary_iface, WIFI_TEST_INTERFACE);
579
580    property_set("ctl.start", supplicant_name);
581    sched_yield();
582
583    while (count-- > 0) {
584#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
585        if (pi == NULL) {
586            pi = __system_property_find(supplicant_prop_name);
587        }
588        if (pi != NULL) {
589            __system_property_read(pi, NULL, supp_status);
590            if (strcmp(supp_status, "running") == 0) {
591                return 0;
592            } else if (pi->serial != serial &&
593                    strcmp(supp_status, "stopped") == 0) {
594                return -1;
595            }
596        }
597#else
598        if (property_get(supplicant_prop_name, supp_status, NULL)) {
599            if (strcmp(supp_status, "running") == 0)
600                return 0;
601        }
602#endif
603        usleep(100000);
604    }
605    return -1;
606}
607
608int wifi_stop_supplicant(int p2p_supported)
609{
610    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
611    int count = 50; /* wait at most 5 seconds for completion */
612
613    if (p2p_supported) {
614        strcpy(supplicant_name, P2P_SUPPLICANT_NAME);
615        strcpy(supplicant_prop_name, P2P_PROP_NAME);
616    } else {
617        strcpy(supplicant_name, SUPPLICANT_NAME);
618        strcpy(supplicant_prop_name, SUPP_PROP_NAME);
619    }
620
621    /* Check whether supplicant already stopped */
622    if (property_get(supplicant_prop_name, supp_status, NULL)
623        && strcmp(supp_status, "stopped") == 0) {
624        return 0;
625    }
626
627    property_set("ctl.stop", supplicant_name);
628    sched_yield();
629
630    while (count-- > 0) {
631        if (property_get(supplicant_prop_name, supp_status, NULL)) {
632            if (strcmp(supp_status, "stopped") == 0)
633                return 0;
634        }
635        usleep(100000);
636    }
637    ALOGE("Failed to stop supplicant");
638    return -1;
639}
640
641int wifi_connect_on_socket_path(int index, const char *path)
642{
643    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
644
645    /* Make sure supplicant is running */
646    if (!property_get(supplicant_prop_name, supp_status, NULL)
647            || strcmp(supp_status, "running") != 0) {
648        ALOGE("Supplicant not running, cannot connect");
649        return -1;
650    }
651
652    ctrl_conn[index] = wpa_ctrl_open(path);
653    if (ctrl_conn[index] == NULL) {
654        ALOGE("Unable to open connection to supplicant on \"%s\": %s",
655             path, strerror(errno));
656        return -1;
657    }
658    monitor_conn[index] = wpa_ctrl_open(path);
659    if (monitor_conn[index] == NULL) {
660        wpa_ctrl_close(ctrl_conn[index]);
661        ctrl_conn[index] = NULL;
662        return -1;
663    }
664    if (wpa_ctrl_attach(monitor_conn[index]) != 0) {
665        wpa_ctrl_close(monitor_conn[index]);
666        wpa_ctrl_close(ctrl_conn[index]);
667        ctrl_conn[index] = monitor_conn[index] = NULL;
668        return -1;
669    }
670
671    if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets[index]) == -1) {
672        wpa_ctrl_close(monitor_conn[index]);
673        wpa_ctrl_close(ctrl_conn[index]);
674        ctrl_conn[index] = monitor_conn[index] = NULL;
675        return -1;
676    }
677
678    return 0;
679}
680
681/* Establishes the control and monitor socket connections on the interface */
682int wifi_connect_to_supplicant(const char *ifname)
683{
684    char path[256];
685
686    if (is_primary_interface(ifname)) {
687        if (access(IFACE_DIR, F_OK) == 0) {
688            snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, primary_iface);
689        } else {
690            strlcpy(path, primary_iface, sizeof(path));
691        }
692        return wifi_connect_on_socket_path(PRIMARY, path);
693    } else {
694        sprintf(path, "%s/%s", CONTROL_IFACE_PATH, ifname);
695        return wifi_connect_on_socket_path(SECONDARY, path);
696    }
697}
698
699int wifi_send_command(int index, const char *cmd, char *reply, size_t *reply_len)
700{
701    int ret;
702
703    if (ctrl_conn[index] == NULL) {
704        ALOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd);
705        return -1;
706    }
707    ret = wpa_ctrl_request(ctrl_conn[index], cmd, strlen(cmd), reply, reply_len, NULL);
708    if (ret == -2) {
709        ALOGD("'%s' command timed out.\n", cmd);
710        /* unblocks the monitor receive socket for termination */
711        TEMP_FAILURE_RETRY(write(exit_sockets[index][0], "T", 1));
712        return -2;
713    } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) {
714        return -1;
715    }
716    if (strncmp(cmd, "PING", 4) == 0) {
717        reply[*reply_len] = '\0';
718    }
719    return 0;
720}
721
722int wifi_ctrl_recv(int index, char *reply, size_t *reply_len)
723{
724    int res;
725    int ctrlfd = wpa_ctrl_get_fd(monitor_conn[index]);
726    struct pollfd rfds[2];
727
728    memset(rfds, 0, 2 * sizeof(struct pollfd));
729    rfds[0].fd = ctrlfd;
730    rfds[0].events |= POLLIN;
731    rfds[1].fd = exit_sockets[index][1];
732    rfds[1].events |= POLLIN;
733    res = TEMP_FAILURE_RETRY(poll(rfds, 2, -1));
734    if (res < 0) {
735        ALOGE("Error poll = %d", res);
736        return res;
737    }
738    if (rfds[0].revents & POLLIN) {
739        return wpa_ctrl_recv(monitor_conn[index], reply, reply_len);
740    } else if (rfds[1].revents & POLLIN) {
741        /* Close only the p2p sockets on receive side
742         * see wifi_close_supplicant_connection()
743         */
744        if (index == SECONDARY) {
745            ALOGD("close sockets %d", index);
746            wifi_close_sockets(index);
747        }
748    }
749    return -2;
750}
751
752int wifi_wait_on_socket(int index, char *buf, size_t buflen)
753{
754    size_t nread = buflen - 1;
755    int result;
756
757    if (monitor_conn[index] == NULL) {
758        ALOGD("Connection closed\n");
759        strncpy(buf, WPA_EVENT_TERMINATING " - connection closed", buflen-1);
760        buf[buflen-1] = '\0';
761        return strlen(buf);
762    }
763
764    result = wifi_ctrl_recv(index, buf, &nread);
765
766    /* Terminate reception on exit socket */
767    if (result == -2) {
768        strncpy(buf, WPA_EVENT_TERMINATING " - connection closed", buflen-1);
769        buf[buflen-1] = '\0';
770        return strlen(buf);
771    }
772
773    if (result < 0) {
774        ALOGD("wifi_ctrl_recv failed: %s\n", strerror(errno));
775        strncpy(buf, WPA_EVENT_TERMINATING " - recv error", buflen-1);
776        buf[buflen-1] = '\0';
777        return strlen(buf);
778    }
779    buf[nread] = '\0';
780    /* Check for EOF on the socket */
781    if (result == 0 && nread == 0) {
782        /* Fabricate an event to pass up */
783        ALOGD("Received EOF on supplicant socket\n");
784        strncpy(buf, WPA_EVENT_TERMINATING " - signal 0 received", buflen-1);
785        buf[buflen-1] = '\0';
786        return strlen(buf);
787    }
788    /*
789     * Events strings are in the format
790     *
791     *     <N>CTRL-EVENT-XXX
792     *
793     * where N is the message level in numerical form (0=VERBOSE, 1=DEBUG,
794     * etc.) and XXX is the event name. The level information is not useful
795     * to us, so strip it off.
796     */
797    if (buf[0] == '<') {
798        char *match = strchr(buf, '>');
799        if (match != NULL) {
800            nread -= (match+1-buf);
801            memmove(buf, match+1, nread+1);
802        }
803    }
804
805    return nread;
806}
807
808int wifi_wait_for_event(const char *ifname, char *buf, size_t buflen)
809{
810    if (is_primary_interface(ifname)) {
811        return wifi_wait_on_socket(PRIMARY, buf, buflen);
812    } else {
813        return wifi_wait_on_socket(SECONDARY, buf, buflen);
814    }
815}
816
817void wifi_close_sockets(int index)
818{
819    if (ctrl_conn[index] != NULL) {
820        wpa_ctrl_close(ctrl_conn[index]);
821        ctrl_conn[index] = NULL;
822    }
823
824    if (monitor_conn[index] != NULL) {
825        wpa_ctrl_close(monitor_conn[index]);
826        monitor_conn[index] = NULL;
827    }
828
829    if (exit_sockets[index][0] >= 0) {
830        close(exit_sockets[index][0]);
831        exit_sockets[index][0] = -1;
832    }
833
834    if (exit_sockets[index][1] >= 0) {
835        close(exit_sockets[index][1]);
836        exit_sockets[index][1] = -1;
837    }
838}
839
840void wifi_close_supplicant_connection(const char *ifname)
841{
842    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
843    int count = 50; /* wait at most 5 seconds to ensure init has stopped stupplicant */
844
845    if (is_primary_interface(ifname)) {
846        wifi_close_sockets(PRIMARY);
847    } else {
848        /* p2p socket termination needs unblocking the monitor socket
849         * STA connection does not need it since supplicant gets shutdown
850         */
851        TEMP_FAILURE_RETRY(write(exit_sockets[SECONDARY][0], "T", 1));
852        /* p2p sockets are closed after the monitor thread
853         * receives the terminate on the exit socket
854         */
855        return;
856    }
857
858    while (count-- > 0) {
859        if (property_get(supplicant_prop_name, supp_status, NULL)) {
860            if (strcmp(supp_status, "stopped") == 0)
861                return;
862        }
863        usleep(100000);
864    }
865}
866
867int wifi_command(const char *ifname, const char *command, char *reply, size_t *reply_len)
868{
869    if (is_primary_interface(ifname)) {
870        return wifi_send_command(PRIMARY, command, reply, reply_len);
871    } else {
872        return wifi_send_command(SECONDARY, command, reply, reply_len);
873    }
874}
875
876const char *wifi_get_fw_path(int fw_type)
877{
878    switch (fw_type) {
879    case WIFI_GET_FW_PATH_STA:
880        return WIFI_DRIVER_FW_PATH_STA;
881    case WIFI_GET_FW_PATH_AP:
882        return WIFI_DRIVER_FW_PATH_AP;
883    case WIFI_GET_FW_PATH_P2P:
884        return WIFI_DRIVER_FW_PATH_P2P;
885    }
886    return NULL;
887}
888
889int wifi_change_fw_path(const char *fwpath)
890{
891    int len;
892    int fd;
893    int ret = 0;
894
895    if (!fwpath)
896        return ret;
897    fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY));
898    if (fd < 0) {
899        ALOGE("Failed to open wlan fw path param (%s)", strerror(errno));
900        return -1;
901    }
902    len = strlen(fwpath) + 1;
903    if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) {
904        ALOGE("Failed to write wlan fw path param (%s)", strerror(errno));
905        ret = -1;
906    }
907    close(fd);
908    return ret;
909}
910