/*************************************************************************** interface_wireless_wirelessextensions.cpp - description ------------------- begin : Sun May 6 2001 copyright : (C) 2001 by Stefan Winter email : mail@stefan-winter.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "interface_wireless_wirelessextensions.h" #include #include #include #include #include #ifndef WITHOUT_ARTS #include #include #include #include #endif #ifndef PROC_NET_DEV #define PROC_NET_DEV "/proc/net/dev" #endif #include #include #include #include #include #include #include #include #include #include #include // domi:the wireless-tools people managed to change their interfaces // around. Someone with more knowledge of this code should look into // moving to use the new iw_range interfaces. #ifdef HAVE_IW_27 #ifndef HAVE_IW_27pre19 #define WIFI_CONFIG(config,field) config.field #define WIFI_EXTRACT_EVENT_STREAM(stream, event) \ iw_extract_event_stream(stream, event) #else #define WIFI_CONFIG(config,field) config.b.field #define WIFI_EXTRACT_EVENT_STREAM(stream, event) \ iw_extract_event_stream(stream, event, WIRELESS_EXT) #endif #define WIFI_GET_STATS(skfd, ifname, stats) \ iw_get_stats (skfd, ifname, stats, 0, 0) #define WIFI_PRINT_STATS(buff, event) \ iw_print_stats(buffer, sizeof(buffer), &event->u.qual, 0, 0); #else // HAVE_IW_25 #define WIFI_CONFIG(config,field) config.field #define WIFI_EXTRACT_EVENT_STREAM(stream, event) \ iw_extract_event_stream(stream, event) #define WIFI_GET_STATS(skfd, ifname, stats) \ iw_get_stats (skfd, ifname, stats) #define WIFI_PRINT_STATS(buff, event) \ iw_print_stats(buffer, &event->u.qual, 0, 0); #endif /* ================================== FROM IWCONFIG.C ================================== */ int Interface_wireless_wirelessextensions::get_info (int skfd, const TQString& interface, struct wireless_info& info) { struct iwreq wrq; char ifname[20]; snprintf(ifname, sizeof(ifname), "%s", interface.latin1() ); memset (&info, 0, sizeof(info)); /* Get wireless name */ if (iw_get_ext (skfd, ifname, SIOCGIWNAME, &wrq) < 0) { /* If no wireless name : no wireless extensions */ /* But let's check if the interface exists at all */ struct ifreq ifr; strcpy (ifr.ifr_name, ifname); if (ioctl (skfd, SIOCGIFFLAGS, &ifr) < 0) return (-ENODEV); else return (-ENOTSUP); } else { strncpy (WIFI_CONFIG(info,name), wrq.u.name, IFNAMSIZ); WIFI_CONFIG(info,name)[IFNAMSIZ] = '\0'; } /* Get ranges */ if (iw_get_range_info (skfd, ifname, &(info.range)) >= 0) info.has_range = 1; /* Get network ID */ if (iw_get_ext (skfd, ifname, SIOCGIWNWID, &wrq) >= 0) { WIFI_CONFIG(info,has_nwid) = 1; memcpy (&(WIFI_CONFIG(info,nwid)), &(wrq.u.nwid), sizeof (iwparam)); } /* Get frequency / channel */ if (iw_get_ext (skfd, ifname, SIOCGIWFREQ, &wrq) >= 0) { WIFI_CONFIG(info,has_freq) = 1; WIFI_CONFIG(info,freq) = iw_freq2float (&(wrq.u.freq)); } /* Get sensitivity */ if (iw_get_ext (skfd, ifname, SIOCGIWSENS, &wrq) >= 0) { info.has_sens = 1; memcpy (&(info.sens), &(wrq.u.sens), sizeof (iwparam)); } /* Get encryption information */ wrq.u.data.pointer = (caddr_t) WIFI_CONFIG(info,key); wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; if (iw_get_ext (skfd, ifname, SIOCGIWENCODE, &wrq) >= 0) { WIFI_CONFIG(info,has_key) = 1; WIFI_CONFIG(info,key_size) = wrq.u.data.length; WIFI_CONFIG(info,key_flags) = wrq.u.data.flags; } /* Get ESSID */ /* prepare NULL-terminated buffer in case the string returned by SIOCGIWESSID is NOT NULL-terminated */ memset(wrq.u.essid.pointer, '\0', IW_ESSID_MAX_SIZE + 1); wrq.u.essid.pointer = (caddr_t) WIFI_CONFIG(info,essid); wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; wrq.u.essid.flags = 0; if (iw_get_ext (skfd, ifname, SIOCGIWESSID, &wrq) >= 0) { WIFI_CONFIG(info,has_essid) = 1; WIFI_CONFIG(info,essid_on) = wrq.u.data.flags; } /* Get AP address */ if (iw_get_ext (skfd, ifname, SIOCGIWAP, &wrq) >= 0) { info.has_ap_addr = 1; memcpy (&(info.ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr)); } /* Get NickName */ wrq.u.essid.pointer = (caddr_t) info.nickname; wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; wrq.u.essid.flags = 0; if (iw_get_ext (skfd, ifname, SIOCGIWNICKN, &wrq) >= 0) if (wrq.u.data.length > 1) info.has_nickname = 1; /* Get bit rate */ if (iw_get_ext (skfd, ifname, SIOCGIWRATE, &wrq) >= 0) { info.has_bitrate = 1; memcpy (&(info.bitrate), &(wrq.u.bitrate), sizeof (iwparam)); } /* Get RTS threshold */ if (iw_get_ext (skfd, ifname, SIOCGIWRTS, &wrq) >= 0) { info.has_rts = 1; memcpy (&(info.rts), &(wrq.u.rts), sizeof (iwparam)); } /* Get fragmentation threshold */ if (iw_get_ext (skfd, ifname, SIOCGIWFRAG, &wrq) >= 0) { info.has_frag = 1; memcpy (&(info.frag), &(wrq.u.frag), sizeof (iwparam)); } /* Get operation mode */ if (iw_get_ext (skfd, ifname, SIOCGIWMODE, &wrq) >= 0) { WIFI_CONFIG(info,mode) = wrq.u.mode; if ((WIFI_CONFIG(info,mode) < IW_NUM_OPER_MODE) && (WIFI_CONFIG(info,mode) >= 0)) WIFI_CONFIG(info,has_mode) = 1; } /* Get Power Management settings */ wrq.u.power.flags = 0; if (iw_get_ext (skfd, ifname, SIOCGIWPOWER, &wrq) >= 0) { info.has_power = 1; memcpy (&(info.power), &(wrq.u.power), sizeof (iwparam)); } #if WIRELESS_EXT > 9 /* Get Transmit Power and check if it is disabled */ bool emitTXPowerChanged = false; if (iw_get_ext (skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0) { if (txpower_disabled != info.txpower.disabled) { emitTXPowerChanged = true; } info.has_txpower = 1; memcpy (&(info.txpower), &(wrq.u.txpower), sizeof (iwparam)); } has_txpower = info.has_txpower; txpower_disabled = ( int )info.txpower.disabled; if (emitTXPowerChanged) { emit txPowerChanged(); } #endif #if WIRELESS_EXT > 10 /* Get retry limit/lifetime */ if (iw_get_ext (skfd, ifname, SIOCGIWRETRY, &wrq) >= 0) { info.has_retry = 1; memcpy (&(info.retry), &(wrq.u.retry), sizeof (iwparam)); } #endif /* WIRELESS_EXT > 10 */ /* Get stats */ if (WIFI_GET_STATS (skfd, (char *) ifname, &(info.stats)) >= 0) { info.has_stats = 1; } return (0); } /* ================================ END IWCONFIG.C ================================ */ Interface_wireless_wirelessextensions::Interface_wireless_wirelessextensions (TQStringList * ignoreInterfaces) : Interface_wireless(ignoreInterfaces) { } bool Interface_wireless_wirelessextensions::isSocketOpen() { if (socket <= 0) socket = iw_sockets_open (); return (socket > 0); } void Interface_wireless_wirelessextensions::setActiveDevice( TQString device ) { kdDebug () << "activating wireless device " << device << endl; interface_name = device; if (!isSocketOpen()) return; emit interfaceChanged (); emit strengthChanged (); emit statusChanged (); emit modeChanged (); emit speedChanged (); valid[current] = false; emit statsUpdated (); } void Interface_wireless_wirelessextensions::setNoActiveDevice( ) { // interface has disappeared - unplugged? // reset all info except stats has_frequency = false; frequency = 0.0; has_mode = false; mode = 0; has_key = 0; key = TQString(); key_size = 0; key_flags = 0; essid = TQString(); access_point_address = TQString(); ip_address = TQString(); bitrate = 0; has_range = false; has_txpower = false; txpower_disabled = 0; // propagate the changes setActiveDevice( TQString() ); } TQStringList Interface_wireless_wirelessextensions::available_wifi_devices() { TQFile procnetdev(PROC_NET_DEV); procnetdev.open (IO_ReadOnly); kdDebug () << "Autodetecting..." << endl; TQStringList liste; TQString device; while (!procnetdev.atEnd()) { procnetdev.readLine (device, 9999); int pos = device.find (':'); if (pos == -1) continue; device = device.left(pos).stripWhiteSpace(); if (device.isEmpty()) continue; // Some drivers create two interfaces, ethX and wifiX. The // wifiX device are not useful to users because they only // control the physical wlan settings, not the logical ones. If // we find a wifiX device then we move it to the start of the // list which means the first instance of KWifiManger will pick // up the ethX and only the second instance will pick up the // wifiX. if (device.startsWith("wifi")) liste.prepend(device); else liste.append(device); } if (liste.isEmpty()) kdDebug () << "No wireless interface found." << endl; return liste; } bool Interface_wireless_wirelessextensions::autodetect_device() { if (!isSocketOpen()) return false; TQStringList liste = available_wifi_devices(); for (TQStringList::Iterator it = liste.begin (); it != liste.end (); ++it) { TQString device = *it; kdDebug () << "[ " << device << " ] " << endl; wireless_info info; int result = get_info (socket, device, info); if ((result != -ENODEV) && (result != -ENOTSUP) && (!ignoreInterfaces || ignoreInterfaces->findIndex(device)==-1)) { setActiveDevice(device); } } if (interface_name.isEmpty()) { close(socket); socket = -1; return false; } return true; } bool Interface_wireless_wirelessextensions::poll_device_info () { if (current < MAX_HISTORY-1) ++current; else current = 0; if (interface_name.isEmpty()) if (!autodetect_device()) return false; wireless_info info; int result = get_info (socket, interface_name, info); if ((result == -ENODEV) || (result == -ENOTSUP)) { // interface has disappeared - unplugged? // reset all info except stats setNoActiveDevice(); close(socket); socket = -1; return false; } bool emitStatusChanged = false, emitModeChanged = false, emitEssidChanged = false, emitSpeedChanged = false, emitStrengthChanged = false; iwstats tempic2; WIFI_GET_STATS (socket, (char *) interface_name.latin1(), &tempic2); has_frequency = WIFI_CONFIG(info,has_freq); if (has_frequency) { if (frequency != WIFI_CONFIG(info,freq)) emitStatusChanged = true; frequency = WIFI_CONFIG(info,freq); } has_mode = WIFI_CONFIG(info,has_mode); if (has_mode) { if (mode != WIFI_CONFIG(info,mode)) emitModeChanged = true; mode = WIFI_CONFIG(info,mode); } has_key = WIFI_CONFIG(info,has_key); if (has_key) { if ((key != (char *) WIFI_CONFIG(info,key)) || (key_size != WIFI_CONFIG(info,key_size)) || (key_flags != WIFI_CONFIG(info,key_flags))) emitStatusChanged = true; key = (char *) WIFI_CONFIG(info,key); key_size = WIFI_CONFIG(info,key_size); key_flags = WIFI_CONFIG(info,key_flags); } if (essid != WIFI_CONFIG(info,essid)) { emitStatusChanged = true; emitEssidChanged = true; } essid = (WIFI_CONFIG(info,essid_on) ? WIFI_CONFIG(info,essid) : "any"); char ap_addr[256]; iw_ether_ntop ( (const ether_addr *) info.ap_addr.sa_data, ap_addr); if (access_point_address != ap_addr) emitStatusChanged = true; access_point_address = ap_addr; if (bitrate != info.bitrate.value) emitSpeedChanged = true; bitrate = info.bitrate.value; has_range = info.has_range; sigLevel[current] = tempic2.qual.level; noiseLevel[current] = tempic2.qual.noise; if (has_range) { range = info.range.max_qual.qual; // the following checks adjust values for sig levels that are in dBm // according to iwlib.c. If offset is applied, the resulting // value is negative and the GUI knows it can add the scale // unit dBm. if (tempic2.qual.level > info.range.max_qual.level) { sigLevel[current] = tempic2.qual.level - 0x100; noiseLevel[current] = tempic2.qual.noise - 0x100; } } if (sigLevel[current] < sigLevelMin) sigLevelMin = sigLevel[current]; if (sigLevel[current] > sigLevelMax) sigLevelMax = sigLevel[current]; if (noiseLevel[current] < noiseLevelMin) noiseLevelMin = noiseLevel[current]; if (noiseLevel[current] > noiseLevelMax) noiseLevelMax = noiseLevel[current]; int tempqual = tempic2.qual.qual; if (has_range && (range != 0)) tempqual = tempqual * 100 / range; if ( qual[current != 0 ? current - 1 : MAX_HISTORY-1] != tempqual) emitStrengthChanged = true; qual[current] = ( tempqual <= 100 ? tempqual : 100 ); valid[current] = true; // try to get our local IP address struct sockaddr * sa; struct sockaddr_in * sin; struct ifreq ifr; /* Copy the interface name into the buffer */ strncpy (ifr.ifr_name, interface_name.latin1 (), IFNAMSIZ); if (ioctl (socket, SIOCGIFADDR, &ifr) == -1) { if (ip_address != "unavailable") emitStatusChanged = true; ip_address = "unavailable"; } /* Now the buffer will contain the information we requested */ sa = (struct sockaddr *) &(ifr.ifr_addr); if (sa->sa_family == AF_INET) { sin = (struct sockaddr_in *) sa; if (ip_address != (TQString) inet_ntoa (sin->sin_addr)) emitStatusChanged = true; ip_address = (TQString) inet_ntoa (sin->sin_addr); } else { ip_address = "unavailable"; } if (emitStatusChanged) emit statusChanged (); if (emitStrengthChanged) emit strengthChanged (); if (emitModeChanged) emit modeChanged (); if (emitSpeedChanged) emit speedChanged (); if (emitEssidChanged) emit essidChanged (essid); emit statsUpdated (); return true; } TQTable* Interface_wireless_wirelessextensions::get_available_networks () { networks = new TQTable(0,4,0); networks->horizontalHeader()->setLabel( 0, i18n("Network Name") ); networks->horizontalHeader()->setLabel( 1, i18n("Mode") ); networks->horizontalHeader()->setLabel( 2, i18n("Quality") ); networks->horizontalHeader()->setLabel( 3, i18n("WEP") ); KProcIO *iwlist = new KProcIO; TQString iwlist_bin = TDEStandardDirs::findExe("iwlist"); if(iwlist_bin.isEmpty()) iwlist_bin = TDEStandardDirs::findExe("iwlist", "/usr/local/sbin:/usr/sbin:/sbin"); if(iwlist_bin.isEmpty()) iwlist_bin = "iwlist"; // try our best ;/ *iwlist << iwlist_bin << interface_name << "scanning"; // connect ( iwlist, TQT_SIGNAL ( readReady ( KProcIO * ) ), this, TQT_SLOT ( parseScanData ( KProcIO * ) ) ); if ( !iwlist->start ( TDEProcess::Block ) ) KMessageBox::sorry ( 0, i18n ( "Unable to perform the scan. Please make sure the executable \"iwlist\" is in your $PATH." ), i18n ( "Scanning not possible" ) ); // this should never happen. But there was a report about Block not being as blocking as it should, so let's be safe about it while (iwlist->isRunning()) sleep ( 1 ); parseScanData ( iwlist ); for (int i = 0; i<4; i++ ) networks->adjustColumn(i); return networks; } void Interface_wireless_wirelessextensions::parseScanData ( KProcIO * iwlist ) { TQString data; int cellcount = 0, iteratecount = 0; bool ignoreRemainingBits = false; while ( iwlist->readln ( data, true ) >= 0 ) { kdDebug ( ) << "iwlist: " << data << "\n"; if ( data.contains ( "does not support scanning" ) ) KMessageBox::sorry ( 0, i18n ( "Your card does not support scanning. The results window will not contain any results." ), i18n ( "Scanning not possible" ) ); if ( data.contains ( "Scan completed" ) ) cellcount = 0; // at the very beginning of a scan if ( data.contains ( "Cell" ) ) { cellcount++; // new cell discovered networks->setNumRows ( networks->numRows() +1 ); ignoreRemainingBits = false; } if ( data.contains ( "ESSID:" ) ) { TQString ssid = data.mid ( data.find ( "\"" ) + 1, data.length ( ) - data.find ( "\"" ) - 2 ); if ((ssid=="") || (ssid==" ")) ssid = "(hidden cell)"; networks->setText ( cellcount - 1, 0, ssid ); } if ( data.contains ( "Mode:" ) ) { if ( data.contains ( "Master" ) ) networks->setText ( cellcount - 1, 1, TQString ( i18n ( "Managed" ) ) ); if ( data.contains ( "Ad-Hoc" ) ) networks->setText ( cellcount - 1, 1, TQString ( i18n ( "Ad-Hoc" ) ) ); // if could be that this cell belongs to an SSID already discovered, or that there are more than one // hidden cells, which doesn't give any new information. So, we first search for duplicates and delete // this row if it's a duplicate. If the same SSID is there once as Managed and once as Ad-Hoc it is no // duplicate of course, but "something completely different" for (iteratecount = 0; iteratecount < cellcount - 1; iteratecount++) { kdDebug() << "Comparing <" << networks->text(cellcount - 1, 0) << "," << networks->text(iteratecount,0) << " and <" << networks->text(cellcount - 1, 1) << "," << networks->text(iteratecount,1) << ">.\n"; if ((networks->text(cellcount - 1 , 0) == networks->text(iteratecount,0)) && (networks->text(cellcount - 1 , 1) == networks->text(iteratecount,1)) ) { networks->setNumRows ( networks->numRows() - 1 ); cellcount--; ignoreRemainingBits = true; } } } if ( !ignoreRemainingBits && data.contains ( "Encryption key:" ) ) { if ( data.contains ( "off" ) ) networks->setText ( cellcount - 1, 3, TQString ( "off" ) ); else networks->setText ( cellcount - 1, 3, TQString ( "on" ) ); } if ( !ignoreRemainingBits && data.contains ( "Quality:" ) ) { TQString quality = data.mid ( data.find ( ":" ) + 1, data.find ( "/" ) - data.find ( ":" ) - 1 ); networks->setText ( cellcount - 1, 2, quality ); } if ( !ignoreRemainingBits && data.contains ( "Quality=" ) ) { TQString quality = data.mid ( data.find ( "=" ) + 1, data.find ( "/" ) - data.find ( "=" ) - 1 ); networks->setText ( cellcount - 1, 2, quality ); } if ( !ignoreRemainingBits && data.contains ( "wpa_ie" ) ) { networks->setText ( cellcount - 1, 3, TQString ( "WPA" ) ); } if ( !ignoreRemainingBits && data.contains ( "rsn_ie" ) ) { networks->setText ( cellcount - 1, 3, TQString ( "WPA2" ) ); } } } #include "interface_wireless_wirelessextensions.moc"