📄 iwlib.c
字号:
info->has_freq = 1; info->freq = iw_freq2float(&(wrq.u.freq)); } /* 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 operation mode */ if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0) { info->mode = wrq.u.mode; if((info->mode < 6) && (info->mode >= 0)) info->has_mode = 1; } return(0);}/*------------------------------------------------------------------*//* * Set essential wireless config in the device driver * We will call all the classical wireless ioctl on the driver through * the socket to know what is supported and to set the settings... * We support only the restricted set as above... */intiw_set_basic_config(int skfd, char * ifname, wireless_config * info){ struct iwreq wrq; int ret = 0; /* Get wireless name (check if interface is valid) */ if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0) /* If no wireless name : no wireless extensions */ return(-2); /* Set Network ID, if available (this is for non-802.11 cards) */ if(info->has_nwid) { memcpy(&(wrq.u.nwid), &(info->nwid), sizeof(iwparam)); wrq.u.nwid.fixed = 1; /* Hum... When in Rome... */ if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0) { fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno)); ret = -1; } } /* Set frequency / channel */ if(info->has_freq) { iw_float2freq(info->freq, &(wrq.u.freq)); if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0) { fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno)); ret = -1; } } /* Set encryption information */ if(info->has_key) { int flags = info->key_flags; /* Check if there is a key index */ if((flags & IW_ENCODE_INDEX) > 0) { /* Set the index */ wrq.u.data.pointer = (caddr_t) NULL; wrq.u.data.flags = (flags & (IW_ENCODE_INDEX)) | IW_ENCODE_NOKEY; wrq.u.data.length = 0; if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", errno, strerror(errno)); ret = -1; } } /* Mask out index to minimise probability of reject when setting key */ flags = flags & (~IW_ENCODE_INDEX); /* Set the key itself (set current key in this case) */ wrq.u.data.pointer = (caddr_t) info->key; wrq.u.data.length = info->key_size; wrq.u.data.flags = flags; if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", errno, strerror(errno)); ret = -1; } } /* Set ESSID (extended network), if available */ if(info->has_essid) { wrq.u.essid.pointer = (caddr_t) info->essid; wrq.u.essid.length = strlen(info->essid) + 1; wrq.u.data.flags = info->essid_on; if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0) { fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno)); ret = -1; } } /* Set the current mode of operation */ if(info->has_mode) { strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.mode = info->mode; if(iw_get_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno)); ret = -1; } } return(ret);}/*********************** PROTOCOL SUBROUTINES ***********************//* * Fun stuff with protocol identifiers (SIOCGIWNAME). * We assume that drivers are returning sensible values in there, * which is not always the case :-( *//*------------------------------------------------------------------*//* * Compare protocol identifiers. * We don't want to know if the two protocols are the exactly same, * but if they interoperate at some level, and also if they accept the * same type of config (ESSID vs NWID, freq...). * This is supposed to work around the alphabet soup. * Return 1 if protocols are compatible */intiw_protocol_compare(char * protocol1, char * protocol2){ char * dot11 = "IEEE 802.11"; char * dot11_ds = "Dbg"; /* If the strings are the same -> easy */ if(!strncmp(protocol1, protocol2, IFNAMSIZ)) return(1); /* Are we dealing with one of the 802.11 variant ? */ if( (!strncmp(protocol1, dot11, strlen(dot11))) && (!strncmp(protocol2, dot11, strlen(dot11))) ) { char * sub1 = protocol1 + strlen(dot11); char * sub2 = protocol2 + strlen(dot11); /* Skip optional separator */ if(*sub1 == '-') sub1++; if(*sub2 == '-') sub2++; /* Check if they are both 2.4 GHz Direct Sequence compatible */ if( (strchr(dot11_ds, *sub1) != NULL) && (strchr(dot11_ds, *sub2) != NULL) ) return(1); } /* Not compatible */ return(0);}/********************** FREQUENCY SUBROUTINES ***********************//* * Note : the two functions below are the cause of troubles on * various embeeded platforms, as they are the reason we require * libm (math library). * In this case, please use enable BUILD_NOLIBM in the makefile * * FIXME : check negative mantissa and exponent *//*------------------------------------------------------------------*//* * Convert a floating point the our internal representation of * frequencies. * The kernel doesn't want to hear about floating point, so we use * this custom format instead. */voidiw_float2freq(double in, iwfreq * out){#ifdef WE_NOLIBM /* Version without libm : slower */ out->e = 0; while(in > 1e9) { in /= 10; out->e++; } out->m = (long) in;#else /* WE_NOLIBM */ /* Version with libm : faster */ out->e = (short) (floor(log10(in))); if(out->e > 8) { out->m = ((long) (floor(in / pow(10,out->e - 6)))) * 100; out->e -= 8; } else { out->m = (long) in; out->e = 0; }#endif /* WE_NOLIBM */}/*------------------------------------------------------------------*//* * Convert our internal representation of frequencies to a floating point. */doubleiw_freq2float(iwfreq * in){#ifdef WE_NOLIBM /* Version without libm : slower */ int i; double res = (double) in->m; for(i = 0; i < in->e; i++) res *= 10; return(res);#else /* WE_NOLIBM */ /* Version with libm : faster */ return ((double) in->m) * pow(10,in->e);#endif /* WE_NOLIBM */}/*------------------------------------------------------------------*//* * Output a frequency with proper scaling */voidiw_print_freq(char * buffer, double freq){ if(freq < KILO) sprintf(buffer, "Channel:%g", freq); else { if(freq >= GIGA) sprintf(buffer, "Frequency:%gGHz", freq / GIGA); else { if(freq >= MEGA) sprintf(buffer, "Frequency:%gMHz", freq / MEGA); else sprintf(buffer, "Frequency:%gkHz", freq / KILO); } }}/*------------------------------------------------------------------*//* * Convert a frequency to a channel (negative -> error) */intiw_freq_to_channel(double freq, struct iw_range * range){ double ref_freq; int k; /* Check if it's a frequency or not already a channel */ if(freq < KILO) return(-1); /* We compare the frequencies as double to ignore differences * in encoding. Slower, but safer... */ for(k = 0; k < range->num_frequency; k++) { ref_freq = iw_freq2float(&(range->freq[k])); if(freq == ref_freq) return(range->freq[k].i); } /* Not found */ return(-2);}/*********************** BITRATE SUBROUTINES ***********************//*------------------------------------------------------------------*//* * Output a bitrate with proper scaling */voidiw_print_bitrate(char * buffer, int bitrate){ double rate = bitrate; if(rate >= GIGA) sprintf(buffer, "%gGb/s", rate / GIGA); else if(rate >= MEGA) sprintf(buffer, "%gMb/s", rate / MEGA); else sprintf(buffer, "%gkb/s", rate / KILO);}/************************ POWER SUBROUTINES *************************//*------------------------------------------------------------------*//* * Convert a value in dBm to a value in milliWatt. */intiw_dbm2mwatt(int in){#ifdef WE_NOLIBM /* Version without libm : slower */ int ip = in / 10; int fp = in % 10; int k; double res = 1.0; /* Split integral and floating part to avoid accumulating rounding errors */ for(k = 0; k < ip; k++) res *= 10; for(k = 0; k < fp; k++) res *= LOG10_MAGIC; return((int) res);#else /* WE_NOLIBM */ /* Version with libm : faster */ return((int) (floor(pow(10.0, (((double) in) / 10.0)))));#endif /* WE_NOLIBM */}/*------------------------------------------------------------------*//* * Convert a value in milliWatt to a value in dBm. */intiw_mwatt2dbm(int in){#ifdef WE_NOLIBM /* Version without libm : slower */ double fin = (double) in; int res = 0; /* Split integral and floating part to avoid accumulating rounding errors */ while(fin > 10.0) { res += 10; fin /= 10.0; } while(fin > 1.000001) /* Eliminate rounding errors, take ceil */ { res += 1; fin /= LOG10_MAGIC; } return(res);#else /* WE_NOLIBM */ /* Version with libm : faster */ return((int) (ceil(10.0 * log10((double) in))));#endif /* WE_NOLIBM */}/********************** STATISTICS SUBROUTINES **********************//*------------------------------------------------------------------*//* * Read /proc/net/wireless to get the latest statistics */intiw_get_stats(int skfd, char * ifname, iwstats * stats){#if WIRELESS_EXT > 11 struct iwreq wrq; wrq.u.data.pointer = (caddr_t) stats; wrq.u.data.length = 0; wrq.u.data.flags = 1; /* Clear updated flag */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(iw_get_ext(skfd, ifname, SIOCGIWSTATS, &wrq) < 0) return(-1); return(0);#else /* WIRELESS_EXT > 11 */ FILE * f = fopen(PROC_NET_WIRELESS, "r"); char buf[256]; char * bp; int t; skfd = skfd; /* Avoid "Unused parameter" warning */ if(f==NULL) return -1; /* Loop on all devices */ while(fgets(buf,255,f)) { bp=buf; while(*bp&&isspace(*bp)) bp++; /* Is it the good device ? */ if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':') { /* Skip ethX: */ bp=strchr(bp,':'); bp++; /* -- status -- */ bp = strtok(bp, " "); sscanf(bp, "%X", &t); stats->status = (unsigned short) t; /* -- link quality -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated |= 1; sscanf(bp, "%d", &t); stats->qual.qual = (unsigned char) t; /* -- signal level -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated |= 2; sscanf(bp, "%d", &t); stats->qual.level = (unsigned char) t; /* -- noise level -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated += 4; sscanf(bp, "%d", &t); stats->qual.noise = (unsigned char) t; /* -- discarded packets -- */ bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.nwid); bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.code); bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.misc); fclose(f); return 0; } } fclose(f); return -1;#endif /* WIRELESS_EXT > 11 */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -