From 31c1bf4fa3c1c5f4add94cebe7eeaf2ffbab63bb Mon Sep 17 00:00:00 2001 From: Doug MacEachern Date: Sat, 20 Dec 2008 17:08:39 -0800 Subject: [PATCH] openvpn plugin: Add a plugin to read OpenVPN statistics. Simple but useful module for monitoring per-client openvpn traffic.. The plugin reads a statistics file maintained by OpenVPN. The location of the statistics file is configurable. Signed-off-by: Doug MacEachern Signed-off-by: Florian Forster --- README | 4 ++ configure.in | 2 + src/Makefile.am | 9 ++++ src/collectd.conf.in | 1 + src/openvpn.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 152 insertions(+) create mode 100644 src/openvpn.c diff --git a/README b/README index 5c9eed03..9b06f642 100644 --- a/README +++ b/README @@ -146,6 +146,10 @@ Features Read onewire sensors using the owcapu library of the owfs project. Please read in collectd.conf(5) why this plugin is experimental. + - openvpn + RX and TX of each client in openvpn-status.log (status-version 2). + + - perl The perl plugin implements a Perl-interpreter into collectd. You can write your own plugins in Perl and return arbitrary values using this diff --git a/configure.in b/configure.in index 6b8571d3..55ce936b 100644 --- a/configure.in +++ b/configure.in @@ -3008,6 +3008,7 @@ AC_PLUGIN([notify_email], [$with_libesmtp], [Email notifier]) AC_PLUGIN([ntpd], [yes], [NTPd statistics]) AC_PLUGIN([nut], [$with_libupsclient], [Network UPS tools statistics]) AC_PLUGIN([onewire], [$with_libowcapi], [OneWire sensor statistics]) +AC_PLUGIN([openvpn], [yes], [OpenVPN client statistics]) AC_PLUGIN([oracle], [$with_oracle], [Oracle plugin]) AC_PLUGIN([perl], [$plugin_perl], [Embed a Perl interpreter]) AC_PLUGIN([ping], [$with_liboping], [Network latency statistics]) @@ -3188,6 +3189,7 @@ Configuration: ntpd . . . . . . . . $enable_ntpd nut . . . . . . . . . $enable_nut onewire . . . . . . . $enable_onewire + openvpn . . . . . . . $enable_openvpn oracle . . . . . . . $enable_oracle perl . . . . . . . . $enable_perl ping . . . . . . . . $enable_ping diff --git a/src/Makefile.am b/src/Makefile.am index f5776d5e..892ddea1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -570,6 +570,15 @@ collectd_LDADD += "-dlopen" onewire.la collectd_DEPENDENCIES += onewire.la endif +if BUILD_PLUGIN_OPENVPN +pkglib_LTLIBRARIES += openvpn.la +openvpn_la_SOURCES = openvpn.c +openvpn_la_CFLAGS = $(AM_CFLAGS) +openvpn_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" openvpn.la +collectd_DEPENDENCIES += openvpn.la +endif + if BUILD_PLUGIN_ORACLE pkglib_LTLIBRARIES += oracle.la oracle_la_SOURCES = oracle.c diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 01017e3e..0c27edcf 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -64,6 +64,7 @@ FQDNLookup true @BUILD_PLUGIN_NTPD_TRUE@LoadPlugin ntpd @BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut @BUILD_PLUGIN_ONEWIRE_TRUE@LoadPlugin onewire +@BUILD_PLUGIN_OPENVPN_TRUE@LoadPlugin openvpn @BUILD_PLUGIN_PERL_TRUE@LoadPlugin perl @BUILD_PLUGIN_PING_TRUE@LoadPlugin ping @BUILD_PLUGIN_POSTGRESQL_TRUE@LoadPlugin postgresql diff --git a/src/openvpn.c b/src/openvpn.c new file mode 100644 index 00000000..16d4502f --- /dev/null +++ b/src/openvpn.c @@ -0,0 +1,136 @@ +/** + * collectd - src/openvpn.c + * Copyright (C) 2008 Doug MacEachern + * Copyright (C) 2008 Florian octo Forster + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; only version 2 of the License is applicable. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Doug MacEachern + * Florian octo Forster + **/ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" + +static char *status_file = "/etc/openvpn/openvpn-status.log"; + +static const char *config_keys[] = +{ + "StatusFile" +}; +static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); + +/* copy-n-pasted from common.c - changed delim to "," */ +static int openvpn_strsplit (char *string, char **fields, size_t size) +{ + size_t i; + char *ptr; + char *saveptr; + + i = 0; + ptr = string; + saveptr = NULL; + while ((fields[i] = strtok_r (ptr, ",", &saveptr)) != NULL) + { + ptr = NULL; + i++; + + if (i >= size) + break; + } + + return (i); +} /* int openvpn_strsplit */ + +static void openvpn_submit (char *name, counter_t rx, counter_t tx) +{ + value_t values[2]; + value_list_t vl = VALUE_LIST_INIT; + + values[0].counter = rx; + values[1].counter = tx; + + vl.values = values; + vl.values_len = STATIC_ARRAY_SIZE (values); + vl.time = time (NULL); + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "openvpn", sizeof (vl.plugin)); + sstrncpy (vl.type_instance, name, sizeof (vl.type_instance)); + sstrncpy (vl.type, "if_octets", sizeof (vl.type)); + + plugin_dispatch_values (&vl); +} /* void openvpn_submit */ + +static int openvpn_read (void) +{ + char *name; + counter_t rx, tx; + FILE *fh; + char buffer[1024]; + char *fields[8]; + const int max_fields = sizeof(fields)/sizeof(fields[0]); + int fields_num; + static const char *prefix = "CLIENT_LIST,"; + + fh = fopen (status_file, "r"); + if (fh == NULL) + return (-1); + + /* status file is generated by openvpn/multi.c:multi_print_status() + * this plugin requires server.conf: "status-version 2" + * http://svn.openvpn.net/projects/openvpn/trunk/openvpn/multi.c + */ + while (fgets (buffer, sizeof (buffer), fh) != NULL) + { + if (strncmp(buffer, prefix, strlen(prefix)) != 0) + { + continue; + } + + fields_num = openvpn_strsplit (buffer, fields, max_fields); + if (fields_num != max_fields) + { + continue; + } + name = fields[1]; /* "Common Name" */ + rx = atoll (fields[4]); /* "Bytes Received */ + tx = atoll (fields[5]); /* "Bytes Sent" */ + openvpn_submit (name, rx, tx); + } + fclose (fh); + + return (0); +} /* int openvpn_read */ + +static int openvpn_config (const char *key, const char *value) +{ + if (strcasecmp ("StatusFile", key) == 0) + { + status_file = strdup(value); + } + else + { + return (-1); + } + return (0); +} /* int openvpn_config */ + +void module_register (void) +{ + plugin_register_config ("openvpn", openvpn_config, + config_keys, config_keys_num); + plugin_register_read ("openvpn", openvpn_read); +} /* void module_register */ -- 2.11.0