1 /* 2 * wpa_gui - WpaGui class 3 * Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #ifdef CONFIG_NATIVE_WINDOWS 10 #include <windows.h> 11 #endif /* CONFIG_NATIVE_WINDOWS */ 12 13 #include <cstdio> 14 #include <unistd.h> 15 #include <QMessageBox> 16 #include <QCloseEvent> 17 #include <QImageReader> 18 #include <QSettings> 19 20 #include "wpagui.h" 21 #include "dirent.h" 22 #include "common/wpa_ctrl.h" 23 #include "userdatarequest.h" 24 #include "networkconfig.h" 25 26 27 #ifndef QT_NO_DEBUG 28 #define debug(M, ...) qDebug("DEBUG %d: " M, __LINE__, ##__VA_ARGS__) 29 #else 30 #define debug(M, ...) do {} while (0) 31 #endif 32 33 34 WpaGui::WpaGui(QApplication *_app, QWidget *parent, const char *, Qt::WFlags) 35 : QMainWindow(parent), app(_app) 36 { 37 setupUi(this); 38 this->setWindowFlags(Qt::Dialog); 39 40 #ifdef CONFIG_NATIVE_WINDOWS 41 fileStopServiceAction = new QAction(this); 42 fileStopServiceAction->setObjectName("Stop Service"); 43 fileStopServiceAction->setIconText(tr("Stop Service")); 44 fileMenu->insertAction(actionWPS, fileStopServiceAction); 45 46 fileStartServiceAction = new QAction(this); 47 fileStartServiceAction->setObjectName("Start Service"); 48 fileStartServiceAction->setIconText(tr("Start Service")); 49 fileMenu->insertAction(fileStopServiceAction, fileStartServiceAction); 50 51 connect(fileStartServiceAction, SIGNAL(triggered()), this, 52 SLOT(startService())); 53 connect(fileStopServiceAction, SIGNAL(triggered()), this, 54 SLOT(stopService())); 55 56 addInterfaceAction = new QAction(this); 57 addInterfaceAction->setIconText(tr("Add Interface")); 58 fileMenu->insertAction(fileStartServiceAction, addInterfaceAction); 59 60 connect(addInterfaceAction, SIGNAL(triggered()), this, 61 SLOT(addInterface())); 62 #endif /* CONFIG_NATIVE_WINDOWS */ 63 64 (void) statusBar(); 65 66 /* 67 * Disable WPS tab by default; it will be enabled if wpa_supplicant is 68 * built with WPS support. 69 */ 70 wpsTab->setEnabled(false); 71 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), false); 72 73 connect(fileEventHistoryAction, SIGNAL(triggered()), this, 74 SLOT(eventHistory())); 75 connect(fileSaveConfigAction, SIGNAL(triggered()), this, 76 SLOT(saveConfig())); 77 connect(actionWPS, SIGNAL(triggered()), this, SLOT(wpsDialog())); 78 connect(actionPeers, SIGNAL(triggered()), this, SLOT(peersDialog())); 79 connect(fileExitAction, SIGNAL(triggered()), qApp, SLOT(quit())); 80 connect(networkAddAction, SIGNAL(triggered()), this, 81 SLOT(addNetwork())); 82 connect(networkEditAction, SIGNAL(triggered()), this, 83 SLOT(editSelectedNetwork())); 84 connect(networkRemoveAction, SIGNAL(triggered()), this, 85 SLOT(removeSelectedNetwork())); 86 connect(networkEnableAllAction, SIGNAL(triggered()), this, 87 SLOT(enableAllNetworks())); 88 connect(networkDisableAllAction, SIGNAL(triggered()), this, 89 SLOT(disableAllNetworks())); 90 connect(networkRemoveAllAction, SIGNAL(triggered()), this, 91 SLOT(removeAllNetworks())); 92 connect(helpIndexAction, SIGNAL(triggered()), this, SLOT(helpIndex())); 93 connect(helpContentsAction, SIGNAL(triggered()), this, 94 SLOT(helpContents())); 95 connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(helpAbout())); 96 connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect())); 97 connect(scanButton, SIGNAL(clicked()), this, SLOT(scan())); 98 connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB())); 99 connect(adapterSelect, SIGNAL(activated(const QString&)), this, 100 SLOT(selectAdapter(const QString&))); 101 connect(networkSelect, SIGNAL(activated(const QString&)), this, 102 SLOT(selectNetwork(const QString&))); 103 connect(addNetworkButton, SIGNAL(clicked()), this, SLOT(addNetwork())); 104 connect(editNetworkButton, SIGNAL(clicked()), this, 105 SLOT(editListedNetwork())); 106 connect(removeNetworkButton, SIGNAL(clicked()), this, 107 SLOT(removeListedNetwork())); 108 connect(networkList, SIGNAL(itemSelectionChanged()), this, 109 SLOT(updateNetworkDisabledStatus())); 110 connect(enableRadioButton, SIGNAL(toggled(bool)), this, 111 SLOT(enableListedNetwork(bool))); 112 connect(disableRadioButton, SIGNAL(toggled(bool)), this, 113 SLOT(disableListedNetwork(bool))); 114 connect(scanNetworkButton, SIGNAL(clicked()), this, SLOT(scan())); 115 connect(networkList, SIGNAL(itemDoubleClicked(QListWidgetItem *)), 116 this, SLOT(editListedNetwork())); 117 connect(wpaguiTab, SIGNAL(currentChanged(int)), this, 118 SLOT(tabChanged(int))); 119 connect(wpsPbcButton, SIGNAL(clicked()), this, SLOT(wpsPbc())); 120 connect(wpsPinButton, SIGNAL(clicked()), this, SLOT(wpsGeneratePin())); 121 connect(wpsApPinEdit, SIGNAL(textChanged(const QString &)), this, 122 SLOT(wpsApPinChanged(const QString &))); 123 connect(wpsApPinButton, SIGNAL(clicked()), this, SLOT(wpsApPin())); 124 125 eh = NULL; 126 scanres = NULL; 127 peers = NULL; 128 add_iface = NULL; 129 udr = NULL; 130 tray_icon = NULL; 131 startInTray = false; 132 quietMode = false; 133 ctrl_iface = NULL; 134 ctrl_conn = NULL; 135 monitor_conn = NULL; 136 msgNotifier = NULL; 137 ctrl_iface_dir = strdup("/var/run/wpa_supplicant"); 138 139 parse_argv(); 140 141 #ifndef QT_NO_SESSIONMANAGER 142 if (app->isSessionRestored()) { 143 QSettings settings("wpa_supplicant", "wpa_gui"); 144 settings.beginGroup("state"); 145 if (app->sessionId().compare(settings.value("session_id"). 146 toString()) == 0) 147 startInTray = settings.value("in_tray").toBool(); 148 settings.endGroup(); 149 } 150 #endif 151 152 if (QSystemTrayIcon::isSystemTrayAvailable()) 153 createTrayIcon(startInTray); 154 else 155 show(); 156 157 connectedToService = false; 158 textStatus->setText(tr("connecting to wpa_supplicant")); 159 timer = new QTimer(this); 160 connect(timer, SIGNAL(timeout()), SLOT(ping())); 161 timer->setSingleShot(FALSE); 162 timer->start(1000); 163 164 if (openCtrlConnection(ctrl_iface) < 0) { 165 debug("Failed to open control connection to " 166 "wpa_supplicant."); 167 } 168 169 updateStatus(); 170 networkMayHaveChanged = true; 171 updateNetworks(); 172 } 173 174 175 WpaGui::~WpaGui() 176 { 177 delete msgNotifier; 178 179 if (monitor_conn) { 180 wpa_ctrl_detach(monitor_conn); 181 wpa_ctrl_close(monitor_conn); 182 monitor_conn = NULL; 183 } 184 if (ctrl_conn) { 185 wpa_ctrl_close(ctrl_conn); 186 ctrl_conn = NULL; 187 } 188 189 if (eh) { 190 eh->close(); 191 delete eh; 192 eh = NULL; 193 } 194 195 if (scanres) { 196 scanres->close(); 197 delete scanres; 198 scanres = NULL; 199 } 200 201 if (peers) { 202 peers->close(); 203 delete peers; 204 peers = NULL; 205 } 206 207 if (add_iface) { 208 add_iface->close(); 209 delete add_iface; 210 add_iface = NULL; 211 } 212 213 if (udr) { 214 udr->close(); 215 delete udr; 216 udr = NULL; 217 } 218 219 free(ctrl_iface); 220 ctrl_iface = NULL; 221 222 free(ctrl_iface_dir); 223 ctrl_iface_dir = NULL; 224 } 225 226 227 void WpaGui::languageChange() 228 { 229 retranslateUi(this); 230 } 231 232 233 void WpaGui::parse_argv() 234 { 235 int c; 236 for (;;) { 237 c = getopt(qApp->argc(), qApp->argv(), "i:p:tq"); 238 if (c < 0) 239 break; 240 switch (c) { 241 case 'i': 242 free(ctrl_iface); 243 ctrl_iface = strdup(optarg); 244 break; 245 case 'p': 246 free(ctrl_iface_dir); 247 ctrl_iface_dir = strdup(optarg); 248 break; 249 case 't': 250 startInTray = true; 251 break; 252 case 'q': 253 quietMode = true; 254 break; 255 } 256 } 257 } 258 259 260 int WpaGui::openCtrlConnection(const char *ifname) 261 { 262 char *cfile; 263 int flen; 264 char buf[2048], *pos, *pos2; 265 size_t len; 266 267 if (ifname) { 268 if (ifname != ctrl_iface) { 269 free(ctrl_iface); 270 ctrl_iface = strdup(ifname); 271 } 272 } else { 273 #ifdef CONFIG_CTRL_IFACE_UDP 274 free(ctrl_iface); 275 ctrl_iface = strdup("udp"); 276 #endif /* CONFIG_CTRL_IFACE_UDP */ 277 #ifdef CONFIG_CTRL_IFACE_UNIX 278 struct dirent *dent; 279 DIR *dir = opendir(ctrl_iface_dir); 280 free(ctrl_iface); 281 ctrl_iface = NULL; 282 if (dir) { 283 while ((dent = readdir(dir))) { 284 #ifdef _DIRENT_HAVE_D_TYPE 285 /* Skip the file if it is not a socket. 286 * Also accept DT_UNKNOWN (0) in case 287 * the C library or underlying file 288 * system does not support d_type. */ 289 if (dent->d_type != DT_SOCK && 290 dent->d_type != DT_UNKNOWN) 291 continue; 292 #endif /* _DIRENT_HAVE_D_TYPE */ 293 294 if (strcmp(dent->d_name, ".") == 0 || 295 strcmp(dent->d_name, "..") == 0) 296 continue; 297 debug("Selected interface '%s'", 298 dent->d_name); 299 ctrl_iface = strdup(dent->d_name); 300 break; 301 } 302 closedir(dir); 303 } 304 #endif /* CONFIG_CTRL_IFACE_UNIX */ 305 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 306 struct wpa_ctrl *ctrl; 307 int ret; 308 309 free(ctrl_iface); 310 ctrl_iface = NULL; 311 312 ctrl = wpa_ctrl_open(NULL); 313 if (ctrl) { 314 len = sizeof(buf) - 1; 315 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, 316 &len, NULL); 317 if (ret >= 0) { 318 connectedToService = true; 319 buf[len] = '\0'; 320 pos = strchr(buf, '\n'); 321 if (pos) 322 *pos = '\0'; 323 ctrl_iface = strdup(buf); 324 } 325 wpa_ctrl_close(ctrl); 326 } 327 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 328 } 329 330 if (ctrl_iface == NULL) { 331 #ifdef CONFIG_NATIVE_WINDOWS 332 static bool first = true; 333 if (first && !serviceRunning()) { 334 first = false; 335 if (QMessageBox::warning( 336 this, qAppName(), 337 tr("wpa_supplicant service is not " 338 "running.\n" 339 "Do you want to start it?"), 340 QMessageBox::Yes | QMessageBox::No) == 341 QMessageBox::Yes) 342 startService(); 343 } 344 #endif /* CONFIG_NATIVE_WINDOWS */ 345 return -1; 346 } 347 348 #ifdef CONFIG_CTRL_IFACE_UNIX 349 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2; 350 cfile = (char *) malloc(flen); 351 if (cfile == NULL) 352 return -1; 353 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface); 354 #else /* CONFIG_CTRL_IFACE_UNIX */ 355 flen = strlen(ctrl_iface) + 1; 356 cfile = (char *) malloc(flen); 357 if (cfile == NULL) 358 return -1; 359 snprintf(cfile, flen, "%s", ctrl_iface); 360 #endif /* CONFIG_CTRL_IFACE_UNIX */ 361 362 if (ctrl_conn) { 363 wpa_ctrl_close(ctrl_conn); 364 ctrl_conn = NULL; 365 } 366 367 if (monitor_conn) { 368 delete msgNotifier; 369 msgNotifier = NULL; 370 wpa_ctrl_detach(monitor_conn); 371 wpa_ctrl_close(monitor_conn); 372 monitor_conn = NULL; 373 } 374 375 debug("Trying to connect to '%s'", cfile); 376 ctrl_conn = wpa_ctrl_open(cfile); 377 if (ctrl_conn == NULL) { 378 free(cfile); 379 return -1; 380 } 381 monitor_conn = wpa_ctrl_open(cfile); 382 free(cfile); 383 if (monitor_conn == NULL) { 384 wpa_ctrl_close(ctrl_conn); 385 return -1; 386 } 387 if (wpa_ctrl_attach(monitor_conn)) { 388 debug("Failed to attach to wpa_supplicant"); 389 wpa_ctrl_close(monitor_conn); 390 monitor_conn = NULL; 391 wpa_ctrl_close(ctrl_conn); 392 ctrl_conn = NULL; 393 return -1; 394 } 395 396 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) 397 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn), 398 QSocketNotifier::Read, this); 399 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs())); 400 #endif 401 402 adapterSelect->clear(); 403 adapterSelect->addItem(ctrl_iface); 404 adapterSelect->setCurrentIndex(0); 405 406 len = sizeof(buf) - 1; 407 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >= 408 0) { 409 buf[len] = '\0'; 410 pos = buf; 411 while (*pos) { 412 pos2 = strchr(pos, '\n'); 413 if (pos2) 414 *pos2 = '\0'; 415 if (strcmp(pos, ctrl_iface) != 0) 416 adapterSelect->addItem(pos); 417 if (pos2) 418 pos = pos2 + 1; 419 else 420 break; 421 } 422 } 423 424 len = sizeof(buf) - 1; 425 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len, 426 NULL) >= 0) { 427 buf[len] = '\0'; 428 429 QString res(buf); 430 QStringList types = res.split(QChar(' ')); 431 bool wps = types.contains("WSC"); 432 actionWPS->setEnabled(wps); 433 wpsTab->setEnabled(wps); 434 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), wps); 435 } 436 437 return 0; 438 } 439 440 441 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen) 442 { 443 int ret; 444 445 if (ctrl_conn == NULL) 446 return -3; 447 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen, NULL); 448 if (ret == -2) 449 debug("'%s' command timed out.", cmd); 450 else if (ret < 0) 451 debug("'%s' command failed.", cmd); 452 453 return ret; 454 } 455 456 457 QString WpaGui::wpaStateTranslate(char *state) 458 { 459 if (!strcmp(state, "DISCONNECTED")) 460 return tr("Disconnected"); 461 else if (!strcmp(state, "INACTIVE")) 462 return tr("Inactive"); 463 else if (!strcmp(state, "SCANNING")) 464 return tr("Scanning"); 465 else if (!strcmp(state, "AUTHENTICATING")) 466 return tr("Authenticating"); 467 else if (!strcmp(state, "ASSOCIATING")) 468 return tr("Associating"); 469 else if (!strcmp(state, "ASSOCIATED")) 470 return tr("Associated"); 471 else if (!strcmp(state, "4WAY_HANDSHAKE")) 472 return tr("4-Way Handshake"); 473 else if (!strcmp(state, "GROUP_HANDSHAKE")) 474 return tr("Group Handshake"); 475 else if (!strcmp(state, "COMPLETED")) 476 return tr("Completed"); 477 else 478 return tr("Unknown"); 479 } 480 481 482 void WpaGui::updateStatus() 483 { 484 char buf[2048], *start, *end, *pos; 485 size_t len; 486 487 pingsToStatusUpdate = 10; 488 489 len = sizeof(buf) - 1; 490 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) { 491 textStatus->setText(tr("Could not get status from " 492 "wpa_supplicant")); 493 textAuthentication->clear(); 494 textEncryption->clear(); 495 textSsid->clear(); 496 textBssid->clear(); 497 textIpAddress->clear(); 498 updateTrayToolTip(tr("no status information")); 499 500 #ifdef CONFIG_NATIVE_WINDOWS 501 static bool first = true; 502 if (first && connectedToService && 503 (ctrl_iface == NULL || *ctrl_iface == '\0')) { 504 first = false; 505 if (QMessageBox::information( 506 this, qAppName(), 507 tr("No network interfaces in use.\n" 508 "Would you like to add one?"), 509 QMessageBox::Yes | QMessageBox::No) == 510 QMessageBox::Yes) 511 addInterface(); 512 } 513 #endif /* CONFIG_NATIVE_WINDOWS */ 514 return; 515 } 516 517 buf[len] = '\0'; 518 519 bool auth_updated = false, ssid_updated = false; 520 bool bssid_updated = false, ipaddr_updated = false; 521 bool status_updated = false; 522 char *pairwise_cipher = NULL, *group_cipher = NULL; 523 char *mode = NULL; 524 525 start = buf; 526 while (*start) { 527 bool last = false; 528 end = strchr(start, '\n'); 529 if (end == NULL) { 530 last = true; 531 end = start; 532 while (end[0] && end[1]) 533 end++; 534 } 535 *end = '\0'; 536 537 pos = strchr(start, '='); 538 if (pos) { 539 *pos++ = '\0'; 540 if (strcmp(start, "bssid") == 0) { 541 bssid_updated = true; 542 textBssid->setText(pos); 543 } else if (strcmp(start, "ssid") == 0) { 544 ssid_updated = true; 545 textSsid->setText(pos); 546 updateTrayToolTip(pos + tr(" (associated)")); 547 } else if (strcmp(start, "ip_address") == 0) { 548 ipaddr_updated = true; 549 textIpAddress->setText(pos); 550 } else if (strcmp(start, "wpa_state") == 0) { 551 status_updated = true; 552 textStatus->setText(wpaStateTranslate(pos)); 553 } else if (strcmp(start, "key_mgmt") == 0) { 554 auth_updated = true; 555 textAuthentication->setText(pos); 556 /* TODO: could add EAP status to this */ 557 } else if (strcmp(start, "pairwise_cipher") == 0) { 558 pairwise_cipher = pos; 559 } else if (strcmp(start, "group_cipher") == 0) { 560 group_cipher = pos; 561 } else if (strcmp(start, "mode") == 0) { 562 mode = pos; 563 } 564 } 565 566 if (last) 567 break; 568 start = end + 1; 569 } 570 if (status_updated && mode) 571 textStatus->setText(textStatus->text() + " (" + mode + ")"); 572 573 if (pairwise_cipher || group_cipher) { 574 QString encr; 575 if (pairwise_cipher && group_cipher && 576 strcmp(pairwise_cipher, group_cipher) != 0) { 577 encr.append(pairwise_cipher); 578 encr.append(" + "); 579 encr.append(group_cipher); 580 } else if (pairwise_cipher) { 581 encr.append(pairwise_cipher); 582 } else { 583 encr.append(group_cipher); 584 encr.append(" [group key only]"); 585 } 586 textEncryption->setText(encr); 587 } else 588 textEncryption->clear(); 589 590 if (!status_updated) 591 textStatus->clear(); 592 if (!auth_updated) 593 textAuthentication->clear(); 594 if (!ssid_updated) { 595 textSsid->clear(); 596 updateTrayToolTip(tr("(not-associated)")); 597 } 598 if (!bssid_updated) 599 textBssid->clear(); 600 if (!ipaddr_updated) 601 textIpAddress->clear(); 602 } 603 604 605 void WpaGui::updateNetworks() 606 { 607 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags; 608 size_t len; 609 int first_active = -1; 610 int was_selected = -1; 611 bool current = false; 612 613 if (!networkMayHaveChanged) 614 return; 615 616 if (networkList->currentRow() >= 0) 617 was_selected = networkList->currentRow(); 618 619 networkSelect->clear(); 620 networkList->clear(); 621 622 if (ctrl_conn == NULL) 623 return; 624 625 len = sizeof(buf) - 1; 626 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0) 627 return; 628 629 buf[len] = '\0'; 630 start = strchr(buf, '\n'); 631 if (start == NULL) 632 return; 633 start++; 634 635 while (*start) { 636 bool last = false; 637 end = strchr(start, '\n'); 638 if (end == NULL) { 639 last = true; 640 end = start; 641 while (end[0] && end[1]) 642 end++; 643 } 644 *end = '\0'; 645 646 id = start; 647 ssid = strchr(id, '\t'); 648 if (ssid == NULL) 649 break; 650 *ssid++ = '\0'; 651 bssid = strchr(ssid, '\t'); 652 if (bssid == NULL) 653 break; 654 *bssid++ = '\0'; 655 flags = strchr(bssid, '\t'); 656 if (flags == NULL) 657 break; 658 *flags++ = '\0'; 659 660 if (strstr(flags, "[DISABLED][P2P-PERSISTENT]")) { 661 if (last) 662 break; 663 start = end + 1; 664 continue; 665 } 666 667 QString network(id); 668 network.append(": "); 669 network.append(ssid); 670 networkSelect->addItem(network); 671 networkList->addItem(network); 672 673 if (strstr(flags, "[CURRENT]")) { 674 networkSelect->setCurrentIndex(networkSelect->count() - 675 1); 676 current = true; 677 } else if (first_active < 0 && 678 strstr(flags, "[DISABLED]") == NULL) 679 first_active = networkSelect->count() - 1; 680 681 if (last) 682 break; 683 start = end + 1; 684 } 685 686 if (networkSelect->count() > 1) 687 networkSelect->addItem(tr("Select any network")); 688 689 if (!current && first_active >= 0) 690 networkSelect->setCurrentIndex(first_active); 691 692 if (was_selected >= 0 && networkList->count() > 0) { 693 if (was_selected < networkList->count()) 694 networkList->setCurrentRow(was_selected); 695 else 696 networkList->setCurrentRow(networkList->count() - 1); 697 } 698 else 699 networkList->setCurrentRow(networkSelect->currentIndex()); 700 701 networkMayHaveChanged = false; 702 } 703 704 705 void WpaGui::helpIndex() 706 { 707 debug("helpIndex"); 708 } 709 710 711 void WpaGui::helpContents() 712 { 713 debug("helpContents"); 714 } 715 716 717 void WpaGui::helpAbout() 718 { 719 QMessageBox::about(this, "wpa_gui for wpa_supplicant", 720 "Copyright (c) 2003-2013,\n" 721 "Jouni Malinen <j@w1.fi>\n" 722 "and contributors.\n" 723 "\n" 724 "This software may be distributed under\n" 725 "the terms of the BSD license.\n" 726 "See README for more details.\n" 727 "\n" 728 "This product includes software developed\n" 729 "by the OpenSSL Project for use in the\n" 730 "OpenSSL Toolkit (http://www.openssl.org/)\n"); 731 } 732 733 734 void WpaGui::disconnect() 735 { 736 char reply[10]; 737 size_t reply_len = sizeof(reply); 738 ctrlRequest("DISCONNECT", reply, &reply_len); 739 stopWpsRun(false); 740 } 741 742 743 void WpaGui::scan() 744 { 745 if (scanres) { 746 scanres->close(); 747 delete scanres; 748 } 749 750 scanres = new ScanResults(); 751 if (scanres == NULL) 752 return; 753 scanres->setWpaGui(this); 754 scanres->show(); 755 scanres->exec(); 756 } 757 758 759 void WpaGui::eventHistory() 760 { 761 if (eh) { 762 eh->close(); 763 delete eh; 764 } 765 766 eh = new EventHistory(); 767 if (eh == NULL) 768 return; 769 eh->addEvents(msgs); 770 eh->show(); 771 eh->exec(); 772 } 773 774 775 void WpaGui::ping() 776 { 777 char buf[10]; 778 size_t len; 779 780 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 781 /* 782 * QSocketNotifier cannot be used with Windows named pipes, so use a 783 * timer to check for received messages for now. This could be 784 * optimized be doing something specific to named pipes or Windows 785 * events, but it is not clear what would be the best way of doing that 786 * in Qt. 787 */ 788 receiveMsgs(); 789 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 790 791 if (scanres && !scanres->isVisible()) { 792 delete scanres; 793 scanres = NULL; 794 } 795 796 if (eh && !eh->isVisible()) { 797 delete eh; 798 eh = NULL; 799 } 800 801 if (udr && !udr->isVisible()) { 802 delete udr; 803 udr = NULL; 804 } 805 806 len = sizeof(buf) - 1; 807 if (ctrlRequest("PING", buf, &len) < 0) { 808 debug("PING failed - trying to reconnect"); 809 if (openCtrlConnection(ctrl_iface) >= 0) { 810 debug("Reconnected successfully"); 811 pingsToStatusUpdate = 0; 812 } 813 } 814 815 pingsToStatusUpdate--; 816 if (pingsToStatusUpdate <= 0) { 817 updateStatus(); 818 updateNetworks(); 819 } 820 821 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE 822 /* Use less frequent pings and status updates when the main window is 823 * hidden (running in taskbar). */ 824 int interval = isHidden() ? 5000 : 1000; 825 if (timer->interval() != interval) 826 timer->setInterval(interval); 827 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 828 } 829 830 831 static int str_match(const char *a, const char *b) 832 { 833 return strncmp(a, b, strlen(b)) == 0; 834 } 835 836 837 void WpaGui::processMsg(char *msg) 838 { 839 char *pos = msg, *pos2; 840 int priority = 2; 841 842 if (*pos == '<') { 843 /* skip priority */ 844 pos++; 845 priority = atoi(pos); 846 pos = strchr(pos, '>'); 847 if (pos) 848 pos++; 849 else 850 pos = msg; 851 } 852 853 WpaMsg wm(pos, priority); 854 if (eh) 855 eh->addEvent(wm); 856 if (peers) 857 peers->event_notify(wm); 858 msgs.append(wm); 859 while (msgs.count() > 100) 860 msgs.pop_front(); 861 862 /* Update last message with truncated version of the event */ 863 if (strncmp(pos, "CTRL-", 5) == 0) { 864 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' '); 865 if (pos2) 866 pos2++; 867 else 868 pos2 = pos; 869 } else 870 pos2 = pos; 871 QString lastmsg = pos2; 872 lastmsg.truncate(40); 873 textLastMessage->setText(lastmsg); 874 875 pingsToStatusUpdate = 0; 876 networkMayHaveChanged = true; 877 878 if (str_match(pos, WPA_CTRL_REQ)) 879 processCtrlReq(pos + strlen(WPA_CTRL_REQ)); 880 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres) 881 scanres->updateResults(); 882 else if (str_match(pos, WPA_EVENT_DISCONNECTED)) 883 showTrayMessage(QSystemTrayIcon::Information, 3, 884 tr("Disconnected from network.")); 885 else if (str_match(pos, WPA_EVENT_CONNECTED)) { 886 showTrayMessage(QSystemTrayIcon::Information, 3, 887 tr("Connection to network established.")); 888 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus())); 889 stopWpsRun(true); 890 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) { 891 wpsStatusText->setText(tr("WPS AP in active PBC mode found")); 892 if (textStatus->text() == "INACTIVE" || 893 textStatus->text() == "DISCONNECTED") 894 wpaguiTab->setCurrentWidget(wpsTab); 895 wpsInstructions->setText(tr("Press the PBC button on the " 896 "screen to start registration")); 897 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) { 898 wpsStatusText->setText(tr("WPS AP with recently selected " 899 "registrar")); 900 if (textStatus->text() == "INACTIVE" || 901 textStatus->text() == "DISCONNECTED") 902 wpaguiTab->setCurrentWidget(wpsTab); 903 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_AUTH)) { 904 showTrayMessage(QSystemTrayIcon::Information, 3, 905 "Wi-Fi Protected Setup (WPS) AP\n" 906 "indicating this client is authorized."); 907 wpsStatusText->setText("WPS AP indicating this client is " 908 "authorized"); 909 if (textStatus->text() == "INACTIVE" || 910 textStatus->text() == "DISCONNECTED") 911 wpaguiTab->setCurrentWidget(wpsTab); 912 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) { 913 wpsStatusText->setText(tr("WPS AP detected")); 914 } else if (str_match(pos, WPS_EVENT_OVERLAP)) { 915 wpsStatusText->setText(tr("PBC mode overlap detected")); 916 wpsInstructions->setText(tr("More than one AP is currently in " 917 "active WPS PBC mode. Wait couple " 918 "of minutes and try again")); 919 wpaguiTab->setCurrentWidget(wpsTab); 920 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) { 921 wpsStatusText->setText(tr("Network configuration received")); 922 wpaguiTab->setCurrentWidget(wpsTab); 923 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) { 924 if (strstr(pos, "(WSC)")) 925 wpsStatusText->setText(tr("Registration started")); 926 } else if (str_match(pos, WPS_EVENT_M2D)) { 927 wpsStatusText->setText(tr("Registrar does not yet know PIN")); 928 } else if (str_match(pos, WPS_EVENT_FAIL)) { 929 wpsStatusText->setText(tr("Registration failed")); 930 } else if (str_match(pos, WPS_EVENT_SUCCESS)) { 931 wpsStatusText->setText(tr("Registration succeeded")); 932 } 933 } 934 935 936 void WpaGui::processCtrlReq(const char *req) 937 { 938 if (udr) { 939 udr->close(); 940 delete udr; 941 } 942 udr = new UserDataRequest(); 943 if (udr == NULL) 944 return; 945 if (udr->setParams(this, req) < 0) { 946 delete udr; 947 udr = NULL; 948 return; 949 } 950 udr->show(); 951 udr->exec(); 952 } 953 954 955 void WpaGui::receiveMsgs() 956 { 957 char buf[256]; 958 size_t len; 959 960 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) { 961 len = sizeof(buf) - 1; 962 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) { 963 buf[len] = '\0'; 964 processMsg(buf); 965 } 966 } 967 } 968 969 970 void WpaGui::connectB() 971 { 972 char reply[10]; 973 size_t reply_len = sizeof(reply); 974 ctrlRequest("REASSOCIATE", reply, &reply_len); 975 } 976 977 978 void WpaGui::selectNetwork( const QString &sel ) 979 { 980 QString cmd(sel); 981 char reply[10]; 982 size_t reply_len = sizeof(reply); 983 984 if (cmd.contains(QRegExp("^\\d+:"))) 985 cmd.truncate(cmd.indexOf(':')); 986 else 987 cmd = "any"; 988 cmd.prepend("SELECT_NETWORK "); 989 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len); 990 triggerUpdate(); 991 stopWpsRun(false); 992 } 993 994 995 void WpaGui::enableNetwork(const QString &sel) 996 { 997 QString cmd(sel); 998 char reply[10]; 999 size_t reply_len = sizeof(reply); 1000 1001 if (cmd.contains(QRegExp("^\\d+:"))) 1002 cmd.truncate(cmd.indexOf(':')); 1003 else if (!cmd.startsWith("all")) { 1004 debug("Invalid editNetwork '%s'", 1005 cmd.toAscii().constData()); 1006 return; 1007 } 1008 cmd.prepend("ENABLE_NETWORK "); 1009 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len); 1010 triggerUpdate(); 1011 } 1012 1013 1014 void WpaGui::disableNetwork(const QString &sel) 1015 { 1016 QString cmd(sel); 1017 char reply[10]; 1018 size_t reply_len = sizeof(reply); 1019 1020 if (cmd.contains(QRegExp("^\\d+:"))) 1021 cmd.truncate(cmd.indexOf(':')); 1022 else if (!cmd.startsWith("all")) { 1023 debug("Invalid editNetwork '%s'", 1024 cmd.toAscii().constData()); 1025 return; 1026 } 1027 cmd.prepend("DISABLE_NETWORK "); 1028 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len); 1029 triggerUpdate(); 1030 } 1031 1032 1033 void WpaGui::editNetwork(const QString &sel) 1034 { 1035 QString cmd(sel); 1036 int id = -1; 1037 1038 if (cmd.contains(QRegExp("^\\d+:"))) { 1039 cmd.truncate(cmd.indexOf(':')); 1040 id = cmd.toInt(); 1041 } 1042 1043 NetworkConfig *nc = new NetworkConfig(); 1044 if (nc == NULL) 1045 return; 1046 nc->setWpaGui(this); 1047 1048 if (id >= 0) 1049 nc->paramsFromConfig(id); 1050 else 1051 nc->newNetwork(); 1052 1053 nc->show(); 1054 nc->exec(); 1055 } 1056 1057 1058 void WpaGui::editSelectedNetwork() 1059 { 1060 if (networkSelect->count() < 1) { 1061 QMessageBox::information( 1062 this, tr("No Networks"), 1063 tr("There are no networks to edit.\n")); 1064 return; 1065 } 1066 QString sel(networkSelect->currentText()); 1067 editNetwork(sel); 1068 } 1069 1070 1071 void WpaGui::editListedNetwork() 1072 { 1073 if (networkList->currentRow() < 0) { 1074 QMessageBox::information(this, tr("Select A Network"), 1075 tr("Select a network from the list to" 1076 " edit it.\n")); 1077 return; 1078 } 1079 QString sel(networkList->currentItem()->text()); 1080 editNetwork(sel); 1081 } 1082 1083 1084 void WpaGui::triggerUpdate() 1085 { 1086 updateStatus(); 1087 networkMayHaveChanged = true; 1088 updateNetworks(); 1089 } 1090 1091 1092 void WpaGui::addNetwork() 1093 { 1094 NetworkConfig *nc = new NetworkConfig(); 1095 if (nc == NULL) 1096 return; 1097 nc->setWpaGui(this); 1098 nc->newNetwork(); 1099 nc->show(); 1100 nc->exec(); 1101 } 1102 1103 1104 void WpaGui::removeNetwork(const QString &sel) 1105 { 1106 QString cmd(sel); 1107 char reply[10]; 1108 size_t reply_len = sizeof(reply); 1109 1110 if (cmd.contains(QRegExp("^\\d+:"))) 1111 cmd.truncate(cmd.indexOf(':')); 1112 else if (!cmd.startsWith("all")) { 1113 debug("Invalid editNetwork '%s'", 1114 cmd.toAscii().constData()); 1115 return; 1116 } 1117 cmd.prepend("REMOVE_NETWORK "); 1118 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len); 1119 triggerUpdate(); 1120 } 1121 1122 1123 void WpaGui::removeSelectedNetwork() 1124 { 1125 if (networkSelect->count() < 1) { 1126 QMessageBox::information(this, tr("No Networks"), 1127 tr("There are no networks to remove." 1128 "\n")); 1129 return; 1130 } 1131 QString sel(networkSelect->currentText()); 1132 removeNetwork(sel); 1133 } 1134 1135 1136 void WpaGui::removeListedNetwork() 1137 { 1138 if (networkList->currentRow() < 0) { 1139 QMessageBox::information(this, tr("Select A Network"), 1140 tr("Select a network from the list " 1141 "to remove it.\n")); 1142 return; 1143 } 1144 QString sel(networkList->currentItem()->text()); 1145 removeNetwork(sel); 1146 } 1147 1148 1149 void WpaGui::enableAllNetworks() 1150 { 1151 QString sel("all"); 1152 enableNetwork(sel); 1153 } 1154 1155 1156 void WpaGui::disableAllNetworks() 1157 { 1158 QString sel("all"); 1159 disableNetwork(sel); 1160 } 1161 1162 1163 void WpaGui::removeAllNetworks() 1164 { 1165 QString sel("all"); 1166 removeNetwork(sel); 1167 } 1168 1169 1170 int WpaGui::getNetworkDisabled(const QString &sel) 1171 { 1172 QString cmd(sel); 1173 char reply[10]; 1174 size_t reply_len = sizeof(reply) - 1; 1175 int pos = cmd.indexOf(':'); 1176 if (pos < 0) { 1177 debug("Invalid getNetworkDisabled '%s'", 1178 cmd.toAscii().constData()); 1179 return -1; 1180 } 1181 cmd.truncate(pos); 1182 cmd.prepend("GET_NETWORK "); 1183 cmd.append(" disabled"); 1184 1185 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0 1186 && reply_len >= 1) { 1187 reply[reply_len] = '\0'; 1188 if (!str_match(reply, "FAIL")) 1189 return atoi(reply); 1190 } 1191 1192 return -1; 1193 } 1194 1195 1196 void WpaGui::updateNetworkDisabledStatus() 1197 { 1198 if (networkList->currentRow() < 0) 1199 return; 1200 1201 QString sel(networkList->currentItem()->text()); 1202 1203 switch (getNetworkDisabled(sel)) { 1204 case 0: 1205 if (!enableRadioButton->isChecked()) 1206 enableRadioButton->setChecked(true); 1207 return; 1208 case 1: 1209 if (!disableRadioButton->isChecked()) 1210 disableRadioButton->setChecked(true); 1211 return; 1212 } 1213 } 1214 1215 1216 void WpaGui::enableListedNetwork(bool enabled) 1217 { 1218 if (networkList->currentRow() < 0 || !enabled) 1219 return; 1220 1221 QString sel(networkList->currentItem()->text()); 1222 1223 if (getNetworkDisabled(sel) == 1) 1224 enableNetwork(sel); 1225 } 1226 1227 1228 void WpaGui::disableListedNetwork(bool disabled) 1229 { 1230 if (networkList->currentRow() < 0 || !disabled) 1231 return; 1232 1233 QString sel(networkList->currentItem()->text()); 1234 1235 if (getNetworkDisabled(sel) == 0) 1236 disableNetwork(sel); 1237 } 1238 1239 1240 void WpaGui::saveConfig() 1241 { 1242 char buf[10]; 1243 size_t len; 1244 1245 len = sizeof(buf) - 1; 1246 ctrlRequest("SAVE_CONFIG", buf, &len); 1247 1248 buf[len] = '\0'; 1249 1250 if (str_match(buf, "FAIL")) 1251 QMessageBox::warning( 1252 this, tr("Failed to save configuration"), 1253 tr("The configuration could not be saved.\n" 1254 "\n" 1255 "The update_config=1 configuration option\n" 1256 "must be used for configuration saving to\n" 1257 "be permitted.\n")); 1258 else 1259 QMessageBox::information( 1260 this, tr("Saved configuration"), 1261 tr("The current configuration was saved." 1262 "\n")); 1263 } 1264 1265 1266 void WpaGui::selectAdapter( const QString & sel ) 1267 { 1268 if (openCtrlConnection(sel.toAscii().constData()) < 0) 1269 debug("Failed to open control connection to " 1270 "wpa_supplicant."); 1271 updateStatus(); 1272 updateNetworks(); 1273 } 1274 1275 1276 void WpaGui::createTrayIcon(bool trayOnly) 1277 { 1278 QApplication::setQuitOnLastWindowClosed(false); 1279 1280 tray_icon = new QSystemTrayIcon(this); 1281 if (QImageReader::supportedImageFormats().contains(QByteArray("svg"))) 1282 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg")); 1283 else 1284 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png")); 1285 1286 connect(tray_icon, 1287 SIGNAL(activated(QSystemTrayIcon::ActivationReason)), 1288 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason))); 1289 1290 ackTrayIcon = false; 1291 1292 tray_menu = new QMenu(this); 1293 1294 disconnectAction = new QAction(tr("&Disconnect"), this); 1295 reconnectAction = new QAction(tr("Re&connect"), this); 1296 connect(disconnectAction, SIGNAL(triggered()), this, 1297 SLOT(disconnect())); 1298 connect(reconnectAction, SIGNAL(triggered()), this, 1299 SLOT(connectB())); 1300 tray_menu->addAction(disconnectAction); 1301 tray_menu->addAction(reconnectAction); 1302 tray_menu->addSeparator(); 1303 1304 eventAction = new QAction(tr("&Event History"), this); 1305 scanAction = new QAction(tr("Scan &Results"), this); 1306 statAction = new QAction(tr("S&tatus"), this); 1307 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory())); 1308 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan())); 1309 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus())); 1310 tray_menu->addAction(eventAction); 1311 tray_menu->addAction(scanAction); 1312 tray_menu->addAction(statAction); 1313 tray_menu->addSeparator(); 1314 1315 showAction = new QAction(tr("&Show Window"), this); 1316 hideAction = new QAction(tr("&Hide Window"), this); 1317 quitAction = new QAction(tr("&Quit"), this); 1318 connect(showAction, SIGNAL(triggered()), this, SLOT(show())); 1319 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide())); 1320 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); 1321 tray_menu->addAction(showAction); 1322 tray_menu->addAction(hideAction); 1323 tray_menu->addSeparator(); 1324 tray_menu->addAction(quitAction); 1325 1326 tray_icon->setContextMenu(tray_menu); 1327 1328 tray_icon->show(); 1329 1330 if (!trayOnly) 1331 show(); 1332 inTray = trayOnly; 1333 } 1334 1335 1336 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec, 1337 const QString & msg) 1338 { 1339 if (!QSystemTrayIcon::supportsMessages()) 1340 return; 1341 1342 if (isVisible() || !tray_icon || !tray_icon->isVisible() || quietMode) 1343 return; 1344 1345 tray_icon->showMessage(qAppName(), msg, type, sec * 1000); 1346 } 1347 1348 1349 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how) 1350 { 1351 switch (how) { 1352 /* use close() here instead of hide() and allow the 1353 * custom closeEvent handler take care of children */ 1354 case QSystemTrayIcon::Trigger: 1355 ackTrayIcon = true; 1356 if (isVisible()) { 1357 close(); 1358 inTray = true; 1359 } else { 1360 show(); 1361 inTray = false; 1362 } 1363 break; 1364 case QSystemTrayIcon::MiddleClick: 1365 showTrayStatus(); 1366 break; 1367 default: 1368 break; 1369 } 1370 } 1371 1372 1373 void WpaGui::showTrayStatus() 1374 { 1375 char buf[2048]; 1376 size_t len; 1377 1378 len = sizeof(buf) - 1; 1379 if (ctrlRequest("STATUS", buf, &len) < 0) 1380 return; 1381 buf[len] = '\0'; 1382 1383 QString msg, status(buf); 1384 1385 QStringList lines = status.split(QRegExp("\\n")); 1386 for (QStringList::Iterator it = lines.begin(); 1387 it != lines.end(); it++) { 1388 int pos = (*it).indexOf('=') + 1; 1389 if (pos < 1) 1390 continue; 1391 1392 if ((*it).startsWith("bssid=")) 1393 msg.append("BSSID:\t" + (*it).mid(pos) + "\n"); 1394 else if ((*it).startsWith("ssid=")) 1395 msg.append("SSID: \t" + (*it).mid(pos) + "\n"); 1396 else if ((*it).startsWith("pairwise_cipher=")) 1397 msg.append("PAIR: \t" + (*it).mid(pos) + "\n"); 1398 else if ((*it).startsWith("group_cipher=")) 1399 msg.append("GROUP:\t" + (*it).mid(pos) + "\n"); 1400 else if ((*it).startsWith("key_mgmt=")) 1401 msg.append("AUTH: \t" + (*it).mid(pos) + "\n"); 1402 else if ((*it).startsWith("wpa_state=")) 1403 msg.append("STATE:\t" + (*it).mid(pos) + "\n"); 1404 else if ((*it).startsWith("ip_address=")) 1405 msg.append("IP: \t" + (*it).mid(pos) + "\n"); 1406 else if ((*it).startsWith("Supplicant PAE state=")) 1407 msg.append("PAE: \t" + (*it).mid(pos) + "\n"); 1408 else if ((*it).startsWith("EAP state=")) 1409 msg.append("EAP: \t" + (*it).mid(pos) + "\n"); 1410 } 1411 1412 if (!msg.isEmpty()) 1413 showTrayMessage(QSystemTrayIcon::Information, 10, msg); 1414 } 1415 1416 1417 void WpaGui::updateTrayToolTip(const QString &msg) 1418 { 1419 if (tray_icon) 1420 tray_icon->setToolTip(msg); 1421 } 1422 1423 1424 void WpaGui::closeEvent(QCloseEvent *event) 1425 { 1426 if (eh) { 1427 eh->close(); 1428 delete eh; 1429 eh = NULL; 1430 } 1431 1432 if (scanres) { 1433 scanres->close(); 1434 delete scanres; 1435 scanres = NULL; 1436 } 1437 1438 if (peers) { 1439 peers->close(); 1440 delete peers; 1441 peers = NULL; 1442 } 1443 1444 if (udr) { 1445 udr->close(); 1446 delete udr; 1447 udr = NULL; 1448 } 1449 1450 if (tray_icon && !ackTrayIcon) { 1451 /* give user a visual hint that the tray icon exists */ 1452 if (QSystemTrayIcon::supportsMessages()) { 1453 hide(); 1454 showTrayMessage(QSystemTrayIcon::Information, 3, 1455 qAppName() + 1456 tr(" will keep running in " 1457 "the system tray.")); 1458 } else { 1459 QMessageBox::information(this, qAppName() + 1460 tr(" systray"), 1461 tr("The program will keep " 1462 "running in the system " 1463 "tray.")); 1464 } 1465 ackTrayIcon = true; 1466 } 1467 1468 event->accept(); 1469 } 1470 1471 1472 void WpaGui::wpsDialog() 1473 { 1474 wpaguiTab->setCurrentWidget(wpsTab); 1475 } 1476 1477 1478 void WpaGui::peersDialog() 1479 { 1480 if (peers) { 1481 peers->close(); 1482 delete peers; 1483 } 1484 1485 peers = new Peers(); 1486 if (peers == NULL) 1487 return; 1488 peers->setWpaGui(this); 1489 peers->show(); 1490 peers->exec(); 1491 } 1492 1493 1494 void WpaGui::tabChanged(int index) 1495 { 1496 if (index != 2) 1497 return; 1498 1499 if (wpsRunning) 1500 return; 1501 1502 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty()); 1503 if (bssFromScan.isEmpty()) 1504 wpsApPinButton->setEnabled(false); 1505 } 1506 1507 1508 void WpaGui::wpsPbc() 1509 { 1510 char reply[20]; 1511 size_t reply_len = sizeof(reply); 1512 1513 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0) 1514 return; 1515 1516 wpsPinEdit->setEnabled(false); 1517 if (wpsStatusText->text().compare(tr("WPS AP in active PBC mode found"))) { 1518 wpsInstructions->setText(tr("Press the push button on the AP to " 1519 "start the PBC mode.")); 1520 } else { 1521 wpsInstructions->setText(tr("If you have not yet done so, press " 1522 "the push button on the AP to start " 1523 "the PBC mode.")); 1524 } 1525 wpsStatusText->setText(tr("Waiting for Registrar")); 1526 wpsRunning = true; 1527 } 1528 1529 1530 void WpaGui::wpsGeneratePin() 1531 { 1532 char reply[20]; 1533 size_t reply_len = sizeof(reply) - 1; 1534 1535 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0) 1536 return; 1537 1538 reply[reply_len] = '\0'; 1539 1540 wpsPinEdit->setText(reply); 1541 wpsPinEdit->setEnabled(true); 1542 wpsInstructions->setText(tr("Enter the generated PIN into the Registrar " 1543 "(either the internal one in the AP or an " 1544 "external one).")); 1545 wpsStatusText->setText(tr("Waiting for Registrar")); 1546 wpsRunning = true; 1547 } 1548 1549 1550 void WpaGui::setBssFromScan(const QString &bssid) 1551 { 1552 bssFromScan = bssid; 1553 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty()); 1554 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8); 1555 wpsStatusText->setText(tr("WPS AP selected from scan results")); 1556 wpsInstructions->setText(tr("If you want to use an AP device PIN, e.g., " 1557 "from a label in the device, enter the eight " 1558 "digit AP PIN and click Use AP PIN button.")); 1559 } 1560 1561 1562 void WpaGui::wpsApPinChanged(const QString &text) 1563 { 1564 wpsApPinButton->setEnabled(text.length() == 8); 1565 } 1566 1567 1568 void WpaGui::wpsApPin() 1569 { 1570 char reply[20]; 1571 size_t reply_len = sizeof(reply); 1572 1573 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text()); 1574 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0) 1575 return; 1576 1577 wpsStatusText->setText(tr("Waiting for AP/Enrollee")); 1578 wpsRunning = true; 1579 } 1580 1581 1582 void WpaGui::stopWpsRun(bool success) 1583 { 1584 if (wpsRunning) 1585 wpsStatusText->setText(success ? tr("Connected to the network") : 1586 tr("Stopped")); 1587 else 1588 wpsStatusText->setText(""); 1589 wpsPinEdit->setEnabled(false); 1590 wpsInstructions->setText(""); 1591 wpsRunning = false; 1592 bssFromScan = ""; 1593 wpsApPinEdit->setEnabled(false); 1594 wpsApPinButton->setEnabled(false); 1595 } 1596 1597 1598 #ifdef CONFIG_NATIVE_WINDOWS 1599 1600 #ifndef WPASVC_NAME 1601 #define WPASVC_NAME TEXT("wpasvc") 1602 #endif 1603 1604 class ErrorMsg : public QMessageBox { 1605 public: 1606 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError()); 1607 void showMsg(QString msg); 1608 private: 1609 DWORD err; 1610 }; 1611 1612 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) : 1613 QMessageBox(parent), err(last_err) 1614 { 1615 setWindowTitle(tr("wpa_gui error")); 1616 setIcon(QMessageBox::Warning); 1617 } 1618 1619 void ErrorMsg::showMsg(QString msg) 1620 { 1621 LPTSTR buf; 1622 1623 setText(msg); 1624 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 1625 FORMAT_MESSAGE_FROM_SYSTEM, 1626 NULL, err, 0, (LPTSTR) (void *) &buf, 1627 0, NULL) > 0) { 1628 QString msg = QString::fromWCharArray(buf); 1629 setInformativeText(QString("[%1] %2").arg(err).arg(msg)); 1630 LocalFree(buf); 1631 } else { 1632 setInformativeText(QString("[%1]").arg(err)); 1633 } 1634 1635 exec(); 1636 } 1637 1638 1639 void WpaGui::startService() 1640 { 1641 SC_HANDLE svc, scm; 1642 1643 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT); 1644 if (!scm) { 1645 ErrorMsg(this).showMsg(tr("OpenSCManager failed")); 1646 return; 1647 } 1648 1649 svc = OpenService(scm, WPASVC_NAME, SERVICE_START); 1650 if (!svc) { 1651 ErrorMsg(this).showMsg(tr("OpenService failed")); 1652 CloseServiceHandle(scm); 1653 return; 1654 } 1655 1656 if (!StartService(svc, 0, NULL)) { 1657 ErrorMsg(this).showMsg(tr("Failed to start wpa_supplicant " 1658 "service")); 1659 } 1660 1661 CloseServiceHandle(svc); 1662 CloseServiceHandle(scm); 1663 } 1664 1665 1666 void WpaGui::stopService() 1667 { 1668 SC_HANDLE svc, scm; 1669 SERVICE_STATUS status; 1670 1671 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT); 1672 if (!scm) { 1673 ErrorMsg(this).showMsg(tr("OpenSCManager failed")); 1674 return; 1675 } 1676 1677 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP); 1678 if (!svc) { 1679 ErrorMsg(this).showMsg(tr("OpenService failed")); 1680 CloseServiceHandle(scm); 1681 return; 1682 } 1683 1684 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) { 1685 ErrorMsg(this).showMsg(tr("Failed to stop wpa_supplicant " 1686 "service")); 1687 } 1688 1689 CloseServiceHandle(svc); 1690 CloseServiceHandle(scm); 1691 } 1692 1693 1694 bool WpaGui::serviceRunning() 1695 { 1696 SC_HANDLE svc, scm; 1697 SERVICE_STATUS status; 1698 bool running = false; 1699 1700 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT); 1701 if (!scm) { 1702 debug("OpenSCManager failed: %d", (int) GetLastError()); 1703 return false; 1704 } 1705 1706 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS); 1707 if (!svc) { 1708 debug("OpenService failed: %d", (int) GetLastError()); 1709 CloseServiceHandle(scm); 1710 return false; 1711 } 1712 1713 if (QueryServiceStatus(svc, &status)) { 1714 if (status.dwCurrentState != SERVICE_STOPPED) 1715 running = true; 1716 } 1717 1718 CloseServiceHandle(svc); 1719 CloseServiceHandle(scm); 1720 1721 return running; 1722 } 1723 1724 #endif /* CONFIG_NATIVE_WINDOWS */ 1725 1726 1727 void WpaGui::addInterface() 1728 { 1729 if (add_iface) { 1730 add_iface->close(); 1731 delete add_iface; 1732 } 1733 add_iface = new AddInterface(this, this); 1734 add_iface->show(); 1735 add_iface->exec(); 1736 } 1737 1738 1739 #ifndef QT_NO_SESSIONMANAGER 1740 void WpaGui::saveState() 1741 { 1742 QSettings settings("wpa_supplicant", "wpa_gui"); 1743 settings.beginGroup("state"); 1744 settings.setValue("session_id", app->sessionId()); 1745 settings.setValue("in_tray", inTray); 1746 settings.endGroup(); 1747 } 1748 #endif 1749