Code

Merge remote-tracking branch 'github/pr/387'
[collectd.git] / src / madwifi.c
index 364dcbd7b93d934d55c95a1ad8e36b95c09f458d..13301fffe15aea8afbce76c3ce06105ededfa195 100644 (file)
@@ -356,33 +356,40 @@ static const char *config_keys[] =
        "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,7 +459,7 @@ 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, "Source") == 0)
        {
@@ -553,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);
 }
 
@@ -587,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]);
 }
 
@@ -614,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);
 
@@ -686,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;
 
@@ -739,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] == '.')
@@ -762,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
@@ -798,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)
        {
@@ -805,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