diff options
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | about_scr.c | 3 | ||||
-rwxr-xr-x | configure | 40 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | info_scr.c | 75 | ||||
-rw-r--r-- | iw_if.c | 49 | ||||
-rw-r--r-- | iw_if.h | 34 | ||||
-rw-r--r-- | iw_nl80211.c | 2 | ||||
-rw-r--r-- | iw_scan.c | 56 | ||||
-rw-r--r-- | scan_scr.c | 6 | ||||
-rw-r--r-- | wavemon.h | 2 |
11 files changed, 64 insertions, 207 deletions
diff --git a/Makefile.in b/Makefile.in index d2e1c01..c9ecc37 100644 --- a/Makefile.in +++ b/Makefile.in @@ -20,7 +20,7 @@ RM = rm -vf MAIN = @PACKAGE_NAME@.c HEADERS = $(wildcard *.h) -PURESRC = $(filter-out $(MAIN),$(wildcard *.c)) +PURESRC = $(filter-out $(MAIN),$(sort $(wildcard *.c))) OBJS = $(PURESRC:.c=.o) DOCS = README.md NEWS THANKS AUTHORS COPYING ChangeLog diff --git a/about_scr.c b/about_scr.c index fb4c080..76adaba 100644 --- a/about_scr.c +++ b/about_scr.c @@ -29,9 +29,6 @@ static char *about_lines[] = { "original by jan morgenstern <jan@jm-music.de>", "distributed under the GNU general public license v3", "", - "please send suggestions and bug reports to ", - PACKAGE_BUGREPORT, - "", PACKAGE_URL }; @@ -1,8 +1,8 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for wavemon 0.8.0. +# Generated by GNU Autoconf 2.69 for wavemon 0.8.2. # -# Report bugs to <gerrit@erg.abdn.ac.uk>. +# Report bugs to <https://github.com/uoaerg/wavemon>. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -267,10 +267,10 @@ fi $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and -$0: gerrit@erg.abdn.ac.uk about your system, including any -$0: error possibly output before this message. Then install -$0: a modern shell, or manually run the script under such a -$0: shell if you do have one." +$0: https://github.com/uoaerg/wavemon about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." fi exit 1 fi @@ -580,9 +580,9 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='wavemon' PACKAGE_TARNAME='wavemon-current' -PACKAGE_VERSION='0.8.0' -PACKAGE_STRING='wavemon 0.8.0' -PACKAGE_BUGREPORT='gerrit@erg.abdn.ac.uk' +PACKAGE_VERSION='0.8.2' +PACKAGE_STRING='wavemon 0.8.2' +PACKAGE_BUGREPORT='https://github.com/uoaerg/wavemon' PACKAGE_URL='https://github.com/uoaerg/wavemon' # Factoring default headers for most tests. @@ -1249,7 +1249,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures wavemon 0.8.0 to adapt to many kinds of systems. +\`configure' configures wavemon 0.8.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1314,7 +1314,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of wavemon 0.8.0:";; + short | recursive ) echo "Configuration of wavemon 0.8.2:";; esac cat <<\_ACEOF @@ -1343,7 +1343,7 @@ Some influential environment variables: Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. -Report bugs to <gerrit@erg.abdn.ac.uk>. +Report bugs to <https://github.com/uoaerg/wavemon>. wavemon home page: <https://github.com/uoaerg/wavemon>. _ACEOF ac_status=$? @@ -1407,7 +1407,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -wavemon configure 0.8.0 +wavemon configure 0.8.2 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1608,9 +1608,9 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( $as_echo "## ------------------------------------ ## -## Report this to gerrit@erg.abdn.ac.uk ## -## ------------------------------------ ##" +( $as_echo "## ------------------------------------------------ ## +## Report this to https://github.com/uoaerg/wavemon ## +## ------------------------------------------------ ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac @@ -1830,7 +1830,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by wavemon $as_me 0.8.0, which was +It was created by wavemon $as_me 0.8.2, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4955,7 +4955,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by wavemon $as_me 0.8.0, which was +This file was extended by wavemon $as_me 0.8.2, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5002,14 +5002,14 @@ Usage: $0 [OPTION]... [TAG]... Configuration files: $config_files -Report bugs to <gerrit@erg.abdn.ac.uk>. +Report bugs to <https://github.com/uoaerg/wavemon>. wavemon home page: <https://github.com/uoaerg/wavemon>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -wavemon config.status 0.8.0 +wavemon config.status 0.8.2 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 7132dea..323b96c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.64) -AC_INIT([wavemon], [0.8.0], [gerrit@erg.abdn.ac.uk], [wavemon-current], +AC_INIT([wavemon], [0.8.2], [https://github.com/uoaerg/wavemon], [wavemon-current], [https://github.com/uoaerg/wavemon]) @@ -53,6 +53,7 @@ static void *sampling_loop(void *arg) void sampling_init(void) { + pthread_mutex_init(&linkstat.mutex, NULL); linkstat.run = true; pthread_create(&sampling_thread, NULL, sampling_loop, NULL); } @@ -61,6 +62,7 @@ void sampling_stop(void) { linkstat.run = false; pthread_join(sampling_thread, NULL); + pthread_mutex_destroy(&linkstat.mutex); } static void display_levels(void) @@ -78,7 +80,6 @@ static void display_levels(void) bool noise_data_valid; int sig_qual = -1, sig_qual_max, sig_level; - noise_data_valid = iw_nl80211_have_survey_data(&linkstat.data); sig_level = linkstat.data.signal_avg ?: linkstat.data.signal; @@ -103,12 +104,6 @@ static void display_levels(void) 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; - } - line = 1; /* Noise data is rare. Use the space for spreading out. */ @@ -173,7 +168,6 @@ static void display_levels(void) waddstr_b(w_levels, tmp); } -done_levels: wrefresh(w_levels); } @@ -211,7 +205,8 @@ static void display_stats(void) if (linkstat.data.rx_drop_misc) { waddstr(w_stats, ", drop: "); - sprintf(tmp, "%'llu", (unsigned long long)linkstat.data.rx_drop_misc); + sprintf(tmp, "%'llu (%.1f%%)", (unsigned long long)linkstat.data.rx_drop_misc, + (1e2 * linkstat.data.rx_drop_misc)/linkstat.data.rx_packets); waddstr_b(w_stats, tmp); } @@ -237,7 +232,8 @@ static void display_stats(void) if (linkstat.data.tx_retries) { waddstr(w_stats, ", retries: "); - sprintf(tmp, "%'u", linkstat.data.tx_retries); + sprintf(tmp, "%'u (%.1f%%)", linkstat.data.tx_retries, + (1e2 * linkstat.data.tx_retries)/linkstat.data.tx_packets); waddstr_b(w_stats, tmp); } @@ -257,10 +253,9 @@ static void display_info(WINDOW *w_if, WINDOW *w_info) struct iw_nl80211_ifstat ifs; struct iw_nl80211_reg ir; char tmp[0x100]; - int i; iw_getinf_range(conf_ifname(), &range); - dyn_info_get(&info, conf_ifname(), &range); + dyn_info_get(&info, conf_ifname()); iw_nl80211_getifstat(&ifs); iw_nl80211_getreg(&ir); @@ -530,63 +525,11 @@ static void display_info(WINDOW *w_if, WINDOW *w_info) } wclrtoborder(w_info); + /* FIXME: re-enable encryption information (issue #8) wmove(w_info, 7, 1); waddstr(w_info, "encryption: "); - if (info.keys) { - int cnt = dyn_info_active_keys(&info); - - 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)); - - if (info.keys[i].flags & IW_ENCODE_RESTRICTED) - waddstr(w_info, ", restricted"); - 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 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); } @@ -154,11 +154,10 @@ void iw_get_interface_list(char** if_list, size_t max_entries) * @ifname: interface name * @if: range information to use (number of encryption keys) */ -void dyn_info_get(struct iw_dyn_info *info, - const char *ifname, struct iw_range *ir) +void dyn_info_get(struct iw_dyn_info *info, const char *ifname) { struct iwreq iwr; - int i, skfd = socket(AF_INET, SOCK_DGRAM, 0); + int skfd = socket(AF_INET, SOCK_DGRAM, 0); if (skfd < 0) err_sys("%s: can not open socket", __func__); @@ -230,43 +229,6 @@ void dyn_info_get(struct iw_dyn_info *info, info->mode = iwr.u.mode; } - info->nkeys = ir->max_encoding_tokens; - if (info->nkeys) { - info->keys = calloc(info->nkeys, sizeof(*info->keys)); - if (info->keys == NULL) - err_sys("malloc(key array)"); - - /* Get index of default key first */ - iwr.u.data.pointer = info->keys[0].key; - iwr.u.data.length = sizeof(info->keys[0].key); - iwr.u.data.flags = 0; - if (ioctl(skfd, SIOCGIWENCODE, &iwr) < 0) { - free(info->keys); - info->keys = NULL; - info->nkeys = 0; - } else { - info->active_key = iwr.u.data.flags & IW_ENCODE_INDEX; - } - } - /* If successful, populate the key array */ - for (i = 0; i < info->nkeys; i++) { - iwr.u.data.pointer = info->keys[i].key; - iwr.u.data.length = sizeof(info->keys->key); - iwr.u.data.flags = i + 1; /* counts 1..n instead of 0..n-1 */ - if (ioctl(skfd, SIOCGIWENCODE, &iwr) < 0) { - free(info->keys); - info->nkeys = 0; - break; - } - info->keys[i].size = iwr.u.data.length; - info->keys[i].flags = iwr.u.data.flags; - - /* Validate whether the current key is indeed active */ - if (i + 1 == info->active_key && (info->keys[i].size == 0 || - (info->keys[i].flags & IW_ENCODE_DISABLED))) - info->active_key = 0; - } - if (ioctl(skfd, SIOCGIWAP, &iwr) >= 0) { info->cap_ap = 1; memcpy(&info->ap_addr, &iwr.u.ap_addr, sizeof(struct sockaddr)); @@ -274,13 +236,6 @@ void dyn_info_get(struct iw_dyn_info *info, close(skfd); } -void dyn_info_cleanup(struct iw_dyn_info *info) -{ - if (info) - free(info->keys); -} - - /* * Request range information for a given wireless interface. * @ifname: name of the wireless argument @@ -148,37 +148,9 @@ struct iw_dyn_info { float freq; int32_t sens; unsigned long bitrate; - - struct iw_key *keys; - uint8_t nkeys; - uint8_t active_key; }; -/* Return the number of encryption keys marked 'active' in @info */ -static inline uint8_t dyn_info_active_keys(struct iw_dyn_info *info) -{ - int i, num_active = 0; - - for (i = 0; i < info->nkeys; i++) - num_active += info->keys[i].size && - !(info->keys[i].flags & IW_ENCODE_DISABLED); - return num_active; -} - -/* Return the number of 40-bit/104-bit keys in @info */ -static inline uint8_t dyn_info_wep_keys(struct iw_dyn_info *info) -{ - int i, num_wep = 0; - - for (i = 0; i < info->nkeys; i++) - if (!(info->keys[i].flags & IW_ENCODE_DISABLED)) - num_wep += info->keys[i].size == 5 || - info->keys[i].size == 13; - return num_wep; -} -extern void dyn_info_get(struct iw_dyn_info *info, - const char *ifname, struct iw_range *ir); -extern void dyn_info_cleanup(struct iw_dyn_info *info); +extern void dyn_info_get(struct iw_dyn_info *info, const char *ifname); /* @@ -278,8 +250,8 @@ struct scan_result { pthread_mutex_t mutex; }; -extern void scan_result_init(struct scan_result *sr); -extern void scan_result_fini(struct scan_result *sr); +extern void init_scan_list(struct scan_result *sr); +extern void free_scan_list(struct scan_entry *head); extern void *do_scan(void *sr_ptr); /* diff --git a/iw_nl80211.c b/iw_nl80211.c index 5b9c562..339e58b 100644 --- a/iw_nl80211.c +++ b/iw_nl80211.c @@ -128,7 +128,7 @@ void parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen) rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]); if (rate > 0) pos += snprintf(pos, buflen - (pos - buf), - "%d.%d MBit/s", rate / 10, rate % 10); + "%d.%d Mbit/s", rate / 10, rate % 10); if (rinfo[NL80211_RATE_INFO_MCS]) pos += snprintf(pos, buflen - (pos - buf), @@ -105,7 +105,7 @@ static int wait_event(struct nl_msg *msg, void *arg) * Returns true if scan results are available, false if scan was aborted. * Taken from iw:event.c:__do_listen_events */ -static bool wait_for_scan_events(struct scan_result *sr) +static bool wait_for_scan_events(void) { static const uint32_t cmds[] = { NL80211_CMD_NEW_SCAN_RESULTS, @@ -293,7 +293,8 @@ void sort_scan_list(struct scan_entry **headp) *headp = head; } -static void free_scan_list(struct scan_entry *head) +/** De-allocate list. Use after all threads are terminated. */ +void free_scan_list(struct scan_entry *head) { if (head) { free_scan_list(head->next); @@ -301,9 +302,9 @@ static void free_scan_list(struct scan_entry *head) } } -static void clear_scan_list(struct scan_result *sr) +/** Initialize scan results. Requires lock to be taken. */ +void init_scan_list(struct scan_result *sr) { - pthread_mutex_lock(&sr->mutex); free_scan_list(sr->head); free(sr->channel_stats); sr->head = NULL; @@ -311,7 +312,7 @@ static void clear_scan_list(struct scan_result *sr) sr->msg[0] = '\0'; sr->max_essid_len = MAX_ESSID_LEN; memset(&(sr->num), 0, sizeof(sr->num)); - pthread_mutex_unlock(&sr->mutex); + sr->mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; } /* @@ -366,28 +367,6 @@ static void compute_channel_stats(struct scan_result *sr) sr->num.ch_stats = n < MAX_CH_STATS ? n : MAX_CH_STATS; } -/* - * Scan results. - */ -void scan_result_init(struct scan_result *sr) -{ - pthread_mutexattr_t ma; - - memset(sr, 0, sizeof(*sr)); - pthread_mutexattr_init(&ma); - if (pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST) < 0) - err_sys("Failed to set the mutex robust attribute"); - pthread_mutex_init(&sr->mutex, &ma); -} - -void scan_result_fini(struct scan_result *sr) -{ - /* FIXME: this may have a bug on resource de-allocation, if the main thread still holds the lock */ - free_scan_list(sr->head); - free(sr->channel_stats); - pthread_mutex_destroy(&sr->mutex); -} - /** The actual scan thread. */ void *do_scan(void *sr_ptr) { @@ -402,15 +381,21 @@ void *do_scan(void *sr_ptr) pthread_detach(pthread_self()); do { - clear_scan_list(sr); - ret = iw_nl80211_scan_trigger(); + + pthread_mutex_lock(&sr->mutex); + init_scan_list(sr); switch(-ret) { case 0: case EBUSY: /* Trigger returns -EBUSY if a scan request is pending or ready. */ - if (!wait_for_scan_events(sr)) { + pthread_mutex_unlock(&sr->mutex); + + /* Do not hold the lock while awaiting results. */ + if (!wait_for_scan_events()) { + pthread_mutex_lock(&sr->mutex); snprintf(sr->msg, sizeof(sr->msg), "Waiting for scan data..."); + pthread_mutex_unlock(&sr->mutex); } else { pthread_mutex_lock(&sr->mutex); ret = iw_nl80211_get_scan_data(sr); @@ -426,8 +411,8 @@ void *do_scan(void *sr_ptr) break; case EPERM: if (!has_net_admin_capability()) - snprintf(sr->msg, sizeof(sr->msg), - "This screen requires CAP_NET_ADMIN permissions"); + snprintf(sr->msg, sizeof(sr->msg), "This screen requires CAP_NET_ADMIN permissions"); + pthread_mutex_unlock(&sr->mutex); return NULL; case EFAULT: /* EFAULT can occur after a window resizing event: temporary, fall through. */ @@ -435,18 +420,21 @@ void *do_scan(void *sr_ptr) case EAGAIN: /* Temporary errors. */ snprintf(sr->msg, sizeof(sr->msg), "Waiting for device to become ready ..."); + pthread_mutex_unlock(&sr->mutex); break; case ENETDOWN: if (!if_is_up(conf_ifname())) { snprintf(sr->msg, sizeof(sr->msg), "Interface %s is down - setting it up ...", conf_ifname()); + pthread_mutex_unlock(&sr->mutex); + if (if_set_up(conf_ifname()) < 0) err_sys("Can not bring up interface '%s'", conf_ifname()); break; } /* fall through */ default: - snprintf(sr->msg, sizeof(sr->msg), - "Scan trigger failed on %s: %s", conf_ifname(), strerror(-ret)); + snprintf(sr->msg, sizeof(sr->msg), "Scan trigger failed on %s: %s", conf_ifname(), strerror(-ret)); + pthread_mutex_unlock(&sr->mutex); } } while (usleep(conf.stat_iv * 1000) == 0); @@ -203,7 +203,7 @@ void scr_aplst_init(void) mvwaddstr(w_aplst, START_LINE, 1, "Waiting for scan data ..."); wrefresh(w_aplst); - scan_result_init(&sr); + init_scan_list(&sr); pthread_create(&scan_thread, NULL, do_scan, &sr); } @@ -251,6 +251,8 @@ int scr_aplst_loop(WINDOW *w_menu) void scr_aplst_fini(void) { pthread_cancel(scan_thread); - scan_result_fini(&sr); + free_scan_list(sr.head); + free(sr.channel_stats); + delwin(w_aplst); } @@ -51,7 +51,7 @@ enum info_screen_geometry { WH_IFACE = 2, /* 'Interface' area at the top */ WH_LEVEL = 9, /* Level meters */ WH_STATS = 3, /* WiFi statistics area */ - WH_INFO_MIN = 8, /* WiFi information area */ + WH_INFO_MIN = 7, /* WiFi information area */ WH_NET_MIN = 3, /* Network interface information area */ WH_NET_MAX = 5, /* Network interface information area */ WH_MENU = 1 /* Menu bar at the bottom */ |