X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fnetlink.c;h=b998cf316c6522b09f068a04b83cb7956c3c305f;hp=b5ae3bd2c13058ded2aa1902ebfefc2bf9a58fab;hb=a811574a6acbf87f23948411876a231fecaeb491;hpb=d5456237d0de8f9905ea7a32f2bbae52b5e3ea73 diff --git a/src/netlink.c b/src/netlink.c index b5ae3bd2..b998cf31 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -27,8 +27,8 @@ #include "collectd.h" -#include "common.h" #include "plugin.h" +#include "utils/common/common.h" #include @@ -56,6 +56,7 @@ struct ir_link_stats_storage_s { uint64_t tx_dropped; uint64_t multicast; uint64_t collisions; + uint64_t rx_nohandler; uint64_t rx_length_errors; uint64_t rx_over_errors; @@ -91,12 +92,12 @@ struct qos_stats { }; static int ir_ignorelist_invert = 1; -static ir_ignorelist_t *ir_ignorelist_head = NULL; +static ir_ignorelist_t *ir_ignorelist_head; static struct mnl_socket *nl; -static char **iflist = NULL; -static size_t iflist_len = 0; +static char **iflist; +static size_t iflist_len; static const char *config_keys[] = {"Interface", "VerboseInterface", "QDisc", "Class", @@ -197,7 +198,8 @@ static void submit_two(const char *dev, const char *type, const char *type_instance, derive_t rx, derive_t tx) { value_list_t vl = VALUE_LIST_INIT; value_t values[] = { - {.derive = rx}, {.derive = tx}, + {.derive = rx}, + {.derive = tx}, }; vl.values = values; @@ -253,6 +255,10 @@ static void check_ignorelist_and_submit(const char *dev, submit_two(dev, "if_dropped", NULL, stats->rx_dropped, stats->tx_dropped); submit_one(dev, "if_multicast", NULL, stats->multicast); submit_one(dev, "if_collisions", NULL, stats->collisions); +#if defined(HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER) || \ + defined(HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER) + submit_one(dev, "if_rx_nohandler", NULL, stats->rx_nohandler); +#endif submit_one(dev, "if_rx_errors", "length", stats->rx_length_errors); submit_one(dev, "if_rx_errors", "over", stats->rx_over_errors); @@ -304,6 +310,9 @@ static void check_ignorelist_and_submit64(const char *dev, struct ir_link_stats_storage_s s; COPY_RTNL_LINK_STATS(&s, stats); +#ifdef HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER + COPY_RTNL_LINK_VALUE(&s, stats, rx_nohandler); +#endif check_ignorelist_and_submit(dev, &s); } @@ -314,6 +323,9 @@ static void check_ignorelist_and_submit32(const char *dev, struct ir_link_stats_storage_s s; COPY_RTNL_LINK_STATS(&s, stats); +#ifdef HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER + COPY_RTNL_LINK_VALUE(&s, stats, rx_nohandler); +#endif check_ignorelist_and_submit(dev, &s); } @@ -357,11 +369,10 @@ static int link_filter_cb(const struct nlmsghdr *nlh, if (mnl_attr_get_type(attr) != IFLA_STATS64) continue; - if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*stats.stats64)) < 0) { - char errbuf[1024]; - ERROR("netlink plugin: link_filter_cb: IFLA_STATS64 mnl_attr_validate2 " - "failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + uint16_t attr_len = mnl_attr_get_payload_len(attr); + if (attr_len < sizeof(*stats.stats64)) { + ERROR("netlink plugin: link_filter_cb: IFLA_STATS64 attribute has " + "insufficient data."); return MNL_CB_ERROR; } stats.stats64 = mnl_attr_get_payload(attr); @@ -375,11 +386,10 @@ static int link_filter_cb(const struct nlmsghdr *nlh, if (mnl_attr_get_type(attr) != IFLA_STATS) continue; - if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*stats.stats32)) < 0) { - char errbuf[1024]; - ERROR("netlink plugin: link_filter_cb: IFLA_STATS mnl_attr_validate2 " - "failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + uint16_t attr_len = mnl_attr_get_payload_len(attr); + if (attr_len < sizeof(*stats.stats32)) { + ERROR("netlink plugin: link_filter_cb: IFLA_STATS attribute has " + "insufficient data."); return MNL_CB_ERROR; } stats.stats32 = mnl_attr_get_payload(attr); @@ -404,10 +414,9 @@ static int qos_attr_cb(const struct nlattr *attr, void *data) { if (mnl_attr_get_type(attr) == TCA_STATS_BASIC) { if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*q_stats->bs)) < 0) { - char errbuf[1024]; ERROR("netlink plugin: qos_attr_cb: TCA_STATS_BASIC mnl_attr_validate2 " "failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + STRERRNO); return MNL_CB_ERROR; } q_stats->bs = mnl_attr_get_payload(attr); @@ -441,7 +450,7 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { const char *tc_type; char tc_inst[DATA_MAX_NAME_LEN]; - _Bool stats_submitted = 0; + bool stats_submitted = false; if (nlh->nlmsg_type == RTM_NEWQDISC) tc_type = "qdisc"; @@ -464,7 +473,7 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { if ((tm->tcm_ifindex >= 0) && ((size_t)tm->tcm_ifindex >= iflist_len)) { ERROR("netlink plugin: qos_filter_cb: tm->tcm_ifindex = %i " - ">= iflist_len = %zu", + ">= iflist_len = %" PRIsz, tm->tcm_ifindex, iflist_len); return MNL_CB_ERROR; } @@ -501,8 +510,8 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { if (strcmp(tc_type, "filter") == 0) numberic_id = tm->tcm_parent; - snprintf(tc_inst, sizeof(tc_inst), "%s-%x:%x", kind, numberic_id >> 16, - numberic_id & 0x0000FFFF); + ssnprintf(tc_inst, sizeof(tc_inst), "%s-%x:%x", kind, numberic_id >> 16, + numberic_id & 0x0000FFFF); } DEBUG("netlink plugin: qos_filter_cb: got %s for %s (%i).", tc_type, dev, @@ -531,9 +540,15 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { if (q_stats.bs != NULL || q_stats.qs != NULL) { char type_instance[DATA_MAX_NAME_LEN]; - stats_submitted = 1; + stats_submitted = true; - snprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type, tc_inst); + int r = ssnprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type, + tc_inst); + if ((size_t)r >= sizeof(type_instance)) { + ERROR("netlink plugin: type_instance truncated to %zu bytes, need %d", + sizeof(type_instance), r); + return MNL_CB_ERROR; + } if (q_stats.bs != NULL) { submit_one(dev, "ipt_bytes", type_instance, q_stats.bs->bytes); @@ -556,10 +571,9 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { continue; if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*ts)) < 0) { - char errbuf[1024]; ERROR("netlink plugin: qos_filter_cb: TCA_STATS mnl_attr_validate2 " "failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + STRERRNO); return MNL_CB_ERROR; } ts = mnl_attr_get_payload(attr); @@ -567,7 +581,13 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { if (!stats_submitted && ts != NULL) { char type_instance[DATA_MAX_NAME_LEN]; - snprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type, tc_inst); + int r = ssnprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type, + tc_inst); + if ((size_t)r >= sizeof(type_instance)) { + ERROR("netlink plugin: type_instance truncated to %zu bytes, need %d", + sizeof(type_instance), r); + return MNL_CB_ERROR; + } submit_one(dev, "ipt_bytes", type_instance, ts->bytes); submit_one(dev, "ipt_packets", type_instance, ts->packets); @@ -618,7 +638,7 @@ static int ir_config(const char *key, const char *value) { } else if ((strcasecmp(key, "QDisc") == 0) || (strcasecmp(key, "Class") == 0) || (strcasecmp(key, "Filter") == 0)) { - if ((fields_num < 1) || (fields_num > 2)) { + if (fields_num > 2) { ERROR("netlink plugin: Invalid number of fields for option " "`%s'. Got %i, expected 1 or 2.", key, fields_num); @@ -694,9 +714,7 @@ static int ir_read(void) { ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret < 0) { - char errbuf[1024]; - ERROR("netlink plugin: ir_read: mnl_socket_recvfrom failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + ERROR("netlink plugin: ir_read: mnl_socket_recvfrom failed: %s", STRERRNO); return (-1); } @@ -717,7 +735,7 @@ static int ir_read(void) { continue; } - DEBUG("netlink plugin: ir_read: querying %s from %s (%zu).", + DEBUG("netlink plugin: ir_read: querying %s from %s (%" PRIsz ").", type_name[type_index], iflist[ifindex], ifindex); nlh = mnl_nlmsg_put_header(buf); @@ -741,9 +759,8 @@ static int ir_read(void) { ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret < 0) { - char errbuf[1024]; ERROR("netlink plugin: ir_read: mnl_socket_recvfrom failed: %s", - sstrerror(errno, errbuf, sizeof(errbuf))); + STRERRNO); continue; } } /* for (type_index) */