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>
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');
663 network.append(": ");
664 network.append(ssid);
665 networkSelect->addItem(network);
666 networkList->addItem(network);
668 if (strstr(flags, "[CURRENT]")) {
669 networkSelect->setCurrentIndex(networkSelect->count() -
672 } else if (first_active < 0 &&
673 strstr(flags, "[DISABLED]") == NULL)
674 first_active = networkSelect->count() - 1;
681 if (networkSelect->count() > 1)
682 networkSelect->addItem(tr("Select any network"));
684 if (!current && first_active >= 0)
685 networkSelect->setCurrentIndex(first_active);
687 if (was_selected >= 0 && networkList->count() > 0) {
688 if (was_selected < networkList->count())
689 networkList->setCurrentRow(was_selected);
691 networkList->setCurrentRow(networkList->count() - 1);
694 networkList->setCurrentRow(networkSelect->currentIndex());
696 networkMayHaveChanged = false;
700 void WpaGui::helpIndex()
702 printf("helpIndex\n");
706 void WpaGui::helpContents()
708 printf("helpContents\n");
712 void WpaGui::helpAbout()
714 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
715 "Copyright (c) 2003-2008,\n"
716 "Jouni Malinen <j@w1.fi>\n"
717 "and contributors.\n"
719 "This program is free software. You can\n"
720 "distribute it and/or modify it under the terms "
722 "the GNU General Public License version 2.\n"
724 "Alternatively, this software may be distributed\n"
725 "under the terms of the BSD license.\n"
727 "This product includes software developed\n"
728 "by the OpenSSL Project for use in the\n"
729 "OpenSSL Toolkit (http://www.openssl.org/)\n");
733 void WpaGui::disconnect()
736 size_t reply_len = sizeof(reply);
737 ctrlRequest("DISCONNECT", reply, &reply_len);
749 scanres = new ScanResults();
752 scanres->setWpaGui(this);
758 void WpaGui::eventHistory()
765 eh = new EventHistory();
779 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
781 * QSocketNotifier cannot be used with Windows named pipes, so use a
782 * timer to check for received messages for now. This could be
783 * optimized be doing something specific to named pipes or Windows
784 * events, but it is not clear what would be the best way of doing that
788 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
790 if (scanres && !scanres->isVisible()) {
795 if (eh && !eh->isVisible()) {
800 if (udr && !udr->isVisible()) {
805 len = sizeof(buf) - 1;
806 if (ctrlRequest("PING", buf, &len) < 0) {
807 printf("PING failed - trying to reconnect\n");
808 if (openCtrlConnection(ctrl_iface) >= 0) {
809 printf("Reconnected successfully\n");
810 pingsToStatusUpdate = 0;
814 pingsToStatusUpdate--;
815 if (pingsToStatusUpdate <= 0) {
820 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
821 /* Use less frequent pings and status updates when the main window is
822 * hidden (running in taskbar). */
823 int interval = isHidden() ? 5000 : 1000;
824 if (timer->interval() != interval)
825 timer->setInterval(interval);
826 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
830 static int str_match(const char *a, const char *b)
832 return strncmp(a, b, strlen(b)) == 0;
836 void WpaGui::processMsg(char *msg)
838 char *pos = msg, *pos2;
844 priority = atoi(pos);
845 pos = strchr(pos, '>');
852 WpaMsg wm(pos, priority);
856 peers->event_notify(wm);
858 while (msgs.count() > 100)
861 /* Update last message with truncated version of the event */
862 if (strncmp(pos, "CTRL-", 5) == 0) {
863 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
870 QString lastmsg = pos2;
871 lastmsg.truncate(40);
872 textLastMessage->setText(lastmsg);
874 pingsToStatusUpdate = 0;
875 networkMayHaveChanged = true;
877 if (str_match(pos, WPA_CTRL_REQ))
878 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
879 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
880 scanres->updateResults();
881 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
882 showTrayMessage(QSystemTrayIcon::Information, 3,
883 tr("Disconnected from network."));
884 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
885 showTrayMessage(QSystemTrayIcon::Information, 3,
886 tr("Connection to network established."));
887 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
889 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
890 wpsStatusText->setText(tr("WPS AP in active PBC mode found"));
891 if (textStatus->text() == "INACTIVE" ||
892 textStatus->text() == "DISCONNECTED")
893 wpaguiTab->setCurrentWidget(wpsTab);
894 wpsInstructions->setText(tr("Press the PBC button on the "
895 "screen to start registration"));
896 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
897 wpsStatusText->setText(tr("WPS AP with recently selected "
899 if (textStatus->text() == "INACTIVE" ||
900 textStatus->text() == "DISCONNECTED")
901 wpaguiTab->setCurrentWidget(wpsTab);
902 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
903 wpsStatusText->setText(tr("WPS AP detected"));
904 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
905 wpsStatusText->setText(tr("PBC mode overlap detected"));
906 wpsInstructions->setText(tr("More than one AP is currently in "
907 "active WPS PBC mode. Wait couple "
908 "of minutes and try again"));
909 wpaguiTab->setCurrentWidget(wpsTab);
910 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
911 wpsStatusText->setText(tr("Network configuration received"));
912 wpaguiTab->setCurrentWidget(wpsTab);
913 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
914 if (strstr(pos, "(WSC)"))
915 wpsStatusText->setText(tr("Registration started"));
916 } else if (str_match(pos, WPS_EVENT_M2D)) {
917 wpsStatusText->setText(tr("Registrar does not yet know PIN"));
918 } else if (str_match(pos, WPS_EVENT_FAIL)) {
919 wpsStatusText->setText(tr("Registration failed"));
920 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
921 wpsStatusText->setText(tr("Registration succeeded"));
926 void WpaGui::processCtrlReq(const char *req)
932 udr = new UserDataRequest();
935 if (udr->setParams(this, req) < 0) {
945 void WpaGui::receiveMsgs()
950 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
951 len = sizeof(buf) - 1;
952 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
960 void WpaGui::connectB()
963 size_t reply_len = sizeof(reply);
964 ctrlRequest("REASSOCIATE", reply, &reply_len);
968 void WpaGui::selectNetwork( const QString &sel )
972 size_t reply_len = sizeof(reply);
974 if (cmd.compare(tr("Select any network"))) {
977 int pos = cmd.indexOf(':');
979 printf("Invalid selectNetwork '%s'\n",
980 cmd.toAscii().constData());
985 cmd.prepend("SELECT_NETWORK ");
986 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
992 void WpaGui::enableNetwork(const QString &sel)
996 size_t reply_len = sizeof(reply);
998 if (!cmd.startsWith("all")) {
999 int pos = cmd.indexOf(':');
1001 printf("Invalid enableNetwork '%s'\n",
1002 cmd.toAscii().constData());
1007 cmd.prepend("ENABLE_NETWORK ");
1008 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1013 void WpaGui::disableNetwork(const QString &sel)
1017 size_t reply_len = sizeof(reply);
1019 if (!cmd.startsWith("all")) {
1020 int pos = cmd.indexOf(':');
1022 printf("Invalid disableNetwork '%s'\n",
1023 cmd.toAscii().constData());
1028 cmd.prepend("DISABLE_NETWORK ");
1029 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1034 void WpaGui::editNetwork(const QString &sel)
1039 if (!cmd.compare(tr("Select any network"))) {
1040 int pos = sel.indexOf(':');
1042 printf("Invalid editNetwork '%s'\n",
1043 cmd.toAscii().constData());
1050 NetworkConfig *nc = new NetworkConfig();
1053 nc->setWpaGui(this);
1056 nc->paramsFromConfig(id);
1065 void WpaGui::editSelectedNetwork()
1067 if (networkSelect->count() < 1) {
1068 QMessageBox::information(
1069 this, tr("No Networks"),
1070 tr("There are no networks to edit.\n"));
1073 QString sel(networkSelect->currentText());
1078 void WpaGui::editListedNetwork()
1080 if (networkList->currentRow() < 0) {
1081 QMessageBox::information(this, tr("Select A Network"),
1082 tr("Select a network from the list to"
1086 QString sel(networkList->currentItem()->text());
1091 void WpaGui::triggerUpdate()
1094 networkMayHaveChanged = true;
1099 void WpaGui::addNetwork()
1101 NetworkConfig *nc = new NetworkConfig();
1104 nc->setWpaGui(this);
1111 void WpaGui::removeNetwork(const QString &sel)
1115 size_t reply_len = sizeof(reply);
1117 if (cmd.compare(tr("Select any network")))
1120 if (!cmd.startsWith("all")) {
1121 int pos = cmd.indexOf(':');
1123 printf("Invalid removeNetwork '%s'\n",
1124 cmd.toAscii().constData());
1129 cmd.prepend("REMOVE_NETWORK ");
1130 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1135 void WpaGui::removeSelectedNetwork()
1137 if (networkSelect->count() < 1) {
1138 QMessageBox::information(this, tr("No Networks"),
1139 tr("There are no networks to remove."
1143 QString sel(networkSelect->currentText());
1148 void WpaGui::removeListedNetwork()
1150 if (networkList->currentRow() < 0) {
1151 QMessageBox::information(this, tr("Select A Network"),
1152 tr("Select a network from the list "
1153 "to remove it.\n"));
1156 QString sel(networkList->currentItem()->text());
1161 void WpaGui::enableAllNetworks()
1168 void WpaGui::disableAllNetworks()
1171 disableNetwork(sel);
1175 void WpaGui::removeAllNetworks()
1182 int WpaGui::getNetworkDisabled(const QString &sel)
1186 size_t reply_len = sizeof(reply) - 1;
1187 int pos = cmd.indexOf(':');
1189 printf("Invalid getNetworkDisabled '%s'\n",
1190 cmd.toAscii().constData());
1194 cmd.prepend("GET_NETWORK ");
1195 cmd.append(" disabled");
1197 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1198 && reply_len >= 1) {
1199 reply[reply_len] = '\0';
1200 if (!str_match(reply, "FAIL"))
1208 void WpaGui::updateNetworkDisabledStatus()
1210 if (networkList->currentRow() < 0)
1213 QString sel(networkList->currentItem()->text());
1215 switch (getNetworkDisabled(sel)) {
1217 if (!enableRadioButton->isChecked())
1218 enableRadioButton->setChecked(true);
1221 if (!disableRadioButton->isChecked())
1222 disableRadioButton->setChecked(true);
1228 void WpaGui::enableListedNetwork(bool enabled)
1230 if (networkList->currentRow() < 0 || !enabled)
1233 QString sel(networkList->currentItem()->text());
1235 if (getNetworkDisabled(sel) == 1)
1240 void WpaGui::disableListedNetwork(bool disabled)
1242 if (networkList->currentRow() < 0 || !disabled)
1245 QString sel(networkList->currentItem()->text());
1247 if (getNetworkDisabled(sel) == 0)
1248 disableNetwork(sel);
1252 void WpaGui::saveConfig()
1257 len = sizeof(buf) - 1;
1258 ctrlRequest("SAVE_CONFIG", buf, &len);
1262 if (str_match(buf, "FAIL"))
1263 QMessageBox::warning(
1264 this, tr("Failed to save configuration"),
1265 tr("The configuration could not be saved.\n"
1267 "The update_config=1 configuration option\n"
1268 "must be used for configuration saving to\n"
1269 "be permitted.\n"));
1271 QMessageBox::information(
1272 this, tr("Saved configuration"),
1273 tr("The current configuration was saved."
1278 void WpaGui::selectAdapter( const QString & sel )
1280 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1281 printf("Failed to open control connection to "
1282 "wpa_supplicant.\n");
1288 void WpaGui::createTrayIcon(bool trayOnly)
1290 QApplication::setQuitOnLastWindowClosed(false);
1292 tray_icon = new QSystemTrayIcon(this);
1293 tray_icon->setToolTip(qAppName() + tr(" - wpa_supplicant user interface"));
1294 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1295 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1297 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1300 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1301 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1303 ackTrayIcon = false;
1305 tray_menu = new QMenu(this);
1307 disconnectAction = new QAction(tr("&Disconnect"), this);
1308 reconnectAction = new QAction(tr("Re&connect"), this);
1309 connect(disconnectAction, SIGNAL(triggered()), this,
1310 SLOT(disconnect()));
1311 connect(reconnectAction, SIGNAL(triggered()), this,
1313 tray_menu->addAction(disconnectAction);
1314 tray_menu->addAction(reconnectAction);
1315 tray_menu->addSeparator();
1317 eventAction = new QAction(tr("&Event History"), this);
1318 scanAction = new QAction(tr("Scan &Results"), this);
1319 statAction = new QAction(tr("S&tatus"), this);
1320 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1321 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1322 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1323 tray_menu->addAction(eventAction);
1324 tray_menu->addAction(scanAction);
1325 tray_menu->addAction(statAction);
1326 tray_menu->addSeparator();
1328 showAction = new QAction(tr("&Show Window"), this);
1329 hideAction = new QAction(tr("&Hide Window"), this);
1330 quitAction = new QAction(tr("&Quit"), this);
1331 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1332 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1333 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1334 tray_menu->addAction(showAction);
1335 tray_menu->addAction(hideAction);
1336 tray_menu->addSeparator();
1337 tray_menu->addAction(quitAction);
1339 tray_icon->setContextMenu(tray_menu);
1349 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1350 const QString & msg)
1352 if (!QSystemTrayIcon::supportsMessages())
1355 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1358 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1362 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1365 /* use close() here instead of hide() and allow the
1366 * custom closeEvent handler take care of children */
1367 case QSystemTrayIcon::Trigger:
1377 case QSystemTrayIcon::MiddleClick:
1386 void WpaGui::showTrayStatus()
1391 len = sizeof(buf) - 1;
1392 if (ctrlRequest("STATUS", buf, &len) < 0)
1396 QString msg, status(buf);
1398 QStringList lines = status.split(QRegExp("\\n"));
1399 for (QStringList::Iterator it = lines.begin();
1400 it != lines.end(); it++) {
1401 int pos = (*it).indexOf('=') + 1;
1405 if ((*it).startsWith("bssid="))
1406 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1407 else if ((*it).startsWith("ssid="))
1408 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1409 else if ((*it).startsWith("pairwise_cipher="))
1410 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1411 else if ((*it).startsWith("group_cipher="))
1412 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1413 else if ((*it).startsWith("key_mgmt="))
1414 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1415 else if ((*it).startsWith("wpa_state="))
1416 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1417 else if ((*it).startsWith("ip_address="))
1418 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1419 else if ((*it).startsWith("Supplicant PAE state="))
1420 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1421 else if ((*it).startsWith("EAP state="))
1422 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1426 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1430 void WpaGui::closeEvent(QCloseEvent *event)
1456 if (tray_icon && !ackTrayIcon) {
1457 /* give user a visual hint that the tray icon exists */
1458 if (QSystemTrayIcon::supportsMessages()) {
1460 showTrayMessage(QSystemTrayIcon::Information, 3,
1462 tr(" will keep running in "
1463 "the system tray."));
1465 QMessageBox::information(this, qAppName() +
1467 tr("The program will keep "
1468 "running in the system "
1478 void WpaGui::wpsDialog()
1480 wpaguiTab->setCurrentWidget(wpsTab);
1484 void WpaGui::peersDialog()
1491 peers = new Peers();
1494 peers->setWpaGui(this);
1500 void WpaGui::tabChanged(int index)
1508 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1509 if (bssFromScan.isEmpty())
1510 wpsApPinButton->setEnabled(false);
1514 void WpaGui::wpsPbc()
1517 size_t reply_len = sizeof(reply);
1519 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1522 wpsPinEdit->setEnabled(false);
1523 if (wpsStatusText->text().compare(tr("WPS AP in active PBC mode found"))) {
1524 wpsInstructions->setText(tr("Press the push button on the AP to "
1525 "start the PBC mode."));
1527 wpsInstructions->setText(tr("If you have not yet done so, press "
1528 "the push button on the AP to start "
1531 wpsStatusText->setText(tr("Waiting for Registrar"));
1536 void WpaGui::wpsGeneratePin()
1539 size_t reply_len = sizeof(reply) - 1;
1541 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1544 reply[reply_len] = '\0';
1546 wpsPinEdit->setText(reply);
1547 wpsPinEdit->setEnabled(true);
1548 wpsInstructions->setText(tr("Enter the generated PIN into the Registrar "
1549 "(either the internal one in the AP or an "
1551 wpsStatusText->setText(tr("Waiting for Registrar"));
1556 void WpaGui::setBssFromScan(const QString &bssid)
1558 bssFromScan = bssid;
1559 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1560 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1561 wpsStatusText->setText(tr("WPS AP selected from scan results"));
1562 wpsInstructions->setText(tr("If you want to use an AP device PIN, e.g., "
1563 "from a label in the device, enter the eight "
1564 "digit AP PIN and click Use AP PIN button."));
1568 void WpaGui::wpsApPinChanged(const QString &text)
1570 wpsApPinButton->setEnabled(text.length() == 8);
1574 void WpaGui::wpsApPin()
1577 size_t reply_len = sizeof(reply);
1579 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1580 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1583 wpsStatusText->setText(tr("Waiting for AP/Enrollee"));
1588 void WpaGui::stopWpsRun(bool success)
1591 wpsStatusText->setText(success ? tr("Connected to the network") :
1594 wpsStatusText->setText("");
1595 wpsPinEdit->setEnabled(false);
1596 wpsInstructions->setText("");
1599 wpsApPinEdit->setEnabled(false);
1600 wpsApPinButton->setEnabled(false);
1604 #ifdef CONFIG_NATIVE_WINDOWS
1607 #define WPASVC_NAME TEXT("wpasvc")
1610 class ErrorMsg : public QMessageBox {
1612 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1613 void showMsg(QString msg);
1618 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1619 QMessageBox(parent), err(last_err)
1621 setWindowTitle(tr("wpa_gui error"));
1622 setIcon(QMessageBox::Warning);
1625 void ErrorMsg::showMsg(QString msg)
1630 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1631 FORMAT_MESSAGE_FROM_SYSTEM,
1632 NULL, err, 0, (LPTSTR) (void *) &buf,
1634 QString msg = QString::fromWCharArray(buf);
1635 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1638 setInformativeText(QString("[%1]").arg(err));
1645 void WpaGui::startService()
1649 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1651 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1655 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1657 ErrorMsg(this).showMsg(tr("OpenService failed"));
1658 CloseServiceHandle(scm);
1662 if (!StartService(svc, 0, NULL)) {
1663 ErrorMsg(this).showMsg(tr("Failed to start wpa_supplicant "
1667 CloseServiceHandle(svc);
1668 CloseServiceHandle(scm);
1672 void WpaGui::stopService()
1675 SERVICE_STATUS status;
1677 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1679 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1683 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1685 ErrorMsg(this).showMsg(tr("OpenService failed"));
1686 CloseServiceHandle(scm);
1690 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1691 ErrorMsg(this).showMsg(tr("Failed to stop wpa_supplicant "
1695 CloseServiceHandle(svc);
1696 CloseServiceHandle(scm);
1700 bool WpaGui::serviceRunning()
1703 SERVICE_STATUS status;
1704 bool running = false;
1706 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1708 printf(tr("OpenSCManager failed: %d\n"), (int) GetLastError());
1712 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1714 printf(tr("OpenService failed: %d\n\n"), (int) GetLastError());
1715 CloseServiceHandle(scm);
1719 if (QueryServiceStatus(svc, &status)) {
1720 if (status.dwCurrentState != SERVICE_STOPPED)
1724 CloseServiceHandle(svc);
1725 CloseServiceHandle(scm);
1730 #endif /* CONFIG_NATIVE_WINDOWS */
1733 void WpaGui::addInterface()
1739 add_iface = new AddInterface(this, this);
1745 #ifndef QT_NO_SESSIONMANAGER
1746 void WpaGui::saveState()
1748 QSettings settings("wpa_supplicant", "wpa_gui");
1749 settings.beginGroup("state");
1750 settings.setValue("session_id", app->sessionId());
1751 settings.setValue("in_tray", inTray);
1752 settings.endGroup();