2 * wpa_gui - WpaGui class
3 * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
16 /* Need to get getopt() */
20 #ifdef CONFIG_NATIVE_WINDOWS
22 #endif /* CONFIG_NATIVE_WINDOWS */
25 #include <QMessageBox>
26 #include <QCloseEvent>
27 #include <QImageReader>
32 #include "userdatarequest.h"
33 #include "networkconfig.h"
37 #define printf wpagui_printf
38 static int wpagui_printf(const char *, ...)
44 WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags)
49 #ifdef CONFIG_NATIVE_WINDOWS
50 fileStopServiceAction = new QAction(this);
51 fileStopServiceAction->setObjectName("Stop Service");
52 fileStopServiceAction->setIconText("Stop Service");
53 fileMenu->insertAction(actionWPS, fileStopServiceAction);
55 fileStartServiceAction = new QAction(this);
56 fileStartServiceAction->setObjectName("Start Service");
57 fileStartServiceAction->setIconText("Start Service");
58 fileMenu->insertAction(fileStopServiceAction, fileStartServiceAction);
60 connect(fileStartServiceAction, SIGNAL(triggered()), this,
61 SLOT(startService()));
62 connect(fileStopServiceAction, SIGNAL(triggered()), this,
64 #endif /* CONFIG_NATIVE_WINDOWS */
68 connect(fileEventHistoryAction, SIGNAL(triggered()), this,
69 SLOT(eventHistory()));
70 connect(fileSaveConfigAction, SIGNAL(triggered()), this,
72 connect(actionWPS, SIGNAL(triggered()), this, SLOT(wpsDialog()));
73 connect(fileExitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
74 connect(networkAddAction, SIGNAL(triggered()), this,
76 connect(networkEditAction, SIGNAL(triggered()), this,
77 SLOT(editSelectedNetwork()));
78 connect(networkRemoveAction, SIGNAL(triggered()), this,
79 SLOT(removeSelectedNetwork()));
80 connect(networkEnableAllAction, SIGNAL(triggered()), this,
81 SLOT(enableAllNetworks()));
82 connect(networkDisableAllAction, SIGNAL(triggered()), this,
83 SLOT(disableAllNetworks()));
84 connect(networkRemoveAllAction, SIGNAL(triggered()), this,
85 SLOT(removeAllNetworks()));
86 connect(helpIndexAction, SIGNAL(triggered()), this, SLOT(helpIndex()));
87 connect(helpContentsAction, SIGNAL(triggered()), this,
88 SLOT(helpContents()));
89 connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(helpAbout()));
90 connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));
91 connect(scanButton, SIGNAL(clicked()), this, SLOT(scan()));
92 connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB()));
93 connect(adapterSelect, SIGNAL(activated(const QString&)), this,
94 SLOT(selectAdapter(const QString&)));
95 connect(networkSelect, SIGNAL(activated(const QString&)), this,
96 SLOT(selectNetwork(const QString&)));
97 connect(addNetworkButton, SIGNAL(clicked()), this, SLOT(addNetwork()));
98 connect(editNetworkButton, SIGNAL(clicked()), this,
99 SLOT(editListedNetwork()));
100 connect(removeNetworkButton, SIGNAL(clicked()), this,
101 SLOT(removeListedNetwork()));
102 connect(networkList, SIGNAL(itemSelectionChanged()), this,
103 SLOT(updateNetworkDisabledStatus()));
104 connect(enableRadioButton, SIGNAL(toggled(bool)), this,
105 SLOT(enableListedNetwork(bool)));
106 connect(disableRadioButton, SIGNAL(toggled(bool)), this,
107 SLOT(disableListedNetwork(bool)));
108 connect(scanNetworkButton, SIGNAL(clicked()), this, SLOT(scan()));
109 connect(networkList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
110 this, SLOT(editListedNetwork()));
111 connect(wpaguiTab, SIGNAL(currentChanged(int)), this,
112 SLOT(tabChanged(int)));
113 connect(wpsPbcButton, SIGNAL(clicked()), this, SLOT(wpsPbc()));
114 connect(wpsPinButton, SIGNAL(clicked()), this, SLOT(wpsGeneratePin()));
115 connect(wpsApPinEdit, SIGNAL(textChanged(const QString &)), this,
116 SLOT(wpsApPinChanged(const QString &)));
117 connect(wpsApPinButton, SIGNAL(clicked()), this, SLOT(wpsApPin()));
128 ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
132 if (QSystemTrayIcon::isSystemTrayAvailable())
133 createTrayIcon(startInTray);
137 textStatus->setText("connecting to wpa_supplicant");
138 timer = new QTimer(this);
139 connect(timer, SIGNAL(timeout()), SLOT(ping()));
140 timer->setSingleShot(FALSE);
143 if (openCtrlConnection(ctrl_iface) < 0) {
144 printf("Failed to open control connection to "
145 "wpa_supplicant.\n");
149 networkMayHaveChanged = true;
159 wpa_ctrl_detach(monitor_conn);
160 wpa_ctrl_close(monitor_conn);
164 wpa_ctrl_close(ctrl_conn);
189 free(ctrl_iface_dir);
190 ctrl_iface_dir = NULL;
194 void WpaGui::languageChange()
200 void WpaGui::parse_argv()
204 c = getopt(qApp->argc(), qApp->argv(), "i:p:t");
210 ctrl_iface = strdup(optarg);
213 free(ctrl_iface_dir);
214 ctrl_iface_dir = strdup(optarg);
224 int WpaGui::openCtrlConnection(const char *ifname)
228 char buf[2048], *pos, *pos2;
232 if (ifname != ctrl_iface) {
234 ctrl_iface = strdup(ifname);
237 #ifdef CONFIG_CTRL_IFACE_UDP
239 ctrl_iface = strdup("udp");
240 #endif /* CONFIG_CTRL_IFACE_UDP */
241 #ifdef CONFIG_CTRL_IFACE_UNIX
243 DIR *dir = opendir(ctrl_iface_dir);
247 while ((dent = readdir(dir))) {
248 #ifdef _DIRENT_HAVE_D_TYPE
249 /* Skip the file if it is not a socket.
250 * Also accept DT_UNKNOWN (0) in case
251 * the C library or underlying file
252 * system does not support d_type. */
253 if (dent->d_type != DT_SOCK &&
254 dent->d_type != DT_UNKNOWN)
256 #endif /* _DIRENT_HAVE_D_TYPE */
258 if (strcmp(dent->d_name, ".") == 0 ||
259 strcmp(dent->d_name, "..") == 0)
261 printf("Selected interface '%s'\n",
263 ctrl_iface = strdup(dent->d_name);
268 #endif /* CONFIG_CTRL_IFACE_UNIX */
269 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
270 struct wpa_ctrl *ctrl;
276 ctrl = wpa_ctrl_open(NULL);
278 len = sizeof(buf) - 1;
279 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf,
283 pos = strchr(buf, '\n');
286 ctrl_iface = strdup(buf);
288 wpa_ctrl_close(ctrl);
290 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
293 if (ctrl_iface == NULL) {
294 #ifdef CONFIG_NATIVE_WINDOWS
295 static bool first = true;
296 if (first && !serviceRunning()) {
298 if (QMessageBox::warning(
300 "wpa_supplicant service is not running.\n"
301 "Do you want to start it?",
302 QMessageBox::Yes | QMessageBox::No) ==
306 #endif /* CONFIG_NATIVE_WINDOWS */
310 #ifdef CONFIG_CTRL_IFACE_UNIX
311 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
312 cfile = (char *) malloc(flen);
315 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
316 #else /* CONFIG_CTRL_IFACE_UNIX */
317 flen = strlen(ctrl_iface) + 1;
318 cfile = (char *) malloc(flen);
321 snprintf(cfile, flen, "%s", ctrl_iface);
322 #endif /* CONFIG_CTRL_IFACE_UNIX */
325 wpa_ctrl_close(ctrl_conn);
332 wpa_ctrl_detach(monitor_conn);
333 wpa_ctrl_close(monitor_conn);
337 printf("Trying to connect to '%s'\n", cfile);
338 ctrl_conn = wpa_ctrl_open(cfile);
339 if (ctrl_conn == NULL) {
343 monitor_conn = wpa_ctrl_open(cfile);
345 if (monitor_conn == NULL) {
346 wpa_ctrl_close(ctrl_conn);
349 if (wpa_ctrl_attach(monitor_conn)) {
350 printf("Failed to attach to wpa_supplicant\n");
351 wpa_ctrl_close(monitor_conn);
353 wpa_ctrl_close(ctrl_conn);
358 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
359 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
360 QSocketNotifier::Read, this);
361 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
364 adapterSelect->clear();
365 adapterSelect->addItem(ctrl_iface);
366 adapterSelect->setCurrentIndex(0);
368 len = sizeof(buf) - 1;
369 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
374 pos2 = strchr(pos, '\n');
377 if (strcmp(pos, ctrl_iface) != 0)
378 adapterSelect->addItem(pos);
386 len = sizeof(buf) - 1;
387 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len,
392 QStringList types = res.split(QChar(' '));
393 actionWPS->setEnabled(types.contains("WSC"));
400 static void wpa_gui_msg_cb(char *msg, size_t)
402 /* This should not happen anymore since two control connections are
404 printf("missed message: %s\n", msg);
408 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
412 if (ctrl_conn == NULL)
414 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen,
417 printf("'%s' command timed out.\n", cmd);
419 printf("'%s' command failed.\n", cmd);
425 void WpaGui::updateStatus()
427 char buf[2048], *start, *end, *pos;
430 pingsToStatusUpdate = 10;
432 len = sizeof(buf) - 1;
433 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
434 textStatus->setText("Could not get status from "
436 textAuthentication->clear();
437 textEncryption->clear();
440 textIpAddress->clear();
446 bool auth_updated = false, ssid_updated = false;
447 bool bssid_updated = false, ipaddr_updated = false;
448 bool status_updated = false;
449 char *pairwise_cipher = NULL, *group_cipher = NULL;
454 end = strchr(start, '\n');
458 while (end[0] && end[1])
463 pos = strchr(start, '=');
466 if (strcmp(start, "bssid") == 0) {
467 bssid_updated = true;
468 textBssid->setText(pos);
469 } else if (strcmp(start, "ssid") == 0) {
471 textSsid->setText(pos);
472 } else if (strcmp(start, "ip_address") == 0) {
473 ipaddr_updated = true;
474 textIpAddress->setText(pos);
475 } else if (strcmp(start, "wpa_state") == 0) {
476 status_updated = true;
477 textStatus->setText(pos);
478 } else if (strcmp(start, "key_mgmt") == 0) {
480 textAuthentication->setText(pos);
481 /* TODO: could add EAP status to this */
482 } else if (strcmp(start, "pairwise_cipher") == 0) {
483 pairwise_cipher = pos;
484 } else if (strcmp(start, "group_cipher") == 0) {
494 if (pairwise_cipher || group_cipher) {
496 if (pairwise_cipher && group_cipher &&
497 strcmp(pairwise_cipher, group_cipher) != 0) {
498 encr.append(pairwise_cipher);
500 encr.append(group_cipher);
501 } else if (pairwise_cipher) {
502 encr.append(pairwise_cipher);
504 encr.append(group_cipher);
505 encr.append(" [group key only]");
507 textEncryption->setText(encr);
509 textEncryption->clear();
514 textAuthentication->clear();
520 textIpAddress->clear();
524 void WpaGui::updateNetworks()
526 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
528 int first_active = -1;
529 int was_selected = -1;
530 bool current = false;
532 if (!networkMayHaveChanged)
535 if (networkList->currentRow() >= 0)
536 was_selected = networkList->currentRow();
538 networkSelect->clear();
539 networkList->clear();
541 if (ctrl_conn == NULL)
544 len = sizeof(buf) - 1;
545 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
549 start = strchr(buf, '\n');
556 end = strchr(start, '\n');
560 while (end[0] && end[1])
566 ssid = strchr(id, '\t');
570 bssid = strchr(ssid, '\t');
574 flags = strchr(bssid, '\t');
580 network.append(": ");
581 network.append(ssid);
582 networkSelect->addItem(network);
583 networkList->addItem(network);
585 if (strstr(flags, "[CURRENT]")) {
586 networkSelect->setCurrentIndex(networkSelect->count() -
589 } else if (first_active < 0 &&
590 strstr(flags, "[DISABLED]") == NULL)
591 first_active = networkSelect->count() - 1;
598 if (networkSelect->count() > 1)
599 networkSelect->addItem("Select any network");
601 if (!current && first_active >= 0)
602 networkSelect->setCurrentIndex(first_active);
604 if (was_selected >= 0 && networkList->count() > 0) {
605 if (was_selected < networkList->count())
606 networkList->setCurrentRow(was_selected);
608 networkList->setCurrentRow(networkList->count() - 1);
611 networkList->setCurrentRow(networkSelect->currentIndex());
613 networkMayHaveChanged = false;
617 void WpaGui::helpIndex()
619 printf("helpIndex\n");
623 void WpaGui::helpContents()
625 printf("helpContents\n");
629 void WpaGui::helpAbout()
631 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
632 "Copyright (c) 2003-2008,\n"
633 "Jouni Malinen <j@w1.fi>\n"
634 "and contributors.\n"
636 "This program is free software. You can\n"
637 "distribute it and/or modify it under the terms "
639 "the GNU General Public License version 2.\n"
641 "Alternatively, this software may be distributed\n"
642 "under the terms of the BSD license.\n"
644 "This product includes software developed\n"
645 "by the OpenSSL Project for use in the\n"
646 "OpenSSL Toolkit (http://www.openssl.org/)\n");
650 void WpaGui::disconnect()
653 size_t reply_len = sizeof(reply);
654 ctrlRequest("DISCONNECT", reply, &reply_len);
666 scanres = new ScanResults();
669 scanres->setWpaGui(this);
675 void WpaGui::eventHistory()
682 eh = new EventHistory();
696 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
698 * QSocketNotifier cannot be used with Windows named pipes, so use a
699 * timer to check for received messages for now. This could be
700 * optimized be doing something specific to named pipes or Windows
701 * events, but it is not clear what would be the best way of doing that
705 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
707 if (scanres && !scanres->isVisible()) {
712 if (eh && !eh->isVisible()) {
717 if (udr && !udr->isVisible()) {
722 len = sizeof(buf) - 1;
723 if (ctrlRequest("PING", buf, &len) < 0) {
724 printf("PING failed - trying to reconnect\n");
725 if (openCtrlConnection(ctrl_iface) >= 0) {
726 printf("Reconnected successfully\n");
727 pingsToStatusUpdate = 0;
731 pingsToStatusUpdate--;
732 if (pingsToStatusUpdate <= 0) {
737 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
738 /* Use less frequent pings and status updates when the main window is
739 * hidden (running in taskbar). */
740 int interval = isHidden() ? 5000 : 1000;
741 if (timer->interval() != interval)
742 timer->setInterval(interval);
743 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
747 static int str_match(const char *a, const char *b)
749 return strncmp(a, b, strlen(b)) == 0;
753 void WpaGui::processMsg(char *msg)
755 char *pos = msg, *pos2;
761 priority = atoi(pos);
762 pos = strchr(pos, '>');
769 WpaMsg wm(pos, priority);
773 while (msgs.count() > 100)
776 /* Update last message with truncated version of the event */
777 if (strncmp(pos, "CTRL-", 5) == 0) {
778 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
785 QString lastmsg = pos2;
786 lastmsg.truncate(40);
787 textLastMessage->setText(lastmsg);
789 pingsToStatusUpdate = 0;
790 networkMayHaveChanged = true;
792 if (str_match(pos, WPA_CTRL_REQ))
793 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
794 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
795 scanres->updateResults();
796 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
797 showTrayMessage(QSystemTrayIcon::Information, 3,
798 "Disconnected from network.");
799 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
800 showTrayMessage(QSystemTrayIcon::Information, 3,
801 "Connection to network established.");
802 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
804 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
805 showTrayMessage(QSystemTrayIcon::Information, 3,
806 "Wi-Fi Protected Setup (WPS) AP\n"
807 "in active PBC mode found.");
808 wpsStatusText->setText("WPS AP in active PBC mode found");
809 wpaguiTab->setCurrentWidget(wpsTab);
810 wpsInstructions->setText("Press the PBC button on the screen "
811 "to start registration");
812 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
813 showTrayMessage(QSystemTrayIcon::Information, 3,
814 "Wi-Fi Protected Setup (WPS) AP\n"
815 " in active PIN mode found.");
816 wpsStatusText->setText("WPS AP with recently selected "
818 wpaguiTab->setCurrentWidget(wpsTab);
819 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
820 showTrayMessage(QSystemTrayIcon::Information, 3,
821 "Wi-Fi Protected Setup (WPS)\n"
823 wpsStatusText->setText("WPS AP detected");
824 wpaguiTab->setCurrentWidget(wpsTab);
825 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
826 showTrayMessage(QSystemTrayIcon::Information, 3,
827 "Wi-Fi Protected Setup (WPS)\n"
828 "PBC mode overlap detected.");
829 wpsStatusText->setText("PBC mode overlap detected");
830 wpsInstructions->setText("More than one AP is currently in "
831 "active WPS PBC mode. Wait couple of "
832 "minutes and try again");
833 wpaguiTab->setCurrentWidget(wpsTab);
834 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
835 wpsStatusText->setText("Network configuration received");
836 wpaguiTab->setCurrentWidget(wpsTab);
837 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
838 if (strstr(pos, "(WSC)"))
839 wpsStatusText->setText("Registration started");
840 } else if (str_match(pos, WPS_EVENT_M2D)) {
841 wpsStatusText->setText("Registrar does not yet know PIN");
842 } else if (str_match(pos, WPS_EVENT_FAIL)) {
843 wpsStatusText->setText("Registration failed");
844 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
845 wpsStatusText->setText("Registration succeeded");
850 void WpaGui::processCtrlReq(const char *req)
856 udr = new UserDataRequest();
859 if (udr->setParams(this, req) < 0) {
869 void WpaGui::receiveMsgs()
874 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
875 len = sizeof(buf) - 1;
876 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
884 void WpaGui::connectB()
887 size_t reply_len = sizeof(reply);
888 ctrlRequest("REASSOCIATE", reply, &reply_len);
892 void WpaGui::selectNetwork( const QString &sel )
896 size_t reply_len = sizeof(reply);
898 if (cmd.startsWith("Select any")) {
901 int pos = cmd.indexOf(':');
903 printf("Invalid selectNetwork '%s'\n",
904 cmd.toAscii().constData());
909 cmd.prepend("SELECT_NETWORK ");
910 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
916 void WpaGui::enableNetwork(const QString &sel)
920 size_t reply_len = sizeof(reply);
922 if (!cmd.startsWith("all")) {
923 int pos = cmd.indexOf(':');
925 printf("Invalid enableNetwork '%s'\n",
926 cmd.toAscii().constData());
931 cmd.prepend("ENABLE_NETWORK ");
932 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
937 void WpaGui::disableNetwork(const QString &sel)
941 size_t reply_len = sizeof(reply);
943 if (!cmd.startsWith("all")) {
944 int pos = cmd.indexOf(':');
946 printf("Invalid disableNetwork '%s'\n",
947 cmd.toAscii().constData());
952 cmd.prepend("DISABLE_NETWORK ");
953 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
958 void WpaGui::editNetwork(const QString &sel)
963 if (!cmd.startsWith("Select any")) {
964 int pos = sel.indexOf(':');
966 printf("Invalid editNetwork '%s'\n",
967 cmd.toAscii().constData());
974 NetworkConfig *nc = new NetworkConfig();
980 nc->paramsFromConfig(id);
989 void WpaGui::editSelectedNetwork()
991 if (networkSelect->count() < 1) {
992 QMessageBox::information(this, "No Networks",
993 "There are no networks to edit.\n");
996 QString sel(networkSelect->currentText());
1001 void WpaGui::editListedNetwork()
1003 if (networkList->currentRow() < 0) {
1004 QMessageBox::information(this, "Select A Network",
1005 "Select a network from the list to"
1009 QString sel(networkList->currentItem()->text());
1014 void WpaGui::triggerUpdate()
1017 networkMayHaveChanged = true;
1022 void WpaGui::addNetwork()
1024 NetworkConfig *nc = new NetworkConfig();
1027 nc->setWpaGui(this);
1034 void WpaGui::removeNetwork(const QString &sel)
1038 size_t reply_len = sizeof(reply);
1040 if (cmd.startsWith("Select any"))
1043 if (!cmd.startsWith("all")) {
1044 int pos = cmd.indexOf(':');
1046 printf("Invalid removeNetwork '%s'\n",
1047 cmd.toAscii().constData());
1052 cmd.prepend("REMOVE_NETWORK ");
1053 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1058 void WpaGui::removeSelectedNetwork()
1060 if (networkSelect->count() < 1) {
1061 QMessageBox::information(this, "No Networks",
1062 "There are no networks to remove.\n");
1065 QString sel(networkSelect->currentText());
1070 void WpaGui::removeListedNetwork()
1072 if (networkList->currentRow() < 0) {
1073 QMessageBox::information(this, "Select A Network",
1074 "Select a network from the list to"
1078 QString sel(networkList->currentItem()->text());
1083 void WpaGui::enableAllNetworks()
1090 void WpaGui::disableAllNetworks()
1093 disableNetwork(sel);
1097 void WpaGui::removeAllNetworks()
1104 int WpaGui::getNetworkDisabled(const QString &sel)
1108 size_t reply_len = sizeof(reply) - 1;
1109 int pos = cmd.indexOf(':');
1111 printf("Invalid getNetworkDisabled '%s'\n",
1112 cmd.toAscii().constData());
1116 cmd.prepend("GET_NETWORK ");
1117 cmd.append(" disabled");
1119 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1120 && reply_len >= 1) {
1121 reply[reply_len] = '\0';
1122 if (!str_match(reply, "FAIL"))
1130 void WpaGui::updateNetworkDisabledStatus()
1132 if (networkList->currentRow() < 0)
1135 QString sel(networkList->currentItem()->text());
1137 switch (getNetworkDisabled(sel)) {
1139 if (!enableRadioButton->isChecked())
1140 enableRadioButton->setChecked(true);
1143 if (!disableRadioButton->isChecked())
1144 disableRadioButton->setChecked(true);
1150 void WpaGui::enableListedNetwork(bool enabled)
1152 if (networkList->currentRow() < 0 || !enabled)
1155 QString sel(networkList->currentItem()->text());
1157 if (getNetworkDisabled(sel) == 1)
1162 void WpaGui::disableListedNetwork(bool disabled)
1164 if (networkList->currentRow() < 0 || !disabled)
1167 QString sel(networkList->currentItem()->text());
1169 if (getNetworkDisabled(sel) == 0)
1170 disableNetwork(sel);
1174 void WpaGui::saveConfig()
1179 len = sizeof(buf) - 1;
1180 ctrlRequest("SAVE_CONFIG", buf, &len);
1184 if (str_match(buf, "FAIL"))
1185 QMessageBox::warning(this, "Failed to save configuration",
1186 "The configuration could not be saved.\n"
1188 "The update_config=1 configuration option\n"
1189 "must be used for configuration saving to\n"
1192 QMessageBox::information(this, "Saved configuration",
1193 "The current configuration was saved."
1198 void WpaGui::selectAdapter( const QString & sel )
1200 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1201 printf("Failed to open control connection to "
1202 "wpa_supplicant.\n");
1208 void WpaGui::createTrayIcon(bool trayOnly)
1210 QApplication::setQuitOnLastWindowClosed(false);
1212 tray_icon = new QSystemTrayIcon(this);
1213 tray_icon->setToolTip(qAppName() + " - wpa_supplicant user interface");
1214 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1215 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1217 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1220 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1221 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1223 ackTrayIcon = false;
1225 tray_menu = new QMenu(this);
1227 disconnectAction = new QAction("&Disconnect", this);
1228 reconnectAction = new QAction("Re&connect", this);
1229 connect(disconnectAction, SIGNAL(triggered()), this,
1230 SLOT(disconnect()));
1231 connect(reconnectAction, SIGNAL(triggered()), this,
1233 tray_menu->addAction(disconnectAction);
1234 tray_menu->addAction(reconnectAction);
1235 tray_menu->addSeparator();
1237 eventAction = new QAction("&Event History", this);
1238 scanAction = new QAction("Scan &Results", this);
1239 statAction = new QAction("S&tatus", this);
1240 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1241 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1242 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1243 tray_menu->addAction(eventAction);
1244 tray_menu->addAction(scanAction);
1245 tray_menu->addAction(statAction);
1246 tray_menu->addSeparator();
1248 showAction = new QAction("&Show Window", this);
1249 hideAction = new QAction("&Hide Window", this);
1250 quitAction = new QAction("&Quit", this);
1251 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1252 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1253 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1254 tray_menu->addAction(showAction);
1255 tray_menu->addAction(hideAction);
1256 tray_menu->addSeparator();
1257 tray_menu->addAction(quitAction);
1259 tray_icon->setContextMenu(tray_menu);
1268 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1269 const QString & msg)
1271 if (!QSystemTrayIcon::supportsMessages())
1274 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1277 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1281 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1284 /* use close() here instead of hide() and allow the
1285 * custom closeEvent handler take care of children */
1286 case QSystemTrayIcon::Trigger:
1293 case QSystemTrayIcon::MiddleClick:
1302 void WpaGui::showTrayStatus()
1307 len = sizeof(buf) - 1;
1308 if (ctrlRequest("STATUS", buf, &len) < 0)
1312 QString msg, status(buf);
1314 QStringList lines = status.split(QRegExp("\\n"));
1315 for (QStringList::Iterator it = lines.begin();
1316 it != lines.end(); it++) {
1317 int pos = (*it).indexOf('=') + 1;
1321 if ((*it).startsWith("bssid="))
1322 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1323 else if ((*it).startsWith("ssid="))
1324 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1325 else if ((*it).startsWith("pairwise_cipher="))
1326 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1327 else if ((*it).startsWith("group_cipher="))
1328 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1329 else if ((*it).startsWith("key_mgmt="))
1330 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1331 else if ((*it).startsWith("wpa_state="))
1332 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1333 else if ((*it).startsWith("ip_address="))
1334 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1335 else if ((*it).startsWith("Supplicant PAE state="))
1336 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1337 else if ((*it).startsWith("EAP state="))
1338 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1342 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1346 void WpaGui::closeEvent(QCloseEvent *event)
1366 if (tray_icon && !ackTrayIcon) {
1367 /* give user a visual hint that the tray icon exists */
1368 if (QSystemTrayIcon::supportsMessages()) {
1370 showTrayMessage(QSystemTrayIcon::Information, 3,
1371 qAppName() + " will keep running in "
1372 "the system tray.");
1374 QMessageBox::information(this, qAppName() + " systray",
1375 "The program will keep "
1376 "running in the system "
1386 void WpaGui::wpsDialog()
1388 wpaguiTab->setCurrentWidget(wpsTab);
1392 void WpaGui::tabChanged(int index)
1400 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1401 if (bssFromScan.isEmpty())
1402 wpsApPinButton->setEnabled(false);
1406 void WpaGui::wpsPbc()
1409 size_t reply_len = sizeof(reply);
1411 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1414 wpsPinEdit->setEnabled(false);
1415 if (wpsStatusText->text().compare("WPS AP in active PBC mode found")) {
1416 wpsInstructions->setText("Press the push button on the AP to "
1417 "start the PBC mode.");
1419 wpsInstructions->setText("If you have not yet done so, press "
1420 "the push button on the AP to start "
1423 wpsStatusText->setText("Waiting for Registrar");
1428 void WpaGui::wpsGeneratePin()
1431 size_t reply_len = sizeof(reply) - 1;
1433 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1436 reply[reply_len] = '\0';
1438 wpsPinEdit->setText(reply);
1439 wpsPinEdit->setEnabled(true);
1440 wpsInstructions->setText("Enter the generated PIN into the Registrar "
1441 "(either the internal one in the AP or an "
1443 wpsStatusText->setText("Waiting for Registrar");
1448 void WpaGui::setBssFromScan(const QString &bssid)
1450 bssFromScan = bssid;
1451 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1452 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1453 wpsStatusText->setText("WPS AP selected from scan results");
1454 wpsInstructions->setText("If you want to use an AP device PIN, e.g., "
1455 "from a label in the device, enter the eight "
1456 "digit AP PIN and click Use AP PIN button.");
1460 void WpaGui::wpsApPinChanged(const QString &text)
1462 wpsApPinButton->setEnabled(text.length() == 8);
1466 void WpaGui::wpsApPin()
1469 size_t reply_len = sizeof(reply);
1471 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1472 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1475 wpsStatusText->setText("Waiting for AP/Enrollee");
1480 void WpaGui::stopWpsRun(bool success)
1483 wpsStatusText->setText(success ? "Connected to the network" :
1486 wpsStatusText->setText("");
1487 wpsPinEdit->setEnabled(false);
1488 wpsInstructions->setText("");
1491 wpsApPinEdit->setEnabled(false);
1492 wpsApPinButton->setEnabled(false);
1496 #ifdef CONFIG_NATIVE_WINDOWS
1499 #define WPASVC_NAME TEXT("wpasvc")
1502 class ErrorMsg : public QMessageBox {
1504 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1505 void showMsg(QString msg);
1510 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1511 QMessageBox(parent), err(last_err)
1513 setWindowTitle("wpa_gui error");
1514 setIcon(QMessageBox::Warning);
1517 void ErrorMsg::showMsg(QString msg)
1522 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1523 FORMAT_MESSAGE_FROM_SYSTEM,
1524 NULL, err, 0, (LPTSTR) (void *) &buf,
1526 QString msg = QString::fromWCharArray(buf);
1527 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1530 setInformativeText(QString("[%1]").arg(err));
1537 void WpaGui::startService()
1541 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1543 ErrorMsg(this).showMsg("OpenSCManager failed");
1547 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1549 ErrorMsg(this).showMsg("OpenService failed");
1550 CloseServiceHandle(scm);
1554 if (!StartService(svc, 0, NULL)) {
1555 ErrorMsg(this).showMsg("Failed to start wpa_supplicant "
1559 CloseServiceHandle(svc);
1560 CloseServiceHandle(scm);
1564 void WpaGui::stopService()
1567 SERVICE_STATUS status;
1569 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1571 ErrorMsg(this).showMsg("OpenSCManager failed");
1575 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1577 ErrorMsg(this).showMsg("OpenService failed");
1578 CloseServiceHandle(scm);
1582 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1583 ErrorMsg(this).showMsg("Failed to stop wpa_supplicant "
1587 CloseServiceHandle(svc);
1588 CloseServiceHandle(scm);
1592 bool WpaGui::serviceRunning()
1595 SERVICE_STATUS status;
1596 bool running = false;
1598 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1600 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1604 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1606 printf("OpenService failed: %d\n\n", (int) GetLastError());
1607 CloseServiceHandle(scm);
1611 if (QueryServiceStatus(svc, &status)) {
1612 if (status.dwCurrentState != SERVICE_STOPPED)
1616 CloseServiceHandle(svc);
1617 CloseServiceHandle(scm);
1622 #endif /* CONFIG_NATIVE_WINDOWS */