1 /*
2 * wpa_gui - WpaGui class
3 * Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #ifdef __MINGW32__
10 /* Need to get getopt() */
11 #include <unistd.h>
12 #endif
13
14 #ifdef CONFIG_NATIVE_WINDOWS
15 #include <windows.h>
16 #endif /* CONFIG_NATIVE_WINDOWS */
17
18 #include <cstdio>
19 #include <QMessageBox>
20 #include <QCloseEvent>
21 #include <QImageReader>
22 #include <QSettings>
23
24 #include "wpagui.h"
25 #include "dirent.h"
26 #include "common/wpa_ctrl.h"
27 #include "userdatarequest.h"
28 #include "networkconfig.h"
29
30 #if 1
31 /* Silence stdout */
32 #define printf wpagui_printf
wpagui_printf(const char *,...)33 static int wpagui_printf(const char *, ...)
34 {
35 return 0;
36 }
37 #endif
38
WpaGui(QApplication * _app,QWidget * parent,const char *,Qt::WFlags)39 WpaGui::WpaGui(QApplication *_app, QWidget *parent, const char *, Qt::WFlags)
40 : QMainWindow(parent), app(_app)
41 {
42 setupUi(this);
43
44 #ifdef CONFIG_NATIVE_WINDOWS
45 fileStopServiceAction = new QAction(this);
46 fileStopServiceAction->setObjectName("Stop Service");
47 fileStopServiceAction->setIconText(tr("Stop Service"));
48 fileMenu->insertAction(actionWPS, fileStopServiceAction);
49
50 fileStartServiceAction = new QAction(this);
51 fileStartServiceAction->setObjectName("Start Service");
52 fileStartServiceAction->setIconText(tr("Start Service"));
53 fileMenu->insertAction(fileStopServiceAction, fileStartServiceAction);
54
55 connect(fileStartServiceAction, SIGNAL(triggered()), this,
56 SLOT(startService()));
57 connect(fileStopServiceAction, SIGNAL(triggered()), this,
58 SLOT(stopService()));
59
60 addInterfaceAction = new QAction(this);
61 addInterfaceAction->setIconText(tr("Add Interface"));
62 fileMenu->insertAction(fileStartServiceAction, addInterfaceAction);
63
64 connect(addInterfaceAction, SIGNAL(triggered()), this,
65 SLOT(addInterface()));
66 #endif /* CONFIG_NATIVE_WINDOWS */
67
68 (void) statusBar();
69
70 /*
71 * Disable WPS tab by default; it will be enabled if wpa_supplicant is
72 * built with WPS support.
73 */
74 wpsTab->setEnabled(false);
75 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), false);
76
77 connect(fileEventHistoryAction, SIGNAL(triggered()), this,
78 SLOT(eventHistory()));
79 connect(fileSaveConfigAction, SIGNAL(triggered()), this,
80 SLOT(saveConfig()));
81 connect(actionWPS, SIGNAL(triggered()), this, SLOT(wpsDialog()));
82 connect(actionPeers, SIGNAL(triggered()), this, SLOT(peersDialog()));
83 connect(fileExitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
84 connect(networkAddAction, SIGNAL(triggered()), this,
85 SLOT(addNetwork()));
86 connect(networkEditAction, SIGNAL(triggered()), this,
87 SLOT(editSelectedNetwork()));
88 connect(networkRemoveAction, SIGNAL(triggered()), this,
89 SLOT(removeSelectedNetwork()));
90 connect(networkEnableAllAction, SIGNAL(triggered()), this,
91 SLOT(enableAllNetworks()));
92 connect(networkDisableAllAction, SIGNAL(triggered()), this,
93 SLOT(disableAllNetworks()));
94 connect(networkRemoveAllAction, SIGNAL(triggered()), this,
95 SLOT(removeAllNetworks()));
96 connect(helpIndexAction, SIGNAL(triggered()), this, SLOT(helpIndex()));
97 connect(helpContentsAction, SIGNAL(triggered()), this,
98 SLOT(helpContents()));
99 connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(helpAbout()));
100 connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));
101 connect(scanButton, SIGNAL(clicked()), this, SLOT(scan()));
102 connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB()));
103 connect(adapterSelect, SIGNAL(activated(const QString&)), this,
104 SLOT(selectAdapter(const QString&)));
105 connect(networkSelect, SIGNAL(activated(const QString&)), this,
106 SLOT(selectNetwork(const QString&)));
107 connect(addNetworkButton, SIGNAL(clicked()), this, SLOT(addNetwork()));
108 connect(editNetworkButton, SIGNAL(clicked()), this,
109 SLOT(editListedNetwork()));
110 connect(removeNetworkButton, SIGNAL(clicked()), this,
111 SLOT(removeListedNetwork()));
112 connect(networkList, SIGNAL(itemSelectionChanged()), this,
113 SLOT(updateNetworkDisabledStatus()));
114 connect(enableRadioButton, SIGNAL(toggled(bool)), this,
115 SLOT(enableListedNetwork(bool)));
116 connect(disableRadioButton, SIGNAL(toggled(bool)), this,
117 SLOT(disableListedNetwork(bool)));
118 connect(scanNetworkButton, SIGNAL(clicked()), this, SLOT(scan()));
119 connect(networkList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
120 this, SLOT(editListedNetwork()));
121 connect(wpaguiTab, SIGNAL(currentChanged(int)), this,
122 SLOT(tabChanged(int)));
123 connect(wpsPbcButton, SIGNAL(clicked()), this, SLOT(wpsPbc()));
124 connect(wpsPinButton, SIGNAL(clicked()), this, SLOT(wpsGeneratePin()));
125 connect(wpsApPinEdit, SIGNAL(textChanged(const QString &)), this,
126 SLOT(wpsApPinChanged(const QString &)));
127 connect(wpsApPinButton, SIGNAL(clicked()), this, SLOT(wpsApPin()));
128
129 eh = NULL;
130 scanres = NULL;
131 peers = NULL;
132 add_iface = NULL;
133 udr = NULL;
134 tray_icon = NULL;
135 startInTray = false;
136 ctrl_iface = NULL;
137 ctrl_conn = NULL;
138 monitor_conn = NULL;
139 msgNotifier = NULL;
140 ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
141
142 parse_argv();
143
144 #ifndef QT_NO_SESSIONMANAGER
145 if (app->isSessionRestored()) {
146 QSettings settings("wpa_supplicant", "wpa_gui");
147 settings.beginGroup("state");
148 if (app->sessionId().compare(settings.value("session_id").
149 toString()) == 0)
150 startInTray = settings.value("in_tray").toBool();
151 settings.endGroup();
152 }
153 #endif
154
155 if (QSystemTrayIcon::isSystemTrayAvailable())
156 createTrayIcon(startInTray);
157 else
158 show();
159
160 connectedToService = false;
161 textStatus->setText(tr("connecting to wpa_supplicant"));
162 timer = new QTimer(this);
163 connect(timer, SIGNAL(timeout()), SLOT(ping()));
164 timer->setSingleShot(FALSE);
165 timer->start(1000);
166
167 if (openCtrlConnection(ctrl_iface) < 0) {
168 printf("Failed to open control connection to "
169 "wpa_supplicant.\n");
170 }
171
172 updateStatus();
173 networkMayHaveChanged = true;
174 updateNetworks();
175 }
176
177
~WpaGui()178 WpaGui::~WpaGui()
179 {
180 delete msgNotifier;
181
182 if (monitor_conn) {
183 wpa_ctrl_detach(monitor_conn);
184 wpa_ctrl_close(monitor_conn);
185 monitor_conn = NULL;
186 }
187 if (ctrl_conn) {
188 wpa_ctrl_close(ctrl_conn);
189 ctrl_conn = NULL;
190 }
191
192 if (eh) {
193 eh->close();
194 delete eh;
195 eh = NULL;
196 }
197
198 if (scanres) {
199 scanres->close();
200 delete scanres;
201 scanres = NULL;
202 }
203
204 if (peers) {
205 peers->close();
206 delete peers;
207 peers = NULL;
208 }
209
210 if (add_iface) {
211 add_iface->close();
212 delete add_iface;
213 add_iface = NULL;
214 }
215
216 if (udr) {
217 udr->close();
218 delete udr;
219 udr = NULL;
220 }
221
222 free(ctrl_iface);
223 ctrl_iface = NULL;
224
225 free(ctrl_iface_dir);
226 ctrl_iface_dir = NULL;
227 }
228
229
languageChange()230 void WpaGui::languageChange()
231 {
232 retranslateUi(this);
233 }
234
235
parse_argv()236 void WpaGui::parse_argv()
237 {
238 int c;
239 for (;;) {
240 c = getopt(qApp->argc(), qApp->argv(), "i:p:t");
241 if (c < 0)
242 break;
243 switch (c) {
244 case 'i':
245 free(ctrl_iface);
246 ctrl_iface = strdup(optarg);
247 break;
248 case 'p':
249 free(ctrl_iface_dir);
250 ctrl_iface_dir = strdup(optarg);
251 break;
252 case 't':
253 startInTray = true;
254 break;
255 }
256 }
257 }
258
259
openCtrlConnection(const char * ifname)260 int WpaGui::openCtrlConnection(const char *ifname)
261 {
262 char *cfile;
263 int flen;
264 char buf[2048], *pos, *pos2;
265 size_t len;
266
267 if (ifname) {
268 if (ifname != ctrl_iface) {
269 free(ctrl_iface);
270 ctrl_iface = strdup(ifname);
271 }
272 } else {
273 #ifdef CONFIG_CTRL_IFACE_UDP
274 free(ctrl_iface);
275 ctrl_iface = strdup("udp");
276 #endif /* CONFIG_CTRL_IFACE_UDP */
277 #ifdef CONFIG_CTRL_IFACE_UNIX
278 struct dirent *dent;
279 DIR *dir = opendir(ctrl_iface_dir);
280 free(ctrl_iface);
281 ctrl_iface = NULL;
282 if (dir) {
283 while ((dent = readdir(dir))) {
284 #ifdef _DIRENT_HAVE_D_TYPE
285 /* Skip the file if it is not a socket.
286 * Also accept DT_UNKNOWN (0) in case
287 * the C library or underlying file
288 * system does not support d_type. */
289 if (dent->d_type != DT_SOCK &&
290 dent->d_type != DT_UNKNOWN)
291 continue;
292 #endif /* _DIRENT_HAVE_D_TYPE */
293
294 if (strcmp(dent->d_name, ".") == 0 ||
295 strcmp(dent->d_name, "..") == 0)
296 continue;
297 printf("Selected interface '%s'\n",
298 dent->d_name);
299 ctrl_iface = strdup(dent->d_name);
300 break;
301 }
302 closedir(dir);
303 }
304 #endif /* CONFIG_CTRL_IFACE_UNIX */
305 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
306 struct wpa_ctrl *ctrl;
307 int ret;
308
309 free(ctrl_iface);
310 ctrl_iface = NULL;
311
312 ctrl = wpa_ctrl_open(NULL);
313 if (ctrl) {
314 len = sizeof(buf) - 1;
315 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf,
316 &len, NULL);
317 if (ret >= 0) {
318 connectedToService = true;
319 buf[len] = '\0';
320 pos = strchr(buf, '\n');
321 if (pos)
322 *pos = '\0';
323 ctrl_iface = strdup(buf);
324 }
325 wpa_ctrl_close(ctrl);
326 }
327 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
328 }
329
330 if (ctrl_iface == NULL) {
331 #ifdef CONFIG_NATIVE_WINDOWS
332 static bool first = true;
333 if (first && !serviceRunning()) {
334 first = false;
335 if (QMessageBox::warning(
336 this, qAppName(),
337 tr("wpa_supplicant service is not "
338 "running.\n"
339 "Do you want to start it?"),
340 QMessageBox::Yes | QMessageBox::No) ==
341 QMessageBox::Yes)
342 startService();
343 }
344 #endif /* CONFIG_NATIVE_WINDOWS */
345 return -1;
346 }
347
348 #ifdef CONFIG_CTRL_IFACE_UNIX
349 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
350 cfile = (char *) malloc(flen);
351 if (cfile == NULL)
352 return -1;
353 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
354 #else /* CONFIG_CTRL_IFACE_UNIX */
355 flen = strlen(ctrl_iface) + 1;
356 cfile = (char *) malloc(flen);
357 if (cfile == NULL)
358 return -1;
359 snprintf(cfile, flen, "%s", ctrl_iface);
360 #endif /* CONFIG_CTRL_IFACE_UNIX */
361
362 if (ctrl_conn) {
363 wpa_ctrl_close(ctrl_conn);
364 ctrl_conn = NULL;
365 }
366
367 if (monitor_conn) {
368 delete msgNotifier;
369 msgNotifier = NULL;
370 wpa_ctrl_detach(monitor_conn);
371 wpa_ctrl_close(monitor_conn);
372 monitor_conn = NULL;
373 }
374
375 printf("Trying to connect to '%s'\n", cfile);
376 ctrl_conn = wpa_ctrl_open(cfile);
377 if (ctrl_conn == NULL) {
378 free(cfile);
379 return -1;
380 }
381 monitor_conn = wpa_ctrl_open(cfile);
382 free(cfile);
383 if (monitor_conn == NULL) {
384 wpa_ctrl_close(ctrl_conn);
385 return -1;
386 }
387 if (wpa_ctrl_attach(monitor_conn)) {
388 printf("Failed to attach to wpa_supplicant\n");
389 wpa_ctrl_close(monitor_conn);
390 monitor_conn = NULL;
391 wpa_ctrl_close(ctrl_conn);
392 ctrl_conn = NULL;
393 return -1;
394 }
395
396 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
397 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
398 QSocketNotifier::Read, this);
399 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
400 #endif
401
402 adapterSelect->clear();
403 adapterSelect->addItem(ctrl_iface);
404 adapterSelect->setCurrentIndex(0);
405
406 len = sizeof(buf) - 1;
407 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
408 0) {
409 buf[len] = '\0';
410 pos = buf;
411 while (*pos) {
412 pos2 = strchr(pos, '\n');
413 if (pos2)
414 *pos2 = '\0';
415 if (strcmp(pos, ctrl_iface) != 0)
416 adapterSelect->addItem(pos);
417 if (pos2)
418 pos = pos2 + 1;
419 else
420 break;
421 }
422 }
423
424 len = sizeof(buf) - 1;
425 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len,
426 NULL) >= 0) {
427 buf[len] = '\0';
428
429 QString res(buf);
430 QStringList types = res.split(QChar(' '));
431 bool wps = types.contains("WSC");
432 actionWPS->setEnabled(wps);
433 wpsTab->setEnabled(wps);
434 wpaguiTab->setTabEnabled(wpaguiTab->indexOf(wpsTab), wps);
435 }
436
437 return 0;
438 }
439
440
ctrlRequest(const char * cmd,char * buf,size_t * buflen)441 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
442 {
443 int ret;
444
445 if (ctrl_conn == NULL)
446 return -3;
447 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen, NULL);
448 if (ret == -2)
449 printf("'%s' command timed out.\n", cmd);
450 else if (ret < 0)
451 printf("'%s' command failed.\n", cmd);
452
453 return ret;
454 }
455
456
wpaStateTranslate(char * state)457 QString WpaGui::wpaStateTranslate(char *state)
458 {
459 if (!strcmp(state, "DISCONNECTED"))
460 return tr("Disconnected");
461 else if (!strcmp(state, "INACTIVE"))
462 return tr("Inactive");
463 else if (!strcmp(state, "SCANNING"))
464 return tr("Scanning");
465 else if (!strcmp(state, "AUTHENTICATING"))
466 return tr("Authenticating");
467 else if (!strcmp(state, "ASSOCIATING"))
468 return tr("Associating");
469 else if (!strcmp(state, "ASSOCIATED"))
470 return tr("Associated");
471 else if (!strcmp(state, "4WAY_HANDSHAKE"))
472 return tr("4-Way Handshake");
473 else if (!strcmp(state, "GROUP_HANDSHAKE"))
474 return tr("Group Handshake");
475 else if (!strcmp(state, "COMPLETED"))
476 return tr("Completed");
477 else
478 return tr("Unknown");
479 }
480
481
updateStatus()482 void WpaGui::updateStatus()
483 {
484 char buf[2048], *start, *end, *pos;
485 size_t len;
486
487 pingsToStatusUpdate = 10;
488
489 len = sizeof(buf) - 1;
490 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
491 textStatus->setText(tr("Could not get status from "
492 "wpa_supplicant"));
493 textAuthentication->clear();
494 textEncryption->clear();
495 textSsid->clear();
496 textBssid->clear();
497 textIpAddress->clear();
498
499 #ifdef CONFIG_NATIVE_WINDOWS
500 static bool first = true;
501 if (first && connectedToService &&
502 (ctrl_iface == NULL || *ctrl_iface == '\0')) {
503 first = false;
504 if (QMessageBox::information(
505 this, qAppName(),
506 tr("No network interfaces in use.\n"
507 "Would you like to add one?"),
508 QMessageBox::Yes | QMessageBox::No) ==
509 QMessageBox::Yes)
510 addInterface();
511 }
512 #endif /* CONFIG_NATIVE_WINDOWS */
513 return;
514 }
515
516 buf[len] = '\0';
517
518 bool auth_updated = false, ssid_updated = false;
519 bool bssid_updated = false, ipaddr_updated = false;
520 bool status_updated = false;
521 char *pairwise_cipher = NULL, *group_cipher = NULL;
522 char *mode = NULL;
523
524 start = buf;
525 while (*start) {
526 bool last = false;
527 end = strchr(start, '\n');
528 if (end == NULL) {
529 last = true;
530 end = start;
531 while (end[0] && end[1])
532 end++;
533 }
534 *end = '\0';
535
536 pos = strchr(start, '=');
537 if (pos) {
538 *pos++ = '\0';
539 if (strcmp(start, "bssid") == 0) {
540 bssid_updated = true;
541 textBssid->setText(pos);
542 } else if (strcmp(start, "ssid") == 0) {
543 ssid_updated = true;
544 textSsid->setText(pos);
545 } else if (strcmp(start, "ip_address") == 0) {
546 ipaddr_updated = true;
547 textIpAddress->setText(pos);
548 } else if (strcmp(start, "wpa_state") == 0) {
549 status_updated = true;
550 textStatus->setText(wpaStateTranslate(pos));
551 } else if (strcmp(start, "key_mgmt") == 0) {
552 auth_updated = true;
553 textAuthentication->setText(pos);
554 /* TODO: could add EAP status to this */
555 } else if (strcmp(start, "pairwise_cipher") == 0) {
556 pairwise_cipher = pos;
557 } else if (strcmp(start, "group_cipher") == 0) {
558 group_cipher = pos;
559 } else if (strcmp(start, "mode") == 0) {
560 mode = pos;
561 }
562 }
563
564 if (last)
565 break;
566 start = end + 1;
567 }
568 if (status_updated && mode)
569 textStatus->setText(textStatus->text() + " (" + mode + ")");
570
571 if (pairwise_cipher || group_cipher) {
572 QString encr;
573 if (pairwise_cipher && group_cipher &&
574 strcmp(pairwise_cipher, group_cipher) != 0) {
575 encr.append(pairwise_cipher);
576 encr.append(" + ");
577 encr.append(group_cipher);
578 } else if (pairwise_cipher) {
579 encr.append(pairwise_cipher);
580 } else {
581 encr.append(group_cipher);
582 encr.append(" [group key only]");
583 }
584 textEncryption->setText(encr);
585 } else
586 textEncryption->clear();
587
588 if (!status_updated)
589 textStatus->clear();
590 if (!auth_updated)
591 textAuthentication->clear();
592 if (!ssid_updated)
593 textSsid->clear();
594 if (!bssid_updated)
595 textBssid->clear();
596 if (!ipaddr_updated)
597 textIpAddress->clear();
598 }
599
600
updateNetworks()601 void WpaGui::updateNetworks()
602 {
603 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
604 size_t len;
605 int first_active = -1;
606 int was_selected = -1;
607 bool current = false;
608
609 if (!networkMayHaveChanged)
610 return;
611
612 if (networkList->currentRow() >= 0)
613 was_selected = networkList->currentRow();
614
615 networkSelect->clear();
616 networkList->clear();
617
618 if (ctrl_conn == NULL)
619 return;
620
621 len = sizeof(buf) - 1;
622 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
623 return;
624
625 buf[len] = '\0';
626 start = strchr(buf, '\n');
627 if (start == NULL)
628 return;
629 start++;
630
631 while (*start) {
632 bool last = false;
633 end = strchr(start, '\n');
634 if (end == NULL) {
635 last = true;
636 end = start;
637 while (end[0] && end[1])
638 end++;
639 }
640 *end = '\0';
641
642 id = start;
643 ssid = strchr(id, '\t');
644 if (ssid == NULL)
645 break;
646 *ssid++ = '\0';
647 bssid = strchr(ssid, '\t');
648 if (bssid == NULL)
649 break;
650 *bssid++ = '\0';
651 flags = strchr(bssid, '\t');
652 if (flags == NULL)
653 break;
654 *flags++ = '\0';
655
656 if (strstr(flags, "[DISABLED][P2P-PERSISTENT]")) {
657 if (last)
658 break;
659 start = end + 1;
660 continue;
661 }
662
663 QString network(id);
664 network.append(": ");
665 network.append(ssid);
666 networkSelect->addItem(network);
667 networkList->addItem(network);
668
669 if (strstr(flags, "[CURRENT]")) {
670 networkSelect->setCurrentIndex(networkSelect->count() -
671 1);
672 current = true;
673 } else if (first_active < 0 &&
674 strstr(flags, "[DISABLED]") == NULL)
675 first_active = networkSelect->count() - 1;
676
677 if (last)
678 break;
679 start = end + 1;
680 }
681
682 if (networkSelect->count() > 1)
683 networkSelect->addItem(tr("Select any network"));
684
685 if (!current && first_active >= 0)
686 networkSelect->setCurrentIndex(first_active);
687
688 if (was_selected >= 0 && networkList->count() > 0) {
689 if (was_selected < networkList->count())
690 networkList->setCurrentRow(was_selected);
691 else
692 networkList->setCurrentRow(networkList->count() - 1);
693 }
694 else
695 networkList->setCurrentRow(networkSelect->currentIndex());
696
697 networkMayHaveChanged = false;
698 }
699
700
helpIndex()701 void WpaGui::helpIndex()
702 {
703 printf("helpIndex\n");
704 }
705
706
helpContents()707 void WpaGui::helpContents()
708 {
709 printf("helpContents\n");
710 }
711
712
helpAbout()713 void WpaGui::helpAbout()
714 {
715 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
716 "Copyright (c) 2003-2011,\n"
717 "Jouni Malinen <j@w1.fi>\n"
718 "and contributors.\n"
719 "\n"
720 "This program is free software. You can\n"
721 "distribute it and/or modify it under the terms "
722 "of\n"
723 "the GNU General Public License version 2.\n"
724 "\n"
725 "Alternatively, this software may be distributed\n"
726 "under the terms of the BSD license.\n"
727 "\n"
728 "This product includes software developed\n"
729 "by the OpenSSL Project for use in the\n"
730 "OpenSSL Toolkit (http://www.openssl.org/)\n");
731 }
732
733
disconnect()734 void WpaGui::disconnect()
735 {
736 char reply[10];
737 size_t reply_len = sizeof(reply);
738 ctrlRequest("DISCONNECT", reply, &reply_len);
739 stopWpsRun(false);
740 }
741
742
scan()743 void WpaGui::scan()
744 {
745 if (scanres) {
746 scanres->close();
747 delete scanres;
748 }
749
750 scanres = new ScanResults();
751 if (scanres == NULL)
752 return;
753 scanres->setWpaGui(this);
754 scanres->show();
755 scanres->exec();
756 }
757
758
eventHistory()759 void WpaGui::eventHistory()
760 {
761 if (eh) {
762 eh->close();
763 delete eh;
764 }
765
766 eh = new EventHistory();
767 if (eh == NULL)
768 return;
769 eh->addEvents(msgs);
770 eh->show();
771 eh->exec();
772 }
773
774
ping()775 void WpaGui::ping()
776 {
777 char buf[10];
778 size_t len;
779
780 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
781 /*
782 * QSocketNotifier cannot be used with Windows named pipes, so use a
783 * timer to check for received messages for now. This could be
784 * optimized be doing something specific to named pipes or Windows
785 * events, but it is not clear what would be the best way of doing that
786 * in Qt.
787 */
788 receiveMsgs();
789 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
790
791 if (scanres && !scanres->isVisible()) {
792 delete scanres;
793 scanres = NULL;
794 }
795
796 if (eh && !eh->isVisible()) {
797 delete eh;
798 eh = NULL;
799 }
800
801 if (udr && !udr->isVisible()) {
802 delete udr;
803 udr = NULL;
804 }
805
806 len = sizeof(buf) - 1;
807 if (ctrlRequest("PING", buf, &len) < 0) {
808 printf("PING failed - trying to reconnect\n");
809 if (openCtrlConnection(ctrl_iface) >= 0) {
810 printf("Reconnected successfully\n");
811 pingsToStatusUpdate = 0;
812 }
813 }
814
815 pingsToStatusUpdate--;
816 if (pingsToStatusUpdate <= 0) {
817 updateStatus();
818 updateNetworks();
819 }
820
821 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
822 /* Use less frequent pings and status updates when the main window is
823 * hidden (running in taskbar). */
824 int interval = isHidden() ? 5000 : 1000;
825 if (timer->interval() != interval)
826 timer->setInterval(interval);
827 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
828 }
829
830
str_match(const char * a,const char * b)831 static int str_match(const char *a, const char *b)
832 {
833 return strncmp(a, b, strlen(b)) == 0;
834 }
835
836
processMsg(char * msg)837 void WpaGui::processMsg(char *msg)
838 {
839 char *pos = msg, *pos2;
840 int priority = 2;
841
842 if (*pos == '<') {
843 /* skip priority */
844 pos++;
845 priority = atoi(pos);
846 pos = strchr(pos, '>');
847 if (pos)
848 pos++;
849 else
850 pos = msg;
851 }
852
853 WpaMsg wm(pos, priority);
854 if (eh)
855 eh->addEvent(wm);
856 if (peers)
857 peers->event_notify(wm);
858 msgs.append(wm);
859 while (msgs.count() > 100)
860 msgs.pop_front();
861
862 /* Update last message with truncated version of the event */
863 if (strncmp(pos, "CTRL-", 5) == 0) {
864 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
865 if (pos2)
866 pos2++;
867 else
868 pos2 = pos;
869 } else
870 pos2 = pos;
871 QString lastmsg = pos2;
872 lastmsg.truncate(40);
873 textLastMessage->setText(lastmsg);
874
875 pingsToStatusUpdate = 0;
876 networkMayHaveChanged = true;
877
878 if (str_match(pos, WPA_CTRL_REQ))
879 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
880 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
881 scanres->updateResults();
882 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
883 showTrayMessage(QSystemTrayIcon::Information, 3,
884 tr("Disconnected from network."));
885 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
886 showTrayMessage(QSystemTrayIcon::Information, 3,
887 tr("Connection to network established."));
888 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
889 stopWpsRun(true);
890 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
891 wpsStatusText->setText(tr("WPS AP in active PBC mode found"));
892 if (textStatus->text() == "INACTIVE" ||
893 textStatus->text() == "DISCONNECTED")
894 wpaguiTab->setCurrentWidget(wpsTab);
895 wpsInstructions->setText(tr("Press the PBC button on the "
896 "screen to start registration"));
897 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
898 wpsStatusText->setText(tr("WPS AP with recently selected "
899 "registrar"));
900 if (textStatus->text() == "INACTIVE" ||
901 textStatus->text() == "DISCONNECTED")
902 wpaguiTab->setCurrentWidget(wpsTab);
903 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_AUTH)) {
904 showTrayMessage(QSystemTrayIcon::Information, 3,
905 "Wi-Fi Protected Setup (WPS) AP\n"
906 "indicating this client is authorized.");
907 wpsStatusText->setText("WPS AP indicating this client is "
908 "authorized");
909 if (textStatus->text() == "INACTIVE" ||
910 textStatus->text() == "DISCONNECTED")
911 wpaguiTab->setCurrentWidget(wpsTab);
912 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
913 wpsStatusText->setText(tr("WPS AP detected"));
914 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
915 wpsStatusText->setText(tr("PBC mode overlap detected"));
916 wpsInstructions->setText(tr("More than one AP is currently in "
917 "active WPS PBC mode. Wait couple "
918 "of minutes and try again"));
919 wpaguiTab->setCurrentWidget(wpsTab);
920 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
921 wpsStatusText->setText(tr("Network configuration received"));
922 wpaguiTab->setCurrentWidget(wpsTab);
923 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
924 if (strstr(pos, "(WSC)"))
925 wpsStatusText->setText(tr("Registration started"));
926 } else if (str_match(pos, WPS_EVENT_M2D)) {
927 wpsStatusText->setText(tr("Registrar does not yet know PIN"));
928 } else if (str_match(pos, WPS_EVENT_FAIL)) {
929 wpsStatusText->setText(tr("Registration failed"));
930 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
931 wpsStatusText->setText(tr("Registration succeeded"));
932 }
933 }
934
935
processCtrlReq(const char * req)936 void WpaGui::processCtrlReq(const char *req)
937 {
938 if (udr) {
939 udr->close();
940 delete udr;
941 }
942 udr = new UserDataRequest();
943 if (udr == NULL)
944 return;
945 if (udr->setParams(this, req) < 0) {
946 delete udr;
947 udr = NULL;
948 return;
949 }
950 udr->show();
951 udr->exec();
952 }
953
954
receiveMsgs()955 void WpaGui::receiveMsgs()
956 {
957 char buf[256];
958 size_t len;
959
960 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
961 len = sizeof(buf) - 1;
962 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
963 buf[len] = '\0';
964 processMsg(buf);
965 }
966 }
967 }
968
969
connectB()970 void WpaGui::connectB()
971 {
972 char reply[10];
973 size_t reply_len = sizeof(reply);
974 ctrlRequest("REASSOCIATE", reply, &reply_len);
975 }
976
977
selectNetwork(const QString & sel)978 void WpaGui::selectNetwork( const QString &sel )
979 {
980 QString cmd(sel);
981 char reply[10];
982 size_t reply_len = sizeof(reply);
983
984 if (cmd.contains(QRegExp("^\\d+:")))
985 cmd.truncate(cmd.indexOf(':'));
986 else
987 cmd = "any";
988 cmd.prepend("SELECT_NETWORK ");
989 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
990 triggerUpdate();
991 stopWpsRun(false);
992 }
993
994
enableNetwork(const QString & sel)995 void WpaGui::enableNetwork(const QString &sel)
996 {
997 QString cmd(sel);
998 char reply[10];
999 size_t reply_len = sizeof(reply);
1000
1001 if (cmd.contains(QRegExp("^\\d+:")))
1002 cmd.truncate(cmd.indexOf(':'));
1003 else if (!cmd.startsWith("all")) {
1004 printf("Invalid editNetwork '%s'\n",
1005 cmd.toAscii().constData());
1006 return;
1007 }
1008 cmd.prepend("ENABLE_NETWORK ");
1009 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1010 triggerUpdate();
1011 }
1012
1013
disableNetwork(const QString & sel)1014 void WpaGui::disableNetwork(const QString &sel)
1015 {
1016 QString cmd(sel);
1017 char reply[10];
1018 size_t reply_len = sizeof(reply);
1019
1020 if (cmd.contains(QRegExp("^\\d+:")))
1021 cmd.truncate(cmd.indexOf(':'));
1022 else if (!cmd.startsWith("all")) {
1023 printf("Invalid editNetwork '%s'\n",
1024 cmd.toAscii().constData());
1025 return;
1026 }
1027 cmd.prepend("DISABLE_NETWORK ");
1028 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1029 triggerUpdate();
1030 }
1031
1032
editNetwork(const QString & sel)1033 void WpaGui::editNetwork(const QString &sel)
1034 {
1035 QString cmd(sel);
1036 int id = -1;
1037
1038 if (cmd.contains(QRegExp("^\\d+:"))) {
1039 cmd.truncate(cmd.indexOf(':'));
1040 id = cmd.toInt();
1041 }
1042
1043 NetworkConfig *nc = new NetworkConfig();
1044 if (nc == NULL)
1045 return;
1046 nc->setWpaGui(this);
1047
1048 if (id >= 0)
1049 nc->paramsFromConfig(id);
1050 else
1051 nc->newNetwork();
1052
1053 nc->show();
1054 nc->exec();
1055 }
1056
1057
editSelectedNetwork()1058 void WpaGui::editSelectedNetwork()
1059 {
1060 if (networkSelect->count() < 1) {
1061 QMessageBox::information(
1062 this, tr("No Networks"),
1063 tr("There are no networks to edit.\n"));
1064 return;
1065 }
1066 QString sel(networkSelect->currentText());
1067 editNetwork(sel);
1068 }
1069
1070
editListedNetwork()1071 void WpaGui::editListedNetwork()
1072 {
1073 if (networkList->currentRow() < 0) {
1074 QMessageBox::information(this, tr("Select A Network"),
1075 tr("Select a network from the list to"
1076 " edit it.\n"));
1077 return;
1078 }
1079 QString sel(networkList->currentItem()->text());
1080 editNetwork(sel);
1081 }
1082
1083
triggerUpdate()1084 void WpaGui::triggerUpdate()
1085 {
1086 updateStatus();
1087 networkMayHaveChanged = true;
1088 updateNetworks();
1089 }
1090
1091
addNetwork()1092 void WpaGui::addNetwork()
1093 {
1094 NetworkConfig *nc = new NetworkConfig();
1095 if (nc == NULL)
1096 return;
1097 nc->setWpaGui(this);
1098 nc->newNetwork();
1099 nc->show();
1100 nc->exec();
1101 }
1102
1103
removeNetwork(const QString & sel)1104 void WpaGui::removeNetwork(const QString &sel)
1105 {
1106 QString cmd(sel);
1107 char reply[10];
1108 size_t reply_len = sizeof(reply);
1109
1110 if (cmd.contains(QRegExp("^\\d+:")))
1111 cmd.truncate(cmd.indexOf(':'));
1112 else if (!cmd.startsWith("all")) {
1113 printf("Invalid editNetwork '%s'\n",
1114 cmd.toAscii().constData());
1115 return;
1116 }
1117 cmd.prepend("REMOVE_NETWORK ");
1118 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1119 triggerUpdate();
1120 }
1121
1122
removeSelectedNetwork()1123 void WpaGui::removeSelectedNetwork()
1124 {
1125 if (networkSelect->count() < 1) {
1126 QMessageBox::information(this, tr("No Networks"),
1127 tr("There are no networks to remove."
1128 "\n"));
1129 return;
1130 }
1131 QString sel(networkSelect->currentText());
1132 removeNetwork(sel);
1133 }
1134
1135
removeListedNetwork()1136 void WpaGui::removeListedNetwork()
1137 {
1138 if (networkList->currentRow() < 0) {
1139 QMessageBox::information(this, tr("Select A Network"),
1140 tr("Select a network from the list "
1141 "to remove it.\n"));
1142 return;
1143 }
1144 QString sel(networkList->currentItem()->text());
1145 removeNetwork(sel);
1146 }
1147
1148
enableAllNetworks()1149 void WpaGui::enableAllNetworks()
1150 {
1151 QString sel("all");
1152 enableNetwork(sel);
1153 }
1154
1155
disableAllNetworks()1156 void WpaGui::disableAllNetworks()
1157 {
1158 QString sel("all");
1159 disableNetwork(sel);
1160 }
1161
1162
removeAllNetworks()1163 void WpaGui::removeAllNetworks()
1164 {
1165 QString sel("all");
1166 removeNetwork(sel);
1167 }
1168
1169
getNetworkDisabled(const QString & sel)1170 int WpaGui::getNetworkDisabled(const QString &sel)
1171 {
1172 QString cmd(sel);
1173 char reply[10];
1174 size_t reply_len = sizeof(reply) - 1;
1175 int pos = cmd.indexOf(':');
1176 if (pos < 0) {
1177 printf("Invalid getNetworkDisabled '%s'\n",
1178 cmd.toAscii().constData());
1179 return -1;
1180 }
1181 cmd.truncate(pos);
1182 cmd.prepend("GET_NETWORK ");
1183 cmd.append(" disabled");
1184
1185 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1186 && reply_len >= 1) {
1187 reply[reply_len] = '\0';
1188 if (!str_match(reply, "FAIL"))
1189 return atoi(reply);
1190 }
1191
1192 return -1;
1193 }
1194
1195
updateNetworkDisabledStatus()1196 void WpaGui::updateNetworkDisabledStatus()
1197 {
1198 if (networkList->currentRow() < 0)
1199 return;
1200
1201 QString sel(networkList->currentItem()->text());
1202
1203 switch (getNetworkDisabled(sel)) {
1204 case 0:
1205 if (!enableRadioButton->isChecked())
1206 enableRadioButton->setChecked(true);
1207 return;
1208 case 1:
1209 if (!disableRadioButton->isChecked())
1210 disableRadioButton->setChecked(true);
1211 return;
1212 }
1213 }
1214
1215
enableListedNetwork(bool enabled)1216 void WpaGui::enableListedNetwork(bool enabled)
1217 {
1218 if (networkList->currentRow() < 0 || !enabled)
1219 return;
1220
1221 QString sel(networkList->currentItem()->text());
1222
1223 if (getNetworkDisabled(sel) == 1)
1224 enableNetwork(sel);
1225 }
1226
1227
disableListedNetwork(bool disabled)1228 void WpaGui::disableListedNetwork(bool disabled)
1229 {
1230 if (networkList->currentRow() < 0 || !disabled)
1231 return;
1232
1233 QString sel(networkList->currentItem()->text());
1234
1235 if (getNetworkDisabled(sel) == 0)
1236 disableNetwork(sel);
1237 }
1238
1239
saveConfig()1240 void WpaGui::saveConfig()
1241 {
1242 char buf[10];
1243 size_t len;
1244
1245 len = sizeof(buf) - 1;
1246 ctrlRequest("SAVE_CONFIG", buf, &len);
1247
1248 buf[len] = '\0';
1249
1250 if (str_match(buf, "FAIL"))
1251 QMessageBox::warning(
1252 this, tr("Failed to save configuration"),
1253 tr("The configuration could not be saved.\n"
1254 "\n"
1255 "The update_config=1 configuration option\n"
1256 "must be used for configuration saving to\n"
1257 "be permitted.\n"));
1258 else
1259 QMessageBox::information(
1260 this, tr("Saved configuration"),
1261 tr("The current configuration was saved."
1262 "\n"));
1263 }
1264
1265
selectAdapter(const QString & sel)1266 void WpaGui::selectAdapter( const QString & sel )
1267 {
1268 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1269 printf("Failed to open control connection to "
1270 "wpa_supplicant.\n");
1271 updateStatus();
1272 updateNetworks();
1273 }
1274
1275
createTrayIcon(bool trayOnly)1276 void WpaGui::createTrayIcon(bool trayOnly)
1277 {
1278 QApplication::setQuitOnLastWindowClosed(false);
1279
1280 tray_icon = new QSystemTrayIcon(this);
1281 tray_icon->setToolTip(qAppName() + tr(" - wpa_supplicant user interface"));
1282 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1283 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1284 else
1285 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1286
1287 connect(tray_icon,
1288 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1289 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1290
1291 ackTrayIcon = false;
1292
1293 tray_menu = new QMenu(this);
1294
1295 disconnectAction = new QAction(tr("&Disconnect"), this);
1296 reconnectAction = new QAction(tr("Re&connect"), this);
1297 connect(disconnectAction, SIGNAL(triggered()), this,
1298 SLOT(disconnect()));
1299 connect(reconnectAction, SIGNAL(triggered()), this,
1300 SLOT(connectB()));
1301 tray_menu->addAction(disconnectAction);
1302 tray_menu->addAction(reconnectAction);
1303 tray_menu->addSeparator();
1304
1305 eventAction = new QAction(tr("&Event History"), this);
1306 scanAction = new QAction(tr("Scan &Results"), this);
1307 statAction = new QAction(tr("S&tatus"), this);
1308 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1309 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1310 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1311 tray_menu->addAction(eventAction);
1312 tray_menu->addAction(scanAction);
1313 tray_menu->addAction(statAction);
1314 tray_menu->addSeparator();
1315
1316 showAction = new QAction(tr("&Show Window"), this);
1317 hideAction = new QAction(tr("&Hide Window"), this);
1318 quitAction = new QAction(tr("&Quit"), this);
1319 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1320 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1321 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1322 tray_menu->addAction(showAction);
1323 tray_menu->addAction(hideAction);
1324 tray_menu->addSeparator();
1325 tray_menu->addAction(quitAction);
1326
1327 tray_icon->setContextMenu(tray_menu);
1328
1329 tray_icon->show();
1330
1331 if (!trayOnly)
1332 show();
1333 inTray = trayOnly;
1334 }
1335
1336
showTrayMessage(QSystemTrayIcon::MessageIcon type,int sec,const QString & msg)1337 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1338 const QString & msg)
1339 {
1340 if (!QSystemTrayIcon::supportsMessages())
1341 return;
1342
1343 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1344 return;
1345
1346 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1347 }
1348
1349
trayActivated(QSystemTrayIcon::ActivationReason how)1350 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1351 {
1352 switch (how) {
1353 /* use close() here instead of hide() and allow the
1354 * custom closeEvent handler take care of children */
1355 case QSystemTrayIcon::Trigger:
1356 ackTrayIcon = true;
1357 if (isVisible()) {
1358 close();
1359 inTray = true;
1360 } else {
1361 show();
1362 inTray = false;
1363 }
1364 break;
1365 case QSystemTrayIcon::MiddleClick:
1366 showTrayStatus();
1367 break;
1368 default:
1369 break;
1370 }
1371 }
1372
1373
showTrayStatus()1374 void WpaGui::showTrayStatus()
1375 {
1376 char buf[2048];
1377 size_t len;
1378
1379 len = sizeof(buf) - 1;
1380 if (ctrlRequest("STATUS", buf, &len) < 0)
1381 return;
1382 buf[len] = '\0';
1383
1384 QString msg, status(buf);
1385
1386 QStringList lines = status.split(QRegExp("\\n"));
1387 for (QStringList::Iterator it = lines.begin();
1388 it != lines.end(); it++) {
1389 int pos = (*it).indexOf('=') + 1;
1390 if (pos < 1)
1391 continue;
1392
1393 if ((*it).startsWith("bssid="))
1394 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1395 else if ((*it).startsWith("ssid="))
1396 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1397 else if ((*it).startsWith("pairwise_cipher="))
1398 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1399 else if ((*it).startsWith("group_cipher="))
1400 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1401 else if ((*it).startsWith("key_mgmt="))
1402 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1403 else if ((*it).startsWith("wpa_state="))
1404 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1405 else if ((*it).startsWith("ip_address="))
1406 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1407 else if ((*it).startsWith("Supplicant PAE state="))
1408 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1409 else if ((*it).startsWith("EAP state="))
1410 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1411 }
1412
1413 if (!msg.isEmpty())
1414 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1415 }
1416
1417
closeEvent(QCloseEvent * event)1418 void WpaGui::closeEvent(QCloseEvent *event)
1419 {
1420 if (eh) {
1421 eh->close();
1422 delete eh;
1423 eh = NULL;
1424 }
1425
1426 if (scanres) {
1427 scanres->close();
1428 delete scanres;
1429 scanres = NULL;
1430 }
1431
1432 if (peers) {
1433 peers->close();
1434 delete peers;
1435 peers = NULL;
1436 }
1437
1438 if (udr) {
1439 udr->close();
1440 delete udr;
1441 udr = NULL;
1442 }
1443
1444 if (tray_icon && !ackTrayIcon) {
1445 /* give user a visual hint that the tray icon exists */
1446 if (QSystemTrayIcon::supportsMessages()) {
1447 hide();
1448 showTrayMessage(QSystemTrayIcon::Information, 3,
1449 qAppName() +
1450 tr(" will keep running in "
1451 "the system tray."));
1452 } else {
1453 QMessageBox::information(this, qAppName() +
1454 tr(" systray"),
1455 tr("The program will keep "
1456 "running in the system "
1457 "tray."));
1458 }
1459 ackTrayIcon = true;
1460 }
1461
1462 event->accept();
1463 }
1464
1465
wpsDialog()1466 void WpaGui::wpsDialog()
1467 {
1468 wpaguiTab->setCurrentWidget(wpsTab);
1469 }
1470
1471
peersDialog()1472 void WpaGui::peersDialog()
1473 {
1474 if (peers) {
1475 peers->close();
1476 delete peers;
1477 }
1478
1479 peers = new Peers();
1480 if (peers == NULL)
1481 return;
1482 peers->setWpaGui(this);
1483 peers->show();
1484 peers->exec();
1485 }
1486
1487
tabChanged(int index)1488 void WpaGui::tabChanged(int index)
1489 {
1490 if (index != 2)
1491 return;
1492
1493 if (wpsRunning)
1494 return;
1495
1496 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1497 if (bssFromScan.isEmpty())
1498 wpsApPinButton->setEnabled(false);
1499 }
1500
1501
wpsPbc()1502 void WpaGui::wpsPbc()
1503 {
1504 char reply[20];
1505 size_t reply_len = sizeof(reply);
1506
1507 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1508 return;
1509
1510 wpsPinEdit->setEnabled(false);
1511 if (wpsStatusText->text().compare(tr("WPS AP in active PBC mode found"))) {
1512 wpsInstructions->setText(tr("Press the push button on the AP to "
1513 "start the PBC mode."));
1514 } else {
1515 wpsInstructions->setText(tr("If you have not yet done so, press "
1516 "the push button on the AP to start "
1517 "the PBC mode."));
1518 }
1519 wpsStatusText->setText(tr("Waiting for Registrar"));
1520 wpsRunning = true;
1521 }
1522
1523
wpsGeneratePin()1524 void WpaGui::wpsGeneratePin()
1525 {
1526 char reply[20];
1527 size_t reply_len = sizeof(reply) - 1;
1528
1529 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1530 return;
1531
1532 reply[reply_len] = '\0';
1533
1534 wpsPinEdit->setText(reply);
1535 wpsPinEdit->setEnabled(true);
1536 wpsInstructions->setText(tr("Enter the generated PIN into the Registrar "
1537 "(either the internal one in the AP or an "
1538 "external one)."));
1539 wpsStatusText->setText(tr("Waiting for Registrar"));
1540 wpsRunning = true;
1541 }
1542
1543
setBssFromScan(const QString & bssid)1544 void WpaGui::setBssFromScan(const QString &bssid)
1545 {
1546 bssFromScan = bssid;
1547 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1548 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1549 wpsStatusText->setText(tr("WPS AP selected from scan results"));
1550 wpsInstructions->setText(tr("If you want to use an AP device PIN, e.g., "
1551 "from a label in the device, enter the eight "
1552 "digit AP PIN and click Use AP PIN button."));
1553 }
1554
1555
wpsApPinChanged(const QString & text)1556 void WpaGui::wpsApPinChanged(const QString &text)
1557 {
1558 wpsApPinButton->setEnabled(text.length() == 8);
1559 }
1560
1561
wpsApPin()1562 void WpaGui::wpsApPin()
1563 {
1564 char reply[20];
1565 size_t reply_len = sizeof(reply);
1566
1567 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1568 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1569 return;
1570
1571 wpsStatusText->setText(tr("Waiting for AP/Enrollee"));
1572 wpsRunning = true;
1573 }
1574
1575
stopWpsRun(bool success)1576 void WpaGui::stopWpsRun(bool success)
1577 {
1578 if (wpsRunning)
1579 wpsStatusText->setText(success ? tr("Connected to the network") :
1580 tr("Stopped"));
1581 else
1582 wpsStatusText->setText("");
1583 wpsPinEdit->setEnabled(false);
1584 wpsInstructions->setText("");
1585 wpsRunning = false;
1586 bssFromScan = "";
1587 wpsApPinEdit->setEnabled(false);
1588 wpsApPinButton->setEnabled(false);
1589 }
1590
1591
1592 #ifdef CONFIG_NATIVE_WINDOWS
1593
1594 #ifndef WPASVC_NAME
1595 #define WPASVC_NAME TEXT("wpasvc")
1596 #endif
1597
1598 class ErrorMsg : public QMessageBox {
1599 public:
1600 ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
1601 void showMsg(QString msg);
1602 private:
1603 DWORD err;
1604 };
1605
ErrorMsg(QWidget * parent,DWORD last_err)1606 ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
1607 QMessageBox(parent), err(last_err)
1608 {
1609 setWindowTitle(tr("wpa_gui error"));
1610 setIcon(QMessageBox::Warning);
1611 }
1612
showMsg(QString msg)1613 void ErrorMsg::showMsg(QString msg)
1614 {
1615 LPTSTR buf;
1616
1617 setText(msg);
1618 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1619 FORMAT_MESSAGE_FROM_SYSTEM,
1620 NULL, err, 0, (LPTSTR) (void *) &buf,
1621 0, NULL) > 0) {
1622 QString msg = QString::fromWCharArray(buf);
1623 setInformativeText(QString("[%1] %2").arg(err).arg(msg));
1624 LocalFree(buf);
1625 } else {
1626 setInformativeText(QString("[%1]").arg(err));
1627 }
1628
1629 exec();
1630 }
1631
1632
startService()1633 void WpaGui::startService()
1634 {
1635 SC_HANDLE svc, scm;
1636
1637 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1638 if (!scm) {
1639 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1640 return;
1641 }
1642
1643 svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
1644 if (!svc) {
1645 ErrorMsg(this).showMsg(tr("OpenService failed"));
1646 CloseServiceHandle(scm);
1647 return;
1648 }
1649
1650 if (!StartService(svc, 0, NULL)) {
1651 ErrorMsg(this).showMsg(tr("Failed to start wpa_supplicant "
1652 "service"));
1653 }
1654
1655 CloseServiceHandle(svc);
1656 CloseServiceHandle(scm);
1657 }
1658
1659
stopService()1660 void WpaGui::stopService()
1661 {
1662 SC_HANDLE svc, scm;
1663 SERVICE_STATUS status;
1664
1665 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1666 if (!scm) {
1667 ErrorMsg(this).showMsg(tr("OpenSCManager failed"));
1668 return;
1669 }
1670
1671 svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
1672 if (!svc) {
1673 ErrorMsg(this).showMsg(tr("OpenService failed"));
1674 CloseServiceHandle(scm);
1675 return;
1676 }
1677
1678 if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
1679 ErrorMsg(this).showMsg(tr("Failed to stop wpa_supplicant "
1680 "service"));
1681 }
1682
1683 CloseServiceHandle(svc);
1684 CloseServiceHandle(scm);
1685 }
1686
1687
serviceRunning()1688 bool WpaGui::serviceRunning()
1689 {
1690 SC_HANDLE svc, scm;
1691 SERVICE_STATUS status;
1692 bool running = false;
1693
1694 scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
1695 if (!scm) {
1696 printf("OpenSCManager failed: %d\n", (int) GetLastError());
1697 return false;
1698 }
1699
1700 svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
1701 if (!svc) {
1702 printf("OpenService failed: %d\n\n", (int) GetLastError());
1703 CloseServiceHandle(scm);
1704 return false;
1705 }
1706
1707 if (QueryServiceStatus(svc, &status)) {
1708 if (status.dwCurrentState != SERVICE_STOPPED)
1709 running = true;
1710 }
1711
1712 CloseServiceHandle(svc);
1713 CloseServiceHandle(scm);
1714
1715 return running;
1716 }
1717
1718 #endif /* CONFIG_NATIVE_WINDOWS */
1719
1720
addInterface()1721 void WpaGui::addInterface()
1722 {
1723 if (add_iface) {
1724 add_iface->close();
1725 delete add_iface;
1726 }
1727 add_iface = new AddInterface(this, this);
1728 add_iface->show();
1729 add_iface->exec();
1730 }
1731
1732
1733 #ifndef QT_NO_SESSIONMANAGER
saveState()1734 void WpaGui::saveState()
1735 {
1736 QSettings settings("wpa_supplicant", "wpa_gui");
1737 settings.beginGroup("state");
1738 settings.setValue("session_id", app->sessionId());
1739 settings.setValue("in_tray", inTray);
1740 settings.endGroup();
1741 }
1742 #endif
1743