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 if (app->isSessionRestored()) {
151 QSettings settings("wpa_supplicant", "wpa_gui");
152 settings.beginGroup("state");
153 if (app->sessionId().compare(settings.value("session_id").
155 startInTray = settings.value("in_tray").toBool();
159 if (QSystemTrayIcon::isSystemTrayAvailable())
160 createTrayIcon(startInTray);
164 connectedToService = false;
165 textStatus->setText("connecting to wpa_supplicant");
166 timer = new QTimer(this);
167 connect(timer, SIGNAL(timeout()), SLOT(ping()));
168 timer->setSingleShot(FALSE);
171 if (openCtrlConnection(ctrl_iface) < 0) {
172 printf("Failed to open control connection to "
173 "wpa_supplicant.\n");
177 networkMayHaveChanged = true;
187 wpa_ctrl_detach(monitor_conn);
188 wpa_ctrl_close(monitor_conn);
192 wpa_ctrl_close(ctrl_conn);
229 free(ctrl_iface_dir);
230 ctrl_iface_dir = NULL;
234 void WpaGui::languageChange()
240 void WpaGui::parse_argv()
244 c = getopt(qApp->argc(), qApp->argv(), "i:p:t");
250 ctrl_iface = strdup(optarg);
253 free(ctrl_iface_dir);
254 ctrl_iface_dir = strdup(optarg);
264 int WpaGui::openCtrlConnection(const char *ifname)
268 char buf[2048], *pos, *pos2;
272 if (ifname != ctrl_iface) {
274 ctrl_iface = strdup(ifname);
277 #ifdef CONFIG_CTRL_IFACE_UDP
279 ctrl_iface = strdup("udp");
280 #endif /* CONFIG_CTRL_IFACE_UDP */
281 #ifdef CONFIG_CTRL_IFACE_UNIX
283 DIR *dir = opendir(ctrl_iface_dir);
287 while ((dent = readdir(dir))) {
288 #ifdef _DIRENT_HAVE_D_TYPE
289 /* Skip the file if it is not a socket.
290 * Also accept DT_UNKNOWN (0) in case
291 * the C library or underlying file
292 * system does not support d_type. */
293 if (dent->d_type != DT_SOCK &&
294 dent->d_type != DT_UNKNOWN)
296 #endif /* _DIRENT_HAVE_D_TYPE */
298 if (strcmp(dent->d_name, ".") == 0 ||
299 strcmp(dent->d_name, "..") == 0)
301 printf("Selected interface '%s'\n",
303 ctrl_iface = strdup(dent->d_name);
308 #endif /* CONFIG_CTRL_IFACE_UNIX */
309 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
310 struct wpa_ctrl *ctrl;
316 ctrl = wpa_ctrl_open(NULL);
318 len = sizeof(buf) - 1;
319 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf,
322 connectedToService = true;
324 pos = strchr(buf, '\n');
327 ctrl_iface = strdup(buf);
329 wpa_ctrl_close(ctrl);
331 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
334 if (ctrl_iface == NULL) {
335 #ifdef CONFIG_NATIVE_WINDOWS
336 static bool first = true;
337 if (first && !serviceRunning()) {
339 if (QMessageBox::warning(
341 "wpa_supplicant service is not running.\n"
342 "Do you want to start it?",
343 QMessageBox::Yes | QMessageBox::No) ==
347 #endif /* CONFIG_NATIVE_WINDOWS */
351 #ifdef CONFIG_CTRL_IFACE_UNIX
352 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
353 cfile = (char *) malloc(flen);
356 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
357 #else /* CONFIG_CTRL_IFACE_UNIX */
358 flen = strlen(ctrl_iface) + 1;
359 cfile = (char *) malloc(flen);
362 snprintf(cfile, flen, "%s", ctrl_iface);
363 #endif /* CONFIG_CTRL_IFACE_UNIX */
366 wpa_ctrl_close(ctrl_conn);
373 wpa_ctrl_detach(monitor_conn);
374 wpa_ctrl_close(monitor_conn);
378 printf("Trying to connect to '%s'\n", cfile);
379 ctrl_conn = wpa_ctrl_open(cfile);
380 if (ctrl_conn == NULL) {
384 monitor_conn = wpa_ctrl_open(cfile);
386 if (monitor_conn == NULL) {
387 wpa_ctrl_close(ctrl_conn);
390 if (wpa_ctrl_attach(monitor_conn)) {
391 printf("Failed to attach to wpa_supplicant\n");
392 wpa_ctrl_close(monitor_conn);
394 wpa_ctrl_close(ctrl_conn);
399 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
400 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
401 QSocketNotifier::Read, this);
402 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
405 adapterSelect->clear();
406 adapterSelect->addItem(ctrl_iface);
407 adapterSelect->setCurrentIndex(0);
409 len = sizeof(buf) - 1;
410 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
415 pos2 = strchr(pos, '\n');
418 if (strcmp(pos, ctrl_iface) != 0)
419 adapterSelect->addItem(pos);
427 len = sizeof(buf) - 1;
428 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len,
433 QStringList types = res.split(QChar(' '));
434 bool wps = types.contains("WSC");
435 actionWPS->setEnabled(wps);
436 wpsTab->setEnabled(wps);
437 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), wps);
444 static void wpa_gui_msg_cb(char *msg, size_t)
446 /* This should not happen anymore since two control connections are
448 printf("missed message: %s\n", msg);
452 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
456 if (ctrl_conn == NULL)
458 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen,
461 printf("'%s' command timed out.\n", cmd);
463 printf("'%s' command failed.\n", cmd);
469 void WpaGui::updateStatus()
471 char buf[2048], *start, *end, *pos;
474 pingsToStatusUpdate = 10;
476 len = sizeof(buf) - 1;
477 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
478 textStatus->setText("Could not get status from "
480 textAuthentication->clear();
481 textEncryption->clear();
484 textIpAddress->clear();
486 #ifdef CONFIG_NATIVE_WINDOWS
487 static bool first = true;
488 if (first && connectedToService &&
489 (ctrl_iface == NULL || *ctrl_iface == '\0')) {
491 if (QMessageBox::information(
493 "No network interfaces in use.\n"
494 "Would you like to add one?",
495 QMessageBox::Yes | QMessageBox::No) ==
499 #endif /* CONFIG_NATIVE_WINDOWS */
505 bool auth_updated = false, ssid_updated = false;
506 bool bssid_updated = false, ipaddr_updated = false;
507 bool status_updated = false;
508 char *pairwise_cipher = NULL, *group_cipher = NULL;
513 end = strchr(start, '\n');
517 while (end[0] && end[1])
522 pos = strchr(start, '=');
525 if (strcmp(start, "bssid") == 0) {
526 bssid_updated = true;
527 textBssid->setText(pos);
528 } else if (strcmp(start, "ssid") == 0) {
530 textSsid->setText(pos);
531 } else if (strcmp(start, "ip_address") == 0) {
532 ipaddr_updated = true;
533 textIpAddress->setText(pos);
534 } else if (strcmp(start, "wpa_state") == 0) {
535 status_updated = true;
536 textStatus->setText(pos);
537 } else if (strcmp(start, "key_mgmt") == 0) {
539 textAuthentication->setText(pos);
540 /* TODO: could add EAP status to this */
541 } else if (strcmp(start, "pairwise_cipher") == 0) {
542 pairwise_cipher = pos;
543 } else if (strcmp(start, "group_cipher") == 0) {
553 if (pairwise_cipher || group_cipher) {
555 if (pairwise_cipher && group_cipher &&
556 strcmp(pairwise_cipher, group_cipher) != 0) {
557 encr.append(pairwise_cipher);
559 encr.append(group_cipher);
560 } else if (pairwise_cipher) {
561 encr.append(pairwise_cipher);
563 encr.append(group_cipher);
564 encr.append(" [group key only]");
566 textEncryption->setText(encr);
568 textEncryption->clear();
573 textAuthentication->clear();
579 textIpAddress->clear();
583 void WpaGui::updateNetworks()
585 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
587 int first_active = -1;
588 int was_selected = -1;
589 bool current = false;
591 if (!networkMayHaveChanged)
594 if (networkList->currentRow() >= 0)
595 was_selected = networkList->currentRow();
597 networkSelect->clear();
598 networkList->clear();
600 if (ctrl_conn == NULL)
603 len = sizeof(buf) - 1;
604 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
608 start = strchr(buf, '\n');
615 end = strchr(start, '\n');
619 while (end[0] && end[1])
625 ssid = strchr(id, '\t');
629 bssid = strchr(ssid, '\t');
633 flags = strchr(bssid, '\t');
639 network.append(": ");
640 network.append(ssid);
641 networkSelect->addItem(network);
642 networkList->addItem(network);
644 if (strstr(flags, "[CURRENT]")) {
645 networkSelect->setCurrentIndex(networkSelect->count() -
648 } else if (first_active < 0 &&
649 strstr(flags, "[DISABLED]") == NULL)
650 first_active = networkSelect->count() - 1;
657 if (networkSelect->count() > 1)
658 networkSelect->addItem("Select any network");
660 if (!current && first_active >= 0)
661 networkSelect->setCurrentIndex(first_active);
663 if (was_selected >= 0 && networkList->count() > 0) {
664 if (was_selected < networkList->count())
665 networkList->setCurrentRow(was_selected);
667 networkList->setCurrentRow(networkList->count() - 1);
670 networkList->setCurrentRow(networkSelect->currentIndex());
672 networkMayHaveChanged = false;
676 void WpaGui::helpIndex()
678 printf("helpIndex\n");
682 void WpaGui::helpContents()
684 printf("helpContents\n");
688 void WpaGui::helpAbout()
690 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
691 "Copyright (c) 2003-2008,\n"
692 "Jouni Malinen <j@w1.fi>\n"
693 "and contributors.\n"
695 "This program is free software. You can\n"
696 "distribute it and/or modify it under the terms "
698 "the GNU General Public License version 2.\n"
700 "Alternatively, this software may be distributed\n"
701 "under the terms of the BSD license.\n"
703 "This product includes software developed\n"
704 "by the OpenSSL Project for use in the\n"
705 "OpenSSL Toolkit (http://www.openssl.org/)\n");
709 void WpaGui::disconnect()
712 size_t reply_len = sizeof(reply);
713 ctrlRequest("DISCONNECT", reply, &reply_len);
725 scanres = new ScanResults();
728 scanres->setWpaGui(this);
734 void WpaGui::eventHistory()
741 eh = new EventHistory();
755 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
757 * QSocketNotifier cannot be used with Windows named pipes, so use a
758 * timer to check for received messages for now. This could be
759 * optimized be doing something specific to named pipes or Windows
760 * events, but it is not clear what would be the best way of doing that
764 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
766 if (scanres && !scanres->isVisible()) {
771 if (eh && !eh->isVisible()) {
776 if (udr && !udr->isVisible()) {
781 len = sizeof(buf) - 1;
782 if (ctrlRequest("PING", buf, &len) < 0) {
783 printf("PING failed - trying to reconnect\n");
784 if (openCtrlConnection(ctrl_iface) >= 0) {
785 printf("Reconnected successfully\n");
786 pingsToStatusUpdate = 0;
790 pingsToStatusUpdate--;
791 if (pingsToStatusUpdate <= 0) {
796 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
797 /* Use less frequent pings and status updates when the main window is
798 * hidden (running in taskbar). */
799 int interval = isHidden() ? 5000 : 1000;
800 if (timer->interval() != interval)
801 timer->setInterval(interval);
802 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
806 static int str_match(const char *a, const char *b)
808 return strncmp(a, b, strlen(b)) == 0;
812 void WpaGui::processMsg(char *msg)
814 char *pos = msg, *pos2;
820 priority = atoi(pos);
821 pos = strchr(pos, '>');
828 WpaMsg wm(pos, priority);
832 while (msgs.count() > 100)
835 /* Update last message with truncated version of the event */
836 if (strncmp(pos, "CTRL-", 5) == 0) {
837 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
844 QString lastmsg = pos2;
845 lastmsg.truncate(40);
846 textLastMessage->setText(lastmsg);
848 pingsToStatusUpdate = 0;
849 networkMayHaveChanged = true;
851 if (str_match(pos, WPA_CTRL_REQ))
852 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
853 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
854 scanres->updateResults();
855 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
856 showTrayMessage(QSystemTrayIcon::Information, 3,
857 "Disconnected from network.");
858 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
859 showTrayMessage(QSystemTrayIcon::Information, 3,
860 "Connection to network established.");
861 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
863 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
864 showTrayMessage(QSystemTrayIcon::Information, 3,
865 "Wi-Fi Protected Setup (WPS) AP\n"
866 "in active PBC mode found.");
867 wpsStatusText->setText("WPS AP in active PBC mode found");
868 wpaguiTab->setCurrentWidget(wpsTab);
869 wpsInstructions->setText("Press the PBC button on the screen "
870 "to start registration");
871 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
872 showTrayMessage(QSystemTrayIcon::Information, 3,
873 "Wi-Fi Protected Setup (WPS) AP\n"
874 " in active PIN mode found.");
875 wpsStatusText->setText("WPS AP with recently selected "
877 wpaguiTab->setCurrentWidget(wpsTab);
878 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
879 showTrayMessage(QSystemTrayIcon::Information, 3,
880 "Wi-Fi Protected Setup (WPS)\n"
882 wpsStatusText->setText("WPS AP detected");
883 wpaguiTab->setCurrentWidget(wpsTab);
884 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
885 showTrayMessage(QSystemTrayIcon::Information, 3,
886 "Wi-Fi Protected Setup (WPS)\n"
887 "PBC mode overlap detected.");
888 wpsStatusText->setText("PBC mode overlap detected");
889 wpsInstructions->setText("More than one AP is currently in "
890 "active WPS PBC mode. Wait couple of "
891 "minutes and try again");
892 wpaguiTab->setCurrentWidget(wpsTab);
893 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
894 wpsStatusText->setText("Network configuration received");
895 wpaguiTab->setCurrentWidget(wpsTab);
896 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
897 if (strstr(pos, "(WSC)"))
898 wpsStatusText->setText("Registration started");
899 } else if (str_match(pos, WPS_EVENT_M2D)) {
900 wpsStatusText->setText("Registrar does not yet know PIN");
901 } else if (str_match(pos, WPS_EVENT_FAIL)) {
902 wpsStatusText->setText("Registration failed");
903 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
904 wpsStatusText->setText("Registration succeeded");
909 void WpaGui::processCtrlReq(const char *req)
915 udr = new UserDataRequest();
918 if (udr->setParams(this, req) < 0) {
928 void WpaGui::receiveMsgs()
933 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
934 len = sizeof(buf) - 1;
935 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
943 void WpaGui::connectB()
946 size_t reply_len = sizeof(reply);
947 ctrlRequest("REASSOCIATE", reply, &reply_len);
951 void WpaGui::selectNetwork( const QString &sel )
955 size_t reply_len = sizeof(reply);
957 if (cmd.startsWith("Select any")) {
960 int pos = cmd.indexOf(':');
962 printf("Invalid selectNetwork '%s'\n",
963 cmd.toAscii().constData());
968 cmd.prepend("SELECT_NETWORK ");
969 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
975 void WpaGui::enableNetwork(const QString &sel)
979 size_t reply_len = sizeof(reply);
981 if (!cmd.startsWith("all")) {
982 int pos = cmd.indexOf(':');
984 printf("Invalid enableNetwork '%s'\n",
985 cmd.toAscii().constData());
990 cmd.prepend("ENABLE_NETWORK ");
991 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
996 void WpaGui::disableNetwork(const QString &sel)
1000 size_t reply_len = sizeof(reply);
1002 if (!cmd.startsWith("all")) {
1003 int pos = cmd.indexOf(':');
1005 printf("Invalid disableNetwork '%s'\n",
1006 cmd.toAscii().constData());
1011 cmd.prepend("DISABLE_NETWORK ");
1012 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1017 void WpaGui::editNetwork(const QString &sel)
1022 if (!cmd.startsWith("Select any")) {
1023 int pos = sel.indexOf(':');
1025 printf("Invalid editNetwork '%s'\n",
1026 cmd.toAscii().constData());
1033 NetworkConfig *nc = new NetworkConfig();
1036 nc->setWpaGui(this);
1039 nc->paramsFromConfig(id);
1048 void WpaGui::editSelectedNetwork()
1050 if (networkSelect->count() < 1) {
1051 QMessageBox::information(this, "No Networks",
1052 "There are no networks to edit.\n");
1055 QString sel(networkSelect->currentText());
1060 void WpaGui::editListedNetwork()
1062 if (networkList->currentRow() < 0) {
1063 QMessageBox::information(this, "Select A Network",
1064 "Select a network from the list to"
1068 QString sel(networkList->currentItem()->text());
1073 void WpaGui::triggerUpdate()
1076 networkMayHaveChanged = true;
1081 void WpaGui::addNetwork()
1083 NetworkConfig *nc = new NetworkConfig();
1086 nc->setWpaGui(this);
1093 void WpaGui::removeNetwork(const QString &sel)
1097 size_t reply_len = sizeof(reply);
1099 if (cmd.startsWith("Select any"))
1102 if (!cmd.startsWith("all")) {
1103 int pos = cmd.indexOf(':');
1105 printf("Invalid removeNetwork '%s'\n",
1106 cmd.toAscii().constData());
1111 cmd.prepend("REMOVE_NETWORK ");
1112 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1117 void WpaGui::removeSelectedNetwork()
1119 if (networkSelect->count() < 1) {
1120 QMessageBox::information(this, "No Networks",
1121 "There are no networks to remove.\n");
1124 QString sel(networkSelect->currentText());
1129 void WpaGui::removeListedNetwork()
1131 if (networkList->currentRow() < 0) {
1132 QMessageBox::information(this, "Select A Network",
1133 "Select a network from the list to"
1137 QString sel(networkList->currentItem()->text());
1142 void WpaGui::enableAllNetworks()
1149 void WpaGui::disableAllNetworks()
1152 disableNetwork(sel);
1156 void WpaGui::removeAllNetworks()
1163 int WpaGui::getNetworkDisabled(const QString &sel)
1167 size_t reply_len = sizeof(reply) - 1;
1168 int pos = cmd.indexOf(':');
1170 printf("Invalid getNetworkDisabled '%s'\n",
1171 cmd.toAscii().constData());
1175 cmd.prepend("GET_NETWORK ");
1176 cmd.append(" disabled");
1178 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1179 && reply_len >= 1) {
1180 reply[reply_len] = '\0';
1181 if (!str_match(reply, "FAIL"))
1189 void WpaGui::updateNetworkDisabledStatus()
1191 if (networkList->currentRow() < 0)
1194 QString sel(networkList->currentItem()->text());
1196 switch (getNetworkDisabled(sel)) {
1198 if (!enableRadioButton->isChecked())
1199 enableRadioButton->setChecked(true);
1202 if (!disableRadioButton->isChecked())
1203 disableRadioButton->setChecked(true);
1209 void WpaGui::enableListedNetwork(bool enabled)
1211 if (networkList->currentRow() < 0 || !enabled)
1214 QString sel(networkList->currentItem()->text());
1216 if (getNetworkDisabled(sel) == 1)
1221 void WpaGui::disableListedNetwork(bool disabled)
1223 if (networkList->currentRow() < 0 || !disabled)
1226 QString sel(networkList->currentItem()->text());
1228 if (getNetworkDisabled(sel) == 0)
1229 disableNetwork(sel);
1233 void WpaGui::saveConfig()
1238 len = sizeof(buf) - 1;
1239 ctrlRequest("SAVE_CONFIG", buf, &len);
1243 if (str_match(buf, "FAIL"))
1244 QMessageBox::warning(this, "Failed to save configuration",
1245 "The configuration could not be saved.\n"
1247 "The update_config=1 configuration option\n"
1248 "must be used for configuration saving to\n"
1251 QMessageBox::information(this, "Saved configuration",
1252 "The current configuration was saved."
1257 void WpaGui::selectAdapter( const QString & sel )
1259 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1260 printf("Failed to open control connection to "
1261 "wpa_supplicant.\n");
1267 void WpaGui::createTrayIcon(bool trayOnly)
1269 QApplication::setQuitOnLastWindowClosed(false);
1271 tray_icon = new QSystemTrayIcon(this);
1272 tray_icon->setToolTip(qAppName() + " - wpa_supplicant user interface");
1273 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1274 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1276 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1279 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1280 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1282 ackTrayIcon = false;
1284 tray_menu = new QMenu(this);
1286 disconnectAction = new QAction("&Disconnect", this);
1287 reconnectAction = new QAction("Re&connect", this);
1288 connect(disconnectAction, SIGNAL(triggered()), this,
1289 SLOT(disconnect()));
1290 connect(reconnectAction, SIGNAL(triggered()), this,
1292 tray_menu->addAction(disconnectAction);
1293 tray_menu->addAction(reconnectAction);
1294 tray_menu->addSeparator();
1296 eventAction = new QAction("&Event History", this);
1297 scanAction = new QAction("Scan &Results", this);
1298 statAction = new QAction("S&tatus", this);
1299 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1300 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1301 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1302 tray_menu->addAction(eventAction);
1303 tray_menu->addAction(scanAction);
1304 tray_menu->addAction(statAction);
1305 tray_menu->addSeparator();
1307 showAction = new QAction("&Show Window", this);
1308 hideAction = new QAction("&Hide Window", this);
1309 quitAction = new QAction("&Quit", this);
1310 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1311 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1312 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1313 tray_menu->addAction(showAction);
1314 tray_menu->addAction(hideAction);
1315 tray_menu->addSeparator();
1316 tray_menu->addAction(quitAction);
1318 tray_icon->setContextMenu(tray_menu);
1328 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1329 const QString & msg)
1331 if (!QSystemTrayIcon::supportsMessages())
1334 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1337 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1341 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1344 /* use close() here instead of hide() and allow the
1345 * custom closeEvent handler take care of children */
1346 case QSystemTrayIcon::Trigger:
1356 case QSystemTrayIcon::MiddleClick:
1365 void WpaGui::showTrayStatus()
1370 len = sizeof(buf) - 1;
1371 if (ctrlRequest("STATUS", buf, &len) < 0)
1375 QString msg, status(buf);
1377 QStringList lines = status.split(QRegExp("\\n"));
1378 for (QStringList::Iterator it = lines.begin();
1379 it != lines.end(); it++) {
1380 int pos = (*it).indexOf('=') + 1;
1384 if ((*it).startsWith("bssid="))
1385 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1386 else if ((*it).startsWith("ssid="))
1387 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1388 else if ((*it).startsWith("pairwise_cipher="))
1389 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1390 else if ((*it).startsWith("group_cipher="))
1391 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1392 else if ((*it).startsWith("key_mgmt="))
1393 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1394 else if ((*it).startsWith("wpa_state="))
1395 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1396 else if ((*it).startsWith("ip_address="))
1397 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1398 else if ((*it).startsWith("Supplicant PAE state="))
1399 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1400 else if ((*it).startsWith("EAP state="))
1401 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1405 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1409 void WpaGui::closeEvent(QCloseEvent *event)
1435 if (tray_icon && !ackTrayIcon) {
1436 /* give user a visual hint that the tray icon exists */
1437 if (QSystemTrayIcon::supportsMessages()) {
1439 showTrayMessage(QSystemTrayIcon::Information, 3,
1440 qAppName() + " will keep running in "
1441 "the system tray.");
1443 QMessageBox::information(this, qAppName() + " systray",
1444 "The program will keep "
1445 "running in the system "
1455 void WpaGui::wpsDialog()
1457 wpaguiTab->setCurrentWidget(wpsTab);
1461 void WpaGui::peersDialog()
1468 peers = new Peers();
1471 peers->setWpaGui(this);
1477 void WpaGui::tabChanged(int index)
1485 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1486 if (bssFromScan.isEmpty())
1487 wpsApPinButton->setEnabled(false);
1491 void WpaGui::wpsPbc()
1494 size_t reply_len = sizeof(reply);
1496 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1499 wpsPinEdit->setEnabled(false);
1500 if (wpsStatusText->text().compare("WPS AP in active PBC mode found")) {
1501 wpsInstructions->setText("Press the push button on the AP to "
1502 "start the PBC mode.");
1504 wpsInstructions->setText("If you have not yet done so, press "
1505 "the push button on the AP to start "
1508 wpsStatusText->setText("Waiting for Registrar");
1513 void WpaGui::wpsGeneratePin()
1516 size_t reply_len = sizeof(reply) - 1;
1518 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1521 reply[reply_len] = '\0';
1523 wpsPinEdit->setText(reply);
1524 wpsPinEdit->setEnabled(true);
1525 wpsInstructions->setText("Enter the generated PIN into the Registrar "
1526 "(either the internal one in the AP or an "
1528 wpsStatusText->setText("Waiting for Registrar");
1533 void WpaGui::setBssFromScan(const QString &bssid)
1535 bssFromScan = bssid;
1536 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1537 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1538 wpsStatusText->setText("WPS AP selected from scan results");
1539 wpsInstructions->setText("If you want to use an AP device PIN, e.g., "
1540 "from a label in the device, enter the eight "
1541 "digit AP PIN and click Use AP PIN button.");
1545 void WpaGui::wpsApPinChanged(const QString &text)
1547 wpsApPinButton->setEnabled(text.length() == 8);
1551 void WpaGui::wpsApPin()
1554 size_t reply_len = sizeof(reply);
1556 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1557 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1560 wpsStatusText->setText("Waiting for AP/Enrollee");
1565 void WpaGui::stopWpsRun(bool success)
1568 wpsStatusText->setText(success ? "Connected to the network" :
1571 wpsStatusText->setText("");
1572 wpsPinEdit->setEnabled(false);
1573 wpsInstructions->setText("");
1576 wpsApPinEdit->setEnabled(false);
1577 wpsApPinButton->setEnabled(false);
1581 #ifdef CONFIG_NATIVE_WINDOWS
1584 #define WPASVC_NAME TEXT("wpasvc")
1587 class ErrorMsg : public QMessageBox {
1589 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1590 void showMsg(QString msg);
1595 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1596 QMessageBox(parent), err(last_err)
1598 setWindowTitle("wpa_gui error");
1599 setIcon(QMessageBox::Warning);
1602 void ErrorMsg::showMsg(QString msg)
1607 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1608 FORMAT_MESSAGE_FROM_SYSTEM,
1609 NULL, err, 0, (LPTSTR) (void *) &buf,
1611 QString msg = QString::fromWCharArray(buf);
1612 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1615 setInformativeText(QString("[%1]").arg(err));
1622 void WpaGui::startService()
1626 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1628 ErrorMsg(this).showMsg("OpenSCManager failed");
1632 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1634 ErrorMsg(this).showMsg("OpenService failed");
1635 CloseServiceHandle(scm);
1639 if (!StartService(svc, 0, NULL)) {
1640 ErrorMsg(this).showMsg("Failed to start wpa_supplicant "
1644 CloseServiceHandle(svc);
1645 CloseServiceHandle(scm);
1649 void WpaGui::stopService()
1652 SERVICE_STATUS status;
1654 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1656 ErrorMsg(this).showMsg("OpenSCManager failed");
1660 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1662 ErrorMsg(this).showMsg("OpenService failed");
1663 CloseServiceHandle(scm);
1667 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1668 ErrorMsg(this).showMsg("Failed to stop wpa_supplicant "
1672 CloseServiceHandle(svc);
1673 CloseServiceHandle(scm);
1677 bool WpaGui::serviceRunning()
1680 SERVICE_STATUS status;
1681 bool running = false;
1683 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1685 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1689 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1691 printf("OpenService failed: %d\n\n", (int) GetLastError());
1692 CloseServiceHandle(scm);
1696 if (QueryServiceStatus(svc, &status)) {
1697 if (status.dwCurrentState != SERVICE_STOPPED)
1701 CloseServiceHandle(svc);
1702 CloseServiceHandle(scm);
1707 #endif /* CONFIG_NATIVE_WINDOWS */
1710 void WpaGui::addInterface()
1716 add_iface = new AddInterface(this, this);
1722 void WpaGui::saveState()
1724 QSettings settings("wpa_supplicant", "wpa_gui");
1725 settings.beginGroup("state");
1726 settings.setValue("session_id", app->sessionId());
1727 settings.setValue("in_tray", inTray);
1728 settings.endGroup();