9 #define IW_ESSID_MAX_SIZE 32
14 #include <sys/param.h>
15 #include <sys/ioctl.h>
16 #include <sys/socket.h>
19 #include <net/if_media.h>
20 #include <net80211/ieee80211.h>
21 #include <net80211/ieee80211_ioctl.h>
23 #define IW_ESSID_MAX_SIZE IEEE80211_NWID_LEN
28 #define WIRELESS_INFO_FLAG_HAS_ESSID (1 << 0)
29 #define WIRELESS_INFO_FLAG_HAS_QUALITY (1 << 1)
30 #define WIRELESS_INFO_FLAG_HAS_SIGNAL (1 << 2)
31 #define WIRELESS_INFO_FLAG_HAS_NOISE (1 << 3)
33 #define PERCENT_VALUE(value, total) ((int)(value * 100 / (float)total + 0.5f))
37 char essid[IW_ESSID_MAX_SIZE + 1];
48 static int get_wireless_info(const char *interface, wireless_info_t *info) {
49 memset(info, 0, sizeof(wireless_info_t));
52 int skfd = iw_sockets_open();
54 perror("iw_sockets_open");
59 if (iw_get_basic_config(skfd, interface, &wcfg) < 0) {
64 if (wcfg.has_essid && wcfg.essid_on) {
65 info->flags |= WIRELESS_INFO_FLAG_HAS_ESSID;
66 strncpy(&info->essid[0], wcfg.essid, IW_ESSID_MAX_SIZE);
67 info->essid[IW_ESSID_MAX_SIZE] = '\0';
70 /* Wireless quality is a relative value in a driver-specific range.
71 Signal and noise level can be either relative or absolute values
72 in dBm. Furthermore, noise and quality can be expressed directly
73 in dBm or in RCPI (802.11k), which we convert to dBm. When those
74 values are expressed directly in dBm, they range from -192 to 63,
75 and since the values are packed into 8 bits, we need to perform
76 8-bit arithmetic on them. Assume absolute values if everything
77 else fails (driver bug). */
80 if (iw_get_range_info(skfd, interface, &range) < 0) {
86 if (iw_get_stats(skfd, interface, &stats, &range, 1) < 0) {
91 if (stats.qual.level != 0 || (stats.qual.updated & (IW_QUAL_DBM | IW_QUAL_RCPI))) {
92 if (!(stats.qual.updated & IW_QUAL_QUAL_INVALID)) {
93 info->quality = stats.qual.qual;
94 info->quality_max = range.max_qual.qual;
95 info->quality_average = range.avg_qual.qual;
96 info->flags |= WIRELESS_INFO_FLAG_HAS_QUALITY;
99 if (stats.qual.updated & IW_QUAL_RCPI) {
100 if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
101 info->signal_level = stats.qual.level / 2.0 - 110 + 0.5;
102 info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
104 if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
105 info->noise_level = stats.qual.noise / 2.0 - 110 + 0.5;
106 info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
110 if ((stats.qual.updated & IW_QUAL_DBM) || stats.qual.level > range.max_qual.level) {
111 if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
112 info->signal_level = stats.qual.level;
113 if (info->signal_level > 63)
114 info->signal_level -= 256;
115 info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
117 if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
118 info->noise_level = stats.qual.noise;
119 if (info->noise_level > 63)
120 info->noise_level -= 256;
121 info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
125 if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
126 info->signal_level = stats.qual.level;
127 info->signal_level_max = range.max_qual.level;
128 info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
130 if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
131 info->noise_level = stats.qual.noise;
132 info->noise_level_max = range.max_qual.noise;
133 info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
139 if (!(stats.qual.updated & IW_QUAL_QUAL_INVALID)) {
140 info->quality = stats.qual.qual;
141 info->flags |= WIRELESS_INFO_FLAG_HAS_QUALITY;
143 if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
144 info->quality = stats.qual.level;
145 info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
147 if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
148 info->quality = stats.qual.noise;
149 info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
154 if (iw_get_ext(skfd, interface, SIOCGIWRATE, &wrq) >= 0)
155 info->bitrate = wrq.u.bitrate.value;
162 uint8_t buf[24 * 1024], *cp;
163 struct ieee80211req na;
164 char network_id[IEEE80211_NWID_LEN + 1];
166 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
169 memset(&na, 0, sizeof(na));
170 strlcpy(na.i_name, interface, sizeof(na.i_name));
171 na.i_type = IEEE80211_IOC_SSID;
172 na.i_data = &info->essid[0];
173 na.i_len = IEEE80211_NWID_LEN + 1;
174 if ((inwid = ioctl(s, SIOCG80211, (caddr_t)&na)) == -1) {
179 if (na.i_len <= IEEE80211_NWID_LEN)
182 len = IEEE80211_NWID_LEN + 1;
183 info->essid[len -1] = '\0';
188 info->flags |= WIRELESS_INFO_FLAG_HAS_ESSID;
190 memset(&na, 0, sizeof(na));
191 strlcpy(na.i_name, interface, sizeof(na.i_name));
192 na.i_type = IEEE80211_IOC_SCAN_RESULTS;
194 na.i_len = sizeof(buf);
196 if (ioctl(s, SIOCG80211, (caddr_t)&na) == -1) {
205 struct ieee80211req_scan_result *sr;
207 sr = (struct ieee80211req_scan_result *)cp;
208 vp = (u_int8_t *)(sr + 1);
209 strlcpy(network_id, (const char *)vp, sr->isr_ssid_len + 1);
210 if (!strcmp(network_id, &info->essid[0])) {
211 info->signal_level = sr->isr_rssi;
212 info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
213 info->noise_level = sr->isr_noise;
214 info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
215 info->quality = sr->isr_intval;
216 info->flags |= WIRELESS_INFO_FLAG_HAS_QUALITY;
224 void print_wireless_info(const char *interface, const char *format_up, const char *format_down) {
226 wireless_info_t info;
227 if (get_wireless_info(interface, &info)) {
229 if (info.flags & WIRELESS_INFO_FLAG_HAS_QUALITY)
230 printf("%s", info.quality < info.quality_average ? color("color_degraded") : color("color_good"));
234 printf("%s", color("color_bad"));
237 for (; *walk != '\0'; walk++) {
243 if (BEGINS_WITH(walk+1, "quality")) {
244 if (info.flags & WIRELESS_INFO_FLAG_HAS_QUALITY) {
245 if (info.quality_max)
246 printf("%03d%%", PERCENT_VALUE(info.quality, info.quality_max));
248 printf("%d", info.quality);
253 walk += strlen("quality");
256 if (BEGINS_WITH(walk+1, "signal")) {
257 if (info.flags & WIRELESS_INFO_FLAG_HAS_SIGNAL) {
258 if (info.signal_level_max)
259 printf("%03d%%", PERCENT_VALUE(info.signal_level, info.signal_level_max));
261 printf("%d dBm", info.signal_level);
266 walk += strlen("signal");
269 if (BEGINS_WITH(walk+1, "noise")) {
270 if (info.flags & WIRELESS_INFO_FLAG_HAS_NOISE) {
271 if (info.noise_level_max)
272 printf("%03d%%", PERCENT_VALUE(info.noise_level, info.noise_level_max));
274 printf("%d dBm", info.noise_level);
279 walk += strlen("noise");
282 if (BEGINS_WITH(walk+1, "essid")) {
283 if (info.flags & WIRELESS_INFO_FLAG_HAS_ESSID)
284 printf("%s", info.essid);
287 walk += strlen("essid");
290 if (BEGINS_WITH(walk+1, "ip")) {
291 const char *ip_address = get_ip_addr(interface);
292 if (ip_address != NULL)
293 (void)printf("%s", get_ip_addr(interface));
294 else (void)printf("no IP");
295 walk += strlen("ip");
299 if (BEGINS_WITH(walk+1, "bitrate")) {
302 iw_print_bitrate(buffer, sizeof(buffer), info.bitrate);
304 printf("%s", buffer);
305 walk += strlen("bitrate");
310 (void)printf("%s", endcolor());