author | Florian Forster <octo@leeloo.lan.home.verplant.org> | |
Sat, 11 Apr 2009 07:37:30 +0000 (09:37 +0200) | ||
committer | Florian Forster <octo@leeloo.lan.home.verplant.org> | |
Sat, 11 Apr 2009 07:37:30 +0000 (09:37 +0200) |
1 | 2 | |||
---|---|---|---|---|
configure.in | patch | | diff1 | | diff2 | | blob | history |
src/exec.c | patch | | diff1 | | diff2 | | blob | history |
src/network.c | patch | | diff1 | | diff2 | | blob | history |
diff --combined configure.in
index 3540a3e2b18c1305a8b5dd395bd81ef3487377f4,2344cdb57e65b8bb09970a873f754a096bfb2ae5..f0c43121990012b19cae6be48cd5bac488b2b650
--- 1/configure.in
--- 2/configure.in
+++ b/configure.in
AM_CONDITIONAL(BUILD_WITH_LIBESMTP, test "x$with_libesmtp" = "xyes")
# }}}
+# --with-libganglia {{{
+AC_ARG_WITH(libganglia, [AS_HELP_STRING([--with-libganglia@<:@=PREFIX@:>@], [Path to libganglia.])],
+[
+ if test -f "$withval" && test -x "$withval"
+ then
+ with_libganglia_config="$withval"
+ with_libganglia="yes"
+ else if test -f "$withval/bin/ganglia-config" && test -x "$withval/bin/ganglia-config"
+ then
+ with_libganglia_config="$withval/bin/ganglia-config"
+ with_libganglia="yes"
+ else if test -d "$withval"
+ then
+ GANGLIA_CPPFLAGS="-I$withval/include"
+ GANGLIA_LDFLAGS="-L$withval/lib"
+ with_libganglia="yes"
+ else
+ with_libganglia_config="ganglia-config"
+ with_libganglia="$withval"
+ fi; fi; fi
+],
+[
+ with_libganglia_config="ganglia-config"
+ with_libganglia="yes"
+])
+
+if test "x$with_libganglia" = "xyes" && test "x$with_libganglia_config" != "x"
+then
+ if test "x$GANGLIA_CPPFLAGS" = "x"
+ then
+ GANGLIA_CPPFLAGS=`"$with_libganglia_config" --cflags 2>/dev/null`
+ fi
+
+ if test "x$GANGLIA_LDFLAGS" = "x"
+ then
+ GANGLIA_LDFLAGS=`"$with_libganglia_config" --ldflags 2>/dev/null`
+ fi
+
+ if test "x$GANGLIA_LIBS" = "x"
+ then
+ GANGLIA_LIBS=`"$with_libganglia_config" --libs 2>/dev/null`
+ fi
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $GANGLIA_CPPFLAGS"
+LDFLAGS="$LDFLAGS $GANGLIA_LDFLAGS"
+
+if test "x$with_libganglia" = "xyes"
+then
+ AC_CHECK_HEADERS(gm_protocol.h,
+ [
+ AC_DEFINE(HAVE_GM_PROTOCOL_H, 1,
+ [Define to 1 if you have the <gm_protocol.h> header file.])
+ ], [with_libganglia="no (gm_protocol.h not found)"])
+fi
+
+if test "x$with_libganglia" = "xyes"
+then
+ AC_CHECK_LIB(ganglia, xdr_Ganglia_value_msg,
+ [
+ AC_DEFINE(HAVE_LIBGANGLIA, 1,
+ [Define to 1 if you have the ganglia library (-lganglia).])
+ ], [with_libganglia="no (symbol xdr_Ganglia_value_msg not found)"])
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+AC_SUBST(GANGLIA_CPPFLAGS)
+AC_SUBST(GANGLIA_LDFLAGS)
+AC_SUBST(GANGLIA_LIBS)
+AM_CONDITIONAL(BUILD_WITH_LIBGANGLIA, test "x$with_libganglia" = "xyes")
+# }}}
+
+# --with-libgcrypt {{{
+GCRYPT_CPPFLAGS="$GCRYPT_CPPFLAGS"
+GCRYPT_LDFLAGS="$GCRYPT_LDFLAGS"
+GCRYPT_LIBS="$GCRYPT_LIBS"
+AC_ARG_WITH(libgcrypt, [AS_HELP_STRING([--with-libgcrypt@<:@=PREFIX@:>@], [Path to libgcrypt.])],
+[
+ if test -f "$withval" && test -x "$withval"
+ then
+ with_libgcrypt_config="$withval"
+ with_libgcrypt="yes"
+ else if test -f "$withval/bin/gcrypt-config" && test -x "$withval/bin/gcrypt-config"
+ then
+ with_libgcrypt_config="$withval/bin/gcrypt-config"
+ with_libgcrypt="yes"
+ else if test -d "$withval"
+ then
+ GCRYPT_CPPFLAGS="$GCRYPT_CPPFLAGS -I$withval/include"
+ GCRYPT_LDFLAGS="$GCRYPT_LDFLAGS -L$withval/lib"
+ with_libgcrypt="yes"
+ else
+ with_libgcrypt_config="gcrypt-config"
+ with_libgcrypt="$withval"
+ fi; fi; fi
+],
+[
+ with_libgcrypt_config="libgcrypt-config"
+ with_libgcrypt="yes"
+])
+
+if test "x$with_libgcrypt" = "xyes" && test "x$with_libgcrypt_config" != "x"
+then
+ if test "x$GCRYPT_CPPFLAGS" = "x"
+ then
+ GCRYPT_CPPFLAGS=`"$with_libgcrypt_config" --cflags 2>/dev/null`
+ fi
+
+ if test "x$GCRYPT_LDFLAGS" = "x"
+ then
+ gcrypt_exec_prefix=`"$with_libgcrypt_config" --exec-prefix 2>/dev/null`
+ GCRYPT_LDFLAGS="-L$gcrypt_exec_prefix/lib"
+ fi
+
+ if test "x$GCRYPT_LIBS" = "x"
+ then
+ GCRYPT_LIBS=`"$with_libgcrypt_config" --libs 2>/dev/null`
+ fi
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $GCRYPT_CPPFLAGS"
+LDFLAGS="$LDFLAGS $GCRYPT_LDFLAGS"
+
+if test "x$with_libgcrypt" = "xyes"
+then
+ if test "x$GCRYPT_CPPFLAGS" != "x"
+ then
+ AC_MSG_NOTICE([gcrypt CPPFLAGS: $GCRYPT_CPPFLAGS])
+ fi
+ AC_CHECK_HEADERS(gcrypt.h,
+ [with_libgcrypt="yes"],
+ [with_libgcrypt="no (gcrypt.h not found)"])
+fi
+
+if test "x$with_libgcrypt" = "xyes"
+then
+ if test "x$GCRYPT_LDFLAGS" != "x"
+ then
+ AC_MSG_NOTICE([gcrypt LDFLAGS: $GCRYPT_LDFLAGS])
+ fi
+ AC_CHECK_LIB(gcrypt, gcry_md_hash_buffer,
+ [with_libgcrypt="yes"],
+ [with_libgcrypt="no (symbol gcry_md_hash_buffer not found)"])
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+AC_SUBST(GCRYPT_CPPFLAGS)
+AC_SUBST(GCRYPT_LDFLAGS)
+AC_SUBST(GCRYPT_LIBS)
+AM_CONDITIONAL(BUILD_WITH_LIBGCRYPT, test "x$with_libgcrypt" = "xyes")
+# }}}
+
# --with-libiptc {{{
with_own_libiptc="no"
AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to libiptc.])],
fi
# }}}
+# --with-java {{{
+with_java_home="$JAVA_HOME"
+with_java_vmtype="client"
+with_java_cflags=""
+with_java_libs=""
+AC_ARG_WITH(java, [AS_HELP_STRING([--with-java@<:@=PREFIX@:>@], [Path to Java home.])],
+[
+ if test "x$withval" = "xno"
+ then
+ with_java="no"
+ else if test "x$withval" = "xyes"
+ then
+ with_java="yes"
+ else
+ with_java_home="$withval"
+ with_java="yes"
+ fi; fi
+],
+[with_java="yes"])
+if test "x$with_java" = "xyes"
+then
+ if test -d "$with_java_home"
+ then
+ if test -d "$with_java_home/include"
+ then
+ JAVA_CPPFLAGS="$JAVA_CPPFLAGS -I$with_java_home/include"
+ else
+ JAVA_CPPFLAGS="$JAVA_CPPFLAGS -I$with_java_home"
+ fi
+
+ if test -d "$with_java_home/lib"
+ then
+ JAVA_LDFLAGS="$JAVA_LDFLAGS -L$with_java_home/lib"
+ else
+ JAVA_LDFLAGS="$JAVA_LDFLAGS -L$with_java_home"
+ fi
+ else if test "x$with_java_home" != "x"
+ then
+ AC_MSG_WARN([JAVA_HOME: No such directory: $with_java_home])
+ fi; fi
+fi
+
+if test "x$JAVA_CPPFLAGS" != "x"
+then
+ AC_MSG_NOTICE([Building with JAVA_CPPFLAGS set to: $JAVA_CPPFLAGS])
+fi
+if test "x$JAVA_CFLAGS" != "x"
+then
+ AC_MSG_NOTICE([Building with JAVA_CFLAGS set to: $JAVA_CFLAGS])
+fi
+if test "x$JAVA_LDFLAGS" != "x"
+then
+ AC_MSG_NOTICE([Building with JAVA_LDFLAGS set to: $JAVA_LDFLAGS])
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_CFLAGS="$CFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $JAVA_CPPFLAGS"
+CFLAGS="$CFLAGS $JAVA_CFLAGS"
+LDFLAGS="$LDFLAGS $JAVA_LDFLAGS"
+
+if test "x$with_java" = "xyes"
+then
+ AC_CHECK_HEADERS(jni.h, [], [with_java="no (jni.h not found)"])
+fi
+if test "x$with_java" = "xyes"
+then
+ AC_CHECK_LIB(jvm, JNI_CreateJavaVM,
+ [with_java="yes"],
+ [with_java="no (libjvm not found)"],
+ [$JAVA_LIBS])
+fi
+if test "x$with_java" = "xyes"
+then
+ JAVA_LIBS="$JAVA_LIBS -ljvm"
+ AC_MSG_NOTICE([Building with JAVA_LIBS set to: $JAVA_LIBS])
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+CFLAGS="$SAVE_CFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+AC_SUBST(JAVA_CPPFLAGS)
+AC_SUBST(JAVA_CFLAGS)
+AC_SUBST(JAVA_LDFLAGS)
+AC_SUBST(JAVA_LIBS)
+AM_CONDITIONAL(BUILD_WITH_JAVA, test "x$with_java" = "xyes")
+# }}}
+
+# --with-libmemcached {{{
+with_libmemcached_cppflags=""
+with_libmemcached_ldflags=""
+AC_ARG_WITH(libmemcached, [AS_HELP_STRING([--with-libmemcached@<:@=PREFIX@:>@], [Path to libmemcached.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_libmemcached_cppflags="-I$withval/include"
+ with_libmemcached_ldflags="-L$withval/lib"
+ with_libmemcached="yes"
+ else
+ with_libmemcached="$withval"
+ fi
+],
+[
+ with_libmemcached="yes"
+])
+if test "x$with_libmemcached" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libmemcached_cppflags"
+
+ AC_CHECK_HEADERS(libmemcached/memcached.h, [with_libmemcached="yes"], [with_libmemcached="no (libmemcached/memcached.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmemcached" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libmemcached_cppflags"
+ LDFLAGS="$LDFLAGS $with_libmemcached_ldflags"
+
+ AC_CHECK_LIB(memcached, memcached_create, [with_libmemcached="yes"], [with_libmemcached="no (Symbol 'memcached_create' not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libmemcached" = "xyes"
+then
+ BUILD_WITH_LIBMEMCACHED_CPPFLAGS="$with_libmemcached_cppflags"
+ BUILD_WITH_LIBMEMCACHED_LDFLAGS="$with_libmemcached_ldflags"
+ BUILD_WITH_LIBMEMCACHED_LIBS="-lmemcached"
+ AC_SUBST(BUILD_WITH_LIBMEMCACHED_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBMEMCACHED_LDFLAGS)
+ AC_SUBST(BUILD_WITH_LIBMEMCACHED_LIBS)
+ AC_DEFINE(HAVE_LIBMEMCACHED, 1, [Define if libmemcached is present and usable.])
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBMEMCACHED, test "x$with_libmemcached" = "xyes")
+# }}}
+
# --with-libmysql {{{
with_mysql_config="mysql_config"
with_mysql_cflags=""
# }}}
# --with-liboping {{{
-with_own_liboping="no"
-liboping_LDFLAGS="$LDFLAGS"
-liboping_CPPFLAGS="$CPPFLAGS"
AC_ARG_WITH(liboping, [AS_HELP_STRING([--with-liboping@<:@=PREFIX@:>@], [Path to liboping.])],
[
- if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ if test "x$withval" = "xyes"
+ then
+ with_liboping="yes"
+ else if test "x$withval" = "xno"
+ then
+ with_liboping="no"
+ else
+ with_liboping="yes"
+ LIBOPING_CPPFLAGS="$LIBOPING_CPPFLAGS -I$withval/include"
+ LIBOPING_LDFLAGS="$LIBOPING_LDFLAGS -L$withval/lib"
+ fi; fi
+],
+[with_liboping="yes"])
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBOPING_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBOPING_LDFLAGS"
+
+if test "x$with_liboping" = "xyes"
+then
+ if test "x$LIBOPING_CPPFLAGS" != "x"
then
- if test -d "$withval/lib"
- then
- liboping_LDFLAGS="$LDFLAGS -L$withval/lib"
- fi
- if test -d "$withval/include"
- then
- liboping_CPPFLAGS="$CPPFLAGS -I$withval/include"
- fi
+ AC_MSG_NOTICE([liboping CPPFLAGS: $LIBOPING_CPPFLAGS])
fi
- if test "x$withval" = "xno"
- then
- with_liboping="no"
- with_own_liboping="no"
- else if test "x$withval" = "xyes"
+ AC_CHECK_HEADERS(oping.h,
+ [with_liboping="yes"],
+ [with_liboping="no ('oping.h' not found)"])
+fi
+if test "x$with_liboping" = "xyes"
+then
+ if test "x$LIBOPING_LDFLAGS" != "x"
then
- with_liboping="yes"
- fi; fi
-],
-[
- with_liboping="yes"
-])
+ AC_MSG_NOTICE([liboping LDFLAGS: $LIBOPING_LDFLAGS])
+ fi
+ AC_CHECK_LIB(oping, ping_construct,
+ [with_liboping="yes"],
+ [with_liboping="no (symbol 'ping_construct' not found)"])
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
if test "x$with_liboping" = "xyes"
then
- save_LDFLAGS="$LDFLAGS"
- save_CPPFLAGS="$CPPFLAGS"
- LDFLAGS="$liboping_LDFLAGS"
- CPPFLAGS="$liboping_CPPFLAGS"
- AC_CHECK_LIB(oping, ping_construct,
- [
- with_liboping="yes"
- with_own_liboping="no"
- ],
- [
- with_liboping="yes"
- with_own_liboping="yes"
- LDFLAGS="$save_LDFLAGS"
- CPPFLAGS="$save_CPPFLAGS"
- ])
+ BUILD_WITH_LIBOPING_CPPFLAGS="$LIBOPING_CPPFLAGS"
+ BUILD_WITH_LIBOPING_LDFLAGS="$LIBOPING_LDFLAGS"
+ AC_SUBST(BUILD_WITH_LIBOPING_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBOPING_LDFLAGS)
fi
AM_CONDITIONAL(BUILD_WITH_LIBOPING, test "x$with_liboping" = "xyes")
-AM_CONDITIONAL(BUILD_WITH_OWN_LIBOPING, test "x$with_own_liboping" = "xyes")
# }}}
# --with-oracle {{{
then
SAVE_CFLAGS=$CFLAGS
SAVE_LDFLAGS=$LDFLAGS
- PERL_CFLAGS=`$perl_interpreter -MExtUtils::Embed -e ccopts`
- PERL_LDFLAGS=`$perl_interpreter -MExtUtils::Embed -e ldopts`
+ dnl ARCHFLAGS="" -> disable multi -arch on OSX (see Config_heavy.pl:fetch_string)
+ PERL_CFLAGS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ccopts`
+ PERL_LDFLAGS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ldopts`
CFLAGS="$CFLAGS $PERL_CFLAGS"
LDFLAGS="$LDFLAGS $PERL_LDFLAGS"
[with_libpq="yes"],
[with_libpq="no (symbol 'PQconnectdb' not found)"])
+ AC_CHECK_LIB(pq, PQserverVersion,
+ [with_libpq="yes"],
+ [with_libpq="no (symbol 'PQserverVersion' not found)"])
+
LDFLAGS="$SAVE_LDFLAGS"
fi
if test "x$with_libpq" = "xyes"
plugin_nfs="no"
plugin_perl="no"
plugin_processes="no"
+plugin_protocols="no"
plugin_serial="no"
plugin_swap="no"
plugin_tape="no"
plugin_tcpconns="no"
+plugin_ted="no"
plugin_thermal="no"
plugin_users="no"
+plugin_uptime="no"
plugin_vmem="no"
plugin_vserver="no"
plugin_wireless="no"
plugin_memory="yes"
plugin_nfs="yes"
plugin_processes="yes"
+ plugin_protocols="yes"
plugin_serial="yes"
plugin_swap="yes"
plugin_tcpconns="yes"
plugin_thermal="yes"
+ plugin_uptime="yes"
plugin_vmem="yes"
plugin_vserver="yes"
plugin_wireless="yes"
fi
# Solaris
+if test "x$with_kstat" = "xyes"
+then
+ plugin_uptime="yes"
+fi
+
if test "x$with_devinfo$with_kstat" = "xyesyes"
then
plugin_cpu="yes"
then
plugin_cpu="yes"
plugin_swap="yes"
+ plugin_uptime="yes"
fi
if test "x$have_sysctlbyname" = "xyes"
then
if test "x$have_termios_h" = "xyes"
then
plugin_multimeter="yes"
+ plugin_ted="yes"
fi
if test "x$have_thread_info" = "xyes"
AC_PLUGIN([entropy], [$plugin_entropy], [Entropy statistics])
AC_PLUGIN([exec], [yes], [Execution of external programs])
AC_PLUGIN([filecount], [yes], [Count files in directories])
+AC_PLUGIN([gmond], [$with_libganglia], [Ganglia plugin])
AC_PLUGIN([hddtemp], [yes], [Query hddtempd])
AC_PLUGIN([interface], [$plugin_interface], [Interface traffic statistics])
AC_PLUGIN([ipmi], [$plugin_ipmi], [IPMI sensor statistics])
AC_PLUGIN([iptables], [$with_libiptc], [IPTables rule counters])
AC_PLUGIN([ipvs], [$plugin_ipvs], [IPVS connection statistics])
AC_PLUGIN([irq], [$plugin_irq], [IRQ statistics])
+AC_PLUGIN([java], [$with_java], [Embed the Java Virtual Machine])
AC_PLUGIN([libvirt], [$plugin_libvirt], [Virtual machine statistics])
AC_PLUGIN([load], [$plugin_load], [System load])
AC_PLUGIN([logfile], [yes], [File logging plugin])
AC_PLUGIN([match_timediff], [yes], [The timediff match])
AC_PLUGIN([match_value], [yes], [The value match])
AC_PLUGIN([mbmon], [yes], [Query mbmond])
+AC_PLUGIN([memcachec], [$with_libmemcached], [memcachec statistics])
AC_PLUGIN([memcached], [yes], [memcached statistics])
AC_PLUGIN([memory], [$plugin_memory], [Memory usage])
AC_PLUGIN([multimeter], [$plugin_multimeter], [Read multimeter values])
AC_PLUGIN([postgresql], [$with_libpq], [PostgreSQL database statistics])
AC_PLUGIN([powerdns], [yes], [PowerDNS statistics])
AC_PLUGIN([processes], [$plugin_processes], [Process statistics])
+AC_PLUGIN([protocols], [$plugin_protocols], [Protocol (IP, TCP, ...) statistics])
AC_PLUGIN([rrdcached], [$librrd_rrdc_update], [RRDTool output plugin])
AC_PLUGIN([rrdtool], [$with_librrd], [RRDTool output plugin])
AC_PLUGIN([sensors], [$with_libsensors], [lm_sensors statistics])
AC_PLUGIN([snmp], [$with_libnetsnmp], [SNMP querying plugin])
AC_PLUGIN([swap], [$plugin_swap], [Swap usage statistics])
AC_PLUGIN([syslog], [$have_syslog], [Syslog logging plugin])
+AC_PLUGIN([table], [yes], [Parsing of tabular data])
AC_PLUGIN([tail], [yes], [Parsing of logfiles])
AC_PLUGIN([tape], [$plugin_tape], [Tape drive statistics])
AC_PLUGIN([target_notification], [yes], [The notification target])
AC_PLUGIN([target_set], [yes], [The set target])
AC_PLUGIN([tcpconns], [$plugin_tcpconns], [TCP connection statistics])
AC_PLUGIN([teamspeak2], [yes], [TeamSpeak2 server statistics])
+AC_PLUGIN([ted], [$plugin_ted], [Read The Energy Detective values])
AC_PLUGIN([thermal], [$plugin_thermal], [Linux ACPI thermal zone statistics])
AC_PLUGIN([unixsock], [yes], [Unixsock communication plugin])
+AC_PLUGIN([uptime], [$plugin_uptime], [Uptime statistics])
AC_PLUGIN([users], [$plugin_users], [User statistics])
AC_PLUGIN([uuid], [yes], [UUID as hostname plugin])
AC_PLUGIN([vmem], [$plugin_vmem], [Virtual memory statistics])
AC_PLUGIN([wireless], [$plugin_wireless], [Wireless statistics])
AC_PLUGIN([xmms], [$with_libxmms], [XMMS statistics])
+dnl Default configuration file
+# Load either syslog or logfile
+LOAD_PLUGIN_SYSLOG=""
+LOAD_PLUGIN_LOGFILE=""
+
+AC_MSG_CHECKING([which default log plugin to load])
+default_log_plugin="none"
+if test "x$enable_syslog" = "xyes"
+then
+ default_log_plugin="syslog"
+else
+ LOAD_PLUGIN_SYSLOG="##"
+fi
+
+if test "x$enable_logfile" = "xyes"
+then
+ if test "x$default_log_plugin" = "xnone"
+ then
+ default_log_plugin="logfile"
+ else
+ LOAD_PLUGIN_LOGFILE="#"
+ fi
+else
+ LOAD_PLUGIN_LOGFILE="##"
+fi
+AC_MSG_RESULT([$default_log_plugin])
+
+AC_SUBST(LOAD_PLUGIN_SYSLOG)
+AC_SUBST(LOAD_PLUGIN_LOGFILE)
+
+DEFAULT_LOG_LEVEL="info"
+if test "x$enable_debug" = "xyes"
+then
+ DEFAULT_LOG_LEVEL="debug"
+fi
+AC_SUBST(DEFAULT_LOG_LEVEL)
+
+# Load only one of rrdtool, network, csv in the default config.
+LOAD_PLUGIN_RRDTOOL=""
+LOAD_PLUGIN_NETWORK=""
+LOAD_PLUGIN_CSV=""
+
+AC_MSG_CHECKING([which default write plugin to load])
+default_write_plugin="none"
+if test "x$enable_rrdtool" = "xyes"
+then
+ default_write_plugin="rrdtool"
+else
+ LOAD_PLUGIN_RRDTOOL="##"
+fi
+
+if test "x$enable_network" = "xyes"
+then
+ if test "x$default_write_plugin" = "xnone"
+ then
+ default_write_plugin="network"
+ else
+ LOAD_PLUGIN_NETWORK="#"
+ fi
+else
+ LOAD_PLUGIN_NETWORK="##"
+fi
+
+if test "x$enable_csv" = "xyes"
+then
+ if test "x$default_write_plugin" = "xnone"
+ then
+ default_write_plugin="csv"
+ else
+ LOAD_PLUGIN_CSV="#"
+ fi
+else
+ LOAD_PLUGIN_CSV="##"
+fi
+AC_MSG_RESULT([$default_write_plugin])
+
+AC_SUBST(LOAD_PLUGIN_RRDTOOL)
+AC_SUBST(LOAD_PLUGIN_NETWORK)
+AC_SUBST(LOAD_PLUGIN_CSV)
+
dnl ip_vs.h
if test "x$ac_system" = "xLinux" \
&& test "x$have_net_ip_vs_h$have_ip_vs_h" = "xnono"
AC_CONFIG_FILES(src/libcollectdclient/lcc_features.h)
-AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/libiptc/Makefile src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile src/liboping/Makefile bindings/Makefile)
+AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/libiptc/Makefile src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile)
if test "x$with_librrd" = "xyes" \
&& test "x$librrd_threadsafe" != "xyes"
with_librrd="yes (warning: librrd is not thread-safe)"
fi
-if test "x$with_liboping" = "xyes" \
- && test "x$with_own_liboping" = "xyes"
-then
- with_liboping="yes (shipped version)"
-fi
-
if test "x$with_libiptc" = "xyes" -a "x$with_own_libiptc" = "xyes"
then
with_libiptc="yes (shipped version)"
libesmtp . . . . . . $with_libesmtp
libiokit . . . . . . $with_libiokit
libiptc . . . . . . . $with_libiptc
+ libjvm . . . . . . . $with_java
libkstat . . . . . . $with_kstat
libkvm . . . . . . . $with_libkvm
libmysql . . . . . . $with_libmysql
entropy . . . . . . . $enable_entropy
exec . . . . . . . . $enable_exec
filecount . . . . . . $enable_filecount
+ gmond . . . . . . . . $enable_gmond
hddtemp . . . . . . . $enable_hddtemp
interface . . . . . . $enable_interface
ipmi . . . . . . . . $enable_ipmi
iptables . . . . . . $enable_iptables
ipvs . . . . . . . . $enable_ipvs
irq . . . . . . . . . $enable_irq
+ java . . . . . . . . $enable_java
libvirt . . . . . . . $enable_libvirt
load . . . . . . . . $enable_load
logfile . . . . . . . $enable_logfile
match_timediff . . . $enable_match_timediff
match_value . . . . . $enable_match_value
mbmon . . . . . . . . $enable_mbmon
+ memcachec . . . . . . $enable_memcachec
memcached . . . . . . $enable_memcached
memory . . . . . . . $enable_memory
multimeter . . . . . $enable_multimeter
postgresql . . . . . $enable_postgresql
powerdns . . . . . . $enable_powerdns
processes . . . . . . $enable_processes
+ protocols . . . . . . $enable_protocols
rrdcached . . . . . . $enable_rrdcached
rrdtool . . . . . . . $enable_rrdtool
sensors . . . . . . . $enable_sensors
snmp . . . . . . . . $enable_snmp
swap . . . . . . . . $enable_swap
syslog . . . . . . . $enable_syslog
+ table . . . . . . . . $enable_table
tail . . . . . . . . $enable_tail
tape . . . . . . . . $enable_tape
target_notification . $enable_target_notification
target_set . . . . . $enable_target_set
tcpconns . . . . . . $enable_tcpconns
teamspeak2 . . . . . $enable_teamspeak2
+ ted . . . . . . . . . $enable_ted
thermal . . . . . . . $enable_thermal
unixsock . . . . . . $enable_unixsock
+ uptime . . . . . . . $enable_uptime
users . . . . . . . . $enable_users
uuid . . . . . . . . $enable_uuid
vmem . . . . . . . . $enable_vmem
diff --combined src/exec.c
index cdcf6adebdba0f886aa2515cb92e7ac9b21a92d7,c2d42ee0bbcc19f4268ab568ea45971ba70b92df..82aeb29d43d701d08f82459c4995b415a57eb7d7
--- 1/src/exec.c
--- 2/src/exec.c
+++ b/src/exec.c
if (errno == EAGAIN || errno == EINTR) continue;
break;
}
- else if (len == 0) break; /* We've reached EOF */
+ else if (len == 0)
+ {
+ /* We've reached EOF */
+ NOTICE ("exec plugin: Program `%s' has closed STDERR.",
+ pl->exec);
+ close (fd_err);
+ FD_CLR (fd_err, &fdset);
+ highest_fd = fd;
+ fd_err = -1;
+ continue;
+ }
pbuffer_err[len] = '\0';
copy = fdset;
}
+ DEBUG ("exec plugin: exec_read_one: Waiting for `%s' to exit.", pl->exec);
if (waitpid (pl->pid, &status, 0) > 0)
pl->status = status;
pthread_mutex_unlock (&pl_lock);
close (fd);
- close (fd_err);
+ if (fd_err >= 0)
+ close (fd_err);
pthread_exit ((void *) 0);
return (NULL);
return (0);
} /* int exec_read }}} */
-static int exec_notification (const notification_t *n)
+static int exec_notification (const notification_t *n,
+ user_data_t __attribute__((unused)) *user_data)
{
program_list_t *pl;
program_list_and_notification_t *pln;
} /* for (pl) */
return (0);
-} /* int exec_notification */
+} /* }}} int exec_notification */
static int exec_shutdown (void) /* {{{ */
{
plugin_register_complex_config ("exec", exec_config);
plugin_register_init ("exec", exec_init);
plugin_register_read ("exec", exec_read);
- plugin_register_notification ("exec", exec_notification);
+ plugin_register_notification ("exec", exec_notification,
+ /* user_data = */ NULL);
plugin_register_shutdown ("exec", exec_shutdown);
} /* void module_register */
diff --combined src/network.c
index bbe6b6fd7f58600be4f60982ba1605a58e6837ab,902f270e5336b09d3e59d611cafb2c07443ea0f7..51b9922d2f87fdd573c1ec0de05ef3d1c41c981e
--- 1/src/network.c
--- 2/src/network.c
+++ b/src/network.c
/**
* collectd - src/network.c
- * Copyright (C) 2005-2008 Florian octo Forster
+ * Copyright (C) 2005-2009 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
# include <poll.h>
#endif
+#if HAVE_GCRYPT_H
+# include <gcrypt.h>
+#endif
+
/* 1500 - 40 - 8 = Ethernet packet - IPv6 header - UDP header */
/* #define BUFF_SIZE 1452 */
# endif
#endif /* !IP_ADD_MEMBERSHIP */
+/* Buffer size to allocate. */
#define BUFF_SIZE 1024
+/*
+ * Maximum size required for encryption / signing:
+ * Type/length: 4
+ * Hash/orig length: 32
+ * Padding (up to): 16
+ * --------------------
+ * 52
+ */
+#define BUFF_SIG_SIZE 52
+
/*
* Private data types
*/
int fd;
struct sockaddr_storage *addr;
socklen_t addrlen;
+
+#define SECURITY_LEVEL_NONE 0
+#if HAVE_GCRYPT_H
+# define SECURITY_LEVEL_SIGN 1
+# define SECURITY_LEVEL_ENCRYPT 2
+ int security_level;
+ char *shared_secret;
+ gcry_cipher_hd_t cypher;
+#endif /* HAVE_GCRYPT_H */
+
struct sockent *next;
} sockent_t;
};
typedef struct part_values_s part_values_t;
+struct part_signature_sha256_s
+{
+ part_header_t head;
+ char hash[32];
+};
+typedef struct part_signature_sha256_s part_signature_sha256_t;
+
+struct part_encryption_aes256_s
+{
+ part_header_t head;
+ uint16_t orig_length;
+ uint16_t random;
+ char hash[28];
+};
+typedef struct part_encryption_aes256_s part_encryption_aes256_t;
+
struct receive_list_entry_s
{
char data[BUFF_SIZE];
int data_len;
+ int fd;
struct receive_list_entry_s *next;
};
typedef struct receive_list_entry_s receive_list_entry_t;
/*
* Private variables
*/
-static const char *config_keys[] =
-{
- "CacheFlush",
- "Listen",
- "Server",
- "TimeToLive",
- "Forward"
-};
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
-
static int network_config_ttl = 0;
static int network_config_forward = 0;
static pthread_mutex_t receive_list_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t receive_list_cond = PTHREAD_COND_INITIALIZER;
-static struct pollfd *listen_sockets = NULL;
-static int listen_sockets_num = 0;
-
-static int listen_loop = 0;
-static pthread_t receive_thread_id = 0;
-static pthread_t dispatch_thread_id = 0;
-
-static char send_buffer[BUFF_SIZE];
-static char *send_buffer_ptr;
-static int send_buffer_fill;
-static value_list_t send_buffer_vl = VALUE_LIST_STATIC;
-static pthread_mutex_t send_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
-
-static c_avl_tree_t *cache_tree = NULL;
+static sockent_t *listen_sockets = NULL;
+static struct pollfd *listen_sockets_pollfd = NULL;
+static int listen_sockets_num = 0;
+
+/* The receive and dispatch threads will run as long as `listen_loop' is set to
+ * zero. */
+static int listen_loop = 0;
+static int receive_thread_running = 0;
+static pthread_t receive_thread_id;
+static int dispatch_thread_running = 0;
+static pthread_t dispatch_thread_id;
+
+/* Buffer in which to-be-sent network packets are constructed. */
+static char send_buffer[BUFF_SIZE];
+static char *send_buffer_ptr;
+static int send_buffer_fill;
+static value_list_t send_buffer_vl = VALUE_LIST_STATIC;
+static pthread_mutex_t send_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* In this cache we store all the values we received, so we can send out only
+ * those values which were *not* received via the network plugin, too. This is
+ * used for the `Forward false' option. */
+static c_avl_tree_t *cache_tree = NULL;
static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
static time_t cache_flush_last = 0;
static int cache_flush_interval = 1800;
pthread_mutex_unlock (&cache_lock);
- DEBUG ("network plugin: cache_check: key = %s; time = %i; retval = %i",
- key, (int) vl->time, retval);
-
return (retval);
} /* int cache_check */
return (0);
} /* int parse_part_string */
-static int parse_packet (void *buffer, int buffer_len)
+#if HAVE_GCRYPT_H
+static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
+ void **ret_buffer, int *ret_buffer_len)
+{
+ char *buffer = *ret_buffer;
+ size_t buffer_len = (size_t) *ret_buffer_len;
+
+ part_signature_sha256_t ps_received;
+ part_signature_sha256_t ps_expected;
+
+ if (se->shared_secret == NULL)
+ {
+ NOTICE ("network plugin: Received signed network packet but can't verify "
+ "it because no shared secret has been configured. Will accept it.");
+ return (0);
+ }
+
+ if (buffer_len < sizeof (ps_received))
+ return (-ENOMEM);
+
+ memcpy (&ps_received, buffer, sizeof (ps_received));
+
+ memset (&ps_expected, 0, sizeof (ps_expected));
+ ps_expected.head.type = htons (TYPE_SIGN_SHA256);
+ ps_expected.head.length = htons (sizeof (ps_expected));
+ sstrncpy (ps_expected.hash, se->shared_secret, sizeof (ps_expected.hash));
+ memcpy (buffer, &ps_expected, sizeof (ps_expected));
+
+ gcry_md_hash_buffer (GCRY_MD_SHA256, ps_expected.hash, buffer, buffer_len);
+
+ *ret_buffer += sizeof (ps_received);
+
+ if (memcmp (ps_received.hash, ps_expected.hash,
+ sizeof (ps_received.hash)) == 0)
+ return (0);
+ else /* hashes do not match. */
+ return (1);
+} /* }}} int parse_part_sign_sha256 */
+/* #endif HAVE_GCRYPT_H */
+
+#else /* if !HAVE_GCRYPT_H */
+static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
+ void **ret_buffer, int *ret_buffer_len)
+{
+ INFO ("network plugin: Received signed packet, but the network "
+ "plugin was not linked with libgcrypt, so I cannot "
+ "verify the signature. The packet will be accepted.");
+ return (0);
+} /* }}} int parse_part_sign_sha256 */
+#endif /* !HAVE_GCRYPT_H */
+
+#if HAVE_GCRYPT_H
+static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
+ void **ret_buffer, int *ret_buffer_len)
+{
+ char *buffer = *ret_buffer;
+ int buffer_len = *ret_buffer_len;
+ int orig_buffer_len;
+ part_encryption_aes256_t pea;
+ char hash[28];
+ gcry_error_t err;
+
+ if (se->cypher == NULL)
+ {
+ NOTICE ("network plugin: Unable to decrypt packet, because no cypher "
+ "instance is present.");
+ return (-1);
+ }
+
+ /* Decrypt the packet in-place */
+ err = gcry_cipher_decrypt (se->cypher,
+ buffer + sizeof (pea.head), buffer_len - sizeof (pea.head),
+ /* in = */ NULL, /* in len = */ 0);
+ gcry_cipher_reset (se->cypher);
+ if (err != 0)
+ {
+ ERROR ("network plugin: gcry_cipher_decrypt returned: %s",
+ gcry_strerror (err));
+ return (-1);
+ }
+
+ /* Copy the header information to `pea' */
+ memcpy (&pea, buffer, sizeof (pea));
+ buffer += sizeof (pea);
+ buffer_len -= sizeof (pea);
+
+ /* Check sanity of the original length */
+ orig_buffer_len = ntohs (pea.orig_length);
+ if (orig_buffer_len > buffer_len)
+ {
+ ERROR ("network plugin: Decryption failed: Invalid original length.");
+ return (-1);
+ }
+
+ /* Check hash sum */
+ memset (hash, 0, sizeof (hash));
+ gcry_md_hash_buffer (GCRY_MD_SHA224, hash, buffer, orig_buffer_len);
+
+ if (memcmp (hash, pea.hash, sizeof (hash)) != 0)
+ {
+ ERROR ("network plugin: Decryption failed: Checksum mismatch.");
+ return (-1);
+ }
+
+ /* Update return values */
+ *ret_buffer = buffer;
+ *ret_buffer_len = orig_buffer_len;
+
+ return (0);
+} /* }}} int parse_part_encr_aes256 */
+/* #endif HAVE_GCRYPT_H */
+
+#else /* if !HAVE_GCRYPT_H */
+static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
+ void **ret_buffer, int *ret_buffer_len)
+{
+ INFO ("network plugin: Received encrypted packet, but the network "
+ "plugin was not linked with libgcrypt, so I cannot "
+ "decrypt it. The packet will be discarded.");
+ return (-1);
+} /* }}} int parse_part_encr_aes256 */
+#endif /* !HAVE_GCRYPT_H */
+
+static int parse_packet (receive_list_entry_t *rle) /* {{{ */
{
int status;
+ void *buffer;
+ int buffer_len;
+ sockent_t *se;
+
value_list_t vl = VALUE_LIST_INIT;
notification_t n;
- DEBUG ("network plugin: parse_packet: buffer = %p; buffer_len = %i;",
- buffer, buffer_len);
+ int packet_was_encrypted = 0;
+ int packet_was_signed = 0;
+#if HAVE_GCRYPT_H
+ int printed_ignore_warning = 0;
+#endif /* HAVE_GCRYPT_H */
+
+ buffer = rle->data;
+ buffer_len = rle->data_len;
+
+ /* Look for the correct `sockent_t' */
+ se = listen_sockets;
+ while ((se != NULL) && (se->fd != rle->fd))
+ se = se->next;
+
+ if (se == NULL)
+ {
+ ERROR ("network plugin: Got packet from FD %i, but can't "
+ "find an appropriate socket entry.",
+ rle->fd);
+ return (-1);
+ }
memset (&vl, '\0', sizeof (vl));
memset (&n, '\0', sizeof (n));
if (pkg_length < (2 * sizeof (uint16_t)))
break;
- if (pkg_type == TYPE_VALUES)
+ if (pkg_type == TYPE_ENCR_AES256)
+ {
+ status = parse_part_encr_aes256 (se, &buffer, &buffer_len);
+ if (status != 0)
+ {
+ ERROR ("network plugin: Decrypting AES256 "
+ "part failed "
+ "with status %i.", status);
+ break;
+ }
+ else
+ {
+ packet_was_encrypted = 1;
+ }
+ }
+#if HAVE_GCRYPT_H
+ else if ((se->security_level == SECURITY_LEVEL_ENCRYPT)
+ && (packet_was_encrypted == 0))
+ {
+ if (printed_ignore_warning == 0)
+ {
+ INFO ("network plugin: Unencrypted packet or "
+ "part has been ignored.");
+ printed_ignore_warning = 1;
+ }
+ buffer = ((char *) buffer) + pkg_length;
+ continue;
+ }
+#endif /* HAVE_GCRYPT_H */
+ else if (pkg_type == TYPE_SIGN_SHA256)
+ {
+ status = parse_part_sign_sha256 (se, &buffer, &buffer_len);
+ if (status < 0)
+ {
+ ERROR ("network plugin: Verifying SHA-256 "
+ "signature failed "
+ "with status %i.", status);
+ break;
+ }
+ else if (status > 0)
+ {
+ ERROR ("network plugin: Ignoring packet with "
+ "invalid SHA-256 signature.");
+ break;
+ }
+ else
+ {
+ packet_was_signed = 1;
+ }
+ }
+#if HAVE_GCRYPT_H
+ else if ((se->security_level == SECURITY_LEVEL_SIGN)
+ && (packet_was_encrypted == 0)
+ && (packet_was_signed == 0))
+ {
+ if (printed_ignore_warning == 0)
+ {
+ INFO ("network plugin: Unsigned packet or "
+ "part has been ignored.");
+ printed_ignore_warning = 1;
+ }
+ buffer = ((char *) buffer) + pkg_length;
+ continue;
+ }
+#endif /* HAVE_GCRYPT_H */
+ else if (pkg_type == TYPE_VALUES)
{
status = parse_part_values (&buffer, &buffer_len,
&vl.values, &vl.values_len);
} /* while (buffer_len > sizeof (part_header_t)) */
return (status);
-} /* int parse_packet */
+} /* }}} int parse_packet */
-static void free_sockent (sockent_t *se)
+static void free_sockent (sockent_t *se) /* {{{ */
{
sockent_t *next;
while (se != NULL)
{
next = se->next;
+
+#if HAVE_GCRYPT_H
+ if (se->cypher != NULL)
+ {
+ gcry_cipher_close (se->cypher);
+ se->cypher = NULL;
+ }
+ free (se->shared_secret);
+#endif /* HAVE_GCRYPT_H */
+
free (se->addr);
free (se);
+
se = next;
}
-} /* void free_sockent */
+} /* }}} void free_sockent */
/*
* int network_set_ttl
*/
static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
{
+ DEBUG ("network plugin: network_set_ttl: network_config_ttl = %i;",
+ network_config_ttl);
+
if ((network_config_ttl < 1) || (network_config_ttl > 255))
return (-1);
- DEBUG ("ttl = %i", network_config_ttl);
-
if (ai->ai_family == AF_INET)
{
struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
return (0);
} /* int network_set_ttl */
+#if HAVE_GCRYPT_H
+static int network_set_encryption (sockent_t *se, /* {{{ */
+ const char *shared_secret)
+{
+ char hash[32];
+ gcry_error_t err;
+
+ se->shared_secret = sstrdup (shared_secret);
+
+ /*
+ * We use CBC *without* an initialization vector: The cipher is reset after
+ * each packet and we would have to re-set the IV each time. The first
+ * encrypted block will contain the SHA-224 checksum anyway, so this should
+ * be quite unpredictable. Also, there's a 2 byte field in the header that's
+ * being filled with random numbers. So we only use CBC so the blocks
+ * *within* one packet are chained.
+ */
+ err = gcry_cipher_open (&se->cypher,
+ GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, /* flags = */ 0);
+ if (err != 0)
+ {
+ ERROR ("network plugin: gcry_cipher_open returned: %s",
+ gcry_strerror (err));
+ return (-1);
+ }
+
+ assert (se->shared_secret != NULL);
+ gcry_md_hash_buffer (GCRY_MD_SHA256, hash,
+ se->shared_secret, strlen (se->shared_secret));
+
+ err = gcry_cipher_setkey (se->cypher, hash, sizeof (hash));
+ if (err != 0)
+ {
+ DEBUG ("network plugin: gcry_cipher_setkey returned: %s",
+ gcry_strerror (err));
+ gcry_cipher_close (se->cypher);
+ se->cypher = NULL;
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int network_set_encryption */
+#endif /* HAVE_GCRYPT_H */
+
static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
{
int loop = 0;
return (0);
} /* int network_bind_socket */
-static sockent_t *network_create_socket (const char *node,
+#define CREATE_SOCKET_FLAGS_LISTEN 0x0001
+static sockent_t *network_create_socket (const char *node, /* {{{ */
const char *service,
- int listen)
+ const char *shared_secret,
+ int security_level,
+ int flags)
{
struct addrinfo ai_hints;
struct addrinfo *ai_list, *ai_ptr;
for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
sockent_t *se;
+ int status;
if ((se = (sockent_t *) malloc (sizeof (sockent_t))) == NULL)
{
continue;
}
- if (listen != 0)
+ if ((flags & CREATE_SOCKET_FLAGS_LISTEN) != 0)
{
- if (network_bind_socket (se, ai_ptr) != 0)
+ status = network_bind_socket (se, ai_ptr);
+ if (status != 0)
{
close (se->fd);
free (se->addr);
continue;
}
}
- else /* listen == 0 */
+ else /* sending socket */
{
network_set_ttl (se, ai_ptr);
}
+#if HAVE_GCRYPT_H
+ se->security_level = security_level;
+ se->shared_secret = NULL;
+ se->cypher = NULL;
+ if (shared_secret != NULL)
+ {
+ status = network_set_encryption (se, shared_secret);
+ if ((status != 0) && (security_level <= SECURITY_LEVEL_SIGN))
+ {
+ WARNING ("network plugin: Starting cryptograp"
+ "hic subsystem failed. Since "
+ "security level `Sign' or "
+ "`None' is configured I will "
+ "continue.");
+ }
+ else if (status != 0)
+ {
+ ERROR ("network plugin: Starting cryptograp"
+ "hic subsystem failed. "
+ "Because the security level "
+ "is set to `Encrypt' I will "
+ "not continue!");
+ close (se->fd);
+ free (se->addr);
+ free (se);
+ continue;
+ }
+ } /* if (shared_secret != NULL) */
+#else
+ /* Make compiler happy */
+ security_level = 0;
+ shared_secret = NULL;
+#endif /* HAVE_GCRYPT_H */
+
if (se_tail == NULL)
{
se_head = se;
}
/* We don't open more than one write-socket per node/service pair.. */
- if (listen == 0)
+ if ((flags & CREATE_SOCKET_FLAGS_LISTEN) == 0)
break;
}
freeaddrinfo (ai_list);
return (se_head);
-} /* sockent_t *network_create_socket */
+} /* }}} sockent_t *network_create_socket */
-static sockent_t *network_create_default_socket (int listen)
+static sockent_t *network_create_default_socket (int flags) /* {{{ */
{
sockent_t *se_ptr = NULL;
sockent_t *se_head = NULL;
sockent_t *se_tail = NULL;
- se_ptr = network_create_socket (NET_DEFAULT_V6_ADDR,
- NET_DEFAULT_PORT, listen);
+ se_ptr = network_create_socket (NET_DEFAULT_V6_ADDR, NET_DEFAULT_PORT,
+ /* shared secret = */ NULL, SECURITY_LEVEL_NONE,
+ flags);
/* Don't send to the same machine in IPv6 and IPv4 if both are available. */
- if ((listen == 0) && (se_ptr != NULL))
+ if (((flags & CREATE_SOCKET_FLAGS_LISTEN) == 0) && (se_ptr != NULL))
return (se_ptr);
if (se_ptr != NULL)
se_tail = se_tail->next;
}
- se_ptr = network_create_socket (NET_DEFAULT_V4_ADDR, NET_DEFAULT_PORT, listen);
+ se_ptr = network_create_socket (NET_DEFAULT_V4_ADDR, NET_DEFAULT_PORT,
+ /* shared secret = */ NULL, SECURITY_LEVEL_NONE,
+ flags);
if (se_tail == NULL)
return (se_ptr);
se_tail->next = se_ptr;
return (se_head);
-} /* sockent_t *network_create_default_socket */
+} /* }}} sockent_t *network_create_default_socket */
-static int network_add_listen_socket (const char *node, const char *service)
+static int network_add_listen_socket (const char *node, /* {{{ */
+ const char *service, const char *shared_secret, int security_level)
{
sockent_t *se;
sockent_t *se_ptr;
int se_num = 0;
+ int flags;
+
+ flags = CREATE_SOCKET_FLAGS_LISTEN;
+
if (service == NULL)
service = NET_DEFAULT_PORT;
if (node == NULL)
- se = network_create_default_socket (1 /* listen == true */);
+ se = network_create_default_socket (flags);
else
- se = network_create_socket (node, service, 1 /* listen == true */);
+ se = network_create_socket (node, service,
+ shared_secret, security_level, flags);
if (se == NULL)
return (-1);
for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
se_num++;
- listen_sockets = (struct pollfd *) realloc (listen_sockets,
+ listen_sockets_pollfd = realloc (listen_sockets_pollfd,
(listen_sockets_num + se_num)
* sizeof (struct pollfd));
for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
{
- listen_sockets[listen_sockets_num].fd = se_ptr->fd;
- listen_sockets[listen_sockets_num].events = POLLIN | POLLPRI;
- listen_sockets[listen_sockets_num].revents = 0;
+ listen_sockets_pollfd[listen_sockets_num].fd = se_ptr->fd;
+ listen_sockets_pollfd[listen_sockets_num].events = POLLIN | POLLPRI;
+ listen_sockets_pollfd[listen_sockets_num].revents = 0;
listen_sockets_num++;
} /* for (se) */
- free_sockent (se);
+ se_ptr = listen_sockets;
+ while ((se_ptr != NULL) && (se_ptr->next != NULL))
+ se_ptr = se_ptr->next;
+
+ if (se_ptr == NULL)
+ listen_sockets = se;
+ else
+ se_ptr->next = se;
+
return (0);
-} /* int network_add_listen_socket */
+} /* }}} int network_add_listen_socket */
-static int network_add_sending_socket (const char *node, const char *service)
+static int network_add_sending_socket (const char *node, /* {{{ */
+ const char *service, const char *shared_secret, int security_level)
{
sockent_t *se;
sockent_t *se_ptr;
service = NET_DEFAULT_PORT;
if (node == NULL)
- se = network_create_default_socket (0 /* listen == false */);
+ se = network_create_default_socket (/* flags = */ 0);
else
- se = network_create_socket (node, service, 0 /* listen == false */);
+ se = network_create_socket (node, service,
+ shared_secret, security_level,
+ /* flags = */ 0);
if (se == NULL)
return (-1);
se_ptr->next = se;
return (0);
-} /* int network_get_listen_socket */
+} /* }}} int network_add_sending_socket */
static void *dispatch_thread (void __attribute__((unused)) *arg)
{
if (ent == NULL)
break;
- parse_packet (ent->data, ent->data_len);
+ parse_packet (ent);
sfree (ent);
} /* while (42) */
return (NULL);
-} /* void *receive_thread */
+} /* void *dispatch_thread */
static int network_receive (void)
{
receive_list_entry_t *private_list_tail;
if (listen_sockets_num == 0)
- network_add_listen_socket (NULL, NULL);
+ network_add_listen_socket (/* node = */ NULL,
+ /* service = */ NULL,
+ /* shared secret = */ NULL,
+ /* encryption = */ 0);
if (listen_sockets_num == 0)
{
while (listen_loop == 0)
{
- status = poll (listen_sockets, listen_sockets_num, -1);
+ status = poll (listen_sockets_pollfd, listen_sockets_num, -1);
if (status <= 0)
{
{
receive_list_entry_t *ent;
- if ((listen_sockets[i].revents & (POLLIN | POLLPRI)) == 0)
+ if ((listen_sockets_pollfd[i].revents
+ & (POLLIN | POLLPRI)) == 0)
continue;
status--;
- buffer_len = recv (listen_sockets[i].fd,
+ buffer_len = recv (listen_sockets_pollfd[i].fd,
buffer, sizeof (buffer),
0 /* no flags */);
if (buffer_len < 0)
return (-1);
}
+ /* TODO: Possible performance enhancement: Do not free
+ * these entries in the dispatch thread but put them in
+ * another list, so we don't have to allocate more and
+ * more of these structures. */
ent = malloc (sizeof (receive_list_entry_t));
if (ent == NULL)
{
return (-1);
}
memset (ent, 0, sizeof (receive_list_entry_t));
+ ent->fd = listen_sockets_pollfd[i].fd;
ent->next = NULL;
/* Hopefully this be optimized out by the compiler. It
pthread_cond_signal (&receive_list_cond);
pthread_mutex_unlock (&receive_list_lock);
}
- } /* for (listen_sockets) */
+ } /* for (listen_sockets_pollfd) */
} /* while (listen_loop == 0) */
/* Make sure everything is dispatched before exiting. */
}
return (0);
-}
+} /* int network_receive */
static void *receive_thread (void __attribute__((unused)) *arg)
{
return (network_receive () ? (void *) 1 : (void *) 0);
} /* void *receive_thread */
-static void network_send_buffer (const char *buffer, int buffer_len)
+static void network_init_buffer (void)
{
- sockent_t *se;
- int status;
+ memset (send_buffer, 0, sizeof (send_buffer));
+ send_buffer_ptr = send_buffer;
+ send_buffer_fill = 0;
- DEBUG ("network plugin: network_send_buffer: buffer_len = %i", buffer_len);
+ memset (&send_buffer_vl, 0, sizeof (send_buffer_vl));
+} /* int network_init_buffer */
- for (se = sending_sockets; se != NULL; se = se->next)
+static void networt_send_buffer_plain (const sockent_t *se, /* {{{ */
+ const char *buffer, size_t buffer_size)
+{
+ int status;
+
+ while (42)
{
- while (42)
+ status = sendto (se->fd, buffer, buffer_size, 0 /* no flags */,
+ (struct sockaddr *) se->addr, se->addrlen);
+ if (status < 0)
{
- status = sendto (se->fd, buffer, buffer_len, 0 /* no flags */,
- (struct sockaddr *) se->addr, se->addrlen);
- if (status < 0)
- {
- char errbuf[1024];
- if (errno == EINTR)
- continue;
- ERROR ("network plugin: sendto failed: %s",
- sstrerror (errno, errbuf,
- sizeof (errbuf)));
- break;
- }
-
+ char errbuf[1024];
+ if (errno == EINTR)
+ continue;
+ ERROR ("network plugin: sendto failed: %s",
+ sstrerror (errno, errbuf,
+ sizeof (errbuf)));
break;
- } /* while (42) */
- } /* for (sending_sockets) */
-} /* void network_send_buffer */
+ }
+
+ break;
+ } /* while (42) */
+} /* }}} void networt_send_buffer_plain */
+
+#if HAVE_GCRYPT_H
+static void networt_send_buffer_signed (const sockent_t *se, /* {{{ */
+ const char *in_buffer, size_t in_buffer_size)
+{
+ part_signature_sha256_t ps;
+ char buffer[sizeof (ps) + in_buffer_size];
+ char hash[sizeof (ps.hash)];
+
+ /* Initialize the `ps' structure. */
+ memset (&ps, 0, sizeof (ps));
+ ps.head.type = htons (TYPE_SIGN_SHA256);
+ ps.head.length = htons ((uint16_t) sizeof (ps));
+ sstrncpy (ps.hash, se->shared_secret, sizeof (ps.hash));
+
+ /* Prepend the signature. */
+ memcpy (buffer, &ps, sizeof (ps));
+ memcpy (buffer + sizeof (ps), in_buffer, in_buffer_size);
+
+ /* Calculate the hash value. */
+ gcry_md_hash_buffer (GCRY_MD_SHA256, hash, buffer, sizeof (buffer));
+
+ /* Copy the hash value into the buffer. */
+ memcpy (ps.hash, hash, sizeof (ps.hash));
+ memcpy (buffer, &ps, sizeof (ps));
+
+ networt_send_buffer_plain (se, buffer, sizeof (buffer));
+} /* }}} void networt_send_buffer_signed */
+
+static void networt_send_buffer_encrypted (const sockent_t *se, /* {{{ */
+ const char *in_buffer, size_t in_buffer_size)
+{
+ part_encryption_aes256_t pea;
+ char buffer[sizeof (pea) + in_buffer_size + 16];
+ size_t buffer_size;
+ gcry_error_t err;
+
+ /* Round to the next multiple of 16, because AES has a block size of 128 bit.
+ * the first four bytes of `pea' are not encrypted and must be subtracted. */
+ buffer_size = (sizeof (pea) + in_buffer_size + 15 - sizeof (pea.head)) / 16;
+ buffer_size = buffer_size * 16;
+ buffer_size += sizeof (pea.head);
+
+ DEBUG ("network plugin: networt_send_buffer_encrypted: "
+ "buffer_size = %zu;", buffer_size);
+
+ /* Initialize the header fields */
+ memset (&pea, 0, sizeof (pea));
+ pea.head.type = htons (TYPE_ENCR_AES256);
+ pea.head.length = htons ((uint16_t) buffer_size);
+ pea.orig_length = htons ((uint16_t) in_buffer_size);
+
+ /* Fill the extra field with random values. Some entropy in the encrypted
+ * data is usually not a bad thing, I hope. */
+ gcry_randomize (&pea.random, sizeof (pea.random), GCRY_STRONG_RANDOM);
+
+ /* Create hash of the payload */
+ gcry_md_hash_buffer (GCRY_MD_SHA224, pea.hash, in_buffer, in_buffer_size);
+
+ /* Initialize the buffer */
+ memset (buffer, 0, sizeof (buffer));
+ memcpy (buffer, &pea, sizeof (pea));
+ memcpy (buffer + sizeof (pea), in_buffer, in_buffer_size);
+
+ /* Encrypt the buffer in-place */
+ err = gcry_cipher_encrypt (se->cypher,
+ buffer + sizeof (pea.head), buffer_size - sizeof (pea.head),
+ /* in = */ NULL, /* in len = */ 0);
+ gcry_cipher_reset (se->cypher);
+ if (err != 0)
+ {
+ ERROR ("network plugin: gcry_cipher_encrypt returned: %s",
+ gcry_strerror (err));
+ return;
+ }
+
+ /* Send it out without further modifications */
+ networt_send_buffer_plain (se, buffer, buffer_size);
+} /* }}} void networt_send_buffer_encrypted */
+#endif /* HAVE_GCRYPT_H */
+
+static void network_send_buffer (char *buffer, size_t buffer_len) /* {{{ */
+{
+ sockent_t *se;
-static int add_to_buffer (char *buffer, int buffer_size,
+ DEBUG ("network plugin: network_send_buffer: buffer_len = %zu", buffer_len);
+
+ for (se = sending_sockets; se != NULL; se = se->next)
+ {
+#if HAVE_GCRYPT_H
+ if (se->security_level == SECURITY_LEVEL_ENCRYPT)
+ networt_send_buffer_encrypted (se, buffer, buffer_len);
+ else if (se->security_level == SECURITY_LEVEL_SIGN)
+ networt_send_buffer_signed (se, buffer, buffer_len);
+ else /* if (se->security_level == SECURITY_LEVEL_NONE) */
+#endif /* HAVE_GCRYPT_H */
+ networt_send_buffer_plain (se, buffer, buffer_len);
+ } /* for (sending_sockets) */
+} /* }}} void network_send_buffer */
+
+static int add_to_buffer (char *buffer, int buffer_size, /* {{{ */
value_list_t *vl_def,
const data_set_t *ds, const value_list_t *vl)
{
return (-1);
return (buffer - buffer_orig);
-} /* int add_to_buffer */
+} /* }}} int add_to_buffer */
static void flush_buffer (void)
{
DEBUG ("network plugin: flush_buffer: send_buffer_fill = %i",
send_buffer_fill);
- network_send_buffer (send_buffer, send_buffer_fill);
- send_buffer_ptr = send_buffer;
- send_buffer_fill = 0;
- memset (&send_buffer_vl, 0, sizeof (send_buffer_vl));
+ network_send_buffer (send_buffer, (size_t) send_buffer_fill);
+ network_init_buffer ();
}
-static int network_write (const data_set_t *ds, const value_list_t *vl)
+static int network_write (const data_set_t *ds, const value_list_t *vl,
+ user_data_t __attribute__((unused)) *user_data)
{
int status;
pthread_mutex_lock (&send_buffer_lock);
status = add_to_buffer (send_buffer_ptr,
- sizeof (send_buffer) - send_buffer_fill,
+ sizeof (send_buffer) - (send_buffer_fill + BUFF_SIG_SIZE),
&send_buffer_vl,
ds, vl);
if (status >= 0)
flush_buffer ();
status = add_to_buffer (send_buffer_ptr,
- sizeof (send_buffer) - send_buffer_fill,
+ sizeof (send_buffer) - (send_buffer_fill + BUFF_SIG_SIZE),
&send_buffer_vl,
ds, vl);
return ((status < 0) ? -1 : 0);
} /* int network_write */
-static int network_config (const char *key, const char *val)
+static int network_config_set_boolean (const oconfig_item_t *ci, /* {{{ */
+ int *retval)
{
- char *node;
- char *service;
+ if ((ci->values_num != 1)
+ || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN)
+ && (ci->values[0].type != OCONFIG_TYPE_STRING)))
+ {
+ ERROR ("network plugin: The `%s' config option needs "
+ "exactly one boolean argument.", ci->key);
+ return (-1);
+ }
- char *fields[3];
- int fields_num;
+ if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
+ {
+ if (ci->values[0].value.boolean)
+ *retval = 1;
+ else
+ *retval = 0;
+ }
+ else
+ {
+ char *str = ci->values[0].value.string;
+
+ if ((strcasecmp ("true", str) == 0)
+ || (strcasecmp ("yes", str) == 0)
+ || (strcasecmp ("on", str) == 0))
+ *retval = 1;
+ else if ((strcasecmp ("false", str) == 0)
+ || (strcasecmp ("no", str) == 0)
+ || (strcasecmp ("off", str) == 0))
+ *retval = 0;
+ else
+ {
+ ERROR ("network plugin: Cannot parse string value `%s' of the `%s' "
+ "option as boolean value.",
+ str, ci->key);
+ return (-1);
+ }
+ }
- if ((strcasecmp ("Listen", key) == 0)
- || (strcasecmp ("Server", key) == 0))
- {
- char *val_cpy = strdup (val);
- if (val_cpy == NULL)
- return (1);
+ return (0);
+} /* }}} int network_config_set_boolean */
- service = NET_DEFAULT_PORT;
- fields_num = strsplit (val_cpy, fields, 3);
- if ((fields_num != 1)
- && (fields_num != 2))
- {
- sfree (val_cpy);
- return (1);
- }
- else if (fields_num == 2)
- {
- if ((service = strchr (fields[1], '.')) != NULL)
- *service = '\0';
- service = fields[1];
- }
- node = fields[0];
+static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */
+{
+ int tmp;
+ if ((ci->values_num != 1)
+ || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+ {
+ WARNING ("network plugin: The `TimeToLive' config option needs exactly "
+ "one numeric argument.");
+ return (-1);
+ }
- if (strcasecmp ("Listen", key) == 0)
- network_add_listen_socket (node, service);
- else
- network_add_sending_socket (node, service);
+ tmp = (int) ci->values[0].value.number;
+ if ((tmp > 0) && (tmp <= 255))
+ network_config_ttl = tmp;
- sfree (val_cpy);
- }
- else if (strcasecmp ("TimeToLive", key) == 0)
- {
- int tmp = atoi (val);
- if ((tmp > 0) && (tmp < 256))
- network_config_ttl = tmp;
- else
- return (1);
- }
- else if (strcasecmp ("Forward", key) == 0)
- {
- if ((strcasecmp ("true", val) == 0)
- || (strcasecmp ("yes", val) == 0)
- || (strcasecmp ("on", val) == 0))
- network_config_forward = 1;
- else
- network_config_forward = 0;
- }
- else if (strcasecmp ("CacheFlush", key) == 0)
- {
- int tmp = atoi (val);
- if (tmp > 0)
- cache_flush_interval = tmp;
- else return (1);
- }
- else
- {
- return (-1);
- }
- return (0);
-} /* int network_config */
+ return (0);
+} /* }}} int network_config_set_ttl */
+
+#if HAVE_GCRYPT_H
+static int network_config_set_security_level (oconfig_item_t *ci, /* {{{ */
+ int *retval)
+{
+ char *str;
+ if ((ci->values_num != 1)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("network plugin: The `SecurityLevel' config option needs exactly "
+ "one string argument.");
+ return (-1);
+ }
+
+ str = ci->values[0].value.string;
+ if (strcasecmp ("Encrypt", str) == 0)
+ *retval = SECURITY_LEVEL_ENCRYPT;
+ else if (strcasecmp ("Sign", str) == 0)
+ *retval = SECURITY_LEVEL_SIGN;
+ else if (strcasecmp ("None", str) == 0)
+ *retval = SECURITY_LEVEL_NONE;
+ else
+ {
+ WARNING ("network plugin: Unknown security level: %s.", str);
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int network_config_set_security_level */
+#endif /* HAVE_GCRYPT_H */
+
+static int network_config_listen_server (const oconfig_item_t *ci) /* {{{ */
+{
+ char *node;
+ char *service;
+ char *shared_secret = NULL;
+ int security_level = SECURITY_LEVEL_NONE;
+ int i;
+
+ if ((ci->values_num < 1) || (ci->values_num > 2)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING)
+ || ((ci->values_num > 1) && (ci->values[1].type != OCONFIG_TYPE_STRING)))
+ {
+ ERROR ("network plugin: The `%s' config option needs "
+ "one or two string arguments.", ci->key);
+ return (-1);
+ }
+
+ node = ci->values[0].value.string;
+ if (ci->values_num >= 2)
+ service = ci->values[1].value.string;
+ else
+ service = NULL;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+#if HAVE_GCRYPT_H
+ if (strcasecmp ("Secret", child->key) == 0)
+ {
+ if ((child->values_num == 1)
+ && (child->values[0].type == OCONFIG_TYPE_STRING))
+ shared_secret = child->values[0].value.string;
+ else
+ ERROR ("network plugin: The `Secret' option needs exactly one string "
+ "argument.");
+ }
+ else if (strcasecmp ("SecurityLevel", child->key) == 0)
+ network_config_set_security_level (child, &security_level);
+ else
+#endif /* HAVE_GCRYPT_H */
+ {
+ WARNING ("network plugin: Option `%s' is not allowed here.",
+ child->key);
+ }
+ }
+
+ if ((security_level > SECURITY_LEVEL_NONE) && (shared_secret == NULL))
+ {
+ ERROR ("network plugin: A security level higher than `none' was "
+ "requested, but no shared key was given. Cowardly refusing to open "
+ "this socket!");
+ return (-1);
+ }
+
+ if (strcasecmp ("Listen", ci->key) == 0)
+ network_add_listen_socket (node, service, shared_secret, security_level);
+ else
+ network_add_sending_socket (node, service, shared_secret, security_level);
+
+ return (0);
+} /* }}} int network_config_listen_server */
+
+static int network_config_set_cache_flush (const oconfig_item_t *ci) /* {{{ */
+{
+ int tmp;
+ if ((ci->values_num != 1)
+ || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+ {
+ WARNING ("network plugin: The `CacheFlush' config option needs exactly "
+ "one numeric argument.");
+ return (-1);
+ }
-static int network_notification (const notification_t *n)
+ tmp = (int) ci->values[0].value.number;
+ if (tmp > 0)
+ network_config_ttl = tmp;
+
+ return (0);
+} /* }}} int network_config_set_cache_flush */
+
+static int network_config (oconfig_item_t *ci) /* {{{ */
+{
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if ((strcasecmp ("Listen", child->key) == 0)
+ || (strcasecmp ("Server", child->key) == 0))
+ network_config_listen_server (child);
+ else if (strcasecmp ("TimeToLive", child->key) == 0)
+ network_config_set_ttl (child);
+ else if (strcasecmp ("Forward", child->key) == 0)
+ network_config_set_boolean (child, &network_config_forward);
+ else if (strcasecmp ("CacheFlush", child->key) == 0)
+ network_config_set_cache_flush (child);
+ else
+ {
+ WARNING ("network plugin: Option `%s' is not allowed here.",
+ child->key);
+ }
+ }
+
+ return (0);
+} /* }}} int network_config */
+
+static int network_notification (const notification_t *n,
+ user_data_t __attribute__((unused)) *user_data)
{
char buffer[BUFF_SIZE];
char *buffer_ptr = buffer;
listen_loop++;
/* Kill the listening thread */
- if (receive_thread_id != (pthread_t) 0)
+ if (receive_thread_running != 0)
{
+ INFO ("network plugin: Stopping receive thread.");
pthread_kill (receive_thread_id, SIGTERM);
pthread_join (receive_thread_id, NULL /* no return value */);
- receive_thread_id = (pthread_t) 0;
+ memset (&receive_thread_id, 0, sizeof (receive_thread_id));
+ receive_thread_running = 0;
}
/* Shutdown the dispatching thread */
- if (dispatch_thread_id != (pthread_t) 0)
+ if (dispatch_thread_running != 0)
+ {
+ INFO ("network plugin: Stopping dispatch thread.");
+ pthread_mutex_lock (&receive_list_lock);
pthread_cond_broadcast (&receive_list_cond);
+ pthread_mutex_unlock (&receive_list_lock);
+ pthread_join (dispatch_thread_id, /* ret = */ NULL);
+ dispatch_thread_running = 0;
+ }
+
+ free_sockent (listen_sockets);
if (send_buffer_fill > 0)
flush_buffer ();
plugin_register_shutdown ("network", network_shutdown);
- send_buffer_ptr = send_buffer;
- send_buffer_fill = 0;
- memset (&send_buffer_vl, 0, sizeof (send_buffer_vl));
+ network_init_buffer ();
cache_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
cache_flush_last = time (NULL);
/* setup socket(s) and so on */
if (sending_sockets != NULL)
{
- plugin_register_write ("network", network_write);
- plugin_register_notification ("network", network_notification);
+ plugin_register_write ("network", network_write,
+ /* user_data = */ NULL);
+ plugin_register_notification ("network", network_notification,
+ /* user_data = */ NULL);
}
- if ((listen_sockets_num != 0) && (receive_thread_id == 0))
+ /* If no threads need to be started, return here. */
+ if ((listen_sockets_num == 0)
+ || ((dispatch_thread_running != 0)
+ && (receive_thread_running != 0)))
+ return (0);
+
+ if (dispatch_thread_running == 0)
{
int status;
-
status = pthread_create (&dispatch_thread_id,
NULL /* no attributes */,
dispatch_thread,
sstrerror (errno, errbuf,
sizeof (errbuf)));
}
+ else
+ {
+ dispatch_thread_running = 1;
+ }
+ }
+ if (receive_thread_running == 0)
+ {
+ int status;
status = pthread_create (&receive_thread_id,
NULL /* no attributes */,
receive_thread,
sstrerror (errno, errbuf,
sizeof (errbuf)));
}
+ else
+ {
+ receive_thread_running = 1;
+ }
}
+
return (0);
} /* int network_init */
* there, good. If not, well, then there is nothing to flush.. -octo
*/
static int network_flush (int timeout,
- const char __attribute__((unused)) *identifier)
+ const char __attribute__((unused)) *identifier,
+ user_data_t __attribute__((unused)) *user_data)
{
pthread_mutex_lock (&send_buffer_lock);
void module_register (void)
{
- plugin_register_config ("network", network_config,
- config_keys, config_keys_num);
+ plugin_register_complex_config ("network", network_config);
plugin_register_init ("network", network_init);
- plugin_register_flush ("network", network_flush);
+ plugin_register_flush ("network", network_flush,
+ /* user_data = */ NULL);
} /* void module_register */
+
+/* vim: set fdm=marker : */