2 * wpa_gui - WpaGui class
3 * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
16 /* Need to get getopt() */
20 #ifdef CONFIG_NATIVE_WINDOWS
22 #endif /* CONFIG_NATIVE_WINDOWS */
25 #include <QMessageBox>
26 #include <QCloseEvent>
27 #include <QImageReader>
33 #include "userdatarequest.h"
34 #include "networkconfig.h"
38 #define printf wpagui_printf
39 static int wpagui_printf(const char *, ...)
45 WpaGui::WpaGui(QApplication *_app, QWidget *parent, const char *, Qt::WFlags)
46 : QMainWindow(parent), app(_app)
50 #ifdef CONFIG_NATIVE_WINDOWS
51 fileStopServiceAction = new QAction(this);
52 fileStopServiceAction->setObjectName("Stop Service");
53 fileStopServiceAction->setIconText("Stop Service");
54 fileMenu->insertAction(actionWPS, fileStopServiceAction);
56 fileStartServiceAction = new QAction(this);
57 fileStartServiceAction->setObjectName("Start Service");
58 fileStartServiceAction->setIconText("Start Service");
59 fileMenu->insertAction(fileStopServiceAction, fileStartServiceAction);
61 connect(fileStartServiceAction, SIGNAL(triggered()), this,
62 SLOT(startService()));
63 connect(fileStopServiceAction, SIGNAL(triggered()), this,
66 addInterfaceAction = new QAction(this);
67 addInterfaceAction->setIconText("Add Interface");
68 fileMenu->insertAction(fileStartServiceAction, addInterfaceAction);
70 connect(addInterfaceAction, SIGNAL(triggered()), this,
71 SLOT(addInterface()));
72 #endif /* CONFIG_NATIVE_WINDOWS */
77 * Disable WPS tab by default; it will be enabled if wpa_supplicant is
78 * built with WPS support.
80 wpsTab->setEnabled(false);
81 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), false);
83 connect(fileEventHistoryAction, SIGNAL(triggered()), this,
84 SLOT(eventHistory()));
85 connect(fileSaveConfigAction, SIGNAL(triggered()), this,
87 connect(actionWPS, SIGNAL(triggered()), this, SLOT(wpsDialog()));
88 connect(actionPeers, SIGNAL(triggered()), this, SLOT(peersDialog()));
89 connect(fileExitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
90 connect(networkAddAction, SIGNAL(triggered()), this,
92 connect(networkEditAction, SIGNAL(triggered()), this,
93 SLOT(editSelectedNetwork()));
94 connect(networkRemoveAction, SIGNAL(triggered()), this,
95 SLOT(removeSelectedNetwork()));
96 connect(networkEnableAllAction, SIGNAL(triggered()), this,
97 SLOT(enableAllNetworks()));
98 connect(networkDisableAllAction, SIGNAL(triggered()), this,
99 SLOT(disableAllNetworks()));
100 connect(networkRemoveAllAction, SIGNAL(triggered()), this,
101 SLOT(removeAllNetworks()));
102 connect(helpIndexAction, SIGNAL(triggered()), this, SLOT(helpIndex()));
103 connect(helpContentsAction, SIGNAL(triggered()), this,
104 SLOT(helpContents()));
105 connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(helpAbout()));
106 connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));
107 connect(scanButton, SIGNAL(clicked()), this, SLOT(scan()));
108 connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB()));
109 connect(adapterSelect, SIGNAL(activated(const QString&)), this,
110 SLOT(selectAdapter(const QString&)));
111 connect(networkSelect, SIGNAL(activated(const QString&)), this,
112 SLOT(selectNetwork(const QString&)));
113 connect(addNetworkButton, SIGNAL(clicked()), this, SLOT(addNetwork()));
114 connect(editNetworkButton, SIGNAL(clicked()), this,
115 SLOT(editListedNetwork()));
116 connect(removeNetworkButton, SIGNAL(clicked()), this,
117 SLOT(removeListedNetwork()));
118 connect(networkList, SIGNAL(itemSelectionChanged()), this,
119 SLOT(updateNetworkDisabledStatus()));
120 connect(enableRadioButton, SIGNAL(toggled(bool)), this,
121 SLOT(enableListedNetwork(bool)));
122 connect(disableRadioButton, SIGNAL(toggled(bool)), this,
123 SLOT(disableListedNetwork(bool)));
124 connect(scanNetworkButton, SIGNAL(clicked()), this, SLOT(scan()));
125 connect(networkList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
126 this, SLOT(editListedNetwork()));
127 connect(wpaguiTab, SIGNAL(currentChanged(int)), this,
128 SLOT(tabChanged(int)));
129 connect(wpsPbcButton, SIGNAL(clicked()), this, SLOT(wpsPbc()));
130 connect(wpsPinButton, SIGNAL(clicked()), this, SLOT(wpsGeneratePin()));
131 connect(wpsApPinEdit, SIGNAL(textChanged(const QString &)), this,
132 SLOT(wpsApPinChanged(const QString &)));
133 connect(wpsApPinButton, SIGNAL(clicked()), this, SLOT(wpsApPin()));
146 ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
150 #ifndef QT_NO_SESSIONMANAGER
151 if (app->isSessionRestored()) {
152 QSettings settings("wpa_supplicant", "wpa_gui");
153 settings.beginGroup("state");
154 if (app->sessionId().compare(settings.value("session_id").
156 startInTray = settings.value("in_tray").toBool();
161 if (QSystemTrayIcon::isSystemTrayAvailable())
162 createTrayIcon(startInTray);
166 connectedToService = false;
167 textStatus->setText("connecting to wpa_supplicant");
168 timer = new QTimer(this);
169 connect(timer, SIGNAL(timeout()), SLOT(ping()));
170 timer->setSingleShot(FALSE);
173 if (openCtrlConnection(ctrl_iface) < 0) {
174 printf("Failed to open control connection to "
175 "wpa_supplicant.\n");
179 networkMayHaveChanged = true;
189 wpa_ctrl_detach(monitor_conn);
190 wpa_ctrl_close(monitor_conn);
194 wpa_ctrl_close(ctrl_conn);
231 free(ctrl_iface_dir);
232 ctrl_iface_dir = NULL;
236 void WpaGui::languageChange()
242 void WpaGui::parse_argv()
246 c = getopt(qApp->argc(), qApp->argv(), "i:p:t");
252 ctrl_iface = strdup(optarg);
255 free(ctrl_iface_dir);
256 ctrl_iface_dir = strdup(optarg);
266 int WpaGui::openCtrlConnection(const char *ifname)
270 char buf[2048], *pos, *pos2;
274 if (ifname != ctrl_iface) {
276 ctrl_iface = strdup(ifname);
279 #ifdef CONFIG_CTRL_IFACE_UDP
281 ctrl_iface = strdup("udp");
282 #endif /* CONFIG_CTRL_IFACE_UDP */
283 #ifdef CONFIG_CTRL_IFACE_UNIX
285 DIR *dir = opendir(ctrl_iface_dir);
289 while ((dent = readdir(dir))) {
290 #ifdef _DIRENT_HAVE_D_TYPE
291 /* Skip the file if it is not a socket.
292 * Also accept DT_UNKNOWN (0) in case
293 * the C library or underlying file
294 * system does not support d_type. */
295 if (dent->d_type != DT_SOCK &&
296 dent->d_type != DT_UNKNOWN)
298 #endif /* _DIRENT_HAVE_D_TYPE */
300 if (strcmp(dent->d_name, ".") == 0 ||
301 strcmp(dent->d_name, "..") == 0)
303 printf("Selected interface '%s'\n",
305 ctrl_iface = strdup(dent->d_name);
310 #endif /* CONFIG_CTRL_IFACE_UNIX */
311 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
312 struct wpa_ctrl *ctrl;
318 ctrl = wpa_ctrl_open(NULL);
320 len = sizeof(buf) - 1;
321 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf,
324 connectedToService = true;
326 pos = strchr(buf, '\n');
329 ctrl_iface = strdup(buf);
331 wpa_ctrl_close(ctrl);
333 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
336 if (ctrl_iface == NULL) {
337 #ifdef CONFIG_NATIVE_WINDOWS
338 static bool first = true;
339 if (first && !serviceRunning()) {
341 if (QMessageBox::warning(
343 "wpa_supplicant service is not running.\n"
344 "Do you want to start it?",
345 QMessageBox::Yes | QMessageBox::No) ==
349 #endif /* CONFIG_NATIVE_WINDOWS */
353 #ifdef CONFIG_CTRL_IFACE_UNIX
354 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
355 cfile = (char *) malloc(flen);
358 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
359 #else /* CONFIG_CTRL_IFACE_UNIX */
360 flen = strlen(ctrl_iface) + 1;
361 cfile = (char *) malloc(flen);
364 snprintf(cfile, flen, "%s", ctrl_iface);
365 #endif /* CONFIG_CTRL_IFACE_UNIX */
368 wpa_ctrl_close(ctrl_conn);
375 wpa_ctrl_detach(monitor_conn);
376 wpa_ctrl_close(monitor_conn);
380 printf("Trying to connect to '%s'\n", cfile);
381 ctrl_conn = wpa_ctrl_open(cfile);
382 if (ctrl_conn == NULL) {
386 monitor_conn = wpa_ctrl_open(cfile);
388 if (monitor_conn == NULL) {
389 wpa_ctrl_close(ctrl_conn);
392 if (wpa_ctrl_attach(monitor_conn)) {
393 printf("Failed to attach to wpa_supplicant\n");
394 wpa_ctrl_close(monitor_conn);
396 wpa_ctrl_close(ctrl_conn);
401 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
402 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
403 QSocketNotifier::Read, this);
404 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
407 adapterSelect->clear();
408 adapterSelect->addItem(ctrl_iface);
409 adapterSelect->setCurrentIndex(0);
411 len = sizeof(buf) - 1;
412 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
417 pos2 = strchr(pos, '\n');
420 if (strcmp(pos, ctrl_iface) != 0)
421 adapterSelect->addItem(pos);
429 len = sizeof(buf) - 1;
430 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len,
435 QStringList types = res.split(QChar(' '));
436 bool wps = types.contains("WSC");
437 actionWPS->setEnabled(wps);
438 wpsTab->setEnabled(wps);
439 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), wps);
446 static void wpa_gui_msg_cb(char *msg, size_t)
448 /* This should not happen anymore since two control connections are
450 printf("missed message: %s\n", msg);
454 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
458 if (ctrl_conn == NULL)
460 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen,
463 printf("'%s' command timed out.\n", cmd);
465 printf("'%s' command failed.\n", cmd);
471 void WpaGui::updateStatus()
473 char buf[2048], *start, *end, *pos;
476 pingsToStatusUpdate = 10;
478 len = sizeof(buf) - 1;
479 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
480 textStatus->setText("Could not get status from "
482 textAuthentication->clear();
483 textEncryption->clear();
486 textIpAddress->clear();
488 #ifdef CONFIG_NATIVE_WINDOWS
489 static bool first = true;
490 if (first && connectedToService &&
491 (ctrl_iface == NULL || *ctrl_iface == '\0')) {
493 if (QMessageBox::information(
495 "No network interfaces in use.\n"
496 "Would you like to add one?",
497 QMessageBox::Yes | QMessageBox::No) ==
501 #endif /* CONFIG_NATIVE_WINDOWS */
507 bool auth_updated = false, ssid_updated = false;
508 bool bssid_updated = false, ipaddr_updated = false;
509 bool status_updated = false;
510 char *pairwise_cipher = NULL, *group_cipher = NULL;
515 end = strchr(start, '\n');
519 while (end[0] && end[1])
524 pos = strchr(start, '=');
527 if (strcmp(start, "bssid") == 0) {
528 bssid_updated = true;
529 textBssid->setText(pos);
530 } else if (strcmp(start, "ssid") == 0) {
532 textSsid->setText(pos);
533 } else if (strcmp(start, "ip_address") == 0) {
534 ipaddr_updated = true;
535 textIpAddress->setText(pos);
536 } else if (strcmp(start, "wpa_state") == 0) {
537 status_updated = true;
538 textStatus->setText(pos);
539 } else if (strcmp(start, "key_mgmt") == 0) {
541 textAuthentication->setText(pos);
542 /* TODO: could add EAP status to this */
543 } else if (strcmp(start, "pairwise_cipher") == 0) {
544 pairwise_cipher = pos;
545 } else if (strcmp(start, "group_cipher") == 0) {
555 if (pairwise_cipher || group_cipher) {
557 if (pairwise_cipher && group_cipher &&
558 strcmp(pairwise_cipher, group_cipher) != 0) {
559 encr.append(pairwise_cipher);
561 encr.append(group_cipher);
562 } else if (pairwise_cipher) {
563 encr.append(pairwise_cipher);
565 encr.append(group_cipher);
566 encr.append(" [group key only]");
568 textEncryption->setText(encr);
570 textEncryption->clear();
575 textAuthentication->clear();
581 textIpAddress->clear();
585 void WpaGui::updateNetworks()
587 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
589 int first_active = -1;
590 int was_selected = -1;
591 bool current = false;
593 if (!networkMayHaveChanged)
596 if (networkList->currentRow() >= 0)
597 was_selected = networkList->currentRow();
599 networkSelect->clear();
600 networkList->clear();
602 if (ctrl_conn == NULL)
605 len = sizeof(buf) - 1;
606 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
610 start = strchr(buf, '\n');
617 end = strchr(start, '\n');
621 while (end[0] && end[1])
627 ssid = strchr(id, '\t');
631 bssid = strchr(ssid, '\t');
635 flags = strchr(bssid, '\t');
641 network.append(": ");
642 network.append(ssid);
643 networkSelect->addItem(network);
644 networkList->addItem(network);
646 if (strstr(flags, "[CURRENT]")) {
647 networkSelect->setCurrentIndex(networkSelect->count() -
650 } else if (first_active < 0 &&
651 strstr(flags, "[DISABLED]") == NULL)
652 first_active = networkSelect->count() - 1;
659 if (networkSelect->count() > 1)
660 networkSelect->addItem("Select any network");
662 if (!current && first_active >= 0)
663 networkSelect->setCurrentIndex(first_active);
665 if (was_selected >= 0 && networkList->count() > 0) {
666 if (was_selected < networkList->count())
667 networkList->setCurrentRow(was_selected);
669 networkList->setCurrentRow(networkList->count() - 1);
672 networkList->setCurrentRow(networkSelect->currentIndex());
674 networkMayHaveChanged = false;
678 void WpaGui::helpIndex()
680 printf("helpIndex\n");
684 void WpaGui::helpContents()
686 printf("helpContents\n");
690 void WpaGui::helpAbout()
692 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
693 "Copyright (c) 2003-2008,\n"
694 "Jouni Malinen <j@w1.fi>\n"
695 "and contributors.\n"
697 "This program is free software. You can\n"
698 "distribute it and/or modify it under the terms "
700 "the GNU General Public License version 2.\n"
702 "Alternatively, this software may be distributed\n"
703 "under the terms of the BSD license.\n"
705 "This product includes software developed\n"
706 "by the OpenSSL Project for use in the\n"
707 "OpenSSL Toolkit (http://www.openssl.org/)\n");
711 void WpaGui::disconnect()
714 size_t reply_len = sizeof(reply);
715 ctrlRequest("DISCONNECT", reply, &reply_len);
727 scanres = new ScanResults();
730 scanres->setWpaGui(this);
736 void WpaGui::eventHistory()
743 eh = new EventHistory();
757 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
759 * QSocketNotifier cannot be used with Windows named pipes, so use a
760 * timer to check for received messages for now. This could be
761 * optimized be doing something specific to named pipes or Windows
762 * events, but it is not clear what would be the best way of doing that
766 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
768 if (scanres && !scanres->isVisible()) {
773 if (eh && !eh->isVisible()) {
778 if (udr && !udr->isVisible()) {
783 len = sizeof(buf) - 1;
784 if (ctrlRequest("PING", buf, &len) < 0) {
785 printf("PING failed - trying to reconnect\n");
786 if (openCtrlConnection(ctrl_iface) >= 0) {
787 printf("Reconnected successfully\n");
788 pingsToStatusUpdate = 0;
792 pingsToStatusUpdate--;
793 if (pingsToStatusUpdate <= 0) {
798 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
799 /* Use less frequent pings and status updates when the main window is
800 * hidden (running in taskbar). */
801 int interval = isHidden() ? 5000 : 1000;
802 if (timer->interval() != interval)
803 timer->setInterval(interval);
804 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
808 static int str_match(const char *a, const char *b)
810 return strncmp(a, b, strlen(b)) == 0;
814 void WpaGui::processMsg(char *msg)
816 char *pos = msg, *pos2;
822 priority = atoi(pos);
823 pos = strchr(pos, '>');
830 WpaMsg wm(pos, priority);
834 peers->event_notify(wm);
836 while (msgs.count() > 100)
839 /* Update last message with truncated version of the event */
840 if (strncmp(pos, "CTRL-", 5) == 0) {
841 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
848 QString lastmsg = pos2;
849 lastmsg.truncate(40);
850 textLastMessage->setText(lastmsg);
852 pingsToStatusUpdate = 0;
853 networkMayHaveChanged = true;
855 if (str_match(pos, WPA_CTRL_REQ))
856 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
857 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
858 scanres->updateResults();
859 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
860 showTrayMessage(QSystemTrayIcon::Information, 3,
861 "Disconnected from network.");
862 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
863 showTrayMessage(QSystemTrayIcon::Information, 3,
864 "Connection to network established.");
865 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
867 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
868 showTrayMessage(QSystemTrayIcon::Information, 3,
869 "Wi-Fi Protected Setup (WPS) AP\n"
870 "in active PBC mode found.");
871 wpsStatusText->setText("WPS AP in active PBC mode found");
872 if (textStatus->text() == "INACTIVE" ||
873 textStatus->text() == "DISCONNECTED")
874 wpaguiTab->setCurrentWidget(wpsTab);
875 wpsInstructions->setText("Press the PBC button on the screen "
876 "to start registration");
877 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
878 showTrayMessage(QSystemTrayIcon::Information, 3,
879 "Wi-Fi Protected Setup (WPS) AP\n"
880 " in active PIN mode found.");
881 wpsStatusText->setText("WPS AP with recently selected "
883 if (textStatus->text() == "INACTIVE" ||
884 textStatus->text() == "DISCONNECTED")
885 wpaguiTab->setCurrentWidget(wpsTab);
886 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
887 showTrayMessage(QSystemTrayIcon::Information, 3,
888 "Wi-Fi Protected Setup (WPS)\n"
890 wpsStatusText->setText("WPS AP detected");
891 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
892 showTrayMessage(QSystemTrayIcon::Information, 3,
893 "Wi-Fi Protected Setup (WPS)\n"
894 "PBC mode overlap detected.");
895 wpsStatusText->setText("PBC mode overlap detected");
896 wpsInstructions->setText("More than one AP is currently in "
897 "active WPS PBC mode. Wait couple of "
898 "minutes and try again");
899 wpaguiTab->setCurrentWidget(wpsTab);
900 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
901 wpsStatusText->setText("Network configuration received");
902 wpaguiTab->setCurrentWidget(wpsTab);
903 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
904 if (strstr(pos, "(WSC)"))
905 wpsStatusText->setText("Registration started");
906 } else if (str_match(pos, WPS_EVENT_M2D)) {
907 wpsStatusText->setText("Registrar does not yet know PIN");
908 } else if (str_match(pos, WPS_EVENT_FAIL)) {
909 wpsStatusText->setText("Registration failed");
910 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
911 wpsStatusText->setText("Registration succeeded");
916 void WpaGui::processCtrlReq(const char *req)
922 udr = new UserDataRequest();
925 if (udr->setParams(this, req) < 0) {
935 void WpaGui::receiveMsgs()
940 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
941 len = sizeof(buf) - 1;
942 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
950 void WpaGui::connectB()
953 size_t reply_len = sizeof(reply);
954 ctrlRequest("REASSOCIATE", reply, &reply_len);
958 void WpaGui::selectNetwork( const QString &sel )
962 size_t reply_len = sizeof(reply);
964 if (cmd.startsWith("Select any")) {
967 int pos = cmd.indexOf(':');
969 printf("Invalid selectNetwork '%s'\n",
970 cmd.toAscii().constData());
975 cmd.prepend("SELECT_NETWORK ");
976 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
982 void WpaGui::enableNetwork(const QString &sel)
986 size_t reply_len = sizeof(reply);
988 if (!cmd.startsWith("all")) {
989 int pos = cmd.indexOf(':');
991 printf("Invalid enableNetwork '%s'\n",
992 cmd.toAscii().constData());
997 cmd.prepend("ENABLE_NETWORK ");
998 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1003 void WpaGui::disableNetwork(const QString &sel)
1007 size_t reply_len = sizeof(reply);
1009 if (!cmd.startsWith("all")) {
1010 int pos = cmd.indexOf(':');
1012 printf("Invalid disableNetwork '%s'\n",
1013 cmd.toAscii().constData());
1018 cmd.prepend("DISABLE_NETWORK ");
1019 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1024 void WpaGui::editNetwork(const QString &sel)
1029 if (!cmd.startsWith("Select any")) {
1030 int pos = sel.indexOf(':');
1032 printf("Invalid editNetwork '%s'\n",
1033 cmd.toAscii().constData());
1040 NetworkConfig *nc = new NetworkConfig();
1043 nc->setWpaGui(this);
1046 nc->paramsFromConfig(id);
1055 void WpaGui::editSelectedNetwork()
1057 if (networkSelect->count() < 1) {
1058 QMessageBox::information(this, "No Networks",
1059 "There are no networks to edit.\n");
1062 QString sel(networkSelect->currentText());
1067 void WpaGui::editListedNetwork()
1069 if (networkList->currentRow() < 0) {
1070 QMessageBox::information(this, "Select A Network",
1071 "Select a network from the list to"
1075 QString sel(networkList->currentItem()->text());
1080 void WpaGui::triggerUpdate()
1083 networkMayHaveChanged = true;
1088 void WpaGui::addNetwork()
1090 NetworkConfig *nc = new NetworkConfig();
1093 nc->setWpaGui(this);
1100 void WpaGui::removeNetwork(const QString &sel)
1104 size_t reply_len = sizeof(reply);
1106 if (cmd.startsWith("Select any"))
1109 if (!cmd.startsWith("all")) {
1110 int pos = cmd.indexOf(':');
1112 printf("Invalid removeNetwork '%s'\n",
1113 cmd.toAscii().constData());
1118 cmd.prepend("REMOVE_NETWORK ");
1119 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1124 void WpaGui::removeSelectedNetwork()
1126 if (networkSelect->count() < 1) {
1127 QMessageBox::information(this, "No Networks",
1128 "There are no networks to remove.\n");
1131 QString sel(networkSelect->currentText());
1136 void WpaGui::removeListedNetwork()
1138 if (networkList->currentRow() < 0) {
1139 QMessageBox::information(this, "Select A Network",
1140 "Select a network from the list to"
1144 QString sel(networkList->currentItem()->text());
1149 void WpaGui::enableAllNetworks()
1156 void WpaGui::disableAllNetworks()
1159 disableNetwork(sel);
1163 void WpaGui::removeAllNetworks()
1170 int WpaGui::getNetworkDisabled(const QString &sel)
1174 size_t reply_len = sizeof(reply) - 1;
1175 int pos = cmd.indexOf(':');
1177 printf("Invalid getNetworkDisabled '%s'\n",
1178 cmd.toAscii().constData());
1182 cmd.prepend("GET_NETWORK ");
1183 cmd.append(" disabled");
1185 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1186 && reply_len >= 1) {
1187 reply[reply_len] = '\0';
1188 if (!str_match(reply, "FAIL"))
1196 void WpaGui::updateNetworkDisabledStatus()
1198 if (networkList->currentRow() < 0)
1201 QString sel(networkList->currentItem()->text());
1203 switch (getNetworkDisabled(sel)) {
1205 if (!enableRadioButton->isChecked())
1206 enableRadioButton->setChecked(true);
1209 if (!disableRadioButton->isChecked())
1210 disableRadioButton->setChecked(true);
1216 void WpaGui::enableListedNetwork(bool enabled)
1218 if (networkList->currentRow() < 0 || !enabled)
1221 QString sel(networkList->currentItem()->text());
1223 if (getNetworkDisabled(sel) == 1)
1228 void WpaGui::disableListedNetwork(bool disabled)
1230 if (networkList->currentRow() < 0 || !disabled)
1233 QString sel(networkList->currentItem()->text());
1235 if (getNetworkDisabled(sel) == 0)
1236 disableNetwork(sel);
1240 void WpaGui::saveConfig()
1245 len = sizeof(buf) - 1;
1246 ctrlRequest("SAVE_CONFIG", buf, &len);
1250 if (str_match(buf, "FAIL"))
1251 QMessageBox::warning(this, "Failed to save configuration",
1252 "The configuration could not be saved.\n"
1254 "The update_config=1 configuration option\n"
1255 "must be used for configuration saving to\n"
1258 QMessageBox::information(this, "Saved configuration",
1259 "The current configuration was saved."
1264 void WpaGui::selectAdapter( const QString & sel )
1266 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1267 printf("Failed to open control connection to "
1268 "wpa_supplicant.\n");
1274 void WpaGui::createTrayIcon(bool trayOnly)
1276 QApplication::setQuitOnLastWindowClosed(false);
1278 tray_icon = new QSystemTrayIcon(this);
1279 tray_icon->setToolTip(qAppName() + " - wpa_supplicant user interface");
1280 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1281 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1283 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1286 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1287 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1289 ackTrayIcon = false;
1291 tray_menu = new QMenu(this);
1293 disconnectAction = new QAction("&Disconnect", this);
1294 reconnectAction = new QAction("Re&connect", this);
1295 connect(disconnectAction, SIGNAL(triggered()), this,
1296 SLOT(disconnect()));
1297 connect(reconnectAction, SIGNAL(triggered()), this,
1299 tray_menu->addAction(disconnectAction);
1300 tray_menu->addAction(reconnectAction);
1301 tray_menu->addSeparator();
1303 eventAction = new QAction("&Event History", this);
1304 scanAction = new QAction("Scan &Results", this);
1305 statAction = new QAction("S&tatus", this);
1306 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1307 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1308 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1309 tray_menu->addAction(eventAction);
1310 tray_menu->addAction(scanAction);
1311 tray_menu->addAction(statAction);
1312 tray_menu->addSeparator();
1314 showAction = new QAction("&Show Window", this);
1315 hideAction = new QAction("&Hide Window", this);
1316 quitAction = new QAction("&Quit", this);
1317 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1318 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1319 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1320 tray_menu->addAction(showAction);
1321 tray_menu->addAction(hideAction);
1322 tray_menu->addSeparator();
1323 tray_menu->addAction(quitAction);
1325 tray_icon->setContextMenu(tray_menu);
1335 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1336 const QString & msg)
1338 if (!QSystemTrayIcon::supportsMessages())
1341 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1344 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1348 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1351 /* use close() here instead of hide() and allow the
1352 * custom closeEvent handler take care of children */
1353 case QSystemTrayIcon::Trigger:
1363 case QSystemTrayIcon::MiddleClick:
1372 void WpaGui::showTrayStatus()
1377 len = sizeof(buf) - 1;
1378 if (ctrlRequest("STATUS", buf, &len) < 0)
1382 QString msg, status(buf);
1384 QStringList lines = status.split(QRegExp("\\n"));
1385 for (QStringList::Iterator it = lines.begin();
1386 it != lines.end(); it++) {
1387 int pos = (*it).indexOf('=') + 1;
1391 if ((*it).startsWith("bssid="))
1392 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1393 else if ((*it).startsWith("ssid="))
1394 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1395 else if ((*it).startsWith("pairwise_cipher="))
1396 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1397 else if ((*it).startsWith("group_cipher="))
1398 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1399 else if ((*it).startsWith("key_mgmt="))
1400 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1401 else if ((*it).startsWith("wpa_state="))
1402 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1403 else if ((*it).startsWith("ip_address="))
1404 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1405 else if ((*it).startsWith("Supplicant PAE state="))
1406 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1407 else if ((*it).startsWith("EAP state="))
1408 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1412 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1416 void WpaGui::closeEvent(QCloseEvent *event)
1442 if (tray_icon && !ackTrayIcon) {
1443 /* give user a visual hint that the tray icon exists */
1444 if (QSystemTrayIcon::supportsMessages()) {
1446 showTrayMessage(QSystemTrayIcon::Information, 3,
1447 qAppName() + " will keep running in "
1448 "the system tray.");
1450 QMessageBox::information(this, qAppName() + " systray",
1451 "The program will keep "
1452 "running in the system "
1462 void WpaGui::wpsDialog()
1464 wpaguiTab->setCurrentWidget(wpsTab);
1468 void WpaGui::peersDialog()
1475 peers = new Peers();
1478 peers->setWpaGui(this);
1484 void WpaGui::tabChanged(int index)
1492 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1493 if (bssFromScan.isEmpty())
1494 wpsApPinButton->setEnabled(false);
1498 void WpaGui::wpsPbc()
1501 size_t reply_len = sizeof(reply);
1503 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1506 wpsPinEdit->setEnabled(false);
1507 if (wpsStatusText->text().compare("WPS AP in active PBC mode found")) {
1508 wpsInstructions->setText("Press the push button on the AP to "
1509 "start the PBC mode.");
1511 wpsInstructions->setText("If you have not yet done so, press "
1512 "the push button on the AP to start "
1515 wpsStatusText->setText("Waiting for Registrar");
1520 void WpaGui::wpsGeneratePin()
1523 size_t reply_len = sizeof(reply) - 1;
1525 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1528 reply[reply_len] = '\0';
1530 wpsPinEdit->setText(reply);
1531 wpsPinEdit->setEnabled(true);
1532 wpsInstructions->setText("Enter the generated PIN into the Registrar "
1533 "(either the internal one in the AP or an "
1535 wpsStatusText->setText("Waiting for Registrar");
1540 void WpaGui::setBssFromScan(const QString &bssid)
1542 bssFromScan = bssid;
1543 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1544 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1545 wpsStatusText->setText("WPS AP selected from scan results");
1546 wpsInstructions->setText("If you want to use an AP device PIN, e.g., "
1547 "from a label in the device, enter the eight "
1548 "digit AP PIN and click Use AP PIN button.");
1552 void WpaGui::wpsApPinChanged(const QString &text)
1554 wpsApPinButton->setEnabled(text.length() == 8);
1558 void WpaGui::wpsApPin()
1561 size_t reply_len = sizeof(reply);
1563 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1564 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1567 wpsStatusText->setText("Waiting for AP/Enrollee");
1572 void WpaGui::stopWpsRun(bool success)
1575 wpsStatusText->setText(success ? "Connected to the network" :
1578 wpsStatusText->setText("");
1579 wpsPinEdit->setEnabled(false);
1580 wpsInstructions->setText("");
1583 wpsApPinEdit->setEnabled(false);
1584 wpsApPinButton->setEnabled(false);
1588 #ifdef CONFIG_NATIVE_WINDOWS
1591 #define WPASVC_NAME TEXT("wpasvc")
1594 class ErrorMsg : public QMessageBox {
1596 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1597 void showMsg(QString msg);
1602 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1603 QMessageBox(parent), err(last_err)
1605 setWindowTitle("wpa_gui error");
1606 setIcon(QMessageBox::Warning);
1609 void ErrorMsg::showMsg(QString msg)
1614 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1615 FORMAT_MESSAGE_FROM_SYSTEM,
1616 NULL, err, 0, (LPTSTR) (void *) &buf,
1618 QString msg = QString::fromWCharArray(buf);
1619 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1622 setInformativeText(QString("[%1]").arg(err));
1629 void WpaGui::startService()
1633 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1635 ErrorMsg(this).showMsg("OpenSCManager failed");
1639 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1641 ErrorMsg(this).showMsg("OpenService failed");
1642 CloseServiceHandle(scm);
1646 if (!StartService(svc, 0, NULL)) {
1647 ErrorMsg(this).showMsg("Failed to start wpa_supplicant "
1651 CloseServiceHandle(svc);
1652 CloseServiceHandle(scm);
1656 void WpaGui::stopService()
1659 SERVICE_STATUS status;
1661 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1663 ErrorMsg(this).showMsg("OpenSCManager failed");
1667 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1669 ErrorMsg(this).showMsg("OpenService failed");
1670 CloseServiceHandle(scm);
1674 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1675 ErrorMsg(this).showMsg("Failed to stop wpa_supplicant "
1679 CloseServiceHandle(svc);
1680 CloseServiceHandle(scm);
1684 bool WpaGui::serviceRunning()
1687 SERVICE_STATUS status;
1688 bool running = false;
1690 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1692 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1696 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1698 printf("OpenService failed: %d\n\n", (int) GetLastError());
1699 CloseServiceHandle(scm);
1703 if (QueryServiceStatus(svc, &status)) {
1704 if (status.dwCurrentState != SERVICE_STOPPED)
1708 CloseServiceHandle(svc);
1709 CloseServiceHandle(scm);
1714 #endif /* CONFIG_NATIVE_WINDOWS */
1717 void WpaGui::addInterface()
1723 add_iface = new AddInterface(this, this);
1729 #ifndef QT_NO_SESSIONMANAGER
1730 void WpaGui::saveState()
1732 QSettings settings("wpa_supplicant", "wpa_gui");
1733 settings.beginGroup("state");
1734 settings.setValue("session_id", app->sessionId());
1735 settings.setValue("in_tray", inTray);
1736 settings.endGroup();