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