X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fnetlink.c;h=b998cf316c6522b09f068a04b83cb7956c3c305f;hb=41d355dc81bd0a0a508f933c9df61c5e844d585b;hp=305167a5bff7059ee85092926092a4c30e13fa7b;hpb=1f308ce7f49a2cef83b70ade2072f391b7ae261e;p=collectd.git diff --git a/src/netlink.c b/src/netlink.c index 305167a5..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", @@ -108,13 +109,13 @@ static int add_ignorelist(const char *dev, const char *type, const char *inst) { entry = calloc(1, sizeof(*entry)); if (entry == NULL) - return (-1); + return -1; if (strcasecmp(dev, "All") != 0) { entry->device = strdup(dev); if (entry->device == NULL) { sfree(entry); - return (-1); + return -1; } } @@ -122,7 +123,7 @@ static int add_ignorelist(const char *dev, const char *type, const char *inst) { if (entry->type == NULL) { sfree(entry->device); sfree(entry); - return (-1); + return -1; } if (inst != NULL) { @@ -131,14 +132,14 @@ static int add_ignorelist(const char *dev, const char *type, const char *inst) { sfree(entry->type); sfree(entry->device); sfree(entry); - return (-1); + return -1; } } entry->next = ir_ignorelist_head; ir_ignorelist_head = entry; - return (0); + return 0; } /* int add_ignorelist */ /* @@ -150,7 +151,7 @@ static int check_ignorelist(const char *dev, const char *type, assert((dev != NULL) && (type != NULL)); if (ir_ignorelist_head == NULL) - return (ir_ignorelist_invert ? 0 : 1); + return ir_ignorelist_invert ? 0 : 1; for (ir_ignorelist_t *i = ir_ignorelist_head; i != NULL; i = i->next) { /* i->device == NULL => match all devices */ @@ -171,10 +172,10 @@ static int check_ignorelist(const char *dev, const char *type, i->device == NULL ? "(nil)" : i->device, i->type, i->inst == NULL ? "(nil)" : i->inst); - return (ir_ignorelist_invert ? 0 : 1); + return ir_ignorelist_invert ? 0 : 1; } /* for i */ - return (ir_ignorelist_invert); + return ir_ignorelist_invert; } /* int check_ignorelist */ static void submit_one(const char *dev, const char *type, @@ -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; @@ -221,7 +223,7 @@ static int update_iflist(struct ifinfomsg *msg, const char *dev) { temp = realloc(iflist, (msg->ifi_index + 1) * sizeof(char *)); if (temp == NULL) { ERROR("netlink plugin: update_iflist: realloc failed."); - return (-1); + return -1; } memset(temp + iflist_len, '\0', @@ -235,7 +237,7 @@ static int update_iflist(struct ifinfomsg *msg, const char *dev) { iflist[msg->ifi_index] = strdup(dev); } - return (0); + return 0; } /* int update_iflist */ static void check_ignorelist_and_submit(const char *dev, @@ -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,9 +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) { - ERROR("netlink plugin: link_filter_cb: IFLA_STATS64 mnl_attr_validate2 " - "failed."); + 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); @@ -373,9 +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) { - ERROR("netlink plugin: link_filter_cb: IFLA_STATS mnl_attr_validate2 " - "failed."); + 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); @@ -392,31 +406,30 @@ static int link_filter_cb(const struct nlmsghdr *nlh, #if HAVE_TCA_STATS2 static int qos_attr_cb(const struct nlattr *attr, void *data) { - struct qos_stats *qdisc = (struct qos_stats *)data; - struct gnet_stats_basic *bs = qdisc->bs; - struct gnet_stats_queue *qs = qdisc->qs; + struct qos_stats *q_stats = (struct qos_stats *)data; /* skip unsupported attribute in user-space */ if (mnl_attr_type_valid(attr, TCA_STATS_MAX) < 0) return MNL_CB_OK; if (mnl_attr_get_type(attr) == TCA_STATS_BASIC) { - if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*bs)) < 0) { + if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*q_stats->bs)) < 0) { ERROR("netlink plugin: qos_attr_cb: TCA_STATS_BASIC mnl_attr_validate2 " - "failed."); + "failed: %s", + STRERRNO); return MNL_CB_ERROR; } - bs = mnl_attr_get_payload(attr); + q_stats->bs = mnl_attr_get_payload(attr); return MNL_CB_OK; } if (mnl_attr_get_type(attr) == TCA_STATS_QUEUE) { - if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*qs)) < 0) { + if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*q_stats->qs)) < 0) { ERROR("netlink plugin: qos_attr_cb: TCA_STATS_QUEUE mnl_attr_validate2 " "failed."); return MNL_CB_ERROR; } - qs = mnl_attr_get_payload(attr); + q_stats->qs = mnl_attr_get_payload(attr); return MNL_CB_OK; } @@ -437,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"; @@ -460,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; } @@ -487,7 +500,7 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { if (kind == NULL) { ERROR("netlink plugin: qos_filter_cb: kind == NULL"); - return (-1); + return -1; } { /* The ID */ @@ -509,11 +522,9 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { #if HAVE_TCA_STATS2 mnl_attr_for_each(attr, nlh, sizeof(*tm)) { - struct gnet_stats_basic *bs = NULL; - struct gnet_stats_queue *qs = NULL; struct qos_stats q_stats; - q_stats.bs = bs; - q_stats.qs = qs; + + memset(&q_stats, 0x0, sizeof(q_stats)); if (mnl_attr_get_type(attr) != TCA_STATS2) continue; @@ -526,20 +537,25 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { mnl_attr_parse_nested(attr, qos_attr_cb, &q_stats); - if (bs != NULL || qs != NULL) { + if (q_stats.bs != NULL || q_stats.qs != NULL) { char type_instance[DATA_MAX_NAME_LEN]; - stats_submitted = 1; + stats_submitted = true; - ssnprintf(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 (bs != NULL) { - submit_one(dev, "ipt_bytes", type_instance, bs->bytes); - submit_one(dev, "ipt_packets", type_instance, bs->packets); + if (q_stats.bs != NULL) { + submit_one(dev, "ipt_bytes", type_instance, q_stats.bs->bytes); + submit_one(dev, "ipt_packets", type_instance, q_stats.bs->packets); } - if (qs != NULL) { - submit_one(dev, "if_tx_errors", type_instance, qs->drops); + if (q_stats.qs != NULL) { + submit_one(dev, "if_tx_dropped", type_instance, q_stats.qs->drops); } } @@ -556,7 +572,8 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*ts)) < 0) { ERROR("netlink plugin: qos_filter_cb: TCA_STATS mnl_attr_validate2 " - "failed."); + "failed: %s", + STRERRNO); return MNL_CB_ERROR; } ts = mnl_attr_get_payload(attr); @@ -564,8 +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]; - ssnprintf(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); @@ -592,12 +614,12 @@ static int ir_config(const char *key, const char *value) { new_val = strdup(value); if (new_val == NULL) - return (-1); + return -1; fields_num = strsplit(new_val, fields, STATIC_ARRAY_SIZE(fields)); if ((fields_num < 1) || (fields_num > 8)) { sfree(new_val); - return (-1); + return -1; } if ((strcasecmp(key, "Interface") == 0) || @@ -616,11 +638,11 @@ 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); - return (-1); + return -1; } else { add_ignorelist(fields[0], key, (fields_num == 2) ? fields[1] : NULL); status = 0; @@ -642,22 +664,22 @@ static int ir_config(const char *key, const char *value) { sfree(new_val); - return (status); + return status; } /* int ir_config */ static int ir_init(void) { nl = mnl_socket_open(NETLINK_ROUTE); if (nl == NULL) { ERROR("netlink plugin: ir_init: mnl_socket_open failed."); - return (-1); + return -1; } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { ERROR("netlink plugin: ir_init: mnl_socket_bind failed."); - return (-1); + return -1; } - return (0); + return 0; } /* int ir_init */ static int ir_read(void) { @@ -681,7 +703,7 @@ static int ir_read(void) { if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { ERROR("netlink plugin: ir_read: rtnl_wilddump_request failed."); - return (-1); + return -1; } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); @@ -692,7 +714,7 @@ static int ir_read(void) { ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret < 0) { - ERROR("netlink plugin: ir_read: mnl_socket_recvfrom failed."); + ERROR("netlink plugin: ir_read: mnl_socket_recvfrom failed: %s", STRERRNO); return (-1); } @@ -713,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); @@ -737,14 +759,14 @@ static int ir_read(void) { ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret < 0) { - ERROR("netlink plugin: ir_read:mnl_socket_recvfrom failed."); + ERROR("netlink plugin: ir_read: mnl_socket_recvfrom failed: %s", + STRERRNO); continue; } - } /* for (type_index) */ } /* for (if_index) */ - return (0); + return 0; } /* int ir_read */ static int ir_shutdown(void) { @@ -753,7 +775,7 @@ static int ir_shutdown(void) { nl = NULL; } - return (0); + return 0; } /* int ir_shutdown */ void module_register(void) {