2 * wpa_gui - WpaGui class
3 * Copyright (c) 2005-2010, 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 "common/wpa_ctrl.h"
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(tr("Stop Service"));
54 fileMenu
->insertAction(actionWPS
, fileStopServiceAction
);
56 fileStartServiceAction
= new QAction(this);
57 fileStartServiceAction
->setObjectName("Start Service");
58 fileStartServiceAction
->setIconText(tr("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(tr("Add Interface"));
68 fileMenu
->insertAction(fileStartServiceAction
, addInterfaceAction
);
70 connect(addInterfaceAction
, SIGNAL(triggered()), this,
71 SLOT(addInterface()));
72 #endif /* CONFIG_NATIVE_WINDOWS */
77 * Disable WPS tab by default; it will be enabled if wpa_supplicant is
78 * built with WPS support.
80 wpsTab
->setEnabled(false);
81 wpaguiTab
->setTabEnabled(wpaguiTab
->indexOf(wpsTab
), false);
83 connect(fileEventHistoryAction
, SIGNAL(triggered()), this,
84 SLOT(eventHistory()));
85 connect(fileSaveConfigAction
, SIGNAL(triggered()), this,
87 connect(actionWPS
, SIGNAL(triggered()), this, SLOT(wpsDialog()));
88 connect(actionPeers
, SIGNAL(triggered()), this, SLOT(peersDialog()));
89 connect(fileExitAction
, SIGNAL(triggered()), qApp
, SLOT(quit()));
90 connect(networkAddAction
, SIGNAL(triggered()), this,
92 connect(networkEditAction
, SIGNAL(triggered()), this,
93 SLOT(editSelectedNetwork()));
94 connect(networkRemoveAction
, SIGNAL(triggered()), this,
95 SLOT(removeSelectedNetwork()));
96 connect(networkEnableAllAction
, SIGNAL(triggered()), this,
97 SLOT(enableAllNetworks()));
98 connect(networkDisableAllAction
, SIGNAL(triggered()), this,
99 SLOT(disableAllNetworks()));
100 connect(networkRemoveAllAction
, SIGNAL(triggered()), this,
101 SLOT(removeAllNetworks()));
102 connect(helpIndexAction
, SIGNAL(triggered()), this, SLOT(helpIndex()));
103 connect(helpContentsAction
, SIGNAL(triggered()), this,
104 SLOT(helpContents()));
105 connect(helpAboutAction
, SIGNAL(triggered()), this, SLOT(helpAbout()));
106 connect(disconnectButton
, SIGNAL(clicked()), this, SLOT(disconnect()));
107 connect(scanButton
, SIGNAL(clicked()), this, SLOT(scan()));
108 connect(connectButton
, SIGNAL(clicked()), this, SLOT(connectB()));
109 connect(adapterSelect
, SIGNAL(activated(const QString
&)), this,
110 SLOT(selectAdapter(const QString
&)));
111 connect(networkSelect
, SIGNAL(activated(const QString
&)), this,
112 SLOT(selectNetwork(const QString
&)));
113 connect(addNetworkButton
, SIGNAL(clicked()), this, SLOT(addNetwork()));
114 connect(editNetworkButton
, SIGNAL(clicked()), this,
115 SLOT(editListedNetwork()));
116 connect(removeNetworkButton
, SIGNAL(clicked()), this,
117 SLOT(removeListedNetwork()));
118 connect(networkList
, SIGNAL(itemSelectionChanged()), this,
119 SLOT(updateNetworkDisabledStatus()));
120 connect(enableRadioButton
, SIGNAL(toggled(bool)), this,
121 SLOT(enableListedNetwork(bool)));
122 connect(disableRadioButton
, SIGNAL(toggled(bool)), this,
123 SLOT(disableListedNetwork(bool)));
124 connect(scanNetworkButton
, SIGNAL(clicked()), this, SLOT(scan()));
125 connect(networkList
, SIGNAL(itemDoubleClicked(QListWidgetItem
*)),
126 this, SLOT(editListedNetwork()));
127 connect(wpaguiTab
, SIGNAL(currentChanged(int)), this,
128 SLOT(tabChanged(int)));
129 connect(wpsPbcButton
, SIGNAL(clicked()), this, SLOT(wpsPbc()));
130 connect(wpsPinButton
, SIGNAL(clicked()), this, SLOT(wpsGeneratePin()));
131 connect(wpsApPinEdit
, SIGNAL(textChanged(const QString
&)), this,
132 SLOT(wpsApPinChanged(const QString
&)));
133 connect(wpsApPinButton
, SIGNAL(clicked()), this, SLOT(wpsApPin()));
146 ctrl_iface_dir
= strdup("/var/run/wpa_supplicant");
150 #ifndef QT_NO_SESSIONMANAGER
151 if (app
->isSessionRestored()) {
152 QSettings
settings("wpa_supplicant", "wpa_gui");
153 settings
.beginGroup("state");
154 if (app
->sessionId().compare(settings
.value("session_id").
156 startInTray
= settings
.value("in_tray").toBool();
161 if (QSystemTrayIcon::isSystemTrayAvailable())
162 createTrayIcon(startInTray
);
166 connectedToService
= false;
167 textStatus
->setText(tr("connecting to wpa_supplicant"));
168 timer
= new QTimer(this);
169 connect(timer
, SIGNAL(timeout()), SLOT(ping()));
170 timer
->setSingleShot(FALSE
);
173 if (openCtrlConnection(ctrl_iface
) < 0) {
174 printf("Failed to open control connection to "
175 "wpa_supplicant.\n");
179 networkMayHaveChanged
= true;
189 wpa_ctrl_detach(monitor_conn
);
190 wpa_ctrl_close(monitor_conn
);
194 wpa_ctrl_close(ctrl_conn
);
231 free(ctrl_iface_dir
);
232 ctrl_iface_dir
= NULL
;
236 void WpaGui::languageChange()
242 void WpaGui::parse_argv()
246 c
= getopt(qApp
->argc(), qApp
->argv(), "i:p:t");
252 ctrl_iface
= strdup(optarg
);
255 free(ctrl_iface_dir
);
256 ctrl_iface_dir
= strdup(optarg
);
266 int WpaGui::openCtrlConnection(const char *ifname
)
270 char buf
[2048], *pos
, *pos2
;
274 if (ifname
!= ctrl_iface
) {
276 ctrl_iface
= strdup(ifname
);
279 #ifdef CONFIG_CTRL_IFACE_UDP
281 ctrl_iface
= strdup("udp");
282 #endif /* CONFIG_CTRL_IFACE_UDP */
283 #ifdef CONFIG_CTRL_IFACE_UNIX
285 DIR *dir
= opendir(ctrl_iface_dir
);
289 while ((dent
= readdir(dir
))) {
290 #ifdef _DIRENT_HAVE_D_TYPE
291 /* Skip the file if it is not a socket.
292 * Also accept DT_UNKNOWN (0) in case
293 * the C library or underlying file
294 * system does not support d_type. */
295 if (dent
->d_type
!= DT_SOCK
&&
296 dent
->d_type
!= DT_UNKNOWN
)
298 #endif /* _DIRENT_HAVE_D_TYPE */
300 if (strcmp(dent
->d_name
, ".") == 0 ||
301 strcmp(dent
->d_name
, "..") == 0)
303 printf("Selected interface '%s'\n",
305 ctrl_iface
= strdup(dent
->d_name
);
310 #endif /* CONFIG_CTRL_IFACE_UNIX */
311 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
312 struct wpa_ctrl
*ctrl
;
318 ctrl
= wpa_ctrl_open(NULL
);
320 len
= sizeof(buf
) - 1;
321 ret
= wpa_ctrl_request(ctrl
, "INTERFACES", 10, buf
,
324 connectedToService
= true;
326 pos
= strchr(buf
, '\n');
329 ctrl_iface
= strdup(buf
);
331 wpa_ctrl_close(ctrl
);
333 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
336 if (ctrl_iface
== NULL
) {
337 #ifdef CONFIG_NATIVE_WINDOWS
338 static bool first
= true;
339 if (first
&& !serviceRunning()) {
341 if (QMessageBox::warning(
343 tr("wpa_supplicant service is not "
345 "Do you want to start it?"),
346 QMessageBox::Yes
| QMessageBox::No
) ==
350 #endif /* CONFIG_NATIVE_WINDOWS */
354 #ifdef CONFIG_CTRL_IFACE_UNIX
355 flen
= strlen(ctrl_iface_dir
) + strlen(ctrl_iface
) + 2;
356 cfile
= (char *) malloc(flen
);
359 snprintf(cfile
, flen
, "%s/%s", ctrl_iface_dir
, ctrl_iface
);
360 #else /* CONFIG_CTRL_IFACE_UNIX */
361 flen
= strlen(ctrl_iface
) + 1;
362 cfile
= (char *) malloc(flen
);
365 snprintf(cfile
, flen
, "%s", ctrl_iface
);
366 #endif /* CONFIG_CTRL_IFACE_UNIX */
369 wpa_ctrl_close(ctrl_conn
);
376 wpa_ctrl_detach(monitor_conn
);
377 wpa_ctrl_close(monitor_conn
);
381 printf("Trying to connect to '%s'\n", cfile
);
382 ctrl_conn
= wpa_ctrl_open(cfile
);
383 if (ctrl_conn
== NULL
) {
387 monitor_conn
= wpa_ctrl_open(cfile
);
389 if (monitor_conn
== NULL
) {
390 wpa_ctrl_close(ctrl_conn
);
393 if (wpa_ctrl_attach(monitor_conn
)) {
394 printf("Failed to attach to wpa_supplicant\n");
395 wpa_ctrl_close(monitor_conn
);
397 wpa_ctrl_close(ctrl_conn
);
402 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
403 msgNotifier
= new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn
),
404 QSocketNotifier::Read
, this);
405 connect(msgNotifier
, SIGNAL(activated(int)), SLOT(receiveMsgs()));
408 adapterSelect
->clear();
409 adapterSelect
->addItem(ctrl_iface
);
410 adapterSelect
->setCurrentIndex(0);
412 len
= sizeof(buf
) - 1;
413 if (wpa_ctrl_request(ctrl_conn
, "INTERFACES", 10, buf
, &len
, NULL
) >=
418 pos2
= strchr(pos
, '\n');
421 if (strcmp(pos
, ctrl_iface
) != 0)
422 adapterSelect
->addItem(pos
);
430 len
= sizeof(buf
) - 1;
431 if (wpa_ctrl_request(ctrl_conn
, "GET_CAPABILITY eap", 18, buf
, &len
,
436 QStringList types
= res
.split(QChar(' '));
437 bool wps
= types
.contains("WSC");
438 actionWPS
->setEnabled(wps
);
439 wpsTab
->setEnabled(wps
);
440 wpaguiTab
->setTabEnabled(wpaguiTab
->indexOf(wpsTab
), wps
);
447 int WpaGui::ctrlRequest(const char *cmd
, char *buf
, size_t *buflen
)
451 if (ctrl_conn
== NULL
)
453 ret
= wpa_ctrl_request(ctrl_conn
, cmd
, strlen(cmd
), buf
, buflen
, NULL
);
455 printf("'%s' command timed out.\n", cmd
);
457 printf("'%s' command failed.\n", cmd
);
463 QString
WpaGui::wpaStateTranslate(char *state
)
465 if (!strcmp(state
, "DISCONNECTED"))
466 return tr("Disconnected");
467 else if (!strcmp(state
, "INACTIVE"))
468 return tr("Inactive");
469 else if (!strcmp(state
, "SCANNING"))
470 return tr("Scanning");
471 else if (!strcmp(state
, "AUTHENTICATING"))
472 return tr("Authenticating");
473 else if (!strcmp(state
, "ASSOCIATING"))
474 return tr("Associating");
475 else if (!strcmp(state
, "ASSOCIATED"))
476 return tr("Associated");
477 else if (!strcmp(state
, "4WAY_HANDSHAKE"))
478 return tr("4-Way Handshake");
479 else if (!strcmp(state
, "GROUP_HANDSHAKE"))
480 return tr("Group Handshake");
481 else if (!strcmp(state
, "COMPLETED"))
482 return tr("Completed");
484 return tr("Unknown");
488 void WpaGui::updateStatus()
490 char buf
[2048], *start
, *end
, *pos
;
493 pingsToStatusUpdate
= 10;
495 len
= sizeof(buf
) - 1;
496 if (ctrl_conn
== NULL
|| ctrlRequest("STATUS", buf
, &len
) < 0) {
497 textStatus
->setText(tr("Could not get status from "
499 textAuthentication
->clear();
500 textEncryption
->clear();
503 textIpAddress
->clear();
505 #ifdef CONFIG_NATIVE_WINDOWS
506 static bool first
= true;
507 if (first
&& connectedToService
&&
508 (ctrl_iface
== NULL
|| *ctrl_iface
== '\0')) {
510 if (QMessageBox::information(
512 tr("No network interfaces in use.\n"
513 "Would you like to add one?"),
514 QMessageBox::Yes
| QMessageBox::No
) ==
518 #endif /* CONFIG_NATIVE_WINDOWS */
524 bool auth_updated
= false, ssid_updated
= false;
525 bool bssid_updated
= false, ipaddr_updated
= false;
526 bool status_updated
= false;
527 char *pairwise_cipher
= NULL
, *group_cipher
= NULL
;
533 end
= strchr(start
, '\n');
537 while (end
[0] && end
[1])
542 pos
= strchr(start
, '=');
545 if (strcmp(start
, "bssid") == 0) {
546 bssid_updated
= true;
547 textBssid
->setText(pos
);
548 } else if (strcmp(start
, "ssid") == 0) {
550 textSsid
->setText(pos
);
551 } else if (strcmp(start
, "ip_address") == 0) {
552 ipaddr_updated
= true;
553 textIpAddress
->setText(pos
);
554 } else if (strcmp(start
, "wpa_state") == 0) {
555 status_updated
= true;
556 textStatus
->setText(wpaStateTranslate(pos
));
557 } else if (strcmp(start
, "key_mgmt") == 0) {
559 textAuthentication
->setText(pos
);
560 /* TODO: could add EAP status to this */
561 } else if (strcmp(start
, "pairwise_cipher") == 0) {
562 pairwise_cipher
= pos
;
563 } else if (strcmp(start
, "group_cipher") == 0) {
565 } else if (strcmp(start
, "mode") == 0) {
574 if (status_updated
&& mode
)
575 textStatus
->setText(textStatus
->text() + " (" + mode
+ ")");
577 if (pairwise_cipher
|| group_cipher
) {
579 if (pairwise_cipher
&& group_cipher
&&
580 strcmp(pairwise_cipher
, group_cipher
) != 0) {
581 encr
.append(pairwise_cipher
);
583 encr
.append(group_cipher
);
584 } else if (pairwise_cipher
) {
585 encr
.append(pairwise_cipher
);
587 encr
.append(group_cipher
);
588 encr
.append(" [group key only]");
590 textEncryption
->setText(encr
);
592 textEncryption
->clear();
597 textAuthentication
->clear();
603 textIpAddress
->clear();
607 void WpaGui::updateNetworks()
609 char buf
[2048], *start
, *end
, *id
, *ssid
, *bssid
, *flags
;
611 int first_active
= -1;
612 int was_selected
= -1;
613 bool current
= false;
615 if (!networkMayHaveChanged
)
618 if (networkList
->currentRow() >= 0)
619 was_selected
= networkList
->currentRow();
621 networkSelect
->clear();
622 networkList
->clear();
624 if (ctrl_conn
== NULL
)
627 len
= sizeof(buf
) - 1;
628 if (ctrlRequest("LIST_NETWORKS", buf
, &len
) < 0)
632 start
= strchr(buf
, '\n');
639 end
= strchr(start
, '\n');
643 while (end
[0] && end
[1])
649 ssid
= strchr(id
, '\t');
653 bssid
= strchr(ssid
, '\t');
657 flags
= strchr(bssid
, '\t');
663 network
.append(": ");
664 network
.append(ssid
);
665 networkSelect
->addItem(network
);
666 networkList
->addItem(network
);
668 if (strstr(flags
, "[CURRENT]")) {
669 networkSelect
->setCurrentIndex(networkSelect
->count() -
672 } else if (first_active
< 0 &&
673 strstr(flags
, "[DISABLED]") == NULL
)
674 first_active
= networkSelect
->count() - 1;
681 if (networkSelect
->count() > 1)
682 networkSelect
->addItem(tr("Select any network"));
684 if (!current
&& first_active
>= 0)
685 networkSelect
->setCurrentIndex(first_active
);
687 if (was_selected
>= 0 && networkList
->count() > 0) {
688 if (was_selected
< networkList
->count())
689 networkList
->setCurrentRow(was_selected
);
691 networkList
->setCurrentRow(networkList
->count() - 1);
694 networkList
->setCurrentRow(networkSelect
->currentIndex());
696 networkMayHaveChanged
= false;
700 void WpaGui::helpIndex()
702 printf("helpIndex\n");
706 void WpaGui::helpContents()
708 printf("helpContents\n");
712 void WpaGui::helpAbout()
714 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
715 "Copyright (c) 2003-2010,\n"
716 "Jouni Malinen <j@w1.fi>\n"
717 "and contributors.\n"
719 "This program is free software. You can\n"
720 "distribute it and/or modify it under the terms "
722 "the GNU General Public License version 2.\n"
724 "Alternatively, this software may be distributed\n"
725 "under the terms of the BSD license.\n"
727 "This product includes software developed\n"
728 "by the OpenSSL Project for use in the\n"
729 "OpenSSL Toolkit (http://www.openssl.org/)\n");
733 void WpaGui::disconnect()
736 size_t reply_len
= sizeof(reply
);
737 ctrlRequest("DISCONNECT", reply
, &reply_len
);
749 scanres
= new ScanResults();
752 scanres
->setWpaGui(this);
758 void WpaGui::eventHistory()
765 eh
= new EventHistory();
779 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
781 * QSocketNotifier cannot be used with Windows named pipes, so use a
782 * timer to check for received messages for now. This could be
783 * optimized be doing something specific to named pipes or Windows
784 * events, but it is not clear what would be the best way of doing that
788 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
790 if (scanres
&& !scanres
->isVisible()) {
795 if (eh
&& !eh
->isVisible()) {
800 if (udr
&& !udr
->isVisible()) {
805 len
= sizeof(buf
) - 1;
806 if (ctrlRequest("PING", buf
, &len
) < 0) {
807 printf("PING failed - trying to reconnect\n");
808 if (openCtrlConnection(ctrl_iface
) >= 0) {
809 printf("Reconnected successfully\n");
810 pingsToStatusUpdate
= 0;
814 pingsToStatusUpdate
--;
815 if (pingsToStatusUpdate
<= 0) {
820 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
821 /* Use less frequent pings and status updates when the main window is
822 * hidden (running in taskbar). */
823 int interval
= isHidden() ? 5000 : 1000;
824 if (timer
->interval() != interval
)
825 timer
->setInterval(interval
);
826 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
830 static int str_match(const char *a
, const char *b
)
832 return strncmp(a
, b
, strlen(b
)) == 0;
836 void WpaGui::processMsg(char *msg
)
838 char *pos
= msg
, *pos2
;
844 priority
= atoi(pos
);
845 pos
= strchr(pos
, '>');
852 WpaMsg
wm(pos
, priority
);
856 peers
->event_notify(wm
);
858 while (msgs
.count() > 100)
861 /* Update last message with truncated version of the event */
862 if (strncmp(pos
, "CTRL-", 5) == 0) {
863 pos2
= strchr(pos
, str_match(pos
, WPA_CTRL_REQ
) ? ':' : ' ');
870 QString lastmsg
= pos2
;
871 lastmsg
.truncate(40);
872 textLastMessage
->setText(lastmsg
);
874 pingsToStatusUpdate
= 0;
875 networkMayHaveChanged
= true;
877 if (str_match(pos
, WPA_CTRL_REQ
))
878 processCtrlReq(pos
+ strlen(WPA_CTRL_REQ
));
879 else if (str_match(pos
, WPA_EVENT_SCAN_RESULTS
) && scanres
)
880 scanres
->updateResults();
881 else if (str_match(pos
, WPA_EVENT_DISCONNECTED
))
882 showTrayMessage(QSystemTrayIcon::Information
, 3,
883 tr("Disconnected from network."));
884 else if (str_match(pos
, WPA_EVENT_CONNECTED
)) {
885 showTrayMessage(QSystemTrayIcon::Information
, 3,
886 tr("Connection to network established."));
887 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
889 } else if (str_match(pos
, WPS_EVENT_AP_AVAILABLE_PBC
)) {
890 wpsStatusText
->setText(tr("WPS AP in active PBC mode found"));
891 if (textStatus
->text() == "INACTIVE" ||
892 textStatus
->text() == "DISCONNECTED")
893 wpaguiTab
->setCurrentWidget(wpsTab
);
894 wpsInstructions
->setText(tr("Press the PBC button on the "
895 "screen to start registration"));
896 } else if (str_match(pos
, WPS_EVENT_AP_AVAILABLE_PIN
)) {
897 wpsStatusText
->setText(tr("WPS AP with recently selected "
899 if (textStatus
->text() == "INACTIVE" ||
900 textStatus
->text() == "DISCONNECTED")
901 wpaguiTab
->setCurrentWidget(wpsTab
);
902 } else if (str_match(pos
, WPS_EVENT_AP_AVAILABLE
)) {
903 wpsStatusText
->setText(tr("WPS AP detected"));
904 } else if (str_match(pos
, WPS_EVENT_OVERLAP
)) {
905 wpsStatusText
->setText(tr("PBC mode overlap detected"));
906 wpsInstructions
->setText(tr("More than one AP is currently in "
907 "active WPS PBC mode. Wait couple "
908 "of minutes and try again"));
909 wpaguiTab
->setCurrentWidget(wpsTab
);
910 } else if (str_match(pos
, WPS_EVENT_CRED_RECEIVED
)) {
911 wpsStatusText
->setText(tr("Network configuration received"));
912 wpaguiTab
->setCurrentWidget(wpsTab
);
913 } else if (str_match(pos
, WPA_EVENT_EAP_METHOD
)) {
914 if (strstr(pos
, "(WSC)"))
915 wpsStatusText
->setText(tr("Registration started"));
916 } else if (str_match(pos
, WPS_EVENT_M2D
)) {
917 wpsStatusText
->setText(tr("Registrar does not yet know PIN"));
918 } else if (str_match(pos
, WPS_EVENT_FAIL
)) {
919 wpsStatusText
->setText(tr("Registration failed"));
920 } else if (str_match(pos
, WPS_EVENT_SUCCESS
)) {
921 wpsStatusText
->setText(tr("Registration succeeded"));
926 void WpaGui::processCtrlReq(const char *req
)
932 udr
= new UserDataRequest();
935 if (udr
->setParams(this, req
) < 0) {
945 void WpaGui::receiveMsgs()
950 while (monitor_conn
&& wpa_ctrl_pending(monitor_conn
) > 0) {
951 len
= sizeof(buf
) - 1;
952 if (wpa_ctrl_recv(monitor_conn
, buf
, &len
) == 0) {
960 void WpaGui::connectB()
963 size_t reply_len
= sizeof(reply
);
964 ctrlRequest("REASSOCIATE", reply
, &reply_len
);
968 void WpaGui::selectNetwork( const QString
&sel
)
972 size_t reply_len
= sizeof(reply
);
974 if (cmd
.contains(QRegExp("^\\d+:")))
975 cmd
.truncate(cmd
.indexOf(':'));
978 cmd
.prepend("SELECT_NETWORK ");
979 ctrlRequest(cmd
.toAscii().constData(), reply
, &reply_len
);
985 void WpaGui::enableNetwork(const QString
&sel
)
989 size_t reply_len
= sizeof(reply
);
991 if (cmd
.contains(QRegExp("^\\d+:")))
992 cmd
.truncate(cmd
.indexOf(':'));
993 else if (!cmd
.startsWith("all")) {
994 printf("Invalid editNetwork '%s'\n",
995 cmd
.toAscii().constData());
998 cmd
.prepend("ENABLE_NETWORK ");
999 ctrlRequest(cmd
.toAscii().constData(), reply
, &reply_len
);
1004 void WpaGui::disableNetwork(const QString
&sel
)
1008 size_t reply_len
= sizeof(reply
);
1010 if (cmd
.contains(QRegExp("^\\d+:")))
1011 cmd
.truncate(cmd
.indexOf(':'));
1012 else if (!cmd
.startsWith("all")) {
1013 printf("Invalid editNetwork '%s'\n",
1014 cmd
.toAscii().constData());
1017 cmd
.prepend("DISABLE_NETWORK ");
1018 ctrlRequest(cmd
.toAscii().constData(), reply
, &reply_len
);
1023 void WpaGui::editNetwork(const QString
&sel
)
1028 if (cmd
.contains(QRegExp("^\\d+:"))) {
1029 cmd
.truncate(cmd
.indexOf(':'));
1033 NetworkConfig
*nc
= new NetworkConfig();
1036 nc
->setWpaGui(this);
1039 nc
->paramsFromConfig(id
);
1048 void WpaGui::editSelectedNetwork()
1050 if (networkSelect
->count() < 1) {
1051 QMessageBox::information(
1052 this, tr("No Networks"),
1053 tr("There are no networks to edit.\n"));
1056 QString
sel(networkSelect
->currentText());
1061 void WpaGui::editListedNetwork()
1063 if (networkList
->currentRow() < 0) {
1064 QMessageBox::information(this, tr("Select A Network"),
1065 tr("Select a network from the list to"
1069 QString
sel(networkList
->currentItem()->text());
1074 void WpaGui::triggerUpdate()
1077 networkMayHaveChanged
= true;
1082 void WpaGui::addNetwork()
1084 NetworkConfig
*nc
= new NetworkConfig();
1087 nc
->setWpaGui(this);
1094 void WpaGui::removeNetwork(const QString
&sel
)
1098 size_t reply_len
= sizeof(reply
);
1100 if (cmd
.contains(QRegExp("^\\d+:")))
1101 cmd
.truncate(cmd
.indexOf(':'));
1102 else if (!cmd
.startsWith("all")) {
1103 printf("Invalid editNetwork '%s'\n",
1104 cmd
.toAscii().constData());
1107 cmd
.prepend("REMOVE_NETWORK ");
1108 ctrlRequest(cmd
.toAscii().constData(), reply
, &reply_len
);
1113 void WpaGui::removeSelectedNetwork()
1115 if (networkSelect
->count() < 1) {
1116 QMessageBox::information(this, tr("No Networks"),
1117 tr("There are no networks to remove."
1121 QString
sel(networkSelect
->currentText());
1126 void WpaGui::removeListedNetwork()
1128 if (networkList
->currentRow() < 0) {
1129 QMessageBox::information(this, tr("Select A Network"),
1130 tr("Select a network from the list "
1131 "to remove it.\n"));
1134 QString
sel(networkList
->currentItem()->text());
1139 void WpaGui::enableAllNetworks()
1146 void WpaGui::disableAllNetworks()
1149 disableNetwork(sel
);
1153 void WpaGui::removeAllNetworks()
1160 int WpaGui::getNetworkDisabled(const QString
&sel
)
1164 size_t reply_len
= sizeof(reply
) - 1;
1165 int pos
= cmd
.indexOf(':');
1167 printf("Invalid getNetworkDisabled '%s'\n",
1168 cmd
.toAscii().constData());
1172 cmd
.prepend("GET_NETWORK ");
1173 cmd
.append(" disabled");
1175 if (ctrlRequest(cmd
.toAscii().constData(), reply
, &reply_len
) >= 0
1176 && reply_len
>= 1) {
1177 reply
[reply_len
] = '\0';
1178 if (!str_match(reply
, "FAIL"))
1186 void WpaGui::updateNetworkDisabledStatus()
1188 if (networkList
->currentRow() < 0)
1191 QString
sel(networkList
->currentItem()->text());
1193 switch (getNetworkDisabled(sel
)) {
1195 if (!enableRadioButton
->isChecked())
1196 enableRadioButton
->setChecked(true);
1199 if (!disableRadioButton
->isChecked())
1200 disableRadioButton
->setChecked(true);
1206 void WpaGui::enableListedNetwork(bool enabled
)
1208 if (networkList
->currentRow() < 0 || !enabled
)
1211 QString
sel(networkList
->currentItem()->text());
1213 if (getNetworkDisabled(sel
) == 1)
1218 void WpaGui::disableListedNetwork(bool disabled
)
1220 if (networkList
->currentRow() < 0 || !disabled
)
1223 QString
sel(networkList
->currentItem()->text());
1225 if (getNetworkDisabled(sel
) == 0)
1226 disableNetwork(sel
);
1230 void WpaGui::saveConfig()
1235 len
= sizeof(buf
) - 1;
1236 ctrlRequest("SAVE_CONFIG", buf
, &len
);
1240 if (str_match(buf
, "FAIL"))
1241 QMessageBox::warning(
1242 this, tr("Failed to save configuration"),
1243 tr("The configuration could not be saved.\n"
1245 "The update_config=1 configuration option\n"
1246 "must be used for configuration saving to\n"
1247 "be permitted.\n"));
1249 QMessageBox::information(
1250 this, tr("Saved configuration"),
1251 tr("The current configuration was saved."
1256 void WpaGui::selectAdapter( const QString
& sel
)
1258 if (openCtrlConnection(sel
.toAscii().constData()) < 0)
1259 printf("Failed to open control connection to "
1260 "wpa_supplicant.\n");
1266 void WpaGui::createTrayIcon(bool trayOnly
)
1268 QApplication::setQuitOnLastWindowClosed(false);
1270 tray_icon
= new QSystemTrayIcon(this);
1271 tray_icon
->setToolTip(qAppName() + tr(" - wpa_supplicant user interface"));
1272 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1273 tray_icon
->setIcon(QIcon(":/icons/wpa_gui.svg"));
1275 tray_icon
->setIcon(QIcon(":/icons/wpa_gui.png"));
1278 SIGNAL(activated(QSystemTrayIcon::ActivationReason
)),
1279 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason
)));
1281 ackTrayIcon
= false;
1283 tray_menu
= new QMenu(this);
1285 disconnectAction
= new QAction(tr("&Disconnect"), this);
1286 reconnectAction
= new QAction(tr("Re&connect"), this);
1287 connect(disconnectAction
, SIGNAL(triggered()), this,
1288 SLOT(disconnect()));
1289 connect(reconnectAction
, SIGNAL(triggered()), this,
1291 tray_menu
->addAction(disconnectAction
);
1292 tray_menu
->addAction(reconnectAction
);
1293 tray_menu
->addSeparator();
1295 eventAction
= new QAction(tr("&Event History"), this);
1296 scanAction
= new QAction(tr("Scan &Results"), this);
1297 statAction
= new QAction(tr("S&tatus"), this);
1298 connect(eventAction
, SIGNAL(triggered()), this, SLOT(eventHistory()));
1299 connect(scanAction
, SIGNAL(triggered()), this, SLOT(scan()));
1300 connect(statAction
, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1301 tray_menu
->addAction(eventAction
);
1302 tray_menu
->addAction(scanAction
);
1303 tray_menu
->addAction(statAction
);
1304 tray_menu
->addSeparator();
1306 showAction
= new QAction(tr("&Show Window"), this);
1307 hideAction
= new QAction(tr("&Hide Window"), this);
1308 quitAction
= new QAction(tr("&Quit"), this);
1309 connect(showAction
, SIGNAL(triggered()), this, SLOT(show()));
1310 connect(hideAction
, SIGNAL(triggered()), this, SLOT(hide()));
1311 connect(quitAction
, SIGNAL(triggered()), qApp
, SLOT(quit()));
1312 tray_menu
->addAction(showAction
);
1313 tray_menu
->addAction(hideAction
);
1314 tray_menu
->addSeparator();
1315 tray_menu
->addAction(quitAction
);
1317 tray_icon
->setContextMenu(tray_menu
);
1327 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type
, int sec
,
1328 const QString
& msg
)
1330 if (!QSystemTrayIcon::supportsMessages())
1333 if (isVisible() || !tray_icon
|| !tray_icon
->isVisible())
1336 tray_icon
->showMessage(qAppName(), msg
, type
, sec
* 1000);
1340 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how
)
1343 /* use close() here instead of hide() and allow the
1344 * custom closeEvent handler take care of children */
1345 case QSystemTrayIcon::Trigger
:
1355 case QSystemTrayIcon::MiddleClick
:
1364 void WpaGui::showTrayStatus()
1369 len
= sizeof(buf
) - 1;
1370 if (ctrlRequest("STATUS", buf
, &len
) < 0)
1374 QString msg
, status(buf
);
1376 QStringList lines
= status
.split(QRegExp("\\n"));
1377 for (QStringList::Iterator it
= lines
.begin();
1378 it
!= lines
.end(); it
++) {
1379 int pos
= (*it
).indexOf('=') + 1;
1383 if ((*it
).startsWith("bssid="))
1384 msg
.append("BSSID:\t" + (*it
).mid(pos
) + "\n");
1385 else if ((*it
).startsWith("ssid="))
1386 msg
.append("SSID: \t" + (*it
).mid(pos
) + "\n");
1387 else if ((*it
).startsWith("pairwise_cipher="))
1388 msg
.append("PAIR: \t" + (*it
).mid(pos
) + "\n");
1389 else if ((*it
).startsWith("group_cipher="))
1390 msg
.append("GROUP:\t" + (*it
).mid(pos
) + "\n");
1391 else if ((*it
).startsWith("key_mgmt="))
1392 msg
.append("AUTH: \t" + (*it
).mid(pos
) + "\n");
1393 else if ((*it
).startsWith("wpa_state="))
1394 msg
.append("STATE:\t" + (*it
).mid(pos
) + "\n");
1395 else if ((*it
).startsWith("ip_address="))
1396 msg
.append("IP: \t" + (*it
).mid(pos
) + "\n");
1397 else if ((*it
).startsWith("Supplicant PAE state="))
1398 msg
.append("PAE: \t" + (*it
).mid(pos
) + "\n");
1399 else if ((*it
).startsWith("EAP state="))
1400 msg
.append("EAP: \t" + (*it
).mid(pos
) + "\n");
1404 showTrayMessage(QSystemTrayIcon::Information
, 10, msg
);
1408 void WpaGui::closeEvent(QCloseEvent
*event
)
1434 if (tray_icon
&& !ackTrayIcon
) {
1435 /* give user a visual hint that the tray icon exists */
1436 if (QSystemTrayIcon::supportsMessages()) {
1438 showTrayMessage(QSystemTrayIcon::Information
, 3,
1440 tr(" will keep running in "
1441 "the system tray."));
1443 QMessageBox::information(this, qAppName() +
1445 tr("The program will keep "
1446 "running in the system "
1456 void WpaGui::wpsDialog()
1458 wpaguiTab
->setCurrentWidget(wpsTab
);
1462 void WpaGui::peersDialog()
1469 peers
= new Peers();
1472 peers
->setWpaGui(this);
1478 void WpaGui::tabChanged(int index
)
1486 wpsApPinEdit
->setEnabled(!bssFromScan
.isEmpty());
1487 if (bssFromScan
.isEmpty())
1488 wpsApPinButton
->setEnabled(false);
1492 void WpaGui::wpsPbc()
1495 size_t reply_len
= sizeof(reply
);
1497 if (ctrlRequest("WPS_PBC", reply
, &reply_len
) < 0)
1500 wpsPinEdit
->setEnabled(false);
1501 if (wpsStatusText
->text().compare(tr("WPS AP in active PBC mode found"))) {
1502 wpsInstructions
->setText(tr("Press the push button on the AP to "
1503 "start the PBC mode."));
1505 wpsInstructions
->setText(tr("If you have not yet done so, press "
1506 "the push button on the AP to start "
1509 wpsStatusText
->setText(tr("Waiting for Registrar"));
1514 void WpaGui::wpsGeneratePin()
1517 size_t reply_len
= sizeof(reply
) - 1;
1519 if (ctrlRequest("WPS_PIN any", reply
, &reply_len
) < 0)
1522 reply
[reply_len
] = '\0';
1524 wpsPinEdit
->setText(reply
);
1525 wpsPinEdit
->setEnabled(true);
1526 wpsInstructions
->setText(tr("Enter the generated PIN into the Registrar "
1527 "(either the internal one in the AP or an "
1529 wpsStatusText
->setText(tr("Waiting for Registrar"));
1534 void WpaGui::setBssFromScan(const QString
&bssid
)
1536 bssFromScan
= bssid
;
1537 wpsApPinEdit
->setEnabled(!bssFromScan
.isEmpty());
1538 wpsApPinButton
->setEnabled(wpsApPinEdit
->text().length() == 8);
1539 wpsStatusText
->setText(tr("WPS AP selected from scan results"));
1540 wpsInstructions
->setText(tr("If you want to use an AP device PIN, e.g., "
1541 "from a label in the device, enter the eight "
1542 "digit AP PIN and click Use AP PIN button."));
1546 void WpaGui::wpsApPinChanged(const QString
&text
)
1548 wpsApPinButton
->setEnabled(text
.length() == 8);
1552 void WpaGui::wpsApPin()
1555 size_t reply_len
= sizeof(reply
);
1557 QString
cmd("WPS_REG " + bssFromScan
+ " " + wpsApPinEdit
->text());
1558 if (ctrlRequest(cmd
.toAscii().constData(), reply
, &reply_len
) < 0)
1561 wpsStatusText
->setText(tr("Waiting for AP/Enrollee"));
1566 void WpaGui::stopWpsRun(bool success
)
1569 wpsStatusText
->setText(success
? tr("Connected to the network") :
1572 wpsStatusText
->setText("");
1573 wpsPinEdit
->setEnabled(false);
1574 wpsInstructions
->setText("");
1577 wpsApPinEdit
->setEnabled(false);
1578 wpsApPinButton
->setEnabled(false);
1582 #ifdef CONFIG_NATIVE_WINDOWS
1585 #define WPASVC_NAME TEXT("wpasvc")
1588 class ErrorMsg
: public QMessageBox
{
1590 ErrorMsg(QWidget
*parent
, DWORD last_err
= GetLastError());
1591 void showMsg(QString msg
);
1596 ErrorMsg::ErrorMsg(QWidget
*parent
, DWORD last_err
) :
1597 QMessageBox(parent
), err(last_err
)
1599 setWindowTitle(tr("wpa_gui error"));
1600 setIcon(QMessageBox::Warning
);
1603 void ErrorMsg::showMsg(QString msg
)
1608 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
1609 FORMAT_MESSAGE_FROM_SYSTEM
,
1610 NULL
, err
, 0, (LPTSTR
) (void *) &buf
,
1612 QString msg
= QString::fromWCharArray(buf
);
1613 setInformativeText(QString("[%1] %2").arg(err
).arg(msg
));
1616 setInformativeText(QString("[%1]").arg(err
));
1623 void WpaGui::startService()
1627 scm
= OpenSCManager(0, 0, SC_MANAGER_CONNECT
);
1629 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1633 svc
= OpenService(scm
, WPASVC_NAME
, SERVICE_START
);
1635 ErrorMsg(this).showMsg(tr("OpenService failed"));
1636 CloseServiceHandle(scm
);
1640 if (!StartService(svc
, 0, NULL
)) {
1641 ErrorMsg(this).showMsg(tr("Failed to start wpa_supplicant "
1645 CloseServiceHandle(svc
);
1646 CloseServiceHandle(scm
);
1650 void WpaGui::stopService()
1653 SERVICE_STATUS status
;
1655 scm
= OpenSCManager(0, 0, SC_MANAGER_CONNECT
);
1657 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1661 svc
= OpenService(scm
, WPASVC_NAME
, SERVICE_STOP
);
1663 ErrorMsg(this).showMsg(tr("OpenService failed"));
1664 CloseServiceHandle(scm
);
1668 if (!ControlService(svc
, SERVICE_CONTROL_STOP
, &status
)) {
1669 ErrorMsg(this).showMsg(tr("Failed to stop wpa_supplicant "
1673 CloseServiceHandle(svc
);
1674 CloseServiceHandle(scm
);
1678 bool WpaGui::serviceRunning()
1681 SERVICE_STATUS status
;
1682 bool running
= false;
1684 scm
= OpenSCManager(0, 0, SC_MANAGER_CONNECT
);
1686 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1690 svc
= OpenService(scm
, WPASVC_NAME
, SERVICE_QUERY_STATUS
);
1692 printf("OpenService failed: %d\n\n", (int) GetLastError());
1693 CloseServiceHandle(scm
);
1697 if (QueryServiceStatus(svc
, &status
)) {
1698 if (status
.dwCurrentState
!= SERVICE_STOPPED
)
1702 CloseServiceHandle(svc
);
1703 CloseServiceHandle(scm
);
1708 #endif /* CONFIG_NATIVE_WINDOWS */
1711 void WpaGui::addInterface()
1717 add_iface
= new AddInterface(this, this);
1723 #ifndef QT_NO_SESSIONMANAGER
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();