• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Supplicant(WifiController * wc,ISupplicantEventHandler * handlers)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 
~Supplicant()58 Supplicant::~Supplicant() {
59     delete mServiceManager;
60     if (mInterfaceName)
61         free(mInterfaceName);
62 }
63 
start()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 
stop()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 
isStarted()112 bool Supplicant::isStarted() {
113     return mServiceManager->isRunning(SUPPLICANT_SERVICE_NAME);
114 }
115 
sendCommand(const char * cmd,char * reply,size_t * reply_len)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 }
getStatus()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  */
refreshNetworkList()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 
connectToSupplicant()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 
setScanMode(bool active)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 
triggerScan()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 
getRssi(int * buffer)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 
getLinkSpeed()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 
stopDriver()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 
startDriver()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 
createNetwork()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 
removeNetwork(WifiNetwork * wn)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 
lookupNetwork(int networkId)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 
lookupNetwork_UNLOCKED(int networkId)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 
createNetworkList()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 
setupConfig()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 
setNetworkVar(int networkId,const char * var,const char * val)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 
getNetworkVar(int networkId,const char * var,char * buffer,size_t max)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 
enableNetwork(int networkId,bool enabled)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 
enablePacketFilter()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 
disablePacketFilter()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 
enableBluetoothCoexistenceScan()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 
disableBluetoothCoexistenceScan()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 
setBluetoothCoexistenceMode(int mode)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 
setApScanMode(int mode)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 
retrieveInterfaceName()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 
reconnect()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 
disconnect()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 
getNetworkCount()672 int Supplicant::getNetworkCount() {
673     pthread_mutex_lock(&mNetworksLock);
674     int cnt = mNetworks->size();
675     pthread_mutex_unlock(&mNetworksLock);
676     return cnt;
677 }
678