X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fmadwifi.c;h=13301fffe15aea8afbce76c3ce06105ededfa195;hb=3427c2e266c04d67848bda913caa730a395c7295;hp=478341ea2a1b2de2170cc9294e040d36737fcb61;hpb=01c19d8cf54620da94b6b22649b1c4a4e4e55c21;p=collectd.git diff --git a/src/madwifi.c b/src/madwifi.c index 478341ea..13301fff 100644 --- a/src/madwifi.c +++ b/src/madwifi.c @@ -78,13 +78,13 @@ * * * 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. **/ @@ -350,39 +350,46 @@ static const char *config_keys[] = { "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 (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 (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); } @@ -396,7 +403,7 @@ static inline void watchlist_set (uint32_t *wl, uint32_t val) /* 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++) @@ -413,10 +420,10 @@ static int watchitem_find (const char *name) static int madwifi_real_init (void) { - int max = sizeof (specs) / sizeof (struct stat_spec); + int max = STATIC_ARRAY_SIZE (specs); int i; - for (i = 0; i < 4; i++) + for (i = 0; i < STATIC_ARRAY_SIZE (bounds); i++) bounds[i] = 0; watchlist_set(watch_items, 0); @@ -433,19 +440,12 @@ static int madwifi_real_init (void) 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) @@ -459,10 +459,22 @@ static int madwifi_config (const char *key, const char *value) 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) { @@ -541,29 +553,28 @@ static void submit (const char *dev, const char *type, const char *ti1, 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); } @@ -575,23 +586,27 @@ static void submit_gauge (const char *dev, const char *type, const char *ti1, 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]); } @@ -602,67 +617,94 @@ process_stat_struct (int which, const void *ptr, const char *dev, const char *ma uint32_t misc = 0; int i; + assert (which >= 1); + assert (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); @@ -674,43 +716,62 @@ process_station (int sk, const char *dev, struct ieee80211req_sta_info *si) 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 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; @@ -727,21 +788,35 @@ process_stations (int sk, const char *dev) 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] == '.') @@ -750,34 +825,60 @@ check_devname (const char *dev) ssnprintf (buf, sizeof (buf), "/sys/class/net/%s/device/driver", dev); buf[sizeof (buf) - 1] = 0; + memset (buf2, 0, sizeof (buf2)); i = readlink (buf, buf2, sizeof (buf2) - 1); if (i < 0) return 0; - buf2[i] = 0; - return (strstr (buf2, "/drivers/ath_") != NULL); + 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 @@ -786,6 +887,9 @@ procfs_iterate(int sk) char buffer[1024]; char *device, *dummy; FILE *fh; + int status; + int num_success; + int num_fail; if ((fh = fopen ("/proc/net/dev", "r")) == NULL) { @@ -793,38 +897,58 @@ procfs_iterate(int sk) 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