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