static int c_psql_check_connection (c_psql_database_t *db) { /* "ping" */ PQclear (PQexec (db->conn, "SELECT 42;")); if (CONNECTION_OK != PQstatus (db->conn)) { PQreset (db->conn); /* trigger c_release() */ if (0 == db->conn_complaint.interval) db->conn_complaint.interval = 1; if (CONNECTION_OK != PQstatus (db->conn)) { c_complain (LOG_ERR, &db->conn_complaint, "Failed to connect to database %s: %s", db->database, PQerrorMessage (db->conn)); return -1; } db->proto_version = PQprotocolVersion (db->conn); if (3 > db->proto_version) log_warn ("Protocol version %d does not support parameters.", db->proto_version); } db->server_version = PQserverVersion (db->conn); c_release (LOG_INFO, &db->conn_complaint, "Successfully reconnected to database %s", PQdb (db->conn)); return 0; } /* c_psql_check_connection */
static void ethstat_submit_value(const char *device, const char *type_instance, derive_t value) { static c_complain_t complain_no_map = C_COMPLAIN_INIT_STATIC; value_list_t vl = VALUE_LIST_INIT; value_map_t *map = NULL; if (value_map != NULL) c_avl_get(value_map, type_instance, (void *)&map); /* If the "MappedOnly" option is specified, ignore unmapped values. */ if (collect_mapped_only && (map == NULL)) { if (value_map == NULL) c_complain( LOG_WARNING, &complain_no_map, "ethstat plugin: The \"MappedOnly\" option has been set to true, " "but no mapping has been configured. All values will be ignored!"); return; } vl.values = &(value_t){.derive = value}; vl.values_len = 1; sstrncpy(vl.plugin, "ethstat", sizeof(vl.plugin)); sstrncpy(vl.plugin_instance, device, sizeof(vl.plugin_instance)); if (map != NULL) { sstrncpy(vl.type, map->type, sizeof(vl.type)); sstrncpy(vl.type_instance, map->type_instance, sizeof(vl.type_instance)); } else { sstrncpy(vl.type, "derive", sizeof(vl.type)); sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); } plugin_dispatch_values(&vl); }
static int c_psql_check_connection (c_psql_database_t *db) { _Bool init = 0; if (! db->conn) { init = 1; /* trigger c_release() */ if (0 == db->conn_complaint.interval) db->conn_complaint.interval = 1; c_psql_connect (db); } /* "ping" */ PQclear (PQexec (db->conn, "SELECT 42;")); if (CONNECTION_OK != PQstatus (db->conn)) { PQreset (db->conn); /* trigger c_release() */ if (0 == db->conn_complaint.interval) db->conn_complaint.interval = 1; if (CONNECTION_OK != PQstatus (db->conn)) { c_complain (LOG_ERR, &db->conn_complaint, "Failed to connect to database %s (%s): %s", db->database, db->instance, PQerrorMessage (db->conn)); return -1; } db->proto_version = PQprotocolVersion (db->conn); } db->server_version = PQserverVersion (db->conn); if (c_would_release (&db->conn_complaint)) { char *server_host; int server_version; server_host = PQhost (db->conn); server_version = PQserverVersion (db->conn); c_do_release (LOG_INFO, &db->conn_complaint, "Successfully %sconnected to database %s (user %s) " "at server %s%s%s (server version: %d.%d.%d, " "protocol version: %d, pid: %d)", init ? "" : "re", PQdb (db->conn), PQuser (db->conn), C_PSQL_SOCKET3 (server_host, PQport (db->conn)), C_PSQL_SERVER_VERSION3 (server_version), db->proto_version, PQbackendPID (db->conn)); if (3 > db->proto_version) log_warn ("Protocol version %d does not support parameters.", db->proto_version); } return 0; } /* c_psql_check_connection */
/* host->lock must be held when calling this function. */ static int wrr_connect(struct riemann_host *host) /* {{{ */ { char const *node; int port; if (host->client) return 0; node = (host->node != NULL) ? host->node : RIEMANN_HOST; port = (host->port) ? host->port : RIEMANN_PORT; host->client = NULL; host->client = riemann_client_create( host->client_type, node, port, RIEMANN_CLIENT_OPTION_TLS_CA_FILE, host->tls_ca_file, RIEMANN_CLIENT_OPTION_TLS_CERT_FILE, host->tls_cert_file, RIEMANN_CLIENT_OPTION_TLS_KEY_FILE, host->tls_key_file, RIEMANN_CLIENT_OPTION_NONE); if (host->client == NULL) { c_complain(LOG_ERR, &host->init_complaint, "write_riemann plugin: Unable to connect to Riemann at %s:%d", node, port); return -1; } #if RCC_VERSION_NUMBER >= 0x010800 if (host->timeout.tv_sec != 0) { if (riemann_client_set_timeout(host->client, &host->timeout) != 0) { riemann_client_free(host->client); host->client = NULL; c_complain(LOG_ERR, &host->init_complaint, "write_riemann plugin: Unable to connect to Riemann at %s:%d", node, port); return -1; } } #endif set_sock_opts(riemann_client_get_fd(host->client)); c_release(LOG_INFO, &host->init_complaint, "write_riemann plugin: Successfully connected to %s:%d", node, port); return 0; } /* }}} int wrr_connect */
static int lv_read (void) { time_t t; int i; if (conn == NULL) { /* `conn_string == NULL' is acceptable. */ conn = virConnectOpenReadOnly (conn_string); if (conn == NULL) { c_complain (LOG_ERR, &conn_complain, PLUGIN_NAME " plugin: Unable to connect: " "virConnectOpenReadOnly failed."); return -1; } } c_release (LOG_NOTICE, &conn_complain, PLUGIN_NAME " plugin: Connection established."); time (&t); /* Need to refresh domain or device lists? */ if ((last_refresh == (time_t) 0) || ((interval > 0) && ((last_refresh + interval) <= t))) { if (refresh_lists () != 0) { if (conn != NULL) virConnectClose (conn); conn = NULL; return -1; } last_refresh = t; } #if 0 for (i = 0; i < nr_domains; ++i) fprintf (stderr, "domain %s\n", virDomainGetName (domains[i])); for (i = 0; i < nr_block_devices; ++i) fprintf (stderr, "block device %d %s:%s\n", i, virDomainGetName (block_devices[i].dom), block_devices[i].path); for (i = 0; i < nr_interface_devices; ++i) fprintf (stderr, "interface device %d %s:%s\n", i, virDomainGetName (interface_devices[i].dom), interface_devices[i].path); #endif /* Get CPU usage, memory, VCPU usage for each domain. */ for (i = 0; i < nr_domains; ++i) { virDomainInfo info; virVcpuInfoPtr vinfo = NULL; virDomainMemoryStatPtr minfo = NULL; int status; int j; status = virDomainGetInfo (domains[i], &info); if (status != 0) { ERROR (PLUGIN_NAME " plugin: virDomainGetInfo failed with status %i.", status); continue; } if (info.state != VIR_DOMAIN_RUNNING) { /* only gather stats for running domains */ continue; } cpu_submit (info.cpuTime, domains[i], "virt_cpu_total"); memory_submit ((gauge_t) info.memory * 1024, domains[i]); vinfo = malloc (info.nrVirtCpu * sizeof (vinfo[0])); if (vinfo == NULL) { ERROR (PLUGIN_NAME " plugin: malloc failed."); continue; } status = virDomainGetVcpus (domains[i], vinfo, info.nrVirtCpu, /* cpu map = */ NULL, /* cpu map length = */ 0); if (status < 0) { ERROR (PLUGIN_NAME " plugin: virDomainGetVcpus failed with status %i.", status); sfree (vinfo); continue; } for (j = 0; j < info.nrVirtCpu; ++j) vcpu_submit (vinfo[j].cpuTime, domains[i], vinfo[j].number, "virt_vcpu"); sfree (vinfo); minfo = malloc (VIR_DOMAIN_MEMORY_STAT_NR * sizeof (virDomainMemoryStatStruct)); if (minfo == NULL) { ERROR ("virt plugin: malloc failed."); continue; } status = virDomainMemoryStats (domains[i], minfo, VIR_DOMAIN_MEMORY_STAT_NR, 0); if (status < 0) { ERROR ("virt plugin: virDomainMemoryStats failed with status %i.", status); sfree (minfo); continue; } for (j = 0; j < status; j++) { memory_stats_submit ((gauge_t) minfo[j].val * 1024, domains[i], minfo[j].tag); } sfree (minfo); } /* Get block device stats for each domain. */ for (i = 0; i < nr_block_devices; ++i) { struct _virDomainBlockStats stats; if (virDomainBlockStats (block_devices[i].dom, block_devices[i].path, &stats, sizeof stats) != 0) continue; if ((stats.rd_req != -1) && (stats.wr_req != -1)) submit_derive2 ("disk_ops", (derive_t) stats.rd_req, (derive_t) stats.wr_req, block_devices[i].dom, block_devices[i].path); if ((stats.rd_bytes != -1) && (stats.wr_bytes != -1)) submit_derive2 ("disk_octets", (derive_t) stats.rd_bytes, (derive_t) stats.wr_bytes, block_devices[i].dom, block_devices[i].path); } /* for (nr_block_devices) */ /* Get interface stats for each domain. */ for (i = 0; i < nr_interface_devices; ++i) { struct _virDomainInterfaceStats stats; char *display_name = NULL; switch (interface_format) { case if_address: display_name = interface_devices[i].address; break; case if_number: display_name = interface_devices[i].number; break; case if_name: default: display_name = interface_devices[i].path; } if (virDomainInterfaceStats (interface_devices[i].dom, interface_devices[i].path, &stats, sizeof stats) != 0) continue; if ((stats.rx_bytes != -1) && (stats.tx_bytes != -1)) submit_derive2 ("if_octets", (derive_t) stats.rx_bytes, (derive_t) stats.tx_bytes, interface_devices[i].dom, display_name); if ((stats.rx_packets != -1) && (stats.tx_packets != -1)) submit_derive2 ("if_packets", (derive_t) stats.rx_packets, (derive_t) stats.tx_packets, interface_devices[i].dom, display_name); if ((stats.rx_errs != -1) && (stats.tx_errs != -1)) submit_derive2 ("if_errors", (derive_t) stats.rx_errs, (derive_t) stats.tx_errs, interface_devices[i].dom, display_name); if ((stats.rx_drop != -1) && (stats.tx_drop != -1)) submit_derive2 ("if_dropped", (derive_t) stats.rx_drop, (derive_t) stats.tx_drop, interface_devices[i].dom, display_name); } /* for (nr_interface_devices) */ return 0; }
static int csnmp_read_table (host_definition_t *host, data_definition_t *data) { struct snmp_pdu *req; struct snmp_pdu *res; struct variable_list *vb; const data_set_t *ds; size_t oid_list_len = data->values_len + 1; /* Holds the last OID returned by the device. We use this in the GETNEXT * request to proceed. */ oid_t oid_list[oid_list_len]; /* Set to false when an OID has left its subtree so we don't re-request it * again. */ _Bool oid_list_todo[oid_list_len]; int status; size_t i; /* `value_list_head' and `value_list_tail' implement a linked list for each * value. `instance_list_head' and `instance_list_tail' implement a linked list of * instance names. This is used to jump gaps in the table. */ csnmp_list_instances_t *instance_list_head; csnmp_list_instances_t *instance_list_tail; csnmp_table_values_t **value_list_head; csnmp_table_values_t **value_list_tail; DEBUG ("snmp plugin: csnmp_read_table (host = %s, data = %s)", host->name, data->name); if (host->sess_handle == NULL) { DEBUG ("snmp plugin: csnmp_read_table: host->sess_handle == NULL"); return (-1); } ds = plugin_get_ds (data->type); if (!ds) { ERROR ("snmp plugin: DataSet `%s' not defined.", data->type); return (-1); } if (ds->ds_num != data->values_len) { ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu", data->type, ds->ds_num, data->values_len); return (-1); } assert (data->values_len > 0); /* We need a copy of all the OIDs, because GETNEXT will destroy them. */ memcpy (oid_list, data->values, data->values_len * sizeof (oid_t)); if (data->instance.oid.oid_len > 0) memcpy (oid_list + data->values_len, &data->instance.oid, sizeof (oid_t)); else /* no InstanceFrom option specified. */ oid_list_len--; for (i = 0; i < oid_list_len; i++) oid_list_todo[i] = 1; /* We're going to construct n linked lists, one for each "value". * value_list_head will contain pointers to the heads of these linked lists, * value_list_tail will contain pointers to the tail of the lists. */ value_list_head = calloc (data->values_len, sizeof (*value_list_head)); value_list_tail = calloc (data->values_len, sizeof (*value_list_tail)); if ((value_list_head == NULL) || (value_list_tail == NULL)) { ERROR ("snmp plugin: csnmp_read_table: calloc failed."); sfree (value_list_head); sfree (value_list_tail); return (-1); } instance_list_head = NULL; instance_list_tail = NULL; status = 0; while (status == 0) { int oid_list_todo_num; req = snmp_pdu_create (SNMP_MSG_GETNEXT); if (req == NULL) { ERROR ("snmp plugin: snmp_pdu_create failed."); status = -1; break; } oid_list_todo_num = 0; for (i = 0; i < oid_list_len; i++) { /* Do not rerequest already finished OIDs */ if (!oid_list_todo[i]) continue; oid_list_todo_num++; snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len); } if (oid_list_todo_num == 0) { /* The request is still empty - so we are finished */ DEBUG ("snmp plugin: all variables have left their subtree"); status = 0; break; } res = NULL; status = snmp_sess_synch_response (host->sess_handle, req, &res); if ((status != STAT_SUCCESS) || (res == NULL)) { char *errstr = NULL; snmp_sess_error (host->sess_handle, NULL, NULL, &errstr); c_complain (LOG_ERR, &host->complaint, "snmp plugin: host %s: snmp_sess_synch_response failed: %s", host->name, (errstr == NULL) ? "Unknown problem" : errstr); if (res != NULL) snmp_free_pdu (res); res = NULL; /* snmp_synch_response already freed our PDU */ req = NULL; sfree (errstr); csnmp_host_close_session (host); status = -1; break; } status = 0; assert (res != NULL); c_release (LOG_INFO, &host->complaint, "snmp plugin: host %s: snmp_sess_synch_response successful.", host->name); vb = res->variables; if (vb == NULL) { status = -1; break; } for (vb = res->variables, i = 0; (vb != NULL); vb = vb->next_variable, i++) { /* Calculate value index from todo list */ while ((i < oid_list_len) && !oid_list_todo[i]) i++; /* An instance is configured and the res variable we process is the * instance value (last index) */ if ((data->instance.oid.oid_len > 0) && (i == data->values_len)) { if ((vb->type == SNMP_ENDOFMIBVIEW) || (snmp_oid_ncompare (data->instance.oid.oid, data->instance.oid.oid_len, vb->name, vb->name_length, data->instance.oid.oid_len) != 0)) { DEBUG ("snmp plugin: host = %s; data = %s; Instance left its subtree.", host->name, data->name); oid_list_todo[i] = 0; continue; } /* Allocate a new `csnmp_list_instances_t', insert the instance name and * add it to the list */ if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail, res, host, data) != 0) { ERROR ("snmp plugin: host %s: csnmp_instance_list_add failed.", host->name); status = -1; break; } } else /* The variable we are processing is a normal value */ { csnmp_table_values_t *vt; oid_t vb_name; oid_t suffix; int ret; csnmp_oid_init (&vb_name, vb->name, vb->name_length); /* Calculate the current suffix. This is later used to check that the * suffix is increasing. This also checks if we left the subtree */ ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i); if (ret != 0) { DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; " "Value probably left its subtree.", host->name, data->name, i); oid_list_todo[i] = 0; continue; } /* Make sure the OIDs returned by the agent are increasing. Otherwise our * table matching algorithm will get confused. */ if ((value_list_tail[i] != NULL) && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0)) { DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; " "Suffix is not increasing.", host->name, data->name, i); oid_list_todo[i] = 0; continue; } vt = malloc (sizeof (*vt)); if (vt == NULL) { ERROR ("snmp plugin: malloc failed."); status = -1; break; } memset (vt, 0, sizeof (*vt)); vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type, data->scale, data->shift, host->name, data->name); memcpy (&vt->suffix, &suffix, sizeof (vt->suffix)); vt->next = NULL; if (value_list_tail[i] == NULL) value_list_head[i] = vt; else value_list_tail[i]->next = vt; value_list_tail[i] = vt; } /* Copy OID to oid_list[i] */ memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length); oid_list[i].oid_len = vb->name_length; } /* for (vb = res->variables ...) */ if (res != NULL) snmp_free_pdu (res); res = NULL; } /* while (status == 0) */ if (res != NULL) snmp_free_pdu (res); res = NULL; if (req != NULL) snmp_free_pdu (req); req = NULL; if (status == 0) csnmp_dispatch_table (host, data, instance_list_head, value_list_head); /* Free all allocated variables here */ while (instance_list_head != NULL) { csnmp_list_instances_t *next = instance_list_head->next; sfree (instance_list_head); instance_list_head = next; } for (i = 0; i < data->values_len; i++) { while (value_list_head[i] != NULL) { csnmp_table_values_t *next = value_list_head[i]->next; sfree (value_list_head[i]); value_list_head[i] = next; } } sfree (value_list_head); sfree (value_list_tail); return (0); } /* int csnmp_read_table */
static int csnmp_read_table (host_definition_t *host, data_definition_t *data) { struct snmp_pdu *req; struct snmp_pdu *res; struct variable_list *vb; const data_set_t *ds; oid_t *oid_list; uint32_t oid_list_len; int status; int i; /* `value_table' and `value_table_ptr' implement a linked list for each * value. `instance_list' and `instance_list_ptr' implement a linked list of * instance names. This is used to jump gaps in the table. */ csnmp_list_instances_t *instance_list; csnmp_list_instances_t *instance_list_ptr; csnmp_table_values_t **value_table; csnmp_table_values_t **value_table_ptr; DEBUG ("snmp plugin: csnmp_read_table (host = %s, data = %s)", host->name, data->name); if (host->sess_handle == NULL) { DEBUG ("snmp plugin: csnmp_read_table: host->sess_handle == NULL"); return (-1); } ds = plugin_get_ds (data->type); if (!ds) { ERROR ("snmp plugin: DataSet `%s' not defined.", data->type); return (-1); } if (ds->ds_num != data->values_len) { ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i", data->type, ds->ds_num, data->values_len); return (-1); } /* We need a copy of all the OIDs, because GETNEXT will destroy them. */ oid_list_len = data->values_len + 1; oid_list = (oid_t *) malloc (sizeof (oid_t) * (oid_list_len)); if (oid_list == NULL) { ERROR ("snmp plugin: csnmp_read_table: malloc failed."); return (-1); } memcpy (oid_list, data->values, data->values_len * sizeof (oid_t)); if (data->instance.oid.oid_len > 0) memcpy (oid_list + data->values_len, &data->instance.oid, sizeof (oid_t)); else oid_list_len--; /* Allocate the `value_table' */ value_table = (csnmp_table_values_t **) malloc (sizeof (csnmp_table_values_t *) * 2 * data->values_len); if (value_table == NULL) { ERROR ("snmp plugin: csnmp_read_table: malloc failed."); sfree (oid_list); return (-1); } memset (value_table, '\0', sizeof (csnmp_table_values_t *) * 2 * data->values_len); value_table_ptr = value_table + data->values_len; instance_list = NULL; instance_list_ptr = NULL; status = 0; while (status == 0) { req = snmp_pdu_create (SNMP_MSG_GETNEXT); if (req == NULL) { ERROR ("snmp plugin: snmp_pdu_create failed."); status = -1; break; } for (i = 0; (uint32_t) i < oid_list_len; i++) snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len); res = NULL; status = snmp_sess_synch_response (host->sess_handle, req, &res); if ((status != STAT_SUCCESS) || (res == NULL)) { char *errstr = NULL; snmp_sess_error (host->sess_handle, NULL, NULL, &errstr); c_complain (LOG_ERR, &host->complaint, "snmp plugin: host %s: snmp_sess_synch_response failed: %s", host->name, (errstr == NULL) ? "Unknown problem" : errstr); if (res != NULL) snmp_free_pdu (res); res = NULL; sfree (errstr); csnmp_host_close_session (host); status = -1; break; } status = 0; assert (res != NULL); c_release (LOG_INFO, &host->complaint, "snmp plugin: host %s: snmp_sess_synch_response successful.", host->name); vb = res->variables; if (vb == NULL) { status = -1; break; } /* Check if all values (and possibly the instance) have left their * subtree */ if (csnmp_check_res_left_subtree (host, data, res) != 0) { status = 0; break; } /* if an instance-OID is configured.. */ if (data->instance.oid.oid_len > 0) { /* Allocate a new `csnmp_list_instances_t', insert the instance name and * add it to the list */ if (csnmp_instance_list_add (&instance_list, &instance_list_ptr, res) != 0) { ERROR ("snmp plugin: csnmp_instance_list_add failed."); status = -1; break; } /* Set vb on the last variable */ for (vb = res->variables; (vb != NULL) && (vb->next_variable != NULL); vb = vb->next_variable) /* do nothing */; assert (vb != NULL); /* Copy OID to oid_list[data->values_len] */ memcpy (oid_list[data->values_len].oid, vb->name, sizeof (oid) * vb->name_length); oid_list[data->values_len].oid_len = vb->name_length; } for (vb = res->variables, i = 0; (vb != NULL) && (i < data->values_len); vb = vb->next_variable, i++) { csnmp_table_values_t *vt; /* Check if we left the subtree */ if (snmp_oid_ncompare (data->values[i].oid, data->values[i].oid_len, vb->name, vb->name_length, data->values[i].oid_len) != 0) { DEBUG ("snmp plugin: host = %s; data = %s; Value %i left its subtree.", host->name, data->name, i); continue; } if ((value_table_ptr[i] != NULL) && (vb->name[vb->name_length - 1] <= value_table_ptr[i]->subid)) { DEBUG ("snmp plugin: host = %s; data = %s; i = %i; " "SUBID is not increasing.", host->name, data->name, i); continue; } vt = (csnmp_table_values_t *) malloc (sizeof (csnmp_table_values_t)); if (vt == NULL) { ERROR ("snmp plugin: malloc failed."); status = -1; break; } vt->subid = vb->name[vb->name_length - 1]; vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type, data->scale, data->shift); vt->next = NULL; if (value_table_ptr[i] == NULL) value_table[i] = vt; else value_table_ptr[i]->next = vt; value_table_ptr[i] = vt; /* Copy OID to oid_list[i + 1] */ memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length); oid_list[i].oid_len = vb->name_length; } /* for (i = data->values_len) */ if (res != NULL) snmp_free_pdu (res); res = NULL; } /* while (status == 0) */ if (res != NULL) snmp_free_pdu (res); res = NULL; if (status == 0) csnmp_dispatch_table (host, data, instance_list, value_table); /* Free all allocated variables here */ while (instance_list != NULL) { instance_list_ptr = instance_list->next; sfree (instance_list); instance_list = instance_list_ptr; } for (i = 0; i < data->values_len; i++) { csnmp_table_values_t *tmp; while (value_table[i] != NULL) { tmp = value_table[i]->next; sfree (value_table[i]); value_table[i] = tmp; } } sfree (value_table); sfree (oid_list); return (0); } /* int csnmp_read_table */
static int wg_callback_init (struct wg_callback *cb) { struct addrinfo ai_hints; struct addrinfo *ai_list; struct addrinfo *ai_ptr; cdtime_t now; int status; char connerr[1024] = ""; if (cb->sock_fd > 0) return (0); /* Don't try to reconnect too often. By default, one reconnection attempt * is made per second. */ now = cdtime (); if ((now - cb->last_connect_time) < WG_MIN_RECONNECT_INTERVAL) return (EAGAIN); cb->last_connect_time = now; memset (&ai_hints, 0, sizeof (ai_hints)); #ifdef AI_ADDRCONFIG ai_hints.ai_flags |= AI_ADDRCONFIG; #endif ai_hints.ai_family = AF_UNSPEC; if (0 == strcasecmp ("tcp", cb->protocol)) ai_hints.ai_socktype = SOCK_STREAM; else ai_hints.ai_socktype = SOCK_DGRAM; ai_list = NULL; status = getaddrinfo (cb->node, cb->service, &ai_hints, &ai_list); if (status != 0) { ERROR ("write_graphite plugin: getaddrinfo (%s, %s, %s) failed: %s", cb->node, cb->service, cb->protocol, gai_strerror (status)); return (-1); } assert (ai_list != NULL); for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) { cb->sock_fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol); if (cb->sock_fd < 0) { char errbuf[1024]; snprintf (connerr, sizeof (connerr), "failed to open socket: %s", sstrerror (errno, errbuf, sizeof (errbuf))); continue; } status = connect (cb->sock_fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen); if (status != 0) { char errbuf[1024]; snprintf (connerr, sizeof (connerr), "failed to connect to remote " "host: %s", sstrerror (errno, errbuf, sizeof (errbuf))); close (cb->sock_fd); cb->sock_fd = -1; continue; } break; } freeaddrinfo (ai_list); if (cb->sock_fd < 0) { if (connerr[0] == '\0') /* this should not happen but try to get a message anyway */ sstrerror (errno, connerr, sizeof (connerr)); c_complain (LOG_ERR, &cb->init_complaint, "write_graphite plugin: Connecting to %s:%s via %s failed. " "The last error was: %s", cb->node, cb->service, cb->protocol, connerr); return (-1); } else { c_release (LOG_INFO, &cb->init_complaint, "write_graphite plugin: Successfully connected to %s:%s via %s.", cb->node, cb->service, cb->protocol); } /* wg_force_reconnect_check does not flush the buffer before closing a * sending socket, so only call wg_reset_buffer() if the socket was closed * for a different reason (tracked in cb->reconnect_interval_reached). */ if (!cb->reconnect_interval_reached || (cb->send_buf_free == 0)) wg_reset_buffer (cb); else cb->reconnect_interval_reached = 0; return (0); }
static int lv_read (void) { time_t t; int i; if (conn == NULL) { /* `conn_string == NULL' is acceptable. */ conn = virConnectOpenReadOnly (conn_string); if (conn == NULL) { c_complain (LOG_ERR, &conn_complain, "libvirt plugin: Unable to connect: " "virConnectOpenReadOnly failed."); return -1; } } c_release (LOG_NOTICE, &conn_complain, "libvirt plugin: Connection established."); time (&t); /* Need to refresh domain or device lists? */ if ((last_refresh == (time_t) 0) || ((interval > 0) && ((last_refresh + interval) <= t))) { if (refresh_lists () != 0) { if (conn != NULL) virConnectClose (conn); conn = NULL; return -1; } last_refresh = t; } #if 0 for (i = 0; i < nr_domains; ++i) fprintf (stderr, "domain %s\n", virDomainGetName (domains[i])); for (i = 0; i < nr_block_devices; ++i) fprintf (stderr, "block device %d %s:%s\n", i, virDomainGetName (block_devices[i].dom), block_devices[i].path); for (i = 0; i < nr_interface_devices; ++i) fprintf (stderr, "interface device %d %s:%s\n", i, virDomainGetName (interface_devices[i].dom), interface_devices[i].path); #endif /* Get CPU usage, VCPU usage for each domain. */ for (i = 0; i < nr_domains; ++i) { virDomainInfo info; virVcpuInfoPtr vinfo = NULL; int j; if (virDomainGetInfo (domains[i], &info) != 0) continue; cpu_submit (info.cpuTime, domains[i], "virt_cpu_total"); vinfo = malloc (info.nrVirtCpu * sizeof vinfo[0]); if (vinfo == NULL) { ERROR ("libvirt plugin: malloc failed."); continue; } if (virDomainGetVcpus (domains[i], vinfo, info.nrVirtCpu, NULL, 0) != 0) { sfree (vinfo); continue; } for (j = 0; j < info.nrVirtCpu; ++j) vcpu_submit (vinfo[j].cpuTime, domains[i], vinfo[j].number, "virt_vcpu"); sfree (vinfo); } /* Get block device stats for each domain. */ for (i = 0; i < nr_block_devices; ++i) { struct _virDomainBlockStats stats; if (virDomainBlockStats (block_devices[i].dom, block_devices[i].path, &stats, sizeof stats) != 0) continue; if ((stats.rd_req != -1) && (stats.wr_req != -1)) submit_derive2 ("disk_ops", (derive_t) stats.rd_req, (derive_t) stats.wr_req, block_devices[i].dom, block_devices[i].path); if ((stats.rd_bytes != -1) && (stats.wr_bytes != -1)) submit_derive2 ("disk_octets", (derive_t) stats.rd_bytes, (derive_t) stats.wr_bytes, block_devices[i].dom, block_devices[i].path); } /* for (nr_block_devices) */ /* Get interface stats for each domain. */ for (i = 0; i < nr_interface_devices; ++i) { struct _virDomainInterfaceStats stats; char *display_name = interface_devices[i].path; if (interface_format == if_address) display_name = interface_devices[i].address; if (virDomainInterfaceStats (interface_devices[i].dom, interface_devices[i].path, &stats, sizeof stats) != 0) continue; if ((stats.rx_bytes != -1) && (stats.tx_bytes != -1)) submit_derive2 ("if_octets", (derive_t) stats.rx_bytes, (derive_t) stats.tx_bytes, interface_devices[i].dom, display_name); if ((stats.rx_packets != -1) && (stats.tx_packets != -1)) submit_derive2 ("if_packets", (derive_t) stats.rx_packets, (derive_t) stats.tx_packets, interface_devices[i].dom, display_name); if ((stats.rx_errs != -1) && (stats.tx_errs != -1)) submit_derive2 ("if_errors", (derive_t) stats.rx_errs, (derive_t) stats.tx_errs, interface_devices[i].dom, display_name); if ((stats.rx_drop != -1) && (stats.tx_drop != -1)) submit_derive2 ("if_dropped", (derive_t) stats.rx_drop, (derive_t) stats.tx_drop, interface_devices[i].dom, display_name); } /* for (nr_interface_devices) */ return 0; }
static void *ping_thread (void *arg) /* {{{ */ { static pingobj_t *pingobj = NULL; struct timeval tv_begin; struct timeval tv_end; struct timespec ts_wait; struct timespec ts_int; hostlist_t *hl; int count; c_complain_t complaint = C_COMPLAIN_INIT_STATIC; pthread_mutex_lock (&ping_lock); pingobj = ping_construct (); if (pingobj == NULL) { ERROR ("ping plugin: ping_construct failed."); ping_thread_error = 1; pthread_mutex_unlock (&ping_lock); return ((void *) -1); } if (ping_source != NULL) if (ping_setopt (pingobj, PING_OPT_SOURCE, (void *) ping_source) != 0) ERROR ("ping plugin: Failed to set source address: %s", ping_get_error (pingobj)); #ifdef HAVE_OPING_1_3 if (ping_device != NULL) if (ping_setopt (pingobj, PING_OPT_DEVICE, (void *) ping_device) != 0) ERROR ("ping plugin: Failed to set device: %s", ping_get_error (pingobj)); #endif ping_setopt (pingobj, PING_OPT_TIMEOUT, (void *) &ping_timeout); ping_setopt (pingobj, PING_OPT_TTL, (void *) &ping_ttl); if (ping_data != NULL) ping_setopt (pingobj, PING_OPT_DATA, (void *) ping_data); /* Add all the hosts to the ping object. */ count = 0; for (hl = hostlist_head; hl != NULL; hl = hl->next) { int tmp_status; tmp_status = ping_host_add (pingobj, hl->host); if (tmp_status != 0) WARNING ("ping plugin: ping_host_add (%s) failed: %s", hl->host, ping_get_error (pingobj)); else count++; } if (count == 0) { ERROR ("ping plugin: No host could be added to ping object. Giving up."); ping_thread_error = 1; pthread_mutex_unlock (&ping_lock); return ((void *) -1); } /* Set up `ts_int' */ { double temp_sec; double temp_nsec; temp_nsec = modf (ping_interval, &temp_sec); ts_int.tv_sec = (time_t) temp_sec; ts_int.tv_nsec = (long) (temp_nsec * 1000000000L); } while (ping_thread_loop > 0) { int status; _Bool send_successful = 0; if (gettimeofday (&tv_begin, NULL) < 0) { char errbuf[1024]; ERROR ("ping plugin: gettimeofday failed: %s", sstrerror (errno, errbuf, sizeof (errbuf))); ping_thread_error = 1; break; } pthread_mutex_unlock (&ping_lock); status = ping_send (pingobj); if (status < 0) { c_complain (LOG_ERR, &complaint, "ping plugin: ping_send failed: %s", ping_get_error (pingobj)); } else { c_release (LOG_NOTICE, &complaint, "ping plugin: ping_send succeeded."); send_successful = 1; } pthread_mutex_lock (&ping_lock); if (ping_thread_loop <= 0) break; if (send_successful) (void) ping_dispatch_all (pingobj); if (gettimeofday (&tv_end, NULL) < 0) { char errbuf[1024]; ERROR ("ping plugin: gettimeofday failed: %s", sstrerror (errno, errbuf, sizeof (errbuf))); ping_thread_error = 1; break; } /* Calculate the absolute time until which to wait and store it in * `ts_wait'. */ time_calc (&ts_wait, &ts_int, &tv_begin, &tv_end); pthread_cond_timedwait (&ping_cond, &ping_lock, &ts_wait); if (ping_thread_loop <= 0) break; } /* while (ping_thread_loop > 0) */ pthread_mutex_unlock (&ping_lock); ping_destroy (pingobj); return ((void *) 0); } /* }}} void *ping_thread */
static int csnmp_read_table (host_definition_t *host, data_definition_t *data) { struct snmp_pdu *req; struct snmp_pdu *res; struct variable_list *vb; const data_set_t *ds; oid_t *oid_list; uint32_t oid_list_len; int status; int i; /* `value_list_head' and `value_list_tail' implement a linked list for each * value. `instance_list_head' and `instance_list_tail' implement a linked list of * instance names. This is used to jump gaps in the table. */ csnmp_list_instances_t *instance_list_head; csnmp_list_instances_t *instance_list_tail; csnmp_table_values_t **value_list_head; csnmp_table_values_t **value_list_tail; DEBUG ("snmp plugin: csnmp_read_table (host = %s, data = %s)", host->name, data->name); if (host->sess_handle == NULL) { DEBUG ("snmp plugin: csnmp_read_table: host->sess_handle == NULL"); return (-1); } ds = plugin_get_ds (data->type); if (!ds) { ERROR ("snmp plugin: DataSet `%s' not defined.", data->type); return (-1); } if (ds->ds_num != data->values_len) { ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i", data->type, ds->ds_num, data->values_len); return (-1); } /* We need a copy of all the OIDs, because GETNEXT will destroy them. */ oid_list_len = data->values_len + 1; oid_list = (oid_t *) malloc (sizeof (oid_t) * (oid_list_len)); if (oid_list == NULL) { ERROR ("snmp plugin: csnmp_read_table: malloc failed."); return (-1); } memcpy (oid_list, data->values, data->values_len * sizeof (oid_t)); if (data->instance.oid.oid_len > 0) memcpy (oid_list + data->values_len, &data->instance.oid, sizeof (oid_t)); else oid_list_len--; /* We're going to construct n linked lists, one for each "value". * value_list_head will contain pointers to the heads of these linked lists, * value_list_tail will contain pointers to the tail of the lists. */ value_list_head = calloc (data->values_len, sizeof (*value_list_head)); value_list_tail = calloc (data->values_len, sizeof (*value_list_tail)); if ((value_list_head == NULL) || (value_list_tail == NULL)) { ERROR ("snmp plugin: csnmp_read_table: calloc failed."); sfree (oid_list); sfree (value_list_head); sfree (value_list_tail); return (-1); } instance_list_head = NULL; instance_list_tail = NULL; status = 0; while (status == 0) { req = snmp_pdu_create (SNMP_MSG_GETNEXT); if (req == NULL) { ERROR ("snmp plugin: snmp_pdu_create failed."); status = -1; break; } for (i = 0; (uint32_t) i < oid_list_len; i++) snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len); res = NULL; status = snmp_sess_synch_response (host->sess_handle, req, &res); if ((status != STAT_SUCCESS) || (res == NULL)) { char *errstr = NULL; snmp_sess_error (host->sess_handle, NULL, NULL, &errstr); c_complain (LOG_ERR, &host->complaint, "snmp plugin: host %s: snmp_sess_synch_response failed: %s", host->name, (errstr == NULL) ? "Unknown problem" : errstr); if (res != NULL) snmp_free_pdu (res); res = NULL; sfree (errstr); csnmp_host_close_session (host); status = -1; break; } status = 0; assert (res != NULL); c_release (LOG_INFO, &host->complaint, "snmp plugin: host %s: snmp_sess_synch_response successful.", host->name); vb = res->variables; if (vb == NULL) { status = -1; break; } /* Check if all values (and possibly the instance) have left their * subtree */ if (csnmp_check_res_left_subtree (host, data, res) != 0) { status = 0; break; } /* Copy the OID of the value used as instance to oid_list, if an instance * is configured. */ if (data->instance.oid.oid_len > 0) { /* Allocate a new `csnmp_list_instances_t', insert the instance name and * add it to the list */ if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail, res, host, data) != 0) { ERROR ("snmp plugin: csnmp_instance_list_add failed."); status = -1; break; } /* The instance OID is added to the list of OIDs to GET from the * snmp agent last, so set vb on the last variable returned and copy * that OID. */ for (vb = res->variables; (vb != NULL) && (vb->next_variable != NULL); vb = vb->next_variable) /* do nothing */; assert (vb != NULL); /* Copy the OID of the instance value to oid_list[data->values_len]. * "oid_list" is used for the next GETNEXT request. */ memcpy (oid_list[data->values_len].oid, vb->name, sizeof (oid) * vb->name_length); oid_list[data->values_len].oid_len = vb->name_length; } /* Iterate over all the (non-instance) values returned by the agent. The * (i < value_len) check will make sure we're not handling the instance OID * twice. */ for (vb = res->variables, i = 0; (vb != NULL) && (i < data->values_len); vb = vb->next_variable, i++) { csnmp_table_values_t *vt; oid_t vb_name; oid_t suffix; csnmp_oid_init (&vb_name, vb->name, vb->name_length); /* Calculate the current suffix. This is later used to check that the * suffix is increasing. This also checks if we left the subtree */ status = csnmp_oid_suffix (&suffix, &vb_name, data->values + i); if (status != 0) { DEBUG ("snmp plugin: host = %s; data = %s; Value %i failed. " "It probably left its subtree.", host->name, data->name, i); continue; } /* Make sure the OIDs returned by the agent are increasing. Otherwise our * table matching algorithm will get confused. */ if ((value_list_tail[i] != NULL) && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0)) { DEBUG ("snmp plugin: host = %s; data = %s; i = %i; " "Suffix is not increasing.", host->name, data->name, i); continue; } vt = malloc (sizeof (*vt)); if (vt == NULL) { ERROR ("snmp plugin: malloc failed."); status = -1; break; } memset (vt, 0, sizeof (*vt)); vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type, data->scale, data->shift, host->name, data->name); memcpy (&vt->suffix, &suffix, sizeof (vt->suffix)); vt->next = NULL; if (value_list_tail[i] == NULL) value_list_head[i] = vt; else value_list_tail[i]->next = vt; value_list_tail[i] = vt; /* Copy OID to oid_list[i + 1] */ memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length); oid_list[i].oid_len = vb->name_length; } /* for (i = data->values_len) */ if (res != NULL) snmp_free_pdu (res); res = NULL; } /* while (status == 0) */ if (res != NULL) snmp_free_pdu (res); res = NULL; if (status == 0) csnmp_dispatch_table (host, data, instance_list_head, value_list_head); /* Free all allocated variables here */ while (instance_list_head != NULL) { csnmp_list_instances_t *next = instance_list_head->next; sfree (instance_list_head); instance_list_head = next; } for (i = 0; i < data->values_len; i++) { while (value_list_head[i] != NULL) { csnmp_table_values_t *next = value_list_head[i]->next; sfree (value_list_head[i]); value_list_head[i] = next; } } sfree (value_list_head); sfree (value_list_tail); sfree (oid_list); return (0); } /* int csnmp_read_table */