diff options
author | Jonathan McCrohan <jmccrohan@gmail.com> | 2012-02-05 19:03:25 +0000 |
---|---|---|
committer | Jonathan McCrohan <jmccrohan@gmail.com> | 2012-02-05 19:03:25 +0000 |
commit | 03dfbc2efa31d3c4fd7e576111883ea488e3e179 (patch) | |
tree | 6f227b085f675e294edd98d66ccbf190e898f544 /info_scr.c | |
download | wavemon-03dfbc2efa31d3c4fd7e576111883ea488e3e179.tar.gz |
Imported Upstream version 0.6.10upstream/0.6.10
Diffstat (limited to 'info_scr.c')
-rw-r--r-- | info_scr.c | 433 |
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); +} |