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 "userdatarequest.h"
33 #include "networkconfig.h"
37 #define printf wpagui_printf
38 static int wpagui_printf(const char *, ...)
44 WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags)
49 #ifdef CONFIG_NATIVE_WINDOWS
50 fileStopServiceAction = new QAction(this);
51 fileStopServiceAction->setObjectName("Stop Service");
52 fileStopServiceAction->setIconText("Stop Service");
53 fileMenu->insertAction(actionWPS, fileStopServiceAction);
55 fileStartServiceAction = new QAction(this);
56 fileStartServiceAction->setObjectName("Start Service");
57 fileStartServiceAction->setIconText("Start Service");
58 fileMenu->insertAction(fileStopServiceAction, fileStartServiceAction);
60 connect(fileStartServiceAction, SIGNAL(triggered()), this,
61 SLOT(startService()));
62 connect(fileStopServiceAction, SIGNAL(triggered()), this,
65 addInterfaceAction = new QAction(this);
66 addInterfaceAction->setIconText("Add Interface");
67 fileMenu->insertAction(fileStartServiceAction, addInterfaceAction);
69 connect(addInterfaceAction, SIGNAL(triggered()), this,
70 SLOT(addInterface()));
71 #endif /* CONFIG_NATIVE_WINDOWS */
75 connect(fileEventHistoryAction, SIGNAL(triggered()), this,
76 SLOT(eventHistory()));
77 connect(fileSaveConfigAction, SIGNAL(triggered()), this,
79 connect(actionWPS, SIGNAL(triggered()), this, SLOT(wpsDialog()));
80 connect(fileExitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
81 connect(networkAddAction, SIGNAL(triggered()), this,
83 connect(networkEditAction, SIGNAL(triggered()), this,
84 SLOT(editSelectedNetwork()));
85 connect(networkRemoveAction, SIGNAL(triggered()), this,
86 SLOT(removeSelectedNetwork()));
87 connect(networkEnableAllAction, SIGNAL(triggered()), this,
88 SLOT(enableAllNetworks()));
89 connect(networkDisableAllAction, SIGNAL(triggered()), this,
90 SLOT(disableAllNetworks()));
91 connect(networkRemoveAllAction, SIGNAL(triggered()), this,
92 SLOT(removeAllNetworks()));
93 connect(helpIndexAction, SIGNAL(triggered()), this, SLOT(helpIndex()));
94 connect(helpContentsAction, SIGNAL(triggered()), this,
95 SLOT(helpContents()));
96 connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(helpAbout()));
97 connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));
98 connect(scanButton, SIGNAL(clicked()), this, SLOT(scan()));
99 connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB()));
100 connect(adapterSelect, SIGNAL(activated(const QString&)), this,
101 SLOT(selectAdapter(const QString&)));
102 connect(networkSelect, SIGNAL(activated(const QString&)), this,
103 SLOT(selectNetwork(const QString&)));
104 connect(addNetworkButton, SIGNAL(clicked()), this, SLOT(addNetwork()));
105 connect(editNetworkButton, SIGNAL(clicked()), this,
106 SLOT(editListedNetwork()));
107 connect(removeNetworkButton, SIGNAL(clicked()), this,
108 SLOT(removeListedNetwork()));
109 connect(networkList, SIGNAL(itemSelectionChanged()), this,
110 SLOT(updateNetworkDisabledStatus()));
111 connect(enableRadioButton, SIGNAL(toggled(bool)), this,
112 SLOT(enableListedNetwork(bool)));
113 connect(disableRadioButton, SIGNAL(toggled(bool)), this,
114 SLOT(disableListedNetwork(bool)));
115 connect(scanNetworkButton, SIGNAL(clicked()), this, SLOT(scan()));
116 connect(networkList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
117 this, SLOT(editListedNetwork()));
118 connect(wpaguiTab, SIGNAL(currentChanged(int)), this,
119 SLOT(tabChanged(int)));
120 connect(wpsPbcButton, SIGNAL(clicked()), this, SLOT(wpsPbc()));
121 connect(wpsPinButton, SIGNAL(clicked()), this, SLOT(wpsGeneratePin()));
122 connect(wpsApPinEdit, SIGNAL(textChanged(const QString &)), this,
123 SLOT(wpsApPinChanged(const QString &)));
124 connect(wpsApPinButton, SIGNAL(clicked()), this, SLOT(wpsApPin()));
136 ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
140 if (QSystemTrayIcon::isSystemTrayAvailable())
141 createTrayIcon(startInTray);
145 textStatus->setText("connecting to wpa_supplicant");
146 timer = new QTimer(this);
147 connect(timer, SIGNAL(timeout()), SLOT(ping()));
148 timer->setSingleShot(FALSE);
151 if (openCtrlConnection(ctrl_iface) < 0) {
152 printf("Failed to open control connection to "
153 "wpa_supplicant.\n");
157 networkMayHaveChanged = true;
167 wpa_ctrl_detach(monitor_conn);
168 wpa_ctrl_close(monitor_conn);
172 wpa_ctrl_close(ctrl_conn);
203 free(ctrl_iface_dir);
204 ctrl_iface_dir = NULL;
208 void WpaGui::languageChange()
214 void WpaGui::parse_argv()
218 c = getopt(qApp->argc(), qApp->argv(), "i:p:t");
224 ctrl_iface = strdup(optarg);
227 free(ctrl_iface_dir);
228 ctrl_iface_dir = strdup(optarg);
238 int WpaGui::openCtrlConnection(const char *ifname)
242 char buf[2048], *pos, *pos2;
246 if (ifname != ctrl_iface) {
248 ctrl_iface = strdup(ifname);
251 #ifdef CONFIG_CTRL_IFACE_UDP
253 ctrl_iface = strdup("udp");
254 #endif /* CONFIG_CTRL_IFACE_UDP */
255 #ifdef CONFIG_CTRL_IFACE_UNIX
257 DIR *dir = opendir(ctrl_iface_dir);
261 while ((dent = readdir(dir))) {
262 #ifdef _DIRENT_HAVE_D_TYPE
263 /* Skip the file if it is not a socket.
264 * Also accept DT_UNKNOWN (0) in case
265 * the C library or underlying file
266 * system does not support d_type. */
267 if (dent->d_type != DT_SOCK &&
268 dent->d_type != DT_UNKNOWN)
270 #endif /* _DIRENT_HAVE_D_TYPE */
272 if (strcmp(dent->d_name, ".") == 0 ||
273 strcmp(dent->d_name, "..") == 0)
275 printf("Selected interface '%s'\n",
277 ctrl_iface = strdup(dent->d_name);
282 #endif /* CONFIG_CTRL_IFACE_UNIX */
283 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
284 struct wpa_ctrl *ctrl;
290 ctrl = wpa_ctrl_open(NULL);
292 len = sizeof(buf) - 1;
293 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf,
297 pos = strchr(buf, '\n');
300 ctrl_iface = strdup(buf);
302 wpa_ctrl_close(ctrl);
304 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
307 if (ctrl_iface == NULL) {
308 #ifdef CONFIG_NATIVE_WINDOWS
309 static bool first = true;
310 if (first && !serviceRunning()) {
312 if (QMessageBox::warning(
314 "wpa_supplicant service is not running.\n"
315 "Do you want to start it?",
316 QMessageBox::Yes | QMessageBox::No) ==
320 #endif /* CONFIG_NATIVE_WINDOWS */
324 #ifdef CONFIG_CTRL_IFACE_UNIX
325 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
326 cfile = (char *) malloc(flen);
329 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
330 #else /* CONFIG_CTRL_IFACE_UNIX */
331 flen = strlen(ctrl_iface) + 1;
332 cfile = (char *) malloc(flen);
335 snprintf(cfile, flen, "%s", ctrl_iface);
336 #endif /* CONFIG_CTRL_IFACE_UNIX */
339 wpa_ctrl_close(ctrl_conn);
346 wpa_ctrl_detach(monitor_conn);
347 wpa_ctrl_close(monitor_conn);
351 printf("Trying to connect to '%s'\n", cfile);
352 ctrl_conn = wpa_ctrl_open(cfile);
353 if (ctrl_conn == NULL) {
357 monitor_conn = wpa_ctrl_open(cfile);
359 if (monitor_conn == NULL) {
360 wpa_ctrl_close(ctrl_conn);
363 if (wpa_ctrl_attach(monitor_conn)) {
364 printf("Failed to attach to wpa_supplicant\n");
365 wpa_ctrl_close(monitor_conn);
367 wpa_ctrl_close(ctrl_conn);
372 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
373 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
374 QSocketNotifier::Read, this);
375 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
378 adapterSelect->clear();
379 adapterSelect->addItem(ctrl_iface);
380 adapterSelect->setCurrentIndex(0);
382 len = sizeof(buf) - 1;
383 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
388 pos2 = strchr(pos, '\n');
391 if (strcmp(pos, ctrl_iface) != 0)
392 adapterSelect->addItem(pos);
400 len = sizeof(buf) - 1;
401 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len,
406 QStringList types = res.split(QChar(' '));
407 actionWPS->setEnabled(types.contains("WSC"));
414 static void wpa_gui_msg_cb(char *msg, size_t)
416 /* This should not happen anymore since two control connections are
418 printf("missed message: %s\n", msg);
422 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
426 if (ctrl_conn == NULL)
428 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen,
431 printf("'%s' command timed out.\n", cmd);
433 printf("'%s' command failed.\n", cmd);
439 void WpaGui::updateStatus()
441 char buf[2048], *start, *end, *pos;
444 pingsToStatusUpdate = 10;
446 len = sizeof(buf) - 1;
447 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
448 textStatus->setText("Could not get status from "
450 textAuthentication->clear();
451 textEncryption->clear();
454 textIpAddress->clear();
456 #ifdef CONFIG_NATIVE_WINDOWS
457 static bool first = true;
458 if (first && (ctrl_iface == NULL || *ctrl_iface == '\0')) {
460 if (QMessageBox::information(
462 "No network interfaces in use.\n"
463 "Would you like to add one?",
464 QMessageBox::Yes | QMessageBox::No) ==
468 #endif /* CONFIG_NATIVE_WINDOWS */
474 bool auth_updated = false, ssid_updated = false;
475 bool bssid_updated = false, ipaddr_updated = false;
476 bool status_updated = false;
477 char *pairwise_cipher = NULL, *group_cipher = NULL;
482 end = strchr(start, '\n');
486 while (end[0] && end[1])
491 pos = strchr(start, '=');
494 if (strcmp(start, "bssid") == 0) {
495 bssid_updated = true;
496 textBssid->setText(pos);
497 } else if (strcmp(start, "ssid") == 0) {
499 textSsid->setText(pos);
500 } else if (strcmp(start, "ip_address") == 0) {
501 ipaddr_updated = true;
502 textIpAddress->setText(pos);
503 } else if (strcmp(start, "wpa_state") == 0) {
504 status_updated = true;
505 textStatus->setText(pos);
506 } else if (strcmp(start, "key_mgmt") == 0) {
508 textAuthentication->setText(pos);
509 /* TODO: could add EAP status to this */
510 } else if (strcmp(start, "pairwise_cipher") == 0) {
511 pairwise_cipher = pos;
512 } else if (strcmp(start, "group_cipher") == 0) {
522 if (pairwise_cipher || group_cipher) {
524 if (pairwise_cipher && group_cipher &&
525 strcmp(pairwise_cipher, group_cipher) != 0) {
526 encr.append(pairwise_cipher);
528 encr.append(group_cipher);
529 } else if (pairwise_cipher) {
530 encr.append(pairwise_cipher);
532 encr.append(group_cipher);
533 encr.append(" [group key only]");
535 textEncryption->setText(encr);
537 textEncryption->clear();
542 textAuthentication->clear();
548 textIpAddress->clear();
552 void WpaGui::updateNetworks()
554 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
556 int first_active = -1;
557 int was_selected = -1;
558 bool current = false;
560 if (!networkMayHaveChanged)
563 if (networkList->currentRow() >= 0)
564 was_selected = networkList->currentRow();
566 networkSelect->clear();
567 networkList->clear();
569 if (ctrl_conn == NULL)
572 len = sizeof(buf) - 1;
573 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
577 start = strchr(buf, '\n');
584 end = strchr(start, '\n');
588 while (end[0] && end[1])
594 ssid = strchr(id, '\t');
598 bssid = strchr(ssid, '\t');
602 flags = strchr(bssid, '\t');
608 network.append(": ");
609 network.append(ssid);
610 networkSelect->addItem(network);
611 networkList->addItem(network);
613 if (strstr(flags, "[CURRENT]")) {
614 networkSelect->setCurrentIndex(networkSelect->count() -
617 } else if (first_active < 0 &&
618 strstr(flags, "[DISABLED]") == NULL)
619 first_active = networkSelect->count() - 1;
626 if (networkSelect->count() > 1)
627 networkSelect->addItem("Select any network");
629 if (!current && first_active >= 0)
630 networkSelect->setCurrentIndex(first_active);
632 if (was_selected >= 0 && networkList->count() > 0) {
633 if (was_selected < networkList->count())
634 networkList->setCurrentRow(was_selected);
636 networkList->setCurrentRow(networkList->count() - 1);
639 networkList->setCurrentRow(networkSelect->currentIndex());
641 networkMayHaveChanged = false;
645 void WpaGui::helpIndex()
647 printf("helpIndex\n");
651 void WpaGui::helpContents()
653 printf("helpContents\n");
657 void WpaGui::helpAbout()
659 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
660 "Copyright (c) 2003-2008,\n"
661 "Jouni Malinen <j@w1.fi>\n"
662 "and contributors.\n"
664 "This program is free software. You can\n"
665 "distribute it and/or modify it under the terms "
667 "the GNU General Public License version 2.\n"
669 "Alternatively, this software may be distributed\n"
670 "under the terms of the BSD license.\n"
672 "This product includes software developed\n"
673 "by the OpenSSL Project for use in the\n"
674 "OpenSSL Toolkit (http://www.openssl.org/)\n");
678 void WpaGui::disconnect()
681 size_t reply_len = sizeof(reply);
682 ctrlRequest("DISCONNECT", reply, &reply_len);
694 scanres = new ScanResults();
697 scanres->setWpaGui(this);
703 void WpaGui::eventHistory()
710 eh = new EventHistory();
724 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
726 * QSocketNotifier cannot be used with Windows named pipes, so use a
727 * timer to check for received messages for now. This could be
728 * optimized be doing something specific to named pipes or Windows
729 * events, but it is not clear what would be the best way of doing that
733 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
735 if (scanres && !scanres->isVisible()) {
740 if (eh && !eh->isVisible()) {
745 if (udr && !udr->isVisible()) {
750 len = sizeof(buf) - 1;
751 if (ctrlRequest("PING", buf, &len) < 0) {
752 printf("PING failed - trying to reconnect\n");
753 if (openCtrlConnection(ctrl_iface) >= 0) {
754 printf("Reconnected successfully\n");
755 pingsToStatusUpdate = 0;
759 pingsToStatusUpdate--;
760 if (pingsToStatusUpdate <= 0) {
765 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
766 /* Use less frequent pings and status updates when the main window is
767 * hidden (running in taskbar). */
768 int interval = isHidden() ? 5000 : 1000;
769 if (timer->interval() != interval)
770 timer->setInterval(interval);
771 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
775 static int str_match(const char *a, const char *b)
777 return strncmp(a, b, strlen(b)) == 0;
781 void WpaGui::processMsg(char *msg)
783 char *pos = msg, *pos2;
789 priority = atoi(pos);
790 pos = strchr(pos, '>');
797 WpaMsg wm(pos, priority);
801 while (msgs.count() > 100)
804 /* Update last message with truncated version of the event */
805 if (strncmp(pos, "CTRL-", 5) == 0) {
806 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
813 QString lastmsg = pos2;
814 lastmsg.truncate(40);
815 textLastMessage->setText(lastmsg);
817 pingsToStatusUpdate = 0;
818 networkMayHaveChanged = true;
820 if (str_match(pos, WPA_CTRL_REQ))
821 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
822 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
823 scanres->updateResults();
824 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
825 showTrayMessage(QSystemTrayIcon::Information, 3,
826 "Disconnected from network.");
827 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
828 showTrayMessage(QSystemTrayIcon::Information, 3,
829 "Connection to network established.");
830 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
832 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
833 showTrayMessage(QSystemTrayIcon::Information, 3,
834 "Wi-Fi Protected Setup (WPS) AP\n"
835 "in active PBC mode found.");
836 wpsStatusText->setText("WPS AP in active PBC mode found");
837 wpaguiTab->setCurrentWidget(wpsTab);
838 wpsInstructions->setText("Press the PBC button on the screen "
839 "to start registration");
840 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
841 showTrayMessage(QSystemTrayIcon::Information, 3,
842 "Wi-Fi Protected Setup (WPS) AP\n"
843 " in active PIN mode found.");
844 wpsStatusText->setText("WPS AP with recently selected "
846 wpaguiTab->setCurrentWidget(wpsTab);
847 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
848 showTrayMessage(QSystemTrayIcon::Information, 3,
849 "Wi-Fi Protected Setup (WPS)\n"
851 wpsStatusText->setText("WPS AP detected");
852 wpaguiTab->setCurrentWidget(wpsTab);
853 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
854 showTrayMessage(QSystemTrayIcon::Information, 3,
855 "Wi-Fi Protected Setup (WPS)\n"
856 "PBC mode overlap detected.");
857 wpsStatusText->setText("PBC mode overlap detected");
858 wpsInstructions->setText("More than one AP is currently in "
859 "active WPS PBC mode. Wait couple of "
860 "minutes and try again");
861 wpaguiTab->setCurrentWidget(wpsTab);
862 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
863 wpsStatusText->setText("Network configuration received");
864 wpaguiTab->setCurrentWidget(wpsTab);
865 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
866 if (strstr(pos, "(WSC)"))
867 wpsStatusText->setText("Registration started");
868 } else if (str_match(pos, WPS_EVENT_M2D)) {
869 wpsStatusText->setText("Registrar does not yet know PIN");
870 } else if (str_match(pos, WPS_EVENT_FAIL)) {
871 wpsStatusText->setText("Registration failed");
872 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
873 wpsStatusText->setText("Registration succeeded");
878 void WpaGui::processCtrlReq(const char *req)
884 udr = new UserDataRequest();
887 if (udr->setParams(this, req) < 0) {
897 void WpaGui::receiveMsgs()
902 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
903 len = sizeof(buf) - 1;
904 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
912 void WpaGui::connectB()
915 size_t reply_len = sizeof(reply);
916 ctrlRequest("REASSOCIATE", reply, &reply_len);
920 void WpaGui::selectNetwork( const QString &sel )
924 size_t reply_len = sizeof(reply);
926 if (cmd.startsWith("Select any")) {
929 int pos = cmd.indexOf(':');
931 printf("Invalid selectNetwork '%s'\n",
932 cmd.toAscii().constData());
937 cmd.prepend("SELECT_NETWORK ");
938 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
944 void WpaGui::enableNetwork(const QString &sel)
948 size_t reply_len = sizeof(reply);
950 if (!cmd.startsWith("all")) {
951 int pos = cmd.indexOf(':');
953 printf("Invalid enableNetwork '%s'\n",
954 cmd.toAscii().constData());
959 cmd.prepend("ENABLE_NETWORK ");
960 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
965 void WpaGui::disableNetwork(const QString &sel)
969 size_t reply_len = sizeof(reply);
971 if (!cmd.startsWith("all")) {
972 int pos = cmd.indexOf(':');
974 printf("Invalid disableNetwork '%s'\n",
975 cmd.toAscii().constData());
980 cmd.prepend("DISABLE_NETWORK ");
981 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
986 void WpaGui::editNetwork(const QString &sel)
991 if (!cmd.startsWith("Select any")) {
992 int pos = sel.indexOf(':');
994 printf("Invalid editNetwork '%s'\n",
995 cmd.toAscii().constData());
1002 NetworkConfig *nc = new NetworkConfig();
1005 nc->setWpaGui(this);
1008 nc->paramsFromConfig(id);
1017 void WpaGui::editSelectedNetwork()
1019 if (networkSelect->count() < 1) {
1020 QMessageBox::information(this, "No Networks",
1021 "There are no networks to edit.\n");
1024 QString sel(networkSelect->currentText());
1029 void WpaGui::editListedNetwork()
1031 if (networkList->currentRow() < 0) {
1032 QMessageBox::information(this, "Select A Network",
1033 "Select a network from the list to"
1037 QString sel(networkList->currentItem()->text());
1042 void WpaGui::triggerUpdate()
1045 networkMayHaveChanged = true;
1050 void WpaGui::addNetwork()
1052 NetworkConfig *nc = new NetworkConfig();
1055 nc->setWpaGui(this);
1062 void WpaGui::removeNetwork(const QString &sel)
1066 size_t reply_len = sizeof(reply);
1068 if (cmd.startsWith("Select any"))
1071 if (!cmd.startsWith("all")) {
1072 int pos = cmd.indexOf(':');
1074 printf("Invalid removeNetwork '%s'\n",
1075 cmd.toAscii().constData());
1080 cmd.prepend("REMOVE_NETWORK ");
1081 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1086 void WpaGui::removeSelectedNetwork()
1088 if (networkSelect->count() < 1) {
1089 QMessageBox::information(this, "No Networks",
1090 "There are no networks to remove.\n");
1093 QString sel(networkSelect->currentText());
1098 void WpaGui::removeListedNetwork()
1100 if (networkList->currentRow() < 0) {
1101 QMessageBox::information(this, "Select A Network",
1102 "Select a network from the list to"
1106 QString sel(networkList->currentItem()->text());
1111 void WpaGui::enableAllNetworks()
1118 void WpaGui::disableAllNetworks()
1121 disableNetwork(sel);
1125 void WpaGui::removeAllNetworks()
1132 int WpaGui::getNetworkDisabled(const QString &sel)
1136 size_t reply_len = sizeof(reply) - 1;
1137 int pos = cmd.indexOf(':');
1139 printf("Invalid getNetworkDisabled '%s'\n",
1140 cmd.toAscii().constData());
1144 cmd.prepend("GET_NETWORK ");
1145 cmd.append(" disabled");
1147 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1148 && reply_len >= 1) {
1149 reply[reply_len] = '\0';
1150 if (!str_match(reply, "FAIL"))
1158 void WpaGui::updateNetworkDisabledStatus()
1160 if (networkList->currentRow() < 0)
1163 QString sel(networkList->currentItem()->text());
1165 switch (getNetworkDisabled(sel)) {
1167 if (!enableRadioButton->isChecked())
1168 enableRadioButton->setChecked(true);
1171 if (!disableRadioButton->isChecked())
1172 disableRadioButton->setChecked(true);
1178 void WpaGui::enableListedNetwork(bool enabled)
1180 if (networkList->currentRow() < 0 || !enabled)
1183 QString sel(networkList->currentItem()->text());
1185 if (getNetworkDisabled(sel) == 1)
1190 void WpaGui::disableListedNetwork(bool disabled)
1192 if (networkList->currentRow() < 0 || !disabled)
1195 QString sel(networkList->currentItem()->text());
1197 if (getNetworkDisabled(sel) == 0)
1198 disableNetwork(sel);
1202 void WpaGui::saveConfig()
1207 len = sizeof(buf) - 1;
1208 ctrlRequest("SAVE_CONFIG", buf, &len);
1212 if (str_match(buf, "FAIL"))
1213 QMessageBox::warning(this, "Failed to save configuration",
1214 "The configuration could not be saved.\n"
1216 "The update_config=1 configuration option\n"
1217 "must be used for configuration saving to\n"
1220 QMessageBox::information(this, "Saved configuration",
1221 "The current configuration was saved."
1226 void WpaGui::selectAdapter( const QString & sel )
1228 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1229 printf("Failed to open control connection to "
1230 "wpa_supplicant.\n");
1236 void WpaGui::createTrayIcon(bool trayOnly)
1238 QApplication::setQuitOnLastWindowClosed(false);
1240 tray_icon = new QSystemTrayIcon(this);
1241 tray_icon->setToolTip(qAppName() + " - wpa_supplicant user interface");
1242 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1243 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1245 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1248 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1249 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1251 ackTrayIcon = false;
1253 tray_menu = new QMenu(this);
1255 disconnectAction = new QAction("&Disconnect", this);
1256 reconnectAction = new QAction("Re&connect", this);
1257 connect(disconnectAction, SIGNAL(triggered()), this,
1258 SLOT(disconnect()));
1259 connect(reconnectAction, SIGNAL(triggered()), this,
1261 tray_menu->addAction(disconnectAction);
1262 tray_menu->addAction(reconnectAction);
1263 tray_menu->addSeparator();
1265 eventAction = new QAction("&Event History", this);
1266 scanAction = new QAction("Scan &Results", this);
1267 statAction = new QAction("S&tatus", this);
1268 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1269 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1270 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1271 tray_menu->addAction(eventAction);
1272 tray_menu->addAction(scanAction);
1273 tray_menu->addAction(statAction);
1274 tray_menu->addSeparator();
1276 showAction = new QAction("&Show Window", this);
1277 hideAction = new QAction("&Hide Window", this);
1278 quitAction = new QAction("&Quit", this);
1279 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1280 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1281 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1282 tray_menu->addAction(showAction);
1283 tray_menu->addAction(hideAction);
1284 tray_menu->addSeparator();
1285 tray_menu->addAction(quitAction);
1287 tray_icon->setContextMenu(tray_menu);
1296 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1297 const QString & msg)
1299 if (!QSystemTrayIcon::supportsMessages())
1302 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1305 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1309 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1312 /* use close() here instead of hide() and allow the
1313 * custom closeEvent handler take care of children */
1314 case QSystemTrayIcon::Trigger:
1321 case QSystemTrayIcon::MiddleClick:
1330 void WpaGui::showTrayStatus()
1335 len = sizeof(buf) - 1;
1336 if (ctrlRequest("STATUS", buf, &len) < 0)
1340 QString msg, status(buf);
1342 QStringList lines = status.split(QRegExp("\\n"));
1343 for (QStringList::Iterator it = lines.begin();
1344 it != lines.end(); it++) {
1345 int pos = (*it).indexOf('=') + 1;
1349 if ((*it).startsWith("bssid="))
1350 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1351 else if ((*it).startsWith("ssid="))
1352 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1353 else if ((*it).startsWith("pairwise_cipher="))
1354 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1355 else if ((*it).startsWith("group_cipher="))
1356 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1357 else if ((*it).startsWith("key_mgmt="))
1358 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1359 else if ((*it).startsWith("wpa_state="))
1360 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1361 else if ((*it).startsWith("ip_address="))
1362 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1363 else if ((*it).startsWith("Supplicant PAE state="))
1364 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1365 else if ((*it).startsWith("EAP state="))
1366 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1370 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1374 void WpaGui::closeEvent(QCloseEvent *event)
1394 if (tray_icon && !ackTrayIcon) {
1395 /* give user a visual hint that the tray icon exists */
1396 if (QSystemTrayIcon::supportsMessages()) {
1398 showTrayMessage(QSystemTrayIcon::Information, 3,
1399 qAppName() + " will keep running in "
1400 "the system tray.");
1402 QMessageBox::information(this, qAppName() + " systray",
1403 "The program will keep "
1404 "running in the system "
1414 void WpaGui::wpsDialog()
1416 wpaguiTab->setCurrentWidget(wpsTab);
1420 void WpaGui::tabChanged(int index)
1428 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1429 if (bssFromScan.isEmpty())
1430 wpsApPinButton->setEnabled(false);
1434 void WpaGui::wpsPbc()
1437 size_t reply_len = sizeof(reply);
1439 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1442 wpsPinEdit->setEnabled(false);
1443 if (wpsStatusText->text().compare("WPS AP in active PBC mode found")) {
1444 wpsInstructions->setText("Press the push button on the AP to "
1445 "start the PBC mode.");
1447 wpsInstructions->setText("If you have not yet done so, press "
1448 "the push button on the AP to start "
1451 wpsStatusText->setText("Waiting for Registrar");
1456 void WpaGui::wpsGeneratePin()
1459 size_t reply_len = sizeof(reply) - 1;
1461 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1464 reply[reply_len] = '\0';
1466 wpsPinEdit->setText(reply);
1467 wpsPinEdit->setEnabled(true);
1468 wpsInstructions->setText("Enter the generated PIN into the Registrar "
1469 "(either the internal one in the AP or an "
1471 wpsStatusText->setText("Waiting for Registrar");
1476 void WpaGui::setBssFromScan(const QString &bssid)
1478 bssFromScan = bssid;
1479 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1480 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1481 wpsStatusText->setText("WPS AP selected from scan results");
1482 wpsInstructions->setText("If you want to use an AP device PIN, e.g., "
1483 "from a label in the device, enter the eight "
1484 "digit AP PIN and click Use AP PIN button.");
1488 void WpaGui::wpsApPinChanged(const QString &text)
1490 wpsApPinButton->setEnabled(text.length() == 8);
1494 void WpaGui::wpsApPin()
1497 size_t reply_len = sizeof(reply);
1499 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1500 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1503 wpsStatusText->setText("Waiting for AP/Enrollee");
1508 void WpaGui::stopWpsRun(bool success)
1511 wpsStatusText->setText(success ? "Connected to the network" :
1514 wpsStatusText->setText("");
1515 wpsPinEdit->setEnabled(false);
1516 wpsInstructions->setText("");
1519 wpsApPinEdit->setEnabled(false);
1520 wpsApPinButton->setEnabled(false);
1524 #ifdef CONFIG_NATIVE_WINDOWS
1527 #define WPASVC_NAME TEXT("wpasvc")
1530 class ErrorMsg : public QMessageBox {
1532 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1533 void showMsg(QString msg);
1538 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1539 QMessageBox(parent), err(last_err)
1541 setWindowTitle("wpa_gui error");
1542 setIcon(QMessageBox::Warning);
1545 void ErrorMsg::showMsg(QString msg)
1550 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1551 FORMAT_MESSAGE_FROM_SYSTEM,
1552 NULL, err, 0, (LPTSTR) (void *) &buf,
1554 QString msg = QString::fromWCharArray(buf);
1555 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1558 setInformativeText(QString("[%1]").arg(err));
1565 void WpaGui::startService()
1569 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1571 ErrorMsg(this).showMsg("OpenSCManager failed");
1575 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1577 ErrorMsg(this).showMsg("OpenService failed");
1578 CloseServiceHandle(scm);
1582 if (!StartService(svc, 0, NULL)) {
1583 ErrorMsg(this).showMsg("Failed to start wpa_supplicant "
1587 CloseServiceHandle(svc);
1588 CloseServiceHandle(scm);
1592 void WpaGui::stopService()
1595 SERVICE_STATUS status;
1597 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1599 ErrorMsg(this).showMsg("OpenSCManager failed");
1603 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1605 ErrorMsg(this).showMsg("OpenService failed");
1606 CloseServiceHandle(scm);
1610 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1611 ErrorMsg(this).showMsg("Failed to stop wpa_supplicant "
1615 CloseServiceHandle(svc);
1616 CloseServiceHandle(scm);
1620 bool WpaGui::serviceRunning()
1623 SERVICE_STATUS status;
1624 bool running = false;
1626 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1628 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1632 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1634 printf("OpenService failed: %d\n\n", (int) GetLastError());
1635 CloseServiceHandle(scm);
1639 if (QueryServiceStatus(svc, &status)) {
1640 if (status.dwCurrentState != SERVICE_STOPPED)
1644 CloseServiceHandle(svc);
1645 CloseServiceHandle(scm);
1650 #endif /* CONFIG_NATIVE_WINDOWS */
1653 void WpaGui::addInterface()
1659 add_iface = new AddInterface(this, this);