Home | History | Annotate | Download | only in nexus
      1 /*
      2  * Copyright (C) 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 <sys/types.h>
     19 #include <fcntl.h>
     20 #include <errno.h>
     21 
     22 #define LOG_TAG "Supplicant"
     23 #include <cutils/log.h>
     24 #include <cutils/properties.h>
     25 
     26 #include "private/android_filesystem_config.h"
     27 
     28 #include <sysutils/ServiceManager.h>
     29 
     30 #include "Supplicant.h"
     31 #include "SupplicantListener.h"
     32 #include "NetworkManager.h"
     33 #include "WifiController.h"
     34 #include "SupplicantStatus.h"
     35 
     36 #include "libwpa_client/wpa_ctrl.h"
     37 
     38 #define IFACE_DIR        "/data/system/wpa_supplicant"
     39 #define DRIVER_PROP_NAME "wlan.driver.status"
     40 #define SUPPLICANT_SERVICE_NAME  "wpa_supplicant"
     41 #define SUPP_CONFIG_TEMPLATE "/system/etc/wifi/wpa_supplicant.conf"
     42 #define SUPP_CONFIG_FILE "/data/misc/wifi/wpa_supplicant.conf"
     43 
     44 Supplicant::Supplicant(WifiController *wc, ISupplicantEventHandler *handlers) {
     45     mHandlers = handlers;
     46     mController = wc;
     47     mInterfaceName = NULL;
     48     mCtrl = NULL;
     49     mMonitor = NULL;
     50     mListener = NULL;
     51 
     52     mServiceManager = new ServiceManager();
     53 
     54     mNetworks = new WifiNetworkCollection();
     55     pthread_mutex_init(&mNetworksLock, NULL);
     56 }
     57 
     58 Supplicant::~Supplicant() {
     59     delete mServiceManager;
     60     if (mInterfaceName)
     61         free(mInterfaceName);
     62 }
     63 
     64 int Supplicant::start() {
     65 
     66     if (setupConfig()) {
     67         LOGW("Unable to setup supplicant.conf");
     68     }
     69 
     70     if (mServiceManager->start(SUPPLICANT_SERVICE_NAME)) {
     71         LOGE("Error starting supplicant (%s)", strerror(errno));
     72         return -1;
     73     }
     74 
     75     wpa_ctrl_cleanup();
     76     if (connectToSupplicant()) {
     77         LOGE("Error connecting to supplicant (%s)\n", strerror(errno));
     78         return -1;
     79     }
     80 
     81     if (retrieveInterfaceName()) {
     82         LOGE("Error retrieving interface name (%s)\n", strerror(errno));
     83         return -1;
     84     }
     85 
     86     return 0;
     87 }
     88 
     89 int Supplicant::stop() {
     90 
     91     if (mListener->stopListener()) {
     92         LOGW("Unable to stop supplicant listener (%s)", strerror(errno));
     93         return -1;
     94     }
     95 
     96     if (mServiceManager->stop(SUPPLICANT_SERVICE_NAME)) {
     97         LOGW("Error stopping supplicant (%s)", strerror(errno));
     98     }
     99 
    100     if (mCtrl) {
    101         wpa_ctrl_close(mCtrl);
    102         mCtrl = NULL;
    103     }
    104     if (mMonitor) {
    105         wpa_ctrl_close(mMonitor);
    106         mMonitor = NULL;
    107     }
    108 
    109     return 0;
    110 }
    111 
    112 bool Supplicant::isStarted() {
    113     return mServiceManager->isRunning(SUPPLICANT_SERVICE_NAME);
    114 }
    115 
    116 int Supplicant::sendCommand(const char *cmd, char *reply, size_t *reply_len) {
    117 
    118     if (!mCtrl) {
    119         errno = ENOTCONN;
    120         return -1;
    121     }
    122 
    123 //    LOGD("sendCommand(): -> '%s'", cmd);
    124 
    125     int rc;
    126     memset(reply, 0, *reply_len);
    127     if ((rc = wpa_ctrl_request(mCtrl, cmd, strlen(cmd), reply, reply_len, NULL)) == -2)  {
    128         errno = ETIMEDOUT;
    129         return -1;
    130     } else if (rc < 0 || !strncmp(reply, "FAIL", 4)) {
    131         strcpy(reply, "FAIL");
    132         errno = EIO;
    133         return -1;
    134     }
    135 
    136  //   LOGD("sendCommand(): <- '%s'", reply);
    137     return 0;
    138 }
    139 SupplicantStatus *Supplicant::getStatus() {
    140     char *reply;
    141     size_t len = 4096;
    142 
    143     if (!(reply = (char *) malloc(len))) {
    144         errno = ENOMEM;
    145         return NULL;
    146     }
    147 
    148     if (sendCommand("STATUS", reply, &len)) {
    149         free(reply);
    150         return NULL;
    151     }
    152 
    153     SupplicantStatus *ss = SupplicantStatus::createStatus(reply, len);
    154 
    155     free (reply);
    156     return ss;
    157 }
    158 
    159 /*
    160  * Retrieves the list of networks from Supplicant
    161  * and merge them into our current list
    162  */
    163 int Supplicant::refreshNetworkList() {
    164     char *reply;
    165     size_t len = 4096;
    166 
    167     if (!(reply = (char *) malloc(len))) {
    168         errno = ENOMEM;
    169         return -1;
    170     }
    171 
    172     if (sendCommand("LIST_NETWORKS", reply, &len)) {
    173         free(reply);
    174         return -1;
    175     }
    176 
    177     char *linep;
    178     char *linep_next = NULL;
    179 
    180     if (!strtok_r(reply, "\n", &linep_next)) {
    181         LOGW("Malformatted network list\n");
    182         free(reply);
    183         errno = EIO;
    184         return -1;
    185     }
    186 
    187     PropertyManager *pm = NetworkManager::Instance()->getPropMngr();
    188     pthread_mutex_lock(&mNetworksLock);
    189 
    190     int num_added = 0;
    191     int num_refreshed = 0;
    192     int num_removed = 0;
    193     while((linep = strtok_r(NULL, "\n", &linep_next))) {
    194         // TODO: Move the decode into a static method so we
    195         // don't create new_wn when we don't have to.
    196         WifiNetwork *new_wn = new WifiNetwork(mController, this, linep);
    197         WifiNetwork *merge_wn;
    198 
    199         if ((merge_wn = this->lookupNetwork_UNLOCKED(new_wn->getNetworkId()))) {
    200             num_refreshed++;
    201             if (merge_wn->refresh()) {
    202                 LOGW("Error refreshing network %d (%s)",
    203                      merge_wn->getNetworkId(), strerror(errno));
    204                 }
    205             delete new_wn;
    206         } else {
    207             num_added++;
    208             char new_ns[20];
    209             snprintf(new_ns, sizeof(new_ns), "wifi.net.%d", new_wn->getNetworkId());
    210             new_wn->attachProperties(pm, new_ns);
    211             mNetworks->push_back(new_wn);
    212             if (new_wn->refresh()) {
    213                 LOGW("Unable to refresh network id %d (%s)",
    214                     new_wn->getNetworkId(), strerror(errno));
    215             }
    216         }
    217     }
    218 
    219     if (!mNetworks->empty()) {
    220         // TODO: Add support for detecting removed networks
    221         WifiNetworkCollection::iterator i;
    222 
    223         for (i = mNetworks->begin(); i != mNetworks->end(); ++i) {
    224             if (0) {
    225                 num_removed++;
    226                 char del_ns[20];
    227                 snprintf(del_ns, sizeof(del_ns), "wifi.net.%d", (*i)->getNetworkId());
    228                 (*i)->detachProperties(pm, del_ns);
    229                 delete (*i);
    230                 i = mNetworks->erase(i);
    231             }
    232         }
    233     }
    234 
    235 
    236     LOGD("Networks added %d, refreshed %d, removed %d\n",
    237          num_added, num_refreshed, num_removed);
    238     pthread_mutex_unlock(&mNetworksLock);
    239 
    240     free(reply);
    241     return 0;
    242 }
    243 
    244 int Supplicant::connectToSupplicant() {
    245     if (!isStarted())
    246         LOGW("Supplicant service not running");
    247 
    248     mCtrl = wpa_ctrl_open("tiwlan0"); // XXX:
    249     if (mCtrl == NULL) {
    250         LOGE("Unable to open connection to supplicant on \"%s\": %s",
    251              "tiwlan0", strerror(errno));
    252         return -1;
    253     }
    254     mMonitor = wpa_ctrl_open("tiwlan0");
    255     if (mMonitor == NULL) {
    256         wpa_ctrl_close(mCtrl);
    257         mCtrl = NULL;
    258         return -1;
    259     }
    260     if (wpa_ctrl_attach(mMonitor) != 0) {
    261         wpa_ctrl_close(mMonitor);
    262         wpa_ctrl_close(mCtrl);
    263         mCtrl = mMonitor = NULL;
    264         return -1;
    265     }
    266 
    267     mListener = new SupplicantListener(mHandlers, mMonitor);
    268 
    269     if (mListener->startListener()) {
    270         LOGE("Error - unable to start supplicant listener");
    271         stop();
    272         return -1;
    273     }
    274     return 0;
    275 }
    276 
    277 int Supplicant::setScanMode(bool active) {
    278     char reply[255];
    279     size_t len = sizeof(reply);
    280 
    281     if (sendCommand((active ? "DRIVER SCAN-ACTIVE" : "DRIVER SCAN-PASSIVE"),
    282                      reply, &len)) {
    283         LOGW("triggerScan(%d): Error setting scan mode (%s)", active,
    284              strerror(errno));
    285         return -1;
    286     }
    287     return 0;
    288 }
    289 
    290 int Supplicant::triggerScan() {
    291     char reply[255];
    292     size_t len = sizeof(reply);
    293 
    294     if (sendCommand("SCAN", reply, &len)) {
    295         LOGW("triggerScan(): Error initiating scan");
    296         return -1;
    297     }
    298     return 0;
    299 }
    300 
    301 int Supplicant::getRssi(int *buffer) {
    302     char reply[64];
    303     size_t len = sizeof(reply);
    304 
    305     if (sendCommand("DRIVER RSSI", reply, &len)) {
    306         LOGW("Failed to get RSSI (%s)", strerror(errno));
    307         return -1;
    308     }
    309 
    310     char *next = reply;
    311     char *s;
    312     for (int i = 0; i < 3; i++) {
    313         if (!(s = strsep(&next, " "))) {
    314             LOGE("Error parsing RSSI");
    315             errno = EIO;
    316             return -1;
    317         }
    318     }
    319     *buffer = atoi(s);
    320     return 0;
    321 }
    322 
    323 int Supplicant::getLinkSpeed() {
    324     char reply[64];
    325     size_t len = sizeof(reply);
    326 
    327     if (sendCommand("DRIVER LINKSPEED", reply, &len)) {
    328         LOGW("Failed to get LINKSPEED (%s)", strerror(errno));
    329         return -1;
    330     }
    331 
    332     char *next = reply;
    333     char *s;
    334 
    335     if (!(s = strsep(&next, " "))) {
    336         LOGE("Error parsing LINKSPEED");
    337         errno = EIO;
    338         return -1;
    339     }
    340 
    341     if (!(s = strsep(&next, " "))) {
    342         LOGE("Error parsing LINKSPEED");
    343         errno = EIO;
    344         return -1;
    345     }
    346     return atoi(s);
    347 }
    348 
    349 int Supplicant::stopDriver() {
    350     char reply[64];
    351     size_t len = sizeof(reply);
    352 
    353     LOGD("stopDriver()");
    354 
    355     if (sendCommand("DRIVER STOP", reply, &len)) {
    356         LOGW("Failed to stop driver (%s)", strerror(errno));
    357         return -1;
    358     }
    359     return 0;
    360 }
    361 
    362 int Supplicant::startDriver() {
    363     char reply[64];
    364     size_t len = sizeof(reply);
    365 
    366     LOGD("startDriver()");
    367     if (sendCommand("DRIVER START", reply, &len)) {
    368         LOGW("Failed to start driver (%s)", strerror(errno));
    369         return -1;
    370     }
    371     return 0;
    372 }
    373 
    374 WifiNetwork *Supplicant::createNetwork() {
    375     char reply[255];
    376     size_t len = sizeof(reply) -1;
    377 
    378     if (sendCommand("ADD_NETWORK", reply, &len))
    379         return NULL;
    380 
    381     if (reply[strlen(reply) -1] == '\n')
    382         reply[strlen(reply) -1] = '\0';
    383 
    384     WifiNetwork *wn = new WifiNetwork(mController, this, atoi(reply));
    385     PropertyManager *pm = NetworkManager::Instance()->getPropMngr();
    386     pthread_mutex_lock(&mNetworksLock);
    387     char new_ns[20];
    388     snprintf(new_ns, sizeof(new_ns), "wifi.net.%d", wn->getNetworkId());
    389     wn->attachProperties(pm, new_ns);
    390     mNetworks->push_back(wn);
    391     pthread_mutex_unlock(&mNetworksLock);
    392     return wn;
    393 }
    394 
    395 int Supplicant::removeNetwork(WifiNetwork *wn) {
    396     char req[64];
    397 
    398     sprintf(req, "REMOVE_NETWORK %d", wn->getNetworkId());
    399     char reply[32];
    400     size_t len = sizeof(reply) -1;
    401 
    402     if (sendCommand(req, reply, &len))
    403         return -1;
    404 
    405     pthread_mutex_lock(&mNetworksLock);
    406     WifiNetworkCollection::iterator it;
    407     for (it = mNetworks->begin(); it != mNetworks->end(); ++it) {
    408         if ((*it) == wn) {
    409             mNetworks->erase(it);
    410             break;
    411         }
    412     }
    413     pthread_mutex_unlock(&mNetworksLock);
    414     return 0;
    415 }
    416 
    417 WifiNetwork *Supplicant::lookupNetwork(int networkId) {
    418     pthread_mutex_lock(&mNetworksLock);
    419     WifiNetwork *wn = lookupNetwork_UNLOCKED(networkId);
    420     pthread_mutex_unlock(&mNetworksLock);
    421     return wn;
    422 }
    423 
    424 WifiNetwork *Supplicant::lookupNetwork_UNLOCKED(int networkId) {
    425     WifiNetworkCollection::iterator it;
    426     for (it = mNetworks->begin(); it != mNetworks->end(); ++it) {
    427         if ((*it)->getNetworkId() == networkId) {
    428             return *it;
    429         }
    430     }
    431     errno = ENOENT;
    432     return NULL;
    433 }
    434 
    435 WifiNetworkCollection *Supplicant::createNetworkList() {
    436     WifiNetworkCollection *d = new WifiNetworkCollection();
    437     WifiNetworkCollection::iterator i;
    438 
    439     pthread_mutex_lock(&mNetworksLock);
    440     for (i = mNetworks->begin(); i != mNetworks->end(); ++i)
    441         d->push_back((*i)->clone());
    442 
    443     pthread_mutex_unlock(&mNetworksLock);
    444     return d;
    445 }
    446 
    447 int Supplicant::setupConfig() {
    448     char buf[2048];
    449     int srcfd, destfd;
    450     int nread;
    451 
    452     if (access(SUPP_CONFIG_FILE, R_OK|W_OK) == 0) {
    453         return 0;
    454     } else if (errno != ENOENT) {
    455         LOGE("Cannot access \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno));
    456         return -1;
    457     }
    458 
    459     srcfd = open(SUPP_CONFIG_TEMPLATE, O_RDONLY);
    460     if (srcfd < 0) {
    461         LOGE("Cannot open \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
    462         return -1;
    463     }
    464 
    465     destfd = open(SUPP_CONFIG_FILE, O_CREAT|O_WRONLY, 0660);
    466     if (destfd < 0) {
    467         close(srcfd);
    468         LOGE("Cannot create \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno));
    469         return -1;
    470     }
    471 
    472     while ((nread = read(srcfd, buf, sizeof(buf))) != 0) {
    473         if (nread < 0) {
    474             LOGE("Error reading \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
    475             close(srcfd);
    476             close(destfd);
    477             unlink(SUPP_CONFIG_FILE);
    478             return -1;
    479         }
    480         write(destfd, buf, nread);
    481     }
    482 
    483     close(destfd);
    484     close(srcfd);
    485 
    486     if (chown(SUPP_CONFIG_FILE, AID_SYSTEM, AID_WIFI) < 0) {
    487         LOGE("Error changing group ownership of %s to %d: %s",
    488              SUPP_CONFIG_FILE, AID_WIFI, strerror(errno));
    489         unlink(SUPP_CONFIG_FILE);
    490         return -1;
    491     }
    492     return 0;
    493 }
    494 
    495 int Supplicant::setNetworkVar(int networkId, const char *var, const char *val) {
    496     char reply[255];
    497     size_t len = sizeof(reply) -1;
    498 
    499     LOGD("netid %d, var '%s' = '%s'", networkId, var, val);
    500     char *tmp;
    501     asprintf(&tmp, "SET_NETWORK %d %s %s", networkId, var, val);
    502     if (sendCommand(tmp, reply, &len)) {
    503         free(tmp);
    504         return -1;
    505     }
    506     free(tmp);
    507 
    508     len = sizeof(reply) -1;
    509     if (sendCommand("SAVE_CONFIG", reply, &len)) {
    510         LOGE("Error saving config after %s = %s", var, val);
    511         return -1;
    512     }
    513     return 0;
    514 }
    515 
    516 const char *Supplicant::getNetworkVar(int networkId, const char *var,
    517                                       char *buffer, size_t max) {
    518     size_t len = max - 1;
    519     char *tmp;
    520 
    521     asprintf(&tmp, "GET_NETWORK %d %s", networkId, var);
    522     if (sendCommand(tmp, buffer, &len)) {
    523         free(tmp);
    524         return NULL;
    525     }
    526     free(tmp);
    527     return buffer;
    528 }
    529 
    530 int Supplicant::enableNetwork(int networkId, bool enabled) {
    531     char req[64];
    532 
    533     if (enabled)
    534         sprintf(req, "ENABLE_NETWORK %d", networkId);
    535     else
    536         sprintf(req, "DISABLE_NETWORK %d", networkId);
    537 
    538     char reply[16];
    539     size_t len = sizeof(reply) -1;
    540 
    541     if (sendCommand(req, reply, &len))
    542         return -1;
    543     return 0;
    544 }
    545 
    546 int Supplicant::enablePacketFilter() {
    547     char req[128];
    548     char reply[16];
    549     size_t len;
    550     int i;
    551 
    552     for (i = 0; i <=3; i++) {
    553         snprintf(req, sizeof(req), "DRIVER RXFILTER-ADD %d", i);
    554         len = sizeof(reply);
    555         if (sendCommand(req, reply, &len))
    556             return -1;
    557     }
    558 
    559     len = sizeof(reply);
    560     if (sendCommand("DRIVER RXFILTER-START", reply, &len))
    561         return -1;
    562     return 0;
    563 }
    564 
    565 int Supplicant::disablePacketFilter() {
    566     char req[128];
    567     char reply[16];
    568     size_t len;
    569     int i;
    570 
    571     len = sizeof(reply);
    572     if (sendCommand("DRIVER RXFILTER-STOP", reply, &len))
    573         return -1;
    574 
    575     for (i = 3; i >=0; i--) {
    576         snprintf(req, sizeof(req), "DRIVER RXFILTER-REMOVE %d", i);
    577         len = sizeof(reply);
    578         if (sendCommand(req, reply, &len))
    579             return -1;
    580     }
    581     return 0;
    582 }
    583 
    584 int Supplicant::enableBluetoothCoexistenceScan() {
    585     char req[128];
    586     char reply[16];
    587     size_t len;
    588     int i;
    589 
    590     len = sizeof(reply);
    591     if (sendCommand("DRIVER BTCOEXSCAN-START", reply, &len))
    592         return -1;
    593     return 0;
    594 }
    595 
    596 int Supplicant::disableBluetoothCoexistenceScan() {
    597     char req[128];
    598     char reply[16];
    599     size_t len;
    600     int i;
    601 
    602     len = sizeof(reply);
    603     if (sendCommand("DRIVER BTCOEXSCAN-STOP", reply, &len))
    604         return -1;
    605     return 0;
    606 }
    607 
    608 int Supplicant::setBluetoothCoexistenceMode(int mode) {
    609     char req[64];
    610 
    611     sprintf(req, "DRIVER BTCOEXMODE %d", mode);
    612 
    613     char reply[16];
    614     size_t len = sizeof(reply) -1;
    615 
    616     if (sendCommand(req, reply, &len))
    617         return -1;
    618     return 0;
    619 }
    620 
    621 int Supplicant::setApScanMode(int mode) {
    622     char req[64];
    623 
    624 //    LOGD("setApScanMode(%d)", mode);
    625     sprintf(req, "AP_SCAN %d", mode);
    626 
    627     char reply[16];
    628     size_t len = sizeof(reply) -1;
    629 
    630     if (sendCommand(req, reply, &len))
    631         return -1;
    632     return 0;
    633 }
    634 
    635 
    636 int Supplicant::retrieveInterfaceName() {
    637     char reply[255];
    638     size_t len = sizeof(reply) -1;
    639 
    640     if (sendCommand("INTERFACES", reply, &len))
    641         return -1;
    642 
    643     reply[strlen(reply)-1] = '\0';
    644     mInterfaceName = strdup(reply);
    645     return 0;
    646 }
    647 
    648 int Supplicant::reconnect() {
    649     char req[128];
    650     char reply[16];
    651     size_t len;
    652     int i;
    653 
    654     len = sizeof(reply);
    655     if (sendCommand("RECONNECT", reply, &len))
    656         return -1;
    657     return 0;
    658 }
    659 
    660 int Supplicant::disconnect() {
    661     char req[128];
    662     char reply[16];
    663     size_t len;
    664     int i;
    665 
    666     len = sizeof(reply);
    667     if (sendCommand("DISCONNECT", reply, &len))
    668         return -1;
    669     return 0;
    670 }
    671 
    672 int Supplicant::getNetworkCount() {
    673     pthread_mutex_lock(&mNetworksLock);
    674     int cnt = mNetworks->size();
    675     pthread_mutex_unlock(&mNetworksLock);
    676     return cnt;
    677 }
    678