1dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat/*
2dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat * Copyright (C) 2008 The Android Open Source Project
3dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat *
4dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat * you may not use this file except in compliance with the License.
6dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat * You may obtain a copy of the License at
7dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat *
8dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat *
10dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat * Unless required by applicable law or agreed to in writing, software
11dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat * See the License for the specific language governing permissions and
14dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat * limitations under the License.
15dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat */
161441e769b2767e212a3d905bee2fd3535b484ff2San Mehat
171441e769b2767e212a3d905bee2fd3535b484ff2San Mehat#include <stdlib.h>
1869772dc644e1ccc12b6394267f010100470f3c95San Mehat#include <sys/types.h>
1969772dc644e1ccc12b6394267f010100470f3c95San Mehat#include <fcntl.h>
20dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat#include <errno.h>
21dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
22dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat#define LOG_TAG "Supplicant"
23dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat#include <cutils/log.h>
24dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat#include <cutils/properties.h>
25dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
2669772dc644e1ccc12b6394267f010100470f3c95San Mehat#include "private/android_filesystem_config.h"
2769772dc644e1ccc12b6394267f010100470f3c95San Mehat
285d6d417972f8d946c223c4efb9636b1ba4280543San Mehat#include <sysutils/ServiceManager.h>
29dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
30dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat#include "Supplicant.h"
31dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat#include "SupplicantListener.h"
321441e769b2767e212a3d905bee2fd3535b484ff2San Mehat#include "NetworkManager.h"
333c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat#include "WifiController.h"
343aff2d1de59972684bf2ab798351be5544158239San Mehat#include "SupplicantStatus.h"
35dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
36dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat#include "libwpa_client/wpa_ctrl.h"
37dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
38dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat#define IFACE_DIR        "/data/system/wpa_supplicant"
39dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat#define DRIVER_PROP_NAME "wlan.driver.status"
405d6d417972f8d946c223c4efb9636b1ba4280543San Mehat#define SUPPLICANT_SERVICE_NAME  "wpa_supplicant"
4169772dc644e1ccc12b6394267f010100470f3c95San Mehat#define SUPP_CONFIG_TEMPLATE "/system/etc/wifi/wpa_supplicant.conf"
4269772dc644e1ccc12b6394267f010100470f3c95San Mehat#define SUPP_CONFIG_FILE "/data/misc/wifi/wpa_supplicant.conf"
4369772dc644e1ccc12b6394267f010100470f3c95San Mehat
443aff2d1de59972684bf2ab798351be5544158239San MehatSupplicant::Supplicant(WifiController *wc, ISupplicantEventHandler *handlers) {
453aff2d1de59972684bf2ab798351be5544158239San Mehat    mHandlers = handlers;
463c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    mController = wc;
473c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    mInterfaceName = NULL;
48dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    mCtrl = NULL;
49dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    mMonitor = NULL;
50dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    mListener = NULL;
513c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
525d6d417972f8d946c223c4efb9636b1ba4280543San Mehat    mServiceManager = new ServiceManager();
53dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
543c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    mNetworks = new WifiNetworkCollection();
553c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    pthread_mutex_init(&mNetworksLock, NULL);
56dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat}
57dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
585d6d417972f8d946c223c4efb9636b1ba4280543San MehatSupplicant::~Supplicant() {
595d6d417972f8d946c223c4efb9636b1ba4280543San Mehat    delete mServiceManager;
603c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    if (mInterfaceName)
613c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        free(mInterfaceName);
625d6d417972f8d946c223c4efb9636b1ba4280543San Mehat}
635d6d417972f8d946c223c4efb9636b1ba4280543San Mehat
64dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehatint Supplicant::start() {
6569772dc644e1ccc12b6394267f010100470f3c95San Mehat
6669772dc644e1ccc12b6394267f010100470f3c95San Mehat    if (setupConfig()) {
6769772dc644e1ccc12b6394267f010100470f3c95San Mehat        LOGW("Unable to setup supplicant.conf");
6869772dc644e1ccc12b6394267f010100470f3c95San Mehat    }
693c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
705d6d417972f8d946c223c4efb9636b1ba4280543San Mehat    if (mServiceManager->start(SUPPLICANT_SERVICE_NAME)) {
715d6d417972f8d946c223c4efb9636b1ba4280543San Mehat        LOGE("Error starting supplicant (%s)", strerror(errno));
725d6d417972f8d946c223c4efb9636b1ba4280543San Mehat        return -1;
73dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
74dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
751441e769b2767e212a3d905bee2fd3535b484ff2San Mehat    wpa_ctrl_cleanup();
76dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    if (connectToSupplicant()) {
77dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        LOGE("Error connecting to supplicant (%s)\n", strerror(errno));
78dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        return -1;
79dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
803c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
813c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    if (retrieveInterfaceName()) {
823c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        LOGE("Error retrieving interface name (%s)\n", strerror(errno));
833c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        return -1;
843c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    }
853c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
86dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    return 0;
87dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat}
88dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
89dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehatint Supplicant::stop() {
90dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
91dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    if (mListener->stopListener()) {
92dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        LOGW("Unable to stop supplicant listener (%s)", strerror(errno));
93dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        return -1;
94dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
95dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
965d6d417972f8d946c223c4efb9636b1ba4280543San Mehat    if (mServiceManager->stop(SUPPLICANT_SERVICE_NAME)) {
975d6d417972f8d946c223c4efb9636b1ba4280543San Mehat        LOGW("Error stopping supplicant (%s)", strerror(errno));
98dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
99dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
100dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    if (mCtrl) {
101dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        wpa_ctrl_close(mCtrl);
102dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        mCtrl = NULL;
103dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
104dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    if (mMonitor) {
105dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        wpa_ctrl_close(mMonitor);
106dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        mMonitor = NULL;
107dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
108dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
109dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    return 0;
110dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat}
111dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
112dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehatbool Supplicant::isStarted() {
1135d6d417972f8d946c223c4efb9636b1ba4280543San Mehat    return mServiceManager->isRunning(SUPPLICANT_SERVICE_NAME);
114dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat}
115dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
116c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::sendCommand(const char *cmd, char *reply, size_t *reply_len) {
117c4a895b7094461c98101924cf096680bfb7856f1San Mehat
118c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (!mCtrl) {
119c4a895b7094461c98101924cf096680bfb7856f1San Mehat        errno = ENOTCONN;
120c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
121c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
122c4a895b7094461c98101924cf096680bfb7856f1San Mehat
123c4a895b7094461c98101924cf096680bfb7856f1San Mehat//    LOGD("sendCommand(): -> '%s'", cmd);
124c4a895b7094461c98101924cf096680bfb7856f1San Mehat
125c4a895b7094461c98101924cf096680bfb7856f1San Mehat    int rc;
126c4a895b7094461c98101924cf096680bfb7856f1San Mehat    memset(reply, 0, *reply_len);
127c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if ((rc = wpa_ctrl_request(mCtrl, cmd, strlen(cmd), reply, reply_len, NULL)) == -2)  {
128c4a895b7094461c98101924cf096680bfb7856f1San Mehat        errno = ETIMEDOUT;
129c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
130c4a895b7094461c98101924cf096680bfb7856f1San Mehat    } else if (rc < 0 || !strncmp(reply, "FAIL", 4)) {
131c4a895b7094461c98101924cf096680bfb7856f1San Mehat        strcpy(reply, "FAIL");
132c4a895b7094461c98101924cf096680bfb7856f1San Mehat        errno = EIO;
133c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
134c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
135c4a895b7094461c98101924cf096680bfb7856f1San Mehat
136c4a895b7094461c98101924cf096680bfb7856f1San Mehat //   LOGD("sendCommand(): <- '%s'", reply);
137c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return 0;
138c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
1393aff2d1de59972684bf2ab798351be5544158239San MehatSupplicantStatus *Supplicant::getStatus() {
1403aff2d1de59972684bf2ab798351be5544158239San Mehat    char *reply;
1413aff2d1de59972684bf2ab798351be5544158239San Mehat    size_t len = 4096;
1423aff2d1de59972684bf2ab798351be5544158239San Mehat
1433aff2d1de59972684bf2ab798351be5544158239San Mehat    if (!(reply = (char *) malloc(len))) {
1443aff2d1de59972684bf2ab798351be5544158239San Mehat        errno = ENOMEM;
1453aff2d1de59972684bf2ab798351be5544158239San Mehat        return NULL;
1463aff2d1de59972684bf2ab798351be5544158239San Mehat    }
1473aff2d1de59972684bf2ab798351be5544158239San Mehat
1483aff2d1de59972684bf2ab798351be5544158239San Mehat    if (sendCommand("STATUS", reply, &len)) {
1493aff2d1de59972684bf2ab798351be5544158239San Mehat        free(reply);
1503aff2d1de59972684bf2ab798351be5544158239San Mehat        return NULL;
1513aff2d1de59972684bf2ab798351be5544158239San Mehat    }
1523aff2d1de59972684bf2ab798351be5544158239San Mehat
1533aff2d1de59972684bf2ab798351be5544158239San Mehat    SupplicantStatus *ss = SupplicantStatus::createStatus(reply, len);
1543aff2d1de59972684bf2ab798351be5544158239San Mehat
1553aff2d1de59972684bf2ab798351be5544158239San Mehat    free (reply);
1563aff2d1de59972684bf2ab798351be5544158239San Mehat    return ss;
1573aff2d1de59972684bf2ab798351be5544158239San Mehat}
1583aff2d1de59972684bf2ab798351be5544158239San Mehat
1593aff2d1de59972684bf2ab798351be5544158239San Mehat/*
1603aff2d1de59972684bf2ab798351be5544158239San Mehat * Retrieves the list of networks from Supplicant
1613aff2d1de59972684bf2ab798351be5544158239San Mehat * and merge them into our current list
1623aff2d1de59972684bf2ab798351be5544158239San Mehat */
1633c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehatint Supplicant::refreshNetworkList() {
1643c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    char *reply;
1653c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    size_t len = 4096;
1663c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
1673c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    if (!(reply = (char *) malloc(len))) {
1683c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        errno = ENOMEM;
1693c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        return -1;
1703c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    }
1713c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
1723c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    if (sendCommand("LIST_NETWORKS", reply, &len)) {
1733c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        free(reply);
174dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        return -1;
175dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
176dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
1773c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    char *linep;
1783c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    char *linep_next = NULL;
1793c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
1803c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    if (!strtok_r(reply, "\n", &linep_next)) {
1813c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        LOGW("Malformatted network list\n");
1823aff2d1de59972684bf2ab798351be5544158239San Mehat        free(reply);
1833aff2d1de59972684bf2ab798351be5544158239San Mehat        errno = EIO;
1843aff2d1de59972684bf2ab798351be5544158239San Mehat        return -1;
1853aff2d1de59972684bf2ab798351be5544158239San Mehat    }
1863c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
187c4a895b7094461c98101924cf096680bfb7856f1San Mehat    PropertyManager *pm = NetworkManager::Instance()->getPropMngr();
1883aff2d1de59972684bf2ab798351be5544158239San Mehat    pthread_mutex_lock(&mNetworksLock);
1893aff2d1de59972684bf2ab798351be5544158239San Mehat
1903aff2d1de59972684bf2ab798351be5544158239San Mehat    int num_added = 0;
1913aff2d1de59972684bf2ab798351be5544158239San Mehat    int num_refreshed = 0;
1923aff2d1de59972684bf2ab798351be5544158239San Mehat    int num_removed = 0;
1933aff2d1de59972684bf2ab798351be5544158239San Mehat    while((linep = strtok_r(NULL, "\n", &linep_next))) {
1943aff2d1de59972684bf2ab798351be5544158239San Mehat        // TODO: Move the decode into a static method so we
1953aff2d1de59972684bf2ab798351be5544158239San Mehat        // don't create new_wn when we don't have to.
1963aff2d1de59972684bf2ab798351be5544158239San Mehat        WifiNetwork *new_wn = new WifiNetwork(mController, this, linep);
1973aff2d1de59972684bf2ab798351be5544158239San Mehat        WifiNetwork *merge_wn;
1983aff2d1de59972684bf2ab798351be5544158239San Mehat
1993aff2d1de59972684bf2ab798351be5544158239San Mehat        if ((merge_wn = this->lookupNetwork_UNLOCKED(new_wn->getNetworkId()))) {
2003aff2d1de59972684bf2ab798351be5544158239San Mehat            num_refreshed++;
2013aff2d1de59972684bf2ab798351be5544158239San Mehat            if (merge_wn->refresh()) {
2023aff2d1de59972684bf2ab798351be5544158239San Mehat                LOGW("Error refreshing network %d (%s)",
2033aff2d1de59972684bf2ab798351be5544158239San Mehat                     merge_wn->getNetworkId(), strerror(errno));
2043aff2d1de59972684bf2ab798351be5544158239San Mehat                }
2053aff2d1de59972684bf2ab798351be5544158239San Mehat            delete new_wn;
2063aff2d1de59972684bf2ab798351be5544158239San Mehat        } else {
2073aff2d1de59972684bf2ab798351be5544158239San Mehat            num_added++;
208c4a895b7094461c98101924cf096680bfb7856f1San Mehat            char new_ns[20];
209c4a895b7094461c98101924cf096680bfb7856f1San Mehat            snprintf(new_ns, sizeof(new_ns), "wifi.net.%d", new_wn->getNetworkId());
210c4a895b7094461c98101924cf096680bfb7856f1San Mehat            new_wn->attachProperties(pm, new_ns);
2113aff2d1de59972684bf2ab798351be5544158239San Mehat            mNetworks->push_back(new_wn);
2123aff2d1de59972684bf2ab798351be5544158239San Mehat            if (new_wn->refresh()) {
2133aff2d1de59972684bf2ab798351be5544158239San Mehat                LOGW("Unable to refresh network id %d (%s)",
2143aff2d1de59972684bf2ab798351be5544158239San Mehat                    new_wn->getNetworkId(), strerror(errno));
2153aff2d1de59972684bf2ab798351be5544158239San Mehat            }
2163c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        }
2173aff2d1de59972684bf2ab798351be5544158239San Mehat    }
2183c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
2193aff2d1de59972684bf2ab798351be5544158239San Mehat    if (!mNetworks->empty()) {
2203aff2d1de59972684bf2ab798351be5544158239San Mehat        // TODO: Add support for detecting removed networks
2213aff2d1de59972684bf2ab798351be5544158239San Mehat        WifiNetworkCollection::iterator i;
2223aff2d1de59972684bf2ab798351be5544158239San Mehat
2233aff2d1de59972684bf2ab798351be5544158239San Mehat        for (i = mNetworks->begin(); i != mNetworks->end(); ++i) {
2243aff2d1de59972684bf2ab798351be5544158239San Mehat            if (0) {
2253aff2d1de59972684bf2ab798351be5544158239San Mehat                num_removed++;
226c4a895b7094461c98101924cf096680bfb7856f1San Mehat                char del_ns[20];
227c4a895b7094461c98101924cf096680bfb7856f1San Mehat                snprintf(del_ns, sizeof(del_ns), "wifi.net.%d", (*i)->getNetworkId());
228c4a895b7094461c98101924cf096680bfb7856f1San Mehat                (*i)->detachProperties(pm, del_ns);
2293aff2d1de59972684bf2ab798351be5544158239San Mehat                delete (*i);
2303aff2d1de59972684bf2ab798351be5544158239San Mehat                i = mNetworks->erase(i);
2313aff2d1de59972684bf2ab798351be5544158239San Mehat            }
2323aff2d1de59972684bf2ab798351be5544158239San Mehat        }
2333c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    }
2343c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
2353aff2d1de59972684bf2ab798351be5544158239San Mehat
2363aff2d1de59972684bf2ab798351be5544158239San Mehat    LOGD("Networks added %d, refreshed %d, removed %d\n",
2373aff2d1de59972684bf2ab798351be5544158239San Mehat         num_added, num_refreshed, num_removed);
2383aff2d1de59972684bf2ab798351be5544158239San Mehat    pthread_mutex_unlock(&mNetworksLock);
2393aff2d1de59972684bf2ab798351be5544158239San Mehat
2403c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    free(reply);
2413c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    return 0;
2423c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat}
2433c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
2443c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehatint Supplicant::connectToSupplicant() {
2453c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    if (!isStarted())
2463c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        LOGW("Supplicant service not running");
2473c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
2483c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    mCtrl = wpa_ctrl_open("tiwlan0"); // XXX:
249dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    if (mCtrl == NULL) {
250dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        LOGE("Unable to open connection to supplicant on \"%s\": %s",
251dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat             "tiwlan0", strerror(errno));
252dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        return -1;
253dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
254dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    mMonitor = wpa_ctrl_open("tiwlan0");
255dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    if (mMonitor == NULL) {
256dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        wpa_ctrl_close(mCtrl);
257dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        mCtrl = NULL;
258dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        return -1;
259dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
260dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    if (wpa_ctrl_attach(mMonitor) != 0) {
261dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        wpa_ctrl_close(mMonitor);
262dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        wpa_ctrl_close(mCtrl);
263dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        mCtrl = mMonitor = NULL;
264dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        return -1;
265dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
266dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
2673aff2d1de59972684bf2ab798351be5544158239San Mehat    mListener = new SupplicantListener(mHandlers, mMonitor);
2683c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
269dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    if (mListener->startListener()) {
270dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        LOGE("Error - unable to start supplicant listener");
271dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        stop();
272dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        return -1;
273dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
274dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    return 0;
275dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat}
276dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
277c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::setScanMode(bool active) {
278c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[255];
279c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len = sizeof(reply);
280c4a895b7094461c98101924cf096680bfb7856f1San Mehat
281c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand((active ? "DRIVER SCAN-ACTIVE" : "DRIVER SCAN-PASSIVE"),
282c4a895b7094461c98101924cf096680bfb7856f1San Mehat                     reply, &len)) {
283c4a895b7094461c98101924cf096680bfb7856f1San Mehat        LOGW("triggerScan(%d): Error setting scan mode (%s)", active,
284c4a895b7094461c98101924cf096680bfb7856f1San Mehat             strerror(errno));
285dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        return -1;
286dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
287c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return 0;
288c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
289dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
290c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::triggerScan() {
291c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[255];
292c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len = sizeof(reply);
293dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
294c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand("SCAN", reply, &len)) {
295c4a895b7094461c98101924cf096680bfb7856f1San Mehat        LOGW("triggerScan(): Error initiating scan");
296dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        return -1;
297c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
298c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return 0;
299c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
300c4a895b7094461c98101924cf096680bfb7856f1San Mehat
301c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::getRssi(int *buffer) {
302c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[64];
303c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len = sizeof(reply);
304c4a895b7094461c98101924cf096680bfb7856f1San Mehat
305c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand("DRIVER RSSI", reply, &len)) {
306c4a895b7094461c98101924cf096680bfb7856f1San Mehat        LOGW("Failed to get RSSI (%s)", strerror(errno));
307dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        return -1;
308dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
309dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
310c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char *next = reply;
311c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char *s;
312c4a895b7094461c98101924cf096680bfb7856f1San Mehat    for (int i = 0; i < 3; i++) {
313c4a895b7094461c98101924cf096680bfb7856f1San Mehat        if (!(s = strsep(&next, " "))) {
314c4a895b7094461c98101924cf096680bfb7856f1San Mehat            LOGE("Error parsing RSSI");
315c4a895b7094461c98101924cf096680bfb7856f1San Mehat            errno = EIO;
316c4a895b7094461c98101924cf096680bfb7856f1San Mehat            return -1;
317c4a895b7094461c98101924cf096680bfb7856f1San Mehat        }
318c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
319c4a895b7094461c98101924cf096680bfb7856f1San Mehat    *buffer = atoi(s);
320dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    return 0;
321dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat}
322dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
323c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::getLinkSpeed() {
324c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[64];
325dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    size_t len = sizeof(reply);
326dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
327c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand("DRIVER LINKSPEED", reply, &len)) {
328c4a895b7094461c98101924cf096680bfb7856f1San Mehat        LOGW("Failed to get LINKSPEED (%s)", strerror(errno));
329dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        return -1;
330dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
331dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
332c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char *next = reply;
333c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char *s;
334c4a895b7094461c98101924cf096680bfb7856f1San Mehat
335c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (!(s = strsep(&next, " "))) {
336c4a895b7094461c98101924cf096680bfb7856f1San Mehat        LOGE("Error parsing LINKSPEED");
337c4a895b7094461c98101924cf096680bfb7856f1San Mehat        errno = EIO;
338c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
339c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
340c4a895b7094461c98101924cf096680bfb7856f1San Mehat
341c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (!(s = strsep(&next, " "))) {
342c4a895b7094461c98101924cf096680bfb7856f1San Mehat        LOGE("Error parsing LINKSPEED");
343c4a895b7094461c98101924cf096680bfb7856f1San Mehat        errno = EIO;
344c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
345c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
346c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return atoi(s);
347c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
348c4a895b7094461c98101924cf096680bfb7856f1San Mehat
349c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::stopDriver() {
350c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[64];
351c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len = sizeof(reply);
352c4a895b7094461c98101924cf096680bfb7856f1San Mehat
353c4a895b7094461c98101924cf096680bfb7856f1San Mehat    LOGD("stopDriver()");
354c4a895b7094461c98101924cf096680bfb7856f1San Mehat
355c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand("DRIVER STOP", reply, &len)) {
356c4a895b7094461c98101924cf096680bfb7856f1San Mehat        LOGW("Failed to stop driver (%s)", strerror(errno));
357c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
358c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
359c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return 0;
360c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
361c4a895b7094461c98101924cf096680bfb7856f1San Mehat
362c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::startDriver() {
363c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[64];
364c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len = sizeof(reply);
365c4a895b7094461c98101924cf096680bfb7856f1San Mehat
366c4a895b7094461c98101924cf096680bfb7856f1San Mehat    LOGD("startDriver()");
367c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand("DRIVER START", reply, &len)) {
368c4a895b7094461c98101924cf096680bfb7856f1San Mehat        LOGW("Failed to start driver (%s)", strerror(errno));
369dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat        return -1;
370dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    }
371dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat    return 0;
372dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat}
373dc266073e7c3127caedf26671a1c125dc8aadd8dSan Mehat
3743c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San MehatWifiNetwork *Supplicant::createNetwork() {
3753c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    char reply[255];
37682a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat    size_t len = sizeof(reply) -1;
37782a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat
37882a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat    if (sendCommand("ADD_NETWORK", reply, &len))
3793c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        return NULL;
3803c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
3813c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    if (reply[strlen(reply) -1] == '\n')
3823c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        reply[strlen(reply) -1] = '\0';
38382a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat
3843c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    WifiNetwork *wn = new WifiNetwork(mController, this, atoi(reply));
385c4a895b7094461c98101924cf096680bfb7856f1San Mehat    PropertyManager *pm = NetworkManager::Instance()->getPropMngr();
3863c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    pthread_mutex_lock(&mNetworksLock);
387c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char new_ns[20];
388c4a895b7094461c98101924cf096680bfb7856f1San Mehat    snprintf(new_ns, sizeof(new_ns), "wifi.net.%d", wn->getNetworkId());
389c4a895b7094461c98101924cf096680bfb7856f1San Mehat    wn->attachProperties(pm, new_ns);
3903c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    mNetworks->push_back(wn);
3913c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    pthread_mutex_unlock(&mNetworksLock);
3923c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    return wn;
39382a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat}
39482a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat
3953c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehatint Supplicant::removeNetwork(WifiNetwork *wn) {
39682a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat    char req[64];
39782a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat
3983c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    sprintf(req, "REMOVE_NETWORK %d", wn->getNetworkId());
39982a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat    char reply[32];
40082a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat    size_t len = sizeof(reply) -1;
4013c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
40282a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat    if (sendCommand(req, reply, &len))
40382a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat        return -1;
4043c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
4053c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    pthread_mutex_lock(&mNetworksLock);
4063c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    WifiNetworkCollection::iterator it;
4073c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    for (it = mNetworks->begin(); it != mNetworks->end(); ++it) {
4083c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        if ((*it) == wn) {
4093c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat            mNetworks->erase(it);
4103c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat            break;
4113c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        }
4123c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    }
4133c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    pthread_mutex_unlock(&mNetworksLock);
41482a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat    return 0;
41582a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat}
41682a2116e6b67db910bba22c4874e6ca5efd3eec0San Mehat
4173c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San MehatWifiNetwork *Supplicant::lookupNetwork(int networkId) {
4183c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    pthread_mutex_lock(&mNetworksLock);
4193aff2d1de59972684bf2ab798351be5544158239San Mehat    WifiNetwork *wn = lookupNetwork_UNLOCKED(networkId);
4203aff2d1de59972684bf2ab798351be5544158239San Mehat    pthread_mutex_unlock(&mNetworksLock);
4213aff2d1de59972684bf2ab798351be5544158239San Mehat    return wn;
4223aff2d1de59972684bf2ab798351be5544158239San Mehat}
4233aff2d1de59972684bf2ab798351be5544158239San Mehat
4243aff2d1de59972684bf2ab798351be5544158239San MehatWifiNetwork *Supplicant::lookupNetwork_UNLOCKED(int networkId) {
4253c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    WifiNetworkCollection::iterator it;
4263c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    for (it = mNetworks->begin(); it != mNetworks->end(); ++it) {
4273c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        if ((*it)->getNetworkId() == networkId) {
4283c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat            return *it;
4293c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        }
4303c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    }
4313c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    errno = ENOENT;
4323c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    return NULL;
4333c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat}
4343c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
4353c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San MehatWifiNetworkCollection *Supplicant::createNetworkList() {
4363c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    WifiNetworkCollection *d = new WifiNetworkCollection();
4373c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    WifiNetworkCollection::iterator i;
4383c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
4393c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    pthread_mutex_lock(&mNetworksLock);
4403c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    for (i = mNetworks->begin(); i != mNetworks->end(); ++i)
4413c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        d->push_back((*i)->clone());
4423c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
4433c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    pthread_mutex_unlock(&mNetworksLock);
4443c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    return d;
4453c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat}
4463c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
44769772dc644e1ccc12b6394267f010100470f3c95San Mehatint Supplicant::setupConfig() {
44869772dc644e1ccc12b6394267f010100470f3c95San Mehat    char buf[2048];
44969772dc644e1ccc12b6394267f010100470f3c95San Mehat    int srcfd, destfd;
45069772dc644e1ccc12b6394267f010100470f3c95San Mehat    int nread;
45169772dc644e1ccc12b6394267f010100470f3c95San Mehat
45269772dc644e1ccc12b6394267f010100470f3c95San Mehat    if (access(SUPP_CONFIG_FILE, R_OK|W_OK) == 0) {
45369772dc644e1ccc12b6394267f010100470f3c95San Mehat        return 0;
45469772dc644e1ccc12b6394267f010100470f3c95San Mehat    } else if (errno != ENOENT) {
45569772dc644e1ccc12b6394267f010100470f3c95San Mehat        LOGE("Cannot access \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno));
45669772dc644e1ccc12b6394267f010100470f3c95San Mehat        return -1;
45769772dc644e1ccc12b6394267f010100470f3c95San Mehat    }
45869772dc644e1ccc12b6394267f010100470f3c95San Mehat
45969772dc644e1ccc12b6394267f010100470f3c95San Mehat    srcfd = open(SUPP_CONFIG_TEMPLATE, O_RDONLY);
46069772dc644e1ccc12b6394267f010100470f3c95San Mehat    if (srcfd < 0) {
46169772dc644e1ccc12b6394267f010100470f3c95San Mehat        LOGE("Cannot open \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
46269772dc644e1ccc12b6394267f010100470f3c95San Mehat        return -1;
46369772dc644e1ccc12b6394267f010100470f3c95San Mehat    }
46469772dc644e1ccc12b6394267f010100470f3c95San Mehat
46569772dc644e1ccc12b6394267f010100470f3c95San Mehat    destfd = open(SUPP_CONFIG_FILE, O_CREAT|O_WRONLY, 0660);
46669772dc644e1ccc12b6394267f010100470f3c95San Mehat    if (destfd < 0) {
46769772dc644e1ccc12b6394267f010100470f3c95San Mehat        close(srcfd);
46869772dc644e1ccc12b6394267f010100470f3c95San Mehat        LOGE("Cannot create \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno));
46969772dc644e1ccc12b6394267f010100470f3c95San Mehat        return -1;
47069772dc644e1ccc12b6394267f010100470f3c95San Mehat    }
47169772dc644e1ccc12b6394267f010100470f3c95San Mehat
47269772dc644e1ccc12b6394267f010100470f3c95San Mehat    while ((nread = read(srcfd, buf, sizeof(buf))) != 0) {
47369772dc644e1ccc12b6394267f010100470f3c95San Mehat        if (nread < 0) {
47469772dc644e1ccc12b6394267f010100470f3c95San Mehat            LOGE("Error reading \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
47569772dc644e1ccc12b6394267f010100470f3c95San Mehat            close(srcfd);
47669772dc644e1ccc12b6394267f010100470f3c95San Mehat            close(destfd);
47769772dc644e1ccc12b6394267f010100470f3c95San Mehat            unlink(SUPP_CONFIG_FILE);
47869772dc644e1ccc12b6394267f010100470f3c95San Mehat            return -1;
47969772dc644e1ccc12b6394267f010100470f3c95San Mehat        }
48069772dc644e1ccc12b6394267f010100470f3c95San Mehat        write(destfd, buf, nread);
48169772dc644e1ccc12b6394267f010100470f3c95San Mehat    }
48269772dc644e1ccc12b6394267f010100470f3c95San Mehat
48369772dc644e1ccc12b6394267f010100470f3c95San Mehat    close(destfd);
48469772dc644e1ccc12b6394267f010100470f3c95San Mehat    close(srcfd);
48569772dc644e1ccc12b6394267f010100470f3c95San Mehat
48669772dc644e1ccc12b6394267f010100470f3c95San Mehat    if (chown(SUPP_CONFIG_FILE, AID_SYSTEM, AID_WIFI) < 0) {
48769772dc644e1ccc12b6394267f010100470f3c95San Mehat        LOGE("Error changing group ownership of %s to %d: %s",
48869772dc644e1ccc12b6394267f010100470f3c95San Mehat             SUPP_CONFIG_FILE, AID_WIFI, strerror(errno));
48969772dc644e1ccc12b6394267f010100470f3c95San Mehat        unlink(SUPP_CONFIG_FILE);
49069772dc644e1ccc12b6394267f010100470f3c95San Mehat        return -1;
49169772dc644e1ccc12b6394267f010100470f3c95San Mehat    }
49269772dc644e1ccc12b6394267f010100470f3c95San Mehat    return 0;
49369772dc644e1ccc12b6394267f010100470f3c95San Mehat}
4943c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
4953c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehatint Supplicant::setNetworkVar(int networkId, const char *var, const char *val) {
4963c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    char reply[255];
4973c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    size_t len = sizeof(reply) -1;
4983c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
499c4a895b7094461c98101924cf096680bfb7856f1San Mehat    LOGD("netid %d, var '%s' = '%s'", networkId, var, val);
5003c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    char *tmp;
501c4a895b7094461c98101924cf096680bfb7856f1San Mehat    asprintf(&tmp, "SET_NETWORK %d %s %s", networkId, var, val);
5023c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    if (sendCommand(tmp, reply, &len)) {
5033c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        free(tmp);
5043c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        return -1;
5053c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    }
5063c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    free(tmp);
5073aff2d1de59972684bf2ab798351be5544158239San Mehat
5083aff2d1de59972684bf2ab798351be5544158239San Mehat    len = sizeof(reply) -1;
5093aff2d1de59972684bf2ab798351be5544158239San Mehat    if (sendCommand("SAVE_CONFIG", reply, &len)) {
5103aff2d1de59972684bf2ab798351be5544158239San Mehat        LOGE("Error saving config after %s = %s", var, val);
5113aff2d1de59972684bf2ab798351be5544158239San Mehat        return -1;
5123aff2d1de59972684bf2ab798351be5544158239San Mehat    }
5133c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    return 0;
5143c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat}
5153c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
5163c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehatconst char *Supplicant::getNetworkVar(int networkId, const char *var,
5173c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat                                      char *buffer, size_t max) {
5183c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    size_t len = max - 1;
5193c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    char *tmp;
5203c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
5213c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    asprintf(&tmp, "GET_NETWORK %d %s", networkId, var);
5223c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    if (sendCommand(tmp, buffer, &len)) {
5233c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        free(tmp);
5243c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        return NULL;
5253c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    }
5263c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    free(tmp);
5273c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    return buffer;
5283c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat}
5293c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
5303c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehatint Supplicant::enableNetwork(int networkId, bool enabled) {
5313c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    char req[64];
5323c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
5333c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    if (enabled)
5343c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        sprintf(req, "ENABLE_NETWORK %d", networkId);
5353c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    else
5363c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        sprintf(req, "DISABLE_NETWORK %d", networkId);
5373c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
5383c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    char reply[16];
5393c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    size_t len = sizeof(reply) -1;
5403c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
5413c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    if (sendCommand(req, reply, &len))
5423c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        return -1;
5433c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    return 0;
5443c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat}
5453c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
546c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::enablePacketFilter() {
547c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char req[128];
548c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[16];
549c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len;
550c4a895b7094461c98101924cf096680bfb7856f1San Mehat    int i;
551c4a895b7094461c98101924cf096680bfb7856f1San Mehat
552c4a895b7094461c98101924cf096680bfb7856f1San Mehat    for (i = 0; i <=3; i++) {
553c4a895b7094461c98101924cf096680bfb7856f1San Mehat        snprintf(req, sizeof(req), "DRIVER RXFILTER-ADD %d", i);
554c4a895b7094461c98101924cf096680bfb7856f1San Mehat        len = sizeof(reply);
555c4a895b7094461c98101924cf096680bfb7856f1San Mehat        if (sendCommand(req, reply, &len))
556c4a895b7094461c98101924cf096680bfb7856f1San Mehat            return -1;
557c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
558c4a895b7094461c98101924cf096680bfb7856f1San Mehat
559c4a895b7094461c98101924cf096680bfb7856f1San Mehat    len = sizeof(reply);
560c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand("DRIVER RXFILTER-START", reply, &len))
561c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
562c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return 0;
563c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
564c4a895b7094461c98101924cf096680bfb7856f1San Mehat
565c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::disablePacketFilter() {
566c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char req[128];
567c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[16];
568c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len;
569c4a895b7094461c98101924cf096680bfb7856f1San Mehat    int i;
570c4a895b7094461c98101924cf096680bfb7856f1San Mehat
571c4a895b7094461c98101924cf096680bfb7856f1San Mehat    len = sizeof(reply);
572c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand("DRIVER RXFILTER-STOP", reply, &len))
573c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
574c4a895b7094461c98101924cf096680bfb7856f1San Mehat
575c4a895b7094461c98101924cf096680bfb7856f1San Mehat    for (i = 3; i >=0; i--) {
576c4a895b7094461c98101924cf096680bfb7856f1San Mehat        snprintf(req, sizeof(req), "DRIVER RXFILTER-REMOVE %d", i);
577c4a895b7094461c98101924cf096680bfb7856f1San Mehat        len = sizeof(reply);
578c4a895b7094461c98101924cf096680bfb7856f1San Mehat        if (sendCommand(req, reply, &len))
579c4a895b7094461c98101924cf096680bfb7856f1San Mehat            return -1;
580c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
581c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return 0;
582c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
583c4a895b7094461c98101924cf096680bfb7856f1San Mehat
584c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::enableBluetoothCoexistenceScan() {
585c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char req[128];
586c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[16];
587c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len;
588c4a895b7094461c98101924cf096680bfb7856f1San Mehat    int i;
589c4a895b7094461c98101924cf096680bfb7856f1San Mehat
590c4a895b7094461c98101924cf096680bfb7856f1San Mehat    len = sizeof(reply);
591c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand("DRIVER BTCOEXSCAN-START", reply, &len))
592c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
593c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return 0;
594c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
595c4a895b7094461c98101924cf096680bfb7856f1San Mehat
596c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::disableBluetoothCoexistenceScan() {
597c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char req[128];
598c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[16];
599c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len;
600c4a895b7094461c98101924cf096680bfb7856f1San Mehat    int i;
601c4a895b7094461c98101924cf096680bfb7856f1San Mehat
602c4a895b7094461c98101924cf096680bfb7856f1San Mehat    len = sizeof(reply);
603c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand("DRIVER BTCOEXSCAN-STOP", reply, &len))
604c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
605c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return 0;
606c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
607c4a895b7094461c98101924cf096680bfb7856f1San Mehat
608c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::setBluetoothCoexistenceMode(int mode) {
609c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char req[64];
610c4a895b7094461c98101924cf096680bfb7856f1San Mehat
611c4a895b7094461c98101924cf096680bfb7856f1San Mehat    sprintf(req, "DRIVER BTCOEXMODE %d", mode);
612c4a895b7094461c98101924cf096680bfb7856f1San Mehat
613c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[16];
614c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len = sizeof(reply) -1;
615c4a895b7094461c98101924cf096680bfb7856f1San Mehat
616c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand(req, reply, &len))
617c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
618c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return 0;
619c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
620c4a895b7094461c98101924cf096680bfb7856f1San Mehat
621c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::setApScanMode(int mode) {
622c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char req[64];
623c4a895b7094461c98101924cf096680bfb7856f1San Mehat
624c4a895b7094461c98101924cf096680bfb7856f1San Mehat//    LOGD("setApScanMode(%d)", mode);
625c4a895b7094461c98101924cf096680bfb7856f1San Mehat    sprintf(req, "AP_SCAN %d", mode);
626c4a895b7094461c98101924cf096680bfb7856f1San Mehat
627c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[16];
628c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len = sizeof(reply) -1;
629c4a895b7094461c98101924cf096680bfb7856f1San Mehat
630c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand(req, reply, &len))
631c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
632c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return 0;
633c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
634c4a895b7094461c98101924cf096680bfb7856f1San Mehat
6353c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
6363c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehatint Supplicant::retrieveInterfaceName() {
6373c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    char reply[255];
6383c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    size_t len = sizeof(reply) -1;
6393c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
6403c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    if (sendCommand("INTERFACES", reply, &len))
6413c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat        return -1;
6423c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat
6433c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    reply[strlen(reply)-1] = '\0';
6443c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    mInterfaceName = strdup(reply);
6453c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat    return 0;
6463c5a6f0bc8aefc4dacab8e95ba9017a7ac7d91f5San Mehat}
647c4a895b7094461c98101924cf096680bfb7856f1San Mehat
648c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::reconnect() {
649c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char req[128];
650c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[16];
651c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len;
652c4a895b7094461c98101924cf096680bfb7856f1San Mehat    int i;
653c4a895b7094461c98101924cf096680bfb7856f1San Mehat
654c4a895b7094461c98101924cf096680bfb7856f1San Mehat    len = sizeof(reply);
655c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand("RECONNECT", reply, &len))
656c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
657c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return 0;
658c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
659c4a895b7094461c98101924cf096680bfb7856f1San Mehat
660c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::disconnect() {
661c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char req[128];
662c4a895b7094461c98101924cf096680bfb7856f1San Mehat    char reply[16];
663c4a895b7094461c98101924cf096680bfb7856f1San Mehat    size_t len;
664c4a895b7094461c98101924cf096680bfb7856f1San Mehat    int i;
665c4a895b7094461c98101924cf096680bfb7856f1San Mehat
666c4a895b7094461c98101924cf096680bfb7856f1San Mehat    len = sizeof(reply);
667c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (sendCommand("DISCONNECT", reply, &len))
668c4a895b7094461c98101924cf096680bfb7856f1San Mehat        return -1;
669c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return 0;
670c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
671c4a895b7094461c98101924cf096680bfb7856f1San Mehat
672c4a895b7094461c98101924cf096680bfb7856f1San Mehatint Supplicant::getNetworkCount() {
673c4a895b7094461c98101924cf096680bfb7856f1San Mehat    pthread_mutex_lock(&mNetworksLock);
674c4a895b7094461c98101924cf096680bfb7856f1San Mehat    int cnt = mNetworks->size();
675c4a895b7094461c98101924cf096680bfb7856f1San Mehat    pthread_mutex_unlock(&mNetworksLock);
676c4a895b7094461c98101924cf096680bfb7856f1San Mehat    return cnt;
677c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
678