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-2012,\n"
717 "Jouni Malinen <j@w1.fi>\n"
718 "and contributors.\n"
720 "This software may be distributed under\n"
721 "the terms of the BSD license.\n"
722 "See README for more details.\n"
724 "This product includes software developed\n"
725 "by the OpenSSL Project for use in the\n"
726 "OpenSSL Toolkit (http://www.openssl.org/)\n");
730 void WpaGui::disconnect()
733 size_t reply_len = sizeof(reply);
734 ctrlRequest("DISCONNECT", reply, &reply_len);
746 scanres = new ScanResults();
749 scanres->setWpaGui(this);
755 void WpaGui::eventHistory()
762 eh = new EventHistory();
776 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
778 * QSocketNotifier cannot be used with Windows named pipes, so use a
779 * timer to check for received messages for now. This could be
780 * optimized be doing something specific to named pipes or Windows
781 * events, but it is not clear what would be the best way of doing that
785 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
787 if (scanres && !scanres->isVisible()) {
792 if (eh && !eh->isVisible()) {
797 if (udr && !udr->isVisible()) {
802 len = sizeof(buf) - 1;
803 if (ctrlRequest("PING", buf, &len) < 0) {
804 printf("PING failed - trying to reconnect\n");
805 if (openCtrlConnection(ctrl_iface) >= 0) {
806 printf("Reconnected successfully\n");
807 pingsToStatusUpdate = 0;
811 pingsToStatusUpdate--;
812 if (pingsToStatusUpdate <= 0) {
817 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
818 /* Use less frequent pings and status updates when the main window is
819 * hidden (running in taskbar). */
820 int interval = isHidden() ? 5000 : 1000;
821 if (timer->interval() != interval)
822 timer->setInterval(interval);
823 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
827 static int str_match(const char *a, const char *b)
829 return strncmp(a, b, strlen(b)) == 0;
833 void WpaGui::processMsg(char *msg)
835 char *pos = msg, *pos2;
841 priority = atoi(pos);
842 pos = strchr(pos, '>');
849 WpaMsg wm(pos, priority);
853 peers->event_notify(wm);
855 while (msgs.count() > 100)
858 /* Update last message with truncated version of the event */
859 if (strncmp(pos, "CTRL-", 5) == 0) {
860 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
867 QString lastmsg = pos2;
868 lastmsg.truncate(40);
869 textLastMessage->setText(lastmsg);
871 pingsToStatusUpdate = 0;
872 networkMayHaveChanged = true;
874 if (str_match(pos, WPA_CTRL_REQ))
875 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
876 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
877 scanres->updateResults();
878 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
879 showTrayMessage(QSystemTrayIcon::Information, 3,
880 tr("Disconnected from network."));
881 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
882 showTrayMessage(QSystemTrayIcon::Information, 3,
883 tr("Connection to network established."));
884 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
886 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
887 wpsStatusText->setText(tr("WPS AP in active PBC mode found"));
888 if (textStatus->text() == "INACTIVE" ||
889 textStatus->text() == "DISCONNECTED")
890 wpaguiTab->setCurrentWidget(wpsTab);
891 wpsInstructions->setText(tr("Press the PBC button on the "
892 "screen to start registration"));
893 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
894 wpsStatusText->setText(tr("WPS AP with recently selected "
896 if (textStatus->text() == "INACTIVE" ||
897 textStatus->text() == "DISCONNECTED")
898 wpaguiTab->setCurrentWidget(wpsTab);
899 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_AUTH)) {
900 showTrayMessage(QSystemTrayIcon::Information, 3,
901 "Wi-Fi Protected Setup (WPS) AP\n"
902 "indicating this client is authorized.");
903 wpsStatusText->setText("WPS AP indicating this client is "
905 if (textStatus->text() == "INACTIVE" ||
906 textStatus->text() == "DISCONNECTED")
907 wpaguiTab->setCurrentWidget(wpsTab);
908 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
909 wpsStatusText->setText(tr("WPS AP detected"));
910 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
911 wpsStatusText->setText(tr("PBC mode overlap detected"));
912 wpsInstructions->setText(tr("More than one AP is currently in "
913 "active WPS PBC mode. Wait couple "
914 "of minutes and try again"));
915 wpaguiTab->setCurrentWidget(wpsTab);
916 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
917 wpsStatusText->setText(tr("Network configuration received"));
918 wpaguiTab->setCurrentWidget(wpsTab);
919 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
920 if (strstr(pos, "(WSC)"))
921 wpsStatusText->setText(tr("Registration started"));
922 } else if (str_match(pos, WPS_EVENT_M2D)) {
923 wpsStatusText->setText(tr("Registrar does not yet know PIN"));
924 } else if (str_match(pos, WPS_EVENT_FAIL)) {
925 wpsStatusText->setText(tr("Registration failed"));
926 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
927 wpsStatusText->setText(tr("Registration succeeded"));
932 void WpaGui::processCtrlReq(const char *req)
938 udr = new UserDataRequest();
941 if (udr->setParams(this, req) < 0) {
951 void WpaGui::receiveMsgs()
956 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
957 len = sizeof(buf) - 1;
958 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
966 void WpaGui::connectB()
969 size_t reply_len = sizeof(reply);
970 ctrlRequest("REASSOCIATE", reply, &reply_len);
974 void WpaGui::selectNetwork( const QString &sel )
978 size_t reply_len = sizeof(reply);
980 if (cmd.contains(QRegExp("^\\d+:")))
981 cmd.truncate(cmd.indexOf(':'));
984 cmd.prepend("SELECT_NETWORK ");
985 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
991 void WpaGui::enableNetwork(const QString &sel)
995 size_t reply_len = sizeof(reply);
997 if (cmd.contains(QRegExp("^\\d+:")))
998 cmd.truncate(cmd.indexOf(':'));
999 else if (!cmd.startsWith("all")) {
1000 printf("Invalid editNetwork '%s'\n",
1001 cmd.toAscii().constData());
1004 cmd.prepend("ENABLE_NETWORK ");
1005 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1010 void WpaGui::disableNetwork(const QString &sel)
1014 size_t reply_len = sizeof(reply);
1016 if (cmd.contains(QRegExp("^\\d+:")))
1017 cmd.truncate(cmd.indexOf(':'));
1018 else if (!cmd.startsWith("all")) {
1019 printf("Invalid editNetwork '%s'\n",
1020 cmd.toAscii().constData());
1023 cmd.prepend("DISABLE_NETWORK ");
1024 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1029 void WpaGui::editNetwork(const QString &sel)
1034 if (cmd.contains(QRegExp("^\\d+:"))) {
1035 cmd.truncate(cmd.indexOf(':'));
1039 NetworkConfig *nc = new NetworkConfig();
1042 nc->setWpaGui(this);
1045 nc->paramsFromConfig(id);
1054 void WpaGui::editSelectedNetwork()
1056 if (networkSelect->count() < 1) {
1057 QMessageBox::information(
1058 this, tr("No Networks"),
1059 tr("There are no networks to edit.\n"));
1062 QString sel(networkSelect->currentText());
1067 void WpaGui::editListedNetwork()
1069 if (networkList->currentRow() < 0) {
1070 QMessageBox::information(this, tr("Select A Network"),
1071 tr("Select a network from the list to"
1075 QString sel(networkList->currentItem()->text());
1080 void WpaGui::triggerUpdate()
1083 networkMayHaveChanged = true;
1088 void WpaGui::addNetwork()
1090 NetworkConfig *nc = new NetworkConfig();
1093 nc->setWpaGui(this);
1100 void WpaGui::removeNetwork(const QString &sel)
1104 size_t reply_len = sizeof(reply);
1106 if (cmd.contains(QRegExp("^\\d+:")))
1107 cmd.truncate(cmd.indexOf(':'));
1108 else if (!cmd.startsWith("all")) {
1109 printf("Invalid editNetwork '%s'\n",
1110 cmd.toAscii().constData());
1113 cmd.prepend("REMOVE_NETWORK ");
1114 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1119 void WpaGui::removeSelectedNetwork()
1121 if (networkSelect->count() < 1) {
1122 QMessageBox::information(this, tr("No Networks"),
1123 tr("There are no networks to remove."
1127 QString sel(networkSelect->currentText());
1132 void WpaGui::removeListedNetwork()
1134 if (networkList->currentRow() < 0) {
1135 QMessageBox::information(this, tr("Select A Network"),
1136 tr("Select a network from the list "
1137 "to remove it.\n"));
1140 QString sel(networkList->currentItem()->text());
1145 void WpaGui::enableAllNetworks()
1152 void WpaGui::disableAllNetworks()
1155 disableNetwork(sel);
1159 void WpaGui::removeAllNetworks()
1166 int WpaGui::getNetworkDisabled(const QString &sel)
1170 size_t reply_len = sizeof(reply) - 1;
1171 int pos = cmd.indexOf(':');
1173 printf("Invalid getNetworkDisabled '%s'\n",
1174 cmd.toAscii().constData());
1178 cmd.prepend("GET_NETWORK ");
1179 cmd.append(" disabled");
1181 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1182 && reply_len >= 1) {
1183 reply[reply_len] = '\0';
1184 if (!str_match(reply, "FAIL"))
1192 void WpaGui::updateNetworkDisabledStatus()
1194 if (networkList->currentRow() < 0)
1197 QString sel(networkList->currentItem()->text());
1199 switch (getNetworkDisabled(sel)) {
1201 if (!enableRadioButton->isChecked())
1202 enableRadioButton->setChecked(true);
1205 if (!disableRadioButton->isChecked())
1206 disableRadioButton->setChecked(true);
1212 void WpaGui::enableListedNetwork(bool enabled)
1214 if (networkList->currentRow() < 0 || !enabled)
1217 QString sel(networkList->currentItem()->text());
1219 if (getNetworkDisabled(sel) == 1)
1224 void WpaGui::disableListedNetwork(bool disabled)
1226 if (networkList->currentRow() < 0 || !disabled)
1229 QString sel(networkList->currentItem()->text());
1231 if (getNetworkDisabled(sel) == 0)
1232 disableNetwork(sel);
1236 void WpaGui::saveConfig()
1241 len = sizeof(buf) - 1;
1242 ctrlRequest("SAVE_CONFIG", buf, &len);
1246 if (str_match(buf, "FAIL"))
1247 QMessageBox::warning(
1248 this, tr("Failed to save configuration"),
1249 tr("The configuration could not be saved.\n"
1251 "The update_config=1 configuration option\n"
1252 "must be used for configuration saving to\n"
1253 "be permitted.\n"));
1255 QMessageBox::information(
1256 this, tr("Saved configuration"),
1257 tr("The current configuration was saved."
1262 void WpaGui::selectAdapter( const QString & sel )
1264 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1265 printf("Failed to open control connection to "
1266 "wpa_supplicant.\n");
1272 void WpaGui::createTrayIcon(bool trayOnly)
1274 QApplication::setQuitOnLastWindowClosed(false);
1276 tray_icon = new QSystemTrayIcon(this);
1277 tray_icon->setToolTip(qAppName() + tr(" - wpa_supplicant user interface"));
1278 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1279 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1281 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1284 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1285 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1287 ackTrayIcon = false;
1289 tray_menu = new QMenu(this);
1291 disconnectAction = new QAction(tr("&Disconnect"), this);
1292 reconnectAction = new QAction(tr("Re&connect"), this);
1293 connect(disconnectAction, SIGNAL(triggered()), this,
1294 SLOT(disconnect()));
1295 connect(reconnectAction, SIGNAL(triggered()), this,
1297 tray_menu->addAction(disconnectAction);
1298 tray_menu->addAction(reconnectAction);
1299 tray_menu->addSeparator();
1301 eventAction = new QAction(tr("&Event History"), this);
1302 scanAction = new QAction(tr("Scan &Results"), this);
1303 statAction = new QAction(tr("S&tatus"), this);
1304 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1305 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1306 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1307 tray_menu->addAction(eventAction);
1308 tray_menu->addAction(scanAction);
1309 tray_menu->addAction(statAction);
1310 tray_menu->addSeparator();
1312 showAction = new QAction(tr("&Show Window"), this);
1313 hideAction = new QAction(tr("&Hide Window"), this);
1314 quitAction = new QAction(tr("&Quit"), this);
1315 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1316 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1317 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1318 tray_menu->addAction(showAction);
1319 tray_menu->addAction(hideAction);
1320 tray_menu->addSeparator();
1321 tray_menu->addAction(quitAction);
1323 tray_icon->setContextMenu(tray_menu);
1333 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1334 const QString & msg)
1336 if (!QSystemTrayIcon::supportsMessages())
1339 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1342 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1346 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1349 /* use close() here instead of hide() and allow the
1350 * custom closeEvent handler take care of children */
1351 case QSystemTrayIcon::Trigger:
1361 case QSystemTrayIcon::MiddleClick:
1370 void WpaGui::showTrayStatus()
1375 len = sizeof(buf) - 1;
1376 if (ctrlRequest("STATUS", buf, &len) < 0)
1380 QString msg, status(buf);
1382 QStringList lines = status.split(QRegExp("\\n"));
1383 for (QStringList::Iterator it = lines.begin();
1384 it != lines.end(); it++) {
1385 int pos = (*it).indexOf('=') + 1;
1389 if ((*it).startsWith("bssid="))
1390 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1391 else if ((*it).startsWith("ssid="))
1392 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1393 else if ((*it).startsWith("pairwise_cipher="))
1394 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1395 else if ((*it).startsWith("group_cipher="))
1396 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1397 else if ((*it).startsWith("key_mgmt="))
1398 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1399 else if ((*it).startsWith("wpa_state="))
1400 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1401 else if ((*it).startsWith("ip_address="))
1402 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1403 else if ((*it).startsWith("Supplicant PAE state="))
1404 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1405 else if ((*it).startsWith("EAP state="))
1406 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1410 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1414 void WpaGui::closeEvent(QCloseEvent *event)
1440 if (tray_icon && !ackTrayIcon) {
1441 /* give user a visual hint that the tray icon exists */
1442 if (QSystemTrayIcon::supportsMessages()) {
1444 showTrayMessage(QSystemTrayIcon::Information, 3,
1446 tr(" will keep running in "
1447 "the system tray."));
1449 QMessageBox::information(this, qAppName() +
1451 tr("The program will keep "
1452 "running in the system "
1462 void WpaGui::wpsDialog()
1464 wpaguiTab->setCurrentWidget(wpsTab);
1468 void WpaGui::peersDialog()
1475 peers = new Peers();
1478 peers->setWpaGui(this);
1484 void WpaGui::tabChanged(int index)
1492 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1493 if (bssFromScan.isEmpty())
1494 wpsApPinButton->setEnabled(false);
1498 void WpaGui::wpsPbc()
1501 size_t reply_len = sizeof(reply);
1503 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1506 wpsPinEdit->setEnabled(false);
1507 if (wpsStatusText->text().compare(tr("WPS AP in active PBC mode found"))) {
1508 wpsInstructions->setText(tr("Press the push button on the AP to "
1509 "start the PBC mode."));
1511 wpsInstructions->setText(tr("If you have not yet done so, press "
1512 "the push button on the AP to start "
1515 wpsStatusText->setText(tr("Waiting for Registrar"));
1520 void WpaGui::wpsGeneratePin()
1523 size_t reply_len = sizeof(reply) - 1;
1525 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1528 reply[reply_len] = '\0';
1530 wpsPinEdit->setText(reply);
1531 wpsPinEdit->setEnabled(true);
1532 wpsInstructions->setText(tr("Enter the generated PIN into the Registrar "
1533 "(either the internal one in the AP or an "
1535 wpsStatusText->setText(tr("Waiting for Registrar"));
1540 void WpaGui::setBssFromScan(const QString &bssid)
1542 bssFromScan = bssid;
1543 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1544 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1545 wpsStatusText->setText(tr("WPS AP selected from scan results"));
1546 wpsInstructions->setText(tr("If you want to use an AP device PIN, e.g., "
1547 "from a label in the device, enter the eight "
1548 "digit AP PIN and click Use AP PIN button."));
1552 void WpaGui::wpsApPinChanged(const QString &text)
1554 wpsApPinButton->setEnabled(text.length() == 8);
1558 void WpaGui::wpsApPin()
1561 size_t reply_len = sizeof(reply);
1563 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1564 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1567 wpsStatusText->setText(tr("Waiting for AP/Enrollee"));
1572 void WpaGui::stopWpsRun(bool success)
1575 wpsStatusText->setText(success ? tr("Connected to the network") :
1578 wpsStatusText->setText("");
1579 wpsPinEdit->setEnabled(false);
1580 wpsInstructions->setText("");
1583 wpsApPinEdit->setEnabled(false);
1584 wpsApPinButton->setEnabled(false);
1588 #ifdef CONFIG_NATIVE_WINDOWS
1591 #define WPASVC_NAME TEXT("wpasvc")
1594 class ErrorMsg : public QMessageBox {
1596 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1597 void showMsg(QString msg);
1602 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1603 QMessageBox(parent), err(last_err)
1605 setWindowTitle(tr("wpa_gui error"));
1606 setIcon(QMessageBox::Warning);
1609 void ErrorMsg::showMsg(QString msg)
1614 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1615 FORMAT_MESSAGE_FROM_SYSTEM,
1616 NULL, err, 0, (LPTSTR) (void *) &buf,
1618 QString msg = QString::fromWCharArray(buf);
1619 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1622 setInformativeText(QString("[%1]").arg(err));
1629 void WpaGui::startService()
1633 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1635 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1639 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1641 ErrorMsg(this).showMsg(tr("OpenService failed"));
1642 CloseServiceHandle(scm);
1646 if (!StartService(svc, 0, NULL)) {
1647 ErrorMsg(this).showMsg(tr("Failed to start wpa_supplicant "
1651 CloseServiceHandle(svc);
1652 CloseServiceHandle(scm);
1656 void WpaGui::stopService()
1659 SERVICE_STATUS status;
1661 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1663 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1667 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1669 ErrorMsg(this).showMsg(tr("OpenService failed"));
1670 CloseServiceHandle(scm);
1674 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1675 ErrorMsg(this).showMsg(tr("Failed to stop wpa_supplicant "
1679 CloseServiceHandle(svc);
1680 CloseServiceHandle(scm);
1684 bool WpaGui::serviceRunning()
1687 SERVICE_STATUS status;
1688 bool running = false;
1690 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1692 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1696 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1698 printf("OpenService failed: %d\n\n", (int) GetLastError());
1699 CloseServiceHandle(scm);
1703 if (QueryServiceStatus(svc, &status)) {
1704 if (status.dwCurrentState != SERVICE_STOPPED)
1708 CloseServiceHandle(svc);
1709 CloseServiceHandle(scm);
1714 #endif /* CONFIG_NATIVE_WINDOWS */
1717 void WpaGui::addInterface()
1723 add_iface = new AddInterface(this, this);
1729 #ifndef QT_NO_SESSIONMANAGER
1730 void WpaGui::saveState()
1732 QSettings settings("wpa_supplicant", "wpa_gui");
1733 settings.beginGroup("state");
1734 settings.setValue("session_id", app->sessionId());
1735 settings.setValue("in_tray", inTray);
1736 settings.endGroup();