*
*
* By default, madwifi plugin enumerates network interfaces using /sys
- * filesystem. Configuration option DisableSysfs can change this to use
+ * filesystem. Configuration option `Source' can change this to use
* /proc filesystem (which is useful for example when running on Linux
* 2.4). But without /sys filesystem, Madwifi plugin cannot check whether
* given interface is madwifi interface and there are private ioctls used,
* which may do something completely different on non-madwifi devices.
- * Therefore, option DisableSysfs should be used together with option
- * Interface, to limit found interfaces to madwifi interfaces only.
+ * Therefore, the /proc filesystem should always be used together with option
+ * `Interface', to limit found interfaces to madwifi interfaces only.
**/
#include <dirent.h>
#include <sys/ioctl.h>
-#include <sys/socket.h>
#if !KERNEL_LINUX
# error "No applicable input method."
{
"Interface",
"IgnoreSelected",
- "DisableSysfs",
+ "Source",
"WatchAdd",
"WatchRemove",
"WatchSet",
"MiscAdd",
"MiscRemove",
- "MiscSet",
- NULL
+ "MiscSet"
};
-static int config_keys_num = 9;
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
-static ignorelist_t *ignorelist;
+static ignorelist_t *ignorelist = NULL;
static int use_sysfs = 1;
static int init_state = 0;
static inline int item_watched(int i)
{
+ assert (i >= 0);
+ assert (((size_t) i) < ((STATIC_ARRAY_SIZE (watch_items) + 1) * 32));
return watch_items[i / 32] & FLAG (i);
}
static inline int item_summed(int i)
{
+ assert (i >= 0);
+ assert (((size_t) i) < ((STATIC_ARRAY_SIZE (misc_items) + 1) * 32));
return misc_items[i / 32] & FLAG (i);
}
static inline void watchlist_add (uint32_t *wl, int item)
{
+ assert (item >= 0);
+ assert (item < ((WL_LEN + 1) * 32));
wl[item / 32] |= FLAG (item);
}
static inline void watchlist_remove (uint32_t *wl, int item)
{
+ assert (item >= 0);
+ assert (item < ((WL_LEN + 1) * 32));
wl[item / 32] &= ~FLAG (item);
}
/* This is horribly inefficient, but it is called only during configuration */
static int watchitem_find (const char *name)
{
- int max = sizeof (specs) / sizeof (struct stat_spec);
+ int max = STATIC_ARRAY_SIZE (specs);
int i;
for (i = 0; i < max; i++)
static int madwifi_real_init (void)
{
- int max = sizeof (specs) / sizeof (struct stat_spec);
- int i;
+ size_t max = STATIC_ARRAY_SIZE (specs);
+ size_t i;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
bounds[i] = 0;
watchlist_set(watch_items, 0);
misc_items[i / 32] |= FLAG (i);
}
- for (i = 0; i < 4; i++)
+ for (i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
bounds[i]++;
return (0);
}
-static int bool_arg (const char *value)
-{
- return ((strcasecmp (value, "True") == 0)
- || (strcasecmp (value, "Yes") == 0)
- || (strcasecmp (value, "On") == 0));
-}
-
static int madwifi_config (const char *key, const char *value)
{
if (init_state != 1)
ignorelist_add (ignorelist, value);
else if (strcasecmp (key, "IgnoreSelected") == 0)
- ignorelist_set_invert (ignorelist, ! bool_arg(value));
+ ignorelist_set_invert (ignorelist, IS_TRUE (value) ? 0 : 1);
- else if (strcasecmp (key, "DisableSysfs") == 0)
- use_sysfs = ! bool_arg(value);
+ else if (strcasecmp (key, "Source") == 0)
+ {
+ if (strcasecmp (value, "ProcFS") == 0)
+ use_sysfs = 0;
+ else if (strcasecmp (value, "SysFS") == 0)
+ use_sysfs = 1;
+ else
+ {
+ ERROR ("madwifi plugin: The argument of the `Source' "
+ "option must either be `SysFS' or "
+ "`ProcFS'.");
+ return -1;
+ }
+ }
else if (strcasecmp (key, "WatchSet") == 0)
{
sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
sstrncpy (vl.type, type, sizeof (vl.type));
- if (ti1 && !ti2)
- sstrncpy (vl.type_instance, ti1, sizeof (vl.type_instance));
-
- if (ti1 && ti2)
+ if ((ti1 != NULL) && (ti2 != NULL))
ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s", ti1, ti2);
+ else if ((ti1 != NULL) && (ti2 == NULL))
+ sstrncpy (vl.type_instance, ti1, sizeof (vl.type_instance));
plugin_dispatch_values (&vl);
}
-static void submit_counter (const char *dev, const char *type, const char *ti1,
- const char *ti2, counter_t val)
+static void submit_derive (const char *dev, const char *type, const char *ti1,
+ const char *ti2, derive_t val)
{
value_t item;
- item.counter = val;
+ item.derive = val;
submit (dev, type, ti1, ti2, &item, 1);
}
-static void submit_counter2 (const char *dev, const char *type, const char *ti1,
- const char *ti2, counter_t val1, counter_t val2)
+static void submit_derive2 (const char *dev, const char *type, const char *ti1,
+ const char *ti2, derive_t val1, derive_t val2)
{
value_t items[2];
- items[0].counter = val1;
- items[1].counter = val2;
+ items[0].derive = val1;
+ items[1].derive = val2;
submit (dev, type, ti1, ti2, items, 2);
}
submit (dev, type, ti1, ti2, &item, 1);
}
-static void submit_antx (const char *dev, const char *name, u_int32_t *vals)
+static void submit_antx (const char *dev, const char *name,
+ u_int32_t *vals, int vals_num)
{
- char no[2] = {0, 0};
+ char ti2[16];
int i;
- for (i = 0; i < 8; i++)
- if (vals[i])
- {
- no[0] = '0' + i;
- submit_counter (dev, "ath_stat", name, no, vals[i]);
- }
+ for (i = 0; i < vals_num; i++)
+ {
+ if (vals[i] == 0)
+ continue;
+
+ ssnprintf (ti2, sizeof (ti2), "%i", i);
+ submit_derive (dev, "ath_stat", name, ti2,
+ (derive_t) vals[i]);
+ }
}
static inline void
macaddr_to_str (char *buf, size_t bufsize, const uint8_t mac[IEEE80211_ADDR_LEN])
{
- snprintf (buf, bufsize, "%02x:%02x:%02x:%02x:%02x:%02x",
+ ssnprintf (buf, bufsize, "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
uint32_t misc = 0;
int i;
+ assert (which >= 1);
+ assert (((size_t) which) < STATIC_ARRAY_SIZE (bounds));
+
for (i = bounds[which - 1]; i < bounds[which]; i++)
{
uint32_t val = *(uint32_t *)(((char *) ptr) + specs[i].offset) ;
if (item_watched (i) && (val != 0))
- submit_counter (dev, type_name, specs[i].name, mac, val);
+ submit_derive (dev, type_name, specs[i].name, mac, val);
if (item_summed (i))
misc += val;
}
if (misc != 0)
- submit_counter (dev, type_name, misc_name, mac, misc);
+ submit_derive (dev, type_name, misc_name, mac, misc);
}
-static void
+static int
process_athstats (int sk, const char *dev)
{
struct ifreq ifr;
struct ath_stats stats;
+ int status;
- strncpy (ifr.ifr_name, dev, sizeof (ifr.ifr_name));
+ sstrncpy (ifr.ifr_name, dev, sizeof (ifr.ifr_name));
ifr.ifr_data = (void *) &stats;
- if (ioctl (sk, SIOCGATHSTATS, &ifr) < 0)
- return;
+ status = ioctl (sk, SIOCGATHSTATS, &ifr);
+ if (status < 0)
+ {
+ /* Silent, because not all interfaces support all ioctls. */
+ DEBUG ("madwifi plugin: Sending IO-control "
+ "SIOCGATHSTATS to device %s "
+ "failed with status %i.",
+ dev, status);
+ return (status);
+ }
/* These stats are handled as a special case, because they are
eight values each */
if (item_watched (STAT_AST_ANT_RX))
- submit_antx (dev, "ast_ant_rx", stats.ast_ant_rx);
+ submit_antx (dev, "ast_ant_rx", stats.ast_ant_rx,
+ STATIC_ARRAY_SIZE (stats.ast_ant_rx));
if (item_watched (STAT_AST_ANT_TX))
- submit_antx (dev, "ast_ant_tx", stats.ast_ant_tx);
+ submit_antx (dev, "ast_ant_tx", stats.ast_ant_tx,
+ STATIC_ARRAY_SIZE (stats.ast_ant_tx));
/* All other ath statistics */
process_stat_struct (ATH_STAT, &stats, dev, NULL, "ath_stat", "ast_misc");
+ return (0);
}
-static void
+static int
process_80211stats (int sk, const char *dev)
{
struct ifreq ifr;
struct ieee80211_stats stats;
- strncpy (ifr.ifr_name, dev, sizeof (ifr.ifr_name));
+ int status;
+
+ sstrncpy (ifr.ifr_name, dev, sizeof (ifr.ifr_name));
ifr.ifr_data = (void *) &stats;
- if (ioctl(sk, SIOCG80211STATS, &ifr) < 0)
- return;
+ status = ioctl(sk, SIOCG80211STATS, &ifr);
+ if (status < 0)
+ {
+ /* Silent, because not all interfaces support all ioctls. */
+ DEBUG ("madwifi plugin: Sending IO-control "
+ "SIOCG80211STATS to device %s "
+ "failed with status %i.",
+ dev, status);
+ return (status);
+ }
process_stat_struct (IFA_STAT, &stats, dev, NULL, "ath_stat", "is_misc");
+ return (0);
}
-static void
+static int
process_station (int sk, const char *dev, struct ieee80211req_sta_info *si)
{
struct iwreq iwr;
static char mac[DATA_MAX_NAME_LEN];
struct ieee80211req_sta_stats stats;
const struct ieee80211_nodestats *ns = &stats.is_stats;
+ int status;
macaddr_to_str (mac, sizeof (mac), si->isi_macaddr);
submit_gauge (dev, "node_rssi", mac, NULL, si->isi_rssi);
memset (&iwr, 0, sizeof (iwr));
- strncpy(iwr.ifr_name, dev, sizeof (iwr.ifr_name));
+ sstrncpy(iwr.ifr_name, dev, sizeof (iwr.ifr_name));
iwr.u.data.pointer = (void *) &stats;
iwr.u.data.length = sizeof (stats);
memcpy(stats.is_u.macaddr, si->isi_macaddr, IEEE80211_ADDR_LEN);
- if (ioctl(sk, IEEE80211_IOCTL_STA_STATS, &iwr) < 0)
- return;
+ status = ioctl(sk, IEEE80211_IOCTL_STA_STATS, &iwr);
+ if (status < 0)
+ {
+ /* Silent, because not all interfaces support all ioctls. */
+ DEBUG ("madwifi plugin: Sending IO-control "
+ "IEEE80211_IOCTL_STA_STATS to device %s "
+ "failed with status %i.",
+ dev, status);
+ return (status);
+ }
/* These two stats are handled as a special case as they are
a pair of 64bit values */
if (item_watched (STAT_NODE_OCTETS))
- submit_counter2 (dev, "node_octets", mac, NULL,
+ submit_derive2 (dev, "node_octets", mac, NULL,
ns->ns_rx_bytes, ns->ns_tx_bytes);
/* This stat is handled as a special case, because it is stored
as uin64_t, but we will ignore upper half */
if (item_watched (STAT_NS_RX_BEACONS))
- submit_counter (dev, "node_stat", "ns_rx_beacons", mac,
+ submit_derive (dev, "node_stat", "ns_rx_beacons", mac,
(ns->ns_rx_beacons & 0xFFFFFFFF));
/* All other node statistics */
process_stat_struct (NOD_STAT, ns, dev, mac, "node_stat", "ns_misc");
+ return (0);
}
-static void
+static int
process_stations (int sk, const char *dev)
{
uint8_t buf[24*1024];
struct iwreq iwr;
uint8_t *cp;
- int len, nodes;
+ int nodes;
+ size_t len;
+ int status;
memset (&iwr, 0, sizeof (iwr));
- strncpy (iwr.ifr_name, dev, sizeof (iwr.ifr_name));
+ sstrncpy (iwr.ifr_name, dev, sizeof (iwr.ifr_name));
iwr.u.data.pointer = (void *) buf;
iwr.u.data.length = sizeof (buf);
- if (ioctl (sk, IEEE80211_IOCTL_STA_INFO, &iwr) < 0)
- return;
+
+ status = ioctl (sk, IEEE80211_IOCTL_STA_INFO, &iwr);
+ if (status < 0)
+ {
+ /* Silent, because not all interfaces support all ioctls. */
+ DEBUG ("madwifi plugin: Sending IO-control "
+ "IEEE80211_IOCTL_STA_INFO to device %s "
+ "failed with status %i.",
+ dev, status);
+ return (status);
+ }
len = iwr.u.data.length;
if (item_watched (STAT_ATH_NODES))
submit_gauge (dev, "ath_nodes", NULL, NULL, nodes);
+ return (0);
}
-static void
+static int
process_device (int sk, const char *dev)
{
- process_athstats (sk, dev);
- process_80211stats (sk, dev);
- process_stations (sk, dev);
+ int num_success = 0;
+ int status;
+
+ status = process_athstats (sk, dev);
+ if (status == 0)
+ num_success++;
+
+ status = process_80211stats (sk, dev);
+ if (status == 0)
+ num_success++;
+
+ status = process_stations (sk, dev);
+ if (status == 0)
+ num_success++;
+
+ return ((num_success == 0) ? -1 : 0);
}
static int
check_devname (const char *dev)
{
- char buf[256];
- char buf2[256];
+ char buf[PATH_MAX];
+ char buf2[PATH_MAX];
int i;
if (dev[0] == '.')
return 0;
-
+
ssnprintf (buf, sizeof (buf), "/sys/class/net/%s/device/driver", dev);
- buf[sizeof (buf) - 1] = 0;
+ buf[sizeof (buf) - 1] = '\0';
i = readlink (buf, buf2, sizeof (buf2) - 1);
if (i < 0)
return 0;
- buf2[i] = 0;
- return (strstr (buf2, "/drivers/ath_") != NULL);
+ buf2[i] = '\0';
+
+ if (strstr (buf2, "/drivers/ath_") == NULL)
+ return 0;
+ return 1;
}
static int
sysfs_iterate(int sk)
{
struct dirent *de;
+ DIR *nets;
+ int status;
+ int num_success;
+ int num_fail;
- DIR *nets = opendir ("/sys/class/net/");
+ nets = opendir ("/sys/class/net/");
if (nets == NULL)
{
WARNING ("madwifi plugin: opening /sys/class/net failed");
return (-1);
}
+ num_success = 0;
+ num_fail = 0;
while ((de = readdir (nets)))
- if (check_devname (de->d_name) &&
- (ignorelist_match (ignorelist, de->d_name) == 0))
- process_device (sk, de->d_name);
+ {
+ if (check_devname (de->d_name) == 0)
+ continue;
+
+ if (ignorelist_match (ignorelist, de->d_name) != 0)
+ continue;
+
+ status = process_device (sk, de->d_name);
+ if (status != 0)
+ {
+ ERROR ("madwifi plugin: Processing interface "
+ "%s failed.", de->d_name);
+ num_fail++;
+ }
+ else
+ {
+ num_success++;
+ }
+ } /* while (readdir) */
closedir(nets);
- return 0;
+ if ((num_success == 0) && (num_fail != 0))
+ return (-1);
+ return (0);
}
static int
char buffer[1024];
char *device, *dummy;
FILE *fh;
+ int status;
+ int num_success;
+ int num_fail;
if ((fh = fopen ("/proc/net/dev", "r")) == NULL)
{
return (-1);
}
- while (fgets (buffer, 1024, fh) != NULL)
+ num_success = 0;
+ num_fail = 0;
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
- if (!(dummy = strchr(buffer, ':')))
+ dummy = strchr(buffer, ':');
+ if (dummy == NULL)
continue;
- dummy[0] = '\0';
+ dummy[0] = 0;
device = buffer;
while (device[0] == ' ')
device++;
- if (device[0] == '\0')
+ if (device[0] == 0)
continue;
- if (ignorelist_match (ignorelist, device) == 0)
- process_device (sk, device);
- }
+ if (ignorelist_match (ignorelist, device) != 0)
+ continue;
+
+ status = process_device (sk, device);
+ if (status != 0)
+ {
+ ERROR ("madwifi plugin: Processing interface "
+ "%s failed.", device);
+ num_fail++;
+ }
+ else
+ {
+ num_success++;
+ }
+ } /* while (fgets) */
fclose(fh);
+
+ if ((num_success == 0) && (num_fail != 0))
+ return (-1);
return 0;
}
static int madwifi_read (void)
{
+ int rv;
+ int sk;
+
if (init_state == 0)
madwifi_real_init();
init_state = 2;
- int sk = socket(AF_INET, SOCK_DGRAM, 0);
+ sk = socket(AF_INET, SOCK_DGRAM, 0);
if (sk < 0)
return (-1);
- int rv;
/* procfs iteration is not safe because it does not check whether given
interface is madwifi interface and there are private ioctls used, which