C_RESULT vp_com_wf_get_rssi(vp_com_wifi_config_t* cfg, int32_t* rssi) { #ifdef USE_IWLIB struct iwreq wrq; iwstats stats; iwrange range; int wlsock = iw_sockets_open(); vp_os_memset(&wrq, 0, sizeof(struct iwreq)); iw_get_stats(wlsock, cfg->itfName, &stats, &range, 1); iw_sockets_close(wlsock); // struct iw_statistics // { // __u16 status; // Status * - device dependent for now // struct iw_quality qual; // Quality of the link * (instant/mean/max) // struct iw_discarded discard; // Packet discarded counts // struct iw_missed miss; // Packet missed counts // }; // // struct iw_range // { // ... // // Quality of link & SNR stuff */ // // Quality range (link, level, noise) // // If the quality is absolute, it will be in the range [0 ; max_qual], // // if the quality is dBm, it will be in the range [max_qual ; 0]. // // Don't forget that we use 8 bit arithmetics... // struct iw_quality max_qual; // Quality of the link // // This should contain the average/typical values of the quality // // indicator. This should be the threshold between a "good" and // // a "bad" link (example : monitor going from green to orange). // // Currently, user space apps like quality monitors don't have any // // way to calibrate the measurement. With this, they can split // // the range between 0 and max_qual in different quality level // // (using a geometric subdivision centered on the average). // // I expect that people doing the user space apps will feedback // // us on which value we need to put in each driver... // struct iw_quality avg_qual; // Quality of the link // ... // }; // struct iw_quality // { // __u8 qual; // link quality (%retries, SNR, %missed beacons or better...) // __u8 level; // signal level (dBm) // __u8 noise; // noise level (dBm) // __u8 updated; // Flags to know if updated // }; *rssi = stats.qual.qual; #endif return VP_COM_OK; }
static double get_stats_discarded_nwid(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) { return DNAN; } return (double) stats.discard.nwid; }
/* ------------------------------------------------------------------- WirelessInterface_refresh */ static void WirelessInterface_refresh(wiface* self) { iwreq wrq; iw_get_basic_config(self->sock, self->ifname, &(self->info.b)); iw_get_range_info(self->sock, self->ifname, &(self->info.range)); iw_get_ext(self->sock, self->ifname, SIOCGIWRATE, &wrq); memcpy(&(self->info.bitrate), &wrq.u.bitrate, sizeof(iwparam)); iw_get_ext(self->sock, self->ifname, SIOCGIWAP, &wrq); memcpy(&(self->info.ap_addr), &wrq.u.ap_addr, sizeof(sockaddr)); iw_get_stats(self->sock, self->ifname, &(self->info.stats), &(self->info.range), self->info.has_range); }
/** * @brief Gets the signal quality property of the wifi device * @return An updated wifi_signal type */ wifi_signal getSignal() { if (iw_get_stats(wifi_skfd, wifi_dev, &(wifi_info->stats), &wifi_info->range, wifi_info->has_range) >= 0) wifi_info->has_stats = 1; int quality = wifi_info->stats.qual.qual; // Get bit rate if (iw_get_ext(wifi_skfd, wifi_dev, SIOCGIWRATE, &wifi_wrq) >= 0) { wifi_info->has_bitrate = 1; memcpy(&(wifi_info->bitrate), &(wifi_wrq.u.bitrate), sizeof(wifi_info->bitrate)); } wifi_sig.link_quality = quality; return wifi_sig; }
static double get_stats_quality_quality(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_quality: UNKNOWN"); return DNAN; } xsg_debug("get_stats_quality_quality: %f", (double) stats.qual.qual); return (double) stats.qual.qual; }
void get_wireless_info (DevInfo *devinfo) { int fd; int newqual; wireless_info info = {0}; fd = iw_sockets_open (); if (fd < 0) return; if (iw_get_basic_config (fd, devinfo->name, &info.b) < 0) goto out; if (info.b.has_essid) { if ((!devinfo->essid) || (strcmp (devinfo->essid, info.b.essid) != 0)) { devinfo->essid = g_strdup (info.b.essid); } } else { devinfo->essid = NULL; } if (iw_get_stats (fd, devinfo->name, &info.stats, &info.range, info.has_range) >= 0) info.has_stats = 1; if (info.has_stats) { if ((iw_get_range_info(fd, devinfo->name, &info.range) >= 0) && (info.range.max_qual.qual > 0)) { newqual = 0.5f + (100.0f * info.stats.qual.qual) / (1.0f * info.range.max_qual.qual); } else { newqual = info.stats.qual.qual; } newqual = CLAMP(newqual, 0, 100); if (devinfo->qual != newqual) devinfo->qual = newqual; } else { devinfo->qual = 0; } goto out; out: if (fd != -1) close (fd); }
static double get_stats_discarded_misc(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_misc: UNKNOWN"); return DNAN; } xsg_debug("get_stats_discarded_misc: %f", (double) stats.discard.misc); return (double) stats.discard.misc; }
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; }
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; }
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); } }
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; }
/* * 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); }
/* * 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); }
/* * 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); }
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; }