2
* wpa_gui - WpaGui class
3
* Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
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.
9
* Alternatively, this software may be distributed under the terms of BSD
12
* See README and COPYING for more details.
16
/* Need to get getopt() */
20
#include <QMessageBox>
25
#include "userdatarequest.h"
26
#include "networkconfig.h"
28
WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags)
35
connect(helpIndexAction, SIGNAL(activated()), this, SLOT(helpIndex()));
36
connect(helpContentsAction, SIGNAL(activated()), this,
37
SLOT(helpContents()));
38
connect(helpAboutAction, SIGNAL(activated()), this, SLOT(helpAbout()));
39
connect(fileExitAction, SIGNAL(activated()), this, SLOT(close()));
40
connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));
41
connect(scanButton, SIGNAL(clicked()), this, SLOT(scan()));
42
connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB()));
43
connect(fileEventHistoryAction, SIGNAL(activated()), this,
44
SLOT(eventHistory()));
45
connect(networkSelect, SIGNAL(activated(const QString&)), this,
46
SLOT(selectNetwork(const QString&)));
47
connect(fileEdit_networkAction, SIGNAL(activated()), this,
49
connect(fileAdd_NetworkAction, SIGNAL(activated()), this,
51
connect(adapterSelect, SIGNAL(activated(const QString&)), this,
52
SLOT(selectAdapter(const QString&)));
61
ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
65
textStatus->setText("connecting to wpa_supplicant");
66
timer = new QTimer(this);
67
connect(timer, SIGNAL(timeout()), SLOT(ping()));
68
timer->start(1000, FALSE);
70
if (openCtrlConnection(ctrl_iface) < 0) {
71
printf("Failed to open control connection to "
76
networkMayHaveChanged = true;
86
wpa_ctrl_detach(monitor_conn);
87
wpa_ctrl_close(monitor_conn);
91
wpa_ctrl_close(ctrl_conn);
116
free(ctrl_iface_dir);
117
ctrl_iface_dir = NULL;
121
void WpaGui::languageChange()
127
void WpaGui::parse_argv()
131
c = getopt(qApp->argc(), qApp->argv(), "i:p:");
137
ctrl_iface = strdup(optarg);
140
free(ctrl_iface_dir);
141
ctrl_iface_dir = strdup(optarg);
148
int WpaGui::openCtrlConnection(const char *ifname)
152
char buf[2048], *pos, *pos2;
156
if (ifname != ctrl_iface) {
158
ctrl_iface = strdup(ifname);
161
#ifdef CONFIG_CTRL_IFACE_UDP
163
ctrl_iface = strdup("udp");
164
#endif /* CONFIG_CTRL_IFACE_UDP */
165
#ifdef CONFIG_CTRL_IFACE_UNIX
167
DIR *dir = opendir(ctrl_iface_dir);
171
while ((dent = readdir(dir))) {
172
#ifdef _DIRENT_HAVE_D_TYPE
173
/* Skip the file if it is not a socket.
174
* Also accept DT_UNKNOWN (0) in case
175
* the C library or underlying file
176
* system does not support d_type. */
177
if (dent->d_type != DT_SOCK &&
178
dent->d_type != DT_UNKNOWN)
180
#endif /* _DIRENT_HAVE_D_TYPE */
182
if (strcmp(dent->d_name, ".") == 0 ||
183
strcmp(dent->d_name, "..") == 0)
185
printf("Selected interface '%s'\n",
187
ctrl_iface = strdup(dent->d_name);
192
#endif /* CONFIG_CTRL_IFACE_UNIX */
193
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
194
struct wpa_ctrl *ctrl;
200
ctrl = wpa_ctrl_open(NULL);
202
len = sizeof(buf) - 1;
203
ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf,
207
pos = strchr(buf, '\n');
210
ctrl_iface = strdup(buf);
212
wpa_ctrl_close(ctrl);
214
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
217
if (ctrl_iface == NULL)
220
#ifdef CONFIG_CTRL_IFACE_UNIX
221
flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
222
cfile = (char *) malloc(flen);
225
snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
226
#else /* CONFIG_CTRL_IFACE_UNIX */
227
flen = strlen(ctrl_iface) + 1;
228
cfile = (char *) malloc(flen);
231
snprintf(cfile, flen, "%s", ctrl_iface);
232
#endif /* CONFIG_CTRL_IFACE_UNIX */
235
wpa_ctrl_close(ctrl_conn);
242
wpa_ctrl_detach(monitor_conn);
243
wpa_ctrl_close(monitor_conn);
247
printf("Trying to connect to '%s'\n", cfile);
248
ctrl_conn = wpa_ctrl_open(cfile);
249
if (ctrl_conn == NULL) {
253
monitor_conn = wpa_ctrl_open(cfile);
255
if (monitor_conn == NULL) {
256
wpa_ctrl_close(ctrl_conn);
259
if (wpa_ctrl_attach(monitor_conn)) {
260
printf("Failed to attach to wpa_supplicant\n");
261
wpa_ctrl_close(monitor_conn);
263
wpa_ctrl_close(ctrl_conn);
268
#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
269
msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
270
QSocketNotifier::Read, this);
271
connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
274
adapterSelect->clear();
275
adapterSelect->insertItem(ctrl_iface);
276
adapterSelect->setCurrentItem(0);
278
len = sizeof(buf) - 1;
279
if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
284
pos2 = strchr(pos, '\n');
287
if (strcmp(pos, ctrl_iface) != 0)
288
adapterSelect->insertItem(pos);
300
static void wpa_gui_msg_cb(char *msg, size_t)
302
/* This should not happen anymore since two control connections are
304
printf("missed message: %s\n", msg);
308
int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
312
if (ctrl_conn == NULL)
314
ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen,
317
printf("'%s' command timed out.\n", cmd);
319
printf("'%s' command failed.\n", cmd);
325
void WpaGui::updateStatus()
327
char buf[2048], *start, *end, *pos;
330
pingsToStatusUpdate = 10;
332
len = sizeof(buf) - 1;
333
if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
334
textStatus->setText("Could not get status from "
336
textAuthentication->clear();
337
textEncryption->clear();
340
textIpAddress->clear();
346
bool auth_updated = false, ssid_updated = false;
347
bool bssid_updated = false, ipaddr_updated = false;
348
bool status_updated = false;
349
char *pairwise_cipher = NULL, *group_cipher = NULL;
354
end = strchr(start, '\n');
358
while (end[0] && end[1])
363
pos = strchr(start, '=');
366
if (strcmp(start, "bssid") == 0) {
367
bssid_updated = true;
368
textBssid->setText(pos);
369
} else if (strcmp(start, "ssid") == 0) {
371
textSsid->setText(pos);
372
} else if (strcmp(start, "ip_address") == 0) {
373
ipaddr_updated = true;
374
textIpAddress->setText(pos);
375
} else if (strcmp(start, "wpa_state") == 0) {
376
status_updated = true;
377
textStatus->setText(pos);
378
} else if (strcmp(start, "key_mgmt") == 0) {
380
textAuthentication->setText(pos);
381
/* TODO: could add EAP status to this */
382
} else if (strcmp(start, "pairwise_cipher") == 0) {
383
pairwise_cipher = pos;
384
} else if (strcmp(start, "group_cipher") == 0) {
394
if (pairwise_cipher || group_cipher) {
396
if (pairwise_cipher && group_cipher &&
397
strcmp(pairwise_cipher, group_cipher) != 0) {
398
encr.append(pairwise_cipher);
400
encr.append(group_cipher);
401
} else if (pairwise_cipher) {
402
encr.append(pairwise_cipher);
404
encr.append(group_cipher);
405
encr.append(" [group key only]");
407
textEncryption->setText(encr);
409
textEncryption->clear();
414
textAuthentication->clear();
420
textIpAddress->clear();
424
void WpaGui::updateNetworks()
426
char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
428
int first_active = -1;
429
bool selected = false;
431
if (!networkMayHaveChanged)
434
networkSelect->clear();
436
if (ctrl_conn == NULL)
439
len = sizeof(buf) - 1;
440
if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
444
start = strchr(buf, '\n');
451
end = strchr(start, '\n');
455
while (end[0] && end[1])
461
ssid = strchr(id, '\t');
465
bssid = strchr(ssid, '\t');
469
flags = strchr(bssid, '\t');
475
network.append(": ");
476
network.append(ssid);
477
networkSelect->insertItem(network);
479
if (strstr(flags, "[CURRENT]")) {
480
networkSelect->setCurrentItem(networkSelect->count() -
483
} else if (first_active < 0 &&
484
strstr(flags, "[DISABLED]") == NULL)
485
first_active = networkSelect->count() - 1;
492
if (!selected && first_active >= 0)
493
networkSelect->setCurrentItem(first_active);
495
networkMayHaveChanged = false;
499
void WpaGui::helpIndex()
501
printf("helpIndex\n");
505
void WpaGui::helpContents()
507
printf("helpContents\n");
511
void WpaGui::helpAbout()
513
QMessageBox::about(this, "wpa_gui for wpa_supplicant",
514
"Copyright (c) 2003-2006,\n"
515
"Jouni Malinen <j@w1.fi>\n"
516
"and contributors.\n"
518
"This program is free software. You can\n"
519
"distribute it and/or modify it under the terms "
521
"the GNU General Public License version 2.\n"
523
"Alternatively, this software may be distributed\n"
524
"under the terms of the BSD license.\n"
526
"This product includes software developed\n"
527
"by the OpenSSL Project for use in the\n"
528
"OpenSSL Toolkit (http://www.openssl.org/)\n");
532
void WpaGui::disconnect()
535
size_t reply_len = sizeof(reply);
536
ctrlRequest("DISCONNECT", reply, &reply_len);
547
scanres = new ScanResults();
550
scanres->setWpaGui(this);
556
void WpaGui::eventHistory()
563
eh = new EventHistory();
577
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
579
* QSocketNotifier cannot be used with Windows named pipes, so use a
580
* timer to check for received messages for now. This could be
581
* optimized be doing something specific to named pipes or Windows
582
* events, but it is not clear what would be the best way of doing that
586
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
588
if (scanres && !scanres->isVisible()) {
593
if (eh && !eh->isVisible()) {
598
if (udr && !udr->isVisible()) {
603
len = sizeof(buf) - 1;
604
if (ctrlRequest("PING", buf, &len) < 0) {
605
printf("PING failed - trying to reconnect\n");
606
if (openCtrlConnection(ctrl_iface) >= 0) {
607
printf("Reconnected successfully\n");
608
pingsToStatusUpdate = 0;
612
pingsToStatusUpdate--;
613
if (pingsToStatusUpdate <= 0) {
620
static int str_match(const char *a, const char *b)
622
return strncmp(a, b, strlen(b)) == 0;
626
void WpaGui::processMsg(char *msg)
628
char *pos = msg, *pos2;
634
priority = atoi(pos);
635
pos = strchr(pos, '>');
642
WpaMsg wm(pos, priority);
646
while (msgs.count() > 100)
649
/* Update last message with truncated version of the event */
650
if (strncmp(pos, "CTRL-", 5) == 0) {
651
pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
658
QString lastmsg = pos2;
659
lastmsg.truncate(40);
660
textLastMessage->setText(lastmsg);
662
pingsToStatusUpdate = 0;
663
networkMayHaveChanged = true;
665
if (str_match(pos, WPA_CTRL_REQ))
666
processCtrlReq(pos + strlen(WPA_CTRL_REQ));
670
void WpaGui::processCtrlReq(const char *req)
676
udr = new UserDataRequest();
679
if (udr->setParams(this, req) < 0) {
689
void WpaGui::receiveMsgs()
694
while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
695
len = sizeof(buf) - 1;
696
if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
704
void WpaGui::connectB()
707
size_t reply_len = sizeof(reply);
708
ctrlRequest("REASSOCIATE", reply, &reply_len);
712
void WpaGui::selectNetwork( const QString &sel )
716
size_t reply_len = sizeof(reply);
718
int pos = cmd.find(':');
720
printf("Invalid selectNetwork '%s'\n", cmd.ascii());
724
cmd.prepend("SELECT_NETWORK ");
725
ctrlRequest(cmd.ascii(), reply, &reply_len);
729
void WpaGui::editNetwork()
731
QString sel(networkSelect->currentText());
732
int pos = sel.find(':');
734
printf("Invalid selectNetwork '%s'\n", sel.ascii());
739
NetworkConfig *nc = new NetworkConfig();
744
nc->paramsFromConfig(sel.toInt());
750
void WpaGui::triggerUpdate()
753
networkMayHaveChanged = true;
758
void WpaGui::addNetwork()
760
NetworkConfig *nc = new NetworkConfig();
770
void WpaGui::selectAdapter( const QString & sel )
772
if (openCtrlConnection(sel.ascii()) < 0)
773
printf("Failed to open control connection to "
774
"wpa_supplicant.\n");