• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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