diff options
Diffstat (limited to '')
-rw-r--r-- | info_scr.c | 434 |
1 files changed, 299 insertions, 135 deletions
@@ -18,11 +18,13 @@ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "iw_if.h" +#include "iw_nl80211.h" /* GLOBALS */ static WINDOW *w_levels, *w_stats, *w_if, *w_info, *w_net; static struct timer dyn_updates; -static struct iw_stat cur; +struct iw_range range; +static struct iw_nl80211_linkstat ls; void sampling_init(void (*sampling_handler)(int)) { @@ -30,7 +32,7 @@ void sampling_init(void (*sampling_handler)(int)) div_t d = div(conf.stat_iv, 1000); /* conf.stat_iv in msec */ xsignal(SIGALRM, SIG_IGN); - iw_getinf_range(conf_ifname(), &cur.range); + iw_getinf_range(conf_ifname(), &range); i.it_interval.tv_sec = i.it_value.tv_sec = d.quot; i.it_interval.tv_usec = i.it_value.tv_usec = d.rem * 1000; xsignal(SIGALRM, sampling_handler); @@ -41,23 +43,49 @@ void sampling_init(void (*sampling_handler)(int)) void sampling_do_poll(void) { - iw_getstat(&cur); - iw_cache_update(&cur); + iw_nl80211_get_linkstat(&ls); + iw_cache_update(&ls); } static void display_levels(void) { - char nscale[2] = { cur.dbm.signal - 20, cur.dbm.signal }, - lvlscale[2] = { -40, -20}, - snrscale[2] = { 6, 12 }; - char tmp[0x100]; static float qual, signal, noise, ssnr; + /* + * FIXME: revise the scale implementation. It does not work + * satisfactorily, maybe it is better to have a simple + * solution using 3 levels of different colour. + */ + int8_t nscale[2] = { conf.noise_min, conf.noise_max }, + lvlscale[2] = { -40, -20}; + char tmp[0x100]; int line; + bool noise_data_valid = iw_nl80211_have_survey_data(&ls); + int sig_qual = -1; + int sig_qual_max; + int sig_level = ls.signal_avg ?: ls.signal; + + /* See comments in iw_cache_update */ + if (sig_level == 0) + sig_level = ls.bss_signal; for (line = 1; line <= WH_LEVEL; line++) mvwclrtoborder(w_levels, line, 1); - if ((cur.stat.qual.updated & IW_QUAL_ALL_INVALID) == IW_QUAL_ALL_INVALID) { + if (ls.bss_signal_qual) { + /* BSS_SIGNAL_UNSPEC is scaled 0..100 */ + sig_qual = ls.bss_signal_qual; + sig_qual_max = 100; + } else if (sig_level) { + if (sig_level < -110) + sig_qual = 0; + else if (sig_level > -40) + sig_qual = 70; + else + sig_qual = sig_level + 110; + sig_qual_max = 70; + } + + if (sig_qual == -1 && !sig_level && !noise_data_valid) { wattron(w_levels, A_BOLD); waddstr_center(w_levels, (WH_LEVEL + 1)/2, "NO INTERFACE DATA"); goto done_levels; @@ -66,34 +94,33 @@ static void display_levels(void) line = 1; /* Noise data is rare. Use the space for spreading out. */ - if (cur.stat.qual.updated & IW_QUAL_NOISE_INVALID) + if (!noise_data_valid) line++; - if (cur.stat.qual.updated & IW_QUAL_QUAL_INVALID) { + if (sig_qual == -1) { line++; } else { - qual = ewma(qual, cur.stat.qual.qual, conf.meter_decay / 100.0); + qual = ewma(qual, sig_qual, conf.meter_decay / 100.0); mvwaddstr(w_levels, line++, 1, "link quality: "); - sprintf(tmp, "%0.f%% ", (1e2 * qual)/cur.range.max_qual.qual); + sprintf(tmp, "%0.f%% ", (1e2 * qual)/sig_qual_max); waddstr_b(w_levels, tmp); - sprintf(tmp, "(%0.f/%d) ", qual, cur.range.max_qual.qual); + sprintf(tmp, "(%0.f/%d) ", qual, sig_qual_max); waddstr(w_levels, tmp); - waddbar(w_levels, line++, qual, 0, cur.range.max_qual.qual, - lvlscale, true); + waddbar(w_levels, line++, qual, 0, sig_qual_max, lvlscale, true); } - if (cur.stat.qual.updated & IW_QUAL_NOISE_INVALID) + /* Spacer */ + line++; + if (!noise_data_valid) line++; - if (cur.stat.qual.updated & IW_QUAL_LEVEL_INVALID) { - line++; - } else { - signal = ewma(signal, cur.dbm.signal, conf.meter_decay / 100.0); + if (sig_level != 0) { + signal = ewma(signal, sig_level, conf.meter_decay / 100.0); mvwaddstr(w_levels, line++, 1, "signal level: "); - sprintf(tmp, "%.0f dBm (%s) ", signal, dbm2units(signal)); + sprintf(tmp, "%.0f dBm (%s)", signal, dbm2units(signal)); waddstr_b(w_levels, tmp); waddbar(w_levels, line, signal, conf.sig_min, conf.sig_max, @@ -104,32 +131,28 @@ static void display_levels(void) if (conf.hthreshold_action) waddthreshold(w_levels, line, signal, conf.hthreshold, conf.sig_min, conf.sig_max, lvlscale, '<'); - line++; } - if (! (cur.stat.qual.updated & IW_QUAL_NOISE_INVALID)) { - noise = ewma(noise, cur.dbm.noise, conf.meter_decay / 100.0); + line++; + + if (noise_data_valid) { + noise = ewma(noise, ls.survey.noise, conf.meter_decay / 100.0); mvwaddstr(w_levels, line++, 1, "noise level: "); - sprintf(tmp, "%.0f dBm (%s) ", noise, dbm2units(noise)); + sprintf(tmp, "%.0f dBm (%s)", noise, dbm2units(noise)); waddstr_b(w_levels, tmp); waddbar(w_levels, line++, noise, conf.noise_min, conf.noise_max, nscale, false); - /* - * Since we make sure (in iw_if.c) that invalid signal levels always - * imply invalid noise levels, we can display a valid SNR here. - */ - ssnr = ewma(ssnr, cur.dbm.signal - cur.dbm.noise, + } + + if (noise_data_valid && sig_level) { + ssnr = ewma(ssnr, sig_level - ls.survey.noise, conf.meter_decay / 100.0); - mvwaddstr(w_levels, line++, 1, "signal-to-noise ratio: "); - if (ssnr > 0) - waddstr_b(w_levels, "+"); - sprintf(tmp, "%.0f dB ", ssnr); + mvwaddstr(w_levels, line++, 1, "SNR: "); + sprintf(tmp, "%.0f dB", ssnr); waddstr_b(w_levels, tmp); - - waddbar(w_levels, line, ssnr, 0, 110, snrscale, true); } done_levels: @@ -148,27 +171,34 @@ static void display_stats(void) */ mvwaddstr(w_stats, 1, 1, "RX: "); - sprintf(tmp, "%'llu (%s)", nstat.rx_packets, - byte_units(nstat.rx_bytes)); - waddstr_b(w_stats, tmp); - - waddstr(w_stats, ", invalid: "); - sprintf(tmp, "%u", cur.stat.discard.nwid); - - waddstr_b(w_stats, tmp); - waddstr(w_stats, " nwid, "); + if (ls.rx_packets) { + sprintf(tmp, "%'u (%s)", ls.rx_packets, + byte_units(ls.rx_bytes)); + waddstr_b(w_stats, tmp); + } else { + waddstr(w_stats, "n/a"); + } - sprintf(tmp, "%u", cur.stat.discard.code); - waddstr_b(w_stats, tmp); - waddstr(w_stats, " crypt, "); + if (iw_nl80211_have_survey_data(&ls)) { + if (ls.rx_bitrate[0]) { + waddstr(w_stats, ", rate: "); + waddstr_b(w_stats, ls.rx_bitrate); + } - sprintf(tmp, "%u", cur.stat.discard.fragment); - waddstr_b(w_stats, tmp); - waddstr(w_stats, " frag, "); + if (ls.expected_thru) { + if (ls.expected_thru >= 1024) + sprintf(tmp, " (exp: %.1f MB/s)", ls.expected_thru/1024.0); + else + sprintf(tmp, " (exp: %u kB/s)", ls.expected_thru); + waddstr(w_stats, tmp); + } + } - sprintf(tmp, "%u", cur.stat.discard.misc); - waddstr_b(w_stats, tmp); - waddstr(w_stats, " misc"); + if (ls.rx_drop_misc) { + waddstr(w_stats, ", drop: "); + sprintf(tmp, "%'llu", (unsigned long long)ls.rx_drop_misc); + waddstr_b(w_stats, tmp); + } wclrtoborder(w_stats); @@ -177,18 +207,30 @@ static void display_stats(void) */ mvwaddstr(w_stats, 2, 1, "TX: "); - sprintf(tmp, "%'llu (%s)", nstat.tx_packets, - byte_units(nstat.tx_bytes)); - waddstr_b(w_stats, tmp); + if (ls.tx_packets) { + sprintf(tmp, "%'u (%s)", ls.tx_packets, + byte_units(ls.tx_bytes)); + waddstr_b(w_stats, tmp); + } else { + waddstr(w_stats, "n/a"); + } - waddstr(w_stats, ", mac retries: "); - sprintf(tmp, "%u", cur.stat.discard.retries); - waddstr_b(w_stats, tmp); + if (iw_nl80211_have_survey_data(&ls) && ls.tx_bitrate[0]) { + waddstr(w_stats, ", rate: "); + waddstr_b(w_stats, ls.tx_bitrate); + } - waddstr(w_stats, ", missed beacons: "); - sprintf(tmp, "%u", cur.stat.miss.beacon); - waddstr_b(w_stats, tmp); + if (ls.tx_retries) { + waddstr(w_stats, ", retries: "); + sprintf(tmp, "%'u", ls.tx_retries); + waddstr_b(w_stats, tmp); + } + if (ls.tx_failed) { + waddstr(w_stats, ", failed: "); + sprintf(tmp, "%'u", ls.tx_failed); + waddstr_b(w_stats, tmp); + } wclrtoborder(w_stats); wrefresh(w_stats); } @@ -196,112 +238,234 @@ static void display_stats(void) static void display_info(WINDOW *w_if, WINDOW *w_info) { struct iw_dyn_info info; + struct iw_nl80211_ifstat ifs; + struct iw_nl80211_reg ir; char tmp[0x100]; int i; - dyn_info_get(&info, conf_ifname(), &cur.range); + dyn_info_get(&info, conf_ifname(), &range); + iw_nl80211_getifstat(&ifs); + iw_nl80211_getreg(&ir); + /* + * Interface Part + */ wmove(w_if, 1, 1); waddstr_b(w_if, conf_ifname()); - if (cur.range.enc_capa & IW_WPA_MASK) - sprintf(tmp, " (%s, %s)", info.name, format_wpa(&cur.range)); + if (range.enc_capa & IW_WPA_MASK) + sprintf(tmp, " (%s, %s)", info.name, format_wpa(&range)); else sprintf(tmp, " (%s)", info.name); waddstr(w_if, tmp); - if (info.cap_essid) { - waddstr_b(w_if, ","); - waddstr(w_if, " ESSID: "); - if (info.essid_ct > 1) - sprintf(tmp, "\"%s\" [%d]", info.essid, - info.essid_ct); - else if (info.essid_ct) - sprintf(tmp, "\"%s\"", info.essid); - else - sprintf(tmp, "off/any"); - waddstr_b(w_if, tmp); + /* PHY */ + waddstr(w_if, ", phy "); + sprintf(tmp, "%d", ifs.phy); + waddstr_b(w_if, tmp); + + /* Regulatory domain */ + waddstr(w_if, ", reg: "); + if (ir.region > 0) { + waddstr_b(w_if, ir.country); + sprintf(tmp, " (%s)", dfs_domain_name(ir.region)); + waddstr(w_if, tmp); + } else { + waddstr_b(w_if, "n/a"); } - if (info.cap_nickname) { - waddstr(w_if, ", nick: "); - sprintf(tmp, "\"%s\"", info.nickname); - waddstr_b(w_if, tmp); + if (ifs.ssid[0]) { + waddstr(w_if, ", SSID: "); + waddstr_b(w_if, ifs.ssid); } - if (info.cap_nwid) { - waddstr(w_if, ", nwid: "); - if (info.nwid.disabled) - sprintf(tmp, "off/any"); - else - sprintf(tmp, "%X", info.nwid.value); - waddstr_b(w_if, tmp); - } wclrtoborder(w_if); wrefresh(w_if); + /* + * Info window: + */ wmove(w_info, 1, 1); waddstr(w_info, "mode: "); - if (info.cap_mode) - waddstr_b(w_info, iw_opmode(info.mode)); - else - waddstr(w_info, "n/a"); + waddstr_b(w_info, iftype_name(ifs.iftype)); + + if (!ether_addr_is_zero(&ls.bssid)) { + waddstr_b(w_info, ", "); + + switch (ls.status) { + case NL80211_BSS_STATUS_ASSOCIATED: + waddstr(w_info, "connected to: "); + break; + case NL80211_BSS_STATUS_AUTHENTICATED: + waddstr(w_info, "authenticated with: "); + break; + case NL80211_BSS_STATUS_IBSS_JOINED: + waddstr(w_info, "joined IBSS: "); + break; + default: + waddstr(w_info, "station: "); + } + waddstr_b(w_info, ether_lookup(&ls.bssid)); - if (info.mode != IW_MODE_MASTER && - info.mode != IW_MODE_SECOND && info.mode != IW_MODE_MONITOR) { - if (info.mode == IW_MODE_ADHOC) - waddstr(w_info, ", cell: "); - else - waddstr(w_info, ", access point: "); + if (ls.status == NL80211_BSS_STATUS_ASSOCIATED) { + waddstr_b(w_info, ","); + waddstr(w_info, " time: "); + waddstr_b(w_info, pretty_time(ls.connected_time)); - if (info.cap_ap) - waddstr_b(w_info, format_bssid(&info.ap_addr)); - else - waddstr(w_info, "n/a"); - } - - if (info.cap_sens) { - waddstr(w_info, ", sensitivity: "); - if (info.sens < 0) - sprintf(tmp, "%d dBm", info.sens); - else - sprintf(tmp, "%d/%d", info.sens, - cur.range.sensitivity); - waddstr_b(w_info, tmp); + waddstr(w_info, ", inactive: "); + sprintf(tmp, "%.1fs", (float)ls.inactive_time/1e3); + waddstr_b(w_info, tmp); + } } wclrtoborder(w_info); wmove(w_info, 2, 1); - if (info.cap_freq && info.freq < 256) - info.freq = channel_to_freq(info.freq, &cur.range); - if (info.cap_freq && info.freq > 1e3) { + /* Frequency / channel */ + if (ifs.freq) { waddstr(w_info, "freq: "); - sprintf(tmp, "%g GHz", info.freq / 1.0e9); + sprintf(tmp, "%d MHz", ifs.freq); waddstr_b(w_info, tmp); - i = freq_to_channel(info.freq, &cur.range); - if (i >= 0) { - waddstr(w_info, ", channel: "); - sprintf(tmp, "%d", i); + /* The following condition should in theory never happen */ + if (ls.survey.freq && ls.survey.freq != ifs.freq) { + sprintf(tmp, " [survey freq: %d MHz]", ls.survey.freq); + waddstr(w_info, tmp); + } + + if (ifs.freq_ctr1 && ifs.freq_ctr1 != ifs.freq) { + waddstr(w_info, ", ctr1: "); + sprintf(tmp, "%d MHz", ifs.freq_ctr1); waddstr_b(w_info, tmp); } + if (ifs.freq_ctr2 && ifs.freq_ctr2 != ifs.freq_ctr1 && ifs.freq_ctr2 != ifs.freq) { + waddstr(w_info, ", ctr2: "); + sprintf(tmp, "%d MHz", ifs.freq_ctr2); + waddstr_b(w_info, tmp); + } + + waddstr(w_info, ", channel: "); + sprintf(tmp, "%d", ieee80211_frequency_to_channel(ifs.freq)); + waddstr_b(w_info, tmp); + + if (ifs.chan_width >= 0) { + sprintf(tmp, " (width: %s)", channel_width_name(ifs.chan_width)); + waddstr(w_info, tmp); + } else if (ifs.chan_type >= 0) { + sprintf(tmp, " (%s)", channel_type_name(ifs.chan_type)); + waddstr(w_info, tmp); + } + } else if (iw_nl80211_have_survey_data(&ls)) { + waddstr(w_info, "freq: "); + sprintf(tmp, "%d MHz", ls.survey.freq); + waddstr_b(w_info, tmp); } else { waddstr(w_info, "frequency/channel: n/a"); } + wclrtoborder(w_info); + + /* Channel data */ + wmove(w_info, 3, 1); + if (iw_nl80211_have_survey_data(&ls)) { + waddstr(w_info, "channel "); + waddstr(w_info, "active: "); + waddstr_b(w_info, pretty_time_ms(ls.survey.time.active)); + + waddstr(w_info, ", busy: "); + waddstr_b(w_info, pretty_time_ms(ls.survey.time.busy)); + + if (ls.survey.time.ext_busy) { + waddstr(w_info, ", ext-busy: "); + waddstr_b(w_info, pretty_time_ms(ls.survey.time.ext_busy)); + } + + waddstr(w_info, ", rx: "); + waddstr_b(w_info, pretty_time_ms(ls.survey.time.rx)); + + waddstr(w_info, ", tx: "); + waddstr_b(w_info, pretty_time_ms(ls.survey.time.tx)); + + if (ls.survey.time.scan) { + waddstr(w_info, ", scan: "); + waddstr_b(w_info, pretty_time_ms(ls.survey.time.scan)); + } + } else if (ls.tx_bitrate[0] && ls.rx_bitrate[0]) { + waddstr(w_info, "rx rate: "); + waddstr_b(w_info, ls.rx_bitrate); + + if (ls.expected_thru) { + if (ls.expected_thru >= 1024) + sprintf(tmp, " (exp: %.1f MB/s)", ls.expected_thru/1024.0); + else + sprintf(tmp, " (exp: %u kB/s)", ls.expected_thru); + waddstr(w_info, tmp); + } + waddstr(w_info, ", tx rate: "); + waddstr_b(w_info, ls.tx_bitrate); + } - if (! (info.mode >= IW_MODE_MASTER && info.mode <= IW_MODE_MONITOR)) { - waddstr(w_info, ", bitrate: "); - if (info.bitrate) { - sprintf(tmp, "%g Mbit/s", info.bitrate / 1.0e6); + /* Beacons */ + wmove(w_info, 4, 1); + + if (ls.beacons) { + waddstr(w_info, "beacons: "); + sprintf(tmp, "%'llu", (unsigned long long)ls.beacons); + waddstr_b(w_info, tmp); + + if (ls.beacon_loss) { + waddstr(w_info, ", lost: "); + sprintf(tmp, "%'u", ls.beacon_loss); waddstr_b(w_info, tmp); - } else - waddstr(w_info, "n/a"); + } + waddstr(w_info, ", avg sig: "); + sprintf(tmp, "%d dBm", (int8_t)ls.beacon_avg_sig); + waddstr_b(w_info, tmp); + + waddstr(w_info, ", interval: "); + sprintf(tmp, "%.1fs", (ls.beacon_int * 1024.0)/1e6); + waddstr_b(w_info, tmp); + + waddstr(w_info, ", DTIM: "); + sprintf(tmp, "%u", ls.dtim_period); + waddstr_b(w_info, tmp); + } else { + waddstr(w_info, "station flags:"); + if (ls.cts_protection) + waddstr_b(w_info, " CTS"); + if (ls.wme) + waddstr_b(w_info, " WME"); + if (ls.tdls) + waddstr_b(w_info, " TDLS"); + if (ls.mfp) + waddstr_b(w_info, " MFP"); + if (!(ls.cts_protection | ls.wme | ls.tdls | ls.mfp)) + waddstr_b(w_info, " (none)"); + waddstr(w_info, ", preamble:"); + if (ls.long_preamble) + waddstr_b(w_info, " long"); + else + waddstr_b(w_info, " short"); + waddstr(w_info, ", slot:"); + if (ls.short_slot_time) + waddstr_b(w_info, " short"); + else + waddstr_b(w_info, " long"); + } + + if (info.cap_sens) { + waddstr(w_info, ", sensitivity: "); + if (info.sens < 0) + sprintf(tmp, "%d dBm", info.sens); + else + sprintf(tmp, "%d/%d", info.sens, + range.sensitivity); + waddstr_b(w_info, tmp); } + wclrtoborder(w_info); - wmove(w_info, 3, 1); + wmove(w_info, 5, 1); waddstr(w_info, "power mgt: "); if (info.cap_power) - waddstr_b(w_info, format_power(&info.power, &cur.range)); + waddstr_b(w_info, format_power(&info.power, &range)); else waddstr(w_info, "n/a"); @@ -320,10 +484,10 @@ static void display_info(WINDOW *w_if, WINDOW *w_info) } wclrtoborder(w_info); - wmove(w_info, 4, 1); + wmove(w_info, 6, 1); waddstr(w_info, "retry: "); if (info.cap_retry) - waddstr_b(w_info, format_retry(&info.retry, &cur.range)); + waddstr_b(w_info, format_retry(&info.retry, &range)); else waddstr(w_info, "n/a"); @@ -352,7 +516,7 @@ static void display_info(WINDOW *w_if, WINDOW *w_info) } wclrtoborder(w_info); - wmove(w_info, 5, 1); + wmove(w_info, 7, 1); waddstr(w_info, "encryption: "); if (info.keys) { int cnt = dyn_info_active_keys(&info); @@ -480,7 +644,7 @@ static void display_netinfo(WINDOW *w_net) waddstr(w_net, "ip: "); if (!info.addr.s_addr) { - waddstr_b(w_net, "n/a"); + waddstr(w_net, "n/a"); } else { sprintf(tmp, "%s/%u", inet_ntoa(info.addr), prefix_len(&info.netmask)); @@ -526,7 +690,7 @@ void scr_info_init(void) if (LINES >= WH_INFO_SCR_MIN + (WH_NET_MAX - WH_NET_MIN)) w_net = newwin_title(line, WH_NET_MAX, "Network", false); else - w_net = newwin_title(line, WH_NET_MIN, "Network", false); + w_net = newwin_title(line, WH_NET_MAX, "Network", false); display_info(w_if, w_info); display_netinfo(w_net); |