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"));
416 static void wpa_gui_msg_cb(char *msg, size_t)
418 /* This should not happen anymore since two control connections are
420 printf("missed message: %s\n", msg);
424 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
428 if (ctrl_conn == NULL)
430 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen,
433 printf("'%s' command timed out.\n", cmd);
435 printf("'%s' command failed.\n", cmd);
441 void WpaGui::updateStatus()
443 char buf[2048], *start, *end, *pos;
446 pingsToStatusUpdate = 10;
448 len = sizeof(buf) - 1;
449 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
450 textStatus->setText("Could not get status from "
452 textAuthentication->clear();
453 textEncryption->clear();
456 textIpAddress->clear();
458 #ifdef CONFIG_NATIVE_WINDOWS
459 static bool first = true;
460 if (first && connectedToService &&
461 (ctrl_iface == NULL || *ctrl_iface == '\0')) {
463 if (QMessageBox::information(
465 "No network interfaces in use.\n"
466 "Would you like to add one?",
467 QMessageBox::Yes | QMessageBox::No) ==
471 #endif /* CONFIG_NATIVE_WINDOWS */
477 bool auth_updated = false, ssid_updated = false;
478 bool bssid_updated = false, ipaddr_updated = false;
479 bool status_updated = false;
480 char *pairwise_cipher = NULL, *group_cipher = NULL;
485 end = strchr(start, '\n');
489 while (end[0] && end[1])
494 pos = strchr(start, '=');
497 if (strcmp(start, "bssid") == 0) {
498 bssid_updated = true;
499 textBssid->setText(pos);
500 } else if (strcmp(start, "ssid") == 0) {
502 textSsid->setText(pos);
503 } else if (strcmp(start, "ip_address") == 0) {
504 ipaddr_updated = true;
505 textIpAddress->setText(pos);
506 } else if (strcmp(start, "wpa_state") == 0) {
507 status_updated = true;
508 textStatus->setText(pos);
509 } else if (strcmp(start, "key_mgmt") == 0) {
511 textAuthentication->setText(pos);
512 /* TODO: could add EAP status to this */
513 } else if (strcmp(start, "pairwise_cipher") == 0) {
514 pairwise_cipher = pos;
515 } else if (strcmp(start, "group_cipher") == 0) {
525 if (pairwise_cipher || group_cipher) {
527 if (pairwise_cipher && group_cipher &&
528 strcmp(pairwise_cipher, group_cipher) != 0) {
529 encr.append(pairwise_cipher);
531 encr.append(group_cipher);
532 } else if (pairwise_cipher) {
533 encr.append(pairwise_cipher);
535 encr.append(group_cipher);
536 encr.append(" [group key only]");
538 textEncryption->setText(encr);
540 textEncryption->clear();
545 textAuthentication->clear();
551 textIpAddress->clear();
555 void WpaGui::updateNetworks()
557 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
559 int first_active = -1;
560 int was_selected = -1;
561 bool current = false;
563 if (!networkMayHaveChanged)
566 if (networkList->currentRow() >= 0)
567 was_selected = networkList->currentRow();
569 networkSelect->clear();
570 networkList->clear();
572 if (ctrl_conn == NULL)
575 len = sizeof(buf) - 1;
576 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
580 start = strchr(buf, '\n');
587 end = strchr(start, '\n');
591 while (end[0] && end[1])
597 ssid = strchr(id, '\t');
601 bssid = strchr(ssid, '\t');
605 flags = strchr(bssid, '\t');
611 network.append(": ");
612 network.append(ssid);
613 networkSelect->addItem(network);
614 networkList->addItem(network);
616 if (strstr(flags, "[CURRENT]")) {
617 networkSelect->setCurrentIndex(networkSelect->count() -
620 } else if (first_active < 0 &&
621 strstr(flags, "[DISABLED]") == NULL)
622 first_active = networkSelect->count() - 1;
629 if (networkSelect->count() > 1)
630 networkSelect->addItem("Select any network");
632 if (!current && first_active >= 0)
633 networkSelect->setCurrentIndex(first_active);
635 if (was_selected >= 0 && networkList->count() > 0) {
636 if (was_selected < networkList->count())
637 networkList->setCurrentRow(was_selected);
639 networkList->setCurrentRow(networkList->count() - 1);
642 networkList->setCurrentRow(networkSelect->currentIndex());
644 networkMayHaveChanged = false;
648 void WpaGui::helpIndex()
650 printf("helpIndex\n");
654 void WpaGui::helpContents()
656 printf("helpContents\n");
660 void WpaGui::helpAbout()
662 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
663 "Copyright (c) 2003-2008,\n"
664 "Jouni Malinen <j@w1.fi>\n"
665 "and contributors.\n"
667 "This program is free software. You can\n"
668 "distribute it and/or modify it under the terms "
670 "the GNU General Public License version 2.\n"
672 "Alternatively, this software may be distributed\n"
673 "under the terms of the BSD license.\n"
675 "This product includes software developed\n"
676 "by the OpenSSL Project for use in the\n"
677 "OpenSSL Toolkit (http://www.openssl.org/)\n");
681 void WpaGui::disconnect()
684 size_t reply_len = sizeof(reply);
685 ctrlRequest("DISCONNECT", reply, &reply_len);
697 scanres = new ScanResults();
700 scanres->setWpaGui(this);
706 void WpaGui::eventHistory()
713 eh = new EventHistory();
727 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
729 * QSocketNotifier cannot be used with Windows named pipes, so use a
730 * timer to check for received messages for now. This could be
731 * optimized be doing something specific to named pipes or Windows
732 * events, but it is not clear what would be the best way of doing that
736 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
738 if (scanres && !scanres->isVisible()) {
743 if (eh && !eh->isVisible()) {
748 if (udr && !udr->isVisible()) {
753 len = sizeof(buf) - 1;
754 if (ctrlRequest("PING", buf, &len) < 0) {
755 printf("PING failed - trying to reconnect\n");
756 if (openCtrlConnection(ctrl_iface) >= 0) {
757 printf("Reconnected successfully\n");
758 pingsToStatusUpdate = 0;
762 pingsToStatusUpdate--;
763 if (pingsToStatusUpdate <= 0) {
768 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
769 /* Use less frequent pings and status updates when the main window is
770 * hidden (running in taskbar). */
771 int interval = isHidden() ? 5000 : 1000;
772 if (timer->interval() != interval)
773 timer->setInterval(interval);
774 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
778 static int str_match(const char *a, const char *b)
780 return strncmp(a, b, strlen(b)) == 0;
784 void WpaGui::processMsg(char *msg)
786 char *pos = msg, *pos2;
792 priority = atoi(pos);
793 pos = strchr(pos, '>');
800 WpaMsg wm(pos, priority);
804 while (msgs.count() > 100)
807 /* Update last message with truncated version of the event */
808 if (strncmp(pos, "CTRL-", 5) == 0) {
809 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
816 QString lastmsg = pos2;
817 lastmsg.truncate(40);
818 textLastMessage->setText(lastmsg);
820 pingsToStatusUpdate = 0;
821 networkMayHaveChanged = true;
823 if (str_match(pos, WPA_CTRL_REQ))
824 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
825 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
826 scanres->updateResults();
827 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
828 showTrayMessage(QSystemTrayIcon::Information, 3,
829 "Disconnected from network.");
830 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
831 showTrayMessage(QSystemTrayIcon::Information, 3,
832 "Connection to network established.");
833 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
835 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
836 showTrayMessage(QSystemTrayIcon::Information, 3,
837 "Wi-Fi Protected Setup (WPS) AP\n"
838 "in active PBC mode found.");
839 wpsStatusText->setText("WPS AP in active PBC mode found");
840 wpaguiTab->setCurrentWidget(wpsTab);
841 wpsInstructions->setText("Press the PBC button on the screen "
842 "to start registration");
843 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
844 showTrayMessage(QSystemTrayIcon::Information, 3,
845 "Wi-Fi Protected Setup (WPS) AP\n"
846 " in active PIN mode found.");
847 wpsStatusText->setText("WPS AP with recently selected "
849 wpaguiTab->setCurrentWidget(wpsTab);
850 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
851 showTrayMessage(QSystemTrayIcon::Information, 3,
852 "Wi-Fi Protected Setup (WPS)\n"
854 wpsStatusText->setText("WPS AP detected");
855 wpaguiTab->setCurrentWidget(wpsTab);
856 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
857 showTrayMessage(QSystemTrayIcon::Information, 3,
858 "Wi-Fi Protected Setup (WPS)\n"
859 "PBC mode overlap detected.");
860 wpsStatusText->setText("PBC mode overlap detected");
861 wpsInstructions->setText("More than one AP is currently in "
862 "active WPS PBC mode. Wait couple of "
863 "minutes and try again");
864 wpaguiTab->setCurrentWidget(wpsTab);
865 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
866 wpsStatusText->setText("Network configuration received");
867 wpaguiTab->setCurrentWidget(wpsTab);
868 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
869 if (strstr(pos, "(WSC)"))
870 wpsStatusText->setText("Registration started");
871 } else if (str_match(pos, WPS_EVENT_M2D)) {
872 wpsStatusText->setText("Registrar does not yet know PIN");
873 } else if (str_match(pos, WPS_EVENT_FAIL)) {
874 wpsStatusText->setText("Registration failed");
875 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
876 wpsStatusText->setText("Registration succeeded");
881 void WpaGui::processCtrlReq(const char *req)
887 udr = new UserDataRequest();
890 if (udr->setParams(this, req) < 0) {
900 void WpaGui::receiveMsgs()
905 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
906 len = sizeof(buf) - 1;
907 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
915 void WpaGui::connectB()
918 size_t reply_len = sizeof(reply);
919 ctrlRequest("REASSOCIATE", reply, &reply_len);
923 void WpaGui::selectNetwork( const QString &sel )
927 size_t reply_len = sizeof(reply);
929 if (cmd.startsWith("Select any")) {
932 int pos = cmd.indexOf(':');
934 printf("Invalid selectNetwork '%s'\n",
935 cmd.toAscii().constData());
940 cmd.prepend("SELECT_NETWORK ");
941 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
947 void WpaGui::enableNetwork(const QString &sel)
951 size_t reply_len = sizeof(reply);
953 if (!cmd.startsWith("all")) {
954 int pos = cmd.indexOf(':');
956 printf("Invalid enableNetwork '%s'\n",
957 cmd.toAscii().constData());
962 cmd.prepend("ENABLE_NETWORK ");
963 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
968 void WpaGui::disableNetwork(const QString &sel)
972 size_t reply_len = sizeof(reply);
974 if (!cmd.startsWith("all")) {
975 int pos = cmd.indexOf(':');
977 printf("Invalid disableNetwork '%s'\n",
978 cmd.toAscii().constData());
983 cmd.prepend("DISABLE_NETWORK ");
984 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
989 void WpaGui::editNetwork(const QString &sel)
994 if (!cmd.startsWith("Select any")) {
995 int pos = sel.indexOf(':');
997 printf("Invalid editNetwork '%s'\n",
998 cmd.toAscii().constData());
1005 NetworkConfig *nc = new NetworkConfig();
1008 nc->setWpaGui(this);
1011 nc->paramsFromConfig(id);
1020 void WpaGui::editSelectedNetwork()
1022 if (networkSelect->count() < 1) {
1023 QMessageBox::information(this, "No Networks",
1024 "There are no networks to edit.\n");
1027 QString sel(networkSelect->currentText());
1032 void WpaGui::editListedNetwork()
1034 if (networkList->currentRow() < 0) {
1035 QMessageBox::information(this, "Select A Network",
1036 "Select a network from the list to"
1040 QString sel(networkList->currentItem()->text());
1045 void WpaGui::triggerUpdate()
1048 networkMayHaveChanged = true;
1053 void WpaGui::addNetwork()
1055 NetworkConfig *nc = new NetworkConfig();
1058 nc->setWpaGui(this);
1065 void WpaGui::removeNetwork(const QString &sel)
1069 size_t reply_len = sizeof(reply);
1071 if (cmd.startsWith("Select any"))
1074 if (!cmd.startsWith("all")) {
1075 int pos = cmd.indexOf(':');
1077 printf("Invalid removeNetwork '%s'\n",
1078 cmd.toAscii().constData());
1083 cmd.prepend("REMOVE_NETWORK ");
1084 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1089 void WpaGui::removeSelectedNetwork()
1091 if (networkSelect->count() < 1) {
1092 QMessageBox::information(this, "No Networks",
1093 "There are no networks to remove.\n");
1096 QString sel(networkSelect->currentText());
1101 void WpaGui::removeListedNetwork()
1103 if (networkList->currentRow() < 0) {
1104 QMessageBox::information(this, "Select A Network",
1105 "Select a network from the list to"
1109 QString sel(networkList->currentItem()->text());
1114 void WpaGui::enableAllNetworks()
1121 void WpaGui::disableAllNetworks()
1124 disableNetwork(sel);
1128 void WpaGui::removeAllNetworks()
1135 int WpaGui::getNetworkDisabled(const QString &sel)
1139 size_t reply_len = sizeof(reply) - 1;
1140 int pos = cmd.indexOf(':');
1142 printf("Invalid getNetworkDisabled '%s'\n",
1143 cmd.toAscii().constData());
1147 cmd.prepend("GET_NETWORK ");
1148 cmd.append(" disabled");
1150 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1151 && reply_len >= 1) {
1152 reply[reply_len] = '\0';
1153 if (!str_match(reply, "FAIL"))
1161 void WpaGui::updateNetworkDisabledStatus()
1163 if (networkList->currentRow() < 0)
1166 QString sel(networkList->currentItem()->text());
1168 switch (getNetworkDisabled(sel)) {
1170 if (!enableRadioButton->isChecked())
1171 enableRadioButton->setChecked(true);
1174 if (!disableRadioButton->isChecked())
1175 disableRadioButton->setChecked(true);
1181 void WpaGui::enableListedNetwork(bool enabled)
1183 if (networkList->currentRow() < 0 || !enabled)
1186 QString sel(networkList->currentItem()->text());
1188 if (getNetworkDisabled(sel) == 1)
1193 void WpaGui::disableListedNetwork(bool disabled)
1195 if (networkList->currentRow() < 0 || !disabled)
1198 QString sel(networkList->currentItem()->text());
1200 if (getNetworkDisabled(sel) == 0)
1201 disableNetwork(sel);
1205 void WpaGui::saveConfig()
1210 len = sizeof(buf) - 1;
1211 ctrlRequest("SAVE_CONFIG", buf, &len);
1215 if (str_match(buf, "FAIL"))
1216 QMessageBox::warning(this, "Failed to save configuration",
1217 "The configuration could not be saved.\n"
1219 "The update_config=1 configuration option\n"
1220 "must be used for configuration saving to\n"
1223 QMessageBox::information(this, "Saved configuration",
1224 "The current configuration was saved."
1229 void WpaGui::selectAdapter( const QString & sel )
1231 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1232 printf("Failed to open control connection to "
1233 "wpa_supplicant.\n");
1239 void WpaGui::createTrayIcon(bool trayOnly)
1241 QApplication::setQuitOnLastWindowClosed(false);
1243 tray_icon = new QSystemTrayIcon(this);
1244 tray_icon->setToolTip(qAppName() + " - wpa_supplicant user interface");
1245 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1246 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1248 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1251 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1252 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1254 ackTrayIcon = false;
1256 tray_menu = new QMenu(this);
1258 disconnectAction = new QAction("&Disconnect", this);
1259 reconnectAction = new QAction("Re&connect", this);
1260 connect(disconnectAction, SIGNAL(triggered()), this,
1261 SLOT(disconnect()));
1262 connect(reconnectAction, SIGNAL(triggered()), this,
1264 tray_menu->addAction(disconnectAction);
1265 tray_menu->addAction(reconnectAction);
1266 tray_menu->addSeparator();
1268 eventAction = new QAction("&Event History", this);
1269 scanAction = new QAction("Scan &Results", this);
1270 statAction = new QAction("S&tatus", this);
1271 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1272 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1273 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1274 tray_menu->addAction(eventAction);
1275 tray_menu->addAction(scanAction);
1276 tray_menu->addAction(statAction);
1277 tray_menu->addSeparator();
1279 showAction = new QAction("&Show Window", this);
1280 hideAction = new QAction("&Hide Window", this);
1281 quitAction = new QAction("&Quit", this);
1282 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1283 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1284 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1285 tray_menu->addAction(showAction);
1286 tray_menu->addAction(hideAction);
1287 tray_menu->addSeparator();
1288 tray_menu->addAction(quitAction);
1290 tray_icon->setContextMenu(tray_menu);
1299 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1300 const QString & msg)
1302 if (!QSystemTrayIcon::supportsMessages())
1305 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1308 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1312 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1315 /* use close() here instead of hide() and allow the
1316 * custom closeEvent handler take care of children */
1317 case QSystemTrayIcon::Trigger:
1324 case QSystemTrayIcon::MiddleClick:
1333 void WpaGui::showTrayStatus()
1338 len = sizeof(buf) - 1;
1339 if (ctrlRequest("STATUS", buf, &len) < 0)
1343 QString msg, status(buf);
1345 QStringList lines = status.split(QRegExp("\\n"));
1346 for (QStringList::Iterator it = lines.begin();
1347 it != lines.end(); it++) {
1348 int pos = (*it).indexOf('=') + 1;
1352 if ((*it).startsWith("bssid="))
1353 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1354 else if ((*it).startsWith("ssid="))
1355 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1356 else if ((*it).startsWith("pairwise_cipher="))
1357 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1358 else if ((*it).startsWith("group_cipher="))
1359 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1360 else if ((*it).startsWith("key_mgmt="))
1361 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1362 else if ((*it).startsWith("wpa_state="))
1363 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1364 else if ((*it).startsWith("ip_address="))
1365 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1366 else if ((*it).startsWith("Supplicant PAE state="))
1367 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1368 else if ((*it).startsWith("EAP state="))
1369 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1373 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1377 void WpaGui::closeEvent(QCloseEvent *event)
1397 if (tray_icon && !ackTrayIcon) {
1398 /* give user a visual hint that the tray icon exists */
1399 if (QSystemTrayIcon::supportsMessages()) {
1401 showTrayMessage(QSystemTrayIcon::Information, 3,
1402 qAppName() + " will keep running in "
1403 "the system tray.");
1405 QMessageBox::information(this, qAppName() + " systray",
1406 "The program will keep "
1407 "running in the system "
1417 void WpaGui::wpsDialog()
1419 wpaguiTab->setCurrentWidget(wpsTab);
1423 void WpaGui::tabChanged(int index)
1431 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1432 if (bssFromScan.isEmpty())
1433 wpsApPinButton->setEnabled(false);
1437 void WpaGui::wpsPbc()
1440 size_t reply_len = sizeof(reply);
1442 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1445 wpsPinEdit->setEnabled(false);
1446 if (wpsStatusText->text().compare("WPS AP in active PBC mode found")) {
1447 wpsInstructions->setText("Press the push button on the AP to "
1448 "start the PBC mode.");
1450 wpsInstructions->setText("If you have not yet done so, press "
1451 "the push button on the AP to start "
1454 wpsStatusText->setText("Waiting for Registrar");
1459 void WpaGui::wpsGeneratePin()
1462 size_t reply_len = sizeof(reply) - 1;
1464 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1467 reply[reply_len] = '\0';
1469 wpsPinEdit->setText(reply);
1470 wpsPinEdit->setEnabled(true);
1471 wpsInstructions->setText("Enter the generated PIN into the Registrar "
1472 "(either the internal one in the AP or an "
1474 wpsStatusText->setText("Waiting for Registrar");
1479 void WpaGui::setBssFromScan(const QString &bssid)
1481 bssFromScan = bssid;
1482 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1483 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1484 wpsStatusText->setText("WPS AP selected from scan results");
1485 wpsInstructions->setText("If you want to use an AP device PIN, e.g., "
1486 "from a label in the device, enter the eight "
1487 "digit AP PIN and click Use AP PIN button.");
1491 void WpaGui::wpsApPinChanged(const QString &text)
1493 wpsApPinButton->setEnabled(text.length() == 8);
1497 void WpaGui::wpsApPin()
1500 size_t reply_len = sizeof(reply);
1502 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1503 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1506 wpsStatusText->setText("Waiting for AP/Enrollee");
1511 void WpaGui::stopWpsRun(bool success)
1514 wpsStatusText->setText(success ? "Connected to the network" :
1517 wpsStatusText->setText("");
1518 wpsPinEdit->setEnabled(false);
1519 wpsInstructions->setText("");
1522 wpsApPinEdit->setEnabled(false);
1523 wpsApPinButton->setEnabled(false);
1527 #ifdef CONFIG_NATIVE_WINDOWS
1530 #define WPASVC_NAME TEXT("wpasvc")
1533 class ErrorMsg : public QMessageBox {
1535 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1536 void showMsg(QString msg);
1541 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1542 QMessageBox(parent), err(last_err)
1544 setWindowTitle("wpa_gui error");
1545 setIcon(QMessageBox::Warning);
1548 void ErrorMsg::showMsg(QString msg)
1553 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1554 FORMAT_MESSAGE_FROM_SYSTEM,
1555 NULL, err, 0, (LPTSTR) (void *) &buf,
1557 QString msg = QString::fromWCharArray(buf);
1558 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1561 setInformativeText(QString("[%1]").arg(err));
1568 void WpaGui::startService()
1572 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1574 ErrorMsg(this).showMsg("OpenSCManager failed");
1578 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1580 ErrorMsg(this).showMsg("OpenService failed");
1581 CloseServiceHandle(scm);
1585 if (!StartService(svc, 0, NULL)) {
1586 ErrorMsg(this).showMsg("Failed to start wpa_supplicant "
1590 CloseServiceHandle(svc);
1591 CloseServiceHandle(scm);
1595 void WpaGui::stopService()
1598 SERVICE_STATUS status;
1600 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1602 ErrorMsg(this).showMsg("OpenSCManager failed");
1606 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1608 ErrorMsg(this).showMsg("OpenService failed");
1609 CloseServiceHandle(scm);
1613 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1614 ErrorMsg(this).showMsg("Failed to stop wpa_supplicant "
1618 CloseServiceHandle(svc);
1619 CloseServiceHandle(scm);
1623 bool WpaGui::serviceRunning()
1626 SERVICE_STATUS status;
1627 bool running = false;
1629 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1631 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1635 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1637 printf("OpenService failed: %d\n\n", (int) GetLastError());
1638 CloseServiceHandle(scm);
1642 if (QueryServiceStatus(svc, &status)) {
1643 if (status.dwCurrentState != SERVICE_STOPPED)
1647 CloseServiceHandle(svc);
1648 CloseServiceHandle(scm);
1653 #endif /* CONFIG_NATIVE_WINDOWS */
1656 void WpaGui::addInterface()
1662 add_iface = new AddInterface(this, this);