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