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