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