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");
811 void WpaGui::processCtrlReq(const char *req)
817 udr = new UserDataRequest();
820 if (udr->setParams(this, req) < 0) {
830 void WpaGui::receiveMsgs()
835 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
836 len = sizeof(buf) - 1;
837 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
845 void WpaGui::connectB()
848 size_t reply_len = sizeof(reply);
849 ctrlRequest("REASSOCIATE", reply, &reply_len);
853 void WpaGui::selectNetwork( const QString &sel )
857 size_t reply_len = sizeof(reply);
859 if (cmd.startsWith("Select any")) {
862 int pos = cmd.indexOf(':');
864 printf("Invalid selectNetwork '%s'\n",
865 cmd.toAscii().constData());
870 cmd.prepend("SELECT_NETWORK ");
871 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
877 void WpaGui::enableNetwork(const QString &sel)
881 size_t reply_len = sizeof(reply);
883 if (!cmd.startsWith("all")) {
884 int pos = cmd.indexOf(':');
886 printf("Invalid enableNetwork '%s'\n",
887 cmd.toAscii().constData());
892 cmd.prepend("ENABLE_NETWORK ");
893 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
898 void WpaGui::disableNetwork(const QString &sel)
902 size_t reply_len = sizeof(reply);
904 if (!cmd.startsWith("all")) {
905 int pos = cmd.indexOf(':');
907 printf("Invalid disableNetwork '%s'\n",
908 cmd.toAscii().constData());
913 cmd.prepend("DISABLE_NETWORK ");
914 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
919 void WpaGui::editNetwork(const QString &sel)
924 if (!cmd.startsWith("Select any")) {
925 int pos = sel.indexOf(':');
927 printf("Invalid editNetwork '%s'\n",
928 cmd.toAscii().constData());
935 NetworkConfig *nc = new NetworkConfig();
941 nc->paramsFromConfig(id);
950 void WpaGui::editSelectedNetwork()
952 if (networkSelect->count() < 1) {
953 QMessageBox::information(this, "No Networks",
954 "There are no networks to edit.\n");
957 QString sel(networkSelect->currentText());
962 void WpaGui::editListedNetwork()
964 if (networkList->currentRow() < 0) {
965 QMessageBox::information(this, "Select A Network",
966 "Select a network from the list to"
970 QString sel(networkList->currentItem()->text());
975 void WpaGui::triggerUpdate()
978 networkMayHaveChanged = true;
983 void WpaGui::addNetwork()
985 NetworkConfig *nc = new NetworkConfig();
995 void WpaGui::removeNetwork(const QString &sel)
999 size_t reply_len = sizeof(reply);
1001 if (cmd.startsWith("Select any"))
1004 if (!cmd.startsWith("all")) {
1005 int pos = cmd.indexOf(':');
1007 printf("Invalid removeNetwork '%s'\n",
1008 cmd.toAscii().constData());
1013 cmd.prepend("REMOVE_NETWORK ");
1014 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1019 void WpaGui::removeSelectedNetwork()
1021 if (networkSelect->count() < 1) {
1022 QMessageBox::information(this, "No Networks",
1023 "There are no networks to remove.\n");
1026 QString sel(networkSelect->currentText());
1031 void WpaGui::removeListedNetwork()
1033 if (networkList->currentRow() < 0) {
1034 QMessageBox::information(this, "Select A Network",
1035 "Select a network from the list to"
1039 QString sel(networkList->currentItem()->text());
1044 void WpaGui::enableAllNetworks()
1051 void WpaGui::disableAllNetworks()
1054 disableNetwork(sel);
1058 void WpaGui::removeAllNetworks()
1065 int WpaGui::getNetworkDisabled(const QString &sel)
1069 size_t reply_len = sizeof(reply) - 1;
1070 int pos = cmd.indexOf(':');
1072 printf("Invalid getNetworkDisabled '%s'\n",
1073 cmd.toAscii().constData());
1077 cmd.prepend("GET_NETWORK ");
1078 cmd.append(" disabled");
1080 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1081 && reply_len >= 1) {
1082 reply[reply_len] = '\0';
1083 if (!str_match(reply, "FAIL"))
1091 void WpaGui::updateNetworkDisabledStatus()
1093 if (networkList->currentRow() < 0)
1096 QString sel(networkList->currentItem()->text());
1098 switch (getNetworkDisabled(sel)) {
1100 if (!enableRadioButton->isChecked())
1101 enableRadioButton->setChecked(true);
1104 if (!disableRadioButton->isChecked())
1105 disableRadioButton->setChecked(true);
1111 void WpaGui::enableListedNetwork(bool enabled)
1113 if (networkList->currentRow() < 0 || !enabled)
1116 QString sel(networkList->currentItem()->text());
1118 if (getNetworkDisabled(sel) == 1)
1123 void WpaGui::disableListedNetwork(bool disabled)
1125 if (networkList->currentRow() < 0 || !disabled)
1128 QString sel(networkList->currentItem()->text());
1130 if (getNetworkDisabled(sel) == 0)
1131 disableNetwork(sel);
1135 void WpaGui::saveConfig()
1140 len = sizeof(buf) - 1;
1141 ctrlRequest("SAVE_CONFIG", buf, &len);
1145 if (str_match(buf, "FAIL"))
1146 QMessageBox::warning(this, "Failed to save configuration",
1147 "The configuration could not be saved.\n"
1149 "The update_config=1 configuration option\n"
1150 "must be used for configuration saving to\n"
1153 QMessageBox::information(this, "Saved configuration",
1154 "The current configuration was saved."
1159 void WpaGui::selectAdapter( const QString & sel )
1161 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1162 printf("Failed to open control connection to "
1163 "wpa_supplicant.\n");
1169 void WpaGui::createTrayIcon(bool trayOnly)
1171 QApplication::setQuitOnLastWindowClosed(false);
1173 tray_icon = new QSystemTrayIcon(this);
1174 tray_icon->setToolTip(qAppName() + " - wpa_supplicant user interface");
1175 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1176 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1178 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1181 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1182 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1184 ackTrayIcon = false;
1186 tray_menu = new QMenu(this);
1188 disconnectAction = new QAction("&Disconnect", this);
1189 reconnectAction = new QAction("Re&connect", this);
1190 connect(disconnectAction, SIGNAL(triggered()), this,
1191 SLOT(disconnect()));
1192 connect(reconnectAction, SIGNAL(triggered()), this,
1194 tray_menu->addAction(disconnectAction);
1195 tray_menu->addAction(reconnectAction);
1196 tray_menu->addSeparator();
1198 eventAction = new QAction("&Event History", this);
1199 scanAction = new QAction("Scan &Results", this);
1200 statAction = new QAction("S&tatus", this);
1201 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1202 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1203 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1204 tray_menu->addAction(eventAction);
1205 tray_menu->addAction(scanAction);
1206 tray_menu->addAction(statAction);
1207 tray_menu->addSeparator();
1209 showAction = new QAction("&Show Window", this);
1210 hideAction = new QAction("&Hide Window", this);
1211 quitAction = new QAction("&Quit", this);
1212 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1213 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1214 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1215 tray_menu->addAction(showAction);
1216 tray_menu->addAction(hideAction);
1217 tray_menu->addSeparator();
1218 tray_menu->addAction(quitAction);
1220 tray_icon->setContextMenu(tray_menu);
1229 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1230 const QString & msg)
1232 if (!QSystemTrayIcon::supportsMessages())
1235 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1238 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1242 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1245 /* use close() here instead of hide() and allow the
1246 * custom closeEvent handler take care of children */
1247 case QSystemTrayIcon::Trigger:
1254 case QSystemTrayIcon::MiddleClick:
1263 void WpaGui::showTrayStatus()
1268 len = sizeof(buf) - 1;
1269 if (ctrlRequest("STATUS", buf, &len) < 0)
1273 QString msg, status(buf);
1275 QStringList lines = status.split(QRegExp("\\n"));
1276 for (QStringList::Iterator it = lines.begin();
1277 it != lines.end(); it++) {
1278 int pos = (*it).indexOf('=') + 1;
1282 if ((*it).startsWith("bssid="))
1283 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1284 else if ((*it).startsWith("ssid="))
1285 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1286 else if ((*it).startsWith("pairwise_cipher="))
1287 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1288 else if ((*it).startsWith("group_cipher="))
1289 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1290 else if ((*it).startsWith("key_mgmt="))
1291 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1292 else if ((*it).startsWith("wpa_state="))
1293 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1294 else if ((*it).startsWith("ip_address="))
1295 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1296 else if ((*it).startsWith("Supplicant PAE state="))
1297 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1298 else if ((*it).startsWith("EAP state="))
1299 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1303 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1307 void WpaGui::closeEvent(QCloseEvent *event)
1327 if (tray_icon && !ackTrayIcon) {
1328 /* give user a visual hint that the tray icon exists */
1329 if (QSystemTrayIcon::supportsMessages()) {
1331 showTrayMessage(QSystemTrayIcon::Information, 3,
1332 qAppName() + " will keep running in "
1333 "the system tray.");
1335 QMessageBox::information(this, qAppName() + " systray",
1336 "The program will keep "
1337 "running in the system "
1347 void WpaGui::wpsDialog()
1349 wpaguiTab->setCurrentWidget(wpsTab);
1353 void WpaGui::tabChanged(int index)
1361 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1362 if (bssFromScan.isEmpty())
1363 wpsApPinButton->setEnabled(false);
1367 void WpaGui::wpsPbc()
1370 size_t reply_len = sizeof(reply);
1372 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1375 wpsPinEdit->setEnabled(false);
1376 if (wpsStatusText->text().compare("WPS AP in active PBC mode found")) {
1377 wpsInstructions->setText("Press the push button on the AP to "
1378 "start the PBC mode.");
1380 wpsInstructions->setText("If you have not yet done so, press "
1381 "the push button on the AP to start "
1384 wpsStatusText->setText("Waiting for Registrar");
1389 void WpaGui::wpsGeneratePin()
1392 size_t reply_len = sizeof(reply) - 1;
1394 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1397 reply[reply_len] = '\0';
1399 wpsPinEdit->setText(reply);
1400 wpsPinEdit->setEnabled(true);
1401 wpsInstructions->setText("Enter the generated PIN into the Registrar "
1402 "(either the internal one in the AP or an "
1404 wpsStatusText->setText("Waiting for Registrar");
1409 void WpaGui::setBssFromScan(const QString &bssid)
1411 bssFromScan = bssid;
1412 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1413 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1414 wpsStatusText->setText("WPS AP selected from scan results");
1415 wpsInstructions->setText("If you want to use an AP device PIN, e.g., "
1416 "from a label in the device, enter the eight "
1417 "digit AP PIN and click Use AP PIN button.");
1421 void WpaGui::wpsApPinChanged(const QString &text)
1423 wpsApPinButton->setEnabled(text.length() == 8);
1427 void WpaGui::wpsApPin()
1430 size_t reply_len = sizeof(reply);
1432 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1433 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1436 wpsStatusText->setText("Waiting for AP/Enrollee");
1441 void WpaGui::stopWpsRun(bool success)
1444 wpsStatusText->setText(success ? "Connected to the network" :
1447 wpsStatusText->setText("");
1448 wpsPinEdit->setEnabled(false);
1449 wpsInstructions->setText("");
1452 wpsApPinEdit->setEnabled(false);
1453 wpsApPinButton->setEnabled(false);