diff --git a/src/ping.c b/src/ping.c
index c97571b85c066c695fd66369269b6035bba00097..7b28ed37d0c409733b22df09a51e587149f4068d 100644 (file)
--- a/src/ping.c
+++ b/src/ping.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "configfile.h"
#include "utils_complain.h"
-#include <pthread.h>
#include <netinet/in.h>
#if HAVE_NETDB_H
# include <netdb.h> /* NI_MAXHOST */
#endif
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
+
#include <oping.h>
#ifndef NI_MAXHOST
#ifdef HAVE_OPING_1_3
static char *ping_device = NULL;
#endif
+static char *ping_data = NULL;
static int ping_ttl = PING_DEF_TTL;
static double ping_interval = 1.0;
static double ping_timeout = 0.9;
#ifdef HAVE_OPING_1_3
"Device",
#endif
+ "Size",
"TTL",
"Interval",
"Timeout",
static int ping_dispatch_all (pingobj_t *pingobj) /* {{{ */
{
- pingobj_iter_t *iter;
hostlist_t *hl;
int status;
- for (iter = ping_iterator_get (pingobj);
+ for (pingobj_iter_t *iter = ping_iterator_get (pingobj);
iter != NULL;
iter = ping_iterator_next (iter))
{ /* {{{ */
hl->pkg_missed++;
/* if the host did not answer our last N packages, trigger a resolv. */
- if (ping_max_missed >= 0 && hl->pkg_missed >= ping_max_missed)
+ if ((ping_max_missed >= 0)
+ && (hl->pkg_missed >= ((uint32_t) ping_max_missed)))
{ /* {{{ */
/* we reset the missed package counter here, since we only want to
* trigger a resolv every N packages and not every package _AFTER_ N
struct timespec ts_wait;
struct timespec ts_int;
- hostlist_t *hl;
int count;
c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
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)
+ for (hostlist_t *hl = hostlist_head; hl != NULL; hl = hl->next)
{
int tmp_status;
tmp_status = ping_host_add (pingobj, hl->host);
if (ping_thread_loop != 0)
{
pthread_mutex_unlock (&ping_lock);
- return (-1);
+ return (0);
}
ping_thread_loop = 1;
pthread_mutex_unlock (&ping_lock);
return (-1);
}
-
+
pthread_mutex_unlock (&ping_lock);
return (0);
} /* }}} int start_thread */
"Will use a timeout of %gs.", ping_timeout);
}
- if (start_thread () != 0)
- return (-1);
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_NET_RAW)
+ if (check_capability (CAP_NET_RAW) != 0)
+ {
+ if (getuid () == 0)
+ WARNING ("ping plugin: Running collectd as root, but the CAP_NET_RAW "
+ "capability is missing. The plugin's read function will probably "
+ "fail. Is your init system dropping capabilities ?");
+ else
+ WARNING ("ping plugin: collectd doesn't have the CAP_NET_RAW capability. "
+ "If you don't want to run collectd as root, try running \"setcap "
+ "cap_net_raw=ep\" on the collectd binary.");
+ }
+#endif
- return (0);
+ return (start_thread ());
} /* }}} int ping_init */
static int config_set_string (const char *name, /* {{{ */
hostlist_t *hl;
char *host;
- hl = (hostlist_t *) malloc (sizeof (hostlist_t));
+ hl = malloc (sizeof (*hl));
if (hl == NULL)
{
char errbuf[1024];
WARNING ("ping plugin: Ignoring invalid interval %g (%s)",
tmp, value);
}
+ else if (strcasecmp (key, "Size") == 0) {
+ size_t size = (size_t) atoi (value);
+
+ /* Max IP packet size - (IPv6 + ICMP) = 65535 - (40 + 8) = 65487 */
+ if (size <= 65487)
+ {
+ sfree (ping_data);
+ ping_data = malloc (size + 1);
+ if (ping_data == NULL)
+ {
+ ERROR ("ping plugin: malloc failed.");
+ return (1);
+ }
+
+ /* Note: By default oping is using constant string
+ * "liboping -- ICMP ping library <http://octo.it/liboping/>"
+ * which is exactly 56 bytes.
+ *
+ * Optimally we would follow the ping(1) behaviour, but we
+ * cannot use byte 00 or start data payload at exactly same
+ * location, due to oping library limitations. */
+ for (size_t i = 0; i < size; i++) /* {{{ */
+ {
+ /* This restricts data pattern to be only composed of easily
+ * printable characters, and not NUL character. */
+ ping_data[i] = ('0' + i % 64);
+ } /* }}} for (i = 0; i < size; i++) */
+ ping_data[size] = 0;
+ } else
+ WARNING ("ping plugin: Ignoring invalid Size %zu.", size);
+ }
else if (strcasecmp (key, "Timeout") == 0)
{
double tmp;
static int ping_read (void) /* {{{ */
{
- hostlist_t *hl;
-
if (ping_thread_error != 0)
{
ERROR ("ping plugin: The ping thread had a problem. Restarting it.");
stop_thread ();
- for (hl = hostlist_head; hl != NULL; hl = hl->next)
+ for (hostlist_t *hl = hostlist_head; hl != NULL; hl = hl->next)
{
hl->pkg_sent = 0;
hl->pkg_recv = 0;
return (-1);
} /* if (ping_thread_error != 0) */
- for (hl = hostlist_head; hl != NULL; hl = hl->next) /* {{{ */
+ for (hostlist_t *hl = hostlist_head; hl != NULL; hl = hl->next) /* {{{ */
{
uint32_t pkg_sent;
uint32_t pkg_recv;
hl = hl_next;
}
+ if (ping_data != NULL) {
+ free (ping_data);
+ ping_data = NULL;
+ }
+
return (0);
} /* }}} int ping_shutdown */