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.
9 #ifdef CONFIG_NATIVE_WINDOWS
11 #endif /* CONFIG_NATIVE_WINDOWS */
15 #include <QMessageBox>
16 #include <QCloseEvent>
17 #include <QImageReader>
22 #include "common/wpa_ctrl.h"
23 #include "userdatarequest.h"
24 #include "networkconfig.h"
28 #define printf wpagui_printf
29 static int wpagui_printf(const char *, ...)
35 WpaGui::WpaGui(QApplication *_app, QWidget *parent, const char *, Qt::WFlags)
36 : QMainWindow(parent), app(_app)
40 #ifdef CONFIG_NATIVE_WINDOWS
41 fileStopServiceAction = new QAction(this);
42 fileStopServiceAction->setObjectName("Stop Service");
43 fileStopServiceAction->setIconText(tr("Stop Service"));
44 fileMenu->insertAction(actionWPS, fileStopServiceAction);
46 fileStartServiceAction = new QAction(this);
47 fileStartServiceAction->setObjectName("Start Service");
48 fileStartServiceAction->setIconText(tr("Start Service"));
49 fileMenu->insertAction(fileStopServiceAction, fileStartServiceAction);
51 connect(fileStartServiceAction, SIGNAL(triggered()), this,
52 SLOT(startService()));
53 connect(fileStopServiceAction, SIGNAL(triggered()), this,
56 addInterfaceAction = new QAction(this);
57 addInterfaceAction->setIconText(tr("Add Interface"));
58 fileMenu->insertAction(fileStartServiceAction, addInterfaceAction);
60 connect(addInterfaceAction, SIGNAL(triggered()), this,
61 SLOT(addInterface()));
62 #endif /* CONFIG_NATIVE_WINDOWS */
67 * Disable WPS tab by default; it will be enabled if wpa_supplicant is
68 * built with WPS support.
70 wpsTab->setEnabled(false);
71 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), false);
73 connect(fileEventHistoryAction, SIGNAL(triggered()), this,
74 SLOT(eventHistory()));
75 connect(fileSaveConfigAction, SIGNAL(triggered()), this,
77 connect(actionWPS, SIGNAL(triggered()), this, SLOT(wpsDialog()));
78 connect(actionPeers, SIGNAL(triggered()), this, SLOT(peersDialog()));
79 connect(fileExitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
80 connect(networkAddAction, SIGNAL(triggered()), this,
82 connect(networkEditAction, SIGNAL(triggered()), this,
83 SLOT(editSelectedNetwork()));
84 connect(networkRemoveAction, SIGNAL(triggered()), this,
85 SLOT(removeSelectedNetwork()));
86 connect(networkEnableAllAction, SIGNAL(triggered()), this,
87 SLOT(enableAllNetworks()));
88 connect(networkDisableAllAction, SIGNAL(triggered()), this,
89 SLOT(disableAllNetworks()));
90 connect(networkRemoveAllAction, SIGNAL(triggered()), this,
91 SLOT(removeAllNetworks()));
92 connect(helpIndexAction, SIGNAL(triggered()), this, SLOT(helpIndex()));
93 connect(helpContentsAction, SIGNAL(triggered()), this,
94 SLOT(helpContents()));
95 connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(helpAbout()));
96 connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));
97 connect(scanButton, SIGNAL(clicked()), this, SLOT(scan()));
98 connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB()));
99 connect(adapterSelect, SIGNAL(activated(const QString&)), this,
100 SLOT(selectAdapter(const QString&)));
101 connect(networkSelect, SIGNAL(activated(const QString&)), this,
102 SLOT(selectNetwork(const QString&)));
103 connect(addNetworkButton, SIGNAL(clicked()), this, SLOT(addNetwork()));
104 connect(editNetworkButton, SIGNAL(clicked()), this,
105 SLOT(editListedNetwork()));
106 connect(removeNetworkButton, SIGNAL(clicked()), this,
107 SLOT(removeListedNetwork()));
108 connect(networkList, SIGNAL(itemSelectionChanged()), this,
109 SLOT(updateNetworkDisabledStatus()));
110 connect(enableRadioButton, SIGNAL(toggled(bool)), this,
111 SLOT(enableListedNetwork(bool)));
112 connect(disableRadioButton, SIGNAL(toggled(bool)), this,
113 SLOT(disableListedNetwork(bool)));
114 connect(scanNetworkButton, SIGNAL(clicked()), this, SLOT(scan()));
115 connect(networkList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
116 this, SLOT(editListedNetwork()));
117 connect(wpaguiTab, SIGNAL(currentChanged(int)), this,
118 SLOT(tabChanged(int)));
119 connect(wpsPbcButton, SIGNAL(clicked()), this, SLOT(wpsPbc()));
120 connect(wpsPinButton, SIGNAL(clicked()), this, SLOT(wpsGeneratePin()));
121 connect(wpsApPinEdit, SIGNAL(textChanged(const QString &)), this,
122 SLOT(wpsApPinChanged(const QString &)));
123 connect(wpsApPinButton, SIGNAL(clicked()), this, SLOT(wpsApPin()));
136 ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
140 #ifndef QT_NO_SESSIONMANAGER
141 if (app->isSessionRestored()) {
142 QSettings settings("wpa_supplicant", "wpa_gui");
143 settings.beginGroup("state");
144 if (app->sessionId().compare(settings.value("session_id").
146 startInTray = settings.value("in_tray").toBool();
151 if (QSystemTrayIcon::isSystemTrayAvailable())
152 createTrayIcon(startInTray);
156 connectedToService = false;
157 textStatus->setText(tr("connecting to wpa_supplicant"));
158 timer = new QTimer(this);
159 connect(timer, SIGNAL(timeout()), SLOT(ping()));
160 timer->setSingleShot(FALSE);
163 if (openCtrlConnection(ctrl_iface) < 0) {
164 printf("Failed to open control connection to "
165 "wpa_supplicant.\n");
169 networkMayHaveChanged = true;
179 wpa_ctrl_detach(monitor_conn);
180 wpa_ctrl_close(monitor_conn);
184 wpa_ctrl_close(ctrl_conn);
221 free(ctrl_iface_dir);
222 ctrl_iface_dir = NULL;
226 void WpaGui::languageChange()
232 void WpaGui::parse_argv()
236 c = getopt(qApp->argc(), qApp->argv(), "i:p:t");
242 ctrl_iface = strdup(optarg);
245 free(ctrl_iface_dir);
246 ctrl_iface_dir = strdup(optarg);
256 int WpaGui::openCtrlConnection(const char *ifname)
260 char buf[2048], *pos, *pos2;
264 if (ifname != ctrl_iface) {
266 ctrl_iface = strdup(ifname);
269 #ifdef CONFIG_CTRL_IFACE_UDP
271 ctrl_iface = strdup("udp");
272 #endif /* CONFIG_CTRL_IFACE_UDP */
273 #ifdef CONFIG_CTRL_IFACE_UNIX
275 DIR *dir = opendir(ctrl_iface_dir);
279 while ((dent = readdir(dir))) {
280 #ifdef _DIRENT_HAVE_D_TYPE
281 /* Skip the file if it is not a socket.
282 * Also accept DT_UNKNOWN (0) in case
283 * the C library or underlying file
284 * system does not support d_type. */
285 if (dent->d_type != DT_SOCK &&
286 dent->d_type != DT_UNKNOWN)
288 #endif /* _DIRENT_HAVE_D_TYPE */
290 if (strcmp(dent->d_name, ".") == 0 ||
291 strcmp(dent->d_name, "..") == 0)
293 printf("Selected interface '%s'\n",
295 ctrl_iface = strdup(dent->d_name);
300 #endif /* CONFIG_CTRL_IFACE_UNIX */
301 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
302 struct wpa_ctrl *ctrl;
308 ctrl = wpa_ctrl_open(NULL);
310 len = sizeof(buf) - 1;
311 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf,
314 connectedToService = true;
316 pos = strchr(buf, '\n');
319 ctrl_iface = strdup(buf);
321 wpa_ctrl_close(ctrl);
323 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
326 if (ctrl_iface == NULL) {
327 #ifdef CONFIG_NATIVE_WINDOWS
328 static bool first = true;
329 if (first && !serviceRunning()) {
331 if (QMessageBox::warning(
333 tr("wpa_supplicant service is not "
335 "Do you want to start it?"),
336 QMessageBox::Yes | QMessageBox::No) ==
340 #endif /* CONFIG_NATIVE_WINDOWS */
344 #ifdef CONFIG_CTRL_IFACE_UNIX
345 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
346 cfile = (char *) malloc(flen);
349 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
350 #else /* CONFIG_CTRL_IFACE_UNIX */
351 flen = strlen(ctrl_iface) + 1;
352 cfile = (char *) malloc(flen);
355 snprintf(cfile, flen, "%s", ctrl_iface);
356 #endif /* CONFIG_CTRL_IFACE_UNIX */
359 wpa_ctrl_close(ctrl_conn);
366 wpa_ctrl_detach(monitor_conn);
367 wpa_ctrl_close(monitor_conn);
371 printf("Trying to connect to '%s'\n", cfile);
372 ctrl_conn = wpa_ctrl_open(cfile);
373 if (ctrl_conn == NULL) {
377 monitor_conn = wpa_ctrl_open(cfile);
379 if (monitor_conn == NULL) {
380 wpa_ctrl_close(ctrl_conn);
383 if (wpa_ctrl_attach(monitor_conn)) {
384 printf("Failed to attach to wpa_supplicant\n");
385 wpa_ctrl_close(monitor_conn);
387 wpa_ctrl_close(ctrl_conn);
392 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
393 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
394 QSocketNotifier::Read, this);
395 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
398 adapterSelect->clear();
399 adapterSelect->addItem(ctrl_iface);
400 adapterSelect->setCurrentIndex(0);
402 len = sizeof(buf) - 1;
403 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
408 pos2 = strchr(pos, '\n');
411 if (strcmp(pos, ctrl_iface) != 0)
412 adapterSelect->addItem(pos);
420 len = sizeof(buf) - 1;
421 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len,
426 QStringList types = res.split(QChar(' '));
427 bool wps = types.contains("WSC");
428 actionWPS->setEnabled(wps);
429 wpsTab->setEnabled(wps);
430 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), wps);
437 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
441 if (ctrl_conn == NULL)
443 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen, NULL);
445 printf("'%s' command timed out.\n", cmd);
447 printf("'%s' command failed.\n", cmd);
453 QString WpaGui::wpaStateTranslate(char *state)
455 if (!strcmp(state, "DISCONNECTED"))
456 return tr("Disconnected");
457 else if (!strcmp(state, "INACTIVE"))
458 return tr("Inactive");
459 else if (!strcmp(state, "SCANNING"))
460 return tr("Scanning");
461 else if (!strcmp(state, "AUTHENTICATING"))
462 return tr("Authenticating");
463 else if (!strcmp(state, "ASSOCIATING"))
464 return tr("Associating");
465 else if (!strcmp(state, "ASSOCIATED"))
466 return tr("Associated");
467 else if (!strcmp(state, "4WAY_HANDSHAKE"))
468 return tr("4-Way Handshake");
469 else if (!strcmp(state, "GROUP_HANDSHAKE"))
470 return tr("Group Handshake");
471 else if (!strcmp(state, "COMPLETED"))
472 return tr("Completed");
474 return tr("Unknown");
478 void WpaGui::updateStatus()
480 char buf[2048], *start, *end, *pos;
483 pingsToStatusUpdate = 10;
485 len = sizeof(buf) - 1;
486 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
487 textStatus->setText(tr("Could not get status from "
489 textAuthentication->clear();
490 textEncryption->clear();
493 textIpAddress->clear();
495 #ifdef CONFIG_NATIVE_WINDOWS
496 static bool first = true;
497 if (first && connectedToService &&
498 (ctrl_iface == NULL || *ctrl_iface == '\0')) {
500 if (QMessageBox::information(
502 tr("No network interfaces in use.\n"
503 "Would you like to add one?"),
504 QMessageBox::Yes | QMessageBox::No) ==
508 #endif /* CONFIG_NATIVE_WINDOWS */
514 bool auth_updated = false, ssid_updated = false;
515 bool bssid_updated = false, ipaddr_updated = false;
516 bool status_updated = false;
517 char *pairwise_cipher = NULL, *group_cipher = NULL;
523 end = strchr(start, '\n');
527 while (end[0] && end[1])
532 pos = strchr(start, '=');
535 if (strcmp(start, "bssid") == 0) {
536 bssid_updated = true;
537 textBssid->setText(pos);
538 } else if (strcmp(start, "ssid") == 0) {
540 textSsid->setText(pos);
541 } else if (strcmp(start, "ip_address") == 0) {
542 ipaddr_updated = true;
543 textIpAddress->setText(pos);
544 } else if (strcmp(start, "wpa_state") == 0) {
545 status_updated = true;
546 textStatus->setText(wpaStateTranslate(pos));
547 } else if (strcmp(start, "key_mgmt") == 0) {
549 textAuthentication->setText(pos);
550 /* TODO: could add EAP status to this */
551 } else if (strcmp(start, "pairwise_cipher") == 0) {
552 pairwise_cipher = pos;
553 } else if (strcmp(start, "group_cipher") == 0) {
555 } else if (strcmp(start, "mode") == 0) {
564 if (status_updated && mode)
565 textStatus->setText(textStatus->text() + " (" + mode + ")");
567 if (pairwise_cipher || group_cipher) {
569 if (pairwise_cipher && group_cipher &&
570 strcmp(pairwise_cipher, group_cipher) != 0) {
571 encr.append(pairwise_cipher);
573 encr.append(group_cipher);
574 } else if (pairwise_cipher) {
575 encr.append(pairwise_cipher);
577 encr.append(group_cipher);
578 encr.append(" [group key only]");
580 textEncryption->setText(encr);
582 textEncryption->clear();
587 textAuthentication->clear();
593 textIpAddress->clear();
597 void WpaGui::updateNetworks()
599 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
601 int first_active = -1;
602 int was_selected = -1;
603 bool current = false;
605 if (!networkMayHaveChanged)
608 if (networkList->currentRow() >= 0)
609 was_selected = networkList->currentRow();
611 networkSelect->clear();
612 networkList->clear();
614 if (ctrl_conn == NULL)
617 len = sizeof(buf) - 1;
618 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
622 start = strchr(buf, '\n');
629 end = strchr(start, '\n');
633 while (end[0] && end[1])
639 ssid = strchr(id, '\t');
643 bssid = strchr(ssid, '\t');
647 flags = strchr(bssid, '\t');
652 if (strstr(flags, "[DISABLED][P2P-PERSISTENT]")) {
660 network.append(": ");
661 network.append(ssid);
662 networkSelect->addItem(network);
663 networkList->addItem(network);
665 if (strstr(flags, "[CURRENT]")) {
666 networkSelect->setCurrentIndex(networkSelect->count() -
669 } else if (first_active < 0 &&
670 strstr(flags, "[DISABLED]") == NULL)
671 first_active = networkSelect->count() - 1;
678 if (networkSelect->count() > 1)
679 networkSelect->addItem(tr("Select any network"));
681 if (!current && first_active >= 0)
682 networkSelect->setCurrentIndex(first_active);
684 if (was_selected >= 0 && networkList->count() > 0) {
685 if (was_selected < networkList->count())
686 networkList->setCurrentRow(was_selected);
688 networkList->setCurrentRow(networkList->count() - 1);
691 networkList->setCurrentRow(networkSelect->currentIndex());
693 networkMayHaveChanged = false;
697 void WpaGui::helpIndex()
699 printf("helpIndex\n");
703 void WpaGui::helpContents()
705 printf("helpContents\n");
709 void WpaGui::helpAbout()
711 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
712 "Copyright (c) 2003-2013,\n"
713 "Jouni Malinen <j@w1.fi>\n"
714 "and contributors.\n"
716 "This software may be distributed under\n"
717 "the terms of the BSD license.\n"
718 "See README for more details.\n"
720 "This product includes software developed\n"
721 "by the OpenSSL Project for use in the\n"
722 "OpenSSL Toolkit (http://www.openssl.org/)\n");
726 void WpaGui::disconnect()
729 size_t reply_len = sizeof(reply);
730 ctrlRequest("DISCONNECT", reply, &reply_len);
742 scanres = new ScanResults();
745 scanres->setWpaGui(this);
751 void WpaGui::eventHistory()
758 eh = new EventHistory();
772 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
774 * QSocketNotifier cannot be used with Windows named pipes, so use a
775 * timer to check for received messages for now. This could be
776 * optimized be doing something specific to named pipes or Windows
777 * events, but it is not clear what would be the best way of doing that
781 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
783 if (scanres && !scanres->isVisible()) {
788 if (eh && !eh->isVisible()) {
793 if (udr && !udr->isVisible()) {
798 len = sizeof(buf) - 1;
799 if (ctrlRequest("PING", buf, &len) < 0) {
800 printf("PING failed - trying to reconnect\n");
801 if (openCtrlConnection(ctrl_iface) >= 0) {
802 printf("Reconnected successfully\n");
803 pingsToStatusUpdate = 0;
807 pingsToStatusUpdate--;
808 if (pingsToStatusUpdate <= 0) {
813 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
814 /* Use less frequent pings and status updates when the main window is
815 * hidden (running in taskbar). */
816 int interval = isHidden() ? 5000 : 1000;
817 if (timer->interval() != interval)
818 timer->setInterval(interval);
819 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
823 static int str_match(const char *a, const char *b)
825 return strncmp(a, b, strlen(b)) == 0;
829 void WpaGui::processMsg(char *msg)
831 char *pos = msg, *pos2;
837 priority = atoi(pos);
838 pos = strchr(pos, '>');
845 WpaMsg wm(pos, priority);
849 peers->event_notify(wm);
851 while (msgs.count() > 100)
854 /* Update last message with truncated version of the event */
855 if (strncmp(pos, "CTRL-", 5) == 0) {
856 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
863 QString lastmsg = pos2;
864 lastmsg.truncate(40);
865 textLastMessage->setText(lastmsg);
867 pingsToStatusUpdate = 0;
868 networkMayHaveChanged = true;
870 if (str_match(pos, WPA_CTRL_REQ))
871 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
872 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
873 scanres->updateResults();
874 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
875 showTrayMessage(QSystemTrayIcon::Information, 3,
876 tr("Disconnected from network."));
877 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
878 showTrayMessage(QSystemTrayIcon::Information, 3,
879 tr("Connection to network established."));
880 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
882 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
883 wpsStatusText->setText(tr("WPS AP in active PBC mode found"));
884 if (textStatus->text() == "INACTIVE" ||
885 textStatus->text() == "DISCONNECTED")
886 wpaguiTab->setCurrentWidget(wpsTab);
887 wpsInstructions->setText(tr("Press the PBC button on the "
888 "screen to start registration"));
889 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
890 wpsStatusText->setText(tr("WPS AP with recently selected "
892 if (textStatus->text() == "INACTIVE" ||
893 textStatus->text() == "DISCONNECTED")
894 wpaguiTab->setCurrentWidget(wpsTab);
895 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_AUTH)) {
896 showTrayMessage(QSystemTrayIcon::Information, 3,
897 "Wi-Fi Protected Setup (WPS) AP\n"
898 "indicating this client is authorized.");
899 wpsStatusText->setText("WPS AP indicating this client is "
901 if (textStatus->text() == "INACTIVE" ||
902 textStatus->text() == "DISCONNECTED")
903 wpaguiTab->setCurrentWidget(wpsTab);
904 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
905 wpsStatusText->setText(tr("WPS AP detected"));
906 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
907 wpsStatusText->setText(tr("PBC mode overlap detected"));
908 wpsInstructions->setText(tr("More than one AP is currently in "
909 "active WPS PBC mode. Wait couple "
910 "of minutes and try again"));
911 wpaguiTab->setCurrentWidget(wpsTab);
912 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
913 wpsStatusText->setText(tr("Network configuration received"));
914 wpaguiTab->setCurrentWidget(wpsTab);
915 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
916 if (strstr(pos, "(WSC)"))
917 wpsStatusText->setText(tr("Registration started"));
918 } else if (str_match(pos, WPS_EVENT_M2D)) {
919 wpsStatusText->setText(tr("Registrar does not yet know PIN"));
920 } else if (str_match(pos, WPS_EVENT_FAIL)) {
921 wpsStatusText->setText(tr("Registration failed"));
922 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
923 wpsStatusText->setText(tr("Registration succeeded"));
928 void WpaGui::processCtrlReq(const char *req)
934 udr = new UserDataRequest();
937 if (udr->setParams(this, req) < 0) {
947 void WpaGui::receiveMsgs()
952 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
953 len = sizeof(buf) - 1;
954 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
962 void WpaGui::connectB()
965 size_t reply_len = sizeof(reply);
966 ctrlRequest("REASSOCIATE", reply, &reply_len);
970 void WpaGui::selectNetwork( const QString &sel )
974 size_t reply_len = sizeof(reply);
976 if (cmd.contains(QRegExp("^\\d+:")))
977 cmd.truncate(cmd.indexOf(':'));
980 cmd.prepend("SELECT_NETWORK ");
981 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
987 void WpaGui::enableNetwork(const QString &sel)
991 size_t reply_len = sizeof(reply);
993 if (cmd.contains(QRegExp("^\\d+:")))
994 cmd.truncate(cmd.indexOf(':'));
995 else if (!cmd.startsWith("all")) {
996 printf("Invalid editNetwork '%s'\n",
997 cmd.toAscii().constData());
1000 cmd.prepend("ENABLE_NETWORK ");
1001 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1006 void WpaGui::disableNetwork(const QString &sel)
1010 size_t reply_len = sizeof(reply);
1012 if (cmd.contains(QRegExp("^\\d+:")))
1013 cmd.truncate(cmd.indexOf(':'));
1014 else if (!cmd.startsWith("all")) {
1015 printf("Invalid editNetwork '%s'\n",
1016 cmd.toAscii().constData());
1019 cmd.prepend("DISABLE_NETWORK ");
1020 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1025 void WpaGui::editNetwork(const QString &sel)
1030 if (cmd.contains(QRegExp("^\\d+:"))) {
1031 cmd.truncate(cmd.indexOf(':'));
1035 NetworkConfig *nc = new NetworkConfig();
1038 nc->setWpaGui(this);
1041 nc->paramsFromConfig(id);
1050 void WpaGui::editSelectedNetwork()
1052 if (networkSelect->count() < 1) {
1053 QMessageBox::information(
1054 this, tr("No Networks"),
1055 tr("There are no networks to edit.\n"));
1058 QString sel(networkSelect->currentText());
1063 void WpaGui::editListedNetwork()
1065 if (networkList->currentRow() < 0) {
1066 QMessageBox::information(this, tr("Select A Network"),
1067 tr("Select a network from the list to"
1071 QString sel(networkList->currentItem()->text());
1076 void WpaGui::triggerUpdate()
1079 networkMayHaveChanged = true;
1084 void WpaGui::addNetwork()
1086 NetworkConfig *nc = new NetworkConfig();
1089 nc->setWpaGui(this);
1096 void WpaGui::removeNetwork(const QString &sel)
1100 size_t reply_len = sizeof(reply);
1102 if (cmd.contains(QRegExp("^\\d+:")))
1103 cmd.truncate(cmd.indexOf(':'));
1104 else if (!cmd.startsWith("all")) {
1105 printf("Invalid editNetwork '%s'\n",
1106 cmd.toAscii().constData());
1109 cmd.prepend("REMOVE_NETWORK ");
1110 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1115 void WpaGui::removeSelectedNetwork()
1117 if (networkSelect->count() < 1) {
1118 QMessageBox::information(this, tr("No Networks"),
1119 tr("There are no networks to remove."
1123 QString sel(networkSelect->currentText());
1128 void WpaGui::removeListedNetwork()
1130 if (networkList->currentRow() < 0) {
1131 QMessageBox::information(this, tr("Select A Network"),
1132 tr("Select a network from the list "
1133 "to remove it.\n"));
1136 QString sel(networkList->currentItem()->text());
1141 void WpaGui::enableAllNetworks()
1148 void WpaGui::disableAllNetworks()
1151 disableNetwork(sel);
1155 void WpaGui::removeAllNetworks()
1162 int WpaGui::getNetworkDisabled(const QString &sel)
1166 size_t reply_len = sizeof(reply) - 1;
1167 int pos = cmd.indexOf(':');
1169 printf("Invalid getNetworkDisabled '%s'\n",
1170 cmd.toAscii().constData());
1174 cmd.prepend("GET_NETWORK ");
1175 cmd.append(" disabled");
1177 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1178 && reply_len >= 1) {
1179 reply[reply_len] = '\0';
1180 if (!str_match(reply, "FAIL"))
1188 void WpaGui::updateNetworkDisabledStatus()
1190 if (networkList->currentRow() < 0)
1193 QString sel(networkList->currentItem()->text());
1195 switch (getNetworkDisabled(sel)) {
1197 if (!enableRadioButton->isChecked())
1198 enableRadioButton->setChecked(true);
1201 if (!disableRadioButton->isChecked())
1202 disableRadioButton->setChecked(true);
1208 void WpaGui::enableListedNetwork(bool enabled)
1210 if (networkList->currentRow() < 0 || !enabled)
1213 QString sel(networkList->currentItem()->text());
1215 if (getNetworkDisabled(sel) == 1)
1220 void WpaGui::disableListedNetwork(bool disabled)
1222 if (networkList->currentRow() < 0 || !disabled)
1225 QString sel(networkList->currentItem()->text());
1227 if (getNetworkDisabled(sel) == 0)
1228 disableNetwork(sel);
1232 void WpaGui::saveConfig()
1237 len = sizeof(buf) - 1;
1238 ctrlRequest("SAVE_CONFIG", buf, &len);
1242 if (str_match(buf, "FAIL"))
1243 QMessageBox::warning(
1244 this, tr("Failed to save configuration"),
1245 tr("The configuration could not be saved.\n"
1247 "The update_config=1 configuration option\n"
1248 "must be used for configuration saving to\n"
1249 "be permitted.\n"));
1251 QMessageBox::information(
1252 this, tr("Saved configuration"),
1253 tr("The current configuration was saved."
1258 void WpaGui::selectAdapter( const QString & sel )
1260 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1261 printf("Failed to open control connection to "
1262 "wpa_supplicant.\n");
1268 void WpaGui::createTrayIcon(bool trayOnly)
1270 QApplication::setQuitOnLastWindowClosed(false);
1272 tray_icon = new QSystemTrayIcon(this);
1273 tray_icon->setToolTip(qAppName() + tr(" - wpa_supplicant user interface"));
1274 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1275 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1277 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1280 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1281 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1283 ackTrayIcon = false;
1285 tray_menu = new QMenu(this);
1287 disconnectAction = new QAction(tr("&Disconnect"), this);
1288 reconnectAction = new QAction(tr("Re&connect"), this);
1289 connect(disconnectAction, SIGNAL(triggered()), this,
1290 SLOT(disconnect()));
1291 connect(reconnectAction, SIGNAL(triggered()), this,
1293 tray_menu->addAction(disconnectAction);
1294 tray_menu->addAction(reconnectAction);
1295 tray_menu->addSeparator();
1297 eventAction = new QAction(tr("&Event History"), this);
1298 scanAction = new QAction(tr("Scan &Results"), this);
1299 statAction = new QAction(tr("S&tatus"), this);
1300 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1301 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1302 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1303 tray_menu->addAction(eventAction);
1304 tray_menu->addAction(scanAction);
1305 tray_menu->addAction(statAction);
1306 tray_menu->addSeparator();
1308 showAction = new QAction(tr("&Show Window"), this);
1309 hideAction = new QAction(tr("&Hide Window"), this);
1310 quitAction = new QAction(tr("&Quit"), this);
1311 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1312 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1313 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1314 tray_menu->addAction(showAction);
1315 tray_menu->addAction(hideAction);
1316 tray_menu->addSeparator();
1317 tray_menu->addAction(quitAction);
1319 tray_icon->setContextMenu(tray_menu);
1329 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1330 const QString & msg)
1332 if (!QSystemTrayIcon::supportsMessages())
1335 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1338 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1342 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1345 /* use close() here instead of hide() and allow the
1346 * custom closeEvent handler take care of children */
1347 case QSystemTrayIcon::Trigger:
1357 case QSystemTrayIcon::MiddleClick:
1366 void WpaGui::showTrayStatus()
1371 len = sizeof(buf) - 1;
1372 if (ctrlRequest("STATUS", buf, &len) < 0)
1376 QString msg, status(buf);
1378 QStringList lines = status.split(QRegExp("\\n"));
1379 for (QStringList::Iterator it = lines.begin();
1380 it != lines.end(); it++) {
1381 int pos = (*it).indexOf('=') + 1;
1385 if ((*it).startsWith("bssid="))
1386 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1387 else if ((*it).startsWith("ssid="))
1388 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1389 else if ((*it).startsWith("pairwise_cipher="))
1390 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1391 else if ((*it).startsWith("group_cipher="))
1392 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1393 else if ((*it).startsWith("key_mgmt="))
1394 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1395 else if ((*it).startsWith("wpa_state="))
1396 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1397 else if ((*it).startsWith("ip_address="))
1398 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1399 else if ((*it).startsWith("Supplicant PAE state="))
1400 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1401 else if ((*it).startsWith("EAP state="))
1402 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1406 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1410 void WpaGui::closeEvent(QCloseEvent *event)
1436 if (tray_icon && !ackTrayIcon) {
1437 /* give user a visual hint that the tray icon exists */
1438 if (QSystemTrayIcon::supportsMessages()) {
1440 showTrayMessage(QSystemTrayIcon::Information, 3,
1442 tr(" will keep running in "
1443 "the system tray."));
1445 QMessageBox::information(this, qAppName() +
1447 tr("The program will keep "
1448 "running in the system "
1458 void WpaGui::wpsDialog()
1460 wpaguiTab->setCurrentWidget(wpsTab);
1464 void WpaGui::peersDialog()
1471 peers = new Peers();
1474 peers->setWpaGui(this);
1480 void WpaGui::tabChanged(int index)
1488 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1489 if (bssFromScan.isEmpty())
1490 wpsApPinButton->setEnabled(false);
1494 void WpaGui::wpsPbc()
1497 size_t reply_len = sizeof(reply);
1499 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1502 wpsPinEdit->setEnabled(false);
1503 if (wpsStatusText->text().compare(tr("WPS AP in active PBC mode found"))) {
1504 wpsInstructions->setText(tr("Press the push button on the AP to "
1505 "start the PBC mode."));
1507 wpsInstructions->setText(tr("If you have not yet done so, press "
1508 "the push button on the AP to start "
1511 wpsStatusText->setText(tr("Waiting for Registrar"));
1516 void WpaGui::wpsGeneratePin()
1519 size_t reply_len = sizeof(reply) - 1;
1521 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1524 reply[reply_len] = '\0';
1526 wpsPinEdit->setText(reply);
1527 wpsPinEdit->setEnabled(true);
1528 wpsInstructions->setText(tr("Enter the generated PIN into the Registrar "
1529 "(either the internal one in the AP or an "
1531 wpsStatusText->setText(tr("Waiting for Registrar"));
1536 void WpaGui::setBssFromScan(const QString &bssid)
1538 bssFromScan = bssid;
1539 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1540 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1541 wpsStatusText->setText(tr("WPS AP selected from scan results"));
1542 wpsInstructions->setText(tr("If you want to use an AP device PIN, e.g., "
1543 "from a label in the device, enter the eight "
1544 "digit AP PIN and click Use AP PIN button."));
1548 void WpaGui::wpsApPinChanged(const QString &text)
1550 wpsApPinButton->setEnabled(text.length() == 8);
1554 void WpaGui::wpsApPin()
1557 size_t reply_len = sizeof(reply);
1559 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1560 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1563 wpsStatusText->setText(tr("Waiting for AP/Enrollee"));
1568 void WpaGui::stopWpsRun(bool success)
1571 wpsStatusText->setText(success ? tr("Connected to the network") :
1574 wpsStatusText->setText("");
1575 wpsPinEdit->setEnabled(false);
1576 wpsInstructions->setText("");
1579 wpsApPinEdit->setEnabled(false);
1580 wpsApPinButton->setEnabled(false);
1584 #ifdef CONFIG_NATIVE_WINDOWS
1587 #define WPASVC_NAME TEXT("wpasvc")
1590 class ErrorMsg : public QMessageBox {
1592 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1593 void showMsg(QString msg);
1598 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1599 QMessageBox(parent), err(last_err)
1601 setWindowTitle(tr("wpa_gui error"));
1602 setIcon(QMessageBox::Warning);
1605 void ErrorMsg::showMsg(QString msg)
1610 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1611 FORMAT_MESSAGE_FROM_SYSTEM,
1612 NULL, err, 0, (LPTSTR) (void *) &buf,
1614 QString msg = QString::fromWCharArray(buf);
1615 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1618 setInformativeText(QString("[%1]").arg(err));
1625 void WpaGui::startService()
1629 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1631 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1635 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1637 ErrorMsg(this).showMsg(tr("OpenService failed"));
1638 CloseServiceHandle(scm);
1642 if (!StartService(svc, 0, NULL)) {
1643 ErrorMsg(this).showMsg(tr("Failed to start wpa_supplicant "
1647 CloseServiceHandle(svc);
1648 CloseServiceHandle(scm);
1652 void WpaGui::stopService()
1655 SERVICE_STATUS status;
1657 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1659 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1663 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1665 ErrorMsg(this).showMsg(tr("OpenService failed"));
1666 CloseServiceHandle(scm);
1670 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1671 ErrorMsg(this).showMsg(tr("Failed to stop wpa_supplicant "
1675 CloseServiceHandle(svc);
1676 CloseServiceHandle(scm);
1680 bool WpaGui::serviceRunning()
1683 SERVICE_STATUS status;
1684 bool running = false;
1686 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1688 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1692 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1694 printf("OpenService failed: %d\n\n", (int) GetLastError());
1695 CloseServiceHandle(scm);
1699 if (QueryServiceStatus(svc, &status)) {
1700 if (status.dwCurrentState != SERVICE_STOPPED)
1704 CloseServiceHandle(svc);
1705 CloseServiceHandle(scm);
1710 #endif /* CONFIG_NATIVE_WINDOWS */
1713 void WpaGui::addInterface()
1719 add_iface = new AddInterface(this, this);
1725 #ifndef QT_NO_SESSIONMANAGER
1726 void WpaGui::saveState()
1728 QSettings settings("wpa_supplicant", "wpa_gui");
1729 settings.beginGroup("state");
1730 settings.setValue("session_id", app->sessionId());
1731 settings.setValue("in_tray", inTray);
1732 settings.endGroup();