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() */
21 #include <QMessageBox>
22 #include <QCloseEvent>
23 #include <QImageReader>
28 #include "userdatarequest.h"
29 #include "networkconfig.h"
33 #define printf wpagui_printf
34 static int wpagui_printf(const char *, ...)
40 WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags)
47 connect(fileEventHistoryAction, SIGNAL(triggered()), this,
48 SLOT(eventHistory()));
49 connect(fileSaveConfigAction, SIGNAL(triggered()), this,
51 connect(actionWPS, SIGNAL(triggered()), this, SLOT(wpsDialog()));
52 connect(fileExitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
53 connect(networkAddAction, SIGNAL(triggered()), this,
55 connect(networkEditAction, SIGNAL(triggered()), this,
56 SLOT(editSelectedNetwork()));
57 connect(networkRemoveAction, SIGNAL(triggered()), this,
58 SLOT(removeSelectedNetwork()));
59 connect(networkEnableAllAction, SIGNAL(triggered()), this,
60 SLOT(enableAllNetworks()));
61 connect(networkDisableAllAction, SIGNAL(triggered()), this,
62 SLOT(disableAllNetworks()));
63 connect(networkRemoveAllAction, SIGNAL(triggered()), this,
64 SLOT(removeAllNetworks()));
65 connect(helpIndexAction, SIGNAL(triggered()), this, SLOT(helpIndex()));
66 connect(helpContentsAction, SIGNAL(triggered()), this,
67 SLOT(helpContents()));
68 connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(helpAbout()));
69 connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));
70 connect(scanButton, SIGNAL(clicked()), this, SLOT(scan()));
71 connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB()));
72 connect(adapterSelect, SIGNAL(activated(const QString&)), this,
73 SLOT(selectAdapter(const QString&)));
74 connect(networkSelect, SIGNAL(activated(const QString&)), this,
75 SLOT(selectNetwork(const QString&)));
76 connect(addNetworkButton, SIGNAL(clicked()), this, SLOT(addNetwork()));
77 connect(editNetworkButton, SIGNAL(clicked()), this,
78 SLOT(editListedNetwork()));
79 connect(removeNetworkButton, SIGNAL(clicked()), this,
80 SLOT(removeListedNetwork()));
81 connect(networkList, SIGNAL(itemSelectionChanged()), this,
82 SLOT(updateNetworkDisabledStatus()));
83 connect(enableRadioButton, SIGNAL(toggled(bool)), this,
84 SLOT(enableListedNetwork(bool)));
85 connect(disableRadioButton, SIGNAL(toggled(bool)), this,
86 SLOT(disableListedNetwork(bool)));
87 connect(scanNetworkButton, SIGNAL(clicked()), this, SLOT(scan()));
88 connect(networkList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
89 this, SLOT(editListedNetwork()));
90 connect(wpaguiTab, SIGNAL(currentChanged(int)), this,
91 SLOT(tabChanged(int)));
92 connect(wpsPbcButton, SIGNAL(clicked()), this, SLOT(wpsPbc()));
93 connect(wpsPinButton, SIGNAL(clicked()), this, SLOT(wpsGeneratePin()));
94 connect(wpsApPinEdit, SIGNAL(textChanged(const QString &)), this,
95 SLOT(wpsApPinChanged(const QString &)));
96 connect(wpsApPinButton, SIGNAL(clicked()), this, SLOT(wpsApPin()));
107 ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
111 if (QSystemTrayIcon::isSystemTrayAvailable())
112 createTrayIcon(startInTray);
116 textStatus->setText("connecting to wpa_supplicant");
117 timer = new QTimer(this);
118 connect(timer, SIGNAL(timeout()), SLOT(ping()));
119 timer->setSingleShot(FALSE);
122 if (openCtrlConnection(ctrl_iface) < 0) {
123 printf("Failed to open control connection to "
124 "wpa_supplicant.\n");
128 networkMayHaveChanged = true;
138 wpa_ctrl_detach(monitor_conn);
139 wpa_ctrl_close(monitor_conn);
143 wpa_ctrl_close(ctrl_conn);
168 free(ctrl_iface_dir);
169 ctrl_iface_dir = NULL;
173 void WpaGui::languageChange()
179 void WpaGui::parse_argv()
183 c = getopt(qApp->argc(), qApp->argv(), "i:p:t");
189 ctrl_iface = strdup(optarg);
192 free(ctrl_iface_dir);
193 ctrl_iface_dir = strdup(optarg);
203 int WpaGui::openCtrlConnection(const char *ifname)
207 char buf[2048], *pos, *pos2;
211 if (ifname != ctrl_iface) {
213 ctrl_iface = strdup(ifname);
216 #ifdef CONFIG_CTRL_IFACE_UDP
218 ctrl_iface = strdup("udp");
219 #endif /* CONFIG_CTRL_IFACE_UDP */
220 #ifdef CONFIG_CTRL_IFACE_UNIX
222 DIR *dir = opendir(ctrl_iface_dir);
226 while ((dent = readdir(dir))) {
227 #ifdef _DIRENT_HAVE_D_TYPE
228 /* Skip the file if it is not a socket.
229 * Also accept DT_UNKNOWN (0) in case
230 * the C library or underlying file
231 * system does not support d_type. */
232 if (dent->d_type != DT_SOCK &&
233 dent->d_type != DT_UNKNOWN)
235 #endif /* _DIRENT_HAVE_D_TYPE */
237 if (strcmp(dent->d_name, ".") == 0 ||
238 strcmp(dent->d_name, "..") == 0)
240 printf("Selected interface '%s'\n",
242 ctrl_iface = strdup(dent->d_name);
247 #endif /* CONFIG_CTRL_IFACE_UNIX */
248 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
249 struct wpa_ctrl *ctrl;
255 ctrl = wpa_ctrl_open(NULL);
257 len = sizeof(buf) - 1;
258 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf,
262 pos = strchr(buf, '\n');
265 ctrl_iface = strdup(buf);
267 wpa_ctrl_close(ctrl);
269 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
272 if (ctrl_iface == NULL)
275 #ifdef CONFIG_CTRL_IFACE_UNIX
276 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
277 cfile = (char *) malloc(flen);
280 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
281 #else /* CONFIG_CTRL_IFACE_UNIX */
282 flen = strlen(ctrl_iface) + 1;
283 cfile = (char *) malloc(flen);
286 snprintf(cfile, flen, "%s", ctrl_iface);
287 #endif /* CONFIG_CTRL_IFACE_UNIX */
290 wpa_ctrl_close(ctrl_conn);
297 wpa_ctrl_detach(monitor_conn);
298 wpa_ctrl_close(monitor_conn);
302 printf("Trying to connect to '%s'\n", cfile);
303 ctrl_conn = wpa_ctrl_open(cfile);
304 if (ctrl_conn == NULL) {
308 monitor_conn = wpa_ctrl_open(cfile);
310 if (monitor_conn == NULL) {
311 wpa_ctrl_close(ctrl_conn);
314 if (wpa_ctrl_attach(monitor_conn)) {
315 printf("Failed to attach to wpa_supplicant\n");
316 wpa_ctrl_close(monitor_conn);
318 wpa_ctrl_close(ctrl_conn);
323 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
324 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
325 QSocketNotifier::Read, this);
326 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
329 adapterSelect->clear();
330 adapterSelect->addItem(ctrl_iface);
331 adapterSelect->setCurrentIndex(0);
333 len = sizeof(buf) - 1;
334 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
339 pos2 = strchr(pos, '\n');
342 if (strcmp(pos, ctrl_iface) != 0)
343 adapterSelect->addItem(pos);
351 len = sizeof(buf) - 1;
352 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len,
357 QStringList types = res.split(QChar(' '));
358 actionWPS->setEnabled(types.contains("WSC"));
365 static void wpa_gui_msg_cb(char *msg, size_t)
367 /* This should not happen anymore since two control connections are
369 printf("missed message: %s\n", msg);
373 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
377 if (ctrl_conn == NULL)
379 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen,
382 printf("'%s' command timed out.\n", cmd);
384 printf("'%s' command failed.\n", cmd);
390 void WpaGui::updateStatus()
392 char buf[2048], *start, *end, *pos;
395 pingsToStatusUpdate = 10;
397 len = sizeof(buf) - 1;
398 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
399 textStatus->setText("Could not get status from "
401 textAuthentication->clear();
402 textEncryption->clear();
405 textIpAddress->clear();
411 bool auth_updated = false, ssid_updated = false;
412 bool bssid_updated = false, ipaddr_updated = false;
413 bool status_updated = false;
414 char *pairwise_cipher = NULL, *group_cipher = NULL;
419 end = strchr(start, '\n');
423 while (end[0] && end[1])
428 pos = strchr(start, '=');
431 if (strcmp(start, "bssid") == 0) {
432 bssid_updated = true;
433 textBssid->setText(pos);
434 } else if (strcmp(start, "ssid") == 0) {
436 textSsid->setText(pos);
437 } else if (strcmp(start, "ip_address") == 0) {
438 ipaddr_updated = true;
439 textIpAddress->setText(pos);
440 } else if (strcmp(start, "wpa_state") == 0) {
441 status_updated = true;
442 textStatus->setText(pos);
443 } else if (strcmp(start, "key_mgmt") == 0) {
445 textAuthentication->setText(pos);
446 /* TODO: could add EAP status to this */
447 } else if (strcmp(start, "pairwise_cipher") == 0) {
448 pairwise_cipher = pos;
449 } else if (strcmp(start, "group_cipher") == 0) {
459 if (pairwise_cipher || group_cipher) {
461 if (pairwise_cipher && group_cipher &&
462 strcmp(pairwise_cipher, group_cipher) != 0) {
463 encr.append(pairwise_cipher);
465 encr.append(group_cipher);
466 } else if (pairwise_cipher) {
467 encr.append(pairwise_cipher);
469 encr.append(group_cipher);
470 encr.append(" [group key only]");
472 textEncryption->setText(encr);
474 textEncryption->clear();
479 textAuthentication->clear();
485 textIpAddress->clear();
489 void WpaGui::updateNetworks()
491 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
493 int first_active = -1;
494 int was_selected = -1;
495 bool current = false;
497 if (!networkMayHaveChanged)
500 if (networkList->currentRow() >= 0)
501 was_selected = networkList->currentRow();
503 networkSelect->clear();
504 networkList->clear();
506 if (ctrl_conn == NULL)
509 len = sizeof(buf) - 1;
510 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
514 start = strchr(buf, '\n');
521 end = strchr(start, '\n');
525 while (end[0] && end[1])
531 ssid = strchr(id, '\t');
535 bssid = strchr(ssid, '\t');
539 flags = strchr(bssid, '\t');
545 network.append(": ");
546 network.append(ssid);
547 networkSelect->addItem(network);
548 networkList->addItem(network);
550 if (strstr(flags, "[CURRENT]")) {
551 networkSelect->setCurrentIndex(networkSelect->count() -
554 } else if (first_active < 0 &&
555 strstr(flags, "[DISABLED]") == NULL)
556 first_active = networkSelect->count() - 1;
563 if (networkSelect->count() > 1)
564 networkSelect->addItem("Select any network");
566 if (!current && first_active >= 0)
567 networkSelect->setCurrentIndex(first_active);
569 if (was_selected >= 0 && networkList->count() > 0) {
570 if (was_selected < networkList->count())
571 networkList->setCurrentRow(was_selected);
573 networkList->setCurrentRow(networkList->count() - 1);
576 networkList->setCurrentRow(networkSelect->currentIndex());
578 networkMayHaveChanged = false;
582 void WpaGui::helpIndex()
584 printf("helpIndex\n");
588 void WpaGui::helpContents()
590 printf("helpContents\n");
594 void WpaGui::helpAbout()
596 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
597 "Copyright (c) 2003-2008,\n"
598 "Jouni Malinen <j@w1.fi>\n"
599 "and contributors.\n"
601 "This program is free software. You can\n"
602 "distribute it and/or modify it under the terms "
604 "the GNU General Public License version 2.\n"
606 "Alternatively, this software may be distributed\n"
607 "under the terms of the BSD license.\n"
609 "This product includes software developed\n"
610 "by the OpenSSL Project for use in the\n"
611 "OpenSSL Toolkit (http://www.openssl.org/)\n");
615 void WpaGui::disconnect()
618 size_t reply_len = sizeof(reply);
619 ctrlRequest("DISCONNECT", reply, &reply_len);
631 scanres = new ScanResults();
634 scanres->setWpaGui(this);
640 void WpaGui::eventHistory()
647 eh = new EventHistory();
661 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
663 * QSocketNotifier cannot be used with Windows named pipes, so use a
664 * timer to check for received messages for now. This could be
665 * optimized be doing something specific to named pipes or Windows
666 * events, but it is not clear what would be the best way of doing that
670 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
672 if (scanres && !scanres->isVisible()) {
677 if (eh && !eh->isVisible()) {
682 if (udr && !udr->isVisible()) {
687 len = sizeof(buf) - 1;
688 if (ctrlRequest("PING", buf, &len) < 0) {
689 printf("PING failed - trying to reconnect\n");
690 if (openCtrlConnection(ctrl_iface) >= 0) {
691 printf("Reconnected successfully\n");
692 pingsToStatusUpdate = 0;
696 pingsToStatusUpdate--;
697 if (pingsToStatusUpdate <= 0) {
702 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
703 /* Use less frequent pings and status updates when the main window is
704 * hidden (running in taskbar). */
705 int interval = isHidden() ? 5000 : 1000;
706 if (timer->interval() != interval)
707 timer->setInterval(interval);
708 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
712 static int str_match(const char *a, const char *b)
714 return strncmp(a, b, strlen(b)) == 0;
718 void WpaGui::processMsg(char *msg)
720 char *pos = msg, *pos2;
726 priority = atoi(pos);
727 pos = strchr(pos, '>');
734 WpaMsg wm(pos, priority);
738 while (msgs.count() > 100)
741 /* Update last message with truncated version of the event */
742 if (strncmp(pos, "CTRL-", 5) == 0) {
743 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
750 QString lastmsg = pos2;
751 lastmsg.truncate(40);
752 textLastMessage->setText(lastmsg);
754 pingsToStatusUpdate = 0;
755 networkMayHaveChanged = true;
757 if (str_match(pos, WPA_CTRL_REQ))
758 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
759 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
760 scanres->updateResults();
761 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
762 showTrayMessage(QSystemTrayIcon::Information, 3,
763 "Disconnected from network.");
764 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
765 showTrayMessage(QSystemTrayIcon::Information, 3,
766 "Connection to network established.");
767 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
769 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
770 showTrayMessage(QSystemTrayIcon::Information, 3,
771 "Wi-Fi Protected Setup (WPS) AP\n"
772 "in active PBC mode found.");
773 wpsStatusText->setText("WPS AP in active PBC mode found");
774 wpaguiTab->setCurrentWidget(wpsTab);
775 wpsInstructions->setText("Press the PBC button on the screen "
776 "to start registration");
777 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
778 showTrayMessage(QSystemTrayIcon::Information, 3,
779 "Wi-Fi Protected Setup (WPS) AP\n"
780 " in active PIN mode found.");
781 wpsStatusText->setText("WPS AP with recently selected "
783 wpaguiTab->setCurrentWidget(wpsTab);
784 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
785 showTrayMessage(QSystemTrayIcon::Information, 3,
786 "Wi-Fi Protected Setup (WPS)\n"
788 wpsStatusText->setText("WPS AP detected");
789 wpaguiTab->setCurrentWidget(wpsTab);
790 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
791 showTrayMessage(QSystemTrayIcon::Information, 3,
792 "Wi-Fi Protected Setup (WPS)\n"
793 "PBC mode overlap detected.");
794 wpsStatusText->setText("PBC mode overlap detected");
795 wpsInstructions->setText("More than one AP is currently in "
796 "active WPS PBC mode. Wait couple of "
797 "minutes and try again");
798 wpaguiTab->setCurrentWidget(wpsTab);
799 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
800 wpsStatusText->setText("Network configuration received");
801 wpaguiTab->setCurrentWidget(wpsTab);
802 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
803 if (strstr(pos, "(WSC)"))
804 wpsStatusText->setText("Registration started");
805 } else if (str_match(pos, WPS_EVENT_M2D)) {
806 wpsStatusText->setText("Registrar does not yet know PIN");
807 } else if (str_match(pos, WPS_EVENT_FAIL)) {
808 wpsStatusText->setText("Registration failed");
813 void WpaGui::processCtrlReq(const char *req)
819 udr = new UserDataRequest();
822 if (udr->setParams(this, req) < 0) {
832 void WpaGui::receiveMsgs()
837 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
838 len = sizeof(buf) - 1;
839 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
847 void WpaGui::connectB()
850 size_t reply_len = sizeof(reply);
851 ctrlRequest("REASSOCIATE", reply, &reply_len);
855 void WpaGui::selectNetwork( const QString &sel )
859 size_t reply_len = sizeof(reply);
861 if (cmd.startsWith("Select any")) {
864 int pos = cmd.indexOf(':');
866 printf("Invalid selectNetwork '%s'\n",
867 cmd.toAscii().constData());
872 cmd.prepend("SELECT_NETWORK ");
873 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
879 void WpaGui::enableNetwork(const QString &sel)
883 size_t reply_len = sizeof(reply);
885 if (!cmd.startsWith("all")) {
886 int pos = cmd.indexOf(':');
888 printf("Invalid enableNetwork '%s'\n",
889 cmd.toAscii().constData());
894 cmd.prepend("ENABLE_NETWORK ");
895 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
900 void WpaGui::disableNetwork(const QString &sel)
904 size_t reply_len = sizeof(reply);
906 if (!cmd.startsWith("all")) {
907 int pos = cmd.indexOf(':');
909 printf("Invalid disableNetwork '%s'\n",
910 cmd.toAscii().constData());
915 cmd.prepend("DISABLE_NETWORK ");
916 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
921 void WpaGui::editNetwork(const QString &sel)
926 if (!cmd.startsWith("Select any")) {
927 int pos = sel.indexOf(':');
929 printf("Invalid editNetwork '%s'\n",
930 cmd.toAscii().constData());
937 NetworkConfig *nc = new NetworkConfig();
943 nc->paramsFromConfig(id);
952 void WpaGui::editSelectedNetwork()
954 if (networkSelect->count() < 1) {
955 QMessageBox::information(this, "No Networks",
956 "There are no networks to edit.\n");
959 QString sel(networkSelect->currentText());
964 void WpaGui::editListedNetwork()
966 if (networkList->currentRow() < 0) {
967 QMessageBox::information(this, "Select A Network",
968 "Select a network from the list to"
972 QString sel(networkList->currentItem()->text());
977 void WpaGui::triggerUpdate()
980 networkMayHaveChanged = true;
985 void WpaGui::addNetwork()
987 NetworkConfig *nc = new NetworkConfig();
997 void WpaGui::removeNetwork(const QString &sel)
1001 size_t reply_len = sizeof(reply);
1003 if (cmd.startsWith("Select any"))
1006 if (!cmd.startsWith("all")) {
1007 int pos = cmd.indexOf(':');
1009 printf("Invalid removeNetwork '%s'\n",
1010 cmd.toAscii().constData());
1015 cmd.prepend("REMOVE_NETWORK ");
1016 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1021 void WpaGui::removeSelectedNetwork()
1023 if (networkSelect->count() < 1) {
1024 QMessageBox::information(this, "No Networks",
1025 "There are no networks to remove.\n");
1028 QString sel(networkSelect->currentText());
1033 void WpaGui::removeListedNetwork()
1035 if (networkList->currentRow() < 0) {
1036 QMessageBox::information(this, "Select A Network",
1037 "Select a network from the list to"
1041 QString sel(networkList->currentItem()->text());
1046 void WpaGui::enableAllNetworks()
1053 void WpaGui::disableAllNetworks()
1056 disableNetwork(sel);
1060 void WpaGui::removeAllNetworks()
1067 int WpaGui::getNetworkDisabled(const QString &sel)
1071 size_t reply_len = sizeof(reply) - 1;
1072 int pos = cmd.indexOf(':');
1074 printf("Invalid getNetworkDisabled '%s'\n",
1075 cmd.toAscii().constData());
1079 cmd.prepend("GET_NETWORK ");
1080 cmd.append(" disabled");
1082 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1083 && reply_len >= 1) {
1084 reply[reply_len] = '\0';
1085 if (!str_match(reply, "FAIL"))
1093 void WpaGui::updateNetworkDisabledStatus()
1095 if (networkList->currentRow() < 0)
1098 QString sel(networkList->currentItem()->text());
1100 switch (getNetworkDisabled(sel)) {
1102 if (!enableRadioButton->isChecked())
1103 enableRadioButton->setChecked(true);
1106 if (!disableRadioButton->isChecked())
1107 disableRadioButton->setChecked(true);
1113 void WpaGui::enableListedNetwork(bool enabled)
1115 if (networkList->currentRow() < 0 || !enabled)
1118 QString sel(networkList->currentItem()->text());
1120 if (getNetworkDisabled(sel) == 1)
1125 void WpaGui::disableListedNetwork(bool disabled)
1127 if (networkList->currentRow() < 0 || !disabled)
1130 QString sel(networkList->currentItem()->text());
1132 if (getNetworkDisabled(sel) == 0)
1133 disableNetwork(sel);
1137 void WpaGui::saveConfig()
1142 len = sizeof(buf) - 1;
1143 ctrlRequest("SAVE_CONFIG", buf, &len);
1147 if (str_match(buf, "FAIL"))
1148 QMessageBox::warning(this, "Failed to save configuration",
1149 "The configuration could not be saved.\n"
1151 "The update_config=1 configuration option\n"
1152 "must be used for configuration saving to\n"
1155 QMessageBox::information(this, "Saved configuration",
1156 "The current configuration was saved."
1161 void WpaGui::selectAdapter( const QString & sel )
1163 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1164 printf("Failed to open control connection to "
1165 "wpa_supplicant.\n");
1171 void WpaGui::createTrayIcon(bool trayOnly)
1173 QApplication::setQuitOnLastWindowClosed(false);
1175 tray_icon = new QSystemTrayIcon(this);
1176 tray_icon->setToolTip(qAppName() + " - wpa_supplicant user interface");
1177 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1178 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1180 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1183 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1184 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1186 ackTrayIcon = false;
1188 tray_menu = new QMenu(this);
1190 disconnectAction = new QAction("&Disconnect", this);
1191 reconnectAction = new QAction("Re&connect", this);
1192 connect(disconnectAction, SIGNAL(triggered()), this,
1193 SLOT(disconnect()));
1194 connect(reconnectAction, SIGNAL(triggered()), this,
1196 tray_menu->addAction(disconnectAction);
1197 tray_menu->addAction(reconnectAction);
1198 tray_menu->addSeparator();
1200 eventAction = new QAction("&Event History", this);
1201 scanAction = new QAction("Scan &Results", this);
1202 statAction = new QAction("S&tatus", this);
1203 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1204 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1205 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1206 tray_menu->addAction(eventAction);
1207 tray_menu->addAction(scanAction);
1208 tray_menu->addAction(statAction);
1209 tray_menu->addSeparator();
1211 showAction = new QAction("&Show Window", this);
1212 hideAction = new QAction("&Hide Window", this);
1213 quitAction = new QAction("&Quit", this);
1214 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1215 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1216 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1217 tray_menu->addAction(showAction);
1218 tray_menu->addAction(hideAction);
1219 tray_menu->addSeparator();
1220 tray_menu->addAction(quitAction);
1222 tray_icon->setContextMenu(tray_menu);
1231 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1232 const QString & msg)
1234 if (!QSystemTrayIcon::supportsMessages())
1237 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1240 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1244 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1247 /* use close() here instead of hide() and allow the
1248 * custom closeEvent handler take care of children */
1249 case QSystemTrayIcon::Trigger:
1256 case QSystemTrayIcon::MiddleClick:
1265 void WpaGui::showTrayStatus()
1270 len = sizeof(buf) - 1;
1271 if (ctrlRequest("STATUS", buf, &len) < 0)
1275 QString msg, status(buf);
1277 QStringList lines = status.split(QRegExp("\\n"));
1278 for (QStringList::Iterator it = lines.begin();
1279 it != lines.end(); it++) {
1280 int pos = (*it).indexOf('=') + 1;
1284 if ((*it).startsWith("bssid="))
1285 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1286 else if ((*it).startsWith("ssid="))
1287 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1288 else if ((*it).startsWith("pairwise_cipher="))
1289 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1290 else if ((*it).startsWith("group_cipher="))
1291 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1292 else if ((*it).startsWith("key_mgmt="))
1293 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1294 else if ((*it).startsWith("wpa_state="))
1295 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1296 else if ((*it).startsWith("ip_address="))
1297 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1298 else if ((*it).startsWith("Supplicant PAE state="))
1299 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1300 else if ((*it).startsWith("EAP state="))
1301 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1305 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1309 void WpaGui::closeEvent(QCloseEvent *event)
1329 if (tray_icon && !ackTrayIcon) {
1330 /* give user a visual hint that the tray icon exists */
1331 if (QSystemTrayIcon::supportsMessages()) {
1333 showTrayMessage(QSystemTrayIcon::Information, 3,
1334 qAppName() + " will keep running in "
1335 "the system tray.");
1337 QMessageBox::information(this, qAppName() + " systray",
1338 "The program will keep "
1339 "running in the system "
1349 void WpaGui::wpsDialog()
1351 wpaguiTab->setCurrentWidget(wpsTab);
1355 void WpaGui::tabChanged(int index)
1363 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1364 if (bssFromScan.isEmpty())
1365 wpsApPinButton->setEnabled(false);
1369 void WpaGui::wpsPbc()
1372 size_t reply_len = sizeof(reply);
1374 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1377 wpsPinEdit->setEnabled(false);
1378 if (wpsStatusText->text().compare("WPS AP in active PBC mode found")) {
1379 wpsInstructions->setText("Press the push button on the AP to "
1380 "start the PBC mode.");
1382 wpsInstructions->setText("If you have not yet done so, press "
1383 "the push button on the AP to start "
1386 wpsStatusText->setText("Waiting for Registrar");
1391 void WpaGui::wpsGeneratePin()
1394 size_t reply_len = sizeof(reply) - 1;
1396 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1399 reply[reply_len] = '\0';
1401 wpsPinEdit->setText(reply);
1402 wpsPinEdit->setEnabled(true);
1403 wpsInstructions->setText("Enter the generated PIN into the Registrar "
1404 "(either the internal one in the AP or an "
1406 wpsStatusText->setText("Waiting for Registrar");
1411 void WpaGui::setBssFromScan(const QString &bssid)
1413 bssFromScan = bssid;
1414 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1415 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1416 wpsStatusText->setText("WPS AP selected from scan results");
1417 wpsInstructions->setText("If you want to use an AP device PIN, e.g., "
1418 "from a label in the device, enter the eight "
1419 "digit AP PIN and click Use AP PIN button.");
1423 void WpaGui::wpsApPinChanged(const QString &text)
1425 wpsApPinButton->setEnabled(text.length() == 8);
1429 void WpaGui::wpsApPin()
1432 size_t reply_len = sizeof(reply);
1434 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1435 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1438 wpsStatusText->setText("Waiting for AP/Enrollee");
1443 void WpaGui::stopWpsRun(bool success)
1446 wpsStatusText->setText(success ? "Connected to the network" :
1449 wpsStatusText->setText("");
1450 wpsPinEdit->setEnabled(false);
1451 wpsInstructions->setText("");
1454 wpsApPinEdit->setEnabled(false);
1455 wpsApPinButton->setEnabled(false);