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 peers->event_notify(wm);
834 while (msgs.count() > 100)
837 /* Update last message with truncated version of the event */
838 if (strncmp(pos, "CTRL-", 5) == 0) {
839 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
846 QString lastmsg = pos2;
847 lastmsg.truncate(40);
848 textLastMessage->setText(lastmsg);
850 pingsToStatusUpdate = 0;
851 networkMayHaveChanged = true;
853 if (str_match(pos, WPA_CTRL_REQ))
854 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
855 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
856 scanres->updateResults();
857 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
858 showTrayMessage(QSystemTrayIcon::Information, 3,
859 "Disconnected from network.");
860 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
861 showTrayMessage(QSystemTrayIcon::Information, 3,
862 "Connection to network established.");
863 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
865 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
866 showTrayMessage(QSystemTrayIcon::Information, 3,
867 "Wi-Fi Protected Setup (WPS) AP\n"
868 "in active PBC mode found.");
869 wpsStatusText->setText("WPS AP in active PBC mode found");
870 wpaguiTab->setCurrentWidget(wpsTab);
871 wpsInstructions->setText("Press the PBC button on the screen "
872 "to start registration");
873 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
874 showTrayMessage(QSystemTrayIcon::Information, 3,
875 "Wi-Fi Protected Setup (WPS) AP\n"
876 " in active PIN mode found.");
877 wpsStatusText->setText("WPS AP with recently selected "
879 wpaguiTab->setCurrentWidget(wpsTab);
880 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
881 showTrayMessage(QSystemTrayIcon::Information, 3,
882 "Wi-Fi Protected Setup (WPS)\n"
884 wpsStatusText->setText("WPS AP detected");
885 wpaguiTab->setCurrentWidget(wpsTab);
886 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
887 showTrayMessage(QSystemTrayIcon::Information, 3,
888 "Wi-Fi Protected Setup (WPS)\n"
889 "PBC mode overlap detected.");
890 wpsStatusText->setText("PBC mode overlap detected");
891 wpsInstructions->setText("More than one AP is currently in "
892 "active WPS PBC mode. Wait couple of "
893 "minutes and try again");
894 wpaguiTab->setCurrentWidget(wpsTab);
895 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
896 wpsStatusText->setText("Network configuration received");
897 wpaguiTab->setCurrentWidget(wpsTab);
898 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
899 if (strstr(pos, "(WSC)"))
900 wpsStatusText->setText("Registration started");
901 } else if (str_match(pos, WPS_EVENT_M2D)) {
902 wpsStatusText->setText("Registrar does not yet know PIN");
903 } else if (str_match(pos, WPS_EVENT_FAIL)) {
904 wpsStatusText->setText("Registration failed");
905 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
906 wpsStatusText->setText("Registration succeeded");
911 void WpaGui::processCtrlReq(const char *req)
917 udr = new UserDataRequest();
920 if (udr->setParams(this, req) < 0) {
930 void WpaGui::receiveMsgs()
935 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
936 len = sizeof(buf) - 1;
937 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
945 void WpaGui::connectB()
948 size_t reply_len = sizeof(reply);
949 ctrlRequest("REASSOCIATE", reply, &reply_len);
953 void WpaGui::selectNetwork( const QString &sel )
957 size_t reply_len = sizeof(reply);
959 if (cmd.startsWith("Select any")) {
962 int pos = cmd.indexOf(':');
964 printf("Invalid selectNetwork '%s'\n",
965 cmd.toAscii().constData());
970 cmd.prepend("SELECT_NETWORK ");
971 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
977 void WpaGui::enableNetwork(const QString &sel)
981 size_t reply_len = sizeof(reply);
983 if (!cmd.startsWith("all")) {
984 int pos = cmd.indexOf(':');
986 printf("Invalid enableNetwork '%s'\n",
987 cmd.toAscii().constData());
992 cmd.prepend("ENABLE_NETWORK ");
993 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
998 void WpaGui::disableNetwork(const QString &sel)
1002 size_t reply_len = sizeof(reply);
1004 if (!cmd.startsWith("all")) {
1005 int pos = cmd.indexOf(':');
1007 printf("Invalid disableNetwork '%s'\n",
1008 cmd.toAscii().constData());
1013 cmd.prepend("DISABLE_NETWORK ");
1014 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1019 void WpaGui::editNetwork(const QString &sel)
1024 if (!cmd.startsWith("Select any")) {
1025 int pos = sel.indexOf(':');
1027 printf("Invalid editNetwork '%s'\n",
1028 cmd.toAscii().constData());
1035 NetworkConfig *nc = new NetworkConfig();
1038 nc->setWpaGui(this);
1041 nc->paramsFromConfig(id);
1050 void WpaGui::editSelectedNetwork()
1052 if (networkSelect->count() < 1) {
1053 QMessageBox::information(this, "No Networks",
1054 "There are no networks to edit.\n");
1057 QString sel(networkSelect->currentText());
1062 void WpaGui::editListedNetwork()
1064 if (networkList->currentRow() < 0) {
1065 QMessageBox::information(this, "Select A Network",
1066 "Select a network from the list to"
1070 QString sel(networkList->currentItem()->text());
1075 void WpaGui::triggerUpdate()
1078 networkMayHaveChanged = true;
1083 void WpaGui::addNetwork()
1085 NetworkConfig *nc = new NetworkConfig();
1088 nc->setWpaGui(this);
1095 void WpaGui::removeNetwork(const QString &sel)
1099 size_t reply_len = sizeof(reply);
1101 if (cmd.startsWith("Select any"))
1104 if (!cmd.startsWith("all")) {
1105 int pos = cmd.indexOf(':');
1107 printf("Invalid removeNetwork '%s'\n",
1108 cmd.toAscii().constData());
1113 cmd.prepend("REMOVE_NETWORK ");
1114 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1119 void WpaGui::removeSelectedNetwork()
1121 if (networkSelect->count() < 1) {
1122 QMessageBox::information(this, "No Networks",
1123 "There are no networks to remove.\n");
1126 QString sel(networkSelect->currentText());
1131 void WpaGui::removeListedNetwork()
1133 if (networkList->currentRow() < 0) {
1134 QMessageBox::information(this, "Select A Network",
1135 "Select a network from the list to"
1139 QString sel(networkList->currentItem()->text());
1144 void WpaGui::enableAllNetworks()
1151 void WpaGui::disableAllNetworks()
1154 disableNetwork(sel);
1158 void WpaGui::removeAllNetworks()
1165 int WpaGui::getNetworkDisabled(const QString &sel)
1169 size_t reply_len = sizeof(reply) - 1;
1170 int pos = cmd.indexOf(':');
1172 printf("Invalid getNetworkDisabled '%s'\n",
1173 cmd.toAscii().constData());
1177 cmd.prepend("GET_NETWORK ");
1178 cmd.append(" disabled");
1180 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1181 && reply_len >= 1) {
1182 reply[reply_len] = '\0';
1183 if (!str_match(reply, "FAIL"))
1191 void WpaGui::updateNetworkDisabledStatus()
1193 if (networkList->currentRow() < 0)
1196 QString sel(networkList->currentItem()->text());
1198 switch (getNetworkDisabled(sel)) {
1200 if (!enableRadioButton->isChecked())
1201 enableRadioButton->setChecked(true);
1204 if (!disableRadioButton->isChecked())
1205 disableRadioButton->setChecked(true);
1211 void WpaGui::enableListedNetwork(bool enabled)
1213 if (networkList->currentRow() < 0 || !enabled)
1216 QString sel(networkList->currentItem()->text());
1218 if (getNetworkDisabled(sel) == 1)
1223 void WpaGui::disableListedNetwork(bool disabled)
1225 if (networkList->currentRow() < 0 || !disabled)
1228 QString sel(networkList->currentItem()->text());
1230 if (getNetworkDisabled(sel) == 0)
1231 disableNetwork(sel);
1235 void WpaGui::saveConfig()
1240 len = sizeof(buf) - 1;
1241 ctrlRequest("SAVE_CONFIG", buf, &len);
1245 if (str_match(buf, "FAIL"))
1246 QMessageBox::warning(this, "Failed to save configuration",
1247 "The configuration could not be saved.\n"
1249 "The update_config=1 configuration option\n"
1250 "must be used for configuration saving to\n"
1253 QMessageBox::information(this, "Saved configuration",
1254 "The current configuration was saved."
1259 void WpaGui::selectAdapter( const QString & sel )
1261 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1262 printf("Failed to open control connection to "
1263 "wpa_supplicant.\n");
1269 void WpaGui::createTrayIcon(bool trayOnly)
1271 QApplication::setQuitOnLastWindowClosed(false);
1273 tray_icon = new QSystemTrayIcon(this);
1274 tray_icon->setToolTip(qAppName() + " - wpa_supplicant user interface");
1275 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1276 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1278 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1281 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1282 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1284 ackTrayIcon = false;
1286 tray_menu = new QMenu(this);
1288 disconnectAction = new QAction("&Disconnect", this);
1289 reconnectAction = new QAction("Re&connect", this);
1290 connect(disconnectAction, SIGNAL(triggered()), this,
1291 SLOT(disconnect()));
1292 connect(reconnectAction, SIGNAL(triggered()), this,
1294 tray_menu->addAction(disconnectAction);
1295 tray_menu->addAction(reconnectAction);
1296 tray_menu->addSeparator();
1298 eventAction = new QAction("&Event History", this);
1299 scanAction = new QAction("Scan &Results", this);
1300 statAction = new QAction("S&tatus", this);
1301 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1302 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1303 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1304 tray_menu->addAction(eventAction);
1305 tray_menu->addAction(scanAction);
1306 tray_menu->addAction(statAction);
1307 tray_menu->addSeparator();
1309 showAction = new QAction("&Show Window", this);
1310 hideAction = new QAction("&Hide Window", this);
1311 quitAction = new QAction("&Quit", this);
1312 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1313 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1314 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1315 tray_menu->addAction(showAction);
1316 tray_menu->addAction(hideAction);
1317 tray_menu->addSeparator();
1318 tray_menu->addAction(quitAction);
1320 tray_icon->setContextMenu(tray_menu);
1330 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1331 const QString & msg)
1333 if (!QSystemTrayIcon::supportsMessages())
1336 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1339 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1343 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1346 /* use close() here instead of hide() and allow the
1347 * custom closeEvent handler take care of children */
1348 case QSystemTrayIcon::Trigger:
1358 case QSystemTrayIcon::MiddleClick:
1367 void WpaGui::showTrayStatus()
1372 len = sizeof(buf) - 1;
1373 if (ctrlRequest("STATUS", buf, &len) < 0)
1377 QString msg, status(buf);
1379 QStringList lines = status.split(QRegExp("\\n"));
1380 for (QStringList::Iterator it = lines.begin();
1381 it != lines.end(); it++) {
1382 int pos = (*it).indexOf('=') + 1;
1386 if ((*it).startsWith("bssid="))
1387 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1388 else if ((*it).startsWith("ssid="))
1389 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1390 else if ((*it).startsWith("pairwise_cipher="))
1391 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1392 else if ((*it).startsWith("group_cipher="))
1393 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1394 else if ((*it).startsWith("key_mgmt="))
1395 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1396 else if ((*it).startsWith("wpa_state="))
1397 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1398 else if ((*it).startsWith("ip_address="))
1399 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1400 else if ((*it).startsWith("Supplicant PAE state="))
1401 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1402 else if ((*it).startsWith("EAP state="))
1403 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1407 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1411 void WpaGui::closeEvent(QCloseEvent *event)
1437 if (tray_icon && !ackTrayIcon) {
1438 /* give user a visual hint that the tray icon exists */
1439 if (QSystemTrayIcon::supportsMessages()) {
1441 showTrayMessage(QSystemTrayIcon::Information, 3,
1442 qAppName() + " will keep running in "
1443 "the system tray.");
1445 QMessageBox::information(this, qAppName() + " systray",
1446 "The program will keep "
1447 "running in the system "
1457 void WpaGui::wpsDialog()
1459 wpaguiTab->setCurrentWidget(wpsTab);
1463 void WpaGui::peersDialog()
1470 peers = new Peers();
1473 peers->setWpaGui(this);
1479 void WpaGui::tabChanged(int index)
1487 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1488 if (bssFromScan.isEmpty())
1489 wpsApPinButton->setEnabled(false);
1493 void WpaGui::wpsPbc()
1496 size_t reply_len = sizeof(reply);
1498 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1501 wpsPinEdit->setEnabled(false);
1502 if (wpsStatusText->text().compare("WPS AP in active PBC mode found")) {
1503 wpsInstructions->setText("Press the push button on the AP to "
1504 "start the PBC mode.");
1506 wpsInstructions->setText("If you have not yet done so, press "
1507 "the push button on the AP to start "
1510 wpsStatusText->setText("Waiting for Registrar");
1515 void WpaGui::wpsGeneratePin()
1518 size_t reply_len = sizeof(reply) - 1;
1520 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1523 reply[reply_len] = '\0';
1525 wpsPinEdit->setText(reply);
1526 wpsPinEdit->setEnabled(true);
1527 wpsInstructions->setText("Enter the generated PIN into the Registrar "
1528 "(either the internal one in the AP or an "
1530 wpsStatusText->setText("Waiting for Registrar");
1535 void WpaGui::setBssFromScan(const QString &bssid)
1537 bssFromScan = bssid;
1538 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1539 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1540 wpsStatusText->setText("WPS AP selected from scan results");
1541 wpsInstructions->setText("If you want to use an AP device PIN, e.g., "
1542 "from a label in the device, enter the eight "
1543 "digit AP PIN and click Use AP PIN button.");
1547 void WpaGui::wpsApPinChanged(const QString &text)
1549 wpsApPinButton->setEnabled(text.length() == 8);
1553 void WpaGui::wpsApPin()
1556 size_t reply_len = sizeof(reply);
1558 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1559 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1562 wpsStatusText->setText("Waiting for AP/Enrollee");
1567 void WpaGui::stopWpsRun(bool success)
1570 wpsStatusText->setText(success ? "Connected to the network" :
1573 wpsStatusText->setText("");
1574 wpsPinEdit->setEnabled(false);
1575 wpsInstructions->setText("");
1578 wpsApPinEdit->setEnabled(false);
1579 wpsApPinButton->setEnabled(false);
1583 #ifdef CONFIG_NATIVE_WINDOWS
1586 #define WPASVC_NAME TEXT("wpasvc")
1589 class ErrorMsg : public QMessageBox {
1591 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1592 void showMsg(QString msg);
1597 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1598 QMessageBox(parent), err(last_err)
1600 setWindowTitle("wpa_gui error");
1601 setIcon(QMessageBox::Warning);
1604 void ErrorMsg::showMsg(QString msg)
1609 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1610 FORMAT_MESSAGE_FROM_SYSTEM,
1611 NULL, err, 0, (LPTSTR) (void *) &buf,
1613 QString msg = QString::fromWCharArray(buf);
1614 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1617 setInformativeText(QString("[%1]").arg(err));
1624 void WpaGui::startService()
1628 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1630 ErrorMsg(this).showMsg("OpenSCManager failed");
1634 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1636 ErrorMsg(this).showMsg("OpenService failed");
1637 CloseServiceHandle(scm);
1641 if (!StartService(svc, 0, NULL)) {
1642 ErrorMsg(this).showMsg("Failed to start wpa_supplicant "
1646 CloseServiceHandle(svc);
1647 CloseServiceHandle(scm);
1651 void WpaGui::stopService()
1654 SERVICE_STATUS status;
1656 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1658 ErrorMsg(this).showMsg("OpenSCManager failed");
1662 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1664 ErrorMsg(this).showMsg("OpenService failed");
1665 CloseServiceHandle(scm);
1669 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1670 ErrorMsg(this).showMsg("Failed to stop wpa_supplicant "
1674 CloseServiceHandle(svc);
1675 CloseServiceHandle(scm);
1679 bool WpaGui::serviceRunning()
1682 SERVICE_STATUS status;
1683 bool running = false;
1685 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1687 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1691 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1693 printf("OpenService failed: %d\n\n", (int) GetLastError());
1694 CloseServiceHandle(scm);
1698 if (QueryServiceStatus(svc, &status)) {
1699 if (status.dwCurrentState != SERVICE_STOPPED)
1703 CloseServiceHandle(svc);
1704 CloseServiceHandle(scm);
1709 #endif /* CONFIG_NATIVE_WINDOWS */
1712 void WpaGui::addInterface()
1718 add_iface = new AddInterface(this, this);
1724 void WpaGui::saveState()
1726 QSettings settings("wpa_supplicant", "wpa_gui");
1727 settings.beginGroup("state");
1728 settings.setValue("session_id", app->sessionId());
1729 settings.setValue("in_tray", inTray);
1730 settings.endGroup();