wpagui.cpp revision 1.1.1.2
1/* 2 * wpa_gui - WpaGui class 3 * Copyright (c) 2005-2010, 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 39static int wpagui_printf(const char *, ...) 40{ 41 return 0; 42} 43#endif 44 45WpaGui::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 184WpaGui::~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 236void WpaGui::languageChange() 237{ 238 retranslateUi(this); 239} 240 241 242void 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 266int 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 447int 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 463QString 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 488void 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 607void 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 700void WpaGui::helpIndex() 701{ 702 printf("helpIndex\n"); 703} 704 705 706void WpaGui::helpContents() 707{ 708 printf("helpContents\n"); 709} 710 711 712void WpaGui::helpAbout() 713{ 714 QMessageBox::about(this, "wpa_gui for wpa_supplicant", 715 "Copyright (c) 2003-2010,\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 733void 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 742void 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 758void 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 774void 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 830static int str_match(const char *a, const char *b) 831{ 832 return strncmp(a, b, strlen(b)) == 0; 833} 834 835 836void 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 926void 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 945void 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 960void WpaGui::connectB() 961{ 962 char reply[10]; 963 size_t reply_len = sizeof(reply); 964 ctrlRequest("REASSOCIATE", reply, &reply_len); 965} 966 967 968void 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.contains(QRegExp("^\\d+:"))) 975 cmd.truncate(cmd.indexOf(':')); 976 else 977 cmd = "any"; 978 cmd.prepend("SELECT_NETWORK "); 979 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len); 980 triggerUpdate(); 981 stopWpsRun(false); 982} 983 984 985void WpaGui::enableNetwork(const QString &sel) 986{ 987 QString cmd(sel); 988 char reply[10]; 989 size_t reply_len = sizeof(reply); 990 991 if (cmd.contains(QRegExp("^\\d+:"))) 992 cmd.truncate(cmd.indexOf(':')); 993 else if (!cmd.startsWith("all")) { 994 printf("Invalid editNetwork '%s'\n", 995 cmd.toAscii().constData()); 996 return; 997 } 998 cmd.prepend("ENABLE_NETWORK "); 999 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len); 1000 triggerUpdate(); 1001} 1002 1003 1004void WpaGui::disableNetwork(const QString &sel) 1005{ 1006 QString cmd(sel); 1007 char reply[10]; 1008 size_t reply_len = sizeof(reply); 1009 1010 if (cmd.contains(QRegExp("^\\d+:"))) 1011 cmd.truncate(cmd.indexOf(':')); 1012 else if (!cmd.startsWith("all")) { 1013 printf("Invalid editNetwork '%s'\n", 1014 cmd.toAscii().constData()); 1015 return; 1016 } 1017 cmd.prepend("DISABLE_NETWORK "); 1018 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len); 1019 triggerUpdate(); 1020} 1021 1022 1023void WpaGui::editNetwork(const QString &sel) 1024{ 1025 QString cmd(sel); 1026 int id = -1; 1027 1028 if (cmd.contains(QRegExp("^\\d+:"))) { 1029 cmd.truncate(cmd.indexOf(':')); 1030 id = cmd.toInt(); 1031 } 1032 1033 NetworkConfig *nc = new NetworkConfig(); 1034 if (nc == NULL) 1035 return; 1036 nc->setWpaGui(this); 1037 1038 if (id >= 0) 1039 nc->paramsFromConfig(id); 1040 else 1041 nc->newNetwork(); 1042 1043 nc->show(); 1044 nc->exec(); 1045} 1046 1047 1048void WpaGui::editSelectedNetwork() 1049{ 1050 if (networkSelect->count() < 1) { 1051 QMessageBox::information( 1052 this, tr("No Networks"), 1053 tr("There are no networks to edit.\n")); 1054 return; 1055 } 1056 QString sel(networkSelect->currentText()); 1057 editNetwork(sel); 1058} 1059 1060 1061void WpaGui::editListedNetwork() 1062{ 1063 if (networkList->currentRow() < 0) { 1064 QMessageBox::information(this, tr("Select A Network"), 1065 tr("Select a network from the list to" 1066 " edit it.\n")); 1067 return; 1068 } 1069 QString sel(networkList->currentItem()->text()); 1070 editNetwork(sel); 1071} 1072 1073 1074void WpaGui::triggerUpdate() 1075{ 1076 updateStatus(); 1077 networkMayHaveChanged = true; 1078 updateNetworks(); 1079} 1080 1081 1082void WpaGui::addNetwork() 1083{ 1084 NetworkConfig *nc = new NetworkConfig(); 1085 if (nc == NULL) 1086 return; 1087 nc->setWpaGui(this); 1088 nc->newNetwork(); 1089 nc->show(); 1090 nc->exec(); 1091} 1092 1093 1094void WpaGui::removeNetwork(const QString &sel) 1095{ 1096 QString cmd(sel); 1097 char reply[10]; 1098 size_t reply_len = sizeof(reply); 1099 1100 if (cmd.contains(QRegExp("^\\d+:"))) 1101 cmd.truncate(cmd.indexOf(':')); 1102 else if (!cmd.startsWith("all")) { 1103 printf("Invalid editNetwork '%s'\n", 1104 cmd.toAscii().constData()); 1105 return; 1106 } 1107 cmd.prepend("REMOVE_NETWORK "); 1108 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len); 1109 triggerUpdate(); 1110} 1111 1112 1113void WpaGui::removeSelectedNetwork() 1114{ 1115 if (networkSelect->count() < 1) { 1116 QMessageBox::information(this, tr("No Networks"), 1117 tr("There are no networks to remove." 1118 "\n")); 1119 return; 1120 } 1121 QString sel(networkSelect->currentText()); 1122 removeNetwork(sel); 1123} 1124 1125 1126void WpaGui::removeListedNetwork() 1127{ 1128 if (networkList->currentRow() < 0) { 1129 QMessageBox::information(this, tr("Select A Network"), 1130 tr("Select a network from the list " 1131 "to remove it.\n")); 1132 return; 1133 } 1134 QString sel(networkList->currentItem()->text()); 1135 removeNetwork(sel); 1136} 1137 1138 1139void WpaGui::enableAllNetworks() 1140{ 1141 QString sel("all"); 1142 enableNetwork(sel); 1143} 1144 1145 1146void WpaGui::disableAllNetworks() 1147{ 1148 QString sel("all"); 1149 disableNetwork(sel); 1150} 1151 1152 1153void WpaGui::removeAllNetworks() 1154{ 1155 QString sel("all"); 1156 removeNetwork(sel); 1157} 1158 1159 1160int WpaGui::getNetworkDisabled(const QString &sel) 1161{ 1162 QString cmd(sel); 1163 char reply[10]; 1164 size_t reply_len = sizeof(reply) - 1; 1165 int pos = cmd.indexOf(':'); 1166 if (pos < 0) { 1167 printf("Invalid getNetworkDisabled '%s'\n", 1168 cmd.toAscii().constData()); 1169 return -1; 1170 } 1171 cmd.truncate(pos); 1172 cmd.prepend("GET_NETWORK "); 1173 cmd.append(" disabled"); 1174 1175 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0 1176 && reply_len >= 1) { 1177 reply[reply_len] = '\0'; 1178 if (!str_match(reply, "FAIL")) 1179 return atoi(reply); 1180 } 1181 1182 return -1; 1183} 1184 1185 1186void WpaGui::updateNetworkDisabledStatus() 1187{ 1188 if (networkList->currentRow() < 0) 1189 return; 1190 1191 QString sel(networkList->currentItem()->text()); 1192 1193 switch (getNetworkDisabled(sel)) { 1194 case 0: 1195 if (!enableRadioButton->isChecked()) 1196 enableRadioButton->setChecked(true); 1197 return; 1198 case 1: 1199 if (!disableRadioButton->isChecked()) 1200 disableRadioButton->setChecked(true); 1201 return; 1202 } 1203} 1204 1205 1206void WpaGui::enableListedNetwork(bool enabled) 1207{ 1208 if (networkList->currentRow() < 0 || !enabled) 1209 return; 1210 1211 QString sel(networkList->currentItem()->text()); 1212 1213 if (getNetworkDisabled(sel) == 1) 1214 enableNetwork(sel); 1215} 1216 1217 1218void WpaGui::disableListedNetwork(bool disabled) 1219{ 1220 if (networkList->currentRow() < 0 || !disabled) 1221 return; 1222 1223 QString sel(networkList->currentItem()->text()); 1224 1225 if (getNetworkDisabled(sel) == 0) 1226 disableNetwork(sel); 1227} 1228 1229 1230void WpaGui::saveConfig() 1231{ 1232 char buf[10]; 1233 size_t len; 1234 1235 len = sizeof(buf) - 1; 1236 ctrlRequest("SAVE_CONFIG", buf, &len); 1237 1238 buf[len] = '\0'; 1239 1240 if (str_match(buf, "FAIL")) 1241 QMessageBox::warning( 1242 this, tr("Failed to save configuration"), 1243 tr("The configuration could not be saved.\n" 1244 "\n" 1245 "The update_config=1 configuration option\n" 1246 "must be used for configuration saving to\n" 1247 "be permitted.\n")); 1248 else 1249 QMessageBox::information( 1250 this, tr("Saved configuration"), 1251 tr("The current configuration was saved." 1252 "\n")); 1253} 1254 1255 1256void WpaGui::selectAdapter( const QString & sel ) 1257{ 1258 if (openCtrlConnection(sel.toAscii().constData()) < 0) 1259 printf("Failed to open control connection to " 1260 "wpa_supplicant.\n"); 1261 updateStatus(); 1262 updateNetworks(); 1263} 1264 1265 1266void WpaGui::createTrayIcon(bool trayOnly) 1267{ 1268 QApplication::setQuitOnLastWindowClosed(false); 1269 1270 tray_icon = new QSystemTrayIcon(this); 1271 tray_icon->setToolTip(qAppName() + tr(" - wpa_supplicant user interface")); 1272 if (QImageReader::supportedImageFormats().contains(QByteArray("svg"))) 1273 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg")); 1274 else 1275 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png")); 1276 1277 connect(tray_icon, 1278 SIGNAL(activated(QSystemTrayIcon::ActivationReason)), 1279 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason))); 1280 1281 ackTrayIcon = false; 1282 1283 tray_menu = new QMenu(this); 1284 1285 disconnectAction = new QAction(tr("&Disconnect"), this); 1286 reconnectAction = new QAction(tr("Re&connect"), this); 1287 connect(disconnectAction, SIGNAL(triggered()), this, 1288 SLOT(disconnect())); 1289 connect(reconnectAction, SIGNAL(triggered()), this, 1290 SLOT(connectB())); 1291 tray_menu->addAction(disconnectAction); 1292 tray_menu->addAction(reconnectAction); 1293 tray_menu->addSeparator(); 1294 1295 eventAction = new QAction(tr("&Event History"), this); 1296 scanAction = new QAction(tr("Scan &Results"), this); 1297 statAction = new QAction(tr("S&tatus"), this); 1298 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory())); 1299 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan())); 1300 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus())); 1301 tray_menu->addAction(eventAction); 1302 tray_menu->addAction(scanAction); 1303 tray_menu->addAction(statAction); 1304 tray_menu->addSeparator(); 1305 1306 showAction = new QAction(tr("&Show Window"), this); 1307 hideAction = new QAction(tr("&Hide Window"), this); 1308 quitAction = new QAction(tr("&Quit"), this); 1309 connect(showAction, SIGNAL(triggered()), this, SLOT(show())); 1310 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide())); 1311 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); 1312 tray_menu->addAction(showAction); 1313 tray_menu->addAction(hideAction); 1314 tray_menu->addSeparator(); 1315 tray_menu->addAction(quitAction); 1316 1317 tray_icon->setContextMenu(tray_menu); 1318 1319 tray_icon->show(); 1320 1321 if (!trayOnly) 1322 show(); 1323 inTray = trayOnly; 1324} 1325 1326 1327void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec, 1328 const QString & msg) 1329{ 1330 if (!QSystemTrayIcon::supportsMessages()) 1331 return; 1332 1333 if (isVisible() || !tray_icon || !tray_icon->isVisible()) 1334 return; 1335 1336 tray_icon->showMessage(qAppName(), msg, type, sec * 1000); 1337} 1338 1339 1340void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how) 1341 { 1342 switch (how) { 1343 /* use close() here instead of hide() and allow the 1344 * custom closeEvent handler take care of children */ 1345 case QSystemTrayIcon::Trigger: 1346 ackTrayIcon = true; 1347 if (isVisible()) { 1348 close(); 1349 inTray = true; 1350 } else { 1351 show(); 1352 inTray = false; 1353 } 1354 break; 1355 case QSystemTrayIcon::MiddleClick: 1356 showTrayStatus(); 1357 break; 1358 default: 1359 break; 1360 } 1361} 1362 1363 1364void WpaGui::showTrayStatus() 1365{ 1366 char buf[2048]; 1367 size_t len; 1368 1369 len = sizeof(buf) - 1; 1370 if (ctrlRequest("STATUS", buf, &len) < 0) 1371 return; 1372 buf[len] = '\0'; 1373 1374 QString msg, status(buf); 1375 1376 QStringList lines = status.split(QRegExp("\\n")); 1377 for (QStringList::Iterator it = lines.begin(); 1378 it != lines.end(); it++) { 1379 int pos = (*it).indexOf('=') + 1; 1380 if (pos < 1) 1381 continue; 1382 1383 if ((*it).startsWith("bssid=")) 1384 msg.append("BSSID:\t" + (*it).mid(pos) + "\n"); 1385 else if ((*it).startsWith("ssid=")) 1386 msg.append("SSID: \t" + (*it).mid(pos) + "\n"); 1387 else if ((*it).startsWith("pairwise_cipher=")) 1388 msg.append("PAIR: \t" + (*it).mid(pos) + "\n"); 1389 else if ((*it).startsWith("group_cipher=")) 1390 msg.append("GROUP:\t" + (*it).mid(pos) + "\n"); 1391 else if ((*it).startsWith("key_mgmt=")) 1392 msg.append("AUTH: \t" + (*it).mid(pos) + "\n"); 1393 else if ((*it).startsWith("wpa_state=")) 1394 msg.append("STATE:\t" + (*it).mid(pos) + "\n"); 1395 else if ((*it).startsWith("ip_address=")) 1396 msg.append("IP: \t" + (*it).mid(pos) + "\n"); 1397 else if ((*it).startsWith("Supplicant PAE state=")) 1398 msg.append("PAE: \t" + (*it).mid(pos) + "\n"); 1399 else if ((*it).startsWith("EAP state=")) 1400 msg.append("EAP: \t" + (*it).mid(pos) + "\n"); 1401 } 1402 1403 if (!msg.isEmpty()) 1404 showTrayMessage(QSystemTrayIcon::Information, 10, msg); 1405} 1406 1407 1408void WpaGui::closeEvent(QCloseEvent *event) 1409{ 1410 if (eh) { 1411 eh->close(); 1412 delete eh; 1413 eh = NULL; 1414 } 1415 1416 if (scanres) { 1417 scanres->close(); 1418 delete scanres; 1419 scanres = NULL; 1420 } 1421 1422 if (peers) { 1423 peers->close(); 1424 delete peers; 1425 peers = NULL; 1426 } 1427 1428 if (udr) { 1429 udr->close(); 1430 delete udr; 1431 udr = NULL; 1432 } 1433 1434 if (tray_icon && !ackTrayIcon) { 1435 /* give user a visual hint that the tray icon exists */ 1436 if (QSystemTrayIcon::supportsMessages()) { 1437 hide(); 1438 showTrayMessage(QSystemTrayIcon::Information, 3, 1439 qAppName() + 1440 tr(" will keep running in " 1441 "the system tray.")); 1442 } else { 1443 QMessageBox::information(this, qAppName() + 1444 tr(" systray"), 1445 tr("The program will keep " 1446 "running in the system " 1447 "tray.")); 1448 } 1449 ackTrayIcon = true; 1450 } 1451 1452 event->accept(); 1453} 1454 1455 1456void WpaGui::wpsDialog() 1457{ 1458 wpaguiTab->setCurrentWidget(wpsTab); 1459} 1460 1461 1462void WpaGui::peersDialog() 1463{ 1464 if (peers) { 1465 peers->close(); 1466 delete peers; 1467 } 1468 1469 peers = new Peers(); 1470 if (peers == NULL) 1471 return; 1472 peers->setWpaGui(this); 1473 peers->show(); 1474 peers->exec(); 1475} 1476 1477 1478void WpaGui::tabChanged(int index) 1479{ 1480 if (index != 2) 1481 return; 1482 1483 if (wpsRunning) 1484 return; 1485 1486 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty()); 1487 if (bssFromScan.isEmpty()) 1488 wpsApPinButton->setEnabled(false); 1489} 1490 1491 1492void WpaGui::wpsPbc() 1493{ 1494 char reply[20]; 1495 size_t reply_len = sizeof(reply); 1496 1497 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0) 1498 return; 1499 1500 wpsPinEdit->setEnabled(false); 1501 if (wpsStatusText->text().compare(tr("WPS AP in active PBC mode found"))) { 1502 wpsInstructions->setText(tr("Press the push button on the AP to " 1503 "start the PBC mode.")); 1504 } else { 1505 wpsInstructions->setText(tr("If you have not yet done so, press " 1506 "the push button on the AP to start " 1507 "the PBC mode.")); 1508 } 1509 wpsStatusText->setText(tr("Waiting for Registrar")); 1510 wpsRunning = true; 1511} 1512 1513 1514void WpaGui::wpsGeneratePin() 1515{ 1516 char reply[20]; 1517 size_t reply_len = sizeof(reply) - 1; 1518 1519 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0) 1520 return; 1521 1522 reply[reply_len] = '\0'; 1523 1524 wpsPinEdit->setText(reply); 1525 wpsPinEdit->setEnabled(true); 1526 wpsInstructions->setText(tr("Enter the generated PIN into the Registrar " 1527 "(either the internal one in the AP or an " 1528 "external one).")); 1529 wpsStatusText->setText(tr("Waiting for Registrar")); 1530 wpsRunning = true; 1531} 1532 1533 1534void WpaGui::setBssFromScan(const QString &bssid) 1535{ 1536 bssFromScan = bssid; 1537 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty()); 1538 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8); 1539 wpsStatusText->setText(tr("WPS AP selected from scan results")); 1540 wpsInstructions->setText(tr("If you want to use an AP device PIN, e.g., " 1541 "from a label in the device, enter the eight " 1542 "digit AP PIN and click Use AP PIN button.")); 1543} 1544 1545 1546void WpaGui::wpsApPinChanged(const QString &text) 1547{ 1548 wpsApPinButton->setEnabled(text.length() == 8); 1549} 1550 1551 1552void WpaGui::wpsApPin() 1553{ 1554 char reply[20]; 1555 size_t reply_len = sizeof(reply); 1556 1557 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text()); 1558 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0) 1559 return; 1560 1561 wpsStatusText->setText(tr("Waiting for AP/Enrollee")); 1562 wpsRunning = true; 1563} 1564 1565 1566void WpaGui::stopWpsRun(bool success) 1567{ 1568 if (wpsRunning) 1569 wpsStatusText->setText(success ? tr("Connected to the network") : 1570 tr("Stopped")); 1571 else 1572 wpsStatusText->setText(""); 1573 wpsPinEdit->setEnabled(false); 1574 wpsInstructions->setText(""); 1575 wpsRunning = false; 1576 bssFromScan = ""; 1577 wpsApPinEdit->setEnabled(false); 1578 wpsApPinButton->setEnabled(false); 1579} 1580 1581 1582#ifdef CONFIG_NATIVE_WINDOWS 1583 1584#ifndef WPASVC_NAME 1585#define WPASVC_NAME TEXT("wpasvc") 1586#endif 1587 1588class ErrorMsg : public QMessageBox { 1589public: 1590 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError()); 1591 void showMsg(QString msg); 1592private: 1593 DWORD err; 1594}; 1595 1596ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) : 1597 QMessageBox(parent), err(last_err) 1598{ 1599 setWindowTitle(tr("wpa_gui error")); 1600 setIcon(QMessageBox::Warning); 1601} 1602 1603void ErrorMsg::showMsg(QString msg) 1604{ 1605 LPTSTR buf; 1606 1607 setText(msg); 1608 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 1609 FORMAT_MESSAGE_FROM_SYSTEM, 1610 NULL, err, 0, (LPTSTR) (void *) &buf, 1611 0, NULL) > 0) { 1612 QString msg = QString::fromWCharArray(buf); 1613 setInformativeText(QString("[%1] %2").arg(err).arg(msg)); 1614 LocalFree(buf); 1615 } else { 1616 setInformativeText(QString("[%1]").arg(err)); 1617 } 1618 1619 exec(); 1620} 1621 1622 1623void WpaGui::startService() 1624{ 1625 SC_HANDLE svc, scm; 1626 1627 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT); 1628 if (!scm) { 1629 ErrorMsg(this).showMsg(tr("OpenSCManager failed")); 1630 return; 1631 } 1632 1633 svc = OpenService(scm, WPASVC_NAME, SERVICE_START); 1634 if (!svc) { 1635 ErrorMsg(this).showMsg(tr("OpenService failed")); 1636 CloseServiceHandle(scm); 1637 return; 1638 } 1639 1640 if (!StartService(svc, 0, NULL)) { 1641 ErrorMsg(this).showMsg(tr("Failed to start wpa_supplicant " 1642 "service")); 1643 } 1644 1645 CloseServiceHandle(svc); 1646 CloseServiceHandle(scm); 1647} 1648 1649 1650void WpaGui::stopService() 1651{ 1652 SC_HANDLE svc, scm; 1653 SERVICE_STATUS status; 1654 1655 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT); 1656 if (!scm) { 1657 ErrorMsg(this).showMsg(tr("OpenSCManager failed")); 1658 return; 1659 } 1660 1661 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP); 1662 if (!svc) { 1663 ErrorMsg(this).showMsg(tr("OpenService failed")); 1664 CloseServiceHandle(scm); 1665 return; 1666 } 1667 1668 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) { 1669 ErrorMsg(this).showMsg(tr("Failed to stop wpa_supplicant " 1670 "service")); 1671 } 1672 1673 CloseServiceHandle(svc); 1674 CloseServiceHandle(scm); 1675} 1676 1677 1678bool WpaGui::serviceRunning() 1679{ 1680 SC_HANDLE svc, scm; 1681 SERVICE_STATUS status; 1682 bool running = false; 1683 1684 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT); 1685 if (!scm) { 1686 printf("OpenSCManager failed: %d\n", (int) GetLastError()); 1687 return false; 1688 } 1689 1690 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS); 1691 if (!svc) { 1692 printf("OpenService failed: %d\n\n", (int) GetLastError()); 1693 CloseServiceHandle(scm); 1694 return false; 1695 } 1696 1697 if (QueryServiceStatus(svc, &status)) { 1698 if (status.dwCurrentState != SERVICE_STOPPED) 1699 running = true; 1700 } 1701 1702 CloseServiceHandle(svc); 1703 CloseServiceHandle(scm); 1704 1705 return running; 1706} 1707 1708#endif /* CONFIG_NATIVE_WINDOWS */ 1709 1710 1711void WpaGui::addInterface() 1712{ 1713 if (add_iface) { 1714 add_iface->close(); 1715 delete add_iface; 1716 } 1717 add_iface = new AddInterface(this, this); 1718 add_iface->show(); 1719 add_iface->exec(); 1720} 1721 1722 1723#ifndef QT_NO_SESSIONMANAGER 1724void WpaGui::saveState() 1725{ 1726 QSettings settings("wpa_supplicant", "wpa_gui"); 1727 settings.beginGroup("state"); 1728 settings.setValue("session_id", app->sessionId()); 1729 settings.setValue("in_tray", inTray); 1730 settings.endGroup(); 1731} 1732#endif 1733