2 * wpa_gui - WpaGui class
3 * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
16 /* Need to get getopt() */
20 #ifdef CONFIG_NATIVE_WINDOWS
22 #endif /* CONFIG_NATIVE_WINDOWS */
25 #include <QMessageBox>
26 #include <QCloseEvent>
27 #include <QImageReader>
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("Stop Service");
54 fileMenu->insertAction(actionWPS, fileStopServiceAction);
56 fileStartServiceAction = new QAction(this);
57 fileStartServiceAction->setObjectName("Start Service");
58 fileStartServiceAction->setIconText("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("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("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 "wpa_supplicant service is not running.\n"
344 "Do you want to start it?",
345 QMessageBox::Yes | QMessageBox::No) ==
349 #endif /* CONFIG_NATIVE_WINDOWS */
353 #ifdef CONFIG_CTRL_IFACE_UNIX
354 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
355 cfile = (char *) malloc(flen);
358 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
359 #else /* CONFIG_CTRL_IFACE_UNIX */
360 flen = strlen(ctrl_iface) + 1;
361 cfile = (char *) malloc(flen);
364 snprintf(cfile, flen, "%s", ctrl_iface);
365 #endif /* CONFIG_CTRL_IFACE_UNIX */
368 wpa_ctrl_close(ctrl_conn);
375 wpa_ctrl_detach(monitor_conn);
376 wpa_ctrl_close(monitor_conn);
380 printf("Trying to connect to '%s'\n", cfile);
381 ctrl_conn = wpa_ctrl_open(cfile);
382 if (ctrl_conn == NULL) {
386 monitor_conn = wpa_ctrl_open(cfile);
388 if (monitor_conn == NULL) {
389 wpa_ctrl_close(ctrl_conn);
392 if (wpa_ctrl_attach(monitor_conn)) {
393 printf("Failed to attach to wpa_supplicant\n");
394 wpa_ctrl_close(monitor_conn);
396 wpa_ctrl_close(ctrl_conn);
401 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
402 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
403 QSocketNotifier::Read, this);
404 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
407 adapterSelect->clear();
408 adapterSelect->addItem(ctrl_iface);
409 adapterSelect->setCurrentIndex(0);
411 len = sizeof(buf) - 1;
412 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
417 pos2 = strchr(pos, '\n');
420 if (strcmp(pos, ctrl_iface) != 0)
421 adapterSelect->addItem(pos);
429 len = sizeof(buf) - 1;
430 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len,
435 QStringList types = res.split(QChar(' '));
436 bool wps = types.contains("WSC");
437 actionWPS->setEnabled(wps);
438 wpsTab->setEnabled(wps);
439 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), wps);
446 static void wpa_gui_msg_cb(char *msg, size_t)
448 /* This should not happen anymore since two control connections are
450 printf("missed message: %s\n", msg);
454 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
458 if (ctrl_conn == NULL)
460 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen,
463 printf("'%s' command timed out.\n", cmd);
465 printf("'%s' command failed.\n", cmd);
471 void WpaGui::updateStatus()
473 char buf[2048], *start, *end, *pos;
476 pingsToStatusUpdate = 10;
478 len = sizeof(buf) - 1;
479 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
480 textStatus->setText("Could not get status from "
482 textAuthentication->clear();
483 textEncryption->clear();
486 textIpAddress->clear();
488 #ifdef CONFIG_NATIVE_WINDOWS
489 static bool first = true;
490 if (first && connectedToService &&
491 (ctrl_iface == NULL || *ctrl_iface == '\0')) {
493 if (QMessageBox::information(
495 "No network interfaces in use.\n"
496 "Would you like to add one?",
497 QMessageBox::Yes | QMessageBox::No) ==
501 #endif /* CONFIG_NATIVE_WINDOWS */
507 bool auth_updated = false, ssid_updated = false;
508 bool bssid_updated = false, ipaddr_updated = false;
509 bool status_updated = false;
510 char *pairwise_cipher = NULL, *group_cipher = NULL;
515 end = strchr(start, '\n');
519 while (end[0] && end[1])
524 pos = strchr(start, '=');
527 if (strcmp(start, "bssid") == 0) {
528 bssid_updated = true;
529 textBssid->setText(pos);
530 } else if (strcmp(start, "ssid") == 0) {
532 textSsid->setText(pos);
533 } else if (strcmp(start, "ip_address") == 0) {
534 ipaddr_updated = true;
535 textIpAddress->setText(pos);
536 } else if (strcmp(start, "wpa_state") == 0) {
537 status_updated = true;
538 textStatus->setText(pos);
539 } else if (strcmp(start, "key_mgmt") == 0) {
541 textAuthentication->setText(pos);
542 /* TODO: could add EAP status to this */
543 } else if (strcmp(start, "pairwise_cipher") == 0) {
544 pairwise_cipher = pos;
545 } else if (strcmp(start, "group_cipher") == 0) {
555 if (pairwise_cipher || group_cipher) {
557 if (pairwise_cipher && group_cipher &&
558 strcmp(pairwise_cipher, group_cipher) != 0) {
559 encr.append(pairwise_cipher);
561 encr.append(group_cipher);
562 } else if (pairwise_cipher) {
563 encr.append(pairwise_cipher);
565 encr.append(group_cipher);
566 encr.append(" [group key only]");
568 textEncryption->setText(encr);
570 textEncryption->clear();
575 textAuthentication->clear();
581 textIpAddress->clear();
585 void WpaGui::updateNetworks()
587 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
589 int first_active = -1;
590 int was_selected = -1;
591 bool current = false;
593 if (!networkMayHaveChanged)
596 if (networkList->currentRow() >= 0)
597 was_selected = networkList->currentRow();
599 networkSelect->clear();
600 networkList->clear();
602 if (ctrl_conn == NULL)
605 len = sizeof(buf) - 1;
606 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
610 start = strchr(buf, '\n');
617 end = strchr(start, '\n');
621 while (end[0] && end[1])
627 ssid = strchr(id, '\t');
631 bssid = strchr(ssid, '\t');
635 flags = strchr(bssid, '\t');
641 network.append(": ");
642 network.append(ssid);
643 networkSelect->addItem(network);
644 networkList->addItem(network);
646 if (strstr(flags, "[CURRENT]")) {
647 networkSelect->setCurrentIndex(networkSelect->count() -
650 } else if (first_active < 0 &&
651 strstr(flags, "[DISABLED]") == NULL)
652 first_active = networkSelect->count() - 1;
659 if (networkSelect->count() > 1)
660 networkSelect->addItem("Select any network");
662 if (!current && first_active >= 0)
663 networkSelect->setCurrentIndex(first_active);
665 if (was_selected >= 0 && networkList->count() > 0) {
666 if (was_selected < networkList->count())
667 networkList->setCurrentRow(was_selected);
669 networkList->setCurrentRow(networkList->count() - 1);
672 networkList->setCurrentRow(networkSelect->currentIndex());
674 networkMayHaveChanged = false;
678 void WpaGui::helpIndex()
680 printf("helpIndex\n");
684 void WpaGui::helpContents()
686 printf("helpContents\n");
690 void WpaGui::helpAbout()
692 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
693 "Copyright (c) 2003-2008,\n"
694 "Jouni Malinen <j@w1.fi>\n"
695 "and contributors.\n"
697 "This program is free software. You can\n"
698 "distribute it and/or modify it under the terms "
700 "the GNU General Public License version 2.\n"
702 "Alternatively, this software may be distributed\n"
703 "under the terms of the BSD license.\n"
705 "This product includes software developed\n"
706 "by the OpenSSL Project for use in the\n"
707 "OpenSSL Toolkit (http://www.openssl.org/)\n");
711 void WpaGui::disconnect()
714 size_t reply_len = sizeof(reply);
715 ctrlRequest("DISCONNECT", reply, &reply_len);
727 scanres = new ScanResults();
730 scanres->setWpaGui(this);
736 void WpaGui::eventHistory()
743 eh = new EventHistory();
757 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
759 * QSocketNotifier cannot be used with Windows named pipes, so use a
760 * timer to check for received messages for now. This could be
761 * optimized be doing something specific to named pipes or Windows
762 * events, but it is not clear what would be the best way of doing that
766 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
768 if (scanres && !scanres->isVisible()) {
773 if (eh && !eh->isVisible()) {
778 if (udr && !udr->isVisible()) {
783 len = sizeof(buf) - 1;
784 if (ctrlRequest("PING", buf, &len) < 0) {
785 printf("PING failed - trying to reconnect\n");
786 if (openCtrlConnection(ctrl_iface) >= 0) {
787 printf("Reconnected successfully\n");
788 pingsToStatusUpdate = 0;
792 pingsToStatusUpdate--;
793 if (pingsToStatusUpdate <= 0) {
798 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
799 /* Use less frequent pings and status updates when the main window is
800 * hidden (running in taskbar). */
801 int interval = isHidden() ? 5000 : 1000;
802 if (timer->interval() != interval)
803 timer->setInterval(interval);
804 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
808 static int str_match(const char *a, const char *b)
810 return strncmp(a, b, strlen(b)) == 0;
814 void WpaGui::processMsg(char *msg)
816 char *pos = msg, *pos2;
822 priority = atoi(pos);
823 pos = strchr(pos, '>');
830 WpaMsg wm(pos, priority);
834 peers->event_notify(wm);
836 while (msgs.count() > 100)
839 /* Update last message with truncated version of the event */
840 if (strncmp(pos, "CTRL-", 5) == 0) {
841 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
848 QString lastmsg = pos2;
849 lastmsg.truncate(40);
850 textLastMessage->setText(lastmsg);
852 pingsToStatusUpdate = 0;
853 networkMayHaveChanged = true;
855 if (str_match(pos, WPA_CTRL_REQ))
856 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
857 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
858 scanres->updateResults();
859 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
860 showTrayMessage(QSystemTrayIcon::Information, 3,
861 "Disconnected from network.");
862 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
863 showTrayMessage(QSystemTrayIcon::Information, 3,
864 "Connection to network established.");
865 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
867 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
868 showTrayMessage(QSystemTrayIcon::Information, 3,
869 "Wi-Fi Protected Setup (WPS) AP\n"
870 "in active PBC mode found.");
871 wpsStatusText->setText("WPS AP in active PBC mode found");
872 wpaguiTab->setCurrentWidget(wpsTab);
873 wpsInstructions->setText("Press the PBC button on the screen "
874 "to start registration");
875 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
876 showTrayMessage(QSystemTrayIcon::Information, 3,
877 "Wi-Fi Protected Setup (WPS) AP\n"
878 " in active PIN mode found.");
879 wpsStatusText->setText("WPS AP with recently selected "
881 wpaguiTab->setCurrentWidget(wpsTab);
882 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
883 showTrayMessage(QSystemTrayIcon::Information, 3,
884 "Wi-Fi Protected Setup (WPS)\n"
886 wpsStatusText->setText("WPS AP detected");
887 wpaguiTab->setCurrentWidget(wpsTab);
888 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
889 showTrayMessage(QSystemTrayIcon::Information, 3,
890 "Wi-Fi Protected Setup (WPS)\n"
891 "PBC mode overlap detected.");
892 wpsStatusText->setText("PBC mode overlap detected");
893 wpsInstructions->setText("More than one AP is currently in "
894 "active WPS PBC mode. Wait couple of "
895 "minutes and try again");
896 wpaguiTab->setCurrentWidget(wpsTab);
897 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
898 wpsStatusText->setText("Network configuration received");
899 wpaguiTab->setCurrentWidget(wpsTab);
900 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
901 if (strstr(pos, "(WSC)"))
902 wpsStatusText->setText("Registration started");
903 } else if (str_match(pos, WPS_EVENT_M2D)) {
904 wpsStatusText->setText("Registrar does not yet know PIN");
905 } else if (str_match(pos, WPS_EVENT_FAIL)) {
906 wpsStatusText->setText("Registration failed");
907 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
908 wpsStatusText->setText("Registration succeeded");
913 void WpaGui::processCtrlReq(const char *req)
919 udr = new UserDataRequest();
922 if (udr->setParams(this, req) < 0) {
932 void WpaGui::receiveMsgs()
937 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
938 len = sizeof(buf) - 1;
939 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
947 void WpaGui::connectB()
950 size_t reply_len = sizeof(reply);
951 ctrlRequest("REASSOCIATE", reply, &reply_len);
955 void WpaGui::selectNetwork( const QString &sel )
959 size_t reply_len = sizeof(reply);
961 if (cmd.startsWith("Select any")) {
964 int pos = cmd.indexOf(':');
966 printf("Invalid selectNetwork '%s'\n",
967 cmd.toAscii().constData());
972 cmd.prepend("SELECT_NETWORK ");
973 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
979 void WpaGui::enableNetwork(const QString &sel)
983 size_t reply_len = sizeof(reply);
985 if (!cmd.startsWith("all")) {
986 int pos = cmd.indexOf(':');
988 printf("Invalid enableNetwork '%s'\n",
989 cmd.toAscii().constData());
994 cmd.prepend("ENABLE_NETWORK ");
995 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1000 void WpaGui::disableNetwork(const QString &sel)
1004 size_t reply_len = sizeof(reply);
1006 if (!cmd.startsWith("all")) {
1007 int pos = cmd.indexOf(':');
1009 printf("Invalid disableNetwork '%s'\n",
1010 cmd.toAscii().constData());
1015 cmd.prepend("DISABLE_NETWORK ");
1016 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1021 void WpaGui::editNetwork(const QString &sel)
1026 if (!cmd.startsWith("Select any")) {
1027 int pos = sel.indexOf(':');
1029 printf("Invalid editNetwork '%s'\n",
1030 cmd.toAscii().constData());
1037 NetworkConfig *nc = new NetworkConfig();
1040 nc->setWpaGui(this);
1043 nc->paramsFromConfig(id);
1052 void WpaGui::editSelectedNetwork()
1054 if (networkSelect->count() < 1) {
1055 QMessageBox::information(this, "No Networks",
1056 "There are no networks to edit.\n");
1059 QString sel(networkSelect->currentText());
1064 void WpaGui::editListedNetwork()
1066 if (networkList->currentRow() < 0) {
1067 QMessageBox::information(this, "Select A Network",
1068 "Select a network from the list to"
1072 QString sel(networkList->currentItem()->text());
1077 void WpaGui::triggerUpdate()
1080 networkMayHaveChanged = true;
1085 void WpaGui::addNetwork()
1087 NetworkConfig *nc = new NetworkConfig();
1090 nc->setWpaGui(this);
1097 void WpaGui::removeNetwork(const QString &sel)
1101 size_t reply_len = sizeof(reply);
1103 if (cmd.startsWith("Select any"))
1106 if (!cmd.startsWith("all")) {
1107 int pos = cmd.indexOf(':');
1109 printf("Invalid removeNetwork '%s'\n",
1110 cmd.toAscii().constData());
1115 cmd.prepend("REMOVE_NETWORK ");
1116 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1121 void WpaGui::removeSelectedNetwork()
1123 if (networkSelect->count() < 1) {
1124 QMessageBox::information(this, "No Networks",
1125 "There are no networks to remove.\n");
1128 QString sel(networkSelect->currentText());
1133 void WpaGui::removeListedNetwork()
1135 if (networkList->currentRow() < 0) {
1136 QMessageBox::information(this, "Select A Network",
1137 "Select a network from the list to"
1141 QString sel(networkList->currentItem()->text());
1146 void WpaGui::enableAllNetworks()
1153 void WpaGui::disableAllNetworks()
1156 disableNetwork(sel);
1160 void WpaGui::removeAllNetworks()
1167 int WpaGui::getNetworkDisabled(const QString &sel)
1171 size_t reply_len = sizeof(reply) - 1;
1172 int pos = cmd.indexOf(':');
1174 printf("Invalid getNetworkDisabled '%s'\n",
1175 cmd.toAscii().constData());
1179 cmd.prepend("GET_NETWORK ");
1180 cmd.append(" disabled");
1182 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1183 && reply_len >= 1) {
1184 reply[reply_len] = '\0';
1185 if (!str_match(reply, "FAIL"))
1193 void WpaGui::updateNetworkDisabledStatus()
1195 if (networkList->currentRow() < 0)
1198 QString sel(networkList->currentItem()->text());
1200 switch (getNetworkDisabled(sel)) {
1202 if (!enableRadioButton->isChecked())
1203 enableRadioButton->setChecked(true);
1206 if (!disableRadioButton->isChecked())
1207 disableRadioButton->setChecked(true);
1213 void WpaGui::enableListedNetwork(bool enabled)
1215 if (networkList->currentRow() < 0 || !enabled)
1218 QString sel(networkList->currentItem()->text());
1220 if (getNetworkDisabled(sel) == 1)
1225 void WpaGui::disableListedNetwork(bool disabled)
1227 if (networkList->currentRow() < 0 || !disabled)
1230 QString sel(networkList->currentItem()->text());
1232 if (getNetworkDisabled(sel) == 0)
1233 disableNetwork(sel);
1237 void WpaGui::saveConfig()
1242 len = sizeof(buf) - 1;
1243 ctrlRequest("SAVE_CONFIG", buf, &len);
1247 if (str_match(buf, "FAIL"))
1248 QMessageBox::warning(this, "Failed to save configuration",
1249 "The configuration could not be saved.\n"
1251 "The update_config=1 configuration option\n"
1252 "must be used for configuration saving to\n"
1255 QMessageBox::information(this, "Saved configuration",
1256 "The current configuration was saved."
1261 void WpaGui::selectAdapter( const QString & sel )
1263 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1264 printf("Failed to open control connection to "
1265 "wpa_supplicant.\n");
1271 void WpaGui::createTrayIcon(bool trayOnly)
1273 QApplication::setQuitOnLastWindowClosed(false);
1275 tray_icon = new QSystemTrayIcon(this);
1276 tray_icon->setToolTip(qAppName() + " - wpa_supplicant user interface");
1277 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1278 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1280 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1283 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1284 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1286 ackTrayIcon = false;
1288 tray_menu = new QMenu(this);
1290 disconnectAction = new QAction("&Disconnect", this);
1291 reconnectAction = new QAction("Re&connect", this);
1292 connect(disconnectAction, SIGNAL(triggered()), this,
1293 SLOT(disconnect()));
1294 connect(reconnectAction, SIGNAL(triggered()), this,
1296 tray_menu->addAction(disconnectAction);
1297 tray_menu->addAction(reconnectAction);
1298 tray_menu->addSeparator();
1300 eventAction = new QAction("&Event History", this);
1301 scanAction = new QAction("Scan &Results", this);
1302 statAction = new QAction("S&tatus", this);
1303 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1304 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1305 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1306 tray_menu->addAction(eventAction);
1307 tray_menu->addAction(scanAction);
1308 tray_menu->addAction(statAction);
1309 tray_menu->addSeparator();
1311 showAction = new QAction("&Show Window", this);
1312 hideAction = new QAction("&Hide Window", this);
1313 quitAction = new QAction("&Quit", this);
1314 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1315 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1316 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1317 tray_menu->addAction(showAction);
1318 tray_menu->addAction(hideAction);
1319 tray_menu->addSeparator();
1320 tray_menu->addAction(quitAction);
1322 tray_icon->setContextMenu(tray_menu);
1332 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1333 const QString & msg)
1335 if (!QSystemTrayIcon::supportsMessages())
1338 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1341 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1345 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1348 /* use close() here instead of hide() and allow the
1349 * custom closeEvent handler take care of children */
1350 case QSystemTrayIcon::Trigger:
1360 case QSystemTrayIcon::MiddleClick:
1369 void WpaGui::showTrayStatus()
1374 len = sizeof(buf) - 1;
1375 if (ctrlRequest("STATUS", buf, &len) < 0)
1379 QString msg, status(buf);
1381 QStringList lines = status.split(QRegExp("\\n"));
1382 for (QStringList::Iterator it = lines.begin();
1383 it != lines.end(); it++) {
1384 int pos = (*it).indexOf('=') + 1;
1388 if ((*it).startsWith("bssid="))
1389 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1390 else if ((*it).startsWith("ssid="))
1391 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1392 else if ((*it).startsWith("pairwise_cipher="))
1393 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1394 else if ((*it).startsWith("group_cipher="))
1395 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1396 else if ((*it).startsWith("key_mgmt="))
1397 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1398 else if ((*it).startsWith("wpa_state="))
1399 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1400 else if ((*it).startsWith("ip_address="))
1401 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1402 else if ((*it).startsWith("Supplicant PAE state="))
1403 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1404 else if ((*it).startsWith("EAP state="))
1405 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1409 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1413 void WpaGui::closeEvent(QCloseEvent *event)
1439 if (tray_icon && !ackTrayIcon) {
1440 /* give user a visual hint that the tray icon exists */
1441 if (QSystemTrayIcon::supportsMessages()) {
1443 showTrayMessage(QSystemTrayIcon::Information, 3,
1444 qAppName() + " will keep running in "
1445 "the system tray.");
1447 QMessageBox::information(this, qAppName() + " systray",
1448 "The program will keep "
1449 "running in the system "
1459 void WpaGui::wpsDialog()
1461 wpaguiTab->setCurrentWidget(wpsTab);
1465 void WpaGui::peersDialog()
1472 peers = new Peers();
1475 peers->setWpaGui(this);
1481 void WpaGui::tabChanged(int index)
1489 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1490 if (bssFromScan.isEmpty())
1491 wpsApPinButton->setEnabled(false);
1495 void WpaGui::wpsPbc()
1498 size_t reply_len = sizeof(reply);
1500 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1503 wpsPinEdit->setEnabled(false);
1504 if (wpsStatusText->text().compare("WPS AP in active PBC mode found")) {
1505 wpsInstructions->setText("Press the push button on the AP to "
1506 "start the PBC mode.");
1508 wpsInstructions->setText("If you have not yet done so, press "
1509 "the push button on the AP to start "
1512 wpsStatusText->setText("Waiting for Registrar");
1517 void WpaGui::wpsGeneratePin()
1520 size_t reply_len = sizeof(reply) - 1;
1522 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1525 reply[reply_len] = '\0';
1527 wpsPinEdit->setText(reply);
1528 wpsPinEdit->setEnabled(true);
1529 wpsInstructions->setText("Enter the generated PIN into the Registrar "
1530 "(either the internal one in the AP or an "
1532 wpsStatusText->setText("Waiting for Registrar");
1537 void WpaGui::setBssFromScan(const QString &bssid)
1539 bssFromScan = bssid;
1540 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1541 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1542 wpsStatusText->setText("WPS AP selected from scan results");
1543 wpsInstructions->setText("If you want to use an AP device PIN, e.g., "
1544 "from a label in the device, enter the eight "
1545 "digit AP PIN and click Use AP PIN button.");
1549 void WpaGui::wpsApPinChanged(const QString &text)
1551 wpsApPinButton->setEnabled(text.length() == 8);
1555 void WpaGui::wpsApPin()
1558 size_t reply_len = sizeof(reply);
1560 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1561 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1564 wpsStatusText->setText("Waiting for AP/Enrollee");
1569 void WpaGui::stopWpsRun(bool success)
1572 wpsStatusText->setText(success ? "Connected to the network" :
1575 wpsStatusText->setText("");
1576 wpsPinEdit->setEnabled(false);
1577 wpsInstructions->setText("");
1580 wpsApPinEdit->setEnabled(false);
1581 wpsApPinButton->setEnabled(false);
1585 #ifdef CONFIG_NATIVE_WINDOWS
1588 #define WPASVC_NAME TEXT("wpasvc")
1591 class ErrorMsg : public QMessageBox {
1593 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1594 void showMsg(QString msg);
1599 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1600 QMessageBox(parent), err(last_err)
1602 setWindowTitle("wpa_gui error");
1603 setIcon(QMessageBox::Warning);
1606 void ErrorMsg::showMsg(QString msg)
1611 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1612 FORMAT_MESSAGE_FROM_SYSTEM,
1613 NULL, err, 0, (LPTSTR) (void *) &buf,
1615 QString msg = QString::fromWCharArray(buf);
1616 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1619 setInformativeText(QString("[%1]").arg(err));
1626 void WpaGui::startService()
1630 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1632 ErrorMsg(this).showMsg("OpenSCManager failed");
1636 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1638 ErrorMsg(this).showMsg("OpenService failed");
1639 CloseServiceHandle(scm);
1643 if (!StartService(svc, 0, NULL)) {
1644 ErrorMsg(this).showMsg("Failed to start wpa_supplicant "
1648 CloseServiceHandle(svc);
1649 CloseServiceHandle(scm);
1653 void WpaGui::stopService()
1656 SERVICE_STATUS status;
1658 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1660 ErrorMsg(this).showMsg("OpenSCManager failed");
1664 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1666 ErrorMsg(this).showMsg("OpenService failed");
1667 CloseServiceHandle(scm);
1671 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1672 ErrorMsg(this).showMsg("Failed to stop wpa_supplicant "
1676 CloseServiceHandle(svc);
1677 CloseServiceHandle(scm);
1681 bool WpaGui::serviceRunning()
1684 SERVICE_STATUS status;
1685 bool running = false;
1687 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1689 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1693 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1695 printf("OpenService failed: %d\n\n", (int) GetLastError());
1696 CloseServiceHandle(scm);
1700 if (QueryServiceStatus(svc, &status)) {
1701 if (status.dwCurrentState != SERVICE_STOPPED)
1705 CloseServiceHandle(svc);
1706 CloseServiceHandle(scm);
1711 #endif /* CONFIG_NATIVE_WINDOWS */
1714 void WpaGui::addInterface()
1720 add_iface = new AddInterface(this, this);
1726 #ifndef QT_NO_SESSIONMANAGER
1727 void WpaGui::saveState()
1729 QSettings settings("wpa_supplicant", "wpa_gui");
1730 settings.beginGroup("state");
1731 settings.setValue("session_id", app->sessionId());
1732 settings.setValue("in_tray", inTray);
1733 settings.endGroup();