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