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