2 * wpa_gui - WpaGui class
3 * Copyright (c) 2005-2010, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
16 /* Need to get getopt() */
20 #ifdef CONFIG_NATIVE_WINDOWS
22 #endif /* CONFIG_NATIVE_WINDOWS */
25 #include <QMessageBox>
26 #include <QCloseEvent>
27 #include <QImageReader>
32 #include "common/wpa_ctrl.h"
33 #include "userdatarequest.h"
34 #include "networkconfig.h"
38 #define printf wpagui_printf
39 static int wpagui_printf(const char *, ...)
45 WpaGui::WpaGui(QApplication *_app, QWidget *parent, const char *, Qt::WFlags)
46 : QMainWindow(parent), app(_app)
50 #ifdef CONFIG_NATIVE_WINDOWS
51 fileStopServiceAction = new QAction(this);
52 fileStopServiceAction->setObjectName("Stop Service");
53 fileStopServiceAction->setIconText(tr("Stop Service"));
54 fileMenu->insertAction(actionWPS, fileStopServiceAction);
56 fileStartServiceAction = new QAction(this);
57 fileStartServiceAction->setObjectName("Start Service");
58 fileStartServiceAction->setIconText(tr("Start Service"));
59 fileMenu->insertAction(fileStopServiceAction, fileStartServiceAction);
61 connect(fileStartServiceAction, SIGNAL(triggered()), this,
62 SLOT(startService()));
63 connect(fileStopServiceAction, SIGNAL(triggered()), this,
66 addInterfaceAction = new QAction(this);
67 addInterfaceAction->setIconText(tr("Add Interface"));
68 fileMenu->insertAction(fileStartServiceAction, addInterfaceAction);
70 connect(addInterfaceAction, SIGNAL(triggered()), this,
71 SLOT(addInterface()));
72 #endif /* CONFIG_NATIVE_WINDOWS */
77 * Disable WPS tab by default; it will be enabled if wpa_supplicant is
78 * built with WPS support.
80 wpsTab->setEnabled(false);
81 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), false);
83 connect(fileEventHistoryAction, SIGNAL(triggered()), this,
84 SLOT(eventHistory()));
85 connect(fileSaveConfigAction, SIGNAL(triggered()), this,
87 connect(actionWPS, SIGNAL(triggered()), this, SLOT(wpsDialog()));
88 connect(actionPeers, SIGNAL(triggered()), this, SLOT(peersDialog()));
89 connect(fileExitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
90 connect(networkAddAction, SIGNAL(triggered()), this,
92 connect(networkEditAction, SIGNAL(triggered()), this,
93 SLOT(editSelectedNetwork()));
94 connect(networkRemoveAction, SIGNAL(triggered()), this,
95 SLOT(removeSelectedNetwork()));
96 connect(networkEnableAllAction, SIGNAL(triggered()), this,
97 SLOT(enableAllNetworks()));
98 connect(networkDisableAllAction, SIGNAL(triggered()), this,
99 SLOT(disableAllNetworks()));
100 connect(networkRemoveAllAction, SIGNAL(triggered()), this,
101 SLOT(removeAllNetworks()));
102 connect(helpIndexAction, SIGNAL(triggered()), this, SLOT(helpIndex()));
103 connect(helpContentsAction, SIGNAL(triggered()), this,
104 SLOT(helpContents()));
105 connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(helpAbout()));
106 connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));
107 connect(scanButton, SIGNAL(clicked()), this, SLOT(scan()));
108 connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB()));
109 connect(adapterSelect, SIGNAL(activated(const QString&)), this,
110 SLOT(selectAdapter(const QString&)));
111 connect(networkSelect, SIGNAL(activated(const QString&)), this,
112 SLOT(selectNetwork(const QString&)));
113 connect(addNetworkButton, SIGNAL(clicked()), this, SLOT(addNetwork()));
114 connect(editNetworkButton, SIGNAL(clicked()), this,
115 SLOT(editListedNetwork()));
116 connect(removeNetworkButton, SIGNAL(clicked()), this,
117 SLOT(removeListedNetwork()));
118 connect(networkList, SIGNAL(itemSelectionChanged()), this,
119 SLOT(updateNetworkDisabledStatus()));
120 connect(enableRadioButton, SIGNAL(toggled(bool)), this,
121 SLOT(enableListedNetwork(bool)));
122 connect(disableRadioButton, SIGNAL(toggled(bool)), this,
123 SLOT(disableListedNetwork(bool)));
124 connect(scanNetworkButton, SIGNAL(clicked()), this, SLOT(scan()));
125 connect(networkList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
126 this, SLOT(editListedNetwork()));
127 connect(wpaguiTab, SIGNAL(currentChanged(int)), this,
128 SLOT(tabChanged(int)));
129 connect(wpsPbcButton, SIGNAL(clicked()), this, SLOT(wpsPbc()));
130 connect(wpsPinButton, SIGNAL(clicked()), this, SLOT(wpsGeneratePin()));
131 connect(wpsApPinEdit, SIGNAL(textChanged(const QString &)), this,
132 SLOT(wpsApPinChanged(const QString &)));
133 connect(wpsApPinButton, SIGNAL(clicked()), this, SLOT(wpsApPin()));
146 ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
150 #ifndef QT_NO_SESSIONMANAGER
151 if (app->isSessionRestored()) {
152 QSettings settings("wpa_supplicant", "wpa_gui");
153 settings.beginGroup("state");
154 if (app->sessionId().compare(settings.value("session_id").
156 startInTray = settings.value("in_tray").toBool();
161 if (QSystemTrayIcon::isSystemTrayAvailable())
162 createTrayIcon(startInTray);
166 connectedToService = false;
167 textStatus->setText(tr("connecting to wpa_supplicant"));
168 timer = new QTimer(this);
169 connect(timer, SIGNAL(timeout()), SLOT(ping()));
170 timer->setSingleShot(FALSE);
173 if (openCtrlConnection(ctrl_iface) < 0) {
174 printf("Failed to open control connection to "
175 "wpa_supplicant.\n");
179 networkMayHaveChanged = true;
189 wpa_ctrl_detach(monitor_conn);
190 wpa_ctrl_close(monitor_conn);
194 wpa_ctrl_close(ctrl_conn);
231 free(ctrl_iface_dir);
232 ctrl_iface_dir = NULL;
236 void WpaGui::languageChange()
242 void WpaGui::parse_argv()
246 c = getopt(qApp->argc(), qApp->argv(), "i:p:t");
252 ctrl_iface = strdup(optarg);
255 free(ctrl_iface_dir);
256 ctrl_iface_dir = strdup(optarg);
266 int WpaGui::openCtrlConnection(const char *ifname)
270 char buf[2048], *pos, *pos2;
274 if (ifname != ctrl_iface) {
276 ctrl_iface = strdup(ifname);
279 #ifdef CONFIG_CTRL_IFACE_UDP
281 ctrl_iface = strdup("udp");
282 #endif /* CONFIG_CTRL_IFACE_UDP */
283 #ifdef CONFIG_CTRL_IFACE_UNIX
285 DIR *dir = opendir(ctrl_iface_dir);
289 while ((dent = readdir(dir))) {
290 #ifdef _DIRENT_HAVE_D_TYPE
291 /* Skip the file if it is not a socket.
292 * Also accept DT_UNKNOWN (0) in case
293 * the C library or underlying file
294 * system does not support d_type. */
295 if (dent->d_type != DT_SOCK &&
296 dent->d_type != DT_UNKNOWN)
298 #endif /* _DIRENT_HAVE_D_TYPE */
300 if (strcmp(dent->d_name, ".") == 0 ||
301 strcmp(dent->d_name, "..") == 0)
303 printf("Selected interface '%s'\n",
305 ctrl_iface = strdup(dent->d_name);
310 #endif /* CONFIG_CTRL_IFACE_UNIX */
311 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
312 struct wpa_ctrl *ctrl;
318 ctrl = wpa_ctrl_open(NULL);
320 len = sizeof(buf) - 1;
321 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf,
324 connectedToService = true;
326 pos = strchr(buf, '\n');
329 ctrl_iface = strdup(buf);
331 wpa_ctrl_close(ctrl);
333 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
336 if (ctrl_iface == NULL) {
337 #ifdef CONFIG_NATIVE_WINDOWS
338 static bool first = true;
339 if (first && !serviceRunning()) {
341 if (QMessageBox::warning(
343 tr("wpa_supplicant service is not "
345 "Do you want to start it?"),
346 QMessageBox::Yes | QMessageBox::No) ==
350 #endif /* CONFIG_NATIVE_WINDOWS */
354 #ifdef CONFIG_CTRL_IFACE_UNIX
355 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
356 cfile = (char *) malloc(flen);
359 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
360 #else /* CONFIG_CTRL_IFACE_UNIX */
361 flen = strlen(ctrl_iface) + 1;
362 cfile = (char *) malloc(flen);
365 snprintf(cfile, flen, "%s", ctrl_iface);
366 #endif /* CONFIG_CTRL_IFACE_UNIX */
369 wpa_ctrl_close(ctrl_conn);
376 wpa_ctrl_detach(monitor_conn);
377 wpa_ctrl_close(monitor_conn);
381 printf("Trying to connect to '%s'\n", cfile);
382 ctrl_conn = wpa_ctrl_open(cfile);
383 if (ctrl_conn == NULL) {
387 monitor_conn = wpa_ctrl_open(cfile);
389 if (monitor_conn == NULL) {
390 wpa_ctrl_close(ctrl_conn);
393 if (wpa_ctrl_attach(monitor_conn)) {
394 printf("Failed to attach to wpa_supplicant\n");
395 wpa_ctrl_close(monitor_conn);
397 wpa_ctrl_close(ctrl_conn);
402 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
403 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
404 QSocketNotifier::Read, this);
405 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
408 adapterSelect->clear();
409 adapterSelect->addItem(ctrl_iface);
410 adapterSelect->setCurrentIndex(0);
412 len = sizeof(buf) - 1;
413 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
418 pos2 = strchr(pos, '\n');
421 if (strcmp(pos, ctrl_iface) != 0)
422 adapterSelect->addItem(pos);
430 len = sizeof(buf) - 1;
431 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len,
436 QStringList types = res.split(QChar(' '));
437 bool wps = types.contains("WSC");
438 actionWPS->setEnabled(wps);
439 wpsTab->setEnabled(wps);
440 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), wps);
447 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
451 if (ctrl_conn == NULL)
453 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen, NULL);
455 printf("'%s' command timed out.\n", cmd);
457 printf("'%s' command failed.\n", cmd);
463 QString WpaGui::wpaStateTranslate(char *state)
465 if (!strcmp(state, "DISCONNECTED"))
466 return tr("Disconnected");
467 else if (!strcmp(state, "INACTIVE"))
468 return tr("Inactive");
469 else if (!strcmp(state, "SCANNING"))
470 return tr("Scanning");
471 else if (!strcmp(state, "AUTHENTICATING"))
472 return tr("Authenticating");
473 else if (!strcmp(state, "ASSOCIATING"))
474 return tr("Associating");
475 else if (!strcmp(state, "ASSOCIATED"))
476 return tr("Associated");
477 else if (!strcmp(state, "4WAY_HANDSHAKE"))
478 return tr("4-Way Handshake");
479 else if (!strcmp(state, "GROUP_HANDSHAKE"))
480 return tr("Group Handshake");
481 else if (!strcmp(state, "COMPLETED"))
482 return tr("Completed");
484 return tr("Unknown");
488 void WpaGui::updateStatus()
490 char buf[2048], *start, *end, *pos;
493 pingsToStatusUpdate = 10;
495 len = sizeof(buf) - 1;
496 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
497 textStatus->setText(tr("Could not get status from "
499 textAuthentication->clear();
500 textEncryption->clear();
503 textIpAddress->clear();
505 #ifdef CONFIG_NATIVE_WINDOWS
506 static bool first = true;
507 if (first && connectedToService &&
508 (ctrl_iface == NULL || *ctrl_iface == '\0')) {
510 if (QMessageBox::information(
512 tr("No network interfaces in use.\n"
513 "Would you like to add one?"),
514 QMessageBox::Yes | QMessageBox::No) ==
518 #endif /* CONFIG_NATIVE_WINDOWS */
524 bool auth_updated = false, ssid_updated = false;
525 bool bssid_updated = false, ipaddr_updated = false;
526 bool status_updated = false;
527 char *pairwise_cipher = NULL, *group_cipher = NULL;
533 end = strchr(start, '\n');
537 while (end[0] && end[1])
542 pos = strchr(start, '=');
545 if (strcmp(start, "bssid") == 0) {
546 bssid_updated = true;
547 textBssid->setText(pos);
548 } else if (strcmp(start, "ssid") == 0) {
550 textSsid->setText(pos);
551 } else if (strcmp(start, "ip_address") == 0) {
552 ipaddr_updated = true;
553 textIpAddress->setText(pos);
554 } else if (strcmp(start, "wpa_state") == 0) {
555 status_updated = true;
556 textStatus->setText(wpaStateTranslate(pos));
557 } else if (strcmp(start, "key_mgmt") == 0) {
559 textAuthentication->setText(pos);
560 /* TODO: could add EAP status to this */
561 } else if (strcmp(start, "pairwise_cipher") == 0) {
562 pairwise_cipher = pos;
563 } else if (strcmp(start, "group_cipher") == 0) {
565 } else if (strcmp(start, "mode") == 0) {
574 if (status_updated && mode)
575 textStatus->setText(textStatus->text() + " (" + mode + ")");
577 if (pairwise_cipher || group_cipher) {
579 if (pairwise_cipher && group_cipher &&
580 strcmp(pairwise_cipher, group_cipher) != 0) {
581 encr.append(pairwise_cipher);
583 encr.append(group_cipher);
584 } else if (pairwise_cipher) {
585 encr.append(pairwise_cipher);
587 encr.append(group_cipher);
588 encr.append(" [group key only]");
590 textEncryption->setText(encr);
592 textEncryption->clear();
597 textAuthentication->clear();
603 textIpAddress->clear();
607 void WpaGui::updateNetworks()
609 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
611 int first_active = -1;
612 int was_selected = -1;
613 bool current = false;
615 if (!networkMayHaveChanged)
618 if (networkList->currentRow() >= 0)
619 was_selected = networkList->currentRow();
621 networkSelect->clear();
622 networkList->clear();
624 if (ctrl_conn == NULL)
627 len = sizeof(buf) - 1;
628 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
632 start = strchr(buf, '\n');
639 end = strchr(start, '\n');
643 while (end[0] && end[1])
649 ssid = strchr(id, '\t');
653 bssid = strchr(ssid, '\t');
657 flags = strchr(bssid, '\t');
662 if (strstr(flags, "[DISABLED][P2P-PERSISTENT]")) {
670 network.append(": ");
671 network.append(ssid);
672 networkSelect->addItem(network);
673 networkList->addItem(network);
675 if (strstr(flags, "[CURRENT]")) {
676 networkSelect->setCurrentIndex(networkSelect->count() -
679 } else if (first_active < 0 &&
680 strstr(flags, "[DISABLED]") == NULL)
681 first_active = networkSelect->count() - 1;
688 if (networkSelect->count() > 1)
689 networkSelect->addItem(tr("Select any network"));
691 if (!current && first_active >= 0)
692 networkSelect->setCurrentIndex(first_active);
694 if (was_selected >= 0 && networkList->count() > 0) {
695 if (was_selected < networkList->count())
696 networkList->setCurrentRow(was_selected);
698 networkList->setCurrentRow(networkList->count() - 1);
701 networkList->setCurrentRow(networkSelect->currentIndex());
703 networkMayHaveChanged = false;
707 void WpaGui::helpIndex()
709 printf("helpIndex\n");
713 void WpaGui::helpContents()
715 printf("helpContents\n");
719 void WpaGui::helpAbout()
721 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
722 "Copyright (c) 2003-2010,\n"
723 "Jouni Malinen <j@w1.fi>\n"
724 "and contributors.\n"
726 "This program is free software. You can\n"
727 "distribute it and/or modify it under the terms "
729 "the GNU General Public License version 2.\n"
731 "Alternatively, this software may be distributed\n"
732 "under the terms of the BSD license.\n"
734 "This product includes software developed\n"
735 "by the OpenSSL Project for use in the\n"
736 "OpenSSL Toolkit (http://www.openssl.org/)\n");
740 void WpaGui::disconnect()
743 size_t reply_len = sizeof(reply);
744 ctrlRequest("DISCONNECT", reply, &reply_len);
756 scanres = new ScanResults();
759 scanres->setWpaGui(this);
765 void WpaGui::eventHistory()
772 eh = new EventHistory();
786 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
788 * QSocketNotifier cannot be used with Windows named pipes, so use a
789 * timer to check for received messages for now. This could be
790 * optimized be doing something specific to named pipes or Windows
791 * events, but it is not clear what would be the best way of doing that
795 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
797 if (scanres && !scanres->isVisible()) {
802 if (eh && !eh->isVisible()) {
807 if (udr && !udr->isVisible()) {
812 len = sizeof(buf) - 1;
813 if (ctrlRequest("PING", buf, &len) < 0) {
814 printf("PING failed - trying to reconnect\n");
815 if (openCtrlConnection(ctrl_iface) >= 0) {
816 printf("Reconnected successfully\n");
817 pingsToStatusUpdate = 0;
821 pingsToStatusUpdate--;
822 if (pingsToStatusUpdate <= 0) {
827 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
828 /* Use less frequent pings and status updates when the main window is
829 * hidden (running in taskbar). */
830 int interval = isHidden() ? 5000 : 1000;
831 if (timer->interval() != interval)
832 timer->setInterval(interval);
833 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
837 static int str_match(const char *a, const char *b)
839 return strncmp(a, b, strlen(b)) == 0;
843 void WpaGui::processMsg(char *msg)
845 char *pos = msg, *pos2;
851 priority = atoi(pos);
852 pos = strchr(pos, '>');
859 WpaMsg wm(pos, priority);
863 peers->event_notify(wm);
865 while (msgs.count() > 100)
868 /* Update last message with truncated version of the event */
869 if (strncmp(pos, "CTRL-", 5) == 0) {
870 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
877 QString lastmsg = pos2;
878 lastmsg.truncate(40);
879 textLastMessage->setText(lastmsg);
881 pingsToStatusUpdate = 0;
882 networkMayHaveChanged = true;
884 if (str_match(pos, WPA_CTRL_REQ))
885 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
886 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
887 scanres->updateResults();
888 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
889 showTrayMessage(QSystemTrayIcon::Information, 3,
890 tr("Disconnected from network."));
891 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
892 showTrayMessage(QSystemTrayIcon::Information, 3,
893 tr("Connection to network established."));
894 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
896 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
897 wpsStatusText->setText(tr("WPS AP in active PBC mode found"));
898 if (textStatus->text() == "INACTIVE" ||
899 textStatus->text() == "DISCONNECTED")
900 wpaguiTab->setCurrentWidget(wpsTab);
901 wpsInstructions->setText(tr("Press the PBC button on the "
902 "screen to start registration"));
903 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
904 wpsStatusText->setText(tr("WPS AP with recently selected "
906 if (textStatus->text() == "INACTIVE" ||
907 textStatus->text() == "DISCONNECTED")
908 wpaguiTab->setCurrentWidget(wpsTab);
909 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_AUTH)) {
910 showTrayMessage(QSystemTrayIcon::Information, 3,
911 "Wi-Fi Protected Setup (WPS) AP\n"
912 "indicating this client is authorized.");
913 wpsStatusText->setText("WPS AP indicating this client is "
915 if (textStatus->text() == "INACTIVE" ||
916 textStatus->text() == "DISCONNECTED")
917 wpaguiTab->setCurrentWidget(wpsTab);
918 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
919 wpsStatusText->setText(tr("WPS AP detected"));
920 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
921 wpsStatusText->setText(tr("PBC mode overlap detected"));
922 wpsInstructions->setText(tr("More than one AP is currently in "
923 "active WPS PBC mode. Wait couple "
924 "of minutes and try again"));
925 wpaguiTab->setCurrentWidget(wpsTab);
926 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
927 wpsStatusText->setText(tr("Network configuration received"));
928 wpaguiTab->setCurrentWidget(wpsTab);
929 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
930 if (strstr(pos, "(WSC)"))
931 wpsStatusText->setText(tr("Registration started"));
932 } else if (str_match(pos, WPS_EVENT_M2D)) {
933 wpsStatusText->setText(tr("Registrar does not yet know PIN"));
934 } else if (str_match(pos, WPS_EVENT_FAIL)) {
935 wpsStatusText->setText(tr("Registration failed"));
936 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
937 wpsStatusText->setText(tr("Registration succeeded"));
942 void WpaGui::processCtrlReq(const char *req)
948 udr = new UserDataRequest();
951 if (udr->setParams(this, req) < 0) {
961 void WpaGui::receiveMsgs()
966 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
967 len = sizeof(buf) - 1;
968 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
976 void WpaGui::connectB()
979 size_t reply_len = sizeof(reply);
980 ctrlRequest("REASSOCIATE", reply, &reply_len);
984 void WpaGui::selectNetwork( const QString &sel )
988 size_t reply_len = sizeof(reply);
990 if (cmd.contains(QRegExp("^\\d+:")))
991 cmd.truncate(cmd.indexOf(':'));
994 cmd.prepend("SELECT_NETWORK ");
995 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1001 void WpaGui::enableNetwork(const QString &sel)
1005 size_t reply_len = sizeof(reply);
1007 if (cmd.contains(QRegExp("^\\d+:")))
1008 cmd.truncate(cmd.indexOf(':'));
1009 else if (!cmd.startsWith("all")) {
1010 printf("Invalid editNetwork '%s'\n",
1011 cmd.toAscii().constData());
1014 cmd.prepend("ENABLE_NETWORK ");
1015 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1020 void WpaGui::disableNetwork(const QString &sel)
1024 size_t reply_len = sizeof(reply);
1026 if (cmd.contains(QRegExp("^\\d+:")))
1027 cmd.truncate(cmd.indexOf(':'));
1028 else if (!cmd.startsWith("all")) {
1029 printf("Invalid editNetwork '%s'\n",
1030 cmd.toAscii().constData());
1033 cmd.prepend("DISABLE_NETWORK ");
1034 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1039 void WpaGui::editNetwork(const QString &sel)
1044 if (cmd.contains(QRegExp("^\\d+:"))) {
1045 cmd.truncate(cmd.indexOf(':'));
1049 NetworkConfig *nc = new NetworkConfig();
1052 nc->setWpaGui(this);
1055 nc->paramsFromConfig(id);
1064 void WpaGui::editSelectedNetwork()
1066 if (networkSelect->count() < 1) {
1067 QMessageBox::information(
1068 this, tr("No Networks"),
1069 tr("There are no networks to edit.\n"));
1072 QString sel(networkSelect->currentText());
1077 void WpaGui::editListedNetwork()
1079 if (networkList->currentRow() < 0) {
1080 QMessageBox::information(this, tr("Select A Network"),
1081 tr("Select a network from the list to"
1085 QString sel(networkList->currentItem()->text());
1090 void WpaGui::triggerUpdate()
1093 networkMayHaveChanged = true;
1098 void WpaGui::addNetwork()
1100 NetworkConfig *nc = new NetworkConfig();
1103 nc->setWpaGui(this);
1110 void WpaGui::removeNetwork(const QString &sel)
1114 size_t reply_len = sizeof(reply);
1116 if (cmd.contains(QRegExp("^\\d+:")))
1117 cmd.truncate(cmd.indexOf(':'));
1118 else if (!cmd.startsWith("all")) {
1119 printf("Invalid editNetwork '%s'\n",
1120 cmd.toAscii().constData());
1123 cmd.prepend("REMOVE_NETWORK ");
1124 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1129 void WpaGui::removeSelectedNetwork()
1131 if (networkSelect->count() < 1) {
1132 QMessageBox::information(this, tr("No Networks"),
1133 tr("There are no networks to remove."
1137 QString sel(networkSelect->currentText());
1142 void WpaGui::removeListedNetwork()
1144 if (networkList->currentRow() < 0) {
1145 QMessageBox::information(this, tr("Select A Network"),
1146 tr("Select a network from the list "
1147 "to remove it.\n"));
1150 QString sel(networkList->currentItem()->text());
1155 void WpaGui::enableAllNetworks()
1162 void WpaGui::disableAllNetworks()
1165 disableNetwork(sel);
1169 void WpaGui::removeAllNetworks()
1176 int WpaGui::getNetworkDisabled(const QString &sel)
1180 size_t reply_len = sizeof(reply) - 1;
1181 int pos = cmd.indexOf(':');
1183 printf("Invalid getNetworkDisabled '%s'\n",
1184 cmd.toAscii().constData());
1188 cmd.prepend("GET_NETWORK ");
1189 cmd.append(" disabled");
1191 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1192 && reply_len >= 1) {
1193 reply[reply_len] = '\0';
1194 if (!str_match(reply, "FAIL"))
1202 void WpaGui::updateNetworkDisabledStatus()
1204 if (networkList->currentRow() < 0)
1207 QString sel(networkList->currentItem()->text());
1209 switch (getNetworkDisabled(sel)) {
1211 if (!enableRadioButton->isChecked())
1212 enableRadioButton->setChecked(true);
1215 if (!disableRadioButton->isChecked())
1216 disableRadioButton->setChecked(true);
1222 void WpaGui::enableListedNetwork(bool enabled)
1224 if (networkList->currentRow() < 0 || !enabled)
1227 QString sel(networkList->currentItem()->text());
1229 if (getNetworkDisabled(sel) == 1)
1234 void WpaGui::disableListedNetwork(bool disabled)
1236 if (networkList->currentRow() < 0 || !disabled)
1239 QString sel(networkList->currentItem()->text());
1241 if (getNetworkDisabled(sel) == 0)
1242 disableNetwork(sel);
1246 void WpaGui::saveConfig()
1251 len = sizeof(buf) - 1;
1252 ctrlRequest("SAVE_CONFIG", buf, &len);
1256 if (str_match(buf, "FAIL"))
1257 QMessageBox::warning(
1258 this, tr("Failed to save configuration"),
1259 tr("The configuration could not be saved.\n"
1261 "The update_config=1 configuration option\n"
1262 "must be used for configuration saving to\n"
1263 "be permitted.\n"));
1265 QMessageBox::information(
1266 this, tr("Saved configuration"),
1267 tr("The current configuration was saved."
1272 void WpaGui::selectAdapter( const QString & sel )
1274 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1275 printf("Failed to open control connection to "
1276 "wpa_supplicant.\n");
1282 void WpaGui::createTrayIcon(bool trayOnly)
1284 QApplication::setQuitOnLastWindowClosed(false);
1286 tray_icon = new QSystemTrayIcon(this);
1287 tray_icon->setToolTip(qAppName() + tr(" - wpa_supplicant user interface"));
1288 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1289 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1291 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1294 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1295 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1297 ackTrayIcon = false;
1299 tray_menu = new QMenu(this);
1301 disconnectAction = new QAction(tr("&Disconnect"), this);
1302 reconnectAction = new QAction(tr("Re&connect"), this);
1303 connect(disconnectAction, SIGNAL(triggered()), this,
1304 SLOT(disconnect()));
1305 connect(reconnectAction, SIGNAL(triggered()), this,
1307 tray_menu->addAction(disconnectAction);
1308 tray_menu->addAction(reconnectAction);
1309 tray_menu->addSeparator();
1311 eventAction = new QAction(tr("&Event History"), this);
1312 scanAction = new QAction(tr("Scan &Results"), this);
1313 statAction = new QAction(tr("S&tatus"), this);
1314 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1315 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1316 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1317 tray_menu->addAction(eventAction);
1318 tray_menu->addAction(scanAction);
1319 tray_menu->addAction(statAction);
1320 tray_menu->addSeparator();
1322 showAction = new QAction(tr("&Show Window"), this);
1323 hideAction = new QAction(tr("&Hide Window"), this);
1324 quitAction = new QAction(tr("&Quit"), this);
1325 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1326 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1327 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1328 tray_menu->addAction(showAction);
1329 tray_menu->addAction(hideAction);
1330 tray_menu->addSeparator();
1331 tray_menu->addAction(quitAction);
1333 tray_icon->setContextMenu(tray_menu);
1343 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1344 const QString & msg)
1346 if (!QSystemTrayIcon::supportsMessages())
1349 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1352 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1356 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1359 /* use close() here instead of hide() and allow the
1360 * custom closeEvent handler take care of children */
1361 case QSystemTrayIcon::Trigger:
1371 case QSystemTrayIcon::MiddleClick:
1380 void WpaGui::showTrayStatus()
1385 len = sizeof(buf) - 1;
1386 if (ctrlRequest("STATUS", buf, &len) < 0)
1390 QString msg, status(buf);
1392 QStringList lines = status.split(QRegExp("\\n"));
1393 for (QStringList::Iterator it = lines.begin();
1394 it != lines.end(); it++) {
1395 int pos = (*it).indexOf('=') + 1;
1399 if ((*it).startsWith("bssid="))
1400 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1401 else if ((*it).startsWith("ssid="))
1402 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1403 else if ((*it).startsWith("pairwise_cipher="))
1404 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1405 else if ((*it).startsWith("group_cipher="))
1406 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1407 else if ((*it).startsWith("key_mgmt="))
1408 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1409 else if ((*it).startsWith("wpa_state="))
1410 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1411 else if ((*it).startsWith("ip_address="))
1412 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1413 else if ((*it).startsWith("Supplicant PAE state="))
1414 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1415 else if ((*it).startsWith("EAP state="))
1416 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1420 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1424 void WpaGui::closeEvent(QCloseEvent *event)
1450 if (tray_icon && !ackTrayIcon) {
1451 /* give user a visual hint that the tray icon exists */
1452 if (QSystemTrayIcon::supportsMessages()) {
1454 showTrayMessage(QSystemTrayIcon::Information, 3,
1456 tr(" will keep running in "
1457 "the system tray."));
1459 QMessageBox::information(this, qAppName() +
1461 tr("The program will keep "
1462 "running in the system "
1472 void WpaGui::wpsDialog()
1474 wpaguiTab->setCurrentWidget(wpsTab);
1478 void WpaGui::peersDialog()
1485 peers = new Peers();
1488 peers->setWpaGui(this);
1494 void WpaGui::tabChanged(int index)
1502 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1503 if (bssFromScan.isEmpty())
1504 wpsApPinButton->setEnabled(false);
1508 void WpaGui::wpsPbc()
1511 size_t reply_len = sizeof(reply);
1513 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1516 wpsPinEdit->setEnabled(false);
1517 if (wpsStatusText->text().compare(tr("WPS AP in active PBC mode found"))) {
1518 wpsInstructions->setText(tr("Press the push button on the AP to "
1519 "start the PBC mode."));
1521 wpsInstructions->setText(tr("If you have not yet done so, press "
1522 "the push button on the AP to start "
1525 wpsStatusText->setText(tr("Waiting for Registrar"));
1530 void WpaGui::wpsGeneratePin()
1533 size_t reply_len = sizeof(reply) - 1;
1535 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1538 reply[reply_len] = '\0';
1540 wpsPinEdit->setText(reply);
1541 wpsPinEdit->setEnabled(true);
1542 wpsInstructions->setText(tr("Enter the generated PIN into the Registrar "
1543 "(either the internal one in the AP or an "
1545 wpsStatusText->setText(tr("Waiting for Registrar"));
1550 void WpaGui::setBssFromScan(const QString &bssid)
1552 bssFromScan = bssid;
1553 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1554 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1555 wpsStatusText->setText(tr("WPS AP selected from scan results"));
1556 wpsInstructions->setText(tr("If you want to use an AP device PIN, e.g., "
1557 "from a label in the device, enter the eight "
1558 "digit AP PIN and click Use AP PIN button."));
1562 void WpaGui::wpsApPinChanged(const QString &text)
1564 wpsApPinButton->setEnabled(text.length() == 8);
1568 void WpaGui::wpsApPin()
1571 size_t reply_len = sizeof(reply);
1573 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1574 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1577 wpsStatusText->setText(tr("Waiting for AP/Enrollee"));
1582 void WpaGui::stopWpsRun(bool success)
1585 wpsStatusText->setText(success ? tr("Connected to the network") :
1588 wpsStatusText->setText("");
1589 wpsPinEdit->setEnabled(false);
1590 wpsInstructions->setText("");
1593 wpsApPinEdit->setEnabled(false);
1594 wpsApPinButton->setEnabled(false);
1598 #ifdef CONFIG_NATIVE_WINDOWS
1601 #define WPASVC_NAME TEXT("wpasvc")
1604 class ErrorMsg : public QMessageBox {
1606 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1607 void showMsg(QString msg);
1612 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1613 QMessageBox(parent), err(last_err)
1615 setWindowTitle(tr("wpa_gui error"));
1616 setIcon(QMessageBox::Warning);
1619 void ErrorMsg::showMsg(QString msg)
1624 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1625 FORMAT_MESSAGE_FROM_SYSTEM,
1626 NULL, err, 0, (LPTSTR) (void *) &buf,
1628 QString msg = QString::fromWCharArray(buf);
1629 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1632 setInformativeText(QString("[%1]").arg(err));
1639 void WpaGui::startService()
1643 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1645 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1649 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1651 ErrorMsg(this).showMsg(tr("OpenService failed"));
1652 CloseServiceHandle(scm);
1656 if (!StartService(svc, 0, NULL)) {
1657 ErrorMsg(this).showMsg(tr("Failed to start wpa_supplicant "
1661 CloseServiceHandle(svc);
1662 CloseServiceHandle(scm);
1666 void WpaGui::stopService()
1669 SERVICE_STATUS status;
1671 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1673 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1677 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1679 ErrorMsg(this).showMsg(tr("OpenService failed"));
1680 CloseServiceHandle(scm);
1684 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1685 ErrorMsg(this).showMsg(tr("Failed to stop wpa_supplicant "
1689 CloseServiceHandle(svc);
1690 CloseServiceHandle(scm);
1694 bool WpaGui::serviceRunning()
1697 SERVICE_STATUS status;
1698 bool running = false;
1700 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1702 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1706 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1708 printf("OpenService failed: %d\n\n", (int) GetLastError());
1709 CloseServiceHandle(scm);
1713 if (QueryServiceStatus(svc, &status)) {
1714 if (status.dwCurrentState != SERVICE_STOPPED)
1718 CloseServiceHandle(svc);
1719 CloseServiceHandle(scm);
1724 #endif /* CONFIG_NATIVE_WINDOWS */
1727 void WpaGui::addInterface()
1733 add_iface = new AddInterface(this, this);
1739 #ifndef QT_NO_SESSIONMANAGER
1740 void WpaGui::saveState()
1742 QSettings settings("wpa_supplicant", "wpa_gui");
1743 settings.beginGroup("state");
1744 settings.setValue("session_id", app->sessionId());
1745 settings.setValue("in_tray", inTray);
1746 settings.endGroup();