00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifdef __MINGW32__
00015
00016 #include <unistd.h>
00017 #endif
00018
00019 #include <stdlib.h>
00020
00021 void WpaGui::init()
00022 {
00023 eh = NULL;
00024 scanres = NULL;
00025 udr = NULL;
00026 ctrl_iface = NULL;
00027 ctrl_conn = NULL;
00028 monitor_conn = NULL;
00029 msgNotifier = NULL;
00030 ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
00031
00032 parse_argv();
00033
00034 textStatus->setText("connecting to wpa_supplicant");
00035 timer = new QTimer(this);
00036 connect(timer, SIGNAL(timeout()), SLOT(ping()));
00037 timer->start(1000, FALSE);
00038
00039 if (openCtrlConnection(ctrl_iface) < 0) {
00040 printf("Failed to open control connection to wpa_supplicant.\n");
00041 }
00042
00043 updateStatus();
00044 networkMayHaveChanged = true;
00045 updateNetworks();
00046 }
00047
00048
00049 void WpaGui::destroy()
00050 {
00051 delete msgNotifier;
00052
00053 if (monitor_conn) {
00054 wpa_ctrl_detach(monitor_conn);
00055 wpa_ctrl_close(monitor_conn);
00056 monitor_conn = NULL;
00057 }
00058 if (ctrl_conn) {
00059 wpa_ctrl_close(ctrl_conn);
00060 ctrl_conn = NULL;
00061 }
00062
00063 if (eh) {
00064 eh->close();
00065 delete eh;
00066 eh = NULL;
00067 }
00068
00069 if (scanres) {
00070 scanres->close();
00071 delete scanres;
00072 scanres = NULL;
00073 }
00074
00075 if (udr) {
00076 udr->close();
00077 delete udr;
00078 udr = NULL;
00079 }
00080
00081 free(ctrl_iface);
00082 ctrl_iface = NULL;
00083
00084 free(ctrl_iface_dir);
00085 ctrl_iface_dir = NULL;
00086 }
00087
00088
00089 void WpaGui::parse_argv()
00090 {
00091 int c;
00092 for (;;) {
00093 c = getopt(qApp->argc(), qApp->argv(), "i:p:");
00094 if (c < 0)
00095 break;
00096 switch (c) {
00097 case 'i':
00098 free(ctrl_iface);
00099 ctrl_iface = strdup(optarg);
00100 break;
00101 case 'p':
00102 free(ctrl_iface_dir);
00103 ctrl_iface_dir = strdup(optarg);
00104 break;
00105 }
00106 }
00107 }
00108
00109
00110 int WpaGui::openCtrlConnection(const char *ifname)
00111 {
00112 char *cfile;
00113 int flen;
00114 char buf[2048], *pos, *pos2;
00115 size_t len;
00116
00117 if (ifname) {
00118 if (ifname != ctrl_iface) {
00119 free(ctrl_iface);
00120 ctrl_iface = strdup(ifname);
00121 }
00122 } else {
00123 #ifdef CONFIG_CTRL_IFACE_UDP
00124 free(ctrl_iface);
00125 ctrl_iface = strdup("udp");
00126 #endif
00127 #ifdef CONFIG_CTRL_IFACE_UNIX
00128 struct dirent *dent;
00129 DIR *dir = opendir(ctrl_iface_dir);
00130 free(ctrl_iface);
00131 ctrl_iface = NULL;
00132 if (dir) {
00133 while ((dent = readdir(dir))) {
00134 #ifdef _DIRENT_HAVE_D_TYPE
00135
00136
00137
00138
00139 if (dent->d_type != DT_SOCK &&
00140 dent->d_type != DT_UNKNOWN)
00141 continue;
00142 #endif
00143
00144 if (strcmp(dent->d_name, ".") == 0 ||
00145 strcmp(dent->d_name, "..") == 0)
00146 continue;
00147 printf("Selected interface '%s'\n", dent->d_name);
00148 ctrl_iface = strdup(dent->d_name);
00149 break;
00150 }
00151 closedir(dir);
00152 }
00153 #endif
00154 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
00155 struct wpa_ctrl *ctrl;
00156 int ret;
00157
00158 free(ctrl_iface);
00159 ctrl_iface = NULL;
00160
00161 ctrl = wpa_ctrl_open(NULL);
00162 if (ctrl) {
00163 len = sizeof(buf) - 1;
00164 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
00165 if (ret >= 0) {
00166 buf[len] = '\0';
00167 pos = strchr(buf, '\n');
00168 if (pos)
00169 *pos = '\0';
00170 ctrl_iface = strdup(buf);
00171 }
00172 wpa_ctrl_close(ctrl);
00173 }
00174 #endif
00175 }
00176
00177 if (ctrl_iface == NULL)
00178 return -1;
00179
00180 #ifdef CONFIG_CTRL_IFACE_UNIX
00181 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
00182 cfile = (char *) malloc(flen);
00183 if (cfile == NULL)
00184 return -1;
00185 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
00186 #else
00187 flen = strlen(ctrl_iface) + 1;
00188 cfile = (char *) malloc(flen);
00189 if (cfile == NULL)
00190 return -1;
00191 snprintf(cfile, flen, "%s", ctrl_iface);
00192 #endif
00193
00194 if (ctrl_conn) {
00195 wpa_ctrl_close(ctrl_conn);
00196 ctrl_conn = NULL;
00197 }
00198
00199 if (monitor_conn) {
00200 delete msgNotifier;
00201 msgNotifier = NULL;
00202 wpa_ctrl_detach(monitor_conn);
00203 wpa_ctrl_close(monitor_conn);
00204 monitor_conn = NULL;
00205 }
00206
00207 printf("Trying to connect to '%s'\n", cfile);
00208 ctrl_conn = wpa_ctrl_open(cfile);
00209 if (ctrl_conn == NULL) {
00210 free(cfile);
00211 return -1;
00212 }
00213 monitor_conn = wpa_ctrl_open(cfile);
00214 free(cfile);
00215 if (monitor_conn == NULL) {
00216 wpa_ctrl_close(ctrl_conn);
00217 return -1;
00218 }
00219 if (wpa_ctrl_attach(monitor_conn)) {
00220 printf("Failed to attach to wpa_supplicant\n");
00221 wpa_ctrl_close(monitor_conn);
00222 monitor_conn = NULL;
00223 wpa_ctrl_close(ctrl_conn);
00224 ctrl_conn = NULL;
00225 return -1;
00226 }
00227
00228 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
00229 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
00230 QSocketNotifier::Read, this);
00231 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
00232 #endif
00233
00234 adapterSelect->clear();
00235 adapterSelect->insertItem(ctrl_iface);
00236 adapterSelect->setCurrentItem(0);
00237
00238 len = sizeof(buf) - 1;
00239 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >= 0) {
00240 buf[len] = '\0';
00241 pos = buf;
00242 while (*pos) {
00243 pos2 = strchr(pos, '\n');
00244 if (pos2)
00245 *pos2 = '\0';
00246 if (strcmp(pos, ctrl_iface) != 0)
00247 adapterSelect->insertItem(pos);
00248 if (pos2)
00249 pos = pos2 + 1;
00250 else
00251 break;
00252 }
00253 }
00254
00255 return 0;
00256 }
00257
00258
00259 static void wpa_gui_msg_cb(char *msg, size_t)
00260 {
00261
00262 printf("missed message: %s\n", msg);
00263 }
00264
00265
00266 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
00267 {
00268 int ret;
00269
00270 if (ctrl_conn == NULL)
00271 return -3;
00272 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen,
00273 wpa_gui_msg_cb);
00274 if (ret == -2) {
00275 printf("'%s' command timed out.\n", cmd);
00276 } else if (ret < 0) {
00277 printf("'%s' command failed.\n", cmd);
00278 }
00279
00280 return ret;
00281 }
00282
00283
00284 void WpaGui::updateStatus()
00285 {
00286 char buf[2048], *start, *end, *pos;
00287 size_t len;
00288
00289 pingsToStatusUpdate = 10;
00290
00291 len = sizeof(buf) - 1;
00292 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
00293 textStatus->setText("Could not get status from wpa_supplicant");
00294 textAuthentication->clear();
00295 textEncryption->clear();
00296 textSsid->clear();
00297 textBssid->clear();
00298 textIpAddress->clear();
00299 return;
00300 }
00301
00302 buf[len] = '\0';
00303
00304 bool auth_updated = false, ssid_updated = false;
00305 bool bssid_updated = false, ipaddr_updated = false;
00306 bool status_updated = false;
00307 char *pairwise_cipher = NULL, *group_cipher = NULL;
00308
00309 start = buf;
00310 while (*start) {
00311 bool last = false;
00312 end = strchr(start, '\n');
00313 if (end == NULL) {
00314 last = true;
00315 end = start;
00316 while (end[0] && end[1])
00317 end++;
00318 }
00319 *end = '\0';
00320
00321 pos = strchr(start, '=');
00322 if (pos) {
00323 *pos++ = '\0';
00324 if (strcmp(start, "bssid") == 0) {
00325 bssid_updated = true;
00326 textBssid->setText(pos);
00327 } else if (strcmp(start, "ssid") == 0) {
00328 ssid_updated = true;
00329 textSsid->setText(pos);
00330 } else if (strcmp(start, "ip_address") == 0) {
00331 ipaddr_updated = true;
00332 textIpAddress->setText(pos);
00333 } else if (strcmp(start, "wpa_state") == 0) {
00334 status_updated = true;
00335 textStatus->setText(pos);
00336 } else if (strcmp(start, "key_mgmt") == 0) {
00337 auth_updated = true;
00338 textAuthentication->setText(pos);
00339
00340 } else if (strcmp(start, "pairwise_cipher") == 0) {
00341 pairwise_cipher = pos;
00342 } else if (strcmp(start, "group_cipher") == 0) {
00343 group_cipher = pos;
00344 }
00345 }
00346
00347 if (last)
00348 break;
00349 start = end + 1;
00350 }
00351
00352 if (pairwise_cipher || group_cipher) {
00353 QString encr;
00354 if (pairwise_cipher && group_cipher &&
00355 strcmp(pairwise_cipher, group_cipher) != 0) {
00356 encr.append(pairwise_cipher);
00357 encr.append(" + ");
00358 encr.append(group_cipher);
00359 } else if (pairwise_cipher) {
00360 encr.append(pairwise_cipher);
00361 } else {
00362 encr.append(group_cipher);
00363 encr.append(" [group key only]");
00364 }
00365 textEncryption->setText(encr);
00366 } else
00367 textEncryption->clear();
00368
00369 if (!status_updated)
00370 textStatus->clear();
00371 if (!auth_updated)
00372 textAuthentication->clear();
00373 if (!ssid_updated)
00374 textSsid->clear();
00375 if (!bssid_updated)
00376 textBssid->clear();
00377 if (!ipaddr_updated)
00378 textIpAddress->clear();
00379 }
00380
00381
00382 void WpaGui::updateNetworks()
00383 {
00384 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
00385 size_t len;
00386 int first_active = -1;
00387 bool selected = false;
00388
00389 if (!networkMayHaveChanged)
00390 return;
00391
00392 networkSelect->clear();
00393
00394 if (ctrl_conn == NULL)
00395 return;
00396
00397 len = sizeof(buf) - 1;
00398 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
00399 return;
00400
00401 buf[len] = '\0';
00402 start = strchr(buf, '\n');
00403 if (start == NULL)
00404 return;
00405 start++;
00406
00407 while (*start) {
00408 bool last = false;
00409 end = strchr(start, '\n');
00410 if (end == NULL) {
00411 last = true;
00412 end = start;
00413 while (end[0] && end[1])
00414 end++;
00415 }
00416 *end = '\0';
00417
00418 id = start;
00419 ssid = strchr(id, '\t');
00420 if (ssid == NULL)
00421 break;
00422 *ssid++ = '\0';
00423 bssid = strchr(ssid, '\t');
00424 if (bssid == NULL)
00425 break;
00426 *bssid++ = '\0';
00427 flags = strchr(bssid, '\t');
00428 if (flags == NULL)
00429 break;
00430 *flags++ = '\0';
00431
00432 QString network(id);
00433 network.append(": ");
00434 network.append(ssid);
00435 networkSelect->insertItem(network);
00436
00437 if (strstr(flags, "[CURRENT]")) {
00438 networkSelect->setCurrentItem(networkSelect->count() - 1);
00439 selected = true;
00440 } else if (first_active < 0 && strstr(flags, "[DISABLED]") == NULL)
00441 first_active = networkSelect->count() - 1;
00442
00443 if (last)
00444 break;
00445 start = end + 1;
00446 }
00447
00448 if (!selected && first_active >= 0)
00449 networkSelect->setCurrentItem(first_active);
00450
00451 networkMayHaveChanged = false;
00452 }
00453
00454
00455 void WpaGui::helpIndex()
00456 {
00457 printf("helpIndex\n");
00458 }
00459
00460
00461 void WpaGui::helpContents()
00462 {
00463 printf("helpContents\n");
00464 }
00465
00466
00467 void WpaGui::helpAbout()
00468 {
00469 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
00470 "Copyright (c) 2003-2008,\n"
00471 "Jouni Malinen <j@w1.fi>\n"
00472 "and contributors.\n"
00473 "\n"
00474 "This program is free software. You can\n"
00475 "distribute it and/or modify it under the terms of\n"
00476 "the GNU General Public License version 2.\n"
00477 "\n"
00478 "Alternatively, this software may be distributed\n"
00479 "under the terms of the BSD license.\n"
00480 "\n"
00481 "This product includes software developed\n"
00482 "by the OpenSSL Project for use in the\n"
00483 "OpenSSL Toolkit (http://www.openssl.org/)\n");
00484 }
00485
00486
00487 void WpaGui::disconnect()
00488 {
00489 char reply[10];
00490 size_t reply_len = sizeof(reply);
00491 ctrlRequest("DISCONNECT", reply, &reply_len);
00492 }
00493
00494
00495 void WpaGui::scan()
00496 {
00497 if (scanres) {
00498 scanres->close();
00499 delete scanres;
00500 }
00501
00502 scanres = new ScanResults();
00503 if (scanres == NULL)
00504 return;
00505 scanres->setWpaGui(this);
00506 scanres->show();
00507 scanres->exec();
00508 }
00509
00510
00511 void WpaGui::eventHistory()
00512 {
00513 if (eh) {
00514 eh->close();
00515 delete eh;
00516 }
00517
00518 eh = new EventHistory();
00519 if (eh == NULL)
00520 return;
00521 eh->addEvents(msgs);
00522 eh->show();
00523 eh->exec();
00524 }
00525
00526
00527 void WpaGui::ping()
00528 {
00529 char buf[10];
00530 size_t len;
00531
00532 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
00533
00534
00535
00536
00537
00538
00539 receiveMsgs();
00540 #endif
00541
00542 if (scanres && !scanres->isVisible()) {
00543 delete scanres;
00544 scanres = NULL;
00545 }
00546
00547 if (eh && !eh->isVisible()) {
00548 delete eh;
00549 eh = NULL;
00550 }
00551
00552 if (udr && !udr->isVisible()) {
00553 delete udr;
00554 udr = NULL;
00555 }
00556
00557 len = sizeof(buf) - 1;
00558 if (ctrlRequest("PING", buf, &len) < 0) {
00559 printf("PING failed - trying to reconnect\n");
00560 if (openCtrlConnection(ctrl_iface) >= 0) {
00561 printf("Reconnected successfully\n");
00562 pingsToStatusUpdate = 0;
00563 }
00564 }
00565
00566 pingsToStatusUpdate--;
00567 if (pingsToStatusUpdate <= 0) {
00568 updateStatus();
00569 updateNetworks();
00570 }
00571 }
00572
00573
00574 static int str_match(const char *a, const char *b)
00575 {
00576 return strncmp(a, b, strlen(b)) == 0;
00577 }
00578
00579
00580 void WpaGui::processMsg(char *msg)
00581 {
00582 char *pos = msg, *pos2;
00583 int priority = 2;
00584
00585 if (*pos == '<') {
00586
00587 pos++;
00588 priority = atoi(pos);
00589 pos = strchr(pos, '>');
00590 if (pos)
00591 pos++;
00592 else
00593 pos = msg;
00594 }
00595
00596 WpaMsg wm(pos, priority);
00597 if (eh)
00598 eh->addEvent(wm);
00599 msgs.append(wm);
00600 while (msgs.count() > 100)
00601 msgs.pop_front();
00602
00603
00604 if (strncmp(pos, "CTRL-", 5) == 0) {
00605 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
00606 if (pos2)
00607 pos2++;
00608 else
00609 pos2 = pos;
00610 } else
00611 pos2 = pos;
00612 QString lastmsg = pos2;
00613 lastmsg.truncate(40);
00614 textLastMessage->setText(lastmsg);
00615
00616 pingsToStatusUpdate = 0;
00617 networkMayHaveChanged = true;
00618
00619 if (str_match(pos, WPA_CTRL_REQ))
00620 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
00621 }
00622
00623
00624 void WpaGui::processCtrlReq(const char *req)
00625 {
00626 if (udr) {
00627 udr->close();
00628 delete udr;
00629 }
00630 udr = new UserDataRequest();
00631 if (udr == NULL)
00632 return;
00633 if (udr->setParams(this, req) < 0) {
00634 delete udr;
00635 udr = NULL;
00636 return;
00637 }
00638 udr->show();
00639 udr->exec();
00640 }
00641
00642
00643 void WpaGui::receiveMsgs()
00644 {
00645 char buf[256];
00646 size_t len;
00647
00648 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
00649 len = sizeof(buf) - 1;
00650 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
00651 buf[len] = '\0';
00652 processMsg(buf);
00653 }
00654 }
00655 }
00656
00657
00658 void WpaGui::connectB()
00659 {
00660 char reply[10];
00661 size_t reply_len = sizeof(reply);
00662 ctrlRequest("REASSOCIATE", reply, &reply_len);
00663 }
00664
00665
00666 void WpaGui::selectNetwork( const QString &sel )
00667 {
00668 QString cmd(sel);
00669 char reply[10];
00670 size_t reply_len = sizeof(reply);
00671
00672 int pos = cmd.find(':');
00673 if (pos < 0) {
00674 printf("Invalid selectNetwork '%s'\n", cmd.ascii());
00675 return;
00676 }
00677 cmd.truncate(pos);
00678 cmd.prepend("SELECT_NETWORK ");
00679 ctrlRequest(cmd.ascii(), reply, &reply_len);
00680 }
00681
00682
00683 void WpaGui::editNetwork()
00684 {
00685 QString sel(networkSelect->currentText());
00686 int pos = sel.find(':');
00687 if (pos < 0) {
00688 printf("Invalid selectNetwork '%s'\n", sel.ascii());
00689 return;
00690 }
00691 sel.truncate(pos);
00692
00693 NetworkConfig *nc = new NetworkConfig();
00694 if (nc == NULL)
00695 return;
00696 nc->setWpaGui(this);
00697
00698 nc->paramsFromConfig(sel.toInt());
00699 nc->show();
00700 nc->exec();
00701 }
00702
00703
00704 void WpaGui::triggerUpdate()
00705 {
00706 updateStatus();
00707 networkMayHaveChanged = true;
00708 updateNetworks();
00709 }
00710
00711
00712 void WpaGui::addNetwork()
00713 {
00714 NetworkConfig *nc = new NetworkConfig();
00715 if (nc == NULL)
00716 return;
00717 nc->setWpaGui(this);
00718 nc->newNetwork();
00719 nc->show();
00720 nc->exec();
00721 }
00722
00723
00724 void WpaGui::selectAdapter( const QString & sel )
00725 {
00726 if (openCtrlConnection(sel.ascii()) < 0)
00727 printf("Failed to open control connection to wpa_supplicant.\n");
00728 updateStatus();
00729 updateNetworks();
00730 }