$search
00001 /**************************************************************************** 00002 ** ui.h extension file, included from the uic-generated form implementation. 00003 ** 00004 ** If you want to add, delete, or rename functions or slots, use 00005 ** Qt Designer to update this file, preserving your code. 00006 ** 00007 ** You should not define a constructor or destructor in this file. 00008 ** Instead, write your code in functions called init() and destroy(). 00009 ** These will automatically be called by the form's constructor and 00010 ** destructor. 00011 *****************************************************************************/ 00012 00013 00014 #ifdef __MINGW32__ 00015 /* Need to get getopt() */ 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 /* CONFIG_CTRL_IFACE_UDP */ 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 /* Skip the file if it is not a socket. 00136 * Also accept DT_UNKNOWN (0) in case 00137 * the C library or underlying file 00138 * system does not support d_type. */ 00139 if (dent->d_type != DT_SOCK && 00140 dent->d_type != DT_UNKNOWN) 00141 continue; 00142 #endif /* _DIRENT_HAVE_D_TYPE */ 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 /* CONFIG_CTRL_IFACE_UNIX */ 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 /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 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 /* CONFIG_CTRL_IFACE_UNIX */ 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 /* CONFIG_CTRL_IFACE_UNIX */ 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 /* This should not happen anymore since two control connections are used. */ 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 /* TODO: could add EAP status to this */ 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 * QSocketNotifier cannot be used with Windows named pipes, so use a timer 00535 * to check for received messages for now. This could be optimized be doing 00536 * something specific to named pipes or Windows events, but it is not clear 00537 * what would be the best way of doing that in Qt. 00538 */ 00539 receiveMsgs(); 00540 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 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 /* skip priority */ 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 /* Update last message with truncated version of the event */ 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 }