2
* wpa_gui - WpaGui class
3
* Copyright (c) 2005-2006, Jouni Malinen <jkmaline@cc.hut.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);
403
} else if (group_cipher) {
404
encr.append(group_cipher);
405
encr.append(" [group key only]");
409
textEncryption->setText(encr);
411
textEncryption->clear();
416
textAuthentication->clear();
422
textIpAddress->clear();
426
void WpaGui::updateNetworks()
428
char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
430
int first_active = -1;
431
bool selected = false;
433
if (!networkMayHaveChanged)
436
networkSelect->clear();
438
if (ctrl_conn == NULL)
441
len = sizeof(buf) - 1;
442
if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
446
start = strchr(buf, '\n');
453
end = strchr(start, '\n');
457
while (end[0] && end[1])
463
ssid = strchr(id, '\t');
467
bssid = strchr(ssid, '\t');
471
flags = strchr(bssid, '\t');
477
network.append(": ");
478
network.append(ssid);
479
networkSelect->insertItem(network);
481
if (strstr(flags, "[CURRENT]")) {
482
networkSelect->setCurrentItem(networkSelect->count() -
485
} else if (first_active < 0 &&
486
strstr(flags, "[DISABLED]") == NULL)
487
first_active = networkSelect->count() - 1;
494
if (!selected && first_active >= 0)
495
networkSelect->setCurrentItem(first_active);
497
networkMayHaveChanged = false;
501
void WpaGui::helpIndex()
503
printf("helpIndex\n");
507
void WpaGui::helpContents()
509
printf("helpContents\n");
513
void WpaGui::helpAbout()
515
QMessageBox::about(this, "wpa_gui for wpa_supplicant",
516
"Copyright (c) 2003-2006,\n"
517
"Jouni Malinen <jkmaline@cc.hut.fi>\n"
518
"and contributors.\n"
520
"This program is free software. You can\n"
521
"distribute it and/or modify it under the terms "
523
"the GNU General Public License version 2.\n"
525
"Alternatively, this software may be distributed\n"
526
"under the terms of the BSD license.\n"
528
"This product includes software developed\n"
529
"by the OpenSSL Project for use in the\n"
530
"OpenSSL Toolkit (http://www.openssl.org/)\n");
534
void WpaGui::disconnect()
537
size_t reply_len = sizeof(reply);
538
ctrlRequest("DISCONNECT", reply, &reply_len);
549
scanres = new ScanResults();
552
scanres->setWpaGui(this);
558
void WpaGui::eventHistory()
565
eh = new EventHistory();
579
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
581
* QSocketNotifier cannot be used with Windows named pipes, so use a
582
* timer to check for received messages for now. This could be
583
* optimized be doing something specific to named pipes or Windows
584
* events, but it is not clear what would be the best way of doing that
588
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
590
if (scanres && !scanres->isVisible()) {
595
if (eh && !eh->isVisible()) {
600
if (udr && !udr->isVisible()) {
605
len = sizeof(buf) - 1;
606
if (ctrlRequest("PING", buf, &len) < 0) {
607
printf("PING failed - trying to reconnect\n");
608
if (openCtrlConnection(ctrl_iface) >= 0) {
609
printf("Reconnected successfully\n");
610
pingsToStatusUpdate = 0;
614
pingsToStatusUpdate--;
615
if (pingsToStatusUpdate <= 0) {
622
static int str_match(const char *a, const char *b)
624
return strncmp(a, b, strlen(b)) == 0;
628
void WpaGui::processMsg(char *msg)
630
char *pos = msg, *pos2;
636
priority = atoi(pos);
637
pos = strchr(pos, '>');
644
WpaMsg wm(pos, priority);
648
while (msgs.count() > 100)
651
/* Update last message with truncated version of the event */
652
if (strncmp(pos, "CTRL-", 5) == 0) {
653
pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
660
QString lastmsg = pos2;
661
lastmsg.truncate(40);
662
textLastMessage->setText(lastmsg);
664
pingsToStatusUpdate = 0;
665
networkMayHaveChanged = true;
667
if (str_match(pos, WPA_CTRL_REQ))
668
processCtrlReq(pos + strlen(WPA_CTRL_REQ));
672
void WpaGui::processCtrlReq(const char *req)
678
udr = new UserDataRequest();
681
if (udr->setParams(this, req) < 0) {
691
void WpaGui::receiveMsgs()
696
while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
697
len = sizeof(buf) - 1;
698
if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
706
void WpaGui::connectB()
709
size_t reply_len = sizeof(reply);
710
ctrlRequest("REASSOCIATE", reply, &reply_len);
714
void WpaGui::selectNetwork( const QString &sel )
718
size_t reply_len = sizeof(reply);
720
int pos = cmd.find(':');
722
printf("Invalid selectNetwork '%s'\n", cmd.ascii());
726
cmd.prepend("SELECT_NETWORK ");
727
ctrlRequest(cmd.ascii(), reply, &reply_len);
731
void WpaGui::editNetwork()
733
QString sel(networkSelect->currentText());
734
int pos = sel.find(':');
736
printf("Invalid selectNetwork '%s'\n", sel.ascii());
741
NetworkConfig *nc = new NetworkConfig();
746
nc->paramsFromConfig(sel.toInt());
752
void WpaGui::triggerUpdate()
755
networkMayHaveChanged = true;
760
void WpaGui::addNetwork()
762
NetworkConfig *nc = new NetworkConfig();
772
void WpaGui::selectAdapter( const QString & sel )
774
if (openCtrlConnection(sel.ascii()) < 0)
775
printf("Failed to open control connection to "
776
"wpa_supplicant.\n");