summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2015-09-15 13:39:01 -0700
committerJohn Baldwin <jhb@FreeBSD.org>2015-09-15 13:39:01 -0700
commit85618dc8e83f2f6da0953bf22a00108f46572bc0 (patch)
tree81562d0a3459a9a8782031efe5b602129412da01
parent452399d84aac42b538e63d17187ee8918cdb3486 (diff)
Fix various issues with wireless information under FreeBSD:
- Instead of hoping that the currently associated AP will show up as the first AP in the list of scan results, fetch the BSSID of the currently associated AP and use that to fetch station info for the AP. This provides more frequently updated signal strength information than scan results and reliably provides information when multiple APs are in range. - Do not treat the RSSI value as a raw signal value in dBm. Instead, use the same formula as ifconfig(8) to compute a signal value. - Do not report the beacon interval value as a signal quality level.
-rw-r--r--src/print_wireless_info.c49
1 files changed, 30 insertions, 19 deletions
diff --git a/src/print_wireless_info.c b/src/print_wireless_info.c
index 83c717e..99b07f8 100644
--- a/src/print_wireless_info.c
+++ b/src/print_wireless_info.c
@@ -197,10 +197,14 @@ static int get_wireless_info(const char *interface, wireless_info_t *info) {
return 1;
#endif
#if defined(__FreeBSD__) || defined(__DragonFly__)
- int s, len, inwid;
- uint8_t buf[24 * 1024], *cp;
+ int s, inwid;
+ union {
+ struct ieee80211req_sta_req req;
+ uint8_t buf[24 * 1024];
+ } u;
struct ieee80211req na;
- char network_id[IEEE80211_NWID_LEN + 1];
+ char bssid[IEEE80211_ADDR_LEN];
+ size_t len;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
return (0);
@@ -228,31 +232,38 @@ static int get_wireless_info(const char *interface, wireless_info_t *info) {
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);
+ na.i_type = IEEE80211_IOC_BSSID;
+ na.i_data = bssid;
+ na.i_len = sizeof(bssid);
+
+ if (ioctl(s, SIOCG80211, (caddr_t)&na) == -1) {
+ close(s);
+ return (0);
+ }
+
+ memcpy(u.req.is_u.macaddr, bssid, sizeof(bssid));
+ memset(&na, 0, sizeof(na));
+ strlcpy(na.i_name, interface, sizeof(na.i_name));
+ na.i_type = IEEE80211_IOC_STA_INFO;
+ na.i_data = &u;
+ na.i_len = sizeof(u);
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;
+ if (na.i_len >= sizeof(u.req)) {
+ /*
+ * Just use the first BSSID returned even if there are
+ * multiple APs sharing the same BSSID.
+ */
+ info->signal_level = u.req.info[0].isi_rssi / 2 +
+ u.req.info[0].isi_noise;
info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
- info->noise_level = sr->isr_noise;
+ info->noise_level = u.req.info[0].isi_noise;
info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
- info->quality = sr->isr_intval;
- info->flags |= WIRELESS_INFO_FLAG_HAS_QUALITY;
}
return 1;