static double get_stats_discarded_code(void *arg) { int has_range = 1; if (iw_get_range_info(skfd, arg, &range) < 0) { has_range = 0; } if (iw_get_stats(skfd, arg, &stats, &range, has_range) < 0) { xsg_debug("get_stats_discarded_code: UNKNOWN"); return DNAN; } xsg_debug("get_stats_discarded_code: %f", (double) stats.discard.code); return (double) stats.discard.code; }
static const char * get_power_management(void *arg) { static xsg_string_t *string = NULL; wrq.u.power.flags = 0; if (iw_get_ext(skfd, arg, SIOCGIWPOWER, &wrq) < 0) { xsg_debug("get_power_management: UNKNOWN"); return NULL; } if (wrq.u.power.disabled) { xsg_debug("get_power_management: \"off\""); return "off"; } if (string == NULL) { string = xsg_string_new(NULL); } if (wrq.u.power.flags & IW_POWER_TYPE) { if (iw_get_range_info(skfd, arg, &range) >= 0) { iw_print_pm_value(buffer, sizeof(buffer), wrq.u.power.value, wrq.u.power.flags, range.we_version_compiled); xsg_string_append_len(string, buffer, -1); } } iw_print_pm_mode(buffer, sizeof(buffer), wrq.u.power.flags); xsg_string_append_len(string, buffer, -1); if (wrq.u.power.flags == IW_POWER_ON) { xsg_string_append_len(string, "on", -1); } if (string->str[0] == ' ') { xsg_debug("get_power_management: \"%s\"", string->str + 1); return string->str + 1; } else { xsg_debug("get_power_management: \"%s\"", string->str); return string->str; } }
/* * Display the channel (converted from frequency) if possible */ static int print_channel(int skfd, const char * ifname, int format) { struct iwreq wrq; struct iw_range range; double freq; int channel; /* Get frequency / channel */ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0) return(-1); /* Convert to channel */ if(iw_get_range_info(skfd, ifname, &range) < 0) return(-2); freq = iw_freq2float(&(wrq.u.freq)); if(freq < KILO) channel = (int) freq; else { channel = iw_freq_to_channel(freq, &range); if(channel < 0) return(-3); } /* Print */ switch(format) { case FORMAT_SCHEME: /* Prefix with freq to avoid name space collisions */ printf("channel%d\n", channel); break; case FORMAT_RAW: printf("%d\n", channel); break; default: printf("%-8.16s Channel:%d\n", ifname, channel); break; } return(0); }
static double get_stats_quality_noise(void *arg) { int has_range = 1; if (iw_get_range_info(skfd, arg, &range) < 0) { has_range = 0; } if (iw_get_stats(skfd, arg, &stats, &range, has_range) < 0) { xsg_debug("get_stats_quality_noise: UNKNOWN"); return DNAN; } if (has_range && ((stats.qual.level != 0) || (stats.qual.updated & (IW_QUAL_DBM | IW_QUAL_RCPI)))) { if (stats.qual.updated & IW_QUAL_RCPI) { if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) { xsg_debug("get_stats_quality_noise: %f", (stats.qual.noise / 2.0) - 110.0); return (stats.qual.noise / 2.0) - 110.0; } } else if ((stats.qual.updated & IW_QUAL_DBM) || (stats.qual.level > range.max_qual.level)) { if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) { int dbnoise = stats.qual.noise; if (stats.qual.noise >= 64) { dbnoise -= 0x100; } xsg_debug("get_stats_quality_noise: %f", (double) dbnoise); return (double) dbnoise; } } } xsg_debug("get_stats_quality_noise: UNKNOWN"); return DNAN; }
static double get_freq_number(void *arg) { double freq; if (iw_get_ext(skfd, arg, SIOCGIWFREQ, &wrq) < 0) { xsg_debug("get_freq_number: UNKNOWN"); return DNAN; } freq = iw_freq2float(&(wrq.u.freq)); if (freq < KILO) { if (iw_get_range_info(skfd, arg, &range) >= 0) { iw_channel_to_freq((int) freq, &freq, &range); } } xsg_debug("get_freq_number: %f", freq); return freq; }
static double get_channel(void *arg) { double freq; if (iw_get_ext(skfd, arg, SIOCGIWFREQ, &wrq) < 0) { xsg_debug("get_channel: UNKNOWN"); return DNAN; } freq = iw_freq2float(&(wrq.u.freq)); if (freq >= KILO) { if (iw_get_range_info(skfd, arg, &range) >= 0) { return (double) iw_freq_to_channel(freq, &range); } } xsg_debug("get_channel: %f", freq); return freq; }
char *get_wifi(char *buf) { char devpath[35], state[5]; sprintf(devpath, "/sys/class/net/%s/operstate", WIRELESS_D); infile = fopen(devpath, "r"); fscanf(infile, "%s", state); fclose(infile); if(strcmp(state, "up") == 0) { if(iw_get_basic_config(skfd, WIRELESS_D, &(winfo->b)) > -1) { if(iw_get_stats(skfd, WIRELESS_D, &(winfo->stats), &winfo->range, winfo->has_range) >= 0) winfo->has_stats = 1; if(iw_get_range_info(skfd, WIRELESS_D, &(winfo->range)) >= 0) winfo->has_range = 1; if(winfo->b.has_essid && winfo->b.essid_on) sprintf(buf, WIFI_S, winfo->b.essid, (winfo->stats.qual.qual * 100) / winfo->range.max_qual.qual); } } else sprintf(buf, NO_CONN_S); return buf; }
/** * @brief Fills in basic information like the essid and the maximum signal quality */ bool openDevice() { if ((wifi_skfd = iw_sockets_open()) < 0) { ROS_ERROR("socket error"); return false; } if (iw_get_basic_config(wifi_skfd, wifi_dev, &(wifi_info->b)) < 0) { /* If no wireless name : no wireless extensions */ /* But let's check if the interface exists at all */ struct ifreq ifr; strncpy(ifr.ifr_name, wifi_dev, IFNAMSIZ); int ret = ioctl(wifi_skfd, SIOCGIFFLAGS, &ifr); if (ret < 0) { ROS_ERROR("device doesn't exist"); return false; } else { ROS_ERROR("operation not supported"); return false; } } wifi_sig.essid = wifi_info->b.essid; if (iw_get_range_info(wifi_skfd, wifi_dev, &(wifi_info->range)) >= 0) wifi_info->has_range = 1; wifi_sig.link_quality_max = wifi_info->range.max_qual.qual; return true; }
static double get_stats_missed_beacon(void *arg) { int has_range = 1; if (iw_get_range_info(skfd, arg, &range) < 0) { has_range = 0; } if (range.we_version_compiled <= 11) { xsg_debug("get_stats_missed_beacon: UNKNOWN"); return DNAN; } if (iw_get_stats(skfd, arg, &stats, &range, has_range) < 0) { xsg_debug("get_stats_missed_beacon: UNKNOWN"); return DNAN; } xsg_debug("get_stats_missed_beacon: %f", (double) stats.miss.beacon); return (double) stats.miss.beacon; }
static double get_stats_discarded_retries(void *arg) { int has_range = 1; if (iw_get_range_info(skfd, arg, &range) < 0) { has_range = 0; } if (range.we_version_compiled <= 11) { xsg_debug("get_stats_discarded_retries: UNKNOWN"); return DNAN; } if (iw_get_stats(skfd, arg, &stats, &range, has_range) < 0) { xsg_debug("get_stats_discarded_retries: UNKNOWN"); return DNAN; } xsg_debug("get_stats_discarded_retries: %f", (double) stats.discard.retries); return (double) stats.discard.retries; }
/* check stats, modify the state attribute */ static void wireless_applet_read_device_state (WirelessApplet *applet) { iwrange range; iwstats stats; gboolean has_range; /* ewwwww */ char *enum_args[] = { (char *)applet }; /* clear the device list */ g_list_foreach (applet->devices, (GFunc)g_free, NULL); g_list_free (applet->devices); applet->devices = NULL; /* get the config */ iw_get_basic_config (applet->skfd, applet->device, &applet->cfg); iw_enum_devices (applet->skfd, wireless_applet_device_handler, enum_args, 1); has_range = iw_get_range_info (applet->skfd, applet->device, &range) < 0 ? FALSE : TRUE; if (!iw_get_stats (applet->skfd, applet->device, &stats, &range, has_range)) { wireless_applet_update_state (applet, applet->device, stats.qual.qual, stats.qual.level, stats.qual.noise); } else { wireless_applet_update_state (applet, applet->device, -1, -1, -1); } }
static double get_txpower_dbm(void *arg) { if (iw_get_range_info(skfd, arg, &range) < 0) { xsg_debug("get_txpower_dbm: UNKNOWN"); return DNAN; } if (range.we_version_compiled <= 9) { xsg_debug("get_txpower_dbm: UNKNOWN"); return DNAN; } if (iw_get_ext(skfd, arg, SIOCGIWTXPOW, &wrq) < 0) { xsg_debug("get_txpower_dbm: UNKNOWN"); return DNAN; } if (wrq.u.txpower.disabled) { xsg_debug("get_txpower_dbm: UNKNOWN"); return DNAN; } if (wrq.u.txpower.flags & IW_TXPOW_RELATIVE) { xsg_debug("get_txpower_dbm: UNKNOWN"); return DNAN; } if (wrq.u.txpower.flags & IW_TXPOW_MWATT) { xsg_debug("get_txpower_dbm: %f", (double) iw_mwatt2dbm(wrq.u.txpower.value)); return (double) iw_mwatt2dbm(wrq.u.txpower.value); } xsg_debug("get_txpower_dbm: %f", (double) wrq.u.txpower.value); return (double) wrq.u.txpower.value; }
/* * Print Power Management info for each device */ static int print_pm_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; char buffer[128]; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Extract range info */ if((iw_get_range_info(skfd, ifname, &range) < 0) || (range.we_version_compiled < 10)) fprintf(stderr, "%-8.16s no power management information.\n\n", ifname); else { printf("%-8.16s ", ifname); /* Display modes availables */ if(range.pm_capa & IW_POWER_MODE) { printf("Supported modes :\n "); if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R)) printf("\t\to Receive all packets (unicast & multicast)\n "); if(range.pm_capa & IW_POWER_UNICAST_R) printf("\t\to Receive Unicast only (discard multicast)\n "); if(range.pm_capa & IW_POWER_MULTICAST_R) printf("\t\to Receive Multicast only (discard unicast)\n "); if(range.pm_capa & IW_POWER_FORCE_S) printf("\t\to Force sending using Power Management\n "); if(range.pm_capa & IW_POWER_REPEATER) printf("\t\to Repeat multicast\n "); } /* Display min/max period availables */ if(range.pmp_flags & IW_POWER_PERIOD) { int flags = (range.pmp_flags & ~(IW_POWER_MIN | IW_POWER_MAX)); /* Display if auto or fixed */ if(range.pmp_flags & IW_POWER_MIN) printf("Auto period ; "); else printf("Fixed period ; "); /* Print the range */ iw_print_pm_value(buffer, sizeof(buffer), range.min_pmp, flags | IW_POWER_MIN); printf("%s\n ", buffer); iw_print_pm_value(buffer, sizeof(buffer), range.max_pmp, flags | IW_POWER_MAX); printf("%s\n ", buffer); } /* Display min/max timeout availables */ if(range.pmt_flags & IW_POWER_TIMEOUT) { int flags = (range.pmt_flags & ~(IW_POWER_MIN | IW_POWER_MAX)); /* Display if auto or fixed */ if(range.pmt_flags & IW_POWER_MIN) printf("Auto timeout ; "); else printf("Fixed timeout ; "); /* Print the range */ iw_print_pm_value(buffer, sizeof(buffer), range.min_pmt, flags | IW_POWER_MIN); printf("%s\n ", buffer); iw_print_pm_value(buffer, sizeof(buffer), range.max_pmt, flags | IW_POWER_MAX); printf("%s\n ", buffer); } /* Get current Power Management settings */ wrq.u.power.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0) { int flags = wrq.u.power.flags; /* Is it disabled ? */ if(wrq.u.power.disabled) printf("Current mode:off\n "); else { int pm_mask = 0; /* Let's check the mode */ iw_print_pm_mode(buffer, sizeof(buffer), flags); printf("Current %s", buffer); /* Let's check if nothing (simply on) */ if((flags & IW_POWER_MODE) == IW_POWER_ON) printf("mode:on"); printf("\n "); /* Let's check the value and its type */ if(wrq.u.power.flags & IW_POWER_TYPE) { iw_print_pm_value(buffer, sizeof(buffer), wrq.u.power.value, wrq.u.power.flags); printf("%s", buffer); } /* If we have been returned a MIN value, ask for the MAX */ if(flags & IW_POWER_MIN) pm_mask = IW_POWER_MAX; /* If we have been returned a MAX value, ask for the MIN */ if(flags & IW_POWER_MAX) pm_mask = IW_POWER_MIN; /* If we have something to ask for... */ if(pm_mask) get_pm_value(skfd, ifname, &wrq, pm_mask, buffer, sizeof(buffer)); /* And if we have both a period and a timeout, ask the other */ pm_mask = (range.pm_capa & (~(wrq.u.power.flags) & IW_POWER_TYPE)); if(pm_mask) { int base_mask = pm_mask; flags = get_pm_value(skfd, ifname, &wrq, pm_mask, buffer, sizeof(buffer)); pm_mask = 0; /* If we have been returned a MIN value, ask for the MAX */ if(flags & IW_POWER_MIN) pm_mask = IW_POWER_MAX | base_mask; /* If we have been returned a MAX value, ask for the MIN */ if(flags & IW_POWER_MAX) pm_mask = IW_POWER_MIN | base_mask; /* If we have something to ask for... */ if(pm_mask) get_pm_value(skfd, ifname, &wrq, pm_mask, buffer, sizeof(buffer)); } } } printf("\n"); } return(0); }
/* * Print the number of available transmit powers for the device */ static int print_txpower_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; int dbm; int mwatt; int k; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Extract range info */ if((iw_get_range_info(skfd, ifname, &range) < 0) || (range.we_version_compiled < 10)) fprintf(stderr, "%-8.16s no transmit-power information.\n\n", ifname); else { if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER)) printf("%-8.16s unknown transmit-power information.\n\n", ifname); else { printf("%-8.16s %d available transmit-powers :\n", ifname, range.num_txpower); /* Print them all */ for(k = 0; k < range.num_txpower; k++) { /* Check for relative values */ if(range.txpower_capa & IW_TXPOW_RELATIVE) { printf("\t %d (no units)\n", range.txpower[k]); } else { if(range.txpower_capa & IW_TXPOW_MWATT) { dbm = iw_mwatt2dbm(range.txpower[k]); mwatt = range.txpower[k]; } else { dbm = range.txpower[k]; mwatt = iw_dbm2mwatt(range.txpower[k]); } printf("\t %d dBm \t(%d mW)\n", dbm, mwatt); } } } /* Get current Transmit Power */ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0) { printf(" Current Tx-Power"); /* Disabled ? */ if(wrq.u.txpower.disabled) printf(":off\n\n"); else { /* Fixed ? */ if(wrq.u.txpower.fixed) printf("="); else printf(":"); /* Check for relative values */ if(wrq.u.txpower.flags & IW_TXPOW_RELATIVE) { /* I just hate relative value, because they are * driver specific, so not very meaningfull to apps. * But, we have to support that, because * this is the way hardware is... */ printf("\t %d (no units)\n", wrq.u.txpower.value); } else { if(wrq.u.txpower.flags & IW_TXPOW_MWATT) { dbm = iw_mwatt2dbm(wrq.u.txpower.value); mwatt = wrq.u.txpower.value; } else { dbm = wrq.u.txpower.value; mwatt = iw_dbm2mwatt(wrq.u.txpower.value); } printf("%d dBm \t(%d mW)\n\n", dbm, mwatt); } } } } return(0); }
//noise levels, returned by this functions, are invalid, don't use them void CWextHW::readScanResults() { if (m_wextFd == -1) { return; } //Kill Timer: if (m_scTimerId != -1) { killTimer(m_scPollrate); m_scTimerId = -1; } else { //This is not a timer call; this should not happen qWarning() << tr("Warning, no timer present while trying to get scan results"); return; } struct iwreq wrq; memset(&wrq,0,sizeof(struct iwreq)); unsigned char * buffer = NULL; /* Results */ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */ struct iw_range range; memset(&range,0,sizeof(struct iw_range)); int has_range; QList<WextRawScan> res = QList<WextRawScan>(); WextRawScan singleres; singleres.bssid = libnutcommon::MacAddress(); singleres.group = GCI_UNDEFINED; singleres.pairwise = PCI_UNDEFINED; singleres.protocols = PROTO_UNDEFINED; singleres.keyManagement = KM_UNDEFINED; /* workaround */ struct wireless_config wifiConfig; memset(&wifiConfig,0,sizeof(struct wireless_config)); /* Get basic information */ if(iw_get_basic_config(m_wextFd, m_ifname.toAscii().constData(), &wifiConfig) < 0) { /* If no wireless name : no wireless extensions */ /* But let's check if the interface exists at all */ struct ifreq ifr; memset(&ifr,0,sizeof(struct ifreq)); strncpy(ifr.ifr_name, m_ifname.toAscii().data(), IFNAMSIZ); if(ioctl(m_wextFd, SIOCGIFFLAGS, &ifr) < 0) qWarning() << tr("(Wireless Extension) No device present"); else qWarning() << tr("(Wireless Extension) Device not supported"); return; } qDebug() << "Fetched basic config."; /* Get AP address */ if(iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWAP, &wrq) >= 0) { qDebug() << "Got AP"; } /* Get bit rate */ if(iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWRATE, &wrq) >= 0) { qDebug() << "Got bit rate"; } /* Get Power Management settings */ wrq.u.power.flags = 0; if(iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWPOWER, &wrq) >= 0) { qDebug() << "Got power"; } /* workaround */ /* Get range stuff */ /* Get range stuff */ qDebug() << QString("Getting range stuff for %1").arg(m_ifname.toAscii().data()); if (iw_get_range_info(m_wextFd, m_ifname.toAscii().data(), &range) >= 0) { has_range = 1; qDebug() << "Success readWirelessInfo getrange" << strerror(errno); } else { //This is VERY strange: we always get the "operation not permitted" error, although iw_get_range() worked qDebug() << QString("Error \"hasRange == 0\" (%1)").arg(strerror(errno)); } singleres.hasRange = has_range; //If we get a timeout for more than 5 times, stop polling. if (errno == EAGAIN) { qDebug() << "Scan results not available yet"; m_scTimeOutCount++; if (m_scTimeOutCount == 5) { return; } m_scTimerId = startTimer(m_scPollrate); return; } qDebug() << "Got range stuff"; if (has_range) { singleres.maxquality.level = (quint8) range.max_qual.level; singleres.maxquality.qual = (quint8) range.max_qual.qual; singleres.maxquality.noise = (quint8) range.max_qual.noise; singleres.maxquality.updated = (quint8) range.max_qual.updated; qDebug() << "RANGE (scanresults): " << singleres.maxquality.level << singleres.maxquality.qual << singleres.maxquality.noise << singleres.maxquality.updated; } else { singleres.maxquality.level = 0; singleres.maxquality.qual = 0; singleres.maxquality.noise = 0; singleres.maxquality.updated = 0; qWarning() << tr("Range information are not available"); } unsigned char * newbuf; for (int i=0; i <= 16; i++) { //realloc (don't do this forever) //Allocate newbuffer newbuf = (uchar*) realloc(buffer, buflen); if(newbuf == NULL) { if (buffer) { free(buffer); buffer = NULL; } qDebug() << "Allocating buffer for Wext failed"; return; } buffer = newbuf; //Set Request variables: wrq.u.data.pointer = buffer; wrq.u.data.flags = 0; wrq.u.data.length = buflen; //Get the data: if (iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWSCAN, &wrq) < 0) { //Buffer is too small if((errno == E2BIG) && (range.we_version_compiled > 16)) { //check if driver gives any hints about scan length: if (wrq.u.data.length > buflen) { buflen = wrq.u.data.length; } else { //If not, double the length buflen *= 2; } //Start from the beginning: qDebug() << "Buffer was too small"; continue; } //No range error occured or kernel has wireless extension < 16 if (errno == EAGAIN) { qDebug() << "Scan results not available yet"; m_scTimerId = startTimer(m_scPollrate); return; } //Bad error occured if (buffer) { free(buffer); buffer = NULL; } qWarning() << tr("(%1) Failed to read scan data : %2").arg(m_ifname, QString(strerror(errno))); } else { //Results are there break; } } //Now read the data: if (wrq.u.data.length) { struct iw_event iwe; memset(&iwe,0,sizeof(struct iw_event)); struct stream_descr stream; memset(&stream,0,sizeof(struct stream_descr)); int ret; //Init event stream // char buffer2[128]; libnutcommon::MacAddress tmpMac; iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length); do { /* Extract an event and parse it*/ memset(&iwe,0,sizeof(struct iw_event)); //valgrind complains about it? ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled); if(ret > 0) { //Now parse our scan event: switch(iwe.cmd) { case SIOCGIWAP: //ap_addr has type socketaddr //Workaround for macaddress // iw_saether_ntop(&(iwe.u.ap_addr), buffer2); // tmpMac = libnutcommon::MacAddress(QString::fromAscii(buffer2,128)); tmpMac = libnutcommon::MacAddress( (ether_addr*) iwe.u.ap_addr.sa_data); if (singleres.bssid.zero()) { //First bssid singleres.bssid = tmpMac; qDebug() << "Start parsing one network" << singleres.bssid.toString(); } // if our last bssid is different from the actual one, then we have to append it to our scanlist if ( (singleres.bssid != tmpMac) ) { res.append(singleres); qDebug() << "End parsing one network" << singleres.bssid.toString(); //reset singleres singleres.ssid = QString(); singleres.bssid.clear(); singleres.quality = WextRawSignal(); singleres.freq = -1; singleres.group = GCI_UNDEFINED; singleres.pairwise = PCI_UNDEFINED; singleres.keyManagement = KM_UNDEFINED; singleres.protocols = PROTO_UNDEFINED; singleres.opmode = OPM_AUTO; singleres.bssid = tmpMac; qDebug() << "Start parsing one network" << singleres.bssid.toString(); } qDebug() << "BSSID" << singleres.bssid.toString(); break; case IWEVQUAL: //Quality event: qDebug() << "Quality" << singleres.bssid.toString(); singleres.quality.qual = (quint8) iwe.u.qual.qual; singleres.quality.level = (quint8) iwe.u.qual.level; singleres.quality.noise = (quint8) iwe.u.qual.noise; singleres.quality.updated = (quint8) iwe.u.qual.updated; qDebug() << "STATS (scanresults): " << singleres.quality.level << singleres.quality.qual << singleres.quality.noise << singleres.quality.updated; break; case SIOCGIWFREQ: qDebug() << "Frequency" << singleres.bssid.toString(); { double freq; freq = iw_freq2float(&(iwe.u.freq)); //Hopefully in hz if ( ( (freq/1e9) < 10.0 ) && ( (freq/1e9) > 0.0 ) ) { singleres.freq = (int) (freq/1e6); qDebug() << "Channel for" << singleres.ssid << "is " << freq << singleres.freq; } else { singleres.freq = -1; } } break; case SIOCGIWMODE: qDebug() << "Mode:" << singleres.bssid.toString(); if(iwe.u.mode >= IW_NUM_OPER_MODE) { iwe.u.mode = IW_NUM_OPER_MODE; } singleres.opmode = (OPMODE) iwe.u.mode; break; case SIOCGIWESSID: qDebug() << "ESSID:" << singleres.bssid.toString(); if (iwe.u.essid.flags) { /* Does it have an ESSID index ? */ if ( iwe.u.essid.pointer && iwe.u.essid.length ) { if ( (iwe.u.essid.flags & IW_ENCODE_INDEX) > 1) { singleres.ssid = QString("%1 [%2]").arg(QString::fromAscii((char*) iwe.u.essid.pointer,iwe.u.essid.length), QString::number(iwe.u.essid.flags & IW_ENCODE_INDEX)); } else { singleres.ssid = QString("%1").arg(QString::fromAscii((char*) iwe.u.essid.pointer,iwe.u.essid.length)); } } else { singleres.ssid = QString("N/A"); } } else { //Hidden essid or broken driver singleres.ssid = QString(); } break; case SIOCGIWENCODE: //Get encrytion stuff: (just the key) qDebug() << "Encode" << singleres.bssid.toString(); if (! iwe.u.data.pointer) { iwe.u.data.flags |= IW_ENCODE_NOKEY; } if(iwe.u.data.flags & IW_ENCODE_DISABLED) { //Encryption is disabled singleres.keyManagement = KM_NONE; qDebug() << "PARING ENCODE-Information: NO KEY"; } else { //Extract key information: (See iwlib.c line 1500) //keyflags: iwe.u.data.flags //keysize = iwe.u.data.length // //Do we have a key if (iwe.u.data.flags & IW_ENCODE_NOKEY) { //no key if (iwe.u.data.length <= 0) { //Encryption is on, but group is unknown singleres.keyManagement = KM_NONE; qDebug() << "PARSING ENCODE-INFORMATION: WEP KEY"; } } //else: we have a, key but check type later } break; case SIOCGIWRATE: singleres.bitrates.append((qint32) iwe.u.bitrate.value); qDebug() << "Adding Bitrate: " << (qint32) iwe.u.bitrate.value; break; case IWEVGENIE: //group/pairwsie ciphers etc. //buffer = iwe.u.data.pointer //bufflen = iwe.u.data.length qDebug() << "IE_START" << singleres.bssid.toString(); { int offset = 0; /* Loop on each IE, each IE is minimum 2 bytes */ while(offset <= (iwe.u.data.length - 2)) { /* Check IE type */ if (0xdd == ((uchar *) iwe.u.data.pointer)[offset] || (0x30 == ((uchar *) iwe.u.data.pointer)[offset]) ) { // WPA1/2 parseWextIeWpa(((uchar *) iwe.u.data.pointer) + offset, iwe.u.data.length, &singleres); qDebug() << "Parsed IE-Information of " << singleres.ssid << singleres.bssid.toString(); qDebug() << toString(singleres.group) << toString(singleres.pairwise) << toString(singleres.keyManagement); } /* Skip over this IE to the next one in the list. */ offset += buffer[offset+1] + 2; } } qDebug() << "IE_END" << singleres.bssid.toString(); break; default: //Ignore all other event types. Maybe we need them later? break; } } else { //Append last scan: if (!singleres.bssid.zero()) { res.append(singleres); qDebug() << "End parsing one network" << singleres.bssid.toString(); } } } while(ret > 0); //Delete buffer if (buffer) { free(buffer); buffer = NULL; } //We have the data, now construct complete ScanResult setScanResults(res); } else { qWarning() << tr("No Scanresults available"); setScanResults(QList<WextRawScan>()); } if (buffer) { free(buffer); buffer = NULL; } }
/* * Set Power Management */ static int set_power_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i = 1; if(!strcasecmp(args[0], "off")) wrq.u.power.disabled = 1; /* i.e. max size */ else if(!strcasecmp(args[0], "on")) { /* Get old Power info */ wrq.u.power.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.power.disabled = 0; } else { double value; char * unit; int gotone = 0; /* Parse modifiers */ i = parse_modifiers(args, count, &wrq.u.power.flags, iwmod_power, IWMOD_POWER_NUM); if(i < 0) return(i); wrq.u.power.disabled = 0; /* Is there any value to grab ? */ value = strtod(args[0], &unit); if(unit != args[0]) { struct iw_range range; int flags; /* Extract range info to handle properly 'relative' */ if(iw_get_range_info(skfd, ifname, &range) < 0) memset(&range, 0, sizeof(range)); /* Get the flags to be able to do the proper conversion */ switch(wrq.u.power.flags & IW_POWER_TYPE) { case IW_POWER_SAVING: flags = range.pms_flags; break; case IW_POWER_TIMEOUT: flags = range.pmt_flags; break; default: flags = range.pmp_flags; break; } /* Check if time or relative */ if(flags & IW_POWER_RELATIVE) { if(range.we_version_compiled < 21) value *= MEGA; else wrq.u.power.flags |= IW_POWER_RELATIVE; } else { value *= MEGA; /* default = s */ if(unit[0] == 'u') value /= MEGA; if(unit[0] == 'm') value /= KILO; } wrq.u.power.value = (long) value; /* Set some default type if none */ if((wrq.u.power.flags & IW_POWER_TYPE) == 0) wrq.u.power.flags |= IW_POWER_PERIOD; ++i; gotone = 1; } /* Now, check the mode */ if(i < count) { if(!strcasecmp(args[i], "all")) wrq.u.power.flags |= IW_POWER_ALL_R; if(!strncasecmp(args[i], "unicast", 4)) wrq.u.power.flags |= IW_POWER_UNICAST_R; if(!strncasecmp(args[i], "multicast", 5)) wrq.u.power.flags |= IW_POWER_MULTICAST_R; if(!strncasecmp(args[i], "force", 5)) wrq.u.power.flags |= IW_POWER_FORCE_S; if(!strcasecmp(args[i], "repeat")) wrq.u.power.flags |= IW_POWER_REPEATER; if(wrq.u.power.flags & IW_POWER_MODE) { ++i; gotone = 1; } } if(!gotone) { errarg = i; return(IWERR_ARG_TYPE); } } if(iw_set_ext(skfd, ifname, SIOCSIWPOWER, &wrq) < 0) return(IWERR_SET_EXT); /* Var args */ return(i); }
APLIST *wireless_scanning(int iwsockfd, const char *ifname) { APLIST *ap = NULL; APLIST *newap; struct iwreq wrq; int scanflags = 0; /* Flags for scan */ unsigned char * buffer = NULL; /* Results */ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE < 17 */ struct iw_range range; int has_range; struct timeval tv; /* select timeout */ int timeout = 15000000; /* 15s */ /* Get range stuff */ has_range = (iw_get_range_info(iwsockfd, ifname, &range) >= 0); /* Check if the interface could support scanning. */ if ((!has_range) || (range.we_version_compiled < 14)) { fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n", ifname); return NULL; } /* Init timeout value -> 250ms between set and first get */ tv.tv_sec = 0; tv.tv_usec = 250000; wrq.u.data.pointer = NULL; wrq.u.data.flags = 0; wrq.u.data.length = 0; /* Initiate Scanning */ if (iw_set_ext(iwsockfd, ifname, SIOCSIWSCAN, &wrq) < 0) { if ((errno != EPERM) || (scanflags != 0)) { fprintf(stderr, "%-8.16s Interface doesn't support " "scanning : %s\n\n", ifname, strerror(errno)); return NULL; } tv.tv_usec = 0; } timeout -= tv.tv_usec; /* Forever */ while (1) { fd_set rfds; /* File descriptors for select */ int last_fd; /* Last fd */ int ret; /* Guess what ? We must re-generate rfds each time */ FD_ZERO(&rfds); last_fd = -1; /* In here, add the rtnetlink fd in the list */ /* Wait until something happens */ ret = select(last_fd + 1, &rfds, NULL, NULL, &tv); /* Check if there was an error */ if (ret < 0) { if (errno == EAGAIN || errno == EINTR) continue; fprintf(stderr, "Unhandled signal - exiting...\n"); return NULL; } /* Check if there was a timeout */ if (ret == 0) { unsigned char *newbuf; realloc: /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */ newbuf = realloc(buffer, buflen); if (newbuf == NULL) { if (buffer) free(buffer); fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__); return NULL; } buffer = newbuf; /* Try to read the results */ wrq.u.data.pointer = buffer; wrq.u.data.flags = 0; wrq.u.data.length = buflen; if (iw_get_ext(iwsockfd, ifname, SIOCGIWSCAN, &wrq) < 0) { /* Check if buffer was too small (WE-17 only) */ if ((errno == E2BIG) && (range.we_version_compiled > 16)) { /* Check if the driver gave us any hints. */ if (wrq.u.data.length > buflen) buflen = wrq.u.data.length; else buflen *= 2; /* Try again */ goto realloc; } /* Check if results not available yet */ if(errno == EAGAIN) { /* Restart timer for only 100ms*/ tv.tv_sec = 0; tv.tv_usec = 100000; timeout -= tv.tv_usec; if (timeout > 0) continue; /* Try again later */ } /* Bad error */ free(buffer); fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n", ifname, strerror(errno)); return NULL; } else /* We have the results, go to process them */ break; } /* In here, check if event and event type * if scan event, read results. All errors bad & no reset timeout */ } if(wrq.u.data.length) { struct iw_event iwe; struct stream_descr stream; int ret; iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length); do { /* Extract an event and print it */ ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled); if (iwe.cmd==SIOCGIWAP) { newap = malloc(sizeof(APLIST)); newap->info = NULL; newap->next = ap; ap = newap; } ap->info = wireless_parse_scanning_event(&iwe, ap->info); } while (ret > 0); printf("\n"); } else printf("%-8.16s No scan results\n\n", ifname); free(buffer); return ap; }
/* * Set Retry Limit */ static int set_retry_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i = 0; double value; char * unit; /* Parse modifiers */ i = parse_modifiers(args, count, &wrq.u.retry.flags, iwmod_retry, IWMOD_RETRY_NUM); if(i < 0) return(i); /* Add default type if none */ if((wrq.u.retry.flags & IW_RETRY_TYPE) == 0) wrq.u.retry.flags |= IW_RETRY_LIMIT; wrq.u.retry.disabled = 0; /* Is there any value to grab ? */ value = strtod(args[0], &unit); if(unit == args[0]) { errarg = i; return(IWERR_ARG_TYPE); } /* Limit is absolute, on the other hand lifetime is seconds */ if(wrq.u.retry.flags & IW_RETRY_LIFETIME) { struct iw_range range; /* Extract range info to handle properly 'relative' */ if(iw_get_range_info(skfd, ifname, &range) < 0) memset(&range, 0, sizeof(range)); if(range.r_time_flags & IW_RETRY_RELATIVE) { if(range.we_version_compiled < 21) value *= MEGA; else wrq.u.retry.flags |= IW_RETRY_RELATIVE; } else { /* Normalise lifetime */ value *= MEGA; /* default = s */ if(unit[0] == 'u') value /= MEGA; if(unit[0] == 'm') value /= KILO; } } wrq.u.retry.value = (long) value; ++i; if(iw_set_ext(skfd, ifname, SIOCSIWRETRY, &wrq) < 0) return(IWERR_SET_EXT); /* Var args */ return(i); }
/* * Display the spy list of addresses and the associated stats */ static int print_spy_info(int skfd, char * ifname, char * args[], int count) { struct iwreq wrq; char buffer[(sizeof(struct iw_quality) + sizeof(struct sockaddr)) * IW_MAX_SPY]; char temp[128]; struct sockaddr * hwa; struct iw_quality * qual; iwrange range; int has_range = 0; int n; int i; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Collect stats */ wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = IW_MAX_SPY; wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support wireless statistic collection\n\n", ifname); return(-1); } /* Number of addresses */ n = wrq.u.data.length; /* Check if we have valid mac address type */ if(iw_check_mac_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n\n", ifname); return(-2); } /* Get range info if we can */ if(iw_get_range_info(skfd, ifname, &(range)) >= 0) has_range = 1; /* Display it */ if(n == 0) printf("%-8.16s No statistics to collect\n", ifname); else printf("%-8.16s Statistics collected:\n", ifname); /* The two lists */ hwa = (struct sockaddr *) buffer; qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n)); for(i = 0; i < n; i++) { /* Print stats for each address */ printf(" %s : ", iw_saether_ntop(&hwa[i], temp)); iw_print_stats(temp, sizeof(temp), &qual[i], &range, has_range); printf("%s\n", temp); } if((n > 0) && (has_range) && (range.we_version_compiled > 11)) { iwstats stats; /* Get /proc/net/wireless */ if(iw_get_stats(skfd, ifname, &stats, &range, has_range) >= 0) { iw_print_stats(temp, sizeof(temp), &stats.qual, &range, has_range); printf(" Link/Cell/AP : %s\n", temp); /* Display the static data */ iw_print_stats(temp, sizeof(temp), &range.avg_qual, &range, has_range); printf(" Typical/Reference : %s\n", temp); } } printf("\n"); return(0); }
static int get_wireless_info(const char *interface, wireless_info_t *info) { memset(info, 0, sizeof(wireless_info_t)); #ifdef LINUX int skfd = iw_sockets_open(); if (skfd < 0) { perror("iw_sockets_open"); return 0; } wireless_config wcfg; if (iw_get_basic_config(skfd, interface, &wcfg) < 0) { close(skfd); return 0; } if (wcfg.has_essid && wcfg.essid_on) { info->flags |= WIRELESS_INFO_FLAG_HAS_ESSID; strncpy(&info->essid[0], wcfg.essid, IW_ESSID_MAX_SIZE); info->essid[IW_ESSID_MAX_SIZE] = '\0'; } /* If the function iw_get_stats does not return proper stats, the wifi is considered as down. Since ad-hoc network does not have theses stats, we need to return here for this mode. */ if (wcfg.mode == 1) { close(skfd); return 1; } /* Wireless quality is a relative value in a driver-specific range. Signal and noise level can be either relative or absolute values in dBm. Furthermore, noise and quality can be expressed directly in dBm or in RCPI (802.11k), which we convert to dBm. When those values are expressed directly in dBm, they range from -192 to 63, and since the values are packed into 8 bits, we need to perform 8-bit arithmetic on them. Assume absolute values if everything else fails (driver bug). */ iwrange range; if (iw_get_range_info(skfd, interface, &range) < 0) { close(skfd); return 0; } iwstats stats; if (iw_get_stats(skfd, interface, &stats, &range, 1) < 0) { close(skfd); return 0; } if (stats.qual.level != 0 || (stats.qual.updated & (IW_QUAL_DBM | IW_QUAL_RCPI))) { if (!(stats.qual.updated & IW_QUAL_QUAL_INVALID)) { info->quality = stats.qual.qual; info->quality_max = range.max_qual.qual; info->quality_average = range.avg_qual.qual; info->flags |= WIRELESS_INFO_FLAG_HAS_QUALITY; } if (stats.qual.updated & IW_QUAL_RCPI) { if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) { info->signal_level = stats.qual.level / 2.0 - 110 + 0.5; info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL; } if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) { info->noise_level = stats.qual.noise / 2.0 - 110 + 0.5; info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE; } } else { if ((stats.qual.updated & IW_QUAL_DBM) || stats.qual.level > range.max_qual.level) { if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) { info->signal_level = stats.qual.level; if (info->signal_level > 63) info->signal_level -= 256; info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL; } if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) { info->noise_level = stats.qual.noise; if (info->noise_level > 63) info->noise_level -= 256; info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE; } } else { if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) { info->signal_level = stats.qual.level; info->signal_level_max = range.max_qual.level; info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL; } if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) { info->noise_level = stats.qual.noise; info->noise_level_max = range.max_qual.noise; info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE; } } } } else { if (!(stats.qual.updated & IW_QUAL_QUAL_INVALID)) { info->quality = stats.qual.qual; info->flags |= WIRELESS_INFO_FLAG_HAS_QUALITY; } if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) { info->quality = stats.qual.level; info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL; } if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) { info->quality = stats.qual.noise; info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE; } } struct iwreq wrq; if (iw_get_ext(skfd, interface, SIOCGIWRATE, &wrq) >= 0) info->bitrate = wrq.u.bitrate.value; close(skfd); return 1; #endif #if defined(__FreeBSD__) || defined(__DragonFly__) int s, len, inwid; uint8_t buf[24 * 1024], *cp; struct ieee80211req na; char network_id[IEEE80211_NWID_LEN + 1]; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) return (0); memset(&na, 0, sizeof(na)); strlcpy(na.i_name, interface, sizeof(na.i_name)); na.i_type = IEEE80211_IOC_SSID; na.i_data = &info->essid[0]; na.i_len = IEEE80211_NWID_LEN + 1; if ((inwid = ioctl(s, SIOCG80211, (caddr_t)&na)) == -1) { close(s); return (0); } if (inwid == 0) { if (na.i_len <= IEEE80211_NWID_LEN) len = na.i_len + 1; else len = IEEE80211_NWID_LEN + 1; info->essid[len -1] = '\0'; } else { close(s); return (0); } info->flags |= WIRELESS_INFO_FLAG_HAS_ESSID; memset(&na, 0, sizeof(na)); strlcpy(na.i_name, interface, sizeof(na.i_name)); na.i_type = IEEE80211_IOC_SCAN_RESULTS; na.i_data = buf; na.i_len = sizeof(buf); if (ioctl(s, SIOCG80211, (caddr_t)&na) == -1) { printf("fail\n"); close(s); return (0); } close(s); len = na.i_len; cp = buf; struct ieee80211req_scan_result *sr; uint8_t *vp; sr = (struct ieee80211req_scan_result *)cp; vp = (u_int8_t *)(sr + 1); strlcpy(network_id, (const char *)vp, sr->isr_ssid_len + 1); if (!strcmp(network_id, &info->essid[0])) { info->signal_level = sr->isr_rssi; info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL; info->noise_level = sr->isr_noise; info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE; info->quality = sr->isr_intval; info->flags |= WIRELESS_INFO_FLAG_HAS_QUALITY; } return 1; #endif #ifdef __OpenBSD__ struct ifreq ifr; struct ieee80211_bssid bssid; struct ieee80211_nwid nwid; struct ieee80211_nodereq nr; struct ether_addr ea; int s, len, ibssid, inwid; u_int8_t zero_bssid[IEEE80211_ADDR_LEN]; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) return (0); memset(&ifr, 0, sizeof(ifr)); ifr.ifr_data = (caddr_t)&nwid; (void)strlcpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)); inwid = ioctl(s, SIOCG80211NWID, (caddr_t)&ifr); memset(&bssid, 0, sizeof(bssid)); strlcpy(bssid.i_name, interface, sizeof(bssid.i_name)); ibssid = ioctl(s, SIOCG80211BSSID, &bssid); if (ibssid != 0 || inwid != 0) { close(s); return 0; } /* NWID */ { if (nwid.i_len <= IEEE80211_NWID_LEN) len = nwid.i_len + 1; else len = IEEE80211_NWID_LEN + 1; strncpy(&info->essid[0], nwid.i_nwid, len); info->essid[IW_ESSID_MAX_SIZE] = '\0'; info->flags |= WIRELESS_INFO_FLAG_HAS_ESSID; } /* Signal strength */ { memset(&zero_bssid, 0, sizeof(zero_bssid)); if (ibssid == 0 && memcmp(bssid.i_bssid, zero_bssid, IEEE80211_ADDR_LEN) != 0) { memcpy(&ea.ether_addr_octet, bssid.i_bssid, sizeof(ea.ether_addr_octet)); bzero(&nr, sizeof(nr)); bcopy(bssid.i_bssid, &nr.nr_macaddr, sizeof(nr.nr_macaddr)); strlcpy(nr.nr_ifname, interface, sizeof(nr.nr_ifname)); if (ioctl(s, SIOCG80211NODE, &nr) == 0 && nr.nr_rssi) { if (nr.nr_max_rssi) info->signal_level_max = IEEE80211_NODEREQ_RSSI(&nr); else info->signal_level = nr.nr_rssi; info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL; } } } close(s); return 1; #endif return 0; }
/* ---------------------------------------------------------------------- WirelessInterface_Scan */ static PyObject* WirelessInterface_Scan(wiface* self) { iwreq wrq; unsigned char* buffer = NULL; int buflen = IW_SCAN_MAX_DATA; iwrange range; int has_range; timeval tv; int timeout = 15000000; PyObject* scan_list = NULL; has_range = (iw_get_range_info(self->sock, self->ifname, &range) >= 0); tv.tv_sec = 0; tv.tv_usec = 250000; wrq.u.data.pointer = NULL; wrq.u.data.flags = 0; wrq.u.data.length = 0; if (iw_set_ext(self->sock, self->ifname, SIOCSIWSCAN, &wrq) < 0) { if (errno != EPERM) { PyErr_SetString(IwScanError, "Interface doesn't support scanning"); return NULL; } tv.tv_usec = 0; } timeout -= tv.tv_usec; while (1) { fd_set rfds; int last_fd; int ret; FD_ZERO(&rfds); last_fd = -1; ret = select(last_fd + 1, &rfds, NULL, NULL, &tv); if (ret < 0) { if (errno == EAGAIN || errno == EINTR) continue; else { PyErr_SetString(IwScanError, "Unknown scanning error"); return NULL; } } if (!ret) { unsigned char* newbuf; realloc: newbuf = realloc(buffer, buflen); if (!newbuf) { if (buffer) free(buffer); PyErr_SetString(IwScanError, "Memory allocation failure in scan"); return NULL; } buffer = newbuf; wrq.u.data.pointer = buffer; wrq.u.data.flags = 0; wrq.u.data.length = buflen; if (iw_get_ext(self->sock, self->ifname, SIOCGIWSCAN, &wrq) < 0) { if ((errno == E2BIG)) { if (wrq.u.data.length > buflen) buflen = wrq.u.data.length; else buflen *= 2; goto realloc; } if (errno == EAGAIN) { tv.tv_sec = 0; tv.tv_usec = 100000; timeout -= tv.tv_usec; if (timeout > 0) continue; } free(buffer); PyErr_SetString(IwScanError, "Unable to read scan data"); return NULL; } else break; } } if (wrq.u.data.length) { iwevent iwe; stream_descr stream; int ret; PyObject* scan_dict = NULL; scan_list = PyList_New(0); iw_init_event_stream(&stream, (char*)(buffer), wrq.u.data.length); do { ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled); if (ret > 0) { wifacesd sd; int sr = WirelessInterface_ScanItem(&sd, &iwe, &range, has_range); if (sr) { int i; if (scan_dict) { PyList_Append(scan_list, scan_dict); Py_DECREF(scan_dict); } scan_dict = PyDict_New(); for (i = 0; i < IWSCAN_INTERFACE_KEYS; i++) { PyMapping_SetItemString(scan_dict, WirelessInterfaceKeys[i], Py_BuildValue("")); } } if (sd.num) { int i; for (i = 0; i < sd.num; i++) { PyMapping_SetItemString(scan_dict, WirelessInterfaceKeys[sd.keys[i]], sd.objs[i]); Py_DECREF(sd.objs[i]); } } } } while (ret > 0); PyList_Append(scan_list, scan_dict); Py_XDECREF(scan_dict); } else return Py_BuildValue("[]"); free(buffer); return scan_list; }
/* * Get wireless informations & config from the device driver * We will call all the classical wireless ioctl on the driver through * the socket to know what is supported and to get the settings... */ static int get_info(int skfd, char * ifname, struct wireless_info * info) { struct iwreq wrq; memset((char *) info, 0, sizeof(struct wireless_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; // cefiro 2004/1/12 14:39 printf("ifname = %s\n", ifname); printf("skfd = %d\n", skfd); printf("SIOCGIWNAME= %d\n", SIOCGIWNAME); strcpy(ifr.ifr_name, ifname); if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) return(-ENODEV); else return(-ENOTSUP); } else { strncpy(info->name, wrq.u.name, IFNAMSIZ); 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) { info->has_nwid = 1; memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam)); } /* Get frequency / channel */ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0) { info->has_freq = 1; 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) info->key; wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0) { info->has_key = 1; info->key_size = wrq.u.data.length; info->key_flags = wrq.u.data.flags; } /* Get ESSID */ wrq.u.essid.pointer = (caddr_t) 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) { info->has_essid = 1; 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) { info->mode = wrq.u.mode; if((info->mode < IW_NUM_OPER_MODE) && (info->mode >= 0)) 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 */ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0) { info->has_txpower = 1; memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam)); } #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(iw_get_stats(skfd, ifname, &(info->stats)) >= 0) { info->has_stats = 1; } return(0); }
/* * Set the wireless options requested on command line * This function is too long and probably should be split, * because it look like the perfect definition of spaghetti code, * but I'm way to lazy */ static int set_info(int skfd, /* The socket */ char * args[], /* Command line args */ int count, /* Args count */ char * ifname) /* Dev name */ { struct iwreq wrq; int i; /* if nothing after the device name - will never happen */ if(count < 1) { fprintf(stderr, "Error : too few arguments.\n"); return(-1); } /* The other args on the line specify options to be set... */ for(i = 0; i < count; i++) { /* ---------- Commit changes to driver ---------- */ if(!strncmp(args[i], "commit", 6)) { /* No args */ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWCOMMIT, &wrq, "Commit changes"); continue; } /* ---------- Set network ID ---------- */ if((!strcasecmp(args[i], "nwid")) || (!strcasecmp(args[i], "domain"))) { i++; if(i >= count) ABORT_ARG_NUM("Set NWID", SIOCSIWNWID); if((!strcasecmp(args[i], "off")) || (!strcasecmp(args[i], "any"))) wrq.u.nwid.disabled = 1; else if(!strcasecmp(args[i], "on")) { /* Get old nwid */ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWNWID, &wrq, "Set NWID"); wrq.u.nwid.disabled = 0; } else if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value)) != 1) ABORT_ARG_TYPE("Set NWID", SIOCSIWNWID, args[i]); else wrq.u.nwid.disabled = 0; wrq.u.nwid.fixed = 1; /* Set new nwid */ IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNWID, &wrq, "Set NWID"); continue; } /* ---------- Set frequency / channel ---------- */ if((!strncmp(args[i], "freq", 4)) || (!strcmp(args[i], "channel"))) { double freq; if(++i >= count) ABORT_ARG_NUM("Set Frequency", SIOCSIWFREQ); if(sscanf(args[i], "%lg", &(freq)) != 1) ABORT_ARG_TYPE("Set Frequency", SIOCSIWFREQ, args[i]); if(index(args[i], 'G')) freq *= GIGA; if(index(args[i], 'M')) freq *= MEGA; if(index(args[i], 'k')) freq *= KILO; iw_float2freq(freq, &(wrq.u.freq)); IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFREQ, &wrq, "Set Frequency"); continue; } /* ---------- Set sensitivity ---------- */ if(!strncmp(args[i], "sens", 4)) { if(++i >= count) ABORT_ARG_NUM("Set Sensitivity", SIOCSIWSENS); if(sscanf(args[i], "%i", &(wrq.u.sens.value)) != 1) ABORT_ARG_TYPE("Set Sensitivity", SIOCSIWSENS, args[i]); IW_SET_EXT_ERR(skfd, ifname, SIOCSIWSENS, &wrq, "Set Sensitivity"); continue; } /* ---------- Set encryption stuff ---------- */ if((!strncmp(args[i], "enc", 3)) || (!strcmp(args[i], "key"))) { unsigned char key[IW_ENCODING_TOKEN_MAX]; if(++i >= count) ABORT_ARG_NUM("Set Encode", SIOCSIWENCODE); if(!strcasecmp(args[i], "on")) { /* Get old encryption information */ wrq.u.data.pointer = (caddr_t) key; wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; IW_GET_EXT_ERR(skfd, ifname, SIOCGIWENCODE, &wrq, "Set Encode"); wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */ } else { int gotone = 0; int oldone; int keylen; int temp; wrq.u.data.pointer = (caddr_t) NULL; wrq.u.data.flags = 0; wrq.u.data.length = 0; /* Allow arguments in any order (it's safe) */ do { oldone = gotone; /* -- Check for the key -- */ if(i < count) { keylen = iw_in_key_full(skfd, ifname, args[i], key, &wrq.u.data.flags); if(keylen > 0) { wrq.u.data.length = keylen; wrq.u.data.pointer = (caddr_t) key; ++i; gotone++; } } /* -- Check for token index -- */ if((i < count) && (sscanf(args[i], "%i", &temp) == 1) && (temp > 0) && (temp < IW_ENCODE_INDEX)) { wrq.u.encoding.flags |= temp; ++i; gotone++; } /* -- Check the various flags -- */ if((i < count) && (!strcasecmp(args[i], "off"))) { wrq.u.data.flags |= IW_ENCODE_DISABLED; ++i; gotone++; } if((i < count) && (!strcasecmp(args[i], "open"))) { wrq.u.data.flags |= IW_ENCODE_OPEN; ++i; gotone++; } if((i < count) && (!strncasecmp(args[i], "restricted", 5))) { wrq.u.data.flags |= IW_ENCODE_RESTRICTED; ++i; gotone++; } #if WIRELESS_EXT > 15 if((i < count) && (!strncasecmp(args[i], "temporary", 4))) { wrq.u.data.flags |= IW_ENCODE_TEMP; ++i; gotone++; } #endif } while(gotone != oldone); /* Pointer is absent in new API */ if(wrq.u.data.pointer == NULL) wrq.u.data.flags |= IW_ENCODE_NOKEY; /* Check if we have any invalid argument */ if(!gotone) ABORT_ARG_TYPE("Set Encode", SIOCSIWENCODE, args[i]); /* Get back to last processed argument */ --i; } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWENCODE, &wrq, "Set Encode"); continue; } /* ---------- Set ESSID ---------- */ if(!strcasecmp(args[i], "essid")) { char essid[IW_ESSID_MAX_SIZE + 1]; i++; if(i >= count) ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID); if((!strcasecmp(args[i], "off")) || (!strcasecmp(args[i], "any"))) { wrq.u.essid.flags = 0; essid[0] = '\0'; } else if(!strcasecmp(args[i], "on")) { /* Get old essid */ wrq.u.essid.pointer = (caddr_t) essid; wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; wrq.u.essid.flags = 0; IW_GET_EXT_ERR(skfd, ifname, SIOCGIWESSID, &wrq, "Set ESSID"); wrq.u.essid.flags = 1; } else { /* '-' allow to escape the ESSID string, allowing * to set it to the string "any" or "off". * This is a big ugly, but it will do for now */ if(!strcmp(args[i], "-")) { i++; if(i >= count) ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID); } /* Check the size of what the user passed us to avoid * buffer overflows */ if(strlen(args[i]) > IW_ESSID_MAX_SIZE) ABORT_ARG_SIZE("Set ESSID", SIOCSIWESSID, IW_ESSID_MAX_SIZE); else { int temp; wrq.u.essid.flags = 1; strcpy(essid, args[i]); /* Size checked, all clear */ /* Check for ESSID index */ if(((i+1) < count) && (sscanf(args[i+1], "[%i]", &temp) == 1) && (temp > 0) && (temp < IW_ENCODE_INDEX)) { wrq.u.essid.flags = temp; ++i; } } } wrq.u.essid.pointer = (caddr_t) essid; wrq.u.essid.length = strlen(essid) + 1; IW_SET_EXT_ERR(skfd, ifname, SIOCSIWESSID, &wrq, "Set ESSID"); continue; } /* ---------- Set AP address ---------- */ if(!strcasecmp(args[i], "ap")) { if(++i >= count) ABORT_ARG_NUM("Set AP Address", SIOCSIWAP); if((!strcasecmp(args[i], "auto")) || (!strcasecmp(args[i], "any"))) { /* Send a broadcast address */ iw_broad_ether(&(wrq.u.ap_addr)); } else { if(!strcasecmp(args[i], "off")) { /* Send a NULL address */ iw_null_ether(&(wrq.u.ap_addr)); } else { /* Get the address and check if the interface supports it */ if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0) ABORT_ARG_TYPE("Set AP Address", SIOCSIWAP, args[i-1]); } } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWAP, &wrq, "Set AP Address"); continue; } /* ---------- Set NickName ---------- */ if(!strncmp(args[i], "nick", 4)) { i++; if(i >= count) ABORT_ARG_NUM("Set Nickname", SIOCSIWNICKN); if(strlen(args[i]) > IW_ESSID_MAX_SIZE) ABORT_ARG_SIZE("Set Nickname", SIOCSIWNICKN, IW_ESSID_MAX_SIZE); wrq.u.essid.pointer = (caddr_t) args[i]; wrq.u.essid.length = strlen(args[i]) + 1; IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNICKN, &wrq, "Set Nickname"); continue; } /* ---------- Set Bit-Rate ---------- */ if((!strncmp(args[i], "bit", 3)) || (!strcmp(args[i], "rate"))) { if(++i >= count) ABORT_ARG_NUM("Set Bit Rate", SIOCSIWRATE); if(!strcasecmp(args[i], "auto")) { wrq.u.bitrate.value = -1; wrq.u.bitrate.fixed = 0; } else { if(!strcasecmp(args[i], "fixed")) { /* Get old bitrate */ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRATE, &wrq, "Set Bit Rate"); wrq.u.bitrate.fixed = 1; } else /* Should be a numeric value */ { double brate; if(sscanf(args[i], "%lg", &(brate)) != 1) ABORT_ARG_TYPE("Set Bit Rate", SIOCSIWRATE, args[i]); if(index(args[i], 'G')) brate *= GIGA; if(index(args[i], 'M')) brate *= MEGA; if(index(args[i], 'k')) brate *= KILO; wrq.u.bitrate.value = (long) brate; wrq.u.bitrate.fixed = 1; /* Check for an additional argument */ if(((i+1) < count) && (!strcasecmp(args[i+1], "auto"))) { wrq.u.bitrate.fixed = 0; ++i; } if(((i+1) < count) && (!strcasecmp(args[i+1], "fixed"))) { wrq.u.bitrate.fixed = 1; ++i; } } } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRATE, &wrq, "Set Bit Rate"); continue; } /* ---------- Set RTS threshold ---------- */ if(!strncasecmp(args[i], "rts", 3)) { i++; if(i >= count) ABORT_ARG_NUM("Set RTS Threshold", SIOCSIWRTS); wrq.u.rts.value = -1; wrq.u.rts.fixed = 1; wrq.u.rts.disabled = 0; if(!strcasecmp(args[i], "off")) wrq.u.rts.disabled = 1; /* i.e. max size */ else if(!strcasecmp(args[i], "auto")) wrq.u.rts.fixed = 0; else { if(!strcasecmp(args[i], "fixed")) { /* Get old RTS threshold */ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRTS, &wrq, "Set RTS Threshold"); wrq.u.rts.fixed = 1; } else /* Should be a numeric value */ if(sscanf(args[i], "%li", (unsigned long *) &(wrq.u.rts.value)) != 1) ABORT_ARG_TYPE("Set RTS Threshold", SIOCSIWRTS, args[i]); } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRTS, &wrq, "Set RTS Threshold"); continue; } /* ---------- Set fragmentation threshold ---------- */ if(!strncmp(args[i], "frag", 4)) { i++; if(i >= count) ABORT_ARG_NUM("Set Fragmentation Threshold", SIOCSIWFRAG); wrq.u.frag.value = -1; wrq.u.frag.fixed = 1; wrq.u.frag.disabled = 0; if(!strcasecmp(args[i], "off")) wrq.u.frag.disabled = 1; /* i.e. max size */ else if(!strcasecmp(args[i], "auto")) wrq.u.frag.fixed = 0; else { if(!strcasecmp(args[i], "fixed")) { /* Get old fragmentation threshold */ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFRAG, &wrq, "Set Fragmentation Threshold"); wrq.u.frag.fixed = 1; } else /* Should be a numeric value */ if(sscanf(args[i], "%li", (unsigned long *) &(wrq.u.frag.value)) != 1) ABORT_ARG_TYPE("Set Fragmentation Threshold", SIOCSIWFRAG, args[i]); } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFRAG, &wrq, "Set Fragmentation Threshold"); continue; } /* ---------- Set operation mode ---------- */ if(!strcmp(args[i], "mode")) { int k; i++; if(i >= count) ABORT_ARG_NUM("Set Mode", SIOCSIWMODE); if(sscanf(args[i], "%i", &k) != 1) { k = 0; while((k < IW_NUM_OPER_MODE) && strncasecmp(args[i], iw_operation_mode[k], 3)) k++; } if((k >= IW_NUM_OPER_MODE) || (k < 0)) ABORT_ARG_TYPE("Set Mode", SIOCSIWMODE, args[i]); wrq.u.mode = k; IW_SET_EXT_ERR(skfd, ifname, SIOCSIWMODE, &wrq, "Set Mode"); continue; } /* ---------- Set Power Management ---------- */ if(!strncmp(args[i], "power", 3)) { if(++i >= count) ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); if(!strcasecmp(args[i], "off")) wrq.u.power.disabled = 1; /* i.e. max size */ else if(!strcasecmp(args[i], "on")) { /* Get old Power info */ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWPOWER, &wrq, "Set Power Management"); wrq.u.power.disabled = 0; } else { double temp; int gotone = 0; /* Default - nope */ wrq.u.power.flags = IW_POWER_ON; wrq.u.power.disabled = 0; /* Check value modifier */ if(!strcasecmp(args[i], "min")) { wrq.u.power.flags |= IW_POWER_MIN; if(++i >= count) ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); } else if(!strcasecmp(args[i], "max")) { wrq.u.power.flags |= IW_POWER_MAX; if(++i >= count) ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); } /* Check value type */ if(!strcasecmp(args[i], "period")) { wrq.u.power.flags |= IW_POWER_PERIOD; if(++i >= count) ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); } else if(!strcasecmp(args[i], "timeout")) { wrq.u.power.flags |= IW_POWER_TIMEOUT; if(++i >= count) ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER); } /* Is there any value to grab ? */ if(sscanf(args[i], "%lg", &(temp)) == 1) { temp *= MEGA; /* default = s */ if(index(args[i], 'u')) temp /= MEGA; if(index(args[i], 'm')) temp /= KILO; wrq.u.power.value = (long) temp; if((wrq.u.power.flags & IW_POWER_TYPE) == 0) wrq.u.power.flags |= IW_POWER_PERIOD; ++i; gotone = 1; } /* Now, check the mode */ if(i < count) { if(!strcasecmp(args[i], "all")) wrq.u.power.flags |= IW_POWER_ALL_R; if(!strncasecmp(args[i], "unicast", 4)) wrq.u.power.flags |= IW_POWER_UNICAST_R; if(!strncasecmp(args[i], "multicast", 5)) wrq.u.power.flags |= IW_POWER_MULTICAST_R; if(!strncasecmp(args[i], "force", 5)) wrq.u.power.flags |= IW_POWER_FORCE_S; if(!strcasecmp(args[i], "repeat")) wrq.u.power.flags |= IW_POWER_REPEATER; if(wrq.u.power.flags & IW_POWER_MODE) { ++i; gotone = 1; } } if(!gotone) ABORT_ARG_TYPE("Set Power Management", SIOCSIWPOWER, args[i]); --i; } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWPOWER, &wrq, "Set Power Management"); continue; } #if WIRELESS_EXT > 9 /* ---------- Set Transmit-Power ---------- */ if(!strncmp(args[i], "txpower", 3)) { struct iw_range range; if(++i >= count) ABORT_ARG_NUM("Set Tx Power", SIOCSIWTXPOW); /* Extract range info */ if(iw_get_range_info(skfd, ifname, &range) < 0) memset(&range, 0, sizeof(range)); /* Prepare the request */ wrq.u.txpower.value = -1; wrq.u.txpower.fixed = 1; wrq.u.txpower.disabled = 0; wrq.u.data.flags = IW_TXPOW_DBM; if(!strcasecmp(args[i], "off")) wrq.u.txpower.disabled = 1; /* i.e. turn radio off */ else if(!strcasecmp(args[i], "auto")) wrq.u.txpower.fixed = 0; /* i.e. use power control */ else { if(!strcasecmp(args[i], "fixed")) { /* Get old tx-power */ IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq, "Set Tx Power"); wrq.u.txpower.fixed = 1; } else /* Should be a numeric value */ { int power; int ismwatt = 0; /* Get the value */ if(sscanf(args[i], "%i", &(power)) != 1) ABORT_ARG_TYPE("Set Tx Power", SIOCSIWTXPOW, args[i]); /* Check if milliwatt */ ismwatt = (index(args[i], 'm') != NULL); /* Convert */ if(range.txpower_capa & IW_TXPOW_MWATT) { if(!ismwatt) power = iw_dbm2mwatt(power); wrq.u.data.flags = IW_TXPOW_MWATT; } else { if(ismwatt) power = iw_mwatt2dbm(power); wrq.u.data.flags = IW_TXPOW_DBM; } wrq.u.txpower.value = power; /* Check for an additional argument */ if(((i+1) < count) && (!strcasecmp(args[i+1], "auto"))) { wrq.u.txpower.fixed = 0; ++i; } if(((i+1) < count) && (!strcasecmp(args[i+1], "fixed"))) { wrq.u.txpower.fixed = 1; ++i; } } } IW_SET_EXT_ERR(skfd, ifname, SIOCSIWTXPOW, &wrq, "Set Tx Power"); continue; } #endif #if WIRELESS_EXT > 10 /* ---------- Set Retry limit ---------- */ if(!strncmp(args[i], "retry", 3)) { double temp; int gotone = 0; if(++i >= count) ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); /* Default - nope */ wrq.u.retry.flags = IW_RETRY_LIMIT; wrq.u.retry.disabled = 0; /* Check value modifier */ if(!strcasecmp(args[i], "min")) { wrq.u.retry.flags |= IW_RETRY_MIN; if(++i >= count) ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); } else if(!strcasecmp(args[i], "max")) { wrq.u.retry.flags |= IW_RETRY_MAX; if(++i >= count) ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); } /* Check value type */ if(!strcasecmp(args[i], "limit")) { wrq.u.retry.flags |= IW_RETRY_LIMIT; if(++i >= count) ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); } else if(!strncasecmp(args[i], "lifetime", 4)) { wrq.u.retry.flags &= ~IW_RETRY_LIMIT; wrq.u.retry.flags |= IW_RETRY_LIFETIME; if(++i >= count) ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY); } /* Is there any value to grab ? */ if(sscanf(args[i], "%lg", &(temp)) == 1) { /* Limit is absolute, on the other hand lifetime is seconds */ if(!(wrq.u.retry.flags & IW_RETRY_LIMIT)) { /* Normalise lifetime */ temp *= MEGA; /* default = s */ if(index(args[i], 'u')) temp /= MEGA; if(index(args[i], 'm')) temp /= KILO; } wrq.u.retry.value = (long) temp; ++i; gotone = 1; } if(!gotone) ABORT_ARG_TYPE("Set Retry Limit", SIOCSIWRETRY, args[i]); --i; IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRETRY, &wrq, "Set Retry Limit"); continue; } #endif /* WIRELESS_EXT > 10 */ /* ---------- Other ---------- */ /* Here we have an unrecognised arg... */ fprintf(stderr, "Error : unrecognised wireless request \"%s\"\n", args[i]); return(-1); } /* for(index ... */ return(0); }
/* * Print the number of available encryption key for the device */ static int print_keys_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; unsigned char key[IW_ENCODING_TOKEN_MAX]; int k; char buffer[128]; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Extract range info */ if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.16s no encryption keys information.\n\n", ifname); else { printf("%-8.16s ", ifname); /* Print key sizes */ if((range.num_encoding_sizes > 0) && (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES)) { printf("%d key sizes : %d", range.num_encoding_sizes, range.encoding_size[0] * 8); /* Print them all */ for(k = 1; k < range.num_encoding_sizes; k++) printf(", %d", range.encoding_size[k] * 8); printf("bits\n "); } /* Print the keys and associate mode */ printf("%d keys available :\n", range.max_encoding_tokens); for(k = 1; k <= range.max_encoding_tokens; k++) { wrq.u.data.pointer = (caddr_t) key; wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = k; if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0) { fprintf(stderr, "Error reading wireless keys (SIOCGIWENCODE): %s\n", strerror(errno)); break; } if((wrq.u.data.flags & IW_ENCODE_DISABLED) || (wrq.u.data.length == 0)) printf("\t\t[%d]: off\n", k); else { /* Display the key */ iw_print_key(buffer, sizeof(buffer), key, wrq.u.data.length, wrq.u.data.flags); printf("\t\t[%d]: %s", k, buffer); /* Other info... */ printf(" (%d bits)", wrq.u.data.length * 8); printf("\n"); } } /* Print current key and mode */ wrq.u.data.pointer = (caddr_t) key; wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; /* Set index to zero to get current */ if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0) { /* Note : if above fails, we have already printed an error * message int the loop above */ printf(" Current Transmit Key: [%d]\n", wrq.u.data.flags & IW_ENCODE_INDEX); if(wrq.u.data.flags & IW_ENCODE_RESTRICTED) printf(" Security mode:restricted\n"); if(wrq.u.data.flags & IW_ENCODE_OPEN) printf(" Security mode:open\n"); } /* Print WPA/802.1x/802.11i security parameters */ if(range.we_version_compiled > 17) { /* Display advance encryption capabilities */ if(range.enc_capa) { const char * auth_string[] = { "WPA", "WPA2", "CIPHER TKIP", "CIPHER CCMP" }; const int auth_num = (sizeof(auth_string) / sizeof(auth_string[1])); int i; int mask = 0x1; printf(" Authentication capabilities :\n"); for(i = 0; i < auth_num; i++) { if(range.enc_capa & mask) printf("\t\t%s\n", auth_string[i]); mask <<= 1; } } /* Current values for authentication */ wrq.u.param.flags = IW_AUTH_KEY_MGMT; if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0) printf(" Current key_mgmt:0x%X\n", wrq.u.param.value); wrq.u.param.flags = IW_AUTH_CIPHER_PAIRWISE; if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0) printf(" Current cipher_pairwise:0x%X\n", wrq.u.param.value); wrq.u.param.flags = IW_AUTH_CIPHER_GROUP; if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0) printf(" Current cipher_group:0x%X\n", wrq.u.param.value); } printf("\n\n"); } return(0); }
int netproc_scandevice(int sockfd, int iwsockfd, FILE *fp, NETDEVLIST_PTR *netdev_list) { char buffer[512]; int count = 0; int prx_idx, ptx_idx, brx_idx, btx_idx; gulong in_packets, out_packets, in_bytes, out_bytes; NETDEVLIST_PTR devptr = NULL; /* interface information */ struct ifreq ifr; struct ethtool_test edata; iwstats iws; char *status; char *name; struct iw_range iwrange; int has_iwrange = 0; status = fgets (buffer, sizeof(buffer), fp); if (!status) ERR("netstat: netproc_scnadevice(): Error reading first line from stream!\n"); status = fgets (buffer, sizeof(buffer), fp); if (!status) ERR("netstat: netproc_scnadevice(): Error reading second line from stream!\n"); netproc_parse_stats_header(buffer, &prx_idx, &ptx_idx, &brx_idx, &btx_idx); while (fgets(buffer, sizeof(buffer), fp)) { /* getting interface name */ name = buffer; while (g_ascii_isspace(name[0])) { name++; } /* reading packet infomation */ status = netproc_parse_ifname(name); netproc_parse_status(status, prx_idx, ptx_idx, &in_packets, &out_packets, brx_idx, btx_idx, &in_bytes, &out_bytes); /* check interface hw_type */ bzero(&ifr, sizeof(ifr)); strncpy(ifr.ifr_name, name, strlen(name)); ifr.ifr_name[strlen(name)+1] = '\0'; if (ioctl(sockfd, SIOCGIFHWADDR, &ifr)<0) continue; /* hw_types is not Ethernet and PPP */ if (ifr.ifr_hwaddr.sa_family!=ARPHRD_ETHER&&ifr.ifr_hwaddr.sa_family!=ARPHRD_PPP) continue; /* detecting new interface */ if ((devptr = netproc_netdevlist_find(*netdev_list, name))==NULL) { /* check wireless device */ has_iwrange = (iw_get_range_info(iwsockfd, name, &iwrange)>=0); if (!(has_iwrange) || (iwrange.we_version_compiled < 14)) netproc_netdevlist_add(netdev_list, name, in_bytes, in_packets, out_bytes, out_packets, FALSE); else netproc_netdevlist_add(netdev_list, name, in_bytes, in_packets, out_bytes, out_packets, TRUE); devptr = netproc_netdevlist_find(*netdev_list, name); /* MAC Address */ devptr->info.mac = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", ifr.ifr_hwaddr.sa_data[0] & 0377, ifr.ifr_hwaddr.sa_data[1] & 0377, ifr.ifr_hwaddr.sa_data[2] & 0377, ifr.ifr_hwaddr.sa_data[3] & 0377, ifr.ifr_hwaddr.sa_data[4] & 0377, ifr.ifr_hwaddr.sa_data[5] & 0377); } else { /* Setting device status and update flags */ if (devptr->info.recv_packets!=in_packets&&devptr->info.trans_packets!=out_packets) { if (devptr->info.status!=NETDEV_STAT_BOTHRS) devptr->info.updated = TRUE; devptr->info.status = NETDEV_STAT_BOTHRS; } else if (devptr->info.recv_packets!=in_packets) { if (devptr->info.status!=NETDEV_STAT_RECVDATA) devptr->info.updated = TRUE; devptr->info.status = NETDEV_STAT_RECVDATA; } else if (devptr->info.trans_packets!=out_packets) { if (devptr->info.status!=NETDEV_STAT_SENDDATA) devptr->info.updated = TRUE; devptr->info.status = NETDEV_STAT_SENDDATA; } else { if (devptr->info.status!=NETDEV_STAT_NORMAL) devptr->info.updated = TRUE; devptr->info.status = NETDEV_STAT_NORMAL; } /* Recording r/t information */ devptr->info.recv_bytes = in_bytes; devptr->info.recv_packets = in_packets; devptr->info.trans_bytes = out_bytes; devptr->info.trans_packets = out_packets; /* give device a life */ devptr->info.alive = TRUE; } /* Enable */ bzero(&ifr, sizeof(ifr)); strcpy(ifr.ifr_name, devptr->info.ifname); ifr.ifr_name[IF_NAMESIZE - 1] = '\0'; if (ioctl(sockfd, SIOCGIFFLAGS, &ifr)>=0) { devptr->info.flags = ifr.ifr_flags; if (ifr.ifr_flags & IFF_UP) { devptr->info.enable = TRUE; devptr->info.updated = TRUE; } else { devptr->info.enable = FALSE; devptr->info.updated = TRUE; } if (devptr->info.enable) { /* Workaround for Atheros Cards */ if (strncmp(devptr->info.ifname, "ath", 3)==0) wireless_refresh(iwsockfd, devptr->info.ifname); /* plug */ bzero(&ifr, sizeof(ifr)); strcpy(ifr.ifr_name, devptr->info.ifname); ifr.ifr_name[IF_NAMESIZE - 1] = '\0'; edata.cmd = 0x0000000a; ifr.ifr_data = (caddr_t)&edata; if (ioctl(sockfd, SIOCETHTOOL, &ifr)<0) { /* using IFF_RUNNING instead due to system doesn't have ethtool or working in non-root */ if (devptr->info.flags & IFF_RUNNING) { if (!devptr->info.plug) { devptr->info.plug = TRUE; devptr->info.updated = TRUE; } } else if (devptr->info.plug) { devptr->info.plug = FALSE; devptr->info.updated = TRUE; } } else { if (edata.data) { if (!devptr->info.plug) { devptr->info.plug = TRUE; devptr->info.updated = TRUE; } } else if (devptr->info.plug) { devptr->info.plug = FALSE; devptr->info.updated = TRUE; } } /* get network information */ if (devptr->info.enable&&devptr->info.plug) { if (devptr->info.flags & IFF_RUNNING) { /* release old information */ g_free(devptr->info.ipaddr); g_free(devptr->info.bcast); g_free(devptr->info.mask); /* IP Address */ bzero(&ifr, sizeof(ifr)); strcpy(ifr.ifr_name, devptr->info.ifname); ifr.ifr_name[IF_NAMESIZE - 1] = '\0'; if (ioctl(sockfd, SIOCGIFADDR, &ifr)<0) devptr->info.ipaddr = g_strdup("0.0.0.0"); else devptr->info.ipaddr = g_strdup(inet_ntoa(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr)); /* Point-to-Porint Address */ if (devptr->info.flags & IFF_POINTOPOINT) { bzero(&ifr, sizeof(ifr)); strcpy(ifr.ifr_name, devptr->info.ifname); ifr.ifr_name[IF_NAMESIZE - 1] = '\0'; if (ioctl(sockfd, SIOCGIFDSTADDR, &ifr)<0) devptr->info.dest = NULL; else devptr->info.dest = g_strdup(inet_ntoa(((struct sockaddr_in*)&ifr.ifr_dstaddr)->sin_addr)); } /* Broadcast */ if (devptr->info.flags & IFF_BROADCAST) { bzero(&ifr, sizeof(ifr)); strcpy(ifr.ifr_name, devptr->info.ifname); ifr.ifr_name[IF_NAMESIZE - 1] = '\0'; if (ioctl(sockfd, SIOCGIFBRDADDR, &ifr)<0) devptr->info.bcast = NULL; else devptr->info.bcast = g_strdup(inet_ntoa(((struct sockaddr_in*)&ifr.ifr_broadaddr)->sin_addr)); } /* Netmask */ bzero(&ifr, sizeof(ifr)); strcpy(ifr.ifr_name, devptr->info.ifname); ifr.ifr_name[IF_NAMESIZE - 1] = '\0'; if (ioctl(sockfd, SIOCGIFNETMASK, &ifr)<0) devptr->info.mask = NULL; else devptr->info.mask = g_strdup(inet_ntoa(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr)); /* Wireless Information */ if (devptr->info.wireless) { struct wireless_config wconfig; /* get wireless config */ if (iw_get_basic_config(iwsockfd, devptr->info.ifname, &wconfig)>=0) { /* Protocol */ devptr->info.protocol = g_strdup(wconfig.name); /* ESSID */ devptr->info.essid = g_strdup(wconfig.essid); /* Signal Quality */ iw_get_stats(iwsockfd, devptr->info.ifname, &iws, &iwrange, has_iwrange); devptr->info.quality = rint((log (iws.qual.qual) / log (92)) * 100.0); } } /* check problem connection */ if (strcmp(devptr->info.ipaddr, "0.0.0.0")==0) { devptr->info.status = NETDEV_STAT_PROBLEM; /* has connection problem */ if (devptr->info.connected) { devptr->info.connected = FALSE; devptr->info.updated = TRUE; } } else if (!devptr->info.connected) { devptr->info.status = NETDEV_STAT_NORMAL; devptr->info.connected = TRUE; devptr->info.updated = TRUE; } } else { /* has connection problem */ devptr->info.status = NETDEV_STAT_PROBLEM; if (devptr->info.connected) { devptr->info.connected = FALSE; devptr->info.updated = TRUE; } } } } } devptr = NULL; count++; } rewind(fp); fflush(fp); return count; }
/* * Print Retry info for each device */ static int print_retry_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; char buffer[128]; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Extract range info */ if((iw_get_range_info(skfd, ifname, &range) < 0) || (range.we_version_compiled < 11)) fprintf(stderr, "%-8.16s no retry limit/lifetime information.\n\n", ifname); else { printf("%-8.16s ", ifname); /* Display min/max limit availables */ if(range.retry_flags & IW_RETRY_LIMIT) { int flags = (range.retry_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX)); /* Display if auto or fixed */ if(range.retry_flags & IW_RETRY_MIN) printf("Auto limit ; "); else printf("Fixed limit ; "); /* Print the range */ iw_print_retry_value(buffer, sizeof(buffer), range.min_retry, flags | IW_RETRY_MIN); printf("%s\n ", buffer); iw_print_retry_value(buffer, sizeof(buffer), range.max_retry, flags | IW_RETRY_MAX); printf("%s\n ", buffer); } /* Display min/max lifetime availables */ if(range.r_time_flags & IW_RETRY_LIFETIME) { int flags = (range.r_time_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX)); /* Display if auto or fixed */ if(range.r_time_flags & IW_RETRY_MIN) printf("Auto lifetime ; "); else printf("Fixed lifetime ; "); /* Print the range */ iw_print_retry_value(buffer, sizeof(buffer), range.min_r_time, flags | IW_RETRY_MIN); printf("%s\n ", buffer); iw_print_retry_value(buffer, sizeof(buffer), range.max_r_time, flags | IW_RETRY_MAX); printf("%s\n ", buffer); } /* Get current retry settings */ wrq.u.retry.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0) { int flags = wrq.u.retry.flags; /* Is it disabled ? */ if(wrq.u.retry.disabled) printf("Current mode:off\n "); else { int retry_mask = 0; /* Let's check the mode */ printf("Current mode:on\n "); /* Let's check the value and its type */ if(wrq.u.retry.flags & IW_RETRY_TYPE) { iw_print_retry_value(buffer, sizeof(buffer), wrq.u.retry.value, wrq.u.retry.flags); printf("%s\n ", buffer); } /* If we have been returned a MIN value, ask for the MAX */ if(flags & IW_RETRY_MIN) retry_mask = IW_RETRY_MAX; /* If we have been returned a MAX value, ask for the MIN */ if(flags & IW_RETRY_MAX) retry_mask = IW_RETRY_MIN; /* If we have something to ask for... */ if(retry_mask) get_retry_value(skfd, ifname, &wrq, retry_mask, buffer, sizeof(buffer)); /* And if we have both a period and a timeout, ask the other */ retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) & IW_RETRY_TYPE)); if(retry_mask) { int base_mask = retry_mask; flags = get_retry_value(skfd, ifname, &wrq, retry_mask, buffer, sizeof(buffer)); retry_mask = 0; /* If we have been returned a MIN value, ask for the MAX */ if(flags & IW_RETRY_MIN) retry_mask = IW_RETRY_MAX | base_mask; /* If we have been returned a MAX value, ask for the MIN */ if(flags & IW_RETRY_MAX) retry_mask = IW_RETRY_MIN | base_mask; /* If we have something to ask for... */ if(retry_mask) get_retry_value(skfd, ifname, &wrq, retry_mask, buffer, sizeof(buffer)); } } } printf("\n"); } return(0); }
/* * Set Tx Power */ static int set_txpower_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i = 1; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Prepare the request */ wrq.u.txpower.value = -1; wrq.u.txpower.fixed = 1; wrq.u.txpower.disabled = 0; wrq.u.txpower.flags = IW_TXPOW_DBM; if(!strcasecmp(args[0], "off")) wrq.u.txpower.disabled = 1; /* i.e. turn radio off */ else if(!strcasecmp(args[0], "auto")) wrq.u.txpower.fixed = 0; /* i.e. use power control */ else { if(!strcasecmp(args[0], "on")) { /* Get old tx-power */ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.txpower.disabled = 0; } else { if(!strcasecmp(args[0], "fixed")) { /* Get old tx-power */ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.txpower.fixed = 1; wrq.u.txpower.disabled = 0; } else /* Should be a numeric value */ { int power; int ismwatt = 0; struct iw_range range; /* Extract range info to do proper conversion */ if(iw_get_range_info(skfd, ifname, &range) < 0) memset(&range, 0, sizeof(range)); /* Get the value */ if(sscanf(args[0], "%i", &(power)) != 1) { errarg = 0; return(IWERR_ARG_TYPE); } /* Check if milliWatt * We authorise a single 'm' as a shorthand for 'mW', * on the other hand a 'd' probably means 'dBm'... */ ismwatt = ((strchr(args[0], 'm') != NULL) && (strchr(args[0], 'd') == NULL)); /* We could check 'W' alone... Another time... */ /* Convert */ if(range.txpower_capa & IW_TXPOW_RELATIVE) { /* Can't convert */ if(ismwatt) { errarg = 0; return(IWERR_ARG_TYPE); } wrq.u.txpower.flags = IW_TXPOW_RELATIVE; } else if(range.txpower_capa & IW_TXPOW_MWATT) { if(!ismwatt) power = iw_dbm2mwatt(power); wrq.u.txpower.flags = IW_TXPOW_MWATT; } else { if(ismwatt) power = iw_mwatt2dbm(power); wrq.u.txpower.flags = IW_TXPOW_DBM; } wrq.u.txpower.value = power; /* Check for an additional argument */ if((i < count) && (!strcasecmp(args[i], "auto"))) { wrq.u.txpower.fixed = 0; ++i; } if((i < count) && (!strcasecmp(args[i], "fixed"))) { wrq.u.txpower.fixed = 1; ++i; } } } } if(iw_set_ext(skfd, ifname, SIOCSIWTXPOW, &wrq) < 0) return(IWERR_SET_EXT); /* Var args */ return(i); }
void CWextHW::readSignalQuality() { if ( (m_wextFd == -1) ) { return; } struct iw_range range; memset(&range,0,sizeof(struct iw_range)); int hasRange = 0; iwstats stats; memset(&stats,0,sizeof(iwstats)); WextRawScan res; /* workaround */ struct wireless_config wifiConfig; memset(&wifiConfig,0,sizeof(struct wireless_config)); /* Get basic information */ if(iw_get_basic_config(m_wextFd, m_ifname.toAscii().constData(), &wifiConfig) < 0) { /* If no wireless name : no wireless extensions */ /* But let's check if the interface exists at all */ struct ifreq ifr; memset(&ifr,0,sizeof(struct ifreq)); strncpy(ifr.ifr_name, m_ifname.toAscii().data(), IFNAMSIZ); if(ioctl(m_wextFd, SIOCGIFFLAGS, &ifr) < 0) qWarning() << tr("(Wireless Extension) No device present"); else qWarning() << tr("(Wireless Extension) device not supported"); return; } qDebug() << "Fetched basic config."; //We encode frequency in mhz; //kernel encodes as double; (hopefully always in hz) //But better test this: res.freq = -1; if (wifiConfig.has_freq) { if ( ( (wifiConfig.freq/1e9) < 10.0 ) && ( (wifiConfig.freq/1e9) > 0.0 ) ) { res.freq = (int) (wifiConfig.freq/1e6); } } struct iwreq wrq; memset(&wrq,0,sizeof(struct iwreq)); /* Get AP address */ if(iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWAP, &wrq) >= 0) { //Add mac address of current ap; res.bssid = libnutcommon::MacAddress((ether_addr*)wrq.u.ap_addr.sa_data); qDebug() << "Got AP: " << res.bssid.toString(); } /* Get ssid */ quint8 * buffer = new quint8[IW_ESSID_MAX_SIZE]; memset(buffer, '\0', IW_ESSID_MAX_SIZE); wrq.u.essid.pointer = (void *)buffer; wrq.u.essid.length = IW_ESSID_MAX_SIZE; if(iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWESSID, &wrq) >= 0) { if (wrq.u.essid.length > IW_ESSID_MAX_SIZE) wrq.u.essid.length = IW_ESSID_MAX_SIZE; if (wrq.u.essid.flags) { /* Does it have an ESSID index ? */ if ( wrq.u.essid.pointer && wrq.u.essid.length ) { if ( (wrq.u.essid.flags & IW_ENCODE_INDEX) > 1) { res.ssid = QString("%1 [%2]").arg(QString::fromAscii((char*) wrq.u.essid.pointer, wrq.u.essid.length), QString::number(wrq.u.essid.flags & IW_ENCODE_INDEX)); } else { res.ssid = QString::fromAscii((char*) wrq.u.essid.pointer, wrq.u.essid.length); } } else { res.ssid = "N/A"; } } qDebug() << "Got ssid: " << res.ssid; } delete[] buffer; /* Get bit rate */ if(iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWRATE, &wrq) >= 0) { res.bitrates.append((qint32) wrq.u.bitrate.value); qDebug() << "Got bit rate: " << res.bitrates[0]; } /* Get Power Management settings */ wrq.u.power.flags = 0; if(iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWPOWER, &wrq) >= 0) { qDebug() << "Got power"; } /* workaround */ /* Get range stuff */ qDebug() << QString("Getting range stuff for %1").arg(m_ifname.toAscii().data()); if (iw_get_range_info(m_wextFd, m_ifname.toAscii().data(), &range) >= 0) { hasRange = 1; qDebug() << "Success readWirelessInfo getrange" << strerror(errno); } else { //This is VERY strange: we always get the "operation not permitted" error, although iw_get_range() worked qDebug() << QString("Error \"hasRange == 0\" (%1)").arg(strerror(errno)); } res.hasRange = hasRange; if (errno == EAGAIN) { m_sqTimeOutCount++; qDebug() << QString("Getting range stuff failed (%1)").arg(strerror(errno)); if ( (m_sqTimeOutCount > 10) && m_sqPollrate < 1000) { setSignalQualityPollRate(10000); } else if (m_sqTimeOutCount > 10) { //Fast polling disabled, but still EAGAIN errors //Seems the kernel does not care about our calls killTimer(m_sqTimerId); m_sqTimerId = -1; } return; } qDebug() << "Got range stuff"; //Set supported Frequencies if the list is not empty; if (m_supportedFrequencies.isEmpty() && hasRange) { qDebug() << range.num_frequency; qDebug() << "Printing Frequency information"; quint32 m; quint16 e; quint32 freqinmhz; for (int i=0; i < range.num_channels; i++) { m = (quint32) range.freq[i].m; e = (quint16) range.freq[i].e; freqinmhz = m; for (int j=0; j < 9-e-3; j++) { freqinmhz = freqinmhz/10; } if (!m_supportedFrequencies.contains(freqinmhz)) { //Only add frequency that are not in our list m_supportedFrequencies.append(freqinmhz); } qDebug() << m << e << freqinmhz << frequencyToChannel(freqinmhz); } qDebug() << "Done printing"; } else { qDebug() << "m_supportedFrequencies not set"; } if (hasRange) { res.maxquality.level = (quint8) range.max_qual.level; res.maxquality.qual = (quint8) range.max_qual.qual; res.maxquality.noise = (quint8) range.max_qual.noise; res.maxquality.updated = (quint8) range.max_qual.updated; qDebug() << "RANGE: " << res.maxquality.level << res.maxquality.qual << res.maxquality.noise << res.maxquality.updated; } else { res.maxquality.level = 0; res.maxquality.qual = 0; res.maxquality.noise = 0; res.maxquality.updated = 0; qDebug() << "Range information are not available"; } if ( (hasRange) && (range.we_version_compiled > 11) ) { struct iwreq wrq; memset(&wrq,0,sizeof(struct iwreq)); wrq.u.data.pointer = (caddr_t) &stats; wrq.u.data.length = sizeof(struct iw_statistics); wrq.u.data.flags = 1; // Clear updated flag strncpy(wrq.ifr_name, m_ifname.toAscii().data(), IFNAMSIZ); qDebug() << "Getting wireless stats"; if(iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWSTATS, &wrq) < 0) { qWarning() << tr("Error occured while fetching wireless info: ") << strerror(errno); } else { //Stats fetched qDebug() << "Stats fetched"; res.quality.level = (quint8) stats.qual.level; res.quality.qual = (quint8) stats.qual.qual; res.quality.noise = (quint8) stats.qual.noise; res.quality.updated = (quint8) stats.qual.updated; qDebug() << "STATS: " << res.quality.level << res.quality.qual << res.quality.noise << res.quality.updated; m_sq = convertValues(res); qDebug() << "Emittig m_signalQualityUpdated()"; if (m_sqPollrate < 1000) { setSignalQualityPollRate(10000); emit message(tr("Auto-resetting timer to 10 seconds")); } emit signalQualityUpdated(m_sq); } } else if (range.we_version_compiled <= 11) { emit message(tr("Cannot fetch wireless information as your wireless extension is too old")); emit message(tr("Think about updating your kernel (it's way too old)")); } else { qDebug() << "Error while trying to fetch wireless information" << strerror(errno); qDebug() << "Wireless Extension socket file descriptor was: " << m_wextFd; } }
/* * Get wireless informations & config from the device driver * We will call all the classical wireless ioctl on the driver through * the socket to know what is supported and to get the settings... */ static int get_info(int skfd, char * ifname, struct wireless_info * info) { struct iwreq wrq; memset((char *) info, 0, sizeof(struct wireless_info)); /* Get basic information */ if(iw_get_basic_config(skfd, ifname, &(info->b)) < 0) { /* If no wireless name : no wireless extensions */ /* But let's check if the interface exists at all */ struct ifreq ifr; strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) return(-ENODEV); else return(-ENOTSUP); } /* Get ranges */ if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0) info->has_range = 1; /* 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 bit rate */ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0) { info->has_bitrate = 1; memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam)); } /* 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)); } /* Get stats */ if(iw_get_stats(skfd, ifname, &(info->stats), &info->range, info->has_range) >= 0) { info->has_stats = 1; } #ifndef WE_ESSENTIAL /* 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; if((info->has_range) && (info->range.we_version_compiled > 9)) { /* Get Transmit Power */ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0) { info->has_txpower = 1; memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam)); } } /* Get sensitivity */ if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0) { info->has_sens = 1; memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam)); } if((info->has_range) && (info->range.we_version_compiled > 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)); } } /* 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)); } #endif /* WE_ESSENTIAL */ return(0); }
/* * Perform a scanning on one device */ static int print_scanning_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; unsigned char * buffer = NULL; /* Results */ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */ struct iw_range range; int has_range; struct timeval tv; /* Select timeout */ int timeout = 15000000; /* 15s */ /* Avoid "Unused parameter" warning */ args = args; count = count; /* Get range stuff */ has_range = (iw_get_range_info(skfd, ifname, &range) >= 0); /* Check if the interface could support scanning. */ if((!has_range) || (range.we_version_compiled < 14)) { fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n", ifname); return(-1); } /* Init timeout value -> 250ms*/ tv.tv_sec = 0; tv.tv_usec = 250000; /* * Here we should look at the command line args and set the IW_SCAN_ flags * properly */ wrq.u.data.pointer = NULL; /* Later */ wrq.u.data.flags = 0; wrq.u.data.length = 0; /* Initiate Scanning */ if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0) { if(errno != EPERM) { fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n", ifname, strerror(errno)); return(-1); } /* If we don't have the permission to initiate the scan, we may * still have permission to read left-over results. * But, don't wait !!! */ #if 0 /* Not cool, it display for non wireless interfaces... */ fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname); #endif tv.tv_usec = 0; } timeout -= tv.tv_usec; /* Forever */ while(1) { fd_set rfds; /* File descriptors for select */ int last_fd; /* Last fd */ int ret; /* Guess what ? We must re-generate rfds each time */ FD_ZERO(&rfds); last_fd = -1; /* In here, add the rtnetlink fd in the list */ /* Wait until something happens */ ret = select(last_fd + 1, &rfds, NULL, NULL, &tv); /* Check if there was an error */ if(ret < 0) { if(errno == EAGAIN || errno == EINTR) continue; fprintf(stderr, "Unhandled signal - exiting...\n"); return(-1); } /* Check if there was a timeout */ if(ret == 0) { unsigned char * newbuf; realloc: /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */ newbuf = realloc(buffer, buflen); if(newbuf == NULL) { if(buffer) free(buffer); fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__); return(-1); } buffer = newbuf; /* Try to read the results */ wrq.u.data.pointer = buffer; wrq.u.data.flags = 0; wrq.u.data.length = buflen; if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0) { /* Check if buffer was too small (WE-17 only) */ if((errno == E2BIG) && (range.we_version_compiled > 16)) { /* Some driver may return very large scan results, either * because there are many cells, or because they have many * large elements in cells (like IWEVCUSTOM). Most will * only need the regular sized buffer. We now use a dynamic * allocation of the buffer to satisfy everybody. Of course, * as we don't know in advance the size of the array, we try * various increasing sizes. Jean II */ /* Check if the driver gave us any hints. */ if(wrq.u.data.length > buflen) buflen = wrq.u.data.length; else buflen *= 2; /* Try again */ goto realloc; } /* Check if results not available yet */ if(errno == EAGAIN) { /* Restart timer for only 100ms*/ tv.tv_sec = 0; tv.tv_usec = 100000; timeout -= tv.tv_usec; if(timeout > 0) continue; /* Try again later */ } /* Bad error */ free(buffer); fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n", ifname, strerror(errno)); return(-2); } else /* We have the results, go to process them */ break; } /* In here, check if event and event type * if scan event, read results. All errors bad & no reset timeout */ } if(wrq.u.data.length) { struct iw_event iwe; struct stream_descr stream; struct iwscan_state state = { .ap_num = 1, .val_index = 0 }; int ret; #if 0 /* Debugging code. In theory useless, because it's debugged ;-) */ int i; printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]); for(i = 1; i < wrq.u.data.length; i++) printf(":%02X", buffer[i]); printf("]\n"); #endif printf("%-8.16s Scan completed :\n", ifname); iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length); do { /* Extract an event and print it */ ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled); if(ret > 0) print_scanning_token(&stream, &iwe, &state, &range, has_range); } while(ret > 0); printf("\n"); } else printf("%-8.16s No scan results\n", ifname); free(buffer); return(0); }