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