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