2 * wpa_gui - WpaGui class
3 * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
16 /* Need to get getopt() */
20 #ifdef CONFIG_NATIVE_WINDOWS
22 #endif /* CONFIG_NATIVE_WINDOWS */
25 #include <QMessageBox>
26 #include <QCloseEvent>
27 #include <QImageReader>
32 #include "userdatarequest.h"
33 #include "networkconfig.h"
37 #define printf wpagui_printf
38 static int wpagui_printf(const char *, ...)
44 WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags)
49 #ifdef CONFIG_NATIVE_WINDOWS
50 fileStopServiceAction = new QAction(this);
51 fileStopServiceAction->setObjectName("Stop Service");
52 fileStopServiceAction->setIconText("Stop Service");
53 fileMenu->insertAction(actionWPS, fileStopServiceAction);
55 fileStartServiceAction = new QAction(this);
56 fileStartServiceAction->setObjectName("Start Service");
57 fileStartServiceAction->setIconText("Start Service");
58 fileMenu->insertAction(fileStopServiceAction, fileStartServiceAction);
60 connect(fileStartServiceAction, SIGNAL(triggered()), this,
61 SLOT(startService()));
62 connect(fileStopServiceAction, SIGNAL(triggered()), this,
65 addInterfaceAction = new QAction(this);
66 addInterfaceAction->setIconText("Add Interface");
67 fileMenu->insertAction(fileStartServiceAction, addInterfaceAction);
69 connect(addInterfaceAction, SIGNAL(triggered()), this,
70 SLOT(addInterface()));
71 #endif /* CONFIG_NATIVE_WINDOWS */
75 connect(fileEventHistoryAction, SIGNAL(triggered()), this,
76 SLOT(eventHistory()));
77 connect(fileSaveConfigAction, SIGNAL(triggered()), this,
79 connect(actionWPS, SIGNAL(triggered()), this, SLOT(wpsDialog()));
80 connect(fileExitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
81 connect(networkAddAction, SIGNAL(triggered()), this,
83 connect(networkEditAction, SIGNAL(triggered()), this,
84 SLOT(editSelectedNetwork()));
85 connect(networkRemoveAction, SIGNAL(triggered()), this,
86 SLOT(removeSelectedNetwork()));
87 connect(networkEnableAllAction, SIGNAL(triggered()), this,
88 SLOT(enableAllNetworks()));
89 connect(networkDisableAllAction, SIGNAL(triggered()), this,
90 SLOT(disableAllNetworks()));
91 connect(networkRemoveAllAction, SIGNAL(triggered()), this,
92 SLOT(removeAllNetworks()));
93 connect(helpIndexAction, SIGNAL(triggered()), this, SLOT(helpIndex()));
94 connect(helpContentsAction, SIGNAL(triggered()), this,
95 SLOT(helpContents()));
96 connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(helpAbout()));
97 connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));
98 connect(scanButton, SIGNAL(clicked()), this, SLOT(scan()));
99 connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB()));
100 connect(adapterSelect, SIGNAL(activated(const QString&)), this,
101 SLOT(selectAdapter(const QString&)));
102 connect(networkSelect, SIGNAL(activated(const QString&)), this,
103 SLOT(selectNetwork(const QString&)));
104 connect(addNetworkButton, SIGNAL(clicked()), this, SLOT(addNetwork()));
105 connect(editNetworkButton, SIGNAL(clicked()), this,
106 SLOT(editListedNetwork()));
107 connect(removeNetworkButton, SIGNAL(clicked()), this,
108 SLOT(removeListedNetwork()));
109 connect(networkList, SIGNAL(itemSelectionChanged()), this,
110 SLOT(updateNetworkDisabledStatus()));
111 connect(enableRadioButton, SIGNAL(toggled(bool)), this,
112 SLOT(enableListedNetwork(bool)));
113 connect(disableRadioButton, SIGNAL(toggled(bool)), this,
114 SLOT(disableListedNetwork(bool)));
115 connect(scanNetworkButton, SIGNAL(clicked()), this, SLOT(scan()));
116 connect(networkList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
117 this, SLOT(editListedNetwork()));
118 connect(wpaguiTab, SIGNAL(currentChanged(int)), this,
119 SLOT(tabChanged(int)));
120 connect(wpsPbcButton, SIGNAL(clicked()), this, SLOT(wpsPbc()));
121 connect(wpsPinButton, SIGNAL(clicked()), this, SLOT(wpsGeneratePin()));
122 connect(wpsApPinEdit, SIGNAL(textChanged(const QString &)), this,
123 SLOT(wpsApPinChanged(const QString &)));
124 connect(wpsApPinButton, SIGNAL(clicked()), this, SLOT(wpsApPin()));
136 ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
140 if (QSystemTrayIcon::isSystemTrayAvailable())
141 createTrayIcon(startInTray);
145 connectedToService = false;
146 textStatus->setText("connecting to wpa_supplicant");
147 timer = new QTimer(this);
148 connect(timer, SIGNAL(timeout()), SLOT(ping()));
149 timer->setSingleShot(FALSE);
152 if (openCtrlConnection(ctrl_iface) < 0) {
153 printf("Failed to open control connection to "
154 "wpa_supplicant.\n");
158 networkMayHaveChanged = true;
168 wpa_ctrl_detach(monitor_conn);
169 wpa_ctrl_close(monitor_conn);
173 wpa_ctrl_close(ctrl_conn);
204 free(ctrl_iface_dir);
205 ctrl_iface_dir = NULL;
209 void WpaGui::languageChange()
215 void WpaGui::parse_argv()
219 c = getopt(qApp->argc(), qApp->argv(), "i:p:t");
225 ctrl_iface = strdup(optarg);
228 free(ctrl_iface_dir);
229 ctrl_iface_dir = strdup(optarg);
239 int WpaGui::openCtrlConnection(const char *ifname)
243 char buf[2048], *pos, *pos2;
247 if (ifname != ctrl_iface) {
249 ctrl_iface = strdup(ifname);
252 #ifdef CONFIG_CTRL_IFACE_UDP
254 ctrl_iface = strdup("udp");
255 #endif /* CONFIG_CTRL_IFACE_UDP */
256 #ifdef CONFIG_CTRL_IFACE_UNIX
258 DIR *dir = opendir(ctrl_iface_dir);
262 while ((dent = readdir(dir))) {
263 #ifdef _DIRENT_HAVE_D_TYPE
264 /* Skip the file if it is not a socket.
265 * Also accept DT_UNKNOWN (0) in case
266 * the C library or underlying file
267 * system does not support d_type. */
268 if (dent->d_type != DT_SOCK &&
269 dent->d_type != DT_UNKNOWN)
271 #endif /* _DIRENT_HAVE_D_TYPE */
273 if (strcmp(dent->d_name, ".") == 0 ||
274 strcmp(dent->d_name, "..") == 0)
276 printf("Selected interface '%s'\n",
278 ctrl_iface = strdup(dent->d_name);
283 #endif /* CONFIG_CTRL_IFACE_UNIX */
284 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
285 struct wpa_ctrl *ctrl;
291 ctrl = wpa_ctrl_open(NULL);
293 len = sizeof(buf) - 1;
294 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf,
297 connectedToService = true;
299 pos = strchr(buf, '\n');
302 ctrl_iface = strdup(buf);
304 wpa_ctrl_close(ctrl);
306 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
309 if (ctrl_iface == NULL) {
310 #ifdef CONFIG_NATIVE_WINDOWS
311 static bool first = true;
312 if (first && !serviceRunning()) {
314 if (QMessageBox::warning(
316 "wpa_supplicant service is not running.\n"
317 "Do you want to start it?",
318 QMessageBox::Yes | QMessageBox::No) ==
322 #endif /* CONFIG_NATIVE_WINDOWS */
326 #ifdef CONFIG_CTRL_IFACE_UNIX
327 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
328 cfile = (char *) malloc(flen);
331 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
332 #else /* CONFIG_CTRL_IFACE_UNIX */
333 flen = strlen(ctrl_iface) + 1;
334 cfile = (char *) malloc(flen);
337 snprintf(cfile, flen, "%s", ctrl_iface);
338 #endif /* CONFIG_CTRL_IFACE_UNIX */
341 wpa_ctrl_close(ctrl_conn);
348 wpa_ctrl_detach(monitor_conn);
349 wpa_ctrl_close(monitor_conn);
353 printf("Trying to connect to '%s'\n", cfile);
354 ctrl_conn = wpa_ctrl_open(cfile);
355 if (ctrl_conn == NULL) {
359 monitor_conn = wpa_ctrl_open(cfile);
361 if (monitor_conn == NULL) {
362 wpa_ctrl_close(ctrl_conn);
365 if (wpa_ctrl_attach(monitor_conn)) {
366 printf("Failed to attach to wpa_supplicant\n");
367 wpa_ctrl_close(monitor_conn);
369 wpa_ctrl_close(ctrl_conn);
374 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
375 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
376 QSocketNotifier::Read, this);
377 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
380 adapterSelect->clear();
381 adapterSelect->addItem(ctrl_iface);
382 adapterSelect->setCurrentIndex(0);
384 len = sizeof(buf) - 1;
385 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
390 pos2 = strchr(pos, '\n');
393 if (strcmp(pos, ctrl_iface) != 0)
394 adapterSelect->addItem(pos);
402 len = sizeof(buf) - 1;
403 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len,
408 QStringList types = res.split(QChar(' '));
409 actionWPS->setEnabled(types.contains("WSC"));
410 wpsTab->setEnabled(types.contains("WSC"));
417 static void wpa_gui_msg_cb(char *msg, size_t)
419 /* This should not happen anymore since two control connections are
421 printf("missed message: %s\n", msg);
425 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
429 if (ctrl_conn == NULL)
431 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen,
434 printf("'%s' command timed out.\n", cmd);
436 printf("'%s' command failed.\n", cmd);
442 void WpaGui::updateStatus()
444 char buf[2048], *start, *end, *pos;
447 pingsToStatusUpdate = 10;
449 len = sizeof(buf) - 1;
450 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
451 textStatus->setText("Could not get status from "
453 textAuthentication->clear();
454 textEncryption->clear();
457 textIpAddress->clear();
459 #ifdef CONFIG_NATIVE_WINDOWS
460 static bool first = true;
461 if (first && connectedToService &&
462 (ctrl_iface == NULL || *ctrl_iface == '\0')) {
464 if (QMessageBox::information(
466 "No network interfaces in use.\n"
467 "Would you like to add one?",
468 QMessageBox::Yes | QMessageBox::No) ==
472 #endif /* CONFIG_NATIVE_WINDOWS */
478 bool auth_updated = false, ssid_updated = false;
479 bool bssid_updated = false, ipaddr_updated = false;
480 bool status_updated = false;
481 char *pairwise_cipher = NULL, *group_cipher = NULL;
486 end = strchr(start, '\n');
490 while (end[0] && end[1])
495 pos = strchr(start, '=');
498 if (strcmp(start, "bssid") == 0) {
499 bssid_updated = true;
500 textBssid->setText(pos);
501 } else if (strcmp(start, "ssid") == 0) {
503 textSsid->setText(pos);
504 } else if (strcmp(start, "ip_address") == 0) {
505 ipaddr_updated = true;
506 textIpAddress->setText(pos);
507 } else if (strcmp(start, "wpa_state") == 0) {
508 status_updated = true;
509 textStatus->setText(pos);
510 } else if (strcmp(start, "key_mgmt") == 0) {
512 textAuthentication->setText(pos);
513 /* TODO: could add EAP status to this */
514 } else if (strcmp(start, "pairwise_cipher") == 0) {
515 pairwise_cipher = pos;
516 } else if (strcmp(start, "group_cipher") == 0) {
526 if (pairwise_cipher || group_cipher) {
528 if (pairwise_cipher && group_cipher &&
529 strcmp(pairwise_cipher, group_cipher) != 0) {
530 encr.append(pairwise_cipher);
532 encr.append(group_cipher);
533 } else if (pairwise_cipher) {
534 encr.append(pairwise_cipher);
536 encr.append(group_cipher);
537 encr.append(" [group key only]");
539 textEncryption->setText(encr);
541 textEncryption->clear();
546 textAuthentication->clear();
552 textIpAddress->clear();
556 void WpaGui::updateNetworks()
558 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
560 int first_active = -1;
561 int was_selected = -1;
562 bool current = false;
564 if (!networkMayHaveChanged)
567 if (networkList->currentRow() >= 0)
568 was_selected = networkList->currentRow();
570 networkSelect->clear();
571 networkList->clear();
573 if (ctrl_conn == NULL)
576 len = sizeof(buf) - 1;
577 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
581 start = strchr(buf, '\n');
588 end = strchr(start, '\n');
592 while (end[0] && end[1])
598 ssid = strchr(id, '\t');
602 bssid = strchr(ssid, '\t');
606 flags = strchr(bssid, '\t');
612 network.append(": ");
613 network.append(ssid);
614 networkSelect->addItem(network);
615 networkList->addItem(network);
617 if (strstr(flags, "[CURRENT]")) {
618 networkSelect->setCurrentIndex(networkSelect->count() -
621 } else if (first_active < 0 &&
622 strstr(flags, "[DISABLED]") == NULL)
623 first_active = networkSelect->count() - 1;
630 if (networkSelect->count() > 1)
631 networkSelect->addItem("Select any network");
633 if (!current && first_active >= 0)
634 networkSelect->setCurrentIndex(first_active);
636 if (was_selected >= 0 && networkList->count() > 0) {
637 if (was_selected < networkList->count())
638 networkList->setCurrentRow(was_selected);
640 networkList->setCurrentRow(networkList->count() - 1);
643 networkList->setCurrentRow(networkSelect->currentIndex());
645 networkMayHaveChanged = false;
649 void WpaGui::helpIndex()
651 printf("helpIndex\n");
655 void WpaGui::helpContents()
657 printf("helpContents\n");
661 void WpaGui::helpAbout()
663 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
664 "Copyright (c) 2003-2008,\n"
665 "Jouni Malinen <j@w1.fi>\n"
666 "and contributors.\n"
668 "This program is free software. You can\n"
669 "distribute it and/or modify it under the terms "
671 "the GNU General Public License version 2.\n"
673 "Alternatively, this software may be distributed\n"
674 "under the terms of the BSD license.\n"
676 "This product includes software developed\n"
677 "by the OpenSSL Project for use in the\n"
678 "OpenSSL Toolkit (http://www.openssl.org/)\n");
682 void WpaGui::disconnect()
685 size_t reply_len = sizeof(reply);
686 ctrlRequest("DISCONNECT", reply, &reply_len);
698 scanres = new ScanResults();
701 scanres->setWpaGui(this);
707 void WpaGui::eventHistory()
714 eh = new EventHistory();
728 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
730 * QSocketNotifier cannot be used with Windows named pipes, so use a
731 * timer to check for received messages for now. This could be
732 * optimized be doing something specific to named pipes or Windows
733 * events, but it is not clear what would be the best way of doing that
737 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
739 if (scanres && !scanres->isVisible()) {
744 if (eh && !eh->isVisible()) {
749 if (udr && !udr->isVisible()) {
754 len = sizeof(buf) - 1;
755 if (ctrlRequest("PING", buf, &len) < 0) {
756 printf("PING failed - trying to reconnect\n");
757 if (openCtrlConnection(ctrl_iface) >= 0) {
758 printf("Reconnected successfully\n");
759 pingsToStatusUpdate = 0;
763 pingsToStatusUpdate--;
764 if (pingsToStatusUpdate <= 0) {
769 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
770 /* Use less frequent pings and status updates when the main window is
771 * hidden (running in taskbar). */
772 int interval = isHidden() ? 5000 : 1000;
773 if (timer->interval() != interval)
774 timer->setInterval(interval);
775 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
779 static int str_match(const char *a, const char *b)
781 return strncmp(a, b, strlen(b)) == 0;
785 void WpaGui::processMsg(char *msg)
787 char *pos = msg, *pos2;
793 priority = atoi(pos);
794 pos = strchr(pos, '>');
801 WpaMsg wm(pos, priority);
805 while (msgs.count() > 100)
808 /* Update last message with truncated version of the event */
809 if (strncmp(pos, "CTRL-", 5) == 0) {
810 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
817 QString lastmsg = pos2;
818 lastmsg.truncate(40);
819 textLastMessage->setText(lastmsg);
821 pingsToStatusUpdate = 0;
822 networkMayHaveChanged = true;
824 if (str_match(pos, WPA_CTRL_REQ))
825 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
826 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
827 scanres->updateResults();
828 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
829 showTrayMessage(QSystemTrayIcon::Information, 3,
830 "Disconnected from network.");
831 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
832 showTrayMessage(QSystemTrayIcon::Information, 3,
833 "Connection to network established.");
834 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
836 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
837 showTrayMessage(QSystemTrayIcon::Information, 3,
838 "Wi-Fi Protected Setup (WPS) AP\n"
839 "in active PBC mode found.");
840 wpsStatusText->setText("WPS AP in active PBC mode found");
841 wpaguiTab->setCurrentWidget(wpsTab);
842 wpsInstructions->setText("Press the PBC button on the screen "
843 "to start registration");
844 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
845 showTrayMessage(QSystemTrayIcon::Information, 3,
846 "Wi-Fi Protected Setup (WPS) AP\n"
847 " in active PIN mode found.");
848 wpsStatusText->setText("WPS AP with recently selected "
850 wpaguiTab->setCurrentWidget(wpsTab);
851 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
852 showTrayMessage(QSystemTrayIcon::Information, 3,
853 "Wi-Fi Protected Setup (WPS)\n"
855 wpsStatusText->setText("WPS AP detected");
856 wpaguiTab->setCurrentWidget(wpsTab);
857 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
858 showTrayMessage(QSystemTrayIcon::Information, 3,
859 "Wi-Fi Protected Setup (WPS)\n"
860 "PBC mode overlap detected.");
861 wpsStatusText->setText("PBC mode overlap detected");
862 wpsInstructions->setText("More than one AP is currently in "
863 "active WPS PBC mode. Wait couple of "
864 "minutes and try again");
865 wpaguiTab->setCurrentWidget(wpsTab);
866 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
867 wpsStatusText->setText("Network configuration received");
868 wpaguiTab->setCurrentWidget(wpsTab);
869 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
870 if (strstr(pos, "(WSC)"))
871 wpsStatusText->setText("Registration started");
872 } else if (str_match(pos, WPS_EVENT_M2D)) {
873 wpsStatusText->setText("Registrar does not yet know PIN");
874 } else if (str_match(pos, WPS_EVENT_FAIL)) {
875 wpsStatusText->setText("Registration failed");
876 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
877 wpsStatusText->setText("Registration succeeded");
882 void WpaGui::processCtrlReq(const char *req)
888 udr = new UserDataRequest();
891 if (udr->setParams(this, req) < 0) {
901 void WpaGui::receiveMsgs()
906 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
907 len = sizeof(buf) - 1;
908 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
916 void WpaGui::connectB()
919 size_t reply_len = sizeof(reply);
920 ctrlRequest("REASSOCIATE", reply, &reply_len);
924 void WpaGui::selectNetwork( const QString &sel )
928 size_t reply_len = sizeof(reply);
930 if (cmd.startsWith("Select any")) {
933 int pos = cmd.indexOf(':');
935 printf("Invalid selectNetwork '%s'\n",
936 cmd.toAscii().constData());
941 cmd.prepend("SELECT_NETWORK ");
942 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
948 void WpaGui::enableNetwork(const QString &sel)
952 size_t reply_len = sizeof(reply);
954 if (!cmd.startsWith("all")) {
955 int pos = cmd.indexOf(':');
957 printf("Invalid enableNetwork '%s'\n",
958 cmd.toAscii().constData());
963 cmd.prepend("ENABLE_NETWORK ");
964 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
969 void WpaGui::disableNetwork(const QString &sel)
973 size_t reply_len = sizeof(reply);
975 if (!cmd.startsWith("all")) {
976 int pos = cmd.indexOf(':');
978 printf("Invalid disableNetwork '%s'\n",
979 cmd.toAscii().constData());
984 cmd.prepend("DISABLE_NETWORK ");
985 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
990 void WpaGui::editNetwork(const QString &sel)
995 if (!cmd.startsWith("Select any")) {
996 int pos = sel.indexOf(':');
998 printf("Invalid editNetwork '%s'\n",
999 cmd.toAscii().constData());
1006 NetworkConfig *nc = new NetworkConfig();
1009 nc->setWpaGui(this);
1012 nc->paramsFromConfig(id);
1021 void WpaGui::editSelectedNetwork()
1023 if (networkSelect->count() < 1) {
1024 QMessageBox::information(this, "No Networks",
1025 "There are no networks to edit.\n");
1028 QString sel(networkSelect->currentText());
1033 void WpaGui::editListedNetwork()
1035 if (networkList->currentRow() < 0) {
1036 QMessageBox::information(this, "Select A Network",
1037 "Select a network from the list to"
1041 QString sel(networkList->currentItem()->text());
1046 void WpaGui::triggerUpdate()
1049 networkMayHaveChanged = true;
1054 void WpaGui::addNetwork()
1056 NetworkConfig *nc = new NetworkConfig();
1059 nc->setWpaGui(this);
1066 void WpaGui::removeNetwork(const QString &sel)
1070 size_t reply_len = sizeof(reply);
1072 if (cmd.startsWith("Select any"))
1075 if (!cmd.startsWith("all")) {
1076 int pos = cmd.indexOf(':');
1078 printf("Invalid removeNetwork '%s'\n",
1079 cmd.toAscii().constData());
1084 cmd.prepend("REMOVE_NETWORK ");
1085 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1090 void WpaGui::removeSelectedNetwork()
1092 if (networkSelect->count() < 1) {
1093 QMessageBox::information(this, "No Networks",
1094 "There are no networks to remove.\n");
1097 QString sel(networkSelect->currentText());
1102 void WpaGui::removeListedNetwork()
1104 if (networkList->currentRow() < 0) {
1105 QMessageBox::information(this, "Select A Network",
1106 "Select a network from the list to"
1110 QString sel(networkList->currentItem()->text());
1115 void WpaGui::enableAllNetworks()
1122 void WpaGui::disableAllNetworks()
1125 disableNetwork(sel);
1129 void WpaGui::removeAllNetworks()
1136 int WpaGui::getNetworkDisabled(const QString &sel)
1140 size_t reply_len = sizeof(reply) - 1;
1141 int pos = cmd.indexOf(':');
1143 printf("Invalid getNetworkDisabled '%s'\n",
1144 cmd.toAscii().constData());
1148 cmd.prepend("GET_NETWORK ");
1149 cmd.append(" disabled");
1151 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1152 && reply_len >= 1) {
1153 reply[reply_len] = '\0';
1154 if (!str_match(reply, "FAIL"))
1162 void WpaGui::updateNetworkDisabledStatus()
1164 if (networkList->currentRow() < 0)
1167 QString sel(networkList->currentItem()->text());
1169 switch (getNetworkDisabled(sel)) {
1171 if (!enableRadioButton->isChecked())
1172 enableRadioButton->setChecked(true);
1175 if (!disableRadioButton->isChecked())
1176 disableRadioButton->setChecked(true);
1182 void WpaGui::enableListedNetwork(bool enabled)
1184 if (networkList->currentRow() < 0 || !enabled)
1187 QString sel(networkList->currentItem()->text());
1189 if (getNetworkDisabled(sel) == 1)
1194 void WpaGui::disableListedNetwork(bool disabled)
1196 if (networkList->currentRow() < 0 || !disabled)
1199 QString sel(networkList->currentItem()->text());
1201 if (getNetworkDisabled(sel) == 0)
1202 disableNetwork(sel);
1206 void WpaGui::saveConfig()
1211 len = sizeof(buf) - 1;
1212 ctrlRequest("SAVE_CONFIG", buf, &len);
1216 if (str_match(buf, "FAIL"))
1217 QMessageBox::warning(this, "Failed to save configuration",
1218 "The configuration could not be saved.\n"
1220 "The update_config=1 configuration option\n"
1221 "must be used for configuration saving to\n"
1224 QMessageBox::information(this, "Saved configuration",
1225 "The current configuration was saved."
1230 void WpaGui::selectAdapter( const QString & sel )
1232 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1233 printf("Failed to open control connection to "
1234 "wpa_supplicant.\n");
1240 void WpaGui::createTrayIcon(bool trayOnly)
1242 QApplication::setQuitOnLastWindowClosed(false);
1244 tray_icon = new QSystemTrayIcon(this);
1245 tray_icon->setToolTip(qAppName() + " - wpa_supplicant user interface");
1246 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1247 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1249 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1252 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1253 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1255 ackTrayIcon = false;
1257 tray_menu = new QMenu(this);
1259 disconnectAction = new QAction("&Disconnect", this);
1260 reconnectAction = new QAction("Re&connect", this);
1261 connect(disconnectAction, SIGNAL(triggered()), this,
1262 SLOT(disconnect()));
1263 connect(reconnectAction, SIGNAL(triggered()), this,
1265 tray_menu->addAction(disconnectAction);
1266 tray_menu->addAction(reconnectAction);
1267 tray_menu->addSeparator();
1269 eventAction = new QAction("&Event History", this);
1270 scanAction = new QAction("Scan &Results", this);
1271 statAction = new QAction("S&tatus", this);
1272 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1273 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1274 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1275 tray_menu->addAction(eventAction);
1276 tray_menu->addAction(scanAction);
1277 tray_menu->addAction(statAction);
1278 tray_menu->addSeparator();
1280 showAction = new QAction("&Show Window", this);
1281 hideAction = new QAction("&Hide Window", this);
1282 quitAction = new QAction("&Quit", this);
1283 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1284 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1285 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1286 tray_menu->addAction(showAction);
1287 tray_menu->addAction(hideAction);
1288 tray_menu->addSeparator();
1289 tray_menu->addAction(quitAction);
1291 tray_icon->setContextMenu(tray_menu);
1300 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1301 const QString & msg)
1303 if (!QSystemTrayIcon::supportsMessages())
1306 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1309 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1313 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1316 /* use close() here instead of hide() and allow the
1317 * custom closeEvent handler take care of children */
1318 case QSystemTrayIcon::Trigger:
1325 case QSystemTrayIcon::MiddleClick:
1334 void WpaGui::showTrayStatus()
1339 len = sizeof(buf) - 1;
1340 if (ctrlRequest("STATUS", buf, &len) < 0)
1344 QString msg, status(buf);
1346 QStringList lines = status.split(QRegExp("\\n"));
1347 for (QStringList::Iterator it = lines.begin();
1348 it != lines.end(); it++) {
1349 int pos = (*it).indexOf('=') + 1;
1353 if ((*it).startsWith("bssid="))
1354 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1355 else if ((*it).startsWith("ssid="))
1356 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1357 else if ((*it).startsWith("pairwise_cipher="))
1358 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1359 else if ((*it).startsWith("group_cipher="))
1360 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1361 else if ((*it).startsWith("key_mgmt="))
1362 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1363 else if ((*it).startsWith("wpa_state="))
1364 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1365 else if ((*it).startsWith("ip_address="))
1366 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1367 else if ((*it).startsWith("Supplicant PAE state="))
1368 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1369 else if ((*it).startsWith("EAP state="))
1370 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1374 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1378 void WpaGui::closeEvent(QCloseEvent *event)
1398 if (tray_icon && !ackTrayIcon) {
1399 /* give user a visual hint that the tray icon exists */
1400 if (QSystemTrayIcon::supportsMessages()) {
1402 showTrayMessage(QSystemTrayIcon::Information, 3,
1403 qAppName() + " will keep running in "
1404 "the system tray.");
1406 QMessageBox::information(this, qAppName() + " systray",
1407 "The program will keep "
1408 "running in the system "
1418 void WpaGui::wpsDialog()
1420 wpaguiTab->setCurrentWidget(wpsTab);
1424 void WpaGui::tabChanged(int index)
1432 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1433 if (bssFromScan.isEmpty())
1434 wpsApPinButton->setEnabled(false);
1438 void WpaGui::wpsPbc()
1441 size_t reply_len = sizeof(reply);
1443 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1446 wpsPinEdit->setEnabled(false);
1447 if (wpsStatusText->text().compare("WPS AP in active PBC mode found")) {
1448 wpsInstructions->setText("Press the push button on the AP to "
1449 "start the PBC mode.");
1451 wpsInstructions->setText("If you have not yet done so, press "
1452 "the push button on the AP to start "
1455 wpsStatusText->setText("Waiting for Registrar");
1460 void WpaGui::wpsGeneratePin()
1463 size_t reply_len = sizeof(reply) - 1;
1465 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1468 reply[reply_len] = '\0';
1470 wpsPinEdit->setText(reply);
1471 wpsPinEdit->setEnabled(true);
1472 wpsInstructions->setText("Enter the generated PIN into the Registrar "
1473 "(either the internal one in the AP or an "
1475 wpsStatusText->setText("Waiting for Registrar");
1480 void WpaGui::setBssFromScan(const QString &bssid)
1482 bssFromScan = bssid;
1483 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1484 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1485 wpsStatusText->setText("WPS AP selected from scan results");
1486 wpsInstructions->setText("If you want to use an AP device PIN, e.g., "
1487 "from a label in the device, enter the eight "
1488 "digit AP PIN and click Use AP PIN button.");
1492 void WpaGui::wpsApPinChanged(const QString &text)
1494 wpsApPinButton->setEnabled(text.length() == 8);
1498 void WpaGui::wpsApPin()
1501 size_t reply_len = sizeof(reply);
1503 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1504 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1507 wpsStatusText->setText("Waiting for AP/Enrollee");
1512 void WpaGui::stopWpsRun(bool success)
1515 wpsStatusText->setText(success ? "Connected to the network" :
1518 wpsStatusText->setText("");
1519 wpsPinEdit->setEnabled(false);
1520 wpsInstructions->setText("");
1523 wpsApPinEdit->setEnabled(false);
1524 wpsApPinButton->setEnabled(false);
1528 #ifdef CONFIG_NATIVE_WINDOWS
1531 #define WPASVC_NAME TEXT("wpasvc")
1534 class ErrorMsg : public QMessageBox {
1536 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1537 void showMsg(QString msg);
1542 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1543 QMessageBox(parent), err(last_err)
1545 setWindowTitle("wpa_gui error");
1546 setIcon(QMessageBox::Warning);
1549 void ErrorMsg::showMsg(QString msg)
1554 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1555 FORMAT_MESSAGE_FROM_SYSTEM,
1556 NULL, err, 0, (LPTSTR) (void *) &buf,
1558 QString msg = QString::fromWCharArray(buf);
1559 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1562 setInformativeText(QString("[%1]").arg(err));
1569 void WpaGui::startService()
1573 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1575 ErrorMsg(this).showMsg("OpenSCManager failed");
1579 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1581 ErrorMsg(this).showMsg("OpenService failed");
1582 CloseServiceHandle(scm);
1586 if (!StartService(svc, 0, NULL)) {
1587 ErrorMsg(this).showMsg("Failed to start wpa_supplicant "
1591 CloseServiceHandle(svc);
1592 CloseServiceHandle(scm);
1596 void WpaGui::stopService()
1599 SERVICE_STATUS status;
1601 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1603 ErrorMsg(this).showMsg("OpenSCManager failed");
1607 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1609 ErrorMsg(this).showMsg("OpenService failed");
1610 CloseServiceHandle(scm);
1614 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1615 ErrorMsg(this).showMsg("Failed to stop wpa_supplicant "
1619 CloseServiceHandle(svc);
1620 CloseServiceHandle(scm);
1624 bool WpaGui::serviceRunning()
1627 SERVICE_STATUS status;
1628 bool running = false;
1630 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1632 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1636 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1638 printf("OpenService failed: %d\n\n", (int) GetLastError());
1639 CloseServiceHandle(scm);
1643 if (QueryServiceStatus(svc, &status)) {
1644 if (status.dwCurrentState != SERVICE_STOPPED)
1648 CloseServiceHandle(svc);
1649 CloseServiceHandle(scm);
1654 #endif /* CONFIG_NATIVE_WINDOWS */
1657 void WpaGui::addInterface()
1663 add_iface = new AddInterface(this, this);