2 * wpa_gui - WpaGui class
3 * Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
10 /* Need to get getopt() */
14 #ifdef CONFIG_NATIVE_WINDOWS
16 #endif /* CONFIG_NATIVE_WINDOWS */
19 #include <QMessageBox>
20 #include <QCloseEvent>
21 #include <QImageReader>
26 #include "common/wpa_ctrl.h"
27 #include "userdatarequest.h"
28 #include "networkconfig.h"
32 #define printf wpagui_printf
33 static int wpagui_printf(const char *, ...)
39 WpaGui::WpaGui(QApplication *_app, QWidget *parent, const char *, Qt::WFlags)
40 : QMainWindow(parent), app(_app)
44 #ifdef CONFIG_NATIVE_WINDOWS
45 fileStopServiceAction = new QAction(this);
46 fileStopServiceAction->setObjectName("Stop Service");
47 fileStopServiceAction->setIconText(tr("Stop Service"));
48 fileMenu->insertAction(actionWPS, fileStopServiceAction);
50 fileStartServiceAction = new QAction(this);
51 fileStartServiceAction->setObjectName("Start Service");
52 fileStartServiceAction->setIconText(tr("Start Service"));
53 fileMenu->insertAction(fileStopServiceAction, fileStartServiceAction);
55 connect(fileStartServiceAction, SIGNAL(triggered()), this,
56 SLOT(startService()));
57 connect(fileStopServiceAction, SIGNAL(triggered()), this,
60 addInterfaceAction = new QAction(this);
61 addInterfaceAction->setIconText(tr("Add Interface"));
62 fileMenu->insertAction(fileStartServiceAction, addInterfaceAction);
64 connect(addInterfaceAction, SIGNAL(triggered()), this,
65 SLOT(addInterface()));
66 #endif /* CONFIG_NATIVE_WINDOWS */
71 * Disable WPS tab by default; it will be enabled if wpa_supplicant is
72 * built with WPS support.
74 wpsTab->setEnabled(false);
75 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), false);
77 connect(fileEventHistoryAction, SIGNAL(triggered()), this,
78 SLOT(eventHistory()));
79 connect(fileSaveConfigAction, SIGNAL(triggered()), this,
81 connect(actionWPS, SIGNAL(triggered()), this, SLOT(wpsDialog()));
82 connect(actionPeers, SIGNAL(triggered()), this, SLOT(peersDialog()));
83 connect(fileExitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
84 connect(networkAddAction, SIGNAL(triggered()), this,
86 connect(networkEditAction, SIGNAL(triggered()), this,
87 SLOT(editSelectedNetwork()));
88 connect(networkRemoveAction, SIGNAL(triggered()), this,
89 SLOT(removeSelectedNetwork()));
90 connect(networkEnableAllAction, SIGNAL(triggered()), this,
91 SLOT(enableAllNetworks()));
92 connect(networkDisableAllAction, SIGNAL(triggered()), this,
93 SLOT(disableAllNetworks()));
94 connect(networkRemoveAllAction, SIGNAL(triggered()), this,
95 SLOT(removeAllNetworks()));
96 connect(helpIndexAction, SIGNAL(triggered()), this, SLOT(helpIndex()));
97 connect(helpContentsAction, SIGNAL(triggered()), this,
98 SLOT(helpContents()));
99 connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(helpAbout()));
100 connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));
101 connect(scanButton, SIGNAL(clicked()), this, SLOT(scan()));
102 connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB()));
103 connect(adapterSelect, SIGNAL(activated(const QString&)), this,
104 SLOT(selectAdapter(const QString&)));
105 connect(networkSelect, SIGNAL(activated(const QString&)), this,
106 SLOT(selectNetwork(const QString&)));
107 connect(addNetworkButton, SIGNAL(clicked()), this, SLOT(addNetwork()));
108 connect(editNetworkButton, SIGNAL(clicked()), this,
109 SLOT(editListedNetwork()));
110 connect(removeNetworkButton, SIGNAL(clicked()), this,
111 SLOT(removeListedNetwork()));
112 connect(networkList, SIGNAL(itemSelectionChanged()), this,
113 SLOT(updateNetworkDisabledStatus()));
114 connect(enableRadioButton, SIGNAL(toggled(bool)), this,
115 SLOT(enableListedNetwork(bool)));
116 connect(disableRadioButton, SIGNAL(toggled(bool)), this,
117 SLOT(disableListedNetwork(bool)));
118 connect(scanNetworkButton, SIGNAL(clicked()), this, SLOT(scan()));
119 connect(networkList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
120 this, SLOT(editListedNetwork()));
121 connect(wpaguiTab, SIGNAL(currentChanged(int)), this,
122 SLOT(tabChanged(int)));
123 connect(wpsPbcButton, SIGNAL(clicked()), this, SLOT(wpsPbc()));
124 connect(wpsPinButton, SIGNAL(clicked()), this, SLOT(wpsGeneratePin()));
125 connect(wpsApPinEdit, SIGNAL(textChanged(const QString &)), this,
126 SLOT(wpsApPinChanged(const QString &)));
127 connect(wpsApPinButton, SIGNAL(clicked()), this, SLOT(wpsApPin()));
140 ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
144 #ifndef QT_NO_SESSIONMANAGER
145 if (app->isSessionRestored()) {
146 QSettings settings("wpa_supplicant", "wpa_gui");
147 settings.beginGroup("state");
148 if (app->sessionId().compare(settings.value("session_id").
150 startInTray = settings.value("in_tray").toBool();
155 if (QSystemTrayIcon::isSystemTrayAvailable())
156 createTrayIcon(startInTray);
160 connectedToService = false;
161 textStatus->setText(tr("connecting to wpa_supplicant"));
162 timer = new QTimer(this);
163 connect(timer, SIGNAL(timeout()), SLOT(ping()));
164 timer->setSingleShot(FALSE);
167 if (openCtrlConnection(ctrl_iface) < 0) {
168 printf("Failed to open control connection to "
169 "wpa_supplicant.\n");
173 networkMayHaveChanged = true;
183 wpa_ctrl_detach(monitor_conn);
184 wpa_ctrl_close(monitor_conn);
188 wpa_ctrl_close(ctrl_conn);
225 free(ctrl_iface_dir);
226 ctrl_iface_dir = NULL;
230 void WpaGui::languageChange()
236 void WpaGui::parse_argv()
240 c = getopt(qApp->argc(), qApp->argv(), "i:p:t");
246 ctrl_iface = strdup(optarg);
249 free(ctrl_iface_dir);
250 ctrl_iface_dir = strdup(optarg);
260 int WpaGui::openCtrlConnection(const char *ifname)
264 char buf[2048], *pos, *pos2;
268 if (ifname != ctrl_iface) {
270 ctrl_iface = strdup(ifname);
273 #ifdef CONFIG_CTRL_IFACE_UDP
275 ctrl_iface = strdup("udp");
276 #endif /* CONFIG_CTRL_IFACE_UDP */
277 #ifdef CONFIG_CTRL_IFACE_UNIX
279 DIR *dir = opendir(ctrl_iface_dir);
283 while ((dent = readdir(dir))) {
284 #ifdef _DIRENT_HAVE_D_TYPE
285 /* Skip the file if it is not a socket.
286 * Also accept DT_UNKNOWN (0) in case
287 * the C library or underlying file
288 * system does not support d_type. */
289 if (dent->d_type != DT_SOCK &&
290 dent->d_type != DT_UNKNOWN)
292 #endif /* _DIRENT_HAVE_D_TYPE */
294 if (strcmp(dent->d_name, ".") == 0 ||
295 strcmp(dent->d_name, "..") == 0)
297 printf("Selected interface '%s'\n",
299 ctrl_iface = strdup(dent->d_name);
304 #endif /* CONFIG_CTRL_IFACE_UNIX */
305 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
306 struct wpa_ctrl *ctrl;
312 ctrl = wpa_ctrl_open(NULL);
314 len = sizeof(buf) - 1;
315 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf,
318 connectedToService = true;
320 pos = strchr(buf, '\n');
323 ctrl_iface = strdup(buf);
325 wpa_ctrl_close(ctrl);
327 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
330 if (ctrl_iface == NULL) {
331 #ifdef CONFIG_NATIVE_WINDOWS
332 static bool first = true;
333 if (first && !serviceRunning()) {
335 if (QMessageBox::warning(
337 tr("wpa_supplicant service is not "
339 "Do you want to start it?"),
340 QMessageBox::Yes | QMessageBox::No) ==
344 #endif /* CONFIG_NATIVE_WINDOWS */
348 #ifdef CONFIG_CTRL_IFACE_UNIX
349 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
350 cfile = (char *) malloc(flen);
353 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
354 #else /* CONFIG_CTRL_IFACE_UNIX */
355 flen = strlen(ctrl_iface) + 1;
356 cfile = (char *) malloc(flen);
359 snprintf(cfile, flen, "%s", ctrl_iface);
360 #endif /* CONFIG_CTRL_IFACE_UNIX */
363 wpa_ctrl_close(ctrl_conn);
370 wpa_ctrl_detach(monitor_conn);
371 wpa_ctrl_close(monitor_conn);
375 printf("Trying to connect to '%s'\n", cfile);
376 ctrl_conn = wpa_ctrl_open(cfile);
377 if (ctrl_conn == NULL) {
381 monitor_conn = wpa_ctrl_open(cfile);
383 if (monitor_conn == NULL) {
384 wpa_ctrl_close(ctrl_conn);
387 if (wpa_ctrl_attach(monitor_conn)) {
388 printf("Failed to attach to wpa_supplicant\n");
389 wpa_ctrl_close(monitor_conn);
391 wpa_ctrl_close(ctrl_conn);
396 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
397 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
398 QSocketNotifier::Read, this);
399 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
402 adapterSelect->clear();
403 adapterSelect->addItem(ctrl_iface);
404 adapterSelect->setCurrentIndex(0);
406 len = sizeof(buf) - 1;
407 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
412 pos2 = strchr(pos, '\n');
415 if (strcmp(pos, ctrl_iface) != 0)
416 adapterSelect->addItem(pos);
424 len = sizeof(buf) - 1;
425 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len,
430 QStringList types = res.split(QChar(' '));
431 bool wps = types.contains("WSC");
432 actionWPS->setEnabled(wps);
433 wpsTab->setEnabled(wps);
434 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), wps);
441 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
445 if (ctrl_conn == NULL)
447 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen, NULL);
449 printf("'%s' command timed out.\n", cmd);
451 printf("'%s' command failed.\n", cmd);
457 QString WpaGui::wpaStateTranslate(char *state)
459 if (!strcmp(state, "DISCONNECTED"))
460 return tr("Disconnected");
461 else if (!strcmp(state, "INACTIVE"))
462 return tr("Inactive");
463 else if (!strcmp(state, "SCANNING"))
464 return tr("Scanning");
465 else if (!strcmp(state, "AUTHENTICATING"))
466 return tr("Authenticating");
467 else if (!strcmp(state, "ASSOCIATING"))
468 return tr("Associating");
469 else if (!strcmp(state, "ASSOCIATED"))
470 return tr("Associated");
471 else if (!strcmp(state, "4WAY_HANDSHAKE"))
472 return tr("4-Way Handshake");
473 else if (!strcmp(state, "GROUP_HANDSHAKE"))
474 return tr("Group Handshake");
475 else if (!strcmp(state, "COMPLETED"))
476 return tr("Completed");
478 return tr("Unknown");
482 void WpaGui::updateStatus()
484 char buf[2048], *start, *end, *pos;
487 pingsToStatusUpdate = 10;
489 len = sizeof(buf) - 1;
490 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
491 textStatus->setText(tr("Could not get status from "
493 textAuthentication->clear();
494 textEncryption->clear();
497 textIpAddress->clear();
499 #ifdef CONFIG_NATIVE_WINDOWS
500 static bool first = true;
501 if (first && connectedToService &&
502 (ctrl_iface == NULL || *ctrl_iface == '\0')) {
504 if (QMessageBox::information(
506 tr("No network interfaces in use.\n"
507 "Would you like to add one?"),
508 QMessageBox::Yes | QMessageBox::No) ==
512 #endif /* CONFIG_NATIVE_WINDOWS */
518 bool auth_updated = false, ssid_updated = false;
519 bool bssid_updated = false, ipaddr_updated = false;
520 bool status_updated = false;
521 char *pairwise_cipher = NULL, *group_cipher = NULL;
527 end = strchr(start, '\n');
531 while (end[0] && end[1])
536 pos = strchr(start, '=');
539 if (strcmp(start, "bssid") == 0) {
540 bssid_updated = true;
541 textBssid->setText(pos);
542 } else if (strcmp(start, "ssid") == 0) {
544 textSsid->setText(pos);
545 } else if (strcmp(start, "ip_address") == 0) {
546 ipaddr_updated = true;
547 textIpAddress->setText(pos);
548 } else if (strcmp(start, "wpa_state") == 0) {
549 status_updated = true;
550 textStatus->setText(wpaStateTranslate(pos));
551 } else if (strcmp(start, "key_mgmt") == 0) {
553 textAuthentication->setText(pos);
554 /* TODO: could add EAP status to this */
555 } else if (strcmp(start, "pairwise_cipher") == 0) {
556 pairwise_cipher = pos;
557 } else if (strcmp(start, "group_cipher") == 0) {
559 } else if (strcmp(start, "mode") == 0) {
568 if (status_updated && mode)
569 textStatus->setText(textStatus->text() + " (" + mode + ")");
571 if (pairwise_cipher || group_cipher) {
573 if (pairwise_cipher && group_cipher &&
574 strcmp(pairwise_cipher, group_cipher) != 0) {
575 encr.append(pairwise_cipher);
577 encr.append(group_cipher);
578 } else if (pairwise_cipher) {
579 encr.append(pairwise_cipher);
581 encr.append(group_cipher);
582 encr.append(" [group key only]");
584 textEncryption->setText(encr);
586 textEncryption->clear();
591 textAuthentication->clear();
597 textIpAddress->clear();
601 void WpaGui::updateNetworks()
603 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
605 int first_active = -1;
606 int was_selected = -1;
607 bool current = false;
609 if (!networkMayHaveChanged)
612 if (networkList->currentRow() >= 0)
613 was_selected = networkList->currentRow();
615 networkSelect->clear();
616 networkList->clear();
618 if (ctrl_conn == NULL)
621 len = sizeof(buf) - 1;
622 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
626 start = strchr(buf, '\n');
633 end = strchr(start, '\n');
637 while (end[0] && end[1])
643 ssid = strchr(id, '\t');
647 bssid = strchr(ssid, '\t');
651 flags = strchr(bssid, '\t');
656 if (strstr(flags, "[DISABLED][P2P-PERSISTENT]")) {
664 network.append(": ");
665 network.append(ssid);
666 networkSelect->addItem(network);
667 networkList->addItem(network);
669 if (strstr(flags, "[CURRENT]")) {
670 networkSelect->setCurrentIndex(networkSelect->count() -
673 } else if (first_active < 0 &&
674 strstr(flags, "[DISABLED]") == NULL)
675 first_active = networkSelect->count() - 1;
682 if (networkSelect->count() > 1)
683 networkSelect->addItem(tr("Select any network"));
685 if (!current && first_active >= 0)
686 networkSelect->setCurrentIndex(first_active);
688 if (was_selected >= 0 && networkList->count() > 0) {
689 if (was_selected < networkList->count())
690 networkList->setCurrentRow(was_selected);
692 networkList->setCurrentRow(networkList->count() - 1);
695 networkList->setCurrentRow(networkSelect->currentIndex());
697 networkMayHaveChanged = false;
701 void WpaGui::helpIndex()
703 printf("helpIndex\n");
707 void WpaGui::helpContents()
709 printf("helpContents\n");
713 void WpaGui::helpAbout()
715 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
716 "Copyright (c) 2003-2011,\n"
717 "Jouni Malinen <j@w1.fi>\n"
718 "and contributors.\n"
720 "This program is free software. You can\n"
721 "distribute it and/or modify it under the terms "
723 "the GNU General Public License version 2.\n"
725 "Alternatively, this software may be distributed\n"
726 "under the terms of the BSD license.\n"
728 "This product includes software developed\n"
729 "by the OpenSSL Project for use in the\n"
730 "OpenSSL Toolkit (http://www.openssl.org/)\n");
734 void WpaGui::disconnect()
737 size_t reply_len = sizeof(reply);
738 ctrlRequest("DISCONNECT", reply, &reply_len);
750 scanres = new ScanResults();
753 scanres->setWpaGui(this);
759 void WpaGui::eventHistory()
766 eh = new EventHistory();
780 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
782 * QSocketNotifier cannot be used with Windows named pipes, so use a
783 * timer to check for received messages for now. This could be
784 * optimized be doing something specific to named pipes or Windows
785 * events, but it is not clear what would be the best way of doing that
789 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
791 if (scanres && !scanres->isVisible()) {
796 if (eh && !eh->isVisible()) {
801 if (udr && !udr->isVisible()) {
806 len = sizeof(buf) - 1;
807 if (ctrlRequest("PING", buf, &len) < 0) {
808 printf("PING failed - trying to reconnect\n");
809 if (openCtrlConnection(ctrl_iface) >= 0) {
810 printf("Reconnected successfully\n");
811 pingsToStatusUpdate = 0;
815 pingsToStatusUpdate--;
816 if (pingsToStatusUpdate <= 0) {
821 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
822 /* Use less frequent pings and status updates when the main window is
823 * hidden (running in taskbar). */
824 int interval = isHidden() ? 5000 : 1000;
825 if (timer->interval() != interval)
826 timer->setInterval(interval);
827 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
831 static int str_match(const char *a, const char *b)
833 return strncmp(a, b, strlen(b)) == 0;
837 void WpaGui::processMsg(char *msg)
839 char *pos = msg, *pos2;
845 priority = atoi(pos);
846 pos = strchr(pos, '>');
853 WpaMsg wm(pos, priority);
857 peers->event_notify(wm);
859 while (msgs.count() > 100)
862 /* Update last message with truncated version of the event */
863 if (strncmp(pos, "CTRL-", 5) == 0) {
864 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
871 QString lastmsg = pos2;
872 lastmsg.truncate(40);
873 textLastMessage->setText(lastmsg);
875 pingsToStatusUpdate = 0;
876 networkMayHaveChanged = true;
878 if (str_match(pos, WPA_CTRL_REQ))
879 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
880 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
881 scanres->updateResults();
882 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
883 showTrayMessage(QSystemTrayIcon::Information, 3,
884 tr("Disconnected from network."));
885 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
886 showTrayMessage(QSystemTrayIcon::Information, 3,
887 tr("Connection to network established."));
888 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
890 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
891 wpsStatusText->setText(tr("WPS AP in active PBC mode found"));
892 if (textStatus->text() == "INACTIVE" ||
893 textStatus->text() == "DISCONNECTED")
894 wpaguiTab->setCurrentWidget(wpsTab);
895 wpsInstructions->setText(tr("Press the PBC button on the "
896 "screen to start registration"));
897 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
898 wpsStatusText->setText(tr("WPS AP with recently selected "
900 if (textStatus->text() == "INACTIVE" ||
901 textStatus->text() == "DISCONNECTED")
902 wpaguiTab->setCurrentWidget(wpsTab);
903 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_AUTH)) {
904 showTrayMessage(QSystemTrayIcon::Information, 3,
905 "Wi-Fi Protected Setup (WPS) AP\n"
906 "indicating this client is authorized.");
907 wpsStatusText->setText("WPS AP indicating this client is "
909 if (textStatus->text() == "INACTIVE" ||
910 textStatus->text() == "DISCONNECTED")
911 wpaguiTab->setCurrentWidget(wpsTab);
912 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
913 wpsStatusText->setText(tr("WPS AP detected"));
914 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
915 wpsStatusText->setText(tr("PBC mode overlap detected"));
916 wpsInstructions->setText(tr("More than one AP is currently in "
917 "active WPS PBC mode. Wait couple "
918 "of minutes and try again"));
919 wpaguiTab->setCurrentWidget(wpsTab);
920 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
921 wpsStatusText->setText(tr("Network configuration received"));
922 wpaguiTab->setCurrentWidget(wpsTab);
923 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
924 if (strstr(pos, "(WSC)"))
925 wpsStatusText->setText(tr("Registration started"));
926 } else if (str_match(pos, WPS_EVENT_M2D)) {
927 wpsStatusText->setText(tr("Registrar does not yet know PIN"));
928 } else if (str_match(pos, WPS_EVENT_FAIL)) {
929 wpsStatusText->setText(tr("Registration failed"));
930 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
931 wpsStatusText->setText(tr("Registration succeeded"));
936 void WpaGui::processCtrlReq(const char *req)
942 udr = new UserDataRequest();
945 if (udr->setParams(this, req) < 0) {
955 void WpaGui::receiveMsgs()
960 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
961 len = sizeof(buf) - 1;
962 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
970 void WpaGui::connectB()
973 size_t reply_len = sizeof(reply);
974 ctrlRequest("REASSOCIATE", reply, &reply_len);
978 void WpaGui::selectNetwork( const QString &sel )
982 size_t reply_len = sizeof(reply);
984 if (cmd.contains(QRegExp("^\\d+:")))
985 cmd.truncate(cmd.indexOf(':'));
988 cmd.prepend("SELECT_NETWORK ");
989 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
995 void WpaGui::enableNetwork(const QString &sel)
999 size_t reply_len = sizeof(reply);
1001 if (cmd.contains(QRegExp("^\\d+:")))
1002 cmd.truncate(cmd.indexOf(':'));
1003 else if (!cmd.startsWith("all")) {
1004 printf("Invalid editNetwork '%s'\n",
1005 cmd.toAscii().constData());
1008 cmd.prepend("ENABLE_NETWORK ");
1009 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1014 void WpaGui::disableNetwork(const QString &sel)
1018 size_t reply_len = sizeof(reply);
1020 if (cmd.contains(QRegExp("^\\d+:")))
1021 cmd.truncate(cmd.indexOf(':'));
1022 else if (!cmd.startsWith("all")) {
1023 printf("Invalid editNetwork '%s'\n",
1024 cmd.toAscii().constData());
1027 cmd.prepend("DISABLE_NETWORK ");
1028 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1033 void WpaGui::editNetwork(const QString &sel)
1038 if (cmd.contains(QRegExp("^\\d+:"))) {
1039 cmd.truncate(cmd.indexOf(':'));
1043 NetworkConfig *nc = new NetworkConfig();
1046 nc->setWpaGui(this);
1049 nc->paramsFromConfig(id);
1058 void WpaGui::editSelectedNetwork()
1060 if (networkSelect->count() < 1) {
1061 QMessageBox::information(
1062 this, tr("No Networks"),
1063 tr("There are no networks to edit.\n"));
1066 QString sel(networkSelect->currentText());
1071 void WpaGui::editListedNetwork()
1073 if (networkList->currentRow() < 0) {
1074 QMessageBox::information(this, tr("Select A Network"),
1075 tr("Select a network from the list to"
1079 QString sel(networkList->currentItem()->text());
1084 void WpaGui::triggerUpdate()
1087 networkMayHaveChanged = true;
1092 void WpaGui::addNetwork()
1094 NetworkConfig *nc = new NetworkConfig();
1097 nc->setWpaGui(this);
1104 void WpaGui::removeNetwork(const QString &sel)
1108 size_t reply_len = sizeof(reply);
1110 if (cmd.contains(QRegExp("^\\d+:")))
1111 cmd.truncate(cmd.indexOf(':'));
1112 else if (!cmd.startsWith("all")) {
1113 printf("Invalid editNetwork '%s'\n",
1114 cmd.toAscii().constData());
1117 cmd.prepend("REMOVE_NETWORK ");
1118 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1123 void WpaGui::removeSelectedNetwork()
1125 if (networkSelect->count() < 1) {
1126 QMessageBox::information(this, tr("No Networks"),
1127 tr("There are no networks to remove."
1131 QString sel(networkSelect->currentText());
1136 void WpaGui::removeListedNetwork()
1138 if (networkList->currentRow() < 0) {
1139 QMessageBox::information(this, tr("Select A Network"),
1140 tr("Select a network from the list "
1141 "to remove it.\n"));
1144 QString sel(networkList->currentItem()->text());
1149 void WpaGui::enableAllNetworks()
1156 void WpaGui::disableAllNetworks()
1159 disableNetwork(sel);
1163 void WpaGui::removeAllNetworks()
1170 int WpaGui::getNetworkDisabled(const QString &sel)
1174 size_t reply_len = sizeof(reply) - 1;
1175 int pos = cmd.indexOf(':');
1177 printf("Invalid getNetworkDisabled '%s'\n",
1178 cmd.toAscii().constData());
1182 cmd.prepend("GET_NETWORK ");
1183 cmd.append(" disabled");
1185 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1186 && reply_len >= 1) {
1187 reply[reply_len] = '\0';
1188 if (!str_match(reply, "FAIL"))
1196 void WpaGui::updateNetworkDisabledStatus()
1198 if (networkList->currentRow() < 0)
1201 QString sel(networkList->currentItem()->text());
1203 switch (getNetworkDisabled(sel)) {
1205 if (!enableRadioButton->isChecked())
1206 enableRadioButton->setChecked(true);
1209 if (!disableRadioButton->isChecked())
1210 disableRadioButton->setChecked(true);
1216 void WpaGui::enableListedNetwork(bool enabled)
1218 if (networkList->currentRow() < 0 || !enabled)
1221 QString sel(networkList->currentItem()->text());
1223 if (getNetworkDisabled(sel) == 1)
1228 void WpaGui::disableListedNetwork(bool disabled)
1230 if (networkList->currentRow() < 0 || !disabled)
1233 QString sel(networkList->currentItem()->text());
1235 if (getNetworkDisabled(sel) == 0)
1236 disableNetwork(sel);
1240 void WpaGui::saveConfig()
1245 len = sizeof(buf) - 1;
1246 ctrlRequest("SAVE_CONFIG", buf, &len);
1250 if (str_match(buf, "FAIL"))
1251 QMessageBox::warning(
1252 this, tr("Failed to save configuration"),
1253 tr("The configuration could not be saved.\n"
1255 "The update_config=1 configuration option\n"
1256 "must be used for configuration saving to\n"
1257 "be permitted.\n"));
1259 QMessageBox::information(
1260 this, tr("Saved configuration"),
1261 tr("The current configuration was saved."
1266 void WpaGui::selectAdapter( const QString & sel )
1268 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1269 printf("Failed to open control connection to "
1270 "wpa_supplicant.\n");
1276 void WpaGui::createTrayIcon(bool trayOnly)
1278 QApplication::setQuitOnLastWindowClosed(false);
1280 tray_icon = new QSystemTrayIcon(this);
1281 tray_icon->setToolTip(qAppName() + tr(" - wpa_supplicant user interface"));
1282 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1283 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1285 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1288 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1289 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1291 ackTrayIcon = false;
1293 tray_menu = new QMenu(this);
1295 disconnectAction = new QAction(tr("&Disconnect"), this);
1296 reconnectAction = new QAction(tr("Re&connect"), this);
1297 connect(disconnectAction, SIGNAL(triggered()), this,
1298 SLOT(disconnect()));
1299 connect(reconnectAction, SIGNAL(triggered()), this,
1301 tray_menu->addAction(disconnectAction);
1302 tray_menu->addAction(reconnectAction);
1303 tray_menu->addSeparator();
1305 eventAction = new QAction(tr("&Event History"), this);
1306 scanAction = new QAction(tr("Scan &Results"), this);
1307 statAction = new QAction(tr("S&tatus"), this);
1308 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1309 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1310 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1311 tray_menu->addAction(eventAction);
1312 tray_menu->addAction(scanAction);
1313 tray_menu->addAction(statAction);
1314 tray_menu->addSeparator();
1316 showAction = new QAction(tr("&Show Window"), this);
1317 hideAction = new QAction(tr("&Hide Window"), this);
1318 quitAction = new QAction(tr("&Quit"), this);
1319 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1320 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1321 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1322 tray_menu->addAction(showAction);
1323 tray_menu->addAction(hideAction);
1324 tray_menu->addSeparator();
1325 tray_menu->addAction(quitAction);
1327 tray_icon->setContextMenu(tray_menu);
1337 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1338 const QString & msg)
1340 if (!QSystemTrayIcon::supportsMessages())
1343 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1346 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1350 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1353 /* use close() here instead of hide() and allow the
1354 * custom closeEvent handler take care of children */
1355 case QSystemTrayIcon::Trigger:
1365 case QSystemTrayIcon::MiddleClick:
1374 void WpaGui::showTrayStatus()
1379 len = sizeof(buf) - 1;
1380 if (ctrlRequest("STATUS", buf, &len) < 0)
1384 QString msg, status(buf);
1386 QStringList lines = status.split(QRegExp("\\n"));
1387 for (QStringList::Iterator it = lines.begin();
1388 it != lines.end(); it++) {
1389 int pos = (*it).indexOf('=') + 1;
1393 if ((*it).startsWith("bssid="))
1394 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1395 else if ((*it).startsWith("ssid="))
1396 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1397 else if ((*it).startsWith("pairwise_cipher="))
1398 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1399 else if ((*it).startsWith("group_cipher="))
1400 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1401 else if ((*it).startsWith("key_mgmt="))
1402 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1403 else if ((*it).startsWith("wpa_state="))
1404 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1405 else if ((*it).startsWith("ip_address="))
1406 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1407 else if ((*it).startsWith("Supplicant PAE state="))
1408 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1409 else if ((*it).startsWith("EAP state="))
1410 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1414 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1418 void WpaGui::closeEvent(QCloseEvent *event)
1444 if (tray_icon && !ackTrayIcon) {
1445 /* give user a visual hint that the tray icon exists */
1446 if (QSystemTrayIcon::supportsMessages()) {
1448 showTrayMessage(QSystemTrayIcon::Information, 3,
1450 tr(" will keep running in "
1451 "the system tray."));
1453 QMessageBox::information(this, qAppName() +
1455 tr("The program will keep "
1456 "running in the system "
1466 void WpaGui::wpsDialog()
1468 wpaguiTab->setCurrentWidget(wpsTab);
1472 void WpaGui::peersDialog()
1479 peers = new Peers();
1482 peers->setWpaGui(this);
1488 void WpaGui::tabChanged(int index)
1496 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1497 if (bssFromScan.isEmpty())
1498 wpsApPinButton->setEnabled(false);
1502 void WpaGui::wpsPbc()
1505 size_t reply_len = sizeof(reply);
1507 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1510 wpsPinEdit->setEnabled(false);
1511 if (wpsStatusText->text().compare(tr("WPS AP in active PBC mode found"))) {
1512 wpsInstructions->setText(tr("Press the push button on the AP to "
1513 "start the PBC mode."));
1515 wpsInstructions->setText(tr("If you have not yet done so, press "
1516 "the push button on the AP to start "
1519 wpsStatusText->setText(tr("Waiting for Registrar"));
1524 void WpaGui::wpsGeneratePin()
1527 size_t reply_len = sizeof(reply) - 1;
1529 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1532 reply[reply_len] = '\0';
1534 wpsPinEdit->setText(reply);
1535 wpsPinEdit->setEnabled(true);
1536 wpsInstructions->setText(tr("Enter the generated PIN into the Registrar "
1537 "(either the internal one in the AP or an "
1539 wpsStatusText->setText(tr("Waiting for Registrar"));
1544 void WpaGui::setBssFromScan(const QString &bssid)
1546 bssFromScan = bssid;
1547 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1548 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1549 wpsStatusText->setText(tr("WPS AP selected from scan results"));
1550 wpsInstructions->setText(tr("If you want to use an AP device PIN, e.g., "
1551 "from a label in the device, enter the eight "
1552 "digit AP PIN and click Use AP PIN button."));
1556 void WpaGui::wpsApPinChanged(const QString &text)
1558 wpsApPinButton->setEnabled(text.length() == 8);
1562 void WpaGui::wpsApPin()
1565 size_t reply_len = sizeof(reply);
1567 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1568 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1571 wpsStatusText->setText(tr("Waiting for AP/Enrollee"));
1576 void WpaGui::stopWpsRun(bool success)
1579 wpsStatusText->setText(success ? tr("Connected to the network") :
1582 wpsStatusText->setText("");
1583 wpsPinEdit->setEnabled(false);
1584 wpsInstructions->setText("");
1587 wpsApPinEdit->setEnabled(false);
1588 wpsApPinButton->setEnabled(false);
1592 #ifdef CONFIG_NATIVE_WINDOWS
1595 #define WPASVC_NAME TEXT("wpasvc")
1598 class ErrorMsg : public QMessageBox {
1600 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1601 void showMsg(QString msg);
1606 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1607 QMessageBox(parent), err(last_err)
1609 setWindowTitle(tr("wpa_gui error"));
1610 setIcon(QMessageBox::Warning);
1613 void ErrorMsg::showMsg(QString msg)
1618 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1619 FORMAT_MESSAGE_FROM_SYSTEM,
1620 NULL, err, 0, (LPTSTR) (void *) &buf,
1622 QString msg = QString::fromWCharArray(buf);
1623 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1626 setInformativeText(QString("[%1]").arg(err));
1633 void WpaGui::startService()
1637 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1639 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1643 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1645 ErrorMsg(this).showMsg(tr("OpenService failed"));
1646 CloseServiceHandle(scm);
1650 if (!StartService(svc, 0, NULL)) {
1651 ErrorMsg(this).showMsg(tr("Failed to start wpa_supplicant "
1655 CloseServiceHandle(svc);
1656 CloseServiceHandle(scm);
1660 void WpaGui::stopService()
1663 SERVICE_STATUS status;
1665 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1667 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1671 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1673 ErrorMsg(this).showMsg(tr("OpenService failed"));
1674 CloseServiceHandle(scm);
1678 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1679 ErrorMsg(this).showMsg(tr("Failed to stop wpa_supplicant "
1683 CloseServiceHandle(svc);
1684 CloseServiceHandle(scm);
1688 bool WpaGui::serviceRunning()
1691 SERVICE_STATUS status;
1692 bool running = false;
1694 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1696 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1700 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1702 printf("OpenService failed: %d\n\n", (int) GetLastError());
1703 CloseServiceHandle(scm);
1707 if (QueryServiceStatus(svc, &status)) {
1708 if (status.dwCurrentState != SERVICE_STOPPED)
1712 CloseServiceHandle(svc);
1713 CloseServiceHandle(scm);
1718 #endif /* CONFIG_NATIVE_WINDOWS */
1721 void WpaGui::addInterface()
1727 add_iface = new AddInterface(this, this);
1733 #ifndef QT_NO_SESSIONMANAGER
1734 void WpaGui::saveState()
1736 QSettings settings("wpa_supplicant", "wpa_gui");
1737 settings.beginGroup("state");
1738 settings.setValue("session_id", app->sessionId());
1739 settings.setValue("in_tray", inTray);
1740 settings.endGroup();