aboutsummaryrefslogtreecommitdiffstats
path: root/info_scr.c
diff options
context:
space:
mode:
Diffstat (limited to 'info_scr.c')
-rw-r--r--info_scr.c434
1 files changed, 299 insertions, 135 deletions
diff --git a/info_scr.c b/info_scr.c
index 1251ae0..6a50b43 100644
--- a/info_scr.c
+++ b/info_scr.c
@@ -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);