aboutsummaryrefslogtreecommitdiffstats
path: root/info_scr.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--info_scr.c375
1 files changed, 248 insertions, 127 deletions
diff --git a/info_scr.c b/info_scr.c
index 1b4974d..0b8eace 100644
--- a/info_scr.c
+++ b/info_scr.c
@@ -20,45 +20,29 @@
#include "iw_if.h"
/* GLOBALS */
-static WINDOW *w_levels, *w_stats;
-
+static WINDOW *w_levels, *w_stats, *w_if, *w_info, *w_net;
+static struct timer dyn_updates;
static struct iw_stat cur;
-void (*iw_stat_redraw) (void);
-/*
- * Statistics handler for period polling
- */
-static void sampling_handler(int signum)
-{
- iw_getstat(&cur);
- iw_cache_update(&cur);
-
- if (iw_stat_redraw)
- iw_stat_redraw();
-}
-
-static void init_stat_iv(void)
+void sampling_init(void (*sampling_handler)(int))
{
struct itimerval i;
div_t d = div(conf.stat_iv, 1000); /* conf.stat_iv in msec */
+ xsignal(SIGALRM, SIG_IGN);
+ iw_getinf_range(conf_ifname(), &cur.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);
+ (*sampling_handler)(0);
setitimer(ITIMER_REAL, &i, NULL);
-
- signal(SIGALRM, sampling_handler);
}
-void reinit_on_changes(void)
+void sampling_do_poll(void)
{
- static int stat_iv = 0;
-
- if (conf.stat_iv != stat_iv) {
- iw_getinf_range(conf.ifname, &cur.range);
- init_stat_iv();
- stat_iv = conf.stat_iv;
- }
+ iw_getstat(&cur);
+ iw_cache_update(&cur);
}
static void display_levels(void)
@@ -67,66 +51,86 @@ static void display_levels(void)
lvlscale[2] = { -40, -20},
snrscale[2] = { 6, 12 };
char tmp[0x100];
- static float qual, noise, signal, ssnr;
- /* Spread out 'quality' and 'signal' if 'noise' is undefined */
- const bool offset = (cur.stat.qual.updated & IW_QUAL_NOISE_INVALID) != 0;
- int line = 1;
+ static float qual, signal, noise, ssnr;
+ int line;
- if (!(cur.stat.qual.updated & IW_QUAL_QUAL_INVALID)) {
- line += offset;
+ for (line = 1; line <= WH_LEVEL; line++)
+ mvwclrtoborder(w_levels, line, 1);
- mvwaddstr(w_levels, line++, 1, "link quality: ");
+ if ((cur.stat.qual.updated & IW_QUAL_ALL_INVALID) == IW_QUAL_ALL_INVALID) {
+ wattron(w_levels, A_BOLD);
+ waddstr_center(w_levels, (WH_LEVEL + 1)/2, "NO INTERFACE DATA");
+ goto done_levels;
+ }
+
+ line = 1;
+ /* Noise data is rare. Use the space for spreading out. */
+ if (cur.stat.qual.updated & IW_QUAL_NOISE_INVALID)
+ line++;
+
+ if (cur.stat.qual.updated & IW_QUAL_QUAL_INVALID) {
+ line++;
+ } else {
qual = ewma(qual, cur.stat.qual.qual, conf.meter_decay / 100.0);
+
+ mvwaddstr(w_levels, line++, 1, "link quality: ");
sprintf(tmp, "%0.f/%d ", qual, cur.range.max_qual.qual);
waddstr_b(w_levels, tmp);
+
waddbar(w_levels, line++, qual, 0, cur.range.max_qual.qual,
lvlscale, true);
}
- if (!(cur.stat.qual.updated & IW_QUAL_LEVEL_INVALID)) {
+ if (cur.stat.qual.updated & IW_QUAL_NOISE_INVALID)
+ line++;
+
+ if (cur.stat.qual.updated & IW_QUAL_LEVEL_INVALID) {
+ line++;
+ } else {
signal = ewma(signal, cur.dbm.signal, conf.meter_decay / 100.0);
- line += offset;
mvwaddstr(w_levels, line++, 1, "signal level: ");
-
sprintf(tmp, "%.0f dBm (%s) ", signal, dbm2units(signal));
waddstr_b(w_levels, tmp);
+
waddbar(w_levels, line, signal, conf.sig_min, conf.sig_max,
lvlscale, true);
-
if (conf.lthreshold_action)
waddthreshold(w_levels, line, signal, conf.lthreshold,
conf.sig_min, conf.sig_max, lvlscale, '>');
if (conf.hthreshold_action)
waddthreshold(w_levels, line, signal, conf.hthreshold,
conf.sig_min, conf.sig_max, lvlscale, '<');
+ line++;
}
- if (!offset) {
+ if (! (cur.stat.qual.updated & IW_QUAL_NOISE_INVALID)) {
noise = ewma(noise, cur.dbm.noise, conf.meter_decay / 100.0);
- line += 1;
mvwaddstr(w_levels, line++, 1, "noise level: ");
-
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 noise levels always
+ * Since we make sure (in iw_if.c) that invalid signal levels always
* imply invalid noise levels, we can display a valid SNR here.
*/
- mvwaddstr(w_levels, line++, 1, "signal-to-noise ratio: ");
-
ssnr = ewma(ssnr, cur.dbm.signal - cur.dbm.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);
waddstr_b(w_levels, tmp);
- waddbar(w_levels, 8, ssnr, 0, 110, snrscale, true);
+
+ waddbar(w_levels, line, ssnr, 0, 110, snrscale, true);
}
+
+done_levels:
wrefresh(w_levels);
}
@@ -135,7 +139,7 @@ static void display_stats(void)
struct if_stat nstat;
char tmp[0x100];
- if_getstat(conf.ifname, &nstat);
+ if_getstat(conf_ifname(), &nstat);
/*
* Interface RX stats
@@ -156,14 +160,14 @@ static void display_stats(void)
waddstr_b(w_stats, tmp);
waddstr(w_stats, " crypt, ");
- if (cur.range.we_version_compiled > 11) {
- sprintf(tmp, "%'u", cur.stat.discard.fragment);
- waddstr_b(w_stats, tmp);
- waddstr(w_stats, " frag, ");
- }
+ sprintf(tmp, "%'u", cur.stat.discard.fragment);
+ waddstr_b(w_stats, tmp);
+ waddstr(w_stats, " frag, ");
+
sprintf(tmp, "%'u", cur.stat.discard.misc);
waddstr_b(w_stats, tmp);
waddstr(w_stats, " misc");
+
wclrtoborder(w_stats);
/*
@@ -175,39 +179,37 @@ static void display_stats(void)
byte_units(nstat.tx_bytes));
waddstr_b(w_stats, tmp);
- if (cur.range.we_version_compiled > 11) {
- waddstr(w_stats, ", mac retries: ");
- sprintf(tmp, "%'u", cur.stat.discard.retries);
- waddstr_b(w_stats, tmp);
+ waddstr(w_stats, ", mac retries: ");
+ sprintf(tmp, "%'u", cur.stat.discard.retries);
+ waddstr_b(w_stats, tmp);
+
+ waddstr(w_stats, ", missed beacons: ");
+ sprintf(tmp, "%'u", cur.stat.miss.beacon);
+ waddstr_b(w_stats, tmp);
- waddstr(w_stats, ", missed beacons: ");
- sprintf(tmp, "%'u", cur.stat.miss.beacon);
- waddstr_b(w_stats, tmp);
- }
wclrtoborder(w_stats);
wrefresh(w_stats);
}
-static void redraw_stats(void)
-{
- display_levels();
- display_stats();
-}
-
static void display_info(WINDOW *w_if, WINDOW *w_info)
{
struct iw_dyn_info info;
char tmp[0x100];
int i;
- iw_getinf_dyn(conf.ifname, &info);
+ dyn_info_get(&info, conf_ifname(), &cur.range);
wmove(w_if, 1, 1);
- sprintf(tmp, "%s (%s)", conf.ifname, info.name);
- waddstr_b(w_if, tmp);
+ waddstr_b(w_if, conf_ifname());
+ if (cur.range.enc_capa & IW_WPA_MASK)
+ sprintf(tmp, " (%s, %s)", info.name, format_wpa(&cur.range));
+ else
+ sprintf(tmp, " (%s)", info.name);
+ waddstr(w_if, tmp);
if (info.cap_essid) {
- waddstr(w_if, ", ESSID: ");
+ waddstr_b(w_if, ",");
+ waddstr(w_if, " ESSID: ");
if (info.essid_ct > 1)
sprintf(tmp, "\"%s\" [%d]", info.essid,
info.essid_ct);
@@ -264,13 +266,16 @@ static void display_info(WINDOW *w_if, WINDOW *w_info)
cur.range.sensitivity);
waddstr_b(w_info, tmp);
}
-
+ wclrtoborder(w_info);
wmove(w_info, 2, 1);
- if (info.cap_freq) {
+ if (info.cap_freq && info.freq < 256)
+ info.freq = channel_to_freq(info.freq, &cur.range);
+ if (info.cap_freq && info.freq > 1e3) {
waddstr(w_info, "freq: ");
sprintf(tmp, "%g GHz", info.freq / 1.0e9);
waddstr_b(w_info, tmp);
+
i = freq_to_channel(info.freq, &cur.range);
if (i >= 0) {
waddstr(w_info, ", channel: ");
@@ -283,12 +288,13 @@ static void display_info(WINDOW *w_if, WINDOW *w_info)
if (! (info.mode >= IW_MODE_MASTER && info.mode <= IW_MODE_MONITOR)) {
waddstr(w_info, ", bitrate: ");
- if (info.cap_bitrate) {
+ if (info.bitrate) {
sprintf(tmp, "%g Mbit/s", info.bitrate / 1.0e6);
waddstr_b(w_info, tmp);
} else
waddstr(w_info, "n/a");
}
+ wclrtoborder(w_info);
wmove(w_info, 3, 1);
waddstr(w_info, "power mgt: ");
@@ -310,6 +316,7 @@ static void display_info(WINDOW *w_if, WINDOW *w_info)
waddstr(w_info, ", TX-power: ");
waddstr_b(w_info, format_txpower(&info.txpower));
}
+ wclrtoborder(w_info);
wmove(w_info, 4, 1);
waddstr(w_info, "retry: ");
@@ -326,8 +333,9 @@ static void display_info(WINDOW *w_if, WINDOW *w_info)
else
sprintf(tmp, "%d B", info.rts.value);
waddstr_b(w_info, tmp);
- } else
+ } else {
waddstr(w_info, "rts/cts: n/a");
+ }
waddstr(w_info, ", ");
if (info.cap_frag) {
@@ -337,32 +345,68 @@ static void display_info(WINDOW *w_if, WINDOW *w_info)
else
sprintf(tmp, "%d B", info.frag.value);
waddstr_b(w_info, tmp);
- } else
+ } else {
waddstr(w_info, "frag: n/a");
+ }
+ wclrtoborder(w_info);
wmove(w_info, 5, 1);
waddstr(w_info, "encryption: ");
- if (info.cap_key) {
- if (info.key_flags & IW_ENCODE_DISABLED || info.key_size == 0) {
- waddstr_b(w_info, "off");
- } else {
- char *key = format_key(info.key, info.key_size);
+ if (info.keys) {
+ int cnt = dyn_info_active_keys(&info);
- waddstr_b(w_info, curtail(key, "..", MAXXLEN / 2));
+ if (cnt == 0) {
+ waddstr_b(w_info, "off (no key set)");
+ } else if (info.active_key) {
+ i = info.active_key - 1;
+ waddstr_b(w_info, curtail(format_key(info.keys + i),
+ "..", MAXXLEN/2));
- i = info.key_flags & IW_ENCODE_INDEX;
- if (i > 1) {
- sprintf(tmp, " [%d]", i);
- waddstr_b(w_info, tmp);
- }
- if (info.key_flags & IW_ENCODE_RESTRICTED)
+ if (info.keys[i].flags & IW_ENCODE_RESTRICTED)
waddstr(w_info, ", restricted");
- if (info.key_flags & IW_ENCODE_OPEN)
+ if (info.keys[i].flags & IW_ENCODE_OPEN)
waddstr(w_info, ", open");
+
+ /* First key = default */
+ if (cnt > 1 || info.active_key != 1) {
+ sprintf(tmp, " [%d]", info.active_key);
+ waddstr_b(w_info, tmp);
+ }
+ if (cnt > 1) {
+ sprintf(tmp, " (%d other key%s)", cnt - 1,
+ cnt == 2 ? "" : "s");
+ waddstr(w_info, tmp);
+ }
+ } else if (dyn_info_wep_keys(&info) == cnt) {
+ waddstr_b(w_info, "off ");
+ sprintf(tmp, "(%d disabled WEP key%s)", cnt,
+ cnt == 1 ? "" : "s");
+ waddstr(w_info, tmp);
+ } else {
+ uint8_t j = 0, k = 0;
+
+ do if (info.keys[j].size &&
+ !(info.keys[j].flags & IW_ENCODE_DISABLED))
+ info.keys[k++].size = info.keys[j].size;
+ while (k < cnt && ++j < info.nkeys);
+
+ if (cnt == 1)
+ j = sprintf(tmp, "1 key (index #%u), ", j + 1);
+ else
+ j = sprintf(tmp, "%d keys with ", k);
+ for (i = 0; i < k; i++)
+ j += sprintf(tmp + j, "%s%d", i ? "/" : "",
+ info.keys[i].size * 8);
+ sprintf(tmp + j, " bits");
+ waddstr_b(w_info, tmp);
}
- } else
- waddstr(w_info, "n/a");
+ } else if (has_net_admin_capability()) {
+ waddstr(w_info, "no information available");
+ } else {
+ waddstr(w_info, "n/a (requires CAP_NET_ADMIN permissions)");
+ }
+ dyn_info_cleanup(&info);
wclrtoborder(w_info);
wrefresh(w_info);
}
@@ -372,62 +416,139 @@ static void display_netinfo(WINDOW *w_net)
struct if_info info;
char tmp[0x40];
- if_getinf(conf.ifname, &info);
+ if_getinf(conf_ifname(), &info);
- mvwaddstr(w_net, 1, 1, "ip: ");
- sprintf(tmp, "%s/%u", inet_ntoa(info.addr),
- prefix_len(&info.netmask));
- waddstr_b(w_net, tmp);
+ wmove(w_net, 1, 1);
+ wclrtoborder(w_net);
+ if (getmaxy(w_net) == WH_NET_MAX) {
+ waddstr(w_net, conf_ifname());
+
+ waddstr_b(w_net, " (");
+ waddstr(w_net, info.flags & IFF_UP ? "UP" : "DOWN");
+ if (info.flags & IFF_RUNNING) /* Interface RFC2863 OPER_UP */
+ waddstr(w_net, " RUNNING");
+#ifdef IFF_LOWER_UP /* Linux 2.6.17 */
+ if (info.flags & IFF_LOWER_UP) /* Driver signals L1 up */
+ waddstr(w_net, " LOWER_UP");
+#endif
+#ifdef IFF_DORMANT /* Linux 2.6.17 */
+ if (info.flags & IFF_DORMANT) /* Driver signals dormant */
+ waddstr(w_net, " DORMANT");
+#endif
+ if (info.flags & IFF_MASTER) /* Master of a load balancer */
+ waddstr(w_net, " MASTER");
+ if (info.flags & IFF_SLAVE) /* Slave of a load balancer */
+ waddstr(w_net, " SLAVE");
+ if (info.flags & IFF_POINTOPOINT) /* Is a point-to-point link */
+ waddstr(w_net, " POINTOPOINT");
+ if (info.flags & IFF_DYNAMIC) /* Address is volatile */
+ waddstr(w_net, " DYNAMIC");
+ if (info.flags & IFF_BROADCAST) /* Valid broadcast address set */
+ waddstr(w_net, " BROADCAST");
+ if (info.flags & IFF_MULTICAST) /* Supports multicast */
+ waddstr(w_net, " MULTICAST");
+ if (info.flags & IFF_ALLMULTI) /* Receive all mcast packets */
+ waddstr(w_net, " ALLMULTI");
+ if (info.flags & IFF_NOARP) /* No ARP protocol */
+ waddstr(w_net, " NOARP");
+ if (info.flags & IFF_NOTRAILERS) /* Avoid use of trailers */
+ waddstr(w_net, " NOTRAILERS");
+ if (info.flags & IFF_PROMISC) /* Is in promiscuous mode */
+ waddstr(w_net, " PROMISC");
+ if (info.flags & IFF_DEBUG) /* Internal debugging flag */
+ waddstr(w_net, " DEBUG");
+ waddstr_b(w_net, ")");
+
+ wmove(w_net, 2, 1);
+ wclrtoborder(w_net);
+ }
+ waddstr(w_net, "mac: ");
+ waddstr_b(w_net, ether_lookup(&info.hwaddr));
- waddstr(w_net, ", bcast: ");
- waddstr_b(w_net, inet_ntoa(info.bcast));
+ if (getmaxy(w_net) == WH_NET_MAX) {
+ waddstr(w_net, ", qlen: ");
+ sprintf(tmp, "%u", info.txqlen);
+ waddstr_b(w_net, tmp);
- waddstr(w_net, ", mac: ");
- waddstr_b(w_net, ether_addr(&info.hwaddr));
+ wmove(w_net, 3, 1);
+ wclrtoborder(w_net);
+ } else {
+ waddstr(w_net, ", ");
+ }
+ waddstr(w_net, "ip: ");
+
+ if (!info.addr.s_addr) {
+ waddstr_b(w_net, "n/a");
+ } else {
+ sprintf(tmp, "%s/%u", inet_ntoa(info.addr),
+ prefix_len(&info.netmask));
+ waddstr_b(w_net, tmp);
+
+ /* only show bcast address if not set to the obvious default */
+ if (info.bcast.s_addr !=
+ (info.addr.s_addr | ~info.netmask.s_addr)) {
+ waddstr(w_net, ", bcast: ");
+ waddstr_b(w_net, inet_ntoa(info.bcast));
+ }
+ }
+
+ /* 802.11 MTU may be greater than Ethernet MTU (1500) */
+ if (info.mtu && info.mtu != ETH_DATA_LEN) {
+ waddstr(w_net, ", mtu: ");
+ sprintf(tmp, "%u", info.mtu);
+ waddstr_b(w_net, tmp);
+ }
- wclrtoborder(w_net);
wrefresh(w_net);
}
-enum wavemon_screen scr_info(WINDOW *w_menu)
+static void redraw_stat_levels(int signum)
{
- WINDOW *w_if, *w_info, *w_net;
- struct timer t1;
- int key = 0;
+ sampling_do_poll();
+ display_levels();
+ display_stats();
+}
- w_if = newwin_title(0, 2, "Interface", true);
- w_levels = newwin_title(2, 9, "Levels", true);
- w_stats = newwin_title(11, 3, "Statistics", true);
- w_info = newwin_title(14, 6, "Info", true);
- w_net = newwin_title(20, 3, "Network", false);
+void scr_info_init(void)
+{
+ int line = 0;
+
+ w_if = newwin_title(line, WH_IFACE, "Interface", true);
+ line += WH_IFACE;
+ w_levels = newwin_title(line, WH_LEVEL, "Levels", true);
+ line += WH_LEVEL;
+ w_stats = newwin_title(line, WH_STATS, "Statistics", true);
+ line += WH_STATS;
+ w_info = newwin_title(line, WH_INFO_MIN, "Info", true);
+ line += WH_INFO_MIN;
+ 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);
display_info(w_if, w_info);
display_netinfo(w_net);
+ start_timer(&dyn_updates, conf.info_iv * 1000000);
+ sampling_init(redraw_stat_levels);
+}
- iw_stat_redraw = redraw_stats;
-
- while (key < KEY_F(1) || key > KEY_F(10)) {
+int scr_info_loop(WINDOW *w_menu)
+{
+ if (end_timer(&dyn_updates)) {
display_info(w_if, w_info);
display_netinfo(w_net);
-
- start_timer(&t1, conf.info_iv * 1000000);
- while (!end_timer(&t1) && (key = wgetch(w_menu)) <= 0)
- sleep(1);
-
- /* Keyboard shortcuts */
- if (key == 'q')
- key = KEY_F(10);
- else if (key == 'i')
- key = KEY_F(1);
+ start_timer(&dyn_updates, conf.info_iv * 1000000);
}
+ return wgetch(w_menu);
+}
- iw_stat_redraw = NULL;
+void scr_info_fini(void)
+{
+ sampling_stop();
- delwin(w_if);
- delwin(w_levels);
- delwin(w_stats);
- delwin(w_info);
delwin(w_net);
-
- return key - KEY_F(1);
+ delwin(w_info);
+ delwin(w_stats);
+ delwin(w_levels);
+ delwin(w_if);
}