aboutsummaryrefslogtreecommitdiffstats
path: root/info_scr.c
diff options
context:
space:
mode:
authorJonathan McCrohan <jmccrohan@gmail.com>2012-02-05 19:03:25 +0000
committerJonathan McCrohan <jmccrohan@gmail.com>2012-02-05 19:03:25 +0000
commit03dfbc2efa31d3c4fd7e576111883ea488e3e179 (patch)
tree6f227b085f675e294edd98d66ccbf190e898f544 /info_scr.c
downloadwavemon-03dfbc2efa31d3c4fd7e576111883ea488e3e179.tar.gz
Imported Upstream version 0.6.10upstream/0.6.10
Diffstat (limited to 'info_scr.c')
-rw-r--r--info_scr.c433
1 files changed, 433 insertions, 0 deletions
diff --git a/info_scr.c b/info_scr.c
new file mode 100644
index 0000000..1b4974d
--- /dev/null
+++ b/info_scr.c
@@ -0,0 +1,433 @@
+/*
+ * wavemon - a wireless network monitoring aplication
+ *
+ * Copyright (c) 2001-2002 Jan Morgenstern <jan@jm-music.de>
+ *
+ * wavemon is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * wavemon is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with wavemon; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "iw_if.h"
+
+/* GLOBALS */
+static WINDOW *w_levels, *w_stats;
+
+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)
+{
+ struct itimerval i;
+ div_t d = div(conf.stat_iv, 1000); /* conf.stat_iv in msec */
+
+ 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;
+
+ setitimer(ITIMER_REAL, &i, NULL);
+
+ signal(SIGALRM, sampling_handler);
+}
+
+void reinit_on_changes(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;
+ }
+}
+
+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, 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;
+
+ if (!(cur.stat.qual.updated & IW_QUAL_QUAL_INVALID)) {
+ line += offset;
+
+ mvwaddstr(w_levels, line++, 1, "link quality: ");
+
+ qual = ewma(qual, cur.stat.qual.qual, conf.meter_decay / 100.0);
+ 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)) {
+ 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, '<');
+ }
+
+ if (!offset) {
+ 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
+ * 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);
+ 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);
+ }
+ wrefresh(w_levels);
+}
+
+static void display_stats(void)
+{
+ struct if_stat nstat;
+ char tmp[0x100];
+
+ if_getstat(conf.ifname, &nstat);
+
+ /*
+ * Interface RX stats
+ */
+ 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, ");
+
+ sprintf(tmp, "%'u", cur.stat.discard.code);
+ 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.misc);
+ waddstr_b(w_stats, tmp);
+ waddstr(w_stats, " misc");
+ wclrtoborder(w_stats);
+
+ /*
+ * Interface TX stats
+ */
+ mvwaddstr(w_stats, 2, 1, "TX: ");
+
+ sprintf(tmp, "%'llu (%s)", nstat.tx_packets,
+ 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, ", 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);
+
+ wmove(w_if, 1, 1);
+ sprintf(tmp, "%s (%s)", conf.ifname, info.name);
+ waddstr_b(w_if, tmp);
+
+ if (info.cap_essid) {
+ 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);
+ }
+
+ if (info.cap_nickname) {
+ waddstr(w_if, ", nick: ");
+ sprintf(tmp, "\"%s\"", info.nickname);
+ waddstr_b(w_if, tmp);
+ }
+
+ 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);
+
+ 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");
+
+ 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 (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);
+ }
+
+
+ wmove(w_info, 2, 1);
+ if (info.cap_freq) {
+ 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: ");
+ sprintf(tmp, "%d", i);
+ waddstr_b(w_info, tmp);
+ }
+ } else {
+ waddstr(w_info, "frequency/channel: n/a");
+ }
+
+ if (! (info.mode >= IW_MODE_MASTER && info.mode <= IW_MODE_MONITOR)) {
+ waddstr(w_info, ", bitrate: ");
+ if (info.cap_bitrate) {
+ sprintf(tmp, "%g Mbit/s", info.bitrate / 1.0e6);
+ waddstr_b(w_info, tmp);
+ } else
+ waddstr(w_info, "n/a");
+ }
+
+ wmove(w_info, 3, 1);
+ waddstr(w_info, "power mgt: ");
+ if (info.cap_power)
+ waddstr_b(w_info, format_power(&info.power, &cur.range));
+ else
+ waddstr(w_info, "n/a");
+
+ if (info.cap_txpower && info.txpower.disabled) {
+ waddstr(w_info, ", tx-power: off");
+ } else if (info.cap_txpower) {
+ /*
+ * Convention: auto-selected values start with a capital
+ * letter, otherwise with a small letter.
+ */
+ if (info.txpower.fixed)
+ waddstr(w_info, ", tx-power: ");
+ else
+ waddstr(w_info, ", TX-power: ");
+ waddstr_b(w_info, format_txpower(&info.txpower));
+ }
+
+ wmove(w_info, 4, 1);
+ waddstr(w_info, "retry: ");
+ if (info.cap_retry)
+ waddstr_b(w_info, format_retry(&info.retry, &cur.range));
+ else
+ waddstr(w_info, "n/a");
+
+ waddstr(w_info, ", ");
+ if (info.cap_rts) {
+ waddstr(w_info, info.rts.fixed ? "rts/cts: " : "RTS/cts: ");
+ if (info.rts.disabled)
+ sprintf(tmp, "off");
+ else
+ sprintf(tmp, "%d B", info.rts.value);
+ waddstr_b(w_info, tmp);
+ } else
+ waddstr(w_info, "rts/cts: n/a");
+
+ waddstr(w_info, ", ");
+ if (info.cap_frag) {
+ waddstr(w_info, info.frag.fixed ? "frag: " : "Frag: ");
+ if (info.frag.disabled)
+ sprintf(tmp, "off");
+ else
+ sprintf(tmp, "%d B", info.frag.value);
+ waddstr_b(w_info, tmp);
+ } else
+ waddstr(w_info, "frag: n/a");
+
+ 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);
+
+ waddstr_b(w_info, curtail(key, "..", 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)
+ waddstr(w_info, ", restricted");
+ if (info.key_flags & IW_ENCODE_OPEN)
+ waddstr(w_info, ", open");
+ }
+ } else
+ waddstr(w_info, "n/a");
+
+ wclrtoborder(w_info);
+ wrefresh(w_info);
+}
+
+static void display_netinfo(WINDOW *w_net)
+{
+ struct if_info info;
+ char tmp[0x40];
+
+ 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);
+
+ waddstr(w_net, ", bcast: ");
+ waddstr_b(w_net, inet_ntoa(info.bcast));
+
+ waddstr(w_net, ", mac: ");
+ waddstr_b(w_net, ether_addr(&info.hwaddr));
+
+ wclrtoborder(w_net);
+ wrefresh(w_net);
+}
+
+enum wavemon_screen scr_info(WINDOW *w_menu)
+{
+ WINDOW *w_if, *w_info, *w_net;
+ struct timer t1;
+ int key = 0;
+
+ 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);
+
+ display_info(w_if, w_info);
+ display_netinfo(w_net);
+
+ iw_stat_redraw = redraw_stats;
+
+ while (key < KEY_F(1) || key > KEY_F(10)) {
+ 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);
+ }
+
+ iw_stat_redraw = NULL;
+
+ delwin(w_if);
+ delwin(w_levels);
+ delwin(w_stats);
+ delwin(w_info);
+ delwin(w_net);
+
+ return key - KEY_F(1);
+}