1 /* 2 * wpa_gui - WpaGui class 3 * Copyright (c) 2005-2008, Jouni Malinen <j@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 QString network(id); 663 network.append(": "); 664 network.append(ssid); 665 networkSelect->addItem(network); 666 networkList->addItem(network); 667 668 if (strstr(flags, "[CURRENT]")) { 669 networkSelect->setCurrentIndex(networkSelect->count() - 670 1); 671 current = true; 672 } else if (first_active < 0 && 673 strstr(flags, "[DISABLED]") == NULL) 674 first_active = networkSelect->count() - 1; 675 676 if (last) 677 break; 678 start = end + 1; 679 } 680 681 if (networkSelect->count() > 1) 682 networkSelect->addItem(tr("Select any network")); 683 684 if (!current && first_active >= 0) 685 networkSelect->setCurrentIndex(first_active); 686 687 if (was_selected >= 0 && networkList->count() > 0) { 688 if (was_selected < networkList->count()) 689 networkList->setCurrentRow(was_selected); 690 else 691 networkList->setCurrentRow(networkList->count() - 1); 692 } 693 else 694 networkList->setCurrentRow(networkSelect->currentIndex()); 695 696 networkMayHaveChanged = false; 697 } 698 699 700 void WpaGui::helpIndex() 701 { 702 printf("helpIndex\n"); 703 } 704 705 706 void WpaGui::helpContents() 707 { 708 printf("helpContents\n"); 709 } 710 711 712 void WpaGui::helpAbout() 713 { 714 QMessageBox::about(this, "wpa_gui for wpa_supplicant", 715 "Copyright (c) 2003-2008,\n" 716 "Jouni Malinen <j@w1.fi>\n" 717 "and contributors.\n" 718 "\n" 719 "This program is free software. You can\n" 720 "distribute it and/or modify it under the terms " 721 "of\n" 722 "the GNU General Public License version 2.\n" 723 "\n" 724 "Alternatively, this software may be distributed\n" 725 "under the terms of the BSD license.\n" 726 "\n" 727 "This product includes software developed\n" 728 "by the OpenSSL Project for use in the\n" 729 "OpenSSL Toolkit (http://www.openssl.org/)\n"); 730 } 731 732 733 void WpaGui::disconnect() 734 { 735 char reply[10]; 736 size_t reply_len = sizeof(reply); 737 ctrlRequest("DISCONNECT", reply, &reply_len); 738 stopWpsRun(false); 739 } 740 741 742 void WpaGui::scan() 743 { 744 if (scanres) { 745 scanres->close(); 746 delete scanres; 747 } 748 749 scanres = new ScanResults(); 750 if (scanres == NULL) 751 return; 752 scanres->setWpaGui(this); 753 scanres->show(); 754 scanres->exec(); 755 } 756 757 758 void WpaGui::eventHistory() 759 { 760 if (eh) { 761 eh->close(); 762 delete eh; 763 } 764 765 eh = new EventHistory(); 766 if (eh == NULL) 767 return; 768 eh->addEvents(msgs); 769 eh->show(); 770 eh->exec(); 771 } 772 773 774 void WpaGui::ping() 775 { 776 char buf[10]; 777 size_t len; 778 779 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 780 /* 781 * QSocketNotifier cannot be used with Windows named pipes, so use a 782 * timer to check for received messages for now. This could be 783 * optimized be doing something specific to named pipes or Windows 784 * events, but it is not clear what would be the best way of doing that 785 * in Qt. 786 */ 787 receiveMsgs(); 788 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 789 790 if (scanres && !scanres->isVisible()) { 791 delete scanres; 792 scanres = NULL; 793 } 794 795 if (eh && !eh->isVisible()) { 796 delete eh; 797 eh = NULL; 798 } 799 800 if (udr && !udr->isVisible()) { 801 delete udr; 802 udr = NULL; 803 } 804 805 len = sizeof(buf) - 1; 806 if (ctrlRequest("PING", buf, &len) < 0) { 807 printf("PING failed - trying to reconnect\n"); 808 if (openCtrlConnection(ctrl_iface) >= 0) { 809 printf("Reconnected successfully\n"); 810 pingsToStatusUpdate = 0; 811 } 812 } 813 814 pingsToStatusUpdate--; 815 if (pingsToStatusUpdate <= 0) { 816 updateStatus(); 817 updateNetworks(); 818 } 819 820 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE 821 /* Use less frequent pings and status updates when the main window is 822 * hidden (running in taskbar). */ 823 int interval = isHidden() ? 5000 : 1000; 824 if (timer->interval() != interval) 825 timer->setInterval(interval); 826 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 827 } 828 829 830 static int str_match(const char *a, const char *b) 831 { 832 return strncmp(a, b, strlen(b)) == 0; 833 } 834 835 836 void WpaGui::processMsg(char *msg) 837 { 838 char *pos = msg, *pos2; 839 int priority = 2; 840 841 if (*pos == '<') { 842 /* skip priority */ 843 pos++; 844 priority = atoi(pos); 845 pos = strchr(pos, '>'); 846 if (pos) 847 pos++; 848 else 849 pos = msg; 850 } 851 852 WpaMsg wm(pos, priority); 853 if (eh) 854 eh->addEvent(wm); 855 if (peers) 856 peers->event_notify(wm); 857 msgs.append(wm); 858 while (msgs.count() > 100) 859 msgs.pop_front(); 860 861 /* Update last message with truncated version of the event */ 862 if (strncmp(pos, "CTRL-", 5) == 0) { 863 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' '); 864 if (pos2) 865 pos2++; 866 else 867 pos2 = pos; 868 } else 869 pos2 = pos; 870 QString lastmsg = pos2; 871 lastmsg.truncate(40); 872 textLastMessage->setText(lastmsg); 873 874 pingsToStatusUpdate = 0; 875 networkMayHaveChanged = true; 876 877 if (str_match(pos, WPA_CTRL_REQ)) 878 processCtrlReq(pos + strlen(WPA_CTRL_REQ)); 879 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres) 880 scanres->updateResults(); 881 else if (str_match(pos, WPA_EVENT_DISCONNECTED)) 882 showTrayMessage(QSystemTrayIcon::Information, 3, 883 tr("Disconnected from network.")); 884 else if (str_match(pos, WPA_EVENT_CONNECTED)) { 885 showTrayMessage(QSystemTrayIcon::Information, 3, 886 tr("Connection to network established.")); 887 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus())); 888 stopWpsRun(true); 889 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) { 890 wpsStatusText->setText(tr("WPS AP in active PBC mode found")); 891 if (textStatus->text() == "INACTIVE" || 892 textStatus->text() == "DISCONNECTED") 893 wpaguiTab->setCurrentWidget(wpsTab); 894 wpsInstructions->setText(tr("Press the PBC button on the " 895 "screen to start registration")); 896 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) { 897 wpsStatusText->setText(tr("WPS AP with recently selected " 898 "registrar")); 899 if (textStatus->text() == "INACTIVE" || 900 textStatus->text() == "DISCONNECTED") 901 wpaguiTab->setCurrentWidget(wpsTab); 902 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) { 903 wpsStatusText->setText(tr("WPS AP detected")); 904 } else if (str_match(pos, WPS_EVENT_OVERLAP)) { 905 wpsStatusText->setText(tr("PBC mode overlap detected")); 906 wpsInstructions->setText(tr("More than one AP is currently in " 907 "active WPS PBC mode. Wait couple " 908 "of minutes and try again")); 909 wpaguiTab->setCurrentWidget(wpsTab); 910 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) { 911 wpsStatusText->setText(tr("Network configuration received")); 912 wpaguiTab->setCurrentWidget(wpsTab); 913 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) { 914 if (strstr(pos, "(WSC)")) 915 wpsStatusText->setText(tr("Registration started")); 916 } else if (str_match(pos, WPS_EVENT_M2D)) { 917 wpsStatusText->setText(tr("Registrar does not yet know PIN")); 918 } else if (str_match(pos, WPS_EVENT_FAIL)) { 919 wpsStatusText->setText(tr("Registration failed")); 920 } else if (str_match(pos, WPS_EVENT_SUCCESS)) { 921 wpsStatusText->setText(tr("Registration succeeded")); 922 } 923 } 924 925 926 void WpaGui::processCtrlReq(const char *req) 927 { 928 if (udr) { 929 udr->close(); 930 delete udr; 931 } 932 udr = new UserDataRequest(); 933 if (udr == NULL) 934 return; 935 if (udr->setParams(this, req) < 0) { 936 delete udr; 937 udr = NULL; 938 return; 939 } 940 udr->show(); 941 udr->exec(); 942 } 943 944 945 void WpaGui::receiveMsgs() 946 { 947 char buf[256]; 948 size_t len; 949 950 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) { 951 len = sizeof(buf) - 1; 952 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) { 953 buf[len] = '\0'; 954 processMsg(buf); 955 } 956 } 957 } 958 959 960 void WpaGui::connectB() 961 { 962 char reply[10]; 963 size_t reply_len = sizeof(reply); 964 ctrlRequest("REASSOCIATE", reply, &reply_len); 965 } 966 967 968 void WpaGui::selectNetwork( const QString &sel ) 969 { 970 QString cmd(sel); 971 char reply[10]; 972 size_t reply_len = sizeof(reply); 973 974 if (cmd.compare(tr("Select any network"))) { 975 cmd = "any"; 976 } else { 977 int pos = cmd.indexOf(':'); 978 if (pos < 0) { 979 printf("Invalid selectNetwork '%s'\n", 980 cmd.toAscii().constData()); 981 return; 982 } 983 cmd.truncate(pos); 984 } 985 cmd.prepend("SELECT_NETWORK "); 986 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len); 987 triggerUpdate(); 988 stopWpsRun(false); 989 } 990 991 992 void WpaGui::enableNetwork(const QString &sel) 993 { 994 QString cmd(sel); 995 char reply[10]; 996 size_t reply_len = sizeof(reply); 997 998 if (!cmd.startsWith("all")) { 999 int pos = cmd.indexOf(':'); 1000 if (pos < 0) { 1001 printf("Invalid enableNetwork '%s'\n", 1002 cmd.toAscii().constData()); 1003 return; 1004 } 1005 cmd.truncate(pos); 1006 } 1007 cmd.prepend("ENABLE_NETWORK "); 1008 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len); 1009 triggerUpdate(); 1010 } 1011 1012 1013 void WpaGui::disableNetwork(const QString &sel) 1014 { 1015 QString cmd(sel); 1016 char reply[10]; 1017 size_t reply_len = sizeof(reply); 1018 1019 if (!cmd.startsWith("all")) { 1020 int pos = cmd.indexOf(':'); 1021 if (pos < 0) { 1022 printf("Invalid disableNetwork '%s'\n", 1023 cmd.toAscii().constData()); 1024 return; 1025 } 1026 cmd.truncate(pos); 1027 } 1028 cmd.prepend("DISABLE_NETWORK "); 1029 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len); 1030 triggerUpdate(); 1031 } 1032 1033 1034 void WpaGui::editNetwork(const QString &sel) 1035 { 1036 QString cmd(sel); 1037 int id = -1; 1038 1039 if (!cmd.compare(tr("Select any network"))) { 1040 int pos = sel.indexOf(':'); 1041 if (pos < 0) { 1042 printf("Invalid editNetwork '%s'\n", 1043 cmd.toAscii().constData()); 1044 return; 1045 } 1046 cmd.truncate(pos); 1047 id = cmd.toInt(); 1048 } 1049 1050 NetworkConfig *nc = new NetworkConfig(); 1051 if (nc == NULL) 1052 return; 1053 nc->setWpaGui(this); 1054 1055 if (id >= 0) 1056 nc->paramsFromConfig(id); 1057 else 1058 nc->newNetwork(); 1059 1060 nc->show(); 1061 nc->exec(); 1062 } 1063 1064 1065 void WpaGui::editSelectedNetwork() 1066 { 1067 if (networkSelect->count() < 1) { 1068 QMessageBox::information( 1069 this, tr("No Networks"), 1070 tr("There are no networks to edit.\n")); 1071 return; 1072 } 1073 QString sel(networkSelect->currentText()); 1074 editNetwork(sel); 1075 } 1076 1077 1078 void WpaGui::editListedNetwork() 1079 { 1080 if (networkList->currentRow() < 0) { 1081 QMessageBox::information(this, tr("Select A Network"), 1082 tr("Select a network from the list to" 1083 " edit it.\n")); 1084 return; 1085 } 1086 QString sel(networkList->currentItem()->text()); 1087 editNetwork(sel); 1088 } 1089 1090 1091 void WpaGui::triggerUpdate() 1092 { 1093 updateStatus(); 1094 networkMayHaveChanged = true; 1095 updateNetworks(); 1096 } 1097 1098 1099 void WpaGui::addNetwork() 1100 { 1101 NetworkConfig *nc = new NetworkConfig(); 1102 if (nc == NULL) 1103 return; 1104 nc->setWpaGui(this); 1105 nc->newNetwork(); 1106 nc->show(); 1107 nc->exec(); 1108 } 1109 1110 1111 void WpaGui::removeNetwork(const QString &sel) 1112 { 1113 QString cmd(sel); 1114 char reply[10]; 1115 size_t reply_len = sizeof(reply); 1116 1117 if (cmd.compare(tr("Select any network"))) 1118 return; 1119 1120 if (!cmd.startsWith("all")) { 1121 int pos = cmd.indexOf(':'); 1122 if (pos < 0) { 1123 printf("Invalid removeNetwork '%s'\n", 1124 cmd.toAscii().constData()); 1125 return; 1126 } 1127 cmd.truncate(pos); 1128 } 1129 cmd.prepend("REMOVE_NETWORK "); 1130 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len); 1131 triggerUpdate(); 1132 } 1133 1134 1135 void WpaGui::removeSelectedNetwork() 1136 { 1137 if (networkSelect->count() < 1) { 1138 QMessageBox::information(this, tr("No Networks"), 1139 tr("There are no networks to remove." 1140 "\n")); 1141 return; 1142 } 1143 QString sel(networkSelect->currentText()); 1144 removeNetwork(sel); 1145 } 1146 1147 1148 void WpaGui::removeListedNetwork() 1149 { 1150 if (networkList->currentRow() < 0) { 1151 QMessageBox::information(this, tr("Select A Network"), 1152 tr("Select a network from the list " 1153 "to remove it.\n")); 1154 return; 1155 } 1156 QString sel(networkList->currentItem()->text()); 1157 removeNetwork(sel); 1158 } 1159 1160 1161 void WpaGui::enableAllNetworks() 1162 { 1163 QString sel("all"); 1164 enableNetwork(sel); 1165 } 1166 1167 1168 void WpaGui::disableAllNetworks() 1169 { 1170 QString sel("all"); 1171 disableNetwork(sel); 1172 } 1173 1174 1175 void WpaGui::removeAllNetworks() 1176 { 1177 QString sel("all"); 1178 removeNetwork(sel); 1179 } 1180 1181 1182 int WpaGui::getNetworkDisabled(const QString &sel) 1183 { 1184 QString cmd(sel); 1185 char reply[10]; 1186 size_t reply_len = sizeof(reply) - 1; 1187 int pos = cmd.indexOf(':'); 1188 if (pos < 0) { 1189 printf("Invalid getNetworkDisabled '%s'\n", 1190 cmd.toAscii().constData()); 1191 return -1; 1192 } 1193 cmd.truncate(pos); 1194 cmd.prepend("GET_NETWORK "); 1195 cmd.append(" disabled"); 1196 1197 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0 1198 && reply_len >= 1) { 1199 reply[reply_len] = '\0'; 1200 if (!str_match(reply, "FAIL")) 1201 return atoi(reply); 1202 } 1203 1204 return -1; 1205 } 1206 1207 1208 void WpaGui::updateNetworkDisabledStatus() 1209 { 1210 if (networkList->currentRow() < 0) 1211 return; 1212 1213 QString sel(networkList->currentItem()->text()); 1214 1215 switch (getNetworkDisabled(sel)) { 1216 case 0: 1217 if (!enableRadioButton->isChecked()) 1218 enableRadioButton->setChecked(true); 1219 return; 1220 case 1: 1221 if (!disableRadioButton->isChecked()) 1222 disableRadioButton->setChecked(true); 1223 return; 1224 } 1225 } 1226 1227 1228 void WpaGui::enableListedNetwork(bool enabled) 1229 { 1230 if (networkList->currentRow() < 0 || !enabled) 1231 return; 1232 1233 QString sel(networkList->currentItem()->text()); 1234 1235 if (getNetworkDisabled(sel) == 1) 1236 enableNetwork(sel); 1237 } 1238 1239 1240 void WpaGui::disableListedNetwork(bool disabled) 1241 { 1242 if (networkList->currentRow() < 0 || !disabled) 1243 return; 1244 1245 QString sel(networkList->currentItem()->text()); 1246 1247 if (getNetworkDisabled(sel) == 0) 1248 disableNetwork(sel); 1249 } 1250 1251 1252 void WpaGui::saveConfig() 1253 { 1254 char buf[10]; 1255 size_t len; 1256 1257 len = sizeof(buf) - 1; 1258 ctrlRequest("SAVE_CONFIG", buf, &len); 1259 1260 buf[len] = '\0'; 1261 1262 if (str_match(buf, "FAIL")) 1263 QMessageBox::warning( 1264 this, tr("Failed to save configuration"), 1265 tr("The configuration could not be saved.\n" 1266 "\n" 1267 "The update_config=1 configuration option\n" 1268 "must be used for configuration saving to\n" 1269 "be permitted.\n")); 1270 else 1271 QMessageBox::information( 1272 this, tr("Saved configuration"), 1273 tr("The current configuration was saved." 1274 "\n")); 1275 } 1276 1277 1278 void WpaGui::selectAdapter( const QString & sel ) 1279 { 1280 if (openCtrlConnection(sel.toAscii().constData()) < 0) 1281 printf("Failed to open control connection to " 1282 "wpa_supplicant.\n"); 1283 updateStatus(); 1284 updateNetworks(); 1285 } 1286 1287 1288 void WpaGui::createTrayIcon(bool trayOnly) 1289 { 1290 QApplication::setQuitOnLastWindowClosed(false); 1291 1292 tray_icon = new QSystemTrayIcon(this); 1293 tray_icon->setToolTip(qAppName() + tr(" - wpa_supplicant user interface")); 1294 if (QImageReader::supportedImageFormats().contains(QByteArray("svg"))) 1295 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg")); 1296 else 1297 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png")); 1298 1299 connect(tray_icon, 1300 SIGNAL(activated(QSystemTrayIcon::ActivationReason)), 1301 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason))); 1302 1303 ackTrayIcon = false; 1304 1305 tray_menu = new QMenu(this); 1306 1307 disconnectAction = new QAction(tr("&Disconnect"), this); 1308 reconnectAction = new QAction(tr("Re&connect"), this); 1309 connect(disconnectAction, SIGNAL(triggered()), this, 1310 SLOT(disconnect())); 1311 connect(reconnectAction, SIGNAL(triggered()), this, 1312 SLOT(connectB())); 1313 tray_menu->addAction(disconnectAction); 1314 tray_menu->addAction(reconnectAction); 1315 tray_menu->addSeparator(); 1316 1317 eventAction = new QAction(tr("&Event History"), this); 1318 scanAction = new QAction(tr("Scan &Results"), this); 1319 statAction = new QAction(tr("S&tatus"), this); 1320 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory())); 1321 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan())); 1322 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus())); 1323 tray_menu->addAction(eventAction); 1324 tray_menu->addAction(scanAction); 1325 tray_menu->addAction(statAction); 1326 tray_menu->addSeparator(); 1327 1328 showAction = new QAction(tr("&Show Window"), this); 1329 hideAction = new QAction(tr("&Hide Window"), this); 1330 quitAction = new QAction(tr("&Quit"), this); 1331 connect(showAction, SIGNAL(triggered()), this, SLOT(show())); 1332 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide())); 1333 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); 1334 tray_menu->addAction(showAction); 1335 tray_menu->addAction(hideAction); 1336 tray_menu->addSeparator(); 1337 tray_menu->addAction(quitAction); 1338 1339 tray_icon->setContextMenu(tray_menu); 1340 1341 tray_icon->show(); 1342 1343 if (!trayOnly) 1344 show(); 1345 inTray = trayOnly; 1346 } 1347 1348 1349 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec, 1350 const QString & msg) 1351 { 1352 if (!QSystemTrayIcon::supportsMessages()) 1353 return; 1354 1355 if (isVisible() || !tray_icon || !tray_icon->isVisible()) 1356 return; 1357 1358 tray_icon->showMessage(qAppName(), msg, type, sec * 1000); 1359 } 1360 1361 1362 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how) 1363 { 1364 switch (how) { 1365 /* use close() here instead of hide() and allow the 1366 * custom closeEvent handler take care of children */ 1367 case QSystemTrayIcon::Trigger: 1368 ackTrayIcon = true; 1369 if (isVisible()) { 1370 close(); 1371 inTray = true; 1372 } else { 1373 show(); 1374 inTray = false; 1375 } 1376 break; 1377 case QSystemTrayIcon::MiddleClick: 1378 showTrayStatus(); 1379 break; 1380 default: 1381 break; 1382 } 1383 } 1384 1385 1386 void WpaGui::showTrayStatus() 1387 { 1388 char buf[2048]; 1389 size_t len; 1390 1391 len = sizeof(buf) - 1; 1392 if (ctrlRequest("STATUS", buf, &len) < 0) 1393 return; 1394 buf[len] = '\0'; 1395 1396 QString msg, status(buf); 1397 1398 QStringList lines = status.split(QRegExp("\\n")); 1399 for (QStringList::Iterator it = lines.begin(); 1400 it != lines.end(); it++) { 1401 int pos = (*it).indexOf('=') + 1; 1402 if (pos < 1) 1403 continue; 1404 1405 if ((*it).startsWith("bssid=")) 1406 msg.append("BSSID:\t" + (*it).mid(pos) + "\n"); 1407 else if ((*it).startsWith("ssid=")) 1408 msg.append("SSID: \t" + (*it).mid(pos) + "\n"); 1409 else if ((*it).startsWith("pairwise_cipher=")) 1410 msg.append("PAIR: \t" + (*it).mid(pos) + "\n"); 1411 else if ((*it).startsWith("group_cipher=")) 1412 msg.append("GROUP:\t" + (*it).mid(pos) + "\n"); 1413 else if ((*it).startsWith("key_mgmt=")) 1414 msg.append("AUTH: \t" + (*it).mid(pos) + "\n"); 1415 else if ((*it).startsWith("wpa_state=")) 1416 msg.append("STATE:\t" + (*it).mid(pos) + "\n"); 1417 else if ((*it).startsWith("ip_address=")) 1418 msg.append("IP: \t" + (*it).mid(pos) + "\n"); 1419 else if ((*it).startsWith("Supplicant PAE state=")) 1420 msg.append("PAE: \t" + (*it).mid(pos) + "\n"); 1421 else if ((*it).startsWith("EAP state=")) 1422 msg.append("EAP: \t" + (*it).mid(pos) + "\n"); 1423 } 1424 1425 if (!msg.isEmpty()) 1426 showTrayMessage(QSystemTrayIcon::Information, 10, msg); 1427 } 1428 1429 1430 void WpaGui::closeEvent(QCloseEvent *event) 1431 { 1432 if (eh) { 1433 eh->close(); 1434 delete eh; 1435 eh = NULL; 1436 } 1437 1438 if (scanres) { 1439 scanres->close(); 1440 delete scanres; 1441 scanres = NULL; 1442 } 1443 1444 if (peers) { 1445 peers->close(); 1446 delete peers; 1447 peers = NULL; 1448 } 1449 1450 if (udr) { 1451 udr->close(); 1452 delete udr; 1453 udr = NULL; 1454 } 1455 1456 if (tray_icon && !ackTrayIcon) { 1457 /* give user a visual hint that the tray icon exists */ 1458 if (QSystemTrayIcon::supportsMessages()) { 1459 hide(); 1460 showTrayMessage(QSystemTrayIcon::Information, 3, 1461 qAppName() + 1462 tr(" will keep running in " 1463 "the system tray.")); 1464 } else { 1465 QMessageBox::information(this, qAppName() + 1466 tr(" systray"), 1467 tr("The program will keep " 1468 "running in the system " 1469 "tray.")); 1470 } 1471 ackTrayIcon = true; 1472 } 1473 1474 event->accept(); 1475 } 1476 1477 1478 void WpaGui::wpsDialog() 1479 { 1480 wpaguiTab->setCurrentWidget(wpsTab); 1481 } 1482 1483 1484 void WpaGui::peersDialog() 1485 { 1486 if (peers) { 1487 peers->close(); 1488 delete peers; 1489 } 1490 1491 peers = new Peers(); 1492 if (peers == NULL) 1493 return; 1494 peers->setWpaGui(this); 1495 peers->show(); 1496 peers->exec(); 1497 } 1498 1499 1500 void WpaGui::tabChanged(int index) 1501 { 1502 if (index != 2) 1503 return; 1504 1505 if (wpsRunning) 1506 return; 1507 1508 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty()); 1509 if (bssFromScan.isEmpty()) 1510 wpsApPinButton->setEnabled(false); 1511 } 1512 1513 1514 void WpaGui::wpsPbc() 1515 { 1516 char reply[20]; 1517 size_t reply_len = sizeof(reply); 1518 1519 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0) 1520 return; 1521 1522 wpsPinEdit->setEnabled(false); 1523 if (wpsStatusText->text().compare(tr("WPS AP in active PBC mode found"))) { 1524 wpsInstructions->setText(tr("Press the push button on the AP to " 1525 "start the PBC mode.")); 1526 } else { 1527 wpsInstructions->setText(tr("If you have not yet done so, press " 1528 "the push button on the AP to start " 1529 "the PBC mode.")); 1530 } 1531 wpsStatusText->setText(tr("Waiting for Registrar")); 1532 wpsRunning = true; 1533 } 1534 1535 1536 void WpaGui::wpsGeneratePin() 1537 { 1538 char reply[20]; 1539 size_t reply_len = sizeof(reply) - 1; 1540 1541 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0) 1542 return; 1543 1544 reply[reply_len] = '\0'; 1545 1546 wpsPinEdit->setText(reply); 1547 wpsPinEdit->setEnabled(true); 1548 wpsInstructions->setText(tr("Enter the generated PIN into the Registrar " 1549 "(either the internal one in the AP or an " 1550 "external one).")); 1551 wpsStatusText->setText(tr("Waiting for Registrar")); 1552 wpsRunning = true; 1553 } 1554 1555 1556 void WpaGui::setBssFromScan(const QString &bssid) 1557 { 1558 bssFromScan = bssid; 1559 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty()); 1560 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8); 1561 wpsStatusText->setText(tr("WPS AP selected from scan results")); 1562 wpsInstructions->setText(tr("If you want to use an AP device PIN, e.g., " 1563 "from a label in the device, enter the eight " 1564 "digit AP PIN and click Use AP PIN button.")); 1565 } 1566 1567 1568 void WpaGui::wpsApPinChanged(const QString &text) 1569 { 1570 wpsApPinButton->setEnabled(text.length() == 8); 1571 } 1572 1573 1574 void WpaGui::wpsApPin() 1575 { 1576 char reply[20]; 1577 size_t reply_len = sizeof(reply); 1578 1579 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text()); 1580 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0) 1581 return; 1582 1583 wpsStatusText->setText(tr("Waiting for AP/Enrollee")); 1584 wpsRunning = true; 1585 } 1586 1587 1588 void WpaGui::stopWpsRun(bool success) 1589 { 1590 if (wpsRunning) 1591 wpsStatusText->setText(success ? tr("Connected to the network") : 1592 tr("Stopped")); 1593 else 1594 wpsStatusText->setText(""); 1595 wpsPinEdit->setEnabled(false); 1596 wpsInstructions->setText(""); 1597 wpsRunning = false; 1598 bssFromScan = ""; 1599 wpsApPinEdit->setEnabled(false); 1600 wpsApPinButton->setEnabled(false); 1601 } 1602 1603 1604 #ifdef CONFIG_NATIVE_WINDOWS 1605 1606 #ifndef WPASVC_NAME 1607 #define WPASVC_NAME TEXT("wpasvc") 1608 #endif 1609 1610 class ErrorMsg : public QMessageBox { 1611 public: 1612 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError()); 1613 void showMsg(QString msg); 1614 private: 1615 DWORD err; 1616 }; 1617 1618 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) : 1619 QMessageBox(parent), err(last_err) 1620 { 1621 setWindowTitle(tr("wpa_gui error")); 1622 setIcon(QMessageBox::Warning); 1623 } 1624 1625 void ErrorMsg::showMsg(QString msg) 1626 { 1627 LPTSTR buf; 1628 1629 setText(msg); 1630 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 1631 FORMAT_MESSAGE_FROM_SYSTEM, 1632 NULL, err, 0, (LPTSTR) (void *) &buf, 1633 0, NULL) > 0) { 1634 QString msg = QString::fromWCharArray(buf); 1635 setInformativeText(QString("[%1] %2").arg(err).arg(msg)); 1636 LocalFree(buf); 1637 } else { 1638 setInformativeText(QString("[%1]").arg(err)); 1639 } 1640 1641 exec(); 1642 } 1643 1644 1645 void WpaGui::startService() 1646 { 1647 SC_HANDLE svc, scm; 1648 1649 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT); 1650 if (!scm) { 1651 ErrorMsg(this).showMsg(tr("OpenSCManager failed")); 1652 return; 1653 } 1654 1655 svc = OpenService(scm, WPASVC_NAME, SERVICE_START); 1656 if (!svc) { 1657 ErrorMsg(this).showMsg(tr("OpenService failed")); 1658 CloseServiceHandle(scm); 1659 return; 1660 } 1661 1662 if (!StartService(svc, 0, NULL)) { 1663 ErrorMsg(this).showMsg(tr("Failed to start wpa_supplicant " 1664 "service")); 1665 } 1666 1667 CloseServiceHandle(svc); 1668 CloseServiceHandle(scm); 1669 } 1670 1671 1672 void WpaGui::stopService() 1673 { 1674 SC_HANDLE svc, scm; 1675 SERVICE_STATUS status; 1676 1677 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT); 1678 if (!scm) { 1679 ErrorMsg(this).showMsg(tr("OpenSCManager failed")); 1680 return; 1681 } 1682 1683 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP); 1684 if (!svc) { 1685 ErrorMsg(this).showMsg(tr("OpenService failed")); 1686 CloseServiceHandle(scm); 1687 return; 1688 } 1689 1690 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) { 1691 ErrorMsg(this).showMsg(tr("Failed to stop wpa_supplicant " 1692 "service")); 1693 } 1694 1695 CloseServiceHandle(svc); 1696 CloseServiceHandle(scm); 1697 } 1698 1699 1700 bool WpaGui::serviceRunning() 1701 { 1702 SC_HANDLE svc, scm; 1703 SERVICE_STATUS status; 1704 bool running = false; 1705 1706 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT); 1707 if (!scm) { 1708 printf("OpenSCManager failed: %d\n", (int) GetLastError()); 1709 return false; 1710 } 1711 1712 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS); 1713 if (!svc) { 1714 printf("OpenService failed: %d\n\n", (int) GetLastError()); 1715 CloseServiceHandle(scm); 1716 return false; 1717 } 1718 1719 if (QueryServiceStatus(svc, &status)) { 1720 if (status.dwCurrentState != SERVICE_STOPPED) 1721 running = true; 1722 } 1723 1724 CloseServiceHandle(svc); 1725 CloseServiceHandle(scm); 1726 1727 return running; 1728 } 1729 1730 #endif /* CONFIG_NATIVE_WINDOWS */ 1731 1732 1733 void WpaGui::addInterface() 1734 { 1735 if (add_iface) { 1736 add_iface->close(); 1737 delete add_iface; 1738 } 1739 add_iface = new AddInterface(this, this); 1740 add_iface->show(); 1741 add_iface->exec(); 1742 } 1743 1744 1745 #ifndef QT_NO_SESSIONMANAGER 1746 void WpaGui::saveState() 1747 { 1748 QSettings settings("wpa_supplicant", "wpa_gui"); 1749 settings.beginGroup("state"); 1750 settings.setValue("session_id", app->sessionId()); 1751 settings.setValue("in_tray", inTray); 1752 settings.endGroup(); 1753 } 1754 #endif 1755