From 221784cd3d9290ac798c7974827eb153c10cfcb9 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 31 Mar 2008 16:32:56 +0000 Subject: bumping version number --- ChangeLog | 3 +++ configure.ac | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 8f3499c9..15de452f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ --------------------------------------------------------------------------- +Version 3.17.0 (rgerhards), 2008-04-?? +- FEATURE FOCUS for 3.17 is TLS over plain TCP syslog +--------------------------------------------------------------------------- Version 3.13.0-dev0 (rgerhards), 2008-03-31 - bugfix: accidently set debug option in 3.12.5 reset to production This option prevented dlclose() to be called. It had no real bad effects, diff --git a/configure.ac b/configure.ac index 04ec3db5..7ea97864 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([rsyslog],[3.13.0-dev0],[rsyslog@lists.adiscon.com]) +AC_INIT([rsyslog],[3.17.0],[rsyslog@lists.adiscon.com]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([syslogd.c]) AC_CONFIG_HEADERS([config.h]) -- cgit From f47593555554b1aae62a6395d6bf3bb3d2eb61eb Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 31 Mar 2008 16:53:18 +0000 Subject: added configure checks for openssl --- configure.ac | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/configure.ac b/configure.ac index 7ea97864..d09ee302 100644 --- a/configure.ac +++ b/configure.ac @@ -413,6 +413,42 @@ AC_SUBST(libdbi_cflags) AC_SUBST(libdbi_libs) +# openssl support +AC_ARG_ENABLE(openssl, + [AS_HELP_STRING([--enable-openssl],[Enable openssl support @<:@default=yes@:>@])], + [case "${enableval}" in + yes) enable_openssl="yes" ;; + no) enable_openssl="no" ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-openssl) ;; + esac], + [enable_openssl=no] +) +if test "x$enable_openssl" = "xyes"; then + AC_CHECK_HEADERS( + [openssl/ssl.h],, + [AC_MSG_FAILURE([openssl is missing])] + ) + AC_CHECK_LIB( + [crypto], + [CRYPTO_new_ex_data], + [openssl_cflags="" + openssl_libs="-lcrypto" + ], + [AC_MSG_FAILURE([library 'crypto' is missing (needed for openssl)])] + ) + AC_CHECK_LIB( + [ssl], + [SSL_library_init], + [ openssl_libs+="-lssl" + ], + [AC_MSG_FAILURE([library 'ssl' is missing (needed for openssl)])] + ) +fi +AM_CONDITIONAL(ENABLE_OPENSSL, test x$enable_openssl = xyes) +AC_SUBST(openssl_cflags) +AC_SUBST(openssl_libs) + + # SNMP support AC_ARG_ENABLE(snmp, [AS_HELP_STRING([--enable-snmp],[Enable SNMP support @<:@default=no@:>@])], @@ -599,6 +635,7 @@ echo "Networking support enabled: $enable_inet" echo "Enable GSSAPI Kerberos 5 support: $want_gssapi_krb5" echo "Debug mode enabled: $enable_debug" echo "Runtime Instrumentation enabled: $enable_rtinst" +echo "openssl enabled: $enable_openssl" echo "valgrind support settings enabled: $enable_valgrind" echo "rsyslogd will be built: $enable_rsyslogd" -- cgit From ca77f716a3f0acefecee24a4283b351f0832151d Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 31 Mar 2008 16:55:09 +0000 Subject: cleanup --- tcpsrv.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/tcpsrv.c b/tcpsrv.c index adbe26e0..ae5f3371 100644 --- a/tcpsrv.c +++ b/tcpsrv.c @@ -141,32 +141,6 @@ configureTCPListen(tcpsrv_t *pThis, char *cOptarg) } -#if 0 // I think this is no longer needed -static void -configureTCPListenSessMax(char *cOptarg) -{ - register int i; - register char *pArg = cOptarg; - - assert(cOptarg != NULL); - - /* number of sessions */ - i = 0; - while(isdigit((int) *pArg)) { - i = i * 10 + *pArg++ - '0'; - } - - if(i > 0) - pThis->iSessMax = i; - else { - /* too small, need to adjust */ - errmsg.LogError(NO_ERRCODE, "TCP session max configured to %s - changing to 1.\n", cOptarg); - pThis->iSessMax = 1; - } -} -#endif - - /* Initialize the session table * returns 0 if OK, somewhat else otherwise */ -- cgit From 2c2f1022b0d4bed360f41f67a9fb9edf8fe91c2f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 1 Apr 2008 07:18:46 +0000 Subject: - bugfix: rsyslogd was no longer build by default; man pages are only installed if corresponding option is selected. Thanks to Michael Biebl for pointing these problems out. --- ChangeLog | 3 +++ Makefile.am | 7 +++++-- configure.ac | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 15de452f..7aefd39f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ --------------------------------------------------------------------------- Version 3.17.0 (rgerhards), 2008-04-?? - FEATURE FOCUS for 3.17 is TLS over plain TCP syslog +- bugfix: rsyslogd was no longer build by default; man pages are + only installed if corresponding option is selected. Thanks to + Michael Biebl for pointing these problems out. --------------------------------------------------------------------------- Version 3.13.0-dev0 (rgerhards), 2008-03-31 - bugfix: accidently set debug option in 3.12.5 reset to production diff --git a/Makefile.am b/Makefile.am index 99f542fb..eb0497a6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,6 @@ #sbin_PROGRAMS = rfc3195d rsyslogd sbin_PROGRAMS = +man_MANS = if ENABLE_RSYSLOGD sbin_PROGRAMS += rsyslogd @@ -94,6 +95,9 @@ rsyslogd_SOURCES = \ rsyslogd_CPPFLAGS = -D_PATH_MODDIR=\"$(pkglibdir)/\" $(pthreads_cflags) rsyslogd_LDADD = $(zlib_libs) $(pthreads_libs) $(dl_libs) $(rt_libs) rsyslogd_LDFLAGS = -export-dynamic + +man_MANS += rsyslogd.8 rsyslog.conf.5 + endif # if ENABLE_RSYSLOGD # now come the library plugins @@ -103,6 +107,7 @@ if ENABLE_RFC3195 # this does so far not work - a manual build is needed sbin_PROGRAMS += rfc3195d rfc3195d_SOURCES = rfc3195d.c rsyslog.h +man_MANS += rfc3195d.8 endif @@ -173,8 +178,6 @@ lmrelputil_la_LDFLAGS = -module -avoid-version lmrelputil_la_LIBADD = $(relp_libs) endif -man_MANS = rfc3195d.8 rsyslogd.8 rsyslog.conf.5 - EXTRA_DIST = \ redhat/rsyslog.conf \ redhat/rsyslog.init \ diff --git a/configure.ac b/configure.ac index d09ee302..c45ba862 100644 --- a/configure.ac +++ b/configure.ac @@ -486,7 +486,7 @@ AC_ARG_ENABLE(rsyslogd, no) enable_rsyslogd="no" ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-rsyslogd) ;; esac], - [enable_rsyslogd=no] + [enable_rsyslogd=yes] ) AM_CONDITIONAL(ENABLE_RSYSLOGD, test x$enable_rsyslogd = xyes) -- cgit From d853a3f7cdff6f80fbfc45f7a9a7ab8209046884 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 1 Apr 2008 17:07:41 +0000 Subject: added im/omrelp doc --- doc/imrelp.html | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ doc/omrelp.html | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ doc/rsyslog_conf.html | 4 ++-- 3 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 doc/imrelp.html create mode 100644 doc/omrelp.html diff --git a/doc/imrelp.html b/doc/imrelp.html new file mode 100644 index 00000000..b6f1f2bc --- /dev/null +++ b/doc/imrelp.html @@ -0,0 +1,52 @@ + + +RELP Input Module + + + +

RELP Input Module

+

Module Name:    imrelp

+

Author: Rainer Gerhards

+

Description:

+

Provides the ability to receive syslog messages via the +reliable RELP protocol. This module requires librelp to be +present on the system. From the user's point of view, imrelp works much +like imtcp or imgssapi, except that no message loss can occur. Please +note that with the currently supported relp protocol version, a minor +message duplication may occur if a network connection between the relp +client and relp server breaks after the client could successfully send +some messages but the server could not acknowledge them. The window of +opportunity is very slim, but in theory this is possible. Future +versions of RELP will prevent this. Please also note that rsyslogd may +lose a few messages if rsyslog is shutdown while a network conneciton +to the server is broken and could not yet be recovered. Future version +of RELP support in rsyslog will prevent that. Please note that both +scenarios also exists with plain tcp syslog. RELP, even with the small +nits outlined above, is a much more reliable solution than plain tcp +syslog and so it is highly suggested to use RELP instead of plain tcp. +Clients send messages to the RELP server via omrelp.

+

Configuration Directives:

+
    +
  • InputRELPServerRun <port>
    +Starts a RELP server on selected port
  • +
+Caveats/Known Bugs: +
    +
  • see description
  • +
+

Sample:

+

This sets up a RELP server on port 2514.
+

+ +

[rsyslog.conf overview] +[manual index] [rsyslog site]

+

This documentation is part of the +rsyslog +project.
+Copyright © 2008 by Rainer +Gerhards and +Adiscon. +Released under the GNU GPL version 3 or higher.

+ \ No newline at end of file diff --git a/doc/omrelp.html b/doc/omrelp.html new file mode 100644 index 00000000..0952cc71 --- /dev/null +++ b/doc/omrelp.html @@ -0,0 +1,54 @@ + + +RELP Output Module (omrelp) + + + +

RELP Output Module (omlibdbi)

+

Module Name:    omrelp

+

Author: Rainer Gerhards +<rgerhards@adiscon.com>

+

Description:

+

This module supports sending syslog messages over the reliable +RELP protocol. For RELP's advantages over plain tcp syslog, please see +the documentation for imrelp +(the server counterpart). 

+Setup +

Please note the librelp +is required for imrelp (it provides the core relp protocol +implementation).

+

Configuration Directives:

+

This module uses old-style action configuration to keep +consistent with the forwarding rule. So far, no additional +configuration directives can be specified. To send a message via RELP, +use

+

*.* + :omrelp:<sever>:<port>;<template>

+

just as you use 

+

*.* + @@<sever>:<port>;<template>

+

to forward a message via plain tcp syslog.

+Caveats/Known Bugs: +

See imrelp, +which documents them. 

+

Sample:

+

The following sample sends all messages to the central server +"centralserv" at port 2514 (note that that server must run imrelp on +port 2514). Rsyslog's high-precision timestamp format is used, thus the +special "RSYSLOG_ForwardFormat" (case sensitive!) template is used.
+

+ +

[rsyslog.conf overview] +[manual index] [rsyslog site]

+

This documentation is part of the +rsyslog +project.
+Copyright © 2008 by Rainer +Gerhards and +Adiscon. +Released under the GNU GPL version 3 or higher.

+ \ No newline at end of file diff --git a/doc/rsyslog_conf.html b/doc/rsyslog_conf.html index 5931a241..2a0f0c60 100644 --- a/doc/rsyslog_conf.html +++ b/doc/rsyslog_conf.html @@ -26,7 +26,7 @@ number of modules. Here is the entry point to their documentation and what they do (list is currently not complete)

  • omsnmp - SNMP -trap output module
  • omrelp - RELP output module
  • +trap output module
  • omrelp - RELP output module
  • omgss - output module for GSS-enabled syslog
  • ommysql - output module for MySQL
  • ompgsql - output module for PostgreSQL
  • @@ -34,7 +34,7 @@ trap output module
  • omrelp - RELP output module
  • generic database output module (Firebird/Interbase, MS SQL, Sybase, SQLLite, Ingres, Oracle, mSQL)
  • imfile --  input module for text files
  • imrelp - RELP input module
  • +-  input module for text files
  • imrelp - RELP input module
  • imudp - udp syslog message input
  • imtcp - input plugin for plain tcp syslog
  • -- cgit From 6f55976501ac7ab314b6f96522ed73601fef5d93 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 2 Apr 2008 06:54:42 +0000 Subject: included info on 3.15.0 release --- ChangeLog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7aefd39f..f044fb63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,13 @@ --------------------------------------------------------------------------- Version 3.17.0 (rgerhards), 2008-04-?? - FEATURE FOCUS for 3.17 is TLS over plain TCP syslog +--------------------------------------------------------------------------- +Version 3.15.0 (rgerhards), 2008-04-01 +- major new feature: imrelp/omrelp support reliable delivery of syslog + messages via the RELP protocol and librelp (http://www.librelp.com). + Plain tcp syslog, so far the best reliability solution, can lose + messages when something goes wrong or a peer goes down. With RELP, + this can no longer happen. See imrelp.html for more details. - bugfix: rsyslogd was no longer build by default; man pages are only installed if corresponding option is selected. Thanks to Michael Biebl for pointing these problems out. -- cgit From 931ce19540b10322b04e6e8c2107c63f361aae56 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 2 Apr 2008 07:04:16 +0000 Subject: disabled atomic operations for the time being because they introduce some cross-platform trouble - need to see how to fix this in the best possible way --- ChangeLog | 7 +++++++ atomic.h | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f044fb63..202ed851 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,13 @@ Version 3.15.0 (rgerhards), 2008-04-01 only installed if corresponding option is selected. Thanks to Michael Biebl for pointing these problems out. --------------------------------------------------------------------------- +Version 3.14.0 (rgerhards), 2008-04-02 +- bugfix: rsyslogd was no longer build by default; man pages are + only installed if corresponding option is selected. Thanks to + Michael Biebl for pointing these problems out. +- disabled atomic operations for this stable build as it caused + platform problems +--------------------------------------------------------------------------- Version 3.13.0-dev0 (rgerhards), 2008-03-31 - bugfix: accidently set debug option in 3.12.5 reset to production This option prevented dlclose() to be called. It had no real bad effects, diff --git a/atomic.h b/atomic.h index 1883e030..2421c826 100644 --- a/atomic.h +++ b/atomic.h @@ -36,8 +36,15 @@ #define INCLUDED_ATOMIC_H /* set the following to 1 if we have atomic operations (and #undef it otherwise) */ -#define DO_HAVE_ATOMICS 1 +/* #define DO_HAVE_ATOMICS 1 */ +/* for this release, we disable atomic calls because there seem to be some + * portability problems and we can not fix that without destabilizing the build. + * They simply came in too late. -- rgerhards, 2008-04-02 + */ +/* make sure they are not used! #define ATOMIC_INC(data) ((void) __sync_fetch_and_add(&data, 1)) #define ATOMIC_DEC_AND_FETCH(data) __sync_sub_and_fetch(&data, 1) +*/ +#define ATOMIC_INC(data) (++(data)) #endif /* #ifndef INCLUDED_ATOMIC_H */ -- cgit From 7e4785e72b17b8fff26f536342457ceee02d39a0 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 2 Apr 2008 07:58:09 +0000 Subject: added librelp check via PKG_CHECK thanks to Michael Biebl's patch --- Makefile.am | 4 ++-- configure.ac | 21 +++------------------ plugins/imrelp/Makefile.am | 4 ++-- plugins/omrelp/Makefile.am | 4 ++-- 4 files changed, 9 insertions(+), 24 deletions(-) diff --git a/Makefile.am b/Makefile.am index eb0497a6..4e886128 100644 --- a/Makefile.am +++ b/Makefile.am @@ -173,9 +173,9 @@ endif if ENABLE_RELP pkglib_LTLIBRARIES += lmrelputil.la lmrelputil_la_SOURCES = relputil.c relputil.h -lmrelputil_la_CPPFLAGS = $(pthreads_cflags) $(relp_cflags) +lmrelputil_la_CPPFLAGS = $(pthreads_cflags) $(RELP_CFLAGS) lmrelputil_la_LDFLAGS = -module -avoid-version -lmrelputil_la_LIBADD = $(relp_libs) +lmrelputil_la_LIBADD = $(RELP_LIBS) endif EXTRA_DIST = \ diff --git a/configure.ac b/configure.ac index c45ba862..8b407ccf 100644 --- a/configure.ac +++ b/configure.ac @@ -502,26 +502,11 @@ AC_ARG_ENABLE(relp, [enable_relp=no] ) if test "x$enable_relp" = "xyes"; then - AC_CHECK_HEADERS( - [librelp.h],, - [AC_MSG_FAILURE([RELP library is missing (no headers)])] - ) -# I don't know how to tell that librelp needs -lrt, so I disable -# this check for now - the header check should work well enough... -# rgerhards, 2008-03-25 -# AC_CHECK_LIB( -# [relp], -# [relpEngineGetVersion], -# [relp_cflags="" - relp_libs="-lrelp" -# ], -# [AC_MSG_FAILURE([RELP library is missing])] -# ) + PKG_CHECK_MODULES(RELP, relp >= 0.1.1) fi AM_CONDITIONAL(ENABLE_RELP, test x$enable_relp = xyes) -AC_SUBST(relp_cflags) -AC_SUBST(relp_libs) - +AC_SUBST(RELP_CFLAGS) +AC_SUBST(RELP_LIBS) # RFC 3195 support # WARNING: THIS IS NOT REALLY PRESENT YET - needs to be build manually! diff --git a/plugins/imrelp/Makefile.am b/plugins/imrelp/Makefile.am index 167065b0..53c9322c 100644 --- a/plugins/imrelp/Makefile.am +++ b/plugins/imrelp/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = imrelp.la imrelp_la_SOURCES = imrelp.c -imrelp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(relp_cflags) +imrelp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(RELP_CFLAGS) imrelp_la_LDFLAGS = -module -avoid-version -imrelp_la_LIBADD = $(relp_libs) +imrelp_la_LIBADD = $(RELP_LIBS) diff --git a/plugins/omrelp/Makefile.am b/plugins/omrelp/Makefile.am index edec5de9..dfc2111f 100644 --- a/plugins/omrelp/Makefile.am +++ b/plugins/omrelp/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = omrelp.la omrelp_la_SOURCES = omrelp.c -omrelp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(relp_cflags) +omrelp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(RELP_CFLAGS) omrelp_la_LDFLAGS = -module -avoid-version -omrelp_la_LIBADD = $(relp_libs) +omrelp_la_LIBADD = $(RELP_LIBS) -- cgit From ff790810517ce193efab3841ae51330f7c1a72bc Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 2 Apr 2008 08:17:40 +0000 Subject: removed no longer needed file relptuil.c/.h --- ChangeLog | 1 + Makefile.am | 11 ----------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 202ed851..3d5be4d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ --------------------------------------------------------------------------- Version 3.17.0 (rgerhards), 2008-04-?? - FEATURE FOCUS for 3.17 is TLS over plain TCP syslog +- removed no longer needed file relptuil.c/.h --------------------------------------------------------------------------- Version 3.15.0 (rgerhards), 2008-04-01 - major new feature: imrelp/omrelp support reliable delivery of syslog diff --git a/Makefile.am b/Makefile.am index 4e886128..f97687c1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -167,17 +167,6 @@ lmgssutil_la_LDFLAGS = -module -avoid-version lmgssutil_la_LIBADD = $(gss_libs) endif -# -# relp support -# -if ENABLE_RELP -pkglib_LTLIBRARIES += lmrelputil.la -lmrelputil_la_SOURCES = relputil.c relputil.h -lmrelputil_la_CPPFLAGS = $(pthreads_cflags) $(RELP_CFLAGS) -lmrelputil_la_LDFLAGS = -module -avoid-version -lmrelputil_la_LIBADD = $(RELP_LIBS) -endif - EXTRA_DIST = \ redhat/rsyslog.conf \ redhat/rsyslog.init \ -- cgit From 24c5e87b82a655ac7556f66f4d1cec8c3fe9ee2a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 2 Apr 2008 12:34:20 +0000 Subject: added more meaningful error messages to rsyslogd (when some errors happens during startup) --- ChangeLog | 9 +++++++++ conf.c | 2 +- modules.c | 10 +++++----- rsyslog.h | 5 +++++ syslogd.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 60 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3d5be4d6..55412458 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,15 @@ Version 3.17.0 (rgerhards), 2008-04-?? - FEATURE FOCUS for 3.17 is TLS over plain TCP syslog - removed no longer needed file relptuil.c/.h --------------------------------------------------------------------------- +Version 3.15.1 (rgerhards), 2008-04-?? +- disabled atomic operations for the time being because they introduce some + cross-platform trouble - need to see how to fix this in the best + possible way +- added librelp check via PKG_CHECK thanks to Michael Biebl's patch +- file relputil.c deleted, is not actually needed +- added more meaningful error messages to rsyslogd (when some errors + happens during startup) +--------------------------------------------------------------------------- Version 3.15.0 (rgerhards), 2008-04-01 - major new feature: imrelp/omrelp support reliable delivery of syslog messages via the RELP protocol and librelp (http://www.librelp.com). diff --git a/conf.c b/conf.c index f3f10ba3..14e73f0e 100644 --- a/conf.c +++ b/conf.c @@ -1199,7 +1199,7 @@ BEGINAbstractObjClassInit(conf, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANG CHKiRet(objUse(ctok, CORE_COMPONENT)); CHKiRet(objUse(module, CORE_COMPONENT)); CHKiRet(objUse(errmsg, CORE_COMPONENT)); - CHKiRet(objUse(net, LM_NET_FILENAME)); + CHKiRet(objUse(net, LM_NET_FILENAME)); /* TODO: make this dependcy go away! */ ENDObjClassInit(conf) /* vi:set ai: diff --git a/modules.c b/modules.c index b6164f91..86ee64a5 100644 --- a/modules.c +++ b/modules.c @@ -594,7 +594,7 @@ Load(uchar *pModName) } else { errmsg.LogError(NO_ERRCODE, "could not load module '%s', path too long\n", pModName); free(pModNameDup); - ABORT_FINALIZE(RS_RET_ERR); + ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_PATHLEN); } } } @@ -619,24 +619,24 @@ Load(uchar *pModName) if(iPathLen + strlen((char*) pModName) >= sizeof(szPath)) { errmsg.LogError(NO_ERRCODE, "could not load module '%s', path too long\n", pModName); - ABORT_FINALIZE(RS_RET_ERR); + ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_PATHLEN); } /* complete load path constructed, so ... GO! */ dbgprintf("loading module '%s'\n", szPath); if(!(pModHdlr = dlopen((char *) szPath, RTLD_NOW))) { errmsg.LogError(NO_ERRCODE, "could not load module '%s', dlopen: %s\n", szPath, dlerror()); - ABORT_FINALIZE(RS_RET_ERR); + ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_DLOPEN); } if(!(pModInit = dlsym(pModHdlr, "modInit"))) { errmsg.LogError(NO_ERRCODE, "could not load module '%s', dlsym: %s\n", szPath, dlerror()); dlclose(pModHdlr); - ABORT_FINALIZE(RS_RET_ERR); + ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_NO_INIT); } if((iRet = doModInit(pModInit, (uchar*) pModName, pModHdlr)) != RS_RET_OK) { errmsg.LogError(NO_ERRCODE, "could not load module '%s', rsyslog error %d\n", szPath, iRet); dlclose(pModHdlr); - ABORT_FINALIZE(RS_RET_ERR); + ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_INIT_FAILED); } finalize_it: diff --git a/rsyslog.h b/rsyslog.h index 01329aaf..9fe162d5 100644 --- a/rsyslog.h +++ b/rsyslog.h @@ -162,6 +162,11 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_OBJ_ALREADY_REGISTERED = -2061, /**< object (name) is already registered */ RS_RET_OBJ_REGISTRY_OUT_OF_SPACE = -2062, /**< the object registry has run out of space */ RS_RET_HOST_NOT_PERMITTED = -2063, /**< a host is not permitted to perform an action it requested */ + RS_RET_MODULE_LOAD_ERR = -2064, /**< module could not be loaded */ + RS_RET_MODULE_LOAD_ERR_PATHLEN = -2065, /**< module could not be loaded - path to long */ + RS_RET_MODULE_LOAD_ERR_DLOPEN = -2066, /**< module could not be loaded - problem in dlopen() */ + RS_RET_MODULE_LOAD_ERR_NO_INIT = -2067, /**< module could not be loaded - init() missing */ + RS_RET_MODULE_LOAD_ERR_INIT_FAILED = -2068, /**< module could not be loaded - init() failed */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ diff --git a/syslogd.c b/syslogd.c index 1c31fb61..8c71f57d 100644 --- a/syslogd.c +++ b/syslogd.c @@ -2828,11 +2828,15 @@ static rsRetVal InitGlobalClasses(void) { DEFiRet; + char *pErrObj; /* tells us which object failed if that happens (useful for troubleshooting!) */ + pErrObj = "obj"; CHKiRet(objClassInit(NULL)); /* *THIS* *MUST* always be the first class initilizer being called! */ CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */ /* the following classes were intialized by objClassInit() */ + pErrObj = "errmsg"; CHKiRet(objUse(errmsg, CORE_COMPONENT)); + pErrObj = "module"; CHKiRet(objUse(module, CORE_COMPONENT)); /* initialize and use classes. We must be very careful with the order of events. Some @@ -2843,35 +2847,61 @@ InitGlobalClasses(void) * class immediately after it is initialized. And, of course, we load those classes * first that we use ourselfs... -- rgerhards, 2008-03-07 */ + pErrObj = "datetime"; CHKiRet(datetimeClassInit(NULL)); CHKiRet(objUse(datetime, CORE_COMPONENT)); + pErrObj = "msg"; CHKiRet(msgClassInit(NULL)); + pErrObj = "str,"; CHKiRet(strmClassInit(NULL)); + pErrObj = "wti"; CHKiRet(wtiClassInit(NULL)); + pErrObj = "wtp"; CHKiRet(wtpClassInit(NULL)); + pErrObj = "queue"; CHKiRet(queueClassInit(NULL)); + pErrObj = "vmstk"; CHKiRet(vmstkClassInit(NULL)); + pErrObj = "sysvar"; CHKiRet(sysvarClassInit(NULL)); + pErrObj = "vm"; CHKiRet(vmClassInit(NULL)); CHKiRet(objUse(vm, CORE_COMPONENT)); + pErrObj = "vmop"; CHKiRet(vmopClassInit(NULL)); + pErrObj = "vmprg"; CHKiRet(vmprgClassInit(NULL)); + pErrObj = "ctok_token"; CHKiRet(ctok_tokenClassInit(NULL)); + pErrObj = "ctok"; CHKiRet(ctokClassInit(NULL)); + pErrObj = "expr"; CHKiRet(exprClassInit(NULL)); CHKiRet(objUse(expr, CORE_COMPONENT)); + pErrObj = "conf"; CHKiRet(confClassInit(NULL)); CHKiRet(objUse(conf, CORE_COMPONENT)); /* dummy "classes" */ + pErrObj = "action"; CHKiRet(actionClassInit()); + pErrObj = "template"; CHKiRet(templateInit()); + pErrObj = "str"; CHKiRet(strInit()); /* TODO: the dependency on net shall go away! -- rgerhards, 2008-03-07 */ + pErrObj = "net"; CHKiRet(objUse(net, LM_NET_FILENAME)); finalize_it: + if(iRet != RS_RET_OK) { + /* we know we are inside the init sequence, so we can safely emit + * messages to stderr. -- rgerhards, 2008-04-02 + */ + fprintf(stderr, "Error during class init for object '%s' - failing...\n", pErrObj); + } + RETiRet; } @@ -2957,7 +2987,14 @@ int realMain(int argc, char **argv) int bImUxSockLoaded = 0; /* already generated a $ModLoad imuxsock? */ uchar legacyConfLine[80]; - CHKiRet(InitGlobalClasses()); + + CHKiRet_Hdlr(InitGlobalClasses()) { + fprintf(stderr, "rsyslogd initializiation failed - global classes could not be initialized.\n" + "Did you do a \"make install\"?\n" + "Suggested action: run rsyslogd with -d -n options to see what exactly " + "fails.\n"); + FINALIZE; + } /* doing some core initializations */ if((iRet = modInitIminternal()) != RS_RET_OK) { @@ -3298,7 +3335,8 @@ int realMain(int argc, char **argv) finalize_it: if(iRet != RS_RET_OK) - fprintf(stderr, "rsyslogd run failed with error %d.\n", iRet); + fprintf(stderr, "rsyslogd run failed with error %d\n(see rsyslog.h " + "or http://www.rsyslog.com/errcode to learn what that number means)\n", iRet); ENDfunc return 0; -- cgit From 38f0cd67626ce56b0014b05b513e2e573da25e6f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 2 Apr 2008 13:11:04 +0000 Subject: updated status informatation and syslog-ng comparison --- doc/rsyslog_ng_comparison.html | 178 +++++++++++++++++++++++++---------------- doc/status.html | 24 ++++-- 2 files changed, 124 insertions(+), 78 deletions(-) diff --git a/doc/rsyslog_ng_comparison.html b/doc/rsyslog_ng_comparison.html index 547501af..2a1d15bd 100644 --- a/doc/rsyslog_ng_comparison.html +++ b/doc/rsyslog_ng_comparison.html @@ -1,6 +1,8 @@ -rsyslog vs. syslog-ng - a comparison +rsyslog vs. syslog-ng - a comparison + +

    rsyslog vs. syslog-ng

    Written by Rainer Gerhards @@ -25,56 +27,72 @@ comparison sheet, so please don't be shy ;)

    rsyslog syslog-ng - - -
    Input Sources
    +
    +Input Sources
    + -UNIX domain socket + +UNIX domain socket +yes yes -yes - + + UDP yes -yes - +yes + + TCP yes -yes - +yes + + + +RELP +yes +no + + RFC 3195/BEEP yes (needs separate build process) -no - +no + + kernel log yes -yes - +yes + + file yes -yes - +yes + + -mark message generator as an optional input +mark message generator as an +optional input yes -no (?) - +no (?) + + Windows Event Log via EventReporter or MonitorWare Agent (both commercial software) -via separate Windows agent, paid edition only +via separate Windows agent, paid +edition only - - -
    Network (Protocol) Support

    +
    +Network (Protocol) Support

    + support for (plain) tcp based syslog @@ -104,6 +122,11 @@ based framing on syslog/tcp connections yes +syslog over RELP
    this is a truely reliable solution (plain tcp syslog can lose messages!) +yes +no + + on the wire (zlib) message compression yes @@ -146,38 +169,46 @@ hostname in NAT environments and relay chains yes yes - - -
    Message Filtering
    +
    +Message Filtering
    + -Filtering for syslog facility and priority + +Filtering for syslog facility and +priority yes -yes - +yes + + Filtering for hostname yes -yes - +yes + + Filtering for application yes -yes - +yes + + Filtering for message contents yes -yes - +yes + + Filtering for sending IP address yes -yes - +yes + + -ability to filter on any other message -field not mentioned above +ability to filter on any other +message +field not mentioned above (including substrings and the like) yes no @@ -210,8 +241,9 @@ in filters support for discarding messages based on filters yes -yes - +yes + + powerful BSD-style hostname and program name blocks for easy multi-host support @@ -223,10 +255,10 @@ program name blocks for easy multi-host support - - -
    Supported Database Outputs
    +
    +Supported Database Outputs
    + MySQL @@ -274,10 +306,10 @@ program name blocks for easy multi-host support yes (omlibdbi) no (?) - - -
    Enterprise Features
    +
    +Enterprise Features
    + support for on-demand on-disk @@ -292,7 +324,8 @@ by spool files yes -each action can use its own, independant +each action can use its own, +independant set of spool files yes no @@ -314,10 +347,10 @@ syslog/database servers yes yes - - -
    Config File
    +
    +Config File
    + config file format @@ -338,37 +371,40 @@ existing in a specific directory yes no - - - -
    Extensibility
    +
    +Extensibility
    + -Functionality split in separately loadable +Functionality split in separately +loadable modules yes no -Support for third-party input plugins +Support for third-party input +plugins yes no -Support for third-party output plugins + +Support for third-party output +plugins yes no - - - -
    Other Features
    +
    +Other Features
    + + + - ability to generate file names and directories (log targets) dynamically yes @@ -440,8 +476,9 @@ reduction ("last message repeated n times") on a per selector-line basis supports multiple actions per selector/filter condition yes -yes - +yes + + web interface phpLogCon
    @@ -469,8 +506,11 @@ system stress flow control (slow down message reception when system is busy) -yes (advanced, with multiple ways to slow down inputs depending on individual input capabilities, based on watermarks) -yes (limited? "stops accepting messages") +yes (advanced, +with multiple ways to slow down inputs depending on individual input +capabilities, based on watermarks) +yes (limited? +"stops accepting messages") rewriting messages @@ -504,8 +544,6 @@ Solaris; compilation and basic testing done on HP UX no yes - -

    While the rsyslog diff --git a/doc/status.html b/doc/status.html index c6901fb9..bfced290 100644 --- a/doc/status.html +++ b/doc/status.html @@ -2,18 +2,26 @@ rsyslog status page

    rsyslog status page

    -

    This page reflects the status as of 2008-03-31.

    +

    This page reflects the status as of 2008-04-02.

    Current Releases

    -

    development: 3.13.0-dev0 - -change log - -download

    +

    development: 3.15.0 - +change log - +download

    + +

    v3 stable: 3.14.0 - change log - +download + +
    v2 stable: 2.0.4 - change log - +download +
    v0 and v1 are depricated and no longer supported. If you absolutely do not like to +upgrade, you may consider purchasing a +commercial rsyslog support package. Just let us point +out that it is really not a good idea to still run a v0 version. +

    If you updgrade from version 2, be sure to read the rsyslog v3 compatibility document.

    - -

    stable: 2.0.4 - change log - -download

    -

     (How are versions named?)

    +

    (How are versions named?)

    Platforms

    Thankfully, a number of folks have begin to build packages and -- cgit From 9b48c4a481c64503605f25e1d0648d24f43437f1 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 2 Apr 2008 16:53:29 +0000 Subject: begun working on time-window based dequeueing (and rate limiting in general) --- doc/rsyslog_ng_comparison.html | 2 +- queue.c | 57 ++++++++++++++++++++++++++++++++++++++++++ queue.h | 13 +++++++++- wti.c | 8 ++++++ wtp.c | 1 + wtp.h | 1 + 6 files changed, 80 insertions(+), 2 deletions(-) diff --git a/doc/rsyslog_ng_comparison.html b/doc/rsyslog_ng_comparison.html index 2a1d15bd..852ab4ed 100644 --- a/doc/rsyslog_ng_comparison.html +++ b/doc/rsyslog_ng_comparison.html @@ -122,7 +122,7 @@ based framing on syslog/tcp connections yes -syslog over RELP
    this is a truely reliable solution (plain tcp syslog can lose messages!) +syslog over RELP
    truly reliable message delivery (Why is plain tcp syslog not reliable?) yes no diff --git a/queue.c b/queue.c index ed720c55..bfdac204 100644 --- a/queue.c +++ b/queue.c @@ -55,6 +55,7 @@ DEFobjStaticHelpers /* forward-definitions */ rsRetVal queueChkPersist(queue_t *pThis); static rsRetVal queueSetEnqOnly(queue_t *pThis, int bEnqOnly, int bLockMutex); +static rsRetVal queueRateLimiter(queue_t *pThis); static int queueChkStopWrkrDA(queue_t *pThis); static int queueIsIdleDA(queue_t *pThis); static rsRetVal queueConsumerDA(queue_t *pThis, wti_t *pWti, int iCancelStateSave); @@ -341,6 +342,7 @@ queueInitDA(queue_t *pThis, int bEnqOnly, int bLockMutex) lenBuf = snprintf((char*)pszBuf, sizeof(pszBuf), "%s:DA", obj.GetName((obj_t*) pThis)); CHKiRet(wtpConstruct (&pThis->pWtpDA)); CHKiRet(wtpSetDbgHdr (pThis->pWtpDA, pszBuf, lenBuf)); + CHKiRet(wtpSetpfRateLimiter (pThis->pWtpDA, (rsRetVal (*)(void *pUsr)) queueRateLimiter)); CHKiRet(wtpSetpfChkStopWrkr (pThis->pWtpDA, (rsRetVal (*)(void *pUsr, int)) queueChkStopWrkrDA)); CHKiRet(wtpSetpfIsIdle (pThis->pWtpDA, (rsRetVal (*)(void *pUsr, int)) queueIsIdleDA)); CHKiRet(wtpSetpfDoWork (pThis->pWtpDA, (rsRetVal (*)(void *pUsr, void *pWti, int)) queueConsumerDA)); @@ -1450,6 +1452,60 @@ finalize_it: } +/* The rate limiter - we only need one - do we? + * +* Here we may wait if a dequeue time window is defined or if we are + * rate-limited. TODO: If we do so, we should also look into the + * way new worker threads are spawned. Obviously, it doesn't make much + * sense to spawn additional worker threads when none of them can do any + * processing. However, it is deemed acceptable to allow this for an initial + * implementation of the timeframe/rate limiting feature. + * Please also note that these feature could also be implemented at the action + * level. However, that would limit them to be used together with actions. We have + * taken the broader approach, moving it right into the queue. This is even + * necessary if we want to prevent spawning of multiple unnecessary worker + * threads as described above. -- rgerhards, 2008-04-02 + * + * + * time window: tCurr is current time; tFrom is start time, tTo is end time (in mil 24h format). + * We may have tFrom = 4, tTo = 10 --> run from 4 to 10 hrs. nice and happy + * we may also have tFrom= 22, tTo = 4 -> run from 10pm to 4am, which is actually two + * windows: 0-4; 22-23:59 + * so when to run? Let's assume we have 3am + * + * if(tTo < tFrom) { + * if(tCurr < tTo [3 < 4] || tCurr > tFrom [3 > 22]) + * do work + * else + * sleep for tFrom - tCurr "hours" [22 - 5 --> 17] + * } else { + * if(tCurr >= tFrom [3 >= 4] && tCurr < tTo [3 < 10]) + * do work + * else + * sleep for tTo - tCurr "hours" [4 - 3 --> 1] + * } + * + * Bottom line: we need to check which type of window we have and need to adjust our + * logic accordingly. Of course, sleep calculations need to be done up to the minute, + * but you get the idea from the code above. + */ +static rsRetVal +queueRateLimiter(queue_t *pThis) +{ + DEFiRet; + + ISOBJ_TYPE_assert(pThis, queue); + + dbgoprint((obj_t*) pThis, "entering rate limiter\n"); + srSleep(2, 0); + +finalize_it: + dbgoprint((obj_t*) pThis, "rate limiter returns with iRet %d\n", iRet); + RETiRet; +} + + + /* This is the queue consumer in the regular (non-DA) case. It is * protected by the queue mutex, but MUST release it as soon as possible. * rgerhards, 2008-01-21 @@ -1690,6 +1746,7 @@ rsRetVal queueStart(queue_t *pThis) /* this is the ConstructionFinalizer */ lenBuf = snprintf((char*)pszBuf, sizeof(pszBuf), "%s:Reg", obj.GetName((obj_t*) pThis)); CHKiRet(wtpConstruct (&pThis->pWtpReg)); CHKiRet(wtpSetDbgHdr (pThis->pWtpReg, pszBuf, lenBuf)); + CHKiRet(wtpSetpfRateLimiter (pThis->pWtpReg, (rsRetVal (*)(void *pUsr)) queueRateLimiter)); CHKiRet(wtpSetpfChkStopWrkr (pThis->pWtpReg, (rsRetVal (*)(void *pUsr, int)) queueChkStopWrkrReg)); CHKiRet(wtpSetpfIsIdle (pThis->pWtpReg, (rsRetVal (*)(void *pUsr, int)) queueIsIdleReg)); CHKiRet(wtpSetpfDoWork (pThis->pWtpReg, (rsRetVal (*)(void *pUsr, void *pWti, int)) queueConsumerReg)); diff --git a/queue.h b/queue.h index bc09fbd8..6aa09a1b 100644 --- a/queue.h +++ b/queue.h @@ -82,9 +82,20 @@ typedef struct queue_s { int toActShutdown; /* timeout for long-running action shutdown in ms */ int toWrkShutdown; /* timeout for idle workers in ms, -1 means indefinite (0 is immediate) */ int toEnq; /* enqueue timeout */ - /* rate limiting settings (will be expanded */ + /* rate limiting settings (will be expanded) */ int iDeqSlowdown; /* slow down dequeue by specified nbr of microseconds */ /* end rate limiting */ + /* dequeue time window settings (may also be expanded) */ + int iDeqtWinFromHr; /* begin of dequeue time window (hour only) */ + int iDeqtWinToHr; /* end of dequeue time window (hour only) */ + /* note that begin and end have specific semantics. It is a big difference if we have + * begin 4, end 22 or begin 22, end 4. In the later case, dequeuing will run from 10p, + * throughout the night and stop at 4 in the morning. In the first case, it will start + * at 4am, run throughout the day, and stop at 10 in the evening! So far, not logic is + * applied to detect user configuration errors (and tell me how should we detect what + * the user really wanted...). -- rgerhards, 2008-04-02 + */ + /* ane dequeue time window */ rsRetVal (*pConsumer)(void *,void*); /* user-supplied consumer function for dequeued messages */ /* calling interface for pConsumer: arg1 is the global user pointer from this structure, arg2 is the * user pointer that was dequeued (actual sample: for actions, arg1 is the pAction and arg2 is pointer diff --git a/wti.c b/wti.c index 2386dee9..c9184b36 100644 --- a/wti.c +++ b/wti.c @@ -370,6 +370,14 @@ wtiWorker(wti_t *pThis) pthread_yield(); /* see big comment in function header */ # endif + /* if we have a rate-limiter set for this worker pool, let's call it. Please + * keep in mind that the rate-limiter may hold us for an extended period + * of time. -- rgerhards, 2008-04-02 + */ + if(pWtp->pfRateLimiter != NULL) { + pWtp->pfRateLimiter(pWtp->pUsr); + } + wtpSetInactivityGuard(pThis->pWtp, 0, LOCK_MUTEX); /* must be set before usr mutex is locked! */ BEGIN_MTX_PROTECTED_OPERATIONS(pWtp->pmutUsr, LOCK_MUTEX); diff --git a/wtp.c b/wtp.c index 1c2ea30f..d6192bc0 100644 --- a/wtp.c +++ b/wtp.c @@ -545,6 +545,7 @@ DEFpropSetMeth(wtp, pUsr, void*); DEFpropSetMethPTR(wtp, pmutUsr, pthread_mutex_t); DEFpropSetMethPTR(wtp, pcondBusy, pthread_cond_t); DEFpropSetMethFP(wtp, pfChkStopWrkr, rsRetVal(*pVal)(void*, int)); +DEFpropSetMethFP(wtp, pfRateLimiter, rsRetVal(*pVal)(void*)); DEFpropSetMethFP(wtp, pfIsIdle, rsRetVal(*pVal)(void*, int)); DEFpropSetMethFP(wtp, pfDoWork, rsRetVal(*pVal)(void*, void*, int)); DEFpropSetMethFP(wtp, pfOnIdle, rsRetVal(*pVal)(void*, int)); diff --git a/wtp.h b/wtp.h index 6100fe52..b928b149 100644 --- a/wtp.h +++ b/wtp.h @@ -68,6 +68,7 @@ typedef struct wtp_s { pthread_mutex_t *pmutUsr; pthread_cond_t *pcondBusy; /* condition the user will signal "busy again, keep runing" on (awakes worker) */ rsRetVal (*pfChkStopWrkr)(void *pUsr, int); + rsRetVal (*pfRateLimiter)(void *pUsr); rsRetVal (*pfIsIdle)(void *pUsr, int); rsRetVal (*pfDoWork)(void *pUsr, void *pWti, int); rsRetVal (*pfOnIdle)(void *pUsr, int); -- cgit From 2be9977a4db263400c8ba56c82e576b7da42cd86 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 3 Apr 2008 07:27:32 +0000 Subject: new property access functions --- queue.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/queue.h b/queue.h index 6aa09a1b..ecac6ee4 100644 --- a/queue.h +++ b/queue.h @@ -184,6 +184,8 @@ rsRetVal queueConstruct(queue_t **ppThis, queueType_t qType, int iWorkerThreads, int iMaxQueueSize, rsRetVal (*pConsumer)(void*,void*)); PROTOTYPEObjClassInit(queue); PROTOTYPEpropSetMeth(queue, iPersistUpdCnt, int); +PROTOTYPEpropSetMeth(queue, iDeqtWinFromHr, int); +PROTOTYPEpropSetMeth(queue, iDeqtWinToHr, int); PROTOTYPEpropSetMeth(queue, toQShutdown, long); PROTOTYPEpropSetMeth(queue, toActShutdown, long); PROTOTYPEpropSetMeth(queue, toWrkShutdown, long); -- cgit From 11461ad9c6de62556df79a35ff0c4902e2881f57 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 3 Apr 2008 08:47:35 +0000 Subject: bugfix: memory leaks in script engine --- conf.c | 6 ++++++ obj.h | 1 - queue.c | 2 ++ syslogd.c | 15 ++++++++++++--- var.c | 28 +++++++++++++++++++++------- vm.c | 5 ++--- vmop.c | 6 ++++++ vmstk.c | 2 -- 8 files changed, 49 insertions(+), 16 deletions(-) diff --git a/conf.c b/conf.c index 14e73f0e..f87ab992 100644 --- a/conf.c +++ b/conf.c @@ -68,6 +68,7 @@ static rsRetVal processConfFile(uchar *pConfFile); DEFobjStaticHelpers DEFobjCurrIf(expr) DEFobjCurrIf(ctok) +DEFobjCurrIf(ctok_token) DEFobjCurrIf(module) DEFobjCurrIf(errmsg) DEFobjCurrIf(net) @@ -762,9 +763,12 @@ dbgprintf("calling expression parser, pp %p ('%s')\n", *pline, *pline); */ CHKiRet(ctok.GetToken(tok, &pToken)); if(pToken->tok != ctok_THEN) { + ctok_token.Destruct(&pToken); ABORT_FINALIZE(RS_RET_SYNTAX_ERROR); } + ctok_token.Destruct(&pToken); /* no longer needed */ + /* we are done, so we now need to restore things */ CHKiRet(ctok.Getpp(tok, pline)); CHKiRet(ctok.Destruct(&tok)); @@ -1183,6 +1187,7 @@ CODESTARTObjClassExit(conf) /* release objects we no longer need */ objRelease(expr, CORE_COMPONENT); objRelease(ctok, CORE_COMPONENT); + objRelease(ctok_token, CORE_COMPONENT); objRelease(module, CORE_COMPONENT); objRelease(errmsg, CORE_COMPONENT); objRelease(net, LM_NET_FILENAME); @@ -1197,6 +1202,7 @@ BEGINAbstractObjClassInit(conf, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANG /* request objects we use */ CHKiRet(objUse(expr, CORE_COMPONENT)); CHKiRet(objUse(ctok, CORE_COMPONENT)); + CHKiRet(objUse(ctok_token, CORE_COMPONENT)); CHKiRet(objUse(module, CORE_COMPONENT)); CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(net, LM_NET_FILENAME)); /* TODO: make this dependcy go away! */ diff --git a/obj.h b/obj.h index a9d676d5..87c6c91d 100644 --- a/obj.h +++ b/obj.h @@ -92,7 +92,6 @@ /* interfaces */ BEGINinterface(obj) /* name must also be changed in ENDinterface macro! */ - //rsRetVal (*UseObj)(char *srcFile, uchar *pObjName, uchar *pMyLib, uchar *pObjFile, interface_t *pIf); rsRetVal (*UseObj)(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf); rsRetVal (*ReleaseObj)(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf); rsRetVal (*InfoConstruct)(objInfo_t **ppThis, uchar *pszID, int iObjVers, diff --git a/queue.c b/queue.c index bfdac204..57484e60 100644 --- a/queue.c +++ b/queue.c @@ -2208,6 +2208,8 @@ finalize_it: /* some simple object access methods */ DEFpropSetMeth(queue, iPersistUpdCnt, int); +DEFpropSetMeth(queue, iDeqtWinFromHr, int); +DEFpropSetMeth(queue, iDeqtWinToHr, int); DEFpropSetMeth(queue, toQShutdown, long); DEFpropSetMeth(queue, toActShutdown, long); DEFpropSetMeth(queue, toWrkShutdown, long); diff --git a/syslogd.c b/syslogd.c index 8c71f57d..b5554e5f 100644 --- a/syslogd.c +++ b/syslogd.c @@ -170,6 +170,7 @@ DEFobjCurrIf(datetime) DEFobjCurrIf(conf) DEFobjCurrIf(expr) DEFobjCurrIf(vm) +DEFobjCurrIf(var) DEFobjCurrIf(module) DEFobjCurrIf(errmsg) DEFobjCurrIf(net) /* TODO: make go away! */ @@ -928,8 +929,8 @@ static rsRetVal shouldProcessThisMessage(selector_t *f, msg_t *pMsg, int *bProce unsigned short pbMustBeFreed; char *pszPropVal; int bRet = 0; - vm_t *pVM; - var_t *pResult; + vm_t *pVM = NULL; + var_t *pResult = NULL; assert(f != NULL); assert(pMsg != NULL); @@ -995,7 +996,7 @@ static rsRetVal shouldProcessThisMessage(selector_t *f, msg_t *pMsg, int *bProce CHKiRet(vm.ExecProg(pVM, f->f_filterData.f_expr->pVmprg)); CHKiRet(vm.PopBoolFromStack(pVM, &pResult)); dbgprintf("result of expression evaluation: %lld\n", pResult->val.num); - CHKiRet(vm.Destruct(&pVM)); + /* VM is destructed on function exit */ bRet = (pResult->val.num) ? 1 : 0; } else { assert(f->f_filter_type == FILTER_PROP); /* assert() just in case... */ @@ -1051,6 +1052,12 @@ static rsRetVal shouldProcessThisMessage(selector_t *f, msg_t *pMsg, int *bProce } finalize_it: + /* destruct in any case, not just on error, but it makes error handling much easier */ + if(pVM != NULL) { + var.Destruct(&pResult); + vm.Destruct(&pVM); + } + *bProcessMsg = bRet; RETiRet; } @@ -2838,6 +2845,8 @@ InitGlobalClasses(void) CHKiRet(objUse(errmsg, CORE_COMPONENT)); pErrObj = "module"; CHKiRet(objUse(module, CORE_COMPONENT)); + pErrObj = "var"; + CHKiRet(objUse(var, CORE_COMPONENT)); /* initialize and use classes. We must be very careful with the order of events. Some * classes use others and if we do not initialize them in the right order, we may end diff --git a/var.c b/var.c index c1d66643..7de00d88 100644 --- a/var.c +++ b/var.c @@ -63,12 +63,11 @@ rsRetVal varConstructFinalize(var_t __attribute__((unused)) *pThis) BEGINobjDestruct(var) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(var) if(pThis->pcsName != NULL) - d_free(pThis->pcsName); + rsCStrDestruct(&pThis->pcsName); if(pThis->varType == VARTYPE_STR) { if(pThis->val.pStr != NULL) - d_free(pThis->val.pStr); + rsCStrDestruct(&pThis->val.pStr); } - ENDobjDestruct(var) @@ -192,10 +191,16 @@ ConvToNumber(var_t *pThis) } else if(pThis->varType == VARTYPE_STR) { iRet = rsCStrConvertToNumber(pThis->val.pStr, &n); if(iRet == RS_RET_NOT_A_NUMBER) { - n = 0; /* TODO: isn't it better to pass the error? */ + n = 0; + iRet = RS_RET_OK; /* we accept this as part of the language definition */ } else if (iRet != RS_RET_OK) { FINALIZE; } + + /* we need to destruct the string first, because string and number are + * inside a union and share the memory area! -- rgerhards, 2008-04-03 + */ + rsCStrDestruct(&pThis->val.pStr); pThis->val.num = n; pThis->varType = VARTYPE_NUMBER; @@ -244,7 +249,18 @@ ConvToBool(var_t *pThis) if(pThis->varType == VARTYPE_NUMBER) { FINALIZE; } else if(pThis->varType == VARTYPE_STR) { - CHKiRet(rsCStrConvertToBool(pThis->val.pStr, &n)); + iRet = rsCStrConvertToBool(pThis->val.pStr, &n); + if(iRet == RS_RET_NOT_A_NUMBER) { + n = 0; + iRet = RS_RET_OK; /* we accept this as part of the language definition */ + } else if (iRet != RS_RET_OK) { + FINALIZE; + } + + /* we need to destruct the string first, because string and number are + * inside a union and share the memory area! -- rgerhards, 2008-04-03 + */ + rsCStrDestruct(&pThis->val.pStr); pThis->val.num = n; pThis->varType = VARTYPE_NUMBER; } @@ -366,8 +382,6 @@ CODESTARTobjQueryInterface(var) * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ - //xxxpIf->oID = OBJvar; - pIf->Construct = varConstruct; pIf->ConstructFinalize = varConstructFinalize; pIf->Destruct = varDestruct; diff --git a/vm.c b/vm.c index 3cd05622..a26e4331 100644 --- a/vm.c +++ b/vm.c @@ -109,8 +109,6 @@ BEGINop(name) \ number_t bRes; \ CODESTARTop(name) \ CHKiRet(vmstk.Pop2CommOp(pThis->pStk, &operand1, &operand2)); \ -var.DebugPrint(operand1); \ -var.DebugPrint(operand2); \ /* data types are equal (so we look only at operand1), but we must \ * check which type we have to deal with... \ */ \ @@ -122,7 +120,6 @@ var.DebugPrint(operand2); \ } \ \ /* we have a result, so let's push it */ \ -RUNLOG_VAR("%lld", bRes); \ var.SetNumber(operand1, bRes); \ vmstk.Push(pThis->pStk, operand1); /* result */ \ var.Destruct(&operand2); /* no longer needed */ \ @@ -374,6 +371,8 @@ BEGINobjDestruct(vm) /* be sure to specify the object type also in END and CODES CODESTARTobjDestruct(vm) if(pThis->pStk != NULL) vmstk.Destruct(&pThis->pStk); + if(pThis->pMsg != NULL) + msgDestruct(&pThis->pMsg); ENDobjDestruct(vm) diff --git a/vmop.c b/vmop.c index affa83e7..91f84b91 100644 --- a/vmop.c +++ b/vmop.c @@ -59,6 +59,12 @@ rsRetVal vmopConstructFinalize(vmop_t __attribute__((unused)) *pThis) /* destructor for the vmop object */ BEGINobjDestruct(vmop) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(vmop) + if( pThis->opcode == opcode_PUSHSYSVAR + || pThis->opcode == opcode_PUSHMSGVAR + || pThis->opcode == opcode_PUSHCONSTANT) { + if(pThis->operand.pVar != NULL) + var.Destruct(&pThis->operand.pVar); + } ENDobjDestruct(vmop) diff --git a/vmstk.c b/vmstk.c index 9ca815ff..f6614f71 100644 --- a/vmstk.c +++ b/vmstk.c @@ -201,8 +201,6 @@ CODESTARTobjQueryInterface(vmstk) * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ - //xxxpIf->oID = OBJvmstk; - pIf->Construct = vmstkConstruct; pIf->ConstructFinalize = vmstkConstructFinalize; pIf->Destruct = vmstkDestruct; -- cgit From 5e279ea0f79250a07948ed6c24731f60e8221543 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 3 Apr 2008 09:31:55 +0000 Subject: properties are now case-insensitive everywhere (script, filters, templates) --- ChangeLog | 3 +++ conf.c | 4 ++-- doc/property_replacer.html | 46 ++++++++++++++++++++++------------------------ msg.c | 40 ++++++++++++++++++++-------------------- parse.c | 5 +++-- parse.h | 2 +- template.c | 4 ++-- 7 files changed, 53 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index 55412458..4648f791 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,9 @@ Version 3.17.0 (rgerhards), 2008-04-?? - FEATURE FOCUS for 3.17 is TLS over plain TCP syslog - removed no longer needed file relptuil.c/.h +- bugfix: memory leaks in script engine +- properties are now case-insensitive everywhere (script, filters, + templates) --------------------------------------------------------------------------- Version 3.15.1 (rgerhards), 2008-04-?? - disabled atomic operations for the time being because they introduce some diff --git a/conf.c b/conf.c index f87ab992..dac46970 100644 --- a/conf.c +++ b/conf.c @@ -816,7 +816,7 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register selector_t *f) } /* read property */ - iRet = parsDelimCStr(pPars, &f->f_filterData.prop.pCSPropName, ',', 1, 1); + iRet = parsDelimCStr(pPars, &f->f_filterData.prop.pCSPropName, ',', 1, 1, 1); if(iRet != RS_RET_OK) { errmsg.LogError(NO_ERRCODE, "error %d parsing filter property - ignoring selector", iRet); rsParsDestruct(pPars); @@ -824,7 +824,7 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register selector_t *f) } /* read operation */ - iRet = parsDelimCStr(pPars, &pCSCompOp, ',', 1, 1); + iRet = parsDelimCStr(pPars, &pCSCompOp, ',', 1, 1, 1); if(iRet != RS_RET_OK) { errmsg.LogError(NO_ERRCODE, "error %d compare operation property - ignoring selector", iRet); rsParsDestruct(pPars); diff --git a/doc/property_replacer.html b/doc/property_replacer.html index 3484acf2..a2efaede 100644 --- a/doc/property_replacer.html +++ b/doc/property_replacer.html @@ -1,7 +1,5 @@ -The Rsyslogd Property Replacer - - +The Rsyslogd Property Replacer

    The Property Replacer

    The property replacer is a core component in @@ -17,7 +15,7 @@ modified by the property replacer. The full syntax is as follows:

    %propname:fromChar:toChar:options%

    Available Properties

    propname is the -name of the property to access. It is case-sensitive. +name of the property to access. It is case-insensitive (prior to 3.17.0, they were case-senstive). Currently supported are:

    @@ -31,11 +29,11 @@ Currently supported are:

    socket. Should be useful for debugging. - + - + @@ -43,7 +41,7 @@ socket. Should be useful for debugging. - + @@ -59,16 +57,16 @@ BSD syslogd. For example, when TAG is "named[12345]", programname is "named". - + - + - + @@ -110,67 +108,67 @@ what was provided in the message (in most cases, only seconds) - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/msg.c b/msg.c index 76ea2f72..9a12d572 100644 --- a/msg.c +++ b/msg.c @@ -1604,18 +1604,17 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, pRes = getMSG(pMsg); } else if(!strcmp((char*) pName, "rawmsg")) { pRes = getRawMsg(pMsg); - } else if(!strcmp((char*) pName, "UxTradMsg")) { + } else if(!strcmp((char*) pName, "uxtradmsg")) { pRes = getUxTradMsg(pMsg); - } else if(!strcmp((char*) pName, "FROMHOST")) { + } else if(!strcmp((char*) pName, "fromhost")) { pRes = getRcvFrom(pMsg); - } else if(!strcmp((char*) pName, "source") - || !strcmp((char*) pName, "HOSTNAME")) { + } else if(!strcmp((char*) pName, "source") || !strcmp((char*) pName, "hostname")) { pRes = getHOSTNAME(pMsg); } else if(!strcmp((char*) pName, "syslogtag")) { pRes = getTAG(pMsg); - } else if(!strcmp((char*) pName, "PRI")) { + } else if(!strcmp((char*) pName, "pri")) { pRes = getPRI(pMsg); - } else if(!strcmp((char*) pName, "PRI-text")) { + } else if(!strcmp((char*) pName, "pri-text")) { pBuf = malloc(20 * sizeof(char)); if(pBuf == NULL) { *pbMustBeFreed = 0; @@ -1637,57 +1636,57 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, } else if(!strcmp((char*) pName, "timegenerated")) { pRes = getTimeGenerated(pMsg, pTpe->data.field.eDateFormat); } else if(!strcmp((char*) pName, "timereported") - || !strcmp((char*) pName, "TIMESTAMP")) { + || !strcmp((char*) pName, "timestamp")) { pRes = getTimeReported(pMsg, pTpe->data.field.eDateFormat); } else if(!strcmp((char*) pName, "programname")) { pRes = getProgramName(pMsg); - } else if(!strcmp((char*) pName, "PROTOCOL-VERSION")) { + } else if(!strcmp((char*) pName, "protocol-version")) { pRes = getProtocolVersionString(pMsg); - } else if(!strcmp((char*) pName, "STRUCTURED-DATA")) { + } else if(!strcmp((char*) pName, "structured-data")) { pRes = getStructuredData(pMsg); - } else if(!strcmp((char*) pName, "APP-NAME")) { + } else if(!strcmp((char*) pName, "app-name")) { pRes = getAPPNAME(pMsg); - } else if(!strcmp((char*) pName, "PROCID")) { + } else if(!strcmp((char*) pName, "procid")) { pRes = getPROCID(pMsg); - } else if(!strcmp((char*) pName, "MSGID")) { + } else if(!strcmp((char*) pName, "msgid")) { pRes = getMSGID(pMsg); /* here start system properties (those, that do not relate to the message itself */ - } else if(!strcmp((char*) pName, "$NOW")) { + } else if(!strcmp((char*) pName, "$now")) { if((pRes = (char*) getNOW(NOW_NOW)) == NULL) { return "***OUT OF MEMORY***"; } else *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$YEAR")) { + } else if(!strcmp((char*) pName, "$year")) { if((pRes = (char*) getNOW(NOW_YEAR)) == NULL) { return "***OUT OF MEMORY***"; } else *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$MONTH")) { + } else if(!strcmp((char*) pName, "$month")) { if((pRes = (char*) getNOW(NOW_MONTH)) == NULL) { return "***OUT OF MEMORY***"; } else *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$DAY")) { + } else if(!strcmp((char*) pName, "$day")) { if((pRes = (char*) getNOW(NOW_DAY)) == NULL) { return "***OUT OF MEMORY***"; } else *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$HOUR")) { + } else if(!strcmp((char*) pName, "$hour")) { if((pRes = (char*) getNOW(NOW_HOUR)) == NULL) { return "***OUT OF MEMORY***"; } else *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$HHOUR")) { + } else if(!strcmp((char*) pName, "$hhour")) { if((pRes = (char*) getNOW(NOW_HHOUR)) == NULL) { return "***OUT OF MEMORY***"; } else *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$QHOUR")) { + } else if(!strcmp((char*) pName, "$qhour")) { if((pRes = (char*) getNOW(NOW_QHOUR)) == NULL) { return "***OUT OF MEMORY***"; } else *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$MINUTE")) { + } else if(!strcmp((char*) pName, "$minute")) { if((pRes = (char*) getNOW(NOW_MINUTE)) == NULL) { return "***OUT OF MEMORY***"; } else @@ -1696,6 +1695,7 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, /* there is no point in continuing, we may even otherwise render the * error message unreadable. rgerhards, 2007-07-10 */ + dbgprintf("invalid property name: '%s'\n", pName); return "**INVALID PROPERTY NAME**"; } diff --git a/parse.c b/parse.c index bca6457d..5239b540 100644 --- a/parse.c +++ b/parse.c @@ -235,11 +235,12 @@ rsRetVal parsSkipWhitespace(rsParsObj *pThis) * 0 means "no", 1 "yes" * - bTrimLeading * - bTrimTrailing + * - bConvLower - convert string to lower case? * * Output: * ppCStr Pointer to the parsed string - must be freed by caller! */ -rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing) +rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing, int bConvLower) { DEFiRet; register unsigned char *pC; @@ -256,7 +257,7 @@ rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrim while(pThis->iCurrPos < rsCStrLen(pThis->pCStr) && *pC != cDelim) { - if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) { + if((iRet = rsCStrAppendChar(pCStr, bConvLower ? tolower(*pC) : *pC)) != RS_RET_OK) { rsCStrDestruct(&pCStr); FINALIZE; } diff --git a/parse.h b/parse.h index 483c109b..b7ac950d 100644 --- a/parse.h +++ b/parse.h @@ -91,7 +91,7 @@ rsRetVal parsSkipWhitespace(rsParsObj *pThis); * Output: * ppCStr Pointer to the parsed string */ -rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing); +rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing, int bConvLower); rsRetVal parsSkipAfterChar(rsParsObj *pThis, char c); rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr); diff --git a/template.c b/template.c index 75c9ce78..0eea4572 100644 --- a/template.c +++ b/template.c @@ -385,7 +385,6 @@ static int do_Constant(unsigned char **pp, struct template *pTpl) if((pTpe = tpeConstruct(pTpl)) == NULL) { /* OK, we are out of luck. Let's invalidate the * entry and that's it. - * TODO: add panic message once we have a mechanism for this */ pTpe->eEntryType = UNDEFINED; return 1; @@ -510,7 +509,8 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl) pTpe->eEntryType = FIELD; while(*p && *p != '%' && *p != ':') { - rsCStrAppendChar(pStrB, *p++); + rsCStrAppendChar(pStrB, tolower(*p)); + ++p; /* do NOT do this in tolower()! */ } /* got the name*/ -- cgit From 46fbfee41e88034135725beb4136d44b94388ede Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 3 Apr 2008 13:19:48 +0000 Subject: added the capability to specify a processing (actually dequeue) timeframe with queues - so things can be configured to be done at off-peak hours --- ChangeLog | 3 ++ action.c | 15 ++++++-- doc/features.html | 6 +-- doc/queues.html | 12 +++++- doc/rsyslog_ng_comparison.html | 13 ++++++- queue.c | 85 +++++++++++++++++++++++++++++++++--------- queue.h | 2 +- stringbuf.h | 1 + syslogd.c | 23 ++++-------- 9 files changed, 114 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4648f791..f6291a67 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,9 @@ Version 3.17.0 (rgerhards), 2008-04-?? - bugfix: memory leaks in script engine - properties are now case-insensitive everywhere (script, filters, templates) +- added the capability to specify a processing (actually dequeue) + timeframe with queues - so things can be configured to be done + at off-peak hours --------------------------------------------------------------------------- Version 3.15.1 (rgerhards), 2008-04-?? - disabled atomic operations for the time being because they introduce some diff --git a/action.c b/action.c index 99ae8b32..30bf3c92 100644 --- a/action.c +++ b/action.c @@ -74,8 +74,10 @@ static int iActionQtoEnq = 2000; /* timeout for queue enque */ static int iActionQtoWrkShutdown = 60000; /* timeout for worker thread shutdown */ static int iActionQWrkMinMsgs = 100; /* minimum messages per worker needed to start a new one */ static int bActionQSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */ -static int iActionQueueDeqSlowdown = 0; /* dequeue slowdown (simple rate limiting) */ static int64 iActionQueMaxDiskSpace = 0; /* max disk space allocated 0 ==> unlimited */ +static int iActionQueueDeqSlowdown = 0; /* dequeue slowdown (simple rate limiting) */ +static int iActionQueueDeqtWinFromHr = 0; /* hour begin of time frame when queue is to be dequeued */ +static int iActionQueueDeqtWinToHr = 25; /* hour begin of time frame when queue is to be dequeued */ /* the counter below counts actions created. It is used to obtain unique IDs for the action. They * should not be relied on for any long-term activity (e.g. disk queue names!), but they are nice @@ -113,8 +115,10 @@ actionResetQueueParams(void) iActionQtoWrkShutdown = 60000; /* timeout for worker thread shutdown */ iActionQWrkMinMsgs = 100; /* minimum messages per worker needed to start a new one */ bActionQSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */ - iActionQueueDeqSlowdown = 0; iActionQueMaxDiskSpace = 0; + iActionQueueDeqSlowdown = 0; + iActionQueueDeqtWinFromHr = 0; + iActionQueueDeqtWinToHr = 25; /* 25 disables time windowed dequeuing */ glbliActionResumeRetryCount = 0; /* I guess it is smart to reset this one, too */ @@ -237,7 +241,9 @@ actionConstructFinalize(action_t *pThis) setQPROP(queueSetiDiscardSeverity, "$ActionQueueDiscardSeverity", iActionQDiscardSeverity); setQPROP(queueSetiMinMsgsPerWrkr, "$ActionQueueWorkerThreadMinimumMessages", iActionQWrkMinMsgs); setQPROP(queueSetbSaveOnShutdown, "$ActionQueueSaveOnShutdown", bActionQSaveOnShutdown); - setQPROP(queueSetiDeqSlowdown, "$ActionQueueDequeueSlowdown", iActionQueueDeqSlowdown); + setQPROP(queueSetiDeqSlowdown, "$ActionQueueDequeueSlowdown", iActionQueueDeqSlowdown); + setQPROP(queueSetiDeqtWinFromHr, "$ActionQueueDequeueTimeBegin", iActionQueueDeqtWinFromHr); + setQPROP(queueSetiDeqtWinToHr, "$ActionQueueDequeueTimeEnd", iActionQueueDeqtWinToHr); # undef setQPROP # undef setQPROPstr @@ -680,6 +686,8 @@ actionAddCfSysLineHdrl(void) CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuemaxfilesize", 0, eCmdHdlrSize, NULL, &iActionQueMaxFileSize, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuesaveonshutdown", 0, eCmdHdlrBinary, NULL, &bActionQSaveOnShutdown, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeueslowdown", 0, eCmdHdlrInt, NULL, &iActionQueueDeqSlowdown, NULL)); + CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeuetimebegin", 0, eCmdHdlrInt, NULL, &iActionQueueDeqtWinFromHr, NULL)); + CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeuetimeend", 0, eCmdHdlrInt, NULL, &iActionQueueDeqtWinToHr, NULL)); finalize_it: RETiRet; @@ -800,6 +808,5 @@ finalize_it: RETiRet; } - /* vi:set ai: */ diff --git a/doc/features.html b/doc/features.html index 9573030e..f74f2aaf 100644 --- a/doc/features.html +++ b/doc/features.html @@ -1,7 +1,5 @@ -rsyslog features - - +rsyslog features

    RSyslog - Features

    This page lists both current features as well as @@ -31,7 +29,7 @@ reliability

  • support for sending and receiving compressed syslog messages
  • support for on-demand on-disk spooling of messages that can not be processed fast enough (a great feature for writing massive -amounts of syslog messages to a database)
  • +amounts of syslog messages to a database)
  • support for selectively processing messages only during specific timeframes and spooling them to disk otherwise
  • ability to monitor text files and convert their contents into syslog messages (one per line)
  • ability to configure backup syslog/database servers - if diff --git a/doc/queues.html b/doc/queues.html index 80641d8c..a2074d36 100644 --- a/doc/queues.html +++ b/doc/queues.html @@ -288,7 +288,17 @@ directive allows to specify how long (in microseconds) dequeueing should be delayed. While simple, it still is powerful. For example, using a DequeueSlowdown delay of 1,000 microseconds on a UDP send action ensures that no more than 1,000 messages can be sent within a second (actually less, as there is -also some time needed for the processing itself).

    +also some time needed for the processing itself).

    Processing Timeframes

    Queues +can be set to dequeue (process) messages only during certain +timeframes. This is useful if you, for example, would like to transfer +the bulk of messages only during off-peak hours, e.g. when you have +only limited bandwidth on the network path the the central server.

    Currently, +only a single timeframe is supported and, even worse, it can only be +specified by the hour. It is not hard to extend rsyslog's capabilities +in this regard - it was just not requested so far. So if you need more +fine-grained control, let us know and we'll probably implement it. +There are two configuration directives, both should be used together or +results are unpredictable:" $<object>QueueDequeueTimeBegin <hour>" and "$<object>QueueDequeueTimeEnd <hour>". The hour parameter must be specified in 24-hour format (so 10pm is 22). A use case for this parameter can be found in the rsyslog wiki.

    Terminating Queues

    Terminating a process sounds easy, but can be complex. diff --git a/doc/rsyslog_ng_comparison.html b/doc/rsyslog_ng_comparison.html index 852ab4ed..60eeee74 100644 --- a/doc/rsyslog_ng_comparison.html +++ b/doc/rsyslog_ng_comparison.html @@ -1,6 +1,6 @@ -rsyslog vs. syslog-ng - a comparison +rsyslog vs. syslog-ng - a comparison @@ -122,7 +122,9 @@ based framing on syslog/tcp connections

  • - + @@ -337,6 +339,13 @@ be placed on different disk + + + + + diff --git a/queue.c b/queue.c index 57484e60..7456f4a6 100644 --- a/queue.c +++ b/queue.c @@ -1,16 +1,16 @@ /* queue.c -* -* This file implements the queue object and its several queueing methods. -* -* File begun on 2008-01-03 by RGerhards -* -* There is some in-depth documentation available in doc/dev_queue.html -* (and in the web doc set on http://www.rsyslog.com/doc). Be sure to read it -* if you are getting aquainted to the object. -* -* Copyright 2008 Rainer Gerhards and Adiscon GmbH. -* -* This file is part of rsyslog. + * + * This file implements the queue object and its several queueing methods. + * + * File begun on 2008-01-03 by RGerhards + * + * There is some in-depth documentation available in doc/dev_queue.html + * (and in the web doc set on http://www.rsyslog.com/doc). Be sure to read it + * if you are getting aquainted to the object. + * + * Copyright 2008 Rainer Gerhards and Adiscon GmbH. + * + * This file is part of rsyslog. * * Rsyslog is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,6 +38,7 @@ #include #include #include /* required for HP UX */ +#include #include #include "rsyslog.h" @@ -272,6 +273,8 @@ queueStartDA(queue_t *pThis) CHKiRet(queueSettoActShutdown(pThis->pqDA, pThis->toActShutdown)); CHKiRet(queueSettoEnq(pThis->pqDA, pThis->toEnq)); CHKiRet(queueSetEnqOnly(pThis->pqDA, pThis->bDAEnqOnly, MUTEX_ALREADY_LOCKED)); + CHKiRet(queueSetiDeqtWinFromHr(pThis->pqDA, pThis->iDeqtWinFromHr)); + CHKiRet(queueSetiDeqtWinToHr(pThis->pqDA, pThis->iDeqtWinToHr)); CHKiRet(queueSetiHighWtrMrk(pThis->pqDA, 0)); CHKiRet(queueSetiDiscardMrk(pThis->pqDA, 0)); if(pThis->toQShutdown == 0) { @@ -342,7 +345,6 @@ queueInitDA(queue_t *pThis, int bEnqOnly, int bLockMutex) lenBuf = snprintf((char*)pszBuf, sizeof(pszBuf), "%s:DA", obj.GetName((obj_t*) pThis)); CHKiRet(wtpConstruct (&pThis->pWtpDA)); CHKiRet(wtpSetDbgHdr (pThis->pWtpDA, pszBuf, lenBuf)); - CHKiRet(wtpSetpfRateLimiter (pThis->pWtpDA, (rsRetVal (*)(void *pUsr)) queueRateLimiter)); CHKiRet(wtpSetpfChkStopWrkr (pThis->pWtpDA, (rsRetVal (*)(void *pUsr, int)) queueChkStopWrkrDA)); CHKiRet(wtpSetpfIsIdle (pThis->pWtpDA, (rsRetVal (*)(void *pUsr, int)) queueIsIdleDA)); CHKiRet(wtpSetpfDoWork (pThis->pWtpDA, (rsRetVal (*)(void *pUsr, void *pWti, int)) queueConsumerDA)); @@ -1269,6 +1271,7 @@ rsRetVal queueConstruct(queue_t **ppThis, queueType_t qType, int iWorkerThreads, pThis->iMaxQueueSize = iMaxQueueSize; pThis->pConsumer = pConsumer; pThis->iNumWorkerThreads = iWorkerThreads; + pThis->iDeqtWinToHr = 25; /* disable time-windowed dequeuing by default */ pThis->pszFilePrefix = NULL; pThis->qType = qType; @@ -1486,20 +1489,67 @@ finalize_it: * } * * Bottom line: we need to check which type of window we have and need to adjust our - * logic accordingly. Of course, sleep calculations need to be done up to the minute, + * logic accordingly. Of course, sleep calculations need to be done up to the minute, * but you get the idea from the code above. */ static rsRetVal queueRateLimiter(queue_t *pThis) { DEFiRet; + int iDelay; + int iHrCurr; + time_t tCurr; + struct tm m; ISOBJ_TYPE_assert(pThis, queue); dbgoprint((obj_t*) pThis, "entering rate limiter\n"); - srSleep(2, 0); -finalize_it: + iDelay = 0; +dbgprintf("deq win from %d to %d\n", pThis->iDeqtWinFromHr, pThis->iDeqtWinToHr); + if(pThis->iDeqtWinToHr != 25) { /* 25 means disabled */ + /* time calls are expensive, so only do them when needed */ + time(&tCurr); + localtime_r(&tCurr, &m); + iHrCurr = m.tm_hour; +RUNLOG_VAR("%d", iHrCurr); + + if(pThis->iDeqtWinToHr < pThis->iDeqtWinFromHr) { + if(iHrCurr < pThis->iDeqtWinToHr || iHrCurr > pThis->iDeqtWinFromHr) { + ; /* do not delay */ + } else { + iDelay = (pThis->iDeqtWinFromHr - iHrCurr) * 3600; + /* this time, we are already into the next hour, so we need + * to subtract our current minute and seconds. + */ + iDelay -= m.tm_min * 60; + iDelay -= m.tm_sec; + } + } else { + if(iHrCurr >= pThis->iDeqtWinFromHr && iHrCurr < pThis->iDeqtWinToHr) { + ; /* do not delay */ + } else { + if(iHrCurr < pThis->iDeqtWinFromHr) { + iDelay = (pThis->iDeqtWinFromHr - iHrCurr - 1) * 3600; /* -1 as we are already in the hour */ + iDelay += (60 - m.tm_min) * 60; + iDelay += 60 - m.tm_sec; + } else { + iDelay = (24 - iHrCurr + pThis->iDeqtWinFromHr) * 3600; + /* this time, we are already into the next hour, so we need + * to subtract our current minute and seconds. + */ + iDelay -= m.tm_min * 60; + iDelay -= m.tm_sec; + } + } + } + } + + if(iDelay > 0) { + dbgoprint((obj_t*) pThis, "outside dequeue time window, delaying %d seconds\n", iDelay); + srSleep(iDelay, 0); + } + dbgoprint((obj_t*) pThis, "rate limiter returns with iRet %d\n", iRet); RETiRet; } @@ -2272,6 +2322,5 @@ BEGINObjClassInit(queue, 1, OBJ_IS_CORE_MODULE) OBJSetMethodHandler(objMethod_SETPROPERTY, queueSetProperty); ENDObjClassInit(queue) -/* - * vi:set ai: +/* vi:set ai: */ diff --git a/queue.h b/queue.h index ecac6ee4..7dfeb226 100644 --- a/queue.h +++ b/queue.h @@ -87,7 +87,7 @@ typedef struct queue_s { /* end rate limiting */ /* dequeue time window settings (may also be expanded) */ int iDeqtWinFromHr; /* begin of dequeue time window (hour only) */ - int iDeqtWinToHr; /* end of dequeue time window (hour only) */ + int iDeqtWinToHr; /* end of dequeue time window (hour only), set to 25 to disable deq window! */ /* note that begin and end have specific semantics. It is a big difference if we have * begin 4, end 22 or begin 22, end 4. In the later case, dequeuing will run from 10p, * throughout the night and stop at 4 in the morning. In the first case, it will start diff --git a/stringbuf.h b/stringbuf.h index aa31884e..3475b8f6 100755 --- a/stringbuf.h +++ b/stringbuf.h @@ -121,6 +121,7 @@ void rsCStrSetAllocIncrement(cstr_t *pThis, int iNewIncrement); rsRetVal rsCStrAppendInt(cstr_t *pThis, long i); +rsRetVal strExit(void); /* TODO: remove once we have a real object interface! */ uchar* rsCStrGetSzStr(cstr_t *pThis); uchar* rsCStrGetSzStrNoNULL(cstr_t *pThis); rsRetVal rsCStrSetSzStr(cstr_t *pThis, uchar *pszNew); diff --git a/syslogd.c b/syslogd.c index b5554e5f..e6dae301 100644 --- a/syslogd.c +++ b/syslogd.c @@ -338,8 +338,10 @@ static int iMainMsgQtoEnq = 2000; /* timeout for queue enque */ static int iMainMsgQtoWrkShutdown = 60000; /* timeout for worker thread shutdown */ static int iMainMsgQWrkMinMsgs = 100; /* minimum messages per worker needed to start a new one */ static int iMainMsgQDeqSlowdown = 0; /* dequeue slowdown (simple rate limiting) */ -static int bMainMsgQSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */ static int64 iMainMsgQueMaxDiskSpace = 0; /* max disk space allocated 0 ==> unlimited */ +static int bMainMsgQSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */ +static int iMainMsgQueueDeqtWinFromHr = 0; /* hour begin of time frame when queue is to be dequeued */ +static int iMainMsgQueueDeqtWinToHr = 25; /* hour begin of time frame when queue is to be dequeued */ /* support for simple textual representation of FIOP names @@ -2323,6 +2325,8 @@ init(void) setQPROP(queueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", iMainMsgQWrkMinMsgs); setQPROP(queueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", bMainMsgQSaveOnShutdown); setQPROP(queueSetiDeqSlowdown, "$MainMsgQueueDequeueSlowdown", iMainMsgQDeqSlowdown); + setQPROP(queueSetiDeqtWinFromHr, "$MainMsgQueueDequeueTimeBegin", iMainMsgQueueDeqtWinFromHr); + setQPROP(queueSetiDeqtWinToHr, "$MainMsgQueueDequeueTimeEnd", iMainMsgQueueDeqtWinToHr); # undef setQPROP # undef setQPROPstr @@ -2687,6 +2691,8 @@ static rsRetVal loadBuildInModules(void) CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxfilesize", 0, eCmdHdlrSize, NULL, &iMainMsgQueMaxFileSize, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxdiskspace", 0, eCmdHdlrSize, NULL, &iMainMsgQueMaxDiskSpace, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesaveonshutdown", 0, eCmdHdlrBinary, NULL, &bMainMsgQSaveOnShutdown, NULL)); + CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimebegin", 0, eCmdHdlrInt, NULL, &iMainMsgQueueDeqtWinFromHr, NULL)); + CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimeend", 0, eCmdHdlrInt, NULL, &iMainMsgQueueDeqtWinToHr, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgreduction", 0, eCmdHdlrBinary, NULL, &bReduceRepeatMsgs, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlywhenpreviousissuspended", 0, eCmdHdlrBinary, NULL, &bActExecWhenPrevSusp, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt, setActionResumeInterval, NULL, NULL)); @@ -2766,21 +2772,6 @@ static void mainThread() BEGINfunc uchar *pTmp; -#if 0 // code moved back to main() - /* doing some core initializations */ - if((iRet = modInitIminternal()) != RS_RET_OK) { - fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n", - iRet); - exit(1); /* "good" exit, leaving at init for fatal error */ - } - - if((iRet = loadBuildInModules()) != RS_RET_OK) { - fprintf(stderr, "fatal error: could not activate built-in modules. Error code %d.\n", - iRet); - exit(1); /* "good" exit, leaving at init for fatal error */ - } -#endif - /* Note: signals MUST be processed by the thread this code is running in. The reason * is that we need to interrupt the select() system call. -- rgerhards, 2007-10-17 */ -- cgit From 8b8c1f095a8d822a0bde4993e233038567665d90 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 3 Apr 2008 13:55:44 +0000 Subject: bugfix: some memory leak when queue is runing in disk mode --- ChangeLog | 1 + obj.c | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index f6291a67..c30c8c7d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,7 @@ Version 3.17.0 (rgerhards), 2008-04-?? - added the capability to specify a processing (actually dequeue) timeframe with queues - so things can be configured to be done at off-peak hours +- bugfix: some memory leak when queue is runing in disk mode --------------------------------------------------------------------------- Version 3.15.1 (rgerhards), 2008-04-?? - disabled atomic operations for the time being because they introduce some diff --git a/obj.c b/obj.c index 0baaf7a1..d408c4bb 100644 --- a/obj.c +++ b/obj.c @@ -731,7 +731,7 @@ finalize_it: static rsRetVal objDeserializeProperties(obj_t *pObj, objInfo_t *pObjInfo, strm_t *pStrm) { DEFiRet; - var_t *pVar; + var_t *pVar = NULL; ISOBJ_assert(pObj); ISOBJ_TYPE_assert(pStrm, strm); @@ -743,15 +743,23 @@ static rsRetVal objDeserializeProperties(obj_t *pObj, objInfo_t *pObjInfo, strm_ iRet = objDeserializeProperty(pVar, pStrm); while(iRet == RS_RET_OK) { CHKiRet(pObjInfo->objMethods[objMethod_SETPROPERTY](pObj, pVar)); + /* re-init var object - TODO: method of var! */ + rsCStrDestruct(&pVar->pcsName); /* no longer needed */ + if(pVar->varType == VARTYPE_STR) { + if(pVar->val.pStr != NULL) + rsCStrDestruct(&pVar->val.pStr); + } iRet = objDeserializeProperty(pVar, pStrm); } - var.Destruct(&pVar); if(iRet != RS_RET_NO_PROPLINE) FINALIZE; CHKiRet(objDeserializeTrailer(pStrm)); /* do trailer checks */ finalize_it: + if(pVar != NULL) + var.Destruct(&pVar); + RETiRet; } -- cgit From 92a0907c224acfaab99e38f0d9fa6308eb9876fd Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 4 Apr 2008 06:23:56 +0000 Subject: added RELP doc to man pages --- rsyslog.conf.5 | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- rsyslogd.8 | 125 ++++++++++++++++++++++++++++++++++---------------------- 2 files changed, 195 insertions(+), 56 deletions(-) diff --git a/rsyslog.conf.5 b/rsyslog.conf.5 index e673e490..b49a2da4 100644 --- a/rsyslog.conf.5 +++ b/rsyslog.conf.5 @@ -17,7 +17,7 @@ .\" along with this program; if not, write to the Free Software .\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. .\" -.TH RSYSLOG.CONF 5 "28 March 2008" "Version 3.12.5" "Linux System Administration" +.TH RSYSLOG.CONF 5 "04 April 2008" "Version 3.17.0" "Linux System Administration" .SH NAME rsyslog.conf \- rsyslogd(8) configuration file .SH DESCRIPTION @@ -40,6 +40,94 @@ to look at the html documentation, because the man pages only cover basic aspects of operation. +.SH MODULES + +Rsyslog has a modular design. Consequently, there is a growing number +of modules. See the html documentation for their full description. + +.TP +.I omsnmp +SNMP trap output module +.TP +.I omgssapi +Output module for GSS-enabled syslog +.TP +.I ommysql +Output module for MySQL +.TP +.I omprelp +Output module for the reliable RELP protocol (prevents message loss). +For details, see below at imrelp and the html documentation. +It can be used like this: +.IP +*.* :omrelp:server:port +.IP +*.* :omrelp:192.168.0.1:2514 # actual sample +.TP +.I ompgsql +Output module for PostgreSQL +.TP +.I omlibdbi +Generic database output module (Firebird/Interbase, MS SQL, Sybase, +SQLLite, Ingres, Oracle, mSQL) +.TP +.I imfile +Input module for text files +.TP +.I imudp +Input plugin for UDP syslog. Replaces the deprecated -r option. Can be +used like this: +.IP +$ModLoad imudp +.IP +$InputUDPServerRun 514 +.TP +.I imtcp +Input plugin for plain TCP syslog. Replaces the deprecated -t +option. Can be used like this: +.IP +$ModLoad imtcp +.IP +$InputTCPServerRun 514 +.TP +.TP +.I imtcp +Input plugin for the RELP protocol. RELP can be used instead +of UDP or plain TCP syslog to provide reliable delivery of +syslog messages. Please note that plain TCP syslog does NOT +provide truly reliable delivery, with it messages may be lost +when there is a connection problem or the server shuts down. +RELP prevents message loss in those cases. +It can be used like this: +.IP +$ModLoad imrelp +.IP +$InputRELPServerRun 2514 +.TP +.I imgssapi +Input plugin for plain TCP and GSS-enable syslog +.TP +.I immark +Support for mark messages +.TP +.I imklog +Kernel logging. To include kernel log messages, you need to do +.IP +$ModLoad imklog + +Please note that the klogd daemon is no longer necessary and consequently +no longer provided by the rsyslog package. +.TP +.I imuxsock +Unix sockets, including the system log socket. You need to specify +.IP +$ModLoad imudp + +in order to receive log messages from local system processes. This +config directive should only left out if you know exactly what you +are doing. + + .SH BASIC STRUCTURE Lines starting with a hash mark ('#') and empty lines are ignored. @@ -82,7 +170,16 @@ beginning with a slash ('/'). .B Example: .RS -*.* /var/log/traditionalfile.log;TraditionalFormat # log to a file in the traditional format +*.* /var/log/traditionalfile.log;RSYSLOG_TraditionalFormat # log to a file in the traditional format +.RE + +Note: if you would like to use high-precision timestamps in your log files, +just remove the ";RSYSLOG_TraditionalFormat". That will select the default +template, which, if not changed, uses RFC 3339 timestamps. + +.B Example: +.RS +*.* /var/log/file.log # log to a file with RFC3339 timestamps .RE .SS Named pipes @@ -95,9 +192,14 @@ the mkfifo(1) command before rsyslogd(8) is started. If the file you specified is a tty, special tty-handling is done, same with /dev/console. .SS Remote machine -To forward messages to another host, prepend the hostname with the at sign ("@"). A single at -sign means that messages will be forwarded via UDP protocol (the standard for syslog). If you -prepend two at signs ("@@"), the messages will be transmitted via TCP. +There are three ways to forward message: the traditional UDP transport, which is extremely +lossy but standard, the plain TCP based transport which loses messages only during certain +situations but is widely available and the RELP transport which does not lose messages +but is currently available only as part of rsyslogd 3.15.0 and above. + +To forward messages to another host via UDP, prepend the hostname with the at sign ("@"). +To forward it via plain tcp, prepend two at signs ("@@"). To forward via RELP, prepend the +string ":omrelp:" in front of the hostname. .B Example: .RS @@ -105,7 +207,18 @@ prepend two at signs ("@@"), the messages will be transmitted via TCP. .RE .sp In the example above, messages are forwarded via UDP to the machine 192.168.0.1, the destination -port defaults to 514. +port defaults to 514. Due to the nature of UDP, you will probably lose some messages in transit. +If you expect high traffic volume, you can expect to lose a quite noticable number of messages +(the higher the traffic, the more likely and severe is message loss). + +.B If you would like to prevent message loss, use RELP: +.RS +*.* :omrelp:192.168.0.1:2514 +.RE +.sp +Note that a port number was given as there is no standard port for relp. + +Keep in mind that you need to load the correct input and output plugins (see "Modules" above). Please note that rsyslogd offers a variety of options in regarding to remote forwarding. For full details, please see the html documentation. @@ -610,7 +723,6 @@ the html documentation for all features and details. This is especially vital if up a more-then-extremely-simple system. .SH AUTHORS -The .B rsyslogd is taken from sysklogd sources, which have been heavily modified by Rainer Gerhards (rgerhards@adiscon.com) and others. diff --git a/rsyslogd.8 b/rsyslogd.8 index 353fb4c0..fb1505a4 100644 --- a/rsyslogd.8 +++ b/rsyslogd.8 @@ -1,7 +1,7 @@ .\" Copyright 2004-2008 Rainer Gerhards and Adiscon for the rsyslog modifications .\" May be distributed under the GNU General Public License .\" -.TH RSYSLOGD 8 "28 March 2008" "Version 3.12.5 (devel)" "Linux System Administration" +.TH RSYSLOGD 8 "04 April 2008" "Version 3.17.0" "Linux System Administration" .SH NAME rsyslogd \- reliable and extended syslogd .SH SYNOPSIS @@ -45,6 +45,8 @@ To use rsyslog's advanced features, you .B need to look at the html documentation, because the man pages only cover basic aspects of operation. +.B For details and configuration examples, see the rsyslog.conf (5) +.B man page and the online documentation at http://www.rsyslog.com/doc .BR Rsyslogd (8) is derived from the sysklogd package which in turn is derived from the @@ -83,11 +85,11 @@ option, is read at startup. Any lines that begin with the hash mark (``#'') and empty lines are ignored. If an error occurs during parsing the error element is ignored. It is tried to parse the rest of the line. -For details and configuration examples, see the -.B rsyslog.conf (5) -man page. .LP .SH OPTIONS +.B Note that in version 3 of rsyslog a number of command line options +.B have been deprecated and replaced with config file directives. The +.B -c option controls the backward compatibility mode in use. .TP .BI "\-A" When sending UDP messages, there are potentially multiple pathes to @@ -114,6 +116,28 @@ If neither -4 nor -6 is given, .B rsyslogd listens to all configured addresses of the system. .TP +.BI "\-c " "version" +Selects the desired backward compatibility mode. It must always be the +first option on the command line, as it influences processing of the +other options. To use the rsyslog v3 native interface, specify -c3. To +use compatibility mode , either do not use -c at all or use +-c where +.IR version +is the rsyslog version that it shall be +compatible with. Using -c0 tells rsyslog to be command-line compatible +to sysklogd, which is the default if -c is not given. +.B Please note that rsyslogd issues warning messages if the -c3 +.B command line option is not given. +This is to alert you that your are running in compatibility +mode. Compatibility mode interfers with you rsyslog.conf commands and +may cause some undesired side-effects. It is meant to be used with a +plain old rsyslog.conf - if you use new features, things become +messy. So the best advice is to work through this document, convert +your options and config file and then use rsyslog in native mode. In +order to aid you in this process, rsyslog logs every +compatibility-mode config file directive it has generated. So you can +simply copy them from your logfile and paste them to the config. +.TP .B "\-d" Turns on debug mode. Using this the daemon will not proceed a .BR fork (2) @@ -214,51 +238,6 @@ debug option. .B CHLD Wait for childs if some were born, because of wall'ing messages. .LP -.SH SUPPORT FOR REMOTE LOGGING -.B Rsyslogd -provides network support to the syslogd facility. -Network support means that messages can be forwarded from one node -running rsyslogd to another node running rsyslogd (or a -compatible syslog implementation). -actually logged to a disk file. - -To enable this, proper configuration commands must -be entered in rsyslog.conf. See the rsyslog.conf html -documentation for details. - -The strategy is to have rsyslogd listen on a unix domain socket for -locally generated log messages. This behavior will allow rsyslogd to -inter-operate with the syslog found in the standard C library. At the -same time rsyslogd listens on the standard syslog port for messages -forwarded from other hosts. - -.SH OUTPUT TO DATABASES -.B Rsyslogd -has support for writing data to database tables. The exact specifics -are described in the -.B rsyslog.conf (5) -html documentation. Be sure to read it if you plan to use database logging. - -.SH OUTPUT TO NAMED PIPES (FIFOs) -.B Rsyslogd -has support for logging output to named pipes -(fifos). A fifo or named pipe can be used as a destination for log -messages by prepending a pipy symbol (``|'') to the name of the -file. This is handy for debugging. Note that the fifo must be created -with the mkfifo command before -.B rsyslogd -is started. -.IP -The following configuration file routes debug messages from the -kernel to a fifo: -.IP -.nf - # Sample configuration to route kernel debugging - # messages ONLY to /usr/adm/debug which is a - # named pipe. - kern.=debug |/usr/adm/debug -.fi -.LP .SH SECURITY THREATS There is the potential for the rsyslogd daemon to be used as a conduit for a denial of service attack. @@ -314,6 +293,54 @@ The Unix domain socket to from where local syslog messages are read. .I /var/run/rsyslogd.pid The file containing the process id of .BR rsyslogd . +.TP +.I prefix/lib/rsyslog +Default directory for +.B rsyslogd +modules. The +.I prefix +is specified during compilation (e.g. /usr/local). +.SH ENVIRONMENT +.TP +.B RSYSLOG_DEBUG +Controls runtime debug support.It contains an option string with the +following options possible (all are case insensitive): + +.RS +.IP LogFuncFlow +Print out the logical flow of functions (entering and exiting them) +.IP FileTrace +Ppecifies which files to trace LogFuncFlow. If not set (the +default), a LogFuncFlow trace is provided for all files. Set to +limit it to the files specified.FileTrace may be specified multiple +times, one file each (e.g. export RSYSLOG_DEBUG="LogFuncFlow +FileTrace=vm.c FileTrace=expr.c" +.IP PrintFuncDB +Print the content of the debug function database whenever debug +information is printed (e.g. abort case)! +.IP PrintAllDebugInfoOnExit +Print all debug information immediately before rsyslogd exits +(currently not implemented!) +.IP PrintMutexAction +Print mutex action as it happens. Useful for finding deadlocks and +such. +.IP NoLogTimeStamp +Do not prefix log lines with a timestamp (default is to do that). +.IP NoStdOut +Do not emit debug messages to stdout. If RSYSLOG_DEBUGLOG is not +set, this means no messages will be displayed at all. +.IP Help +Display a very short list of commands - hopefully a life saver if +you can't access the documentation... +.RE + +.TP +.B RSYSLOG_DEBUGLOG +If set, writes (allmost) all debug message to the specified log file +in addition to stdout. +.TP +.B RSYSLOG_MODDIR +Provides the default directory in which loadable modules reside. .PD .SH BUGS Please review the file BUGS for up-to-date information on known -- cgit From 54751c7e6e374c130d6d6d5cee5db493f7919fef Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 4 Apr 2008 06:58:48 +0000 Subject: removed the 32 character size limit (from RFC3164) on the tag. This had bad effects on existing envrionments, as sysklogd didn't obey it either (probably another bug in RFC3164...). We now receive the full size, but will modify the outputs so that only 32 characters max are used by default. If you need large tags in the output, you need to provide custom templates. --- ChangeLog | 6 ++++++ syslogd.c | 22 +++++++++------------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index c30c8c7d..6371a746 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,12 @@ Version 3.17.0 (rgerhards), 2008-04-?? timeframe with queues - so things can be configured to be done at off-peak hours - bugfix: some memory leak when queue is runing in disk mode +- We have removed the 32 character size limit (from RFC3164) on the + tag. This had bad effects on existing envrionments, as sysklogd didn't + obey it either (probably another bug in RFC3164...). We now receive + the full size, but will modify the outputs so that only 32 characters + max are used by default. If you need large tags in the output, you need + to provide custom templates. --------------------------------------------------------------------------- Version 3.15.1 (rgerhards), 2008-04-?? - disabled atomic operations for the time being because they introduce some diff --git a/syslogd.c b/syslogd.c index e6dae301..0a786c1f 100644 --- a/syslogd.c +++ b/syslogd.c @@ -424,8 +424,8 @@ static uchar template_SyslogProtocol23Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-r static uchar template_TraditionalFileFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n\""; static uchar template_FileFormat[] = "\"%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n\""; static uchar template_WallFmt[] = "\"\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n %syslogtag%%msg%\n\r\""; -static uchar template_ForwardFormat[] = "\"<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg%\""; -static uchar template_TraditionalForwardFormat[] = "\"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag%%msg%\""; +static uchar template_ForwardFormat[] = "\"<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32%%msg%\""; +static uchar template_TraditionalForwardFormat[] = "\"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag:1:32%%msg%\""; static uchar template_StdUsrMsgFmt[] = "\" %syslogtag%%msg%\n\r\""; static uchar template_StdDBFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')\",SQL"; static uchar template_StdPgSQLFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-pgsql%', '%timegenerated:::date-pgsql%', %iut%, '%syslogtag%')\",STDSQL"; @@ -1410,7 +1410,6 @@ static int parseLegacySyslogMsg(msg_t *pMsg, int flags) * machine that we received the message from and the tag will be empty. This * is meant to be an interim solution, but for now it is in the code. */ - if(bParseHOSTNAMEandTAG && !(flags & INTERNAL_MSG)) { /* parse HOSTNAME - but only if this is network-received! * rger, 2005-11-14: we still have a problem with BSD messages. These messages @@ -1468,16 +1467,18 @@ static int parseLegacySyslogMsg(msg_t *pMsg, int flags) MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg)); } - /* now parse TAG - that should be present in message from - * all sources. + /* now parse TAG - that should be present in message from all sources. * This code is somewhat not compliant with RFC 3164. As of 3164, * the TAG field is ended by any non-alphanumeric character. In * practice, however, the TAG often contains dashes and other things, * which would end the TAG. So it is not desirable. As such, we only * accept colon and SP to be terminators. Even there is a slight difference: * a colon is PART of the TAG, while a SP is NOT part of the tag - * (it is CONTENT). Finally, we allow only up to 32 characters for - * TAG, as it is specified in RFC 3164. + * (it is CONTENT). Starting 2008-04-04, we have removed the 32 character + * size limit (from RFC3164) on the tag. This had bad effects on existing + * envrionments, as sysklogd didn't obey it either (probably another bug + * in RFC3164...). We now receive the full size, but will modify the + * outputs so that only 32 characters max are used by default. */ /* The following code in general is quick & dirty - I need to get * it going for a test, rgerhards 2004-11-16 */ @@ -1491,15 +1492,10 @@ static int parseLegacySyslogMsg(msg_t *pMsg, int flags) rsCStrSetAllocIncrement(pStrB, 33); pWork = pBuf; iCnt = 0; - while(*p2parse && *p2parse != ':' && *p2parse != ' ' && iCnt < 32) { + while(*p2parse && *p2parse != ':' && *p2parse != ' ') { rsCStrAppendChar(pStrB, *p2parse++); ++iCnt; } - if (iCnt == 32) { - while(*p2parse && *p2parse != ':' && *p2parse != ' ') { - ++p2parse; - } - } if(*p2parse == ':') { ++p2parse; rsCStrAppendChar(pStrB, ':'); -- cgit From f5250a3a92ec4c1738556f3cc5139dbc15579add Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 4 Apr 2008 08:34:31 +0000 Subject: changed command line processing. -v, -M, -c options are now parsed and processed before all other options. Inter-option dependencies have been relieved. Among others, permits to specify intial module load path via -M only (not the environment) which makes it much easier to work with non-standard module library locations. Thanks to varmojfekoj for suggesting this change. Matches bugzilla bug 55. --- ChangeLog | 6 ++ glbl.h | 1 + modules.c | 11 +++ obj.c | 7 +- syslogd.c | 251 ++++++++++++++++++++++++++++++++++++++++++++++---------------- wtp.h | 1 + 6 files changed, 208 insertions(+), 69 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6371a746..0024a47f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,12 @@ Version 3.17.0 (rgerhards), 2008-04-?? the full size, but will modify the outputs so that only 32 characters max are used by default. If you need large tags in the output, you need to provide custom templates. +- changed command line processing. -v, -M, -c options are now parsed + and processed before all other options. Inter-option dependencies + have been relieved. Among others, permits to specify intial module + load path via -M only (not the environment) which makes it much + easier to work with non-standard module library locations. Thanks + to varmojfekoj for suggesting this change. Matches bugzilla bug 55. --------------------------------------------------------------------------- Version 3.15.1 (rgerhards), 2008-04-?? - disabled atomic operations for the time being because they introduce some diff --git a/glbl.h b/glbl.h index fb55fb76..6d08ddd5 100644 --- a/glbl.h +++ b/glbl.h @@ -33,6 +33,7 @@ #define glblGetIOBufSize() 4096 /* size of the IO buffer, e.g. for strm class */ +extern uchar *glblModPath; /* module load path */ extern uchar *pszWorkDir; #define glblGetWorkDir() (pszWorkDir == NULL ? (uchar*) "" : pszWorkDir) diff --git a/modules.c b/modules.c index 86ee64a5..623a2f10 100644 --- a/modules.c +++ b/modules.c @@ -783,6 +783,17 @@ BEGINAbstractObjClassInit(module, 1, OBJ_IS_CORE_MODULE) /* class, version - CHA SetModDir(pModPath); } + /* now check if another module path was set via the command line (-M) + * if so, that overrides the environment. Please note that we must use + * a global setting here because the command line parser can NOT call + * into the module object, because it is not initialized at that point. So + * instead a global setting is changed and we pick it up as soon as we + * initialize -- rgerhards, 2008-04-04 + */ + if(glblModPath != NULL) { + SetModDir(glblModPath); + } + /* request objects we use */ CHKiRet(objUse(errmsg, CORE_COMPONENT)); ENDObjClassInit(module) diff --git a/obj.c b/obj.c index d408c4bb..51c7c9df 100644 --- a/obj.c +++ b/obj.c @@ -1073,7 +1073,7 @@ RegisterObj(uchar *pszObjName, objInfo_t *pInfo) if(i >= OBJ_NUM_IDS) ABORT_FINALIZE(RS_RET_OBJ_REGISTRY_OUT_OF_SPACE); arrObjInfo[i] = pInfo; - dbgprintf("object '%s' successfully registered with index %d, qIF %p\n", pszObjName, i, pInfo->QueryIF); + /* DEV debug only: dbgprintf("object '%s' successfully registered with index %d, qIF %p\n", pszObjName, i, pInfo->QueryIF); */ finalize_it: if(iRet != RS_RET_OK) { @@ -1113,7 +1113,7 @@ UnregisterObj(uchar *pszObjName, objInfo_t *pInfo) ABORT_FINALIZE(RS_RET_OBJ_NOT_REGISTERED); InfoDestruct(&arrObjInfo[i]); - dbgprintf("object '%s' successfully unregistered with index %d\n", pszObjName, i); + /* DEV debug only: dbgprintf("object '%s' successfully unregistered with index %d\n", pszObjName, i); */ finalize_it: if(iRet != RS_RET_OK) { @@ -1137,7 +1137,7 @@ UseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf) objInfo_t *pObjInfo; - dbgprintf("source file %s requests object '%s', ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded); + /* DEV debug only: dbgprintf("source file %s requests object '%s', ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded); */ if(pIf->ifIsLoaded == 1) { ABORT_FINALIZE(RS_RET_OK); /* we are already set */ @@ -1170,7 +1170,6 @@ UseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf) } /* if we reach this point, we have a valid pObjInfo */ - //if(pObjInfo->pModInfo != NULL) { /* NULL means core module */ if(pObjFile != NULL) { /* NULL means core module */ module.Use(srcFile, pObjInfo->pModInfo); /* increase refcount */ } diff --git a/syslogd.c b/syslogd.c index 0a786c1f..bb161528 100644 --- a/syslogd.c +++ b/syslogd.c @@ -302,6 +302,7 @@ static int bEscapeCCOnRcv = 1; /* escape control characters on reception: 0 - n int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */ int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */ uchar *pszWorkDir = NULL;/* name of rsyslog's spool directory (without trailing slash) */ +extern uchar *glblModPath = NULL; /* module load path - only used during initial init, only settable via -M command line option */ /* end global config file state variables */ char LocalHostName[MAXHOSTNAMELEN+1];/* our hostname - read-only after startup */ @@ -2197,8 +2198,7 @@ init(void) pDfltProgNameCmp = NULL; eDfltHostnameCmpMode = HN_NO_COMP; - dbgprintf("rsyslog %s.\n", VERSION); - dbgprintf("Called init.\n"); + dbgprintf("rsyslog %s - called init()\n", VERSION); /* delete the message queue, which also flushes all messages left over */ if(pMsgQueue != NULL) { @@ -2792,7 +2792,6 @@ static void mainThread() pTmp = template_StdPgSQLFmt; tplLastStaticInit(tplAddLine(" StdPgSQLFmt", &pTmp)); - dbgprintf("Starting.\n"); init(); if(Debug) { dbgprintf("Debugging enabled, SIGUSR1 to turn off debugging.\n"); @@ -2809,6 +2808,7 @@ static void mainThread() * do the init() and then restart things. * rgerhards, 2005-10-24 */ + dbgprintf("initialization completed, transitioning to regular run mode\n"); mainloop(); ENDfunc @@ -2962,6 +2962,72 @@ dbgprintf("post strExit()\n"); } +/* some support for command line option parsing. Any non-trivial options must be + * buffered until the complete command line has been parsed. This is necessary to + * prevent dependencies between the options. That, in turn, means we need to have + * something that is capable of buffering options and there values. The follwing + * functions handle that. + * rgerhards, 2008-04-04 + */ +typedef struct bufOpt { + struct bufOpt *pNext; + char optchar; + char *arg; +} bufOpt_t; +static bufOpt_t *bufOptRoot = NULL; +static bufOpt_t *bufOptLast = NULL; + +/* add option buffer */ +static rsRetVal +bufOptAdd(char opt, char *arg) +{ + DEFiRet; + bufOpt_t *pBuf; + + if((pBuf = malloc(sizeof(bufOpt_t))) == NULL) + ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); + + pBuf->optchar = opt; + pBuf->arg = arg; + pBuf->pNext = NULL; + + if(bufOptLast == NULL) { + bufOptRoot = pBuf; /* then there is also no root! */ + } else { + bufOptLast->pNext = pBuf; + } + bufOptLast = pBuf; + +finalize_it: + RETiRet; +} + + + +/* remove option buffer from top of list, return values and destruct buffer itself. + * returns RS_RET_END_OF_LINKEDLIST when no more options are present. + * (we use int *opt instead of char *opt to keep consistent with getopt()) + */ +static rsRetVal +bufOptRemove(int *opt, char **arg) +{ + DEFiRet; + bufOpt_t *pBuf; + + if(bufOptRoot == NULL) + ABORT_FINALIZE(RS_RET_END_OF_LINKEDLIST); + pBuf = bufOptRoot; + + *opt = pBuf->optchar; + *arg = pBuf->arg; + + bufOptRoot = pBuf->pNext; + free(pBuf); + +finalize_it: + RETiRet; +} + /* This is the main entry point into rsyslogd. Over time, we should try to * modularize it a bit more... @@ -2981,8 +3047,106 @@ int realMain(int argc, char **argv) int bIsFirstOption = 1; int bEOptionWasGiven = 0; int bImUxSockLoaded = 0; /* already generated a $ModLoad imuxsock? */ + char *arg; /* for command line option processing */ uchar legacyConfLine[80]; + /* first, parse the command line options. We do not carry out any actual work, just + * see what we should do. This relieves us from certain anomalies and we can process + * the parameters down below in the correct order. For example, we must know the + * value of -M before we can do the init, but at the same time we need to have + * the base classes init before we can process most of the options. Now, with the + * split of functionality, this is no longer a problem. Thanks to varmofekoj for + * suggesting this algo. + * Note: where we just need to set some flags and can do so without knowledge + * of other options, we do this during the inital option processing. With later + * versions (if a dependency on -c option is introduced), we must move that code + * to other places, but I think it is quite appropriate and saves code to do this + * only when actually neeeded. + * rgerhards, 2008-04-04 + */ + while ((ch = getopt(argc, argv, "46Ac:dehi:f:g:l:m:M:nqQr::s:t:u:vwx")) != EOF) { + switch((char)ch) { + case '4': + case '6': + case 'A': + case 'a': + case 'f': /* configuration file */ + case 'h': + case 'i': /* pid file name */ + case 'l': + case 'm': /* mark interval */ + case 'n': /* don't fork */ + case 'o': + case 'p': + case 'q': /* add hostname if DNS resolving has failed */ + case 'Q': /* dont resolve hostnames in ACL to IPs */ + case 's': + case 'u': /* misc user settings */ + case 'w': /* disable disallowed host warnigs */ + case 'x': /* disable dns for remote messages */ + CHKiRet(bufOptAdd(ch, optarg)); + break; + case 'c': /* compatibility mode */ + if(!bIsFirstOption) { + fprintf(stderr, "-c option MUST be specified as the first option - aborting...\n"); + usage(); + exit(1); + } + iCompatibilityMode = atoi(optarg); + break; + case 'd': /* debug - must be handled now, so that debug is active during init! */ + Debug = 1; + break; + case 'e': /* log every message (no repeat message supression) */ + fprintf(stderr, "note: -e option is no longer supported, every message is now logged by default\n"); + bEOptionWasGiven = 1; + break; + case 'g': /* enable tcp gssapi logging */ +#if defined(SYSLOG_INET) && defined(USE_GSSAPI) + CHKiRet(bufOptAdd('g', optarg)); +#else + fprintf(stderr, "rsyslogd: -g not valid - not compiled with gssapi support"); +#endif + break; + case 'M': /* default module load path -- this MUST be carried out immediately! */ + glblModPath = (uchar*) optarg; + break; + case 'r': /* accept remote messages */ +#ifdef SYSLOG_INET + CHKiRet(bufOptAdd(ch, optarg)); +#else + fprintf(stderr, "rsyslogd: -r not valid - not compiled with network support\n"); +#endif + break; + case 't': /* enable tcp logging */ +#ifdef SYSLOG_INET + CHKiRet(bufOptAdd(ch, optarg)); +#else + fprintf(stderr, "rsyslogd: -t not valid - not compiled with network support\n"); +#endif + break; + case 'v': /* MUST be carried out immediately! */ + printVersion(); + exit(0); /* exit for -v option - so this is a "good one" */ + case '?': + default: + usage(); + } + bIsFirstOption = 0; /* we already saw an option character */ + } + + if ((argc -= optind)) + usage(); + + dbgprintf("rsyslogd %s startup, compatibility mode %d, module path '%s'\n", + VERSION, iCompatibilityMode, glblModPath == NULL ? "" : (char*)glblModPath); + + /* we are done with the initial option parsing and processing. Now we init the system. */ + + ppid = getpid(); + + if(chdir ("/") != 0) + fprintf(stderr, "Can not do 'cd /' - still trying to run\n"); CHKiRet_Hdlr(InitGlobalClasses()) { fprintf(stderr, "rsyslogd initializiation failed - global classes could not be initialized.\n" @@ -3005,14 +3169,10 @@ int realMain(int argc, char **argv) exit(1); /* "good" exit, leaving at init for fatal error */ } - ppid = getpid(); - - if(chdir ("/") != 0) - fprintf(stderr, "Can not do 'cd /' - still trying to run\n"); + /* END core initializations - we now come back to carrying out command line options*/ - /* END core initializations */ - - while ((ch = getopt(argc, argv, "46Ac:dehi:f:g:l:m:M:nqQr::s:t:u:vwx")) != EOF) { + while((iRet = bufOptRemove(&ch, &arg)) == RS_RET_OK) { +dbgprintf("deque option %c, optarg '%s'\n", ch, arg); switch((char)ch) { case '4': family = PF_INET; @@ -3029,39 +3189,20 @@ int realMain(int argc, char **argv) legacyOptsEnq((uchar *) "ModLoad imuxsock"); bImUxSockLoaded = 1; } - snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "addunixlistensocket %s", optarg); + snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "addunixlistensocket %s", arg); legacyOptsEnq(legacyConfLine); } else { fprintf(stderr, "error -a is no longer supported, use module imuxsock instead"); } break; - case 'c': /* compatibility mode */ - if(!bIsFirstOption) { - fprintf(stderr, "-c option MUST be specified as the first option - aborting...\n"); - usage(); - exit(1); - } - iCompatibilityMode = atoi(optarg); - break; - case 'd': /* debug */ - Debug = 1; - break; - case 'e': /* log every message (no repeat message supression) */ - fprintf(stderr, "note: -e option is no longer supported, every message is now logged by default\n"); - bEOptionWasGiven = 1; - break; case 'f': /* configuration file */ - ConfFile = (uchar*) optarg; + ConfFile = (uchar*) arg; break; case 'g': /* enable tcp gssapi logging */ -#if defined(SYSLOG_INET) && defined(USE_GSSAPI) if(iCompatibilityMode < 3) { - legacyOptsParseTCP(ch, optarg); + legacyOptsParseTCP(ch, arg); } else fprintf(stderr, "-g option only supported in compatibility modes 0 to 2 - ignored\n"); -#else - fprintf(stderr, "rsyslogd: -g not valid - not compiled with gssapi support"); -#endif break; case 'h': if(iCompatibilityMode < 3) { @@ -3071,25 +3212,22 @@ int realMain(int argc, char **argv) } break; case 'i': /* pid file name */ - PidFile = optarg; + PidFile = arg; break; case 'l': if (LocalHosts) { fprintf (stderr, "rsyslogd: Only one -l argument allowed, the first one is taken.\n"); } else { - LocalHosts = crunch_list(optarg); + LocalHosts = crunch_list(arg); } break; case 'm': /* mark interval */ if(iCompatibilityMode < 3) { - MarkInterval = atoi(optarg) * 60; + MarkInterval = atoi(arg) * 60; } else fprintf(stderr, "-m option only supported in compatibility modes 0 to 2 - ignored\n"); break; - case 'M': /* default module load path */ - module.SetModDir((uchar*)optarg); - break; case 'n': /* don't fork */ NoFork = 1; break; @@ -3110,7 +3248,7 @@ int realMain(int argc, char **argv) legacyOptsEnq((uchar *) "ModLoad imuxsock"); bImUxSockLoaded = 1; } - snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "SystemLogSocketName %s", optarg); + snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "SystemLogSocketName %s", arg); legacyOptsEnq(legacyConfLine); } else { fprintf(stderr, "error -p is no longer supported, use module imuxsock instead"); @@ -3122,42 +3260,30 @@ int realMain(int argc, char **argv) *net.pACLDontResolve = 1; break; case 'r': /* accept remote messages */ -#ifdef SYSLOG_INET if(iCompatibilityMode < 3) { legacyOptsEnq((uchar *) "ModLoad imudp"); - snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "UDPServerRun %s", optarg); + snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "UDPServerRun %s", arg); legacyOptsEnq(legacyConfLine); } else - fprintf(stderr, - "-r option only supported in compatibility modes 0 to 2 - ignored\n"); -#else - fprintf(stderr, "rsyslogd: -r not valid - not compiled with network support\n"); -#endif + fprintf(stderr, "-r option only supported in compatibility modes 0 to 2 - ignored\n"); break; case 's': if (StripDomains) { fprintf (stderr, "rsyslogd: Only one -s argument allowed, the first one is taken.\n"); } else { - StripDomains = crunch_list(optarg); + StripDomains = crunch_list(arg); } break; case 't': /* enable tcp logging */ -#ifdef SYSLOG_INET if(iCompatibilityMode < 3) { - legacyOptsParseTCP(ch, optarg); + legacyOptsParseTCP(ch, arg); } else fprintf(stderr, "-t option only supported in compatibility modes 0 to 2 - ignored\n"); -#else - fprintf(stderr, "rsyslogd: -t not valid - not compiled with network support\n"); -#endif break; case 'u': /* misc user settings */ - if(atoi(optarg) == 1) + if(atoi(arg) == 1) bParseHOSTNAMEandTAG = 0; break; - case 'v': - printVersion(); - exit(0); /* exit for -v option - so this is a "good one" */ case 'w': /* disable disallowed host warnigs */ option_DisallowWarning = 0; break; @@ -3168,15 +3294,12 @@ int realMain(int argc, char **argv) default: usage(); } - bIsFirstOption = 0; /* we already saw an option character */ } - if ((argc -= optind)) - usage(); + if(iRet != RS_RET_END_OF_LINKEDLIST) + FINALIZE; - /* TODO: this should go away at a reasonable stage of v3 development. - * rgerhards, 2007-12-19 - */ + /* process compatibility mode settings */ if(iCompatibilityMode < 3) { errmsg.LogError(NO_ERRCODE, "WARNING: rsyslogd is running in compatibility mode. Automatically " "generated config directives may interfer with your rsyslog.conf settings. " @@ -3202,7 +3325,7 @@ int realMain(int argc, char **argv) checkPermissions(); thrdInit(); - if ( !(Debug || NoFork) ) + if( !(Debug || NoFork) ) { dbgprintf("Checking pidfile.\n"); if (!check_pid(PidFile)) @@ -3241,8 +3364,6 @@ int realMain(int argc, char **argv) else debugging_on = 1; - dbgprintf("Compatibility Mode: %d\n", iCompatibilityMode); - /* tuck my process id away */ dbgprintf("Writing pidfile %s.\n", PidFile); if (!check_pid(PidFile)) diff --git a/wtp.h b/wtp.h index b928b149..e47f9fe6 100644 --- a/wtp.h +++ b/wtp.h @@ -100,6 +100,7 @@ rsRetVal wtpShutdownAll(wtp_t *pThis, wtpState_t tShutdownCmd, struct timespec * int wtpGetCurNumWrkr(wtp_t *pThis, int bLockMutex); PROTOTYPEObjClassInit(wtp); PROTOTYPEpropSetMethFP(wtp, pfChkStopWrkr, rsRetVal(*pVal)(void*, int)); +PROTOTYPEpropSetMethFP(wtp, pfRateLimiter, rsRetVal(*pVal)(void*)); PROTOTYPEpropSetMethFP(wtp, pfIsIdle, rsRetVal(*pVal)(void*, int)); PROTOTYPEpropSetMethFP(wtp, pfDoWork, rsRetVal(*pVal)(void*, void*, int)); PROTOTYPEpropSetMethFP(wtp, pfOnIdle, rsRetVal(*pVal)(void*, int)); -- cgit From 8c04e4ef36524aab6281bcecc4cac171e718a426 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 4 Apr 2008 12:03:45 +0000 Subject: bugfix: zero-length strings were not supported in object deserializer --- ChangeLog | 2 ++ obj.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0024a47f..dc45d4b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,8 @@ Version 3.17.0 (rgerhards), 2008-04-?? - FEATURE FOCUS for 3.17 is TLS over plain TCP syslog - removed no longer needed file relptuil.c/.h - bugfix: memory leaks in script engine +- bugfix: zero-length strings were not supported in object + deserializer - properties are now case-insensitive everywhere (script, filters, templates) - added the capability to specify a processing (actually dequeue) diff --git a/obj.c b/obj.c index 51c7c9df..3485803d 100644 --- a/obj.c +++ b/obj.c @@ -495,7 +495,7 @@ finalize_it: } -/* de-serialize a string, length must be provided */ +/* de-serialize a string, length must be provided but may be 0 */ static rsRetVal objDeserializeStr(cstr_t **ppCStr, int iLen, strm_t *pStrm) { DEFiRet; @@ -504,7 +504,7 @@ static rsRetVal objDeserializeStr(cstr_t **ppCStr, int iLen, strm_t *pStrm) cstr_t *pCStr = NULL; assert(ppCStr != NULL); - assert(iLen > 0); + assert(iLen >= 0); CHKiRet(rsCStrConstruct(&pCStr)); -- cgit From cee20af583a19ee2eb7db4664678a41dd6de11d4 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 4 Apr 2008 12:31:01 +0000 Subject: bugfix: some messages were emited without hostname --- ChangeLog | 1 + syslogd.c | 86 ++++++++++++++++++++++++++++++++------------------------------- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index dc45d4b2..35c71f85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -23,6 +23,7 @@ Version 3.17.0 (rgerhards), 2008-04-?? load path via -M only (not the environment) which makes it much easier to work with non-standard module library locations. Thanks to varmojfekoj for suggesting this change. Matches bugzilla bug 55. +- bugfix: some messages were emited without hostname --------------------------------------------------------------------------- Version 3.15.1 (rgerhards), 2008-04-?? - disabled atomic operations for the time being because they introduce some diff --git a/syslogd.c b/syslogd.c index bb161528..d2f3e3b6 100644 --- a/syslogd.c +++ b/syslogd.c @@ -302,7 +302,7 @@ static int bEscapeCCOnRcv = 1; /* escape control characters on reception: 0 - n int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */ int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */ uchar *pszWorkDir = NULL;/* name of rsyslog's spool directory (without trailing slash) */ -extern uchar *glblModPath = NULL; /* module load path - only used during initial init, only settable via -M command line option */ +uchar *glblModPath = NULL; /* module load path - only used during initial init, only settable via -M command line option */ /* end global config file state variables */ char LocalHostName[MAXHOSTNAMELEN+1];/* our hostname - read-only after startup */ @@ -3157,6 +3157,49 @@ int realMain(int argc, char **argv) } /* doing some core initializations */ + + /* get our host and domain names - we need to do this early as we may emit + * error log messages, which need the correct hostname. -- rgerhards, 2008-04-04 + */ + gethostname(LocalHostName, sizeof(LocalHostName)); + if((p = strchr(LocalHostName, '.'))) { + *p++ = '\0'; + LocalDomain = p; + } else { + LocalDomain = ""; + + /* It's not clearly defined whether gethostname() + * should return the simple hostname or the fqdn. A + * good piece of software should be aware of both and + * we want to distribute good software. Joey + * + * Good software also always checks its return values... + * If syslogd starts up before DNS is up & /etc/hosts + * doesn't have LocalHostName listed, gethostbyname will + * return NULL. + */ + /* TODO: gethostbyname() is not thread-safe, but replacing it is + * not urgent as we do not run on multiple threads here. rgerhards, 2007-09-25 + */ + hent = gethostbyname(LocalHostName); + if(hent) { + snprintf(LocalHostName, sizeof(LocalHostName), "%s", hent->h_name); + + if ( (p = strchr(LocalHostName, '.')) ) + { + *p++ = '\0'; + LocalDomain = p; + } + } + } + + /* Convert to lower case to recognize the correct domain laterly + */ + for (p = (char *)LocalDomain; *p ; p++) + if (isupper((int) *p)) + *p = (char)tolower((int)*p); + + /* initialize the objects */ if((iRet = modInitIminternal()) != RS_RET_OK) { fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n", iRet); @@ -3381,47 +3424,6 @@ dbgprintf("deque option %c, optarg '%s'\n", ch, arg); } myPid = getpid(); /* save our pid for further testing (also used for messages) */ - - gethostname(LocalHostName, sizeof(LocalHostName)); - if ( (p = strchr(LocalHostName, '.')) ) { - *p++ = '\0'; - LocalDomain = p; - } - else - { - LocalDomain = ""; - - /* It's not clearly defined whether gethostname() - * should return the simple hostname or the fqdn. A - * good piece of software should be aware of both and - * we want to distribute good software. Joey - * - * Good software also always checks its return values... - * If syslogd starts up before DNS is up & /etc/hosts - * doesn't have LocalHostName listed, gethostbyname will - * return NULL. - */ - /* TODO: gethostbyname() is not thread-safe, but replacing it is - * not urgent as we do not run on multiple threads here. rgerhards, 2007-09-25 - */ - hent = gethostbyname(LocalHostName); - if(hent) { - snprintf(LocalHostName, sizeof(LocalHostName), "%s", hent->h_name); - - if ( (p = strchr(LocalHostName, '.')) ) - { - *p++ = '\0'; - LocalDomain = p; - } - } - } - - /* Convert to lower case to recognize the correct domain laterly - */ - for (p = (char *)LocalDomain; *p ; p++) - if (isupper((int) *p)) - *p = (char)tolower((int)*p); - memset(&sigAct, 0, sizeof (sigAct)); sigemptyset(&sigAct.sa_mask); -- cgit From 5ba8b2c77c3971a69bde54f3dd0ede81e641d798 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 4 Apr 2008 12:35:28 +0000 Subject: cleanup --- queue.c | 9 ++------- syslogd.c | 10 ++++------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/queue.c b/queue.c index 7456f4a6..0828cc1d 100644 --- a/queue.c +++ b/queue.c @@ -1416,12 +1416,10 @@ queueDequeueConsumable(queue_t *pThis, wti_t *pWti, int iCancelStateSave) * on the nail [exact value]) -- rgerhards, 2008-03-14 */ if(iQueueSize < pThis->iFullDlyMrk) { -dbgoprint((obj_t*) pThis, "queue size %d below FullDlyMrk %d\n", iQueueSize, pThis->iFullDlyMrk); pthread_cond_broadcast(&pThis->belowFullDlyWtrMrk); } if(iQueueSize < pThis->iLightDlyMrk) { -dbgoprint((obj_t*) pThis, "queue size %d below LightDlyMrk %d\n", iQueueSize, pThis->iLightDlyMrk); pthread_cond_broadcast(&pThis->belowLightDlyWtrMrk); } @@ -1455,9 +1453,9 @@ finalize_it: } -/* The rate limiter - we only need one - do we? +/* The rate limiter * -* Here we may wait if a dequeue time window is defined or if we are + * Here we may wait if a dequeue time window is defined or if we are * rate-limited. TODO: If we do so, we should also look into the * way new worker threads are spawned. Obviously, it doesn't make much * sense to spawn additional worker threads when none of them can do any @@ -1506,13 +1504,11 @@ queueRateLimiter(queue_t *pThis) dbgoprint((obj_t*) pThis, "entering rate limiter\n"); iDelay = 0; -dbgprintf("deq win from %d to %d\n", pThis->iDeqtWinFromHr, pThis->iDeqtWinToHr); if(pThis->iDeqtWinToHr != 25) { /* 25 means disabled */ /* time calls are expensive, so only do them when needed */ time(&tCurr); localtime_r(&tCurr, &m); iHrCurr = m.tm_hour; -RUNLOG_VAR("%d", iHrCurr); if(pThis->iDeqtWinToHr < pThis->iDeqtWinFromHr) { if(iHrCurr < pThis->iDeqtWinToHr || iHrCurr > pThis->iDeqtWinFromHr) { @@ -1550,7 +1546,6 @@ RUNLOG_VAR("%d", iHrCurr); srSleep(iDelay, 0); } - dbgoprint((obj_t*) pThis, "rate limiter returns with iRet %d\n", iRet); RETiRet; } diff --git a/syslogd.c b/syslogd.c index d2f3e3b6..904bdbd3 100644 --- a/syslogd.c +++ b/syslogd.c @@ -3193,11 +3193,9 @@ int realMain(int argc, char **argv) } } - /* Convert to lower case to recognize the correct domain laterly - */ - for (p = (char *)LocalDomain; *p ; p++) - if (isupper((int) *p)) - *p = (char)tolower((int)*p); + /* Convert to lower case to recognize the correct domain laterly */ + for (p = (char *)LocalDomain ; *p ; p++) + *p = (char)tolower((int)*p); /* initialize the objects */ if((iRet = modInitIminternal()) != RS_RET_OK) { @@ -3215,7 +3213,7 @@ int realMain(int argc, char **argv) /* END core initializations - we now come back to carrying out command line options*/ while((iRet = bufOptRemove(&ch, &arg)) == RS_RET_OK) { -dbgprintf("deque option %c, optarg '%s'\n", ch, arg); + dbgprintf("deque option %c, optarg '%s'\n", ch, arg); switch((char)ch) { case '4': family = PF_INET; -- cgit From c0c9f44966b00bba9c3eaa962cdf6f0010a8f781 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 4 Apr 2008 13:34:47 +0000 Subject: begun work on mail output plugin (open questions on TLS, so I see if I can put this in between) - does not the least yet work ;) --- Makefile.am | 4 + configure.ac | 15 ++++ plugins/ommail/Makefile.am | 6 ++ plugins/ommail/ommail.c | 216 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 241 insertions(+) create mode 100644 plugins/ommail/Makefile.am create mode 100644 plugins/ommail/ommail.c diff --git a/Makefile.am b/Makefile.am index f97687c1..6aea7600 100644 --- a/Makefile.am +++ b/Makefile.am @@ -217,3 +217,7 @@ endif if ENABLE_IMFILE SUBDIRS += plugins/imfile endif + +if ENABLE_MAIL +SUBDIRS += plugins/ommail +endif diff --git a/configure.ac b/configure.ac index 8b407ccf..a938eae2 100644 --- a/configure.ac +++ b/configure.ac @@ -491,6 +491,19 @@ AC_ARG_ENABLE(rsyslogd, AM_CONDITIONAL(ENABLE_RSYSLOGD, test x$enable_rsyslogd = xyes) +# Mail support (so far we do not need a library, but we need to turn this on and off) +AC_ARG_ENABLE(mail, + [AS_HELP_STRING([--enable-mail],[Enable mail support @<:@default=no@:>@])], + [case "${enableval}" in + yes) enable_mail="yes" ;; + no) enable_mail="no" ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-mail) ;; + esac], + [enable_mail=no] +) +AM_CONDITIONAL(ENABLE_MAIL, test x$enable_mail = xyes) + + # RELP support AC_ARG_ENABLE(relp, [AS_HELP_STRING([--enable-relp],[Enable RELP support @<:@default=no@:>@])], @@ -598,6 +611,7 @@ AC_CONFIG_FILES([Makefile \ plugins/ompgsql/Makefile \ plugins/omrelp/Makefile \ plugins/omlibdbi/Makefile \ + plugins/ommail/Makefile \ plugins/omsnmp/Makefile]) AC_OUTPUT @@ -612,6 +626,7 @@ echo "MySql support enabled: $enable_mysql" echo "libdbi support enabled: $enable_libdbi" echo "PostgreSQL support enabled: $enable_pgsql" echo "SNMP support enabled: $enable_snmp" +echo "Mail support enabled: $enable_mail" echo "RELP support enabled: $enable_relp" echo "file input module enabled: $enable_imfile" echo "input template module will be compiled: $enable_imtemplate" diff --git a/plugins/ommail/Makefile.am b/plugins/ommail/Makefile.am new file mode 100644 index 00000000..7e9f5f13 --- /dev/null +++ b/plugins/ommail/Makefile.am @@ -0,0 +1,6 @@ +pkglib_LTLIBRARIES = ommail.la + +ommail_la_SOURCES = ommail.c +ommail_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) +ommail_la_LDFLAGS = -module -avoid-version +ommail_la_LIBADD = diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c new file mode 100644 index 00000000..8a24c279 --- /dev/null +++ b/plugins/ommail/ommail.c @@ -0,0 +1,216 @@ +/* ommail.c + * + * This is an implementation of a mail sending output module. + * + * NOTE: read comments in module-template.h to understand how this file + * works! + * + * File begun on 2008-04-04 by RGerhards + * + * Copyright 2008 Rainer Gerhards and Adiscon GmbH. + * + * This file is part of rsyslog. + * + * Rsyslog 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, either version 3 of the License, or + * (at your option) any later version. + * + * Rsyslog 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 Rsyslog. If not, see . + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + */ +#include "config.h" +#include "rsyslog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "syslogd.h" +#include "syslogd-types.h" +#include "srUtils.h" +#include "cfsysline.h" +#include "module-template.h" +#include "errmsg.h" + +MODULE_TYPE_OUTPUT + +/* internal structures + */ +DEF_OMOD_STATIC_DATA +DEFobjCurrIf(errmsg) + +static uchar *pSrv; +static uchar *pszFrom; +static uchar *pszTo; + +typedef struct _instanceData { + int iMode; /* 0 - smtp, 1 - sendmail */ + union { + struct { + uchar *pszSrv; + uchar *pszSrvPort; + uchar *pszFrom; + uchar *pszTo; + int sock; /* socket to this server (most important when we do multiple msgs per mail) */ + } smtp; + } md; /* mode-specific data */ +} instanceData; + + +BEGINcreateInstance +CODESTARTcreateInstance + pData->bInitialConnect = 1; +ENDcreateInstance + + +BEGINisCompatibleWithFeature +CODESTARTisCompatibleWithFeature + if(eFeat == sFEATURERepeatedMsgReduction) + iRet = RS_RET_OK; +ENDisCompatibleWithFeature + + +BEGINfreeInstance +CODESTARTfreeInstance + if(pThis->iMode == 0) { + if(pThis->md.smtp.pszSrv != NULL) + free(pThis->md.smtp.pszSrv); + if(pThis->md.smtp.pszSrvPort != NULL) + free(pThis->md.smtp.pszSrvPort); + if(pThis->md.smtp.pszFrom != NULL) + free(pThis->md.smtp.pszFrom); + if(pThis->md.smtp.pszTo != NULL) + free(pThis->md.smtp.pszTo); + } + +ENDfreeInstance + + +BEGINdbgPrintInstInfo +CODESTARTdbgPrintInstInfo + printf("mail"); /* TODO: extend! */ +ENDdbgPrintInstInfo + + +/* try to connect to server + * rgerhards, 2008-03-21 + */ +static rsRetVal doConnect(instanceData *pData) +{ + DEFiRet; + + if(pData->bInitialConnect) { + iRet = relpCltConnect(pData->pRelpClt, family, (uchar*) pData->port, (uchar*) pData->f_hname); + if(iRet == RELP_RET_OK) + pData->bInitialConnect = 0; + } else { + iRet = relpCltReconnect(pData->pRelpClt); + } + + if(iRet == RELP_RET_OK) { + pData->bIsConnected = 1; + } else { + pData->bIsConnected = 0; + iRet = RS_RET_SUSPENDED; + } + + RETiRet; +} + + +BEGINtryResume +CODESTARTtryResume + iRet = doConnect(pData); +ENDtryResume + + +BEGINdoAction + uchar *pMsg; /* temporary buffering */ + size_t lenMsg; + relpRetVal ret; +CODESTARTdoAction + dbgprintf(" %s:%s/RELP\n", pData->f_hname, getRelpPt(pData)); + + if(!pData->bIsConnected) { + CHKiRet(doConnect(pData)); + } + + pMsg = ppString[0]; + lenMsg = strlen((char*) pMsg); /* TODO: don't we get this? */ + + /* TODO: think about handling oversize messages! */ + if(lenMsg > MAXLINE) + lenMsg = MAXLINE; + + /* forward */ + ret = relpCltSendSyslog(pData->pRelpClt, (uchar*) pMsg, lenMsg); +RUNLOG_VAR("%d", ret); + if(ret != RELP_RET_OK) { + /* error! */ + dbgprintf("error forwarding via relp, suspending\n"); + iRet = RS_RET_SUSPENDED; + } + +finalize_it: +ENDdoAction + + +BEGINparseSelectorAct + uchar *q; + int i; + int bErr; +CODESTARTparseSelectorAct +CODE_STD_STRING_REQUESTparseSelectorAct(1) + if(!strncmp((char*) p, ":ommail:", sizeof(":ommail:") - 1)) { + p += sizeof(":ommail:") - 1; /* eat indicator sequence (-1 because of '\0'!) */ + } else { + ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); + } + + /* ok, if we reach this point, we have something for us */ + if((iRet = createInstance(&pData)) != RS_RET_OK) + FINALIZE; + + /* TODO: do we need to call freeInstance if we failed - this is a general question for + * all output modules. I'll address it later as the interface evolves. rgerhards, 2007-07-25 + */ +CODE_STD_FINALIZERparseSelectorAct +ENDparseSelectorAct + + +BEGINmodExit +CODESTARTmodExit + relpEngineDestruct(&pRelpEngine); + + /* release what we no longer need */ + objRelease(errmsg, CORE_COMPONENT); +ENDmodExit + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_OMOD_QUERIES +ENDqueryEtryPt + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ +CODEmodInit_QueryRegCFSLineHdlr + /* tell which objects we need */ + CHKiRet(objUse(errmsg, CORE_COMPONENT)); +ENDmodInit + +/* vim:set ai: + */ -- cgit From 6a3b85a41c75555827370953eff08836d3af8025 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 4 Apr 2008 13:43:09 +0000 Subject: cleanup of previous code, ready to implement smtp --- plugins/ommail/ommail.c | 72 +++++++++++++++---------------------------------- 1 file changed, 21 insertions(+), 51 deletions(-) diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c index 8a24c279..57de7fc0 100644 --- a/plugins/ommail/ommail.c +++ b/plugins/ommail/ommail.c @@ -62,6 +62,7 @@ typedef struct _instanceData { uchar *pszSrvPort; uchar *pszFrom; uchar *pszTo; + uchar *pszSubject; int sock; /* socket to this server (most important when we do multiple msgs per mail) */ } smtp; } md; /* mode-specific data */ @@ -70,7 +71,6 @@ typedef struct _instanceData { BEGINcreateInstance CODESTARTcreateInstance - pData->bInitialConnect = 1; ENDcreateInstance @@ -83,17 +83,18 @@ ENDisCompatibleWithFeature BEGINfreeInstance CODESTARTfreeInstance - if(pThis->iMode == 0) { - if(pThis->md.smtp.pszSrv != NULL) - free(pThis->md.smtp.pszSrv); - if(pThis->md.smtp.pszSrvPort != NULL) - free(pThis->md.smtp.pszSrvPort); - if(pThis->md.smtp.pszFrom != NULL) - free(pThis->md.smtp.pszFrom); - if(pThis->md.smtp.pszTo != NULL) - free(pThis->md.smtp.pszTo); + if(pData->iMode == 0) { + if(pData->md.smtp.pszSrv != NULL) + free(pData->md.smtp.pszSrv); + if(pData->md.smtp.pszSrvPort != NULL) + free(pData->md.smtp.pszSrvPort); + if(pData->md.smtp.pszFrom != NULL) + free(pData->md.smtp.pszFrom); + if(pData->md.smtp.pszTo != NULL) + free(pData->md.smtp.pszTo); + if(pData->md.smtp.pszSubject != NULL) + free(pData->md.smtp.pszSubject); } - ENDfreeInstance @@ -103,28 +104,13 @@ CODESTARTdbgPrintInstInfo ENDdbgPrintInstInfo -/* try to connect to server - * rgerhards, 2008-03-21 +/* connect to server + * rgerhards, 2008-04-04 */ static rsRetVal doConnect(instanceData *pData) { DEFiRet; - if(pData->bInitialConnect) { - iRet = relpCltConnect(pData->pRelpClt, family, (uchar*) pData->port, (uchar*) pData->f_hname); - if(iRet == RELP_RET_OK) - pData->bInitialConnect = 0; - } else { - iRet = relpCltReconnect(pData->pRelpClt); - } - - if(iRet == RELP_RET_OK) { - pData->bIsConnected = 1; - } else { - pData->bIsConnected = 0; - iRet = RS_RET_SUSPENDED; - } - RETiRet; } @@ -136,29 +122,18 @@ ENDtryResume BEGINdoAction - uchar *pMsg; /* temporary buffering */ - size_t lenMsg; - relpRetVal ret; CODESTARTdoAction - dbgprintf(" %s:%s/RELP\n", pData->f_hname, getRelpPt(pData)); - - if(!pData->bIsConnected) { - CHKiRet(doConnect(pData)); - } - - pMsg = ppString[0]; - lenMsg = strlen((char*) pMsg); /* TODO: don't we get this? */ + dbgprintf(" Mail\n"); - /* TODO: think about handling oversize messages! */ - if(lenMsg > MAXLINE) - lenMsg = MAXLINE; +// if(!pData->bIsConnected) { +// CHKiRet(doConnect(pData)); +// } /* forward */ - ret = relpCltSendSyslog(pData->pRelpClt, (uchar*) pMsg, lenMsg); -RUNLOG_VAR("%d", ret); - if(ret != RELP_RET_OK) { + iRet = sendSMTP(pData, ppString[0]); + if(iRet != RELP_RET_OK) { /* error! */ - dbgprintf("error forwarding via relp, suspending\n"); + dbgprintf("error sending mail, suspending\n"); iRet = RS_RET_SUSPENDED; } @@ -167,9 +142,6 @@ ENDdoAction BEGINparseSelectorAct - uchar *q; - int i; - int bErr; CODESTARTparseSelectorAct CODE_STD_STRING_REQUESTparseSelectorAct(1) if(!strncmp((char*) p, ":ommail:", sizeof(":ommail:") - 1)) { @@ -191,8 +163,6 @@ ENDparseSelectorAct BEGINmodExit CODESTARTmodExit - relpEngineDestruct(&pRelpEngine); - /* release what we no longer need */ objRelease(errmsg, CORE_COMPONENT); ENDmodExit -- cgit From ee629c4f742ac904c4a5055e85ef86d6decfb344 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 4 Apr 2008 13:55:07 +0000 Subject: fixed typo --- rsyslog.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rsyslog.conf b/rsyslog.conf index 2ff7d271..9a91823c 100644 --- a/rsyslog.conf +++ b/rsyslog.conf @@ -41,7 +41,7 @@ local7.* /var/log/boot.log #$ActionQueueMaxDiskSpace 1g # 1gb space limit (use as much as possible) #$ActionQueueSaveOnShutdown on # save messages to disk on shutdown #$ActionQueueType LinkedList # run asynchronously -#$ActionResumeRetryCount -1 # infinety retries if host is down +#$ActionResumeRetryCount -1 # infinite retries if host is down # remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional #*.* @@remote-host -- cgit From 0d5d42c52228964d76996c0e58fdf69258436716 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 4 Apr 2008 16:57:25 +0000 Subject: an initial, somewhat working, tester for the mail functionality --- ChangeLog | 20 ++++- plugins/ommail/ommail.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++- rsyslog.h | 1 + 3 files changed, 232 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 35c71f85..7eb5ce35 100644 --- a/ChangeLog +++ b/ChangeLog @@ -44,12 +44,30 @@ Version 3.15.0 (rgerhards), 2008-04-01 only installed if corresponding option is selected. Thanks to Michael Biebl for pointing these problems out. --------------------------------------------------------------------------- -Version 3.14.0 (rgerhards), 2008-04-02 +Version 3.14.1 (rgerhards), 2008-04-04 +- bugfix: some messages were emited without hostname - bugfix: rsyslogd was no longer build by default; man pages are only installed if corresponding option is selected. Thanks to Michael Biebl for pointing these problems out. +- bugfix: zero-length strings were not supported in object + deserializer - disabled atomic operations for this stable build as it caused platform problems +- bugfix: memory leaks in script engine +- bugfix: $hostname and $fromhost in RainerScript did not work +- bugfix: some memory leak when queue is runing in disk mode +- man pages improved thanks to varmofekoj and Peter Vrabec +- We have removed the 32 character size limit (from RFC3164) on the + tag. This had bad effects on existing envrionments, as sysklogd didn't + obey it either (probably another bug in RFC3164...). We now receive + the full size, but will modify the outputs so that only 32 characters + max are used by default. If you need large tags in the output, you need + to provide custom templates. +--------------------------------------------------------------------------- +Version 3.14.0 (rgerhards), 2008-04-02 +An interim version was accidently released to the web. It was named 3.14.0. +To avoid confusion, we have not assigned this version number to any +official release. If you happen to use 3.14.0, please update to 3.14.1. --------------------------------------------------------------------------- Version 3.13.0-dev0 (rgerhards), 2008-03-31 - bugfix: accidently set debug option in 3.12.5 reset to production diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c index 57de7fc0..4da4f58c 100644 --- a/plugins/ommail/ommail.c +++ b/plugins/ommail/ommail.c @@ -33,9 +33,10 @@ #include #include #include +#include #include -#include -#include +#include +#include #include "syslogd.h" #include "syslogd-types.h" #include "srUtils.h" @@ -63,6 +64,9 @@ typedef struct _instanceData { uchar *pszFrom; uchar *pszTo; uchar *pszSubject; + char RcvBuf[1024]; /* buffer for receiving server responses */ + size_t lenRcvBuf; + size_t iRcvBuf; /* current index into the rcvBuf (buf empty if iRcvBuf == lenRcvBuf) */ int sock; /* socket to this server (most important when we do multiple msgs per mail) */ } smtp; } md; /* mode-specific data */ @@ -104,6 +108,197 @@ CODESTARTdbgPrintInstInfo ENDdbgPrintInstInfo +/* TCP support code, should probably be moved to net.c or some place else... -- rgerhards, 2008-04-04 */ + +/* "receive" a character from the remote server. A single character + * is returned. Returns RS_RET_NO_MORE_DATA if the server has closed + * the connection and RS_RET_IO_ERROR if something goes wrong. This + * is a blocking read. + * rgerhards, 2008-04-04 + */ +static rsRetVal +getRcvChar(instanceData *pData, char *pC) +{ + DEFiRet; + ssize_t lenBuf; + assert(pData != NULL); + + if(pData->md.smtp.iRcvBuf == pData->md.smtp.lenRcvBuf) { /* buffer empty? */ + /* yes, we need to read the next server response */ + do { + lenBuf = recv(pData->md.smtp.sock, pData->md.smtp.RcvBuf, sizeof(pData->md.smtp.RcvBuf), 0); + if(lenBuf == 0) { + ABORT_FINALIZE(RS_RET_NO_MORE_DATA); + } else if(lenBuf < 0) { + if(errno != EAGAIN) { + ABORT_FINALIZE(RS_RET_IO_ERROR); + } + } else { + /* good read */ + pData->md.smtp.iRcvBuf = 0; + pData->md.smtp.lenRcvBuf = lenBuf; + } + + } while(lenBuf < 1); + } + + /* when we reach this point, we have a non-empty buffer */ + *pC = pData->md.smtp.RcvBuf[pData->md.smtp.iRcvBuf++]; + +finalize_it: + RETiRet; +} + + +#if 0 +/* Initialize TCP socket (for sender), new socket is returned in + * pSock if all goes well. + */ +static rsRetVal +CreateSocket(struct addrinfo *addrDest, int *pSock) +{ + DEFiRet; + int fd; + struct addrinfo *r; + char errStr[1024]; + + r = addrDest; + + while(r != NULL) { + fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol); + if(fd != -1) { + if(connect(fd, r->ai_addr, r->ai_addrlen) != 0) { + dbgprintf("create tcp connection failed, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr))); + } else { + *pSock = fd; + FINALIZE; + } + close(fd); + } else { + dbgprintf("couldn't create send socket, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr))); + } + r = r->ai_next; + } + + dbgprintf("no working socket could be obtained"); + iRet = RS_RET_NO_SOCKET; + +finalize_it: + RETiRet; +} +#endif + + +/* open a connection to the mail server + * rgerhards, 2008-04-04 + */ +static rsRetVal +serverConnect(instanceData *pData) +{ + struct addrinfo *res = NULL; + struct addrinfo hints; + char errStr[1024]; + + DEFiRet; + assert(pData != NULL); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; /* TODO: make configurable! */ + hints.ai_socktype = SOCK_STREAM; + if(getaddrinfo((char*)pData->md.smtp.pszSrv, (char*)pData->md.smtp.pszSrvPort, &hints, &res) != 0) { + dbgprintf("error %d in getaddrinfo\n", errno); + ABORT_FINALIZE(RS_RET_IO_ERROR); + } + + if((pData->md.smtp.sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) { + dbgprintf("couldn't create send socket, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr))); + ABORT_FINALIZE(RS_RET_IO_ERROR); + } + + if(connect(pData->md.smtp.sock, res->ai_addr, res->ai_addrlen) != 0) { + dbgprintf("create tcp connection failed, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr))); + ABORT_FINALIZE(RS_RET_IO_ERROR); + } + +finalize_it: + if(res != NULL) + freeaddrinfo(res); + + if(iRet != RS_RET_OK) { + if(pData->md.smtp.sock != -1) { + close(pData->md.smtp.sock); + pData->md.smtp.sock = -1; + } + } + + RETiRet; +} + + + +/* send text to the server, blocking send */ +static rsRetVal +Send(int sock, char *msg, size_t len) +{ + DEFiRet; + size_t offsBuf = 0; + ssize_t lenSend; + + assert(msg != NULL); + + if(len == 0) /* it's valid, but does not make much sense ;) */ + FINALIZE; + + do { + lenSend = send(sock, msg + offsBuf, len - offsBuf, 0); + dbgprintf("TCP sent %ld bytes, requested %ld\n", (long) lenSend, (long) len); + + if(lenSend == -1) { + if(errno != EAGAIN) { + dbgprintf("message not (tcp)send, errno %d", errno); + ABORT_FINALIZE(RS_RET_TCP_SEND_ERROR); + } + } else if(lenSend != (ssize_t) len) { + offsBuf += len; /* on to next round... */ + } else { + FINALIZE; + } + } while(1); + +finalize_it: + RETiRet; +} + + +/* send a message via SMTP + * TODO: care about the result codes, we can't do it that blindly ;) + * rgerhards, 2008-04-04 + */ +static rsRetVal +sendSMTP(instanceData *pData, uchar *body) +{ + DEFiRet; + + assert(pData != NULL); + + CHKiRet(serverConnect(pData)); + CHKiRet(Send(pData->md.smtp.sock, "HELO\r\n", 6)); + CHKiRet(Send(pData->md.smtp.sock, "MAIL FROM: \r\n", sizeof("MAIL FROM: \r\n") - 1)); + CHKiRet(Send(pData->md.smtp.sock, "RCPT TO: \r\n", sizeof("RCPT TO: \r\n") - 1)); + CHKiRet(Send(pData->md.smtp.sock, "DATA\r\n", sizeof("DATA\r\n") - 1)); + CHKiRet(Send(pData->md.smtp.sock, body, strlen((char*) body))); + CHKiRet(Send(pData->md.smtp.sock, "\r\n.\r\n", sizeof("\r\n.\r\n") - 1)); + CHKiRet(Send(pData->md.smtp.sock, "QUIT\r\n", sizeof("QUIT\r\n") - 1)); + + close(pData->md.smtp.sock); + pData->md.smtp.sock = -1; + +finalize_it: + RETiRet; +} + + + /* connect to server * rgerhards, 2008-04-04 */ @@ -111,6 +306,10 @@ static rsRetVal doConnect(instanceData *pData) { DEFiRet; + iRet = serverConnect(pData); + if(iRet == RS_RET_IO_ERROR) + iRet = RS_RET_SUSPENDED; + RETiRet; } @@ -131,7 +330,7 @@ CODESTARTdoAction /* forward */ iRet = sendSMTP(pData, ppString[0]); - if(iRet != RELP_RET_OK) { + if(iRet != RS_RET_OK) { /* error! */ dbgprintf("error sending mail, suspending\n"); iRet = RS_RET_SUSPENDED; @@ -154,6 +353,16 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) if((iRet = createInstance(&pData)) != RS_RET_OK) FINALIZE; + //pData->md.smtp.pszSrv = "172.19.2.10"; + pData->md.smtp.pszSrv = "172.19.0.6"; + pData->md.smtp.pszSrvPort = "25"; + pData->md.smtp.pszFrom = "rgerhards@adiscon.com"; + pData->md.smtp.pszTo = "rgerhards@adiscon.com"; + pData->md.smtp.pszSubject = "rsyslog test message"; + + /* process template */ + CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_TraditionalForwardFormat")); + /* TODO: do we need to call freeInstance if we failed - this is a general question for * all output modules. I'll address it later as the interface evolves. rgerhards, 2007-07-25 */ diff --git a/rsyslog.h b/rsyslog.h index 9fe162d5..56140aaf 100644 --- a/rsyslog.h +++ b/rsyslog.h @@ -167,6 +167,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_MODULE_LOAD_ERR_DLOPEN = -2066, /**< module could not be loaded - problem in dlopen() */ RS_RET_MODULE_LOAD_ERR_NO_INIT = -2067, /**< module could not be loaded - init() missing */ RS_RET_MODULE_LOAD_ERR_INIT_FAILED = -2068, /**< module could not be loaded - init() failed */ + RS_RET_NO_SOCKET = -2069, /**< socket could not be obtained or was not provided */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ -- cgit From f4803196d7e215b26b29dd68e7d309792c104844 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 4 Apr 2008 17:09:15 +0000 Subject: bugfix: segfault in expression-based filter - so far untested --- syslogd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/syslogd.c b/syslogd.c index 904bdbd3..cd8476d4 100644 --- a/syslogd.c +++ b/syslogd.c @@ -1056,10 +1056,11 @@ static rsRetVal shouldProcessThisMessage(selector_t *f, msg_t *pMsg, int *bProce finalize_it: /* destruct in any case, not just on error, but it makes error handling much easier */ - if(pVM != NULL) { - var.Destruct(&pResult); + if(pVM != NULL) vm.Destruct(&pVM); - } + + if(pResult != NULL) + var.Destruct(&pResult); *bProcessMsg = bRet; RETiRet; -- cgit From e4d27e77e828d4a56f9bc3f0f532d6ac699f156b Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 4 Apr 2008 18:24:47 +0000 Subject: got a bit closer to real SMTP ;) --- plugins/ommail/ommail.c | 148 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 135 insertions(+), 13 deletions(-) diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c index 4da4f58c..c4c2a987 100644 --- a/plugins/ommail/ommail.c +++ b/plugins/ommail/ommail.c @@ -51,9 +51,11 @@ MODULE_TYPE_OUTPUT DEF_OMOD_STATIC_DATA DEFobjCurrIf(errmsg) -static uchar *pSrv; -static uchar *pszFrom; -static uchar *pszTo; +static uchar *pszSrv = NULL; +static uchar *pszSrvPort = NULL; +static uchar *pszFrom = NULL; +static uchar *pszTo = NULL; +static uchar *pszSubject = NULL; typedef struct _instanceData { int iMode; /* 0 - smtp, 1 - sendmail */ @@ -269,6 +271,34 @@ finalize_it: RETiRet; } +/* read response from server + */ +static rsRetVal +readResponse(instanceData *pData) +{ + DEFiRet; + char buf[128]; + int i = 0; + char c; + + assert(pData != NULL); + + do { + CHKiRet(getRcvChar(pData, &c)); + if(c == '\n') + break; + buf[i++] = c; + } while(1); + + +finalize_it: + buf[i] = '\0'; + +dbgprintf("iRet %d, server response: %s\n", iRet, buf); + + RETiRet; +} + /* send a message via SMTP * TODO: care about the result codes, we can't do it that blindly ;) @@ -281,14 +311,52 @@ sendSMTP(instanceData *pData, uchar *body) assert(pData != NULL); + readResponse(pData); + CHKiRet(serverConnect(pData)); - CHKiRet(Send(pData->md.smtp.sock, "HELO\r\n", 6)); - CHKiRet(Send(pData->md.smtp.sock, "MAIL FROM: \r\n", sizeof("MAIL FROM: \r\n") - 1)); - CHKiRet(Send(pData->md.smtp.sock, "RCPT TO: \r\n", sizeof("RCPT TO: \r\n") - 1)); + + CHKiRet(Send(pData->md.smtp.sock, "HELO ", 5)); + CHKiRet(Send(pData->md.smtp.sock, (char*)LocalHostName, strlen((char*)LocalHostName))); + CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); + readResponse(pData); + + CHKiRet(Send(pData->md.smtp.sock, "MAIL FROM: <", sizeof("MAIL FROM: <") - 1)); + CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszFrom, strlen((char*)pData->md.smtp.pszFrom))); + CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); + readResponse(pData); + + CHKiRet(Send(pData->md.smtp.sock, "RCPT TO: <", sizeof("RCPT TO: <") - 1)); + CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszTo, strlen((char*)pData->md.smtp.pszTo))); + CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); + readResponse(pData); + CHKiRet(Send(pData->md.smtp.sock, "DATA\r\n", sizeof("DATA\r\n") - 1)); - CHKiRet(Send(pData->md.smtp.sock, body, strlen((char*) body))); + + /* now come the data part */ + /* header */ + CHKiRet(Send(pData->md.smtp.sock, "From: <", sizeof("From: <") - 1)); + CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszFrom, strlen((char*)pData->md.smtp.pszFrom))); + CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); + + CHKiRet(Send(pData->md.smtp.sock, "To: <", sizeof("To: <") - 1)); + CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszTo, strlen((char*)pData->md.smtp.pszTo))); + CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); + + CHKiRet(Send(pData->md.smtp.sock, "Subject: ", sizeof("Subject: ") - 1)); + CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszSubject, strlen((char*)pData->md.smtp.pszSubject))); + CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); + + CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); /* indicate end of header */ + + /* body */ + CHKiRet(Send(pData->md.smtp.sock, (char*)body, strlen((char*) body))); + + /* end of data, back to envelope transaction */ CHKiRet(Send(pData->md.smtp.sock, "\r\n.\r\n", sizeof("\r\n.\r\n") - 1)); + readResponse(pData); + CHKiRet(Send(pData->md.smtp.sock, "QUIT\r\n", sizeof("QUIT\r\n") - 1)); + readResponse(pData); close(pData->md.smtp.sock); pData->md.smtp.sock = -1; @@ -353,12 +421,17 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) if((iRet = createInstance(&pData)) != RS_RET_OK) FINALIZE; - //pData->md.smtp.pszSrv = "172.19.2.10"; - pData->md.smtp.pszSrv = "172.19.0.6"; - pData->md.smtp.pszSrvPort = "25"; - pData->md.smtp.pszFrom = "rgerhards@adiscon.com"; - pData->md.smtp.pszTo = "rgerhards@adiscon.com"; - pData->md.smtp.pszSubject = "rsyslog test message"; + /* TODO: check strdup() result */ + if(pszSrv != NULL) + pData->md.smtp.pszSrv = (uchar*) strdup((char*)pszSrv); + if(pszSrvPort != NULL) + pData->md.smtp.pszSrvPort = (uchar*) strdup((char*)pszSrvPort); + if(pszSrvPort != NULL) + pData->md.smtp.pszFrom = (uchar*) strdup((char*)pszFrom); + if(pszSrvPort != NULL) + pData->md.smtp.pszTo = (uchar*) strdup((char*)pszTo); + if(pszSrvPort != NULL) + pData->md.smtp.pszSubject = (uchar*) strdup((char*)pszSubject); /* process template */ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_TraditionalForwardFormat")); @@ -370,8 +443,41 @@ CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct +/* Free string config variables and reset them to NULL (not necessarily the default!) */ +static rsRetVal freeConfigVariables(void) +{ + DEFiRet; + + if(pszSrv != NULL) { + free(pszSrv); + pszSrv = NULL; + } + if(pszSrvPort != NULL) { + free(pszSrvPort); + pszSrvPort = NULL; + } + if(pszFrom != NULL) { + free(pszFrom); + pszFrom = NULL; + } + if(pszTo != NULL) { + free(pszTo); + pszTo = NULL; + } + if(pszSubject != NULL) { + free(pszSubject); + pszSubject = NULL; + } + + RETiRet; +} + + BEGINmodExit CODESTARTmodExit + /* cleanup our allocations */ + freeConfigVariables(); + /* release what we no longer need */ objRelease(errmsg, CORE_COMPONENT); ENDmodExit @@ -383,12 +489,28 @@ CODEqueryEtryPt_STD_OMOD_QUERIES ENDqueryEtryPt +/* Reset config variables for this module to default values. + */ +static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) +{ + DEFiRet; + iRet = freeConfigVariables(); + RETiRet; +} + + BEGINmodInit() CODESTARTmodInit *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr /* tell which objects we need */ CHKiRet(objUse(errmsg, CORE_COMPONENT)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpserver", 0, eCmdHdlrGetWord, NULL, &pszSrv, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpport", 0, eCmdHdlrGetWord, NULL, &pszSrvPort, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailfrom", 0, eCmdHdlrGetWord, NULL, &pszFrom, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailto", 0, eCmdHdlrGetWord, NULL, &pszTo, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsubject", 0, eCmdHdlrGetWord, NULL, &pszSubject, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit /* vim:set ai: -- cgit From 8233dd8c60fcbb48ae586b4742ef6fbcf5c0eb18 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 7 Apr 2008 11:10:11 +0200 Subject: fixed file permissions --- liblogging-stub.h | 0 srUtils.c | 0 srUtils.h | 0 stringbuf.c | 0 stringbuf.h | 0 5 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 liblogging-stub.h mode change 100755 => 100644 srUtils.c mode change 100755 => 100644 srUtils.h mode change 100755 => 100644 stringbuf.c mode change 100755 => 100644 stringbuf.h diff --git a/liblogging-stub.h b/liblogging-stub.h old mode 100755 new mode 100644 diff --git a/srUtils.c b/srUtils.c old mode 100755 new mode 100644 diff --git a/srUtils.h b/srUtils.h old mode 100755 new mode 100644 diff --git a/stringbuf.c b/stringbuf.c old mode 100755 new mode 100644 diff --git a/stringbuf.h b/stringbuf.h old mode 100755 new mode 100644 -- cgit From 8a28324ed4ee674b6f38ae02a96c3e5db3800b32 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 7 Apr 2008 11:36:18 +0200 Subject: deleted no longer needed man page --- rklogd.8 | 440 --------------------------------------------------------------- 1 file changed, 440 deletions(-) delete mode 100644 rklogd.8 diff --git a/rklogd.8 b/rklogd.8 deleted file mode 100644 index 39a0a1fa..00000000 --- a/rklogd.8 +++ /dev/null @@ -1,440 +0,0 @@ -.\" Copyright 1994 Dr. Greg Wettstein, Enjellic Systems Development. -.\" May be distributed under the GNU General Public License -.\" Sun Jul 30 01:35:55 MET: Martin Schulze: Updates -.\" Sun Nov 19 23:22:21 MET: Martin Schulze: Updates -.\" Mon Aug 19 09:42:08 CDT 1996: Dr. G.W. Wettstein: Updates -.\" -.TH RKLOGD 8 "03 JULY 2007" "Version 1.14.2 (devel)" "Linux System Administration" -.SH NAME -rklogd \- Kernel Log Daemon -.LP -.SH SYNOPSIS -.B rklogd -.RB [ " \-c " -.I n -] -.RB [ " \-d " ] -.RB [ " \-f " -.I fname -] -.RB [ " \-iI " ] -.RB [ " \-n " ] -.RB [ " \-o " ] -.RB [ " \-p " ] -.RB [ " \-s " ] -.RB [ " \-k " -.I fname -] -.RB [ " \-v " ] -.RB [ " \-x " ] -.RB [ " \-2 " ] -.LP -.SH DESCRIPTION -.B rklogd -is a system daemon which intercepts and logs Linux kernel -messages. -.LP -.SH OPTIONS -.TP -.BI "\-c " n -Sets the default log level of console messages to \fIn\fR. -.TP -.B "\-d" -Enable debugging mode. This will generate \fBLOTS\fR of output to -stderr. -.TP -.BI "\-f " file -Log messages to the specified filename rather than to the syslog facility. -.TP -.BI "\-i \-I" -Signal the currently executing rklogd daemon. Both of these switches control -the loading/reloading of symbol information. The \-i switch signals the -daemon to reload the kernel module symbols. The \-I switch signals for a -reload of both the static kernel symbols and the kernel module symbols. -.TP -.B "\-n" -Avoid auto-backgrounding. This is needed especially if the -.B rklogd -is started and controlled by -.BR init (8). -.TP -.B "-o" -Execute in 'one\-shot' mode. This causes \fBrklogd\fP to read and log -all the messages that are found in the kernel message buffers. After -a single read and log cycle the daemon exits. -.TP -.B "-p" -Enable paranoia. This option controls when rklogd loads kernel module symbol -information. Setting this switch causes rklogd to load the kernel module -symbol information whenever an Oops string is detected in the kernel message -stream. -.TP -.B "-s" -Force \fBrklogd\fP to use the system call interface to the kernel message -buffers. -.TP -.BI "\-k " file -Use the specified file as the source of kernel symbol information. -.TP -.B "\-v" -Print version and exit. -.TP -.B "\-x" -Omits EIP translation and therefore doesn't read the System.map file. -.TP -.B "\-2" -When symbols are expanded, print the line twice. Once with addresses -converted to symbols, once with the raw text. This allows external -programs such as ksymoops do their own processing on the original -data. -.LP -.SH OVERVIEW -The functionality of rklogd has been typically incorporated into other -versions of syslogd but this seems to be a poor place for it. In the -modern Linux kernel a number of kernel messaging issues such as -sourcing, prioritization and resolution of kernel addresses must be -addressed. Incorporating kernel logging into a separate process -offers a cleaner separation of services. - -In Linux there are two potential sources of kernel log information: the -.I /proc -file system and the syscall (sys_syslog) interface, although -ultimately they are one and the same. Klogd is designed to choose -whichever source of information is the most appropriate. It does this -by first checking for the presence of a mounted -.I /proc -file system. If this is found the -.I /proc/kmsg -file is used as the source of kernel log -information. If the proc file system is not mounted -.B rklogd -uses a -system call to obtain kernel messages. The command line switch -.RB ( "\-s" ) -can be used to force rklogd to use the system call interface as its -messaging source. - -If kernel messages are directed through the -.BR syslogd " daemon the " rklogd -daemon, as of version 1.1, has the ability to properly prioritize -kernel messages. Prioritization of the kernel messages was added to it -at approximately version 0.99pl13 of the kernel. The raw kernel messages -are of the form: -.IP -\<[0\-7]\>Something said by the kernel. -.PP -The priority of the kernel message is encoded as a single numeric -digit enclosed inside the <> pair. The definitions of these values is -given in the kernel include file kernel.h. When a message is received -from the kernel the rklogd daemon reads this priority level and assigns -the appropriate priority level to the syslog message. If file output -(\fB-f\fR) is used the prioritization sequence is left pre\-pended to the -kernel message. - -The -.B rklogd -daemon also allows the ability to alter the presentation of -kernel messages to the system console. Consequent with the -prioritization of kernel messages was the inclusion of default -messaging levels for the kernel. In a stock kernel the the default -console log level is set to 7. Any messages with a priority level -numerically lower than 7 (higher priority) appear on the console. - -Messages of priority level 7 are considered to be 'debug' messages and -will thus not appear on the console. Many administrators, -particularly in a multi\-user environment, prefer that all kernel -messages be handled by rklogd and either directed to a file or to -the syslogd daemon. This prevents 'nuisance' messages such as line -printer out of paper or disk change detected from cluttering the -console. - -When -.B \-c -is given on the commandline the -.B rklogd -daemon will execute a system call to inhibit all kernel messages from -being displayed on the console. Former versions always issued this -system call and defaulted to all kernel messages except for panics. -This is handled differently nowardays so -.B rklogd -doesn't need to set this value anymore. The -argument given to the \fB\-c\fR switch specifies the priority level of -messages which will be directed to the console. Note that messages of -a priority value LOWER than the indicated number will be directed to -the console. -.IP -For example, to have the kernel display all messages with a -priority level of 3 -.BR "" ( KERN_ERR ) -or more severe the following -command would be executed: -.IP -.nf - rklogd \-c 4 -.fi -.PP -The definitions of the numeric values for kernel messages are given in -the file -.IR kernel.h " which can be found in the " /usr/include/linux -directory if the kernel sources are installed. These values parallel -the syslog priority values which are defined in the file -.IR syslog.h " found in the " /usr/include/sys " sub\-directory." - -The rklogd daemon can also be used in a 'one\-shot' mode for reading the -kernel message buffers. One shot mode is selected by specifying the -\fB\-o\fR switch on the command line. Output will be directed to either the -syslogd daemon or to an alternate file specified by the \fB-f\fR switch. -.IP -For example, to read all the kernel messages after a system -boot and record them in a file called krnl.msg the following -command would be given. -.IP -.nf - rklogd -o -f ./krnl.msg -.fi -.PP -.SH KERNEL ADDRESS RESOLUTION -If the kernel detects an internal error condition a general protection -fault will be triggered. As part of the GPF handling procedure the -kernel prints out a status report indicating the state of the -processor at the time of the fault. Included in this display are the -contents of the microprocessor's registers, the contents of the kernel -stack and a tracing of what functions were being executed at the time -of the fault. - -This information is -.B EXTREMELY IMPORTANT -in determining what caused the internal error condition. The -difficulty comes when a kernel developer attempts to analyze this -information. The raw numeric information present in the protection -fault printout is of very little use to the developers. This is due -to the fact that kernels are not identical and the addresses of -variable locations or functions will not be the same in all kernels. -In order to correctly diagnose the cause of failure a kernel developer -needs to know what specific kernel functions or variable locations -were involved in the error. - -As part of the kernel compilation process a listing is created which -specified the address locations of important variables and function in -the kernel being compiled. This listing is saved in a file called -System.map in the top of the kernel directory source tree. Using this -listing a kernel developer can determine exactly what the kernel was -doing when the error condition occurred. - -The process of resolving the numeric addresses from the protection -fault printout can be done manually or by using the -.B ksymoops -program which is included in the kernel sources. - -As a convenience -.B rklogd -will attempt to resolve kernel numeric addresses to their symbolic -forms if a kernel symbol table is available at execution time. If you -require the original address of the symbol, use the -.B -2 -switch to preserve the numeric address. A -symbol table may be specified by using the \fB\-k\fR switch on the -command line. If a symbol file is not explicitly specified the -following filenames will be tried: - -.nf -.I /boot/System.map -.I /System.map -.I /usr/src/linux/System.map -.fi - -Version information is supplied in the system maps as of kernel -1.3.43. This version information is used to direct an intelligent -search of the list of symbol tables. This feature is useful since it -provides support for both production and experimental kernels. - -For example a production kernel may have its map file stored in -/boot/System.map. If an experimental or test kernel is compiled with -the sources in the 'standard' location of /usr/src/linux the system -map will be found in /usr/src/linux/System.map. When rklogd starts -under the experimental kernel the map in /boot/System.map will be -bypassed in favor of the map in /usr/src/linux/System.map. - -Modern kernels as of 1.3.43 properly format important kernel addresses -so that they will be recognized and translated by rklogd. Earlier -kernels require a source code patch be applied to the kernel sources. -This patch is supplied with the sysrklogd sources. - -The process of analyzing kernel protections faults works very well -with a static kernel. Additional difficulties are encountered when -attempting to diagnose errors which occur in loadable kernel modules. -Loadable kernel modules are used to implement kernel functionality in -a form which can be loaded or unloaded at will. The use of loadable -modules is useful from a debugging standpoint and can also be useful -in decreasing the amount of memory required by a kernel. - -The difficulty with diagnosing errors in loadable modules is due to -the dynamic nature of the kernel modules. When a module is loaded the -kernel will allocate memory to hold the module, when the module is -unloaded this memory will be returned back to the kernel. This -dynamic memory allocation makes it impossible to produce a map file -which details the addresses of the variable and functions in a kernel -loadable module. Without this location map it is not possible for a -kernel developer to determine what went wrong if a protection fault -involves a kernel module. - -.B rklogd -has support for dealing with the problem of diagnosing protection -faults in kernel loadable modules. At program start time or in -response to a signal the daemon will interrogate the kernel for a -listing of all modules loaded and the addresses in memory they are -loaded at. Individual modules can also register the locations of -important functions when the module is loaded. The addresses of these -exported symbols are also determined during this interrogation -process. - -When a protection fault occurs an attempt will be made to resolve -kernel addresses from the static symbol table. If this fails the -symbols from the currently loaded modules are examined in an attempt -to resolve the addresses. At the very minimum this allows rklogd to -indicate which loadable module was responsible for generating the -protection fault. Additional information may be available if the -module developer chose to export symbol information from the module. - -Proper and accurate resolution of addresses in kernel modules requires -that -.B rklogd -be informed whenever the kernel module status changes. The -.B \-i -and -.B \-I -switches can be used to signal the currently executing daemon that -symbol information be reloaded. Of most importance to proper -resolution of module symbols is the -.B \-i -switch. Each time a kernel module is loaded or removed from the -kernel the following command should be executed: - -.nf -.I rklogd \-i -.fi - -The -.B \-p -switch can also be used to insure that module symbol information is up -to date. This switch instructs -.B rklogd -to reload the module symbol information whenever a protection fault -is detected. Caution should be used before invoking the program in -\'paranoid\' mode. The stability of the kernel and the operating -environment is always under question when a protection fault occurs. -Since the rklogd daemon must execute system calls in order to read the -module symbol information there is the possibility that the system may -be too unstable to capture useful information. A much better policy -is to insure that rklogd is updated whenever a module is loaded or -unloaded. Having uptodate symbol information loaded increases the -probability of properly resolving a protection fault if it should occur. - -Included in the sysrklogd source distribution is a patch to the -modules-2.0.0 package which allows the -.B insmod, -.B rmmod -and -.B modprobe -utilities to automatically signal -.B rklogd -whenever a module is inserted or removed from the kernel. Using this -patch will insure that the symbol information maintained in rklogd is -always consistent with the current kernel state. -.PP -.SH SIGNAL HANDLING -The -.B rklogd -will respond to eight signals: -.BR SIGHUP ", " SIGINT ", " SIGKILL ", " SIGTERM ", " SIGTSTP ", " -.BR SIGUSR1 ", "SIGUSR2 " and " SIGCONT ". The" -.BR SIGINT ", " SIGKILL ", " SIGTERM " and " SIGHUP -signals will cause the daemon to close its kernel log sources and -terminate gracefully. - -The -.BR SIGTSTP " and " SIGCONT -signals are used to start and stop kernel logging. Upon receipt of a -.B SIGTSTP -signal the daemon will close its -log sources and spin in an idle loop. Subsequent receipt of a -.B SIGCONT -signal will cause the daemon to go through its initialization sequence -and re-choose an input source. Using -.BR SIGSTOP " and " SIGCONT -in combination the kernel log input can be re-chosen without stopping and -restarting the daemon. For example if the \fI/proc\fR file system is to be -un-mounted the following command sequence should be used: -.PP -.PD 0 -.TP - # kill -TSTP pid -.TP - # umount /proc -.TP - # kill -CONT pid -.PD -.PP -Notations will be made in the system logs with -.B LOG_INFO -priority -documenting the start/stop of logging. - -The -.BR SIGUSR1 " and " SIGUSR2 -signals are used to initiate loading/reloading of kernel symbol information. -Receipt of the -.B SIGUSR1 -signal will cause the kernel module symbols to be reloaded. Signaling the -daemon with -.B SIGUSR2 -will cause both the static kernel symbols and the kernel module symbols to -be reloaded. - -Provided that the System.map file is placed in an appropriate location the -signal of generally greatest usefulness is the -.B SIGUSR1 -signal. This signal is designed to be used to signal the daemon when kernel -modules are loaded/unloaded. Sending this signal to the daemon after a -kernel module state change will insure that proper resolution of symbols will -occur if a protection fault occurs in the address space occupied by a kernel -module. -.LP -.SH FILES -.PD 0 -.TP -.I /proc/kmsg -One Source for kernel messages -.B rklogd -.TP -.I /var/run/rklogd.pid -The file containing the process id of -.B rklogd -.TP -.I /boot/System.map, /System.map, /usr/src/linux/System.map -Default locations for kernel system maps. -.PD -.SH BUGS -Probably numerous. Well formed context diffs appreciated. -.LP -.SH AUTHOR -The -.B rklogd -was originally written by Steve Lord (lord@cray.com), Greg Wettstein -made major improvements. - -.PD 0 -.TP -Dr. Greg Wettstein (greg@wind.enjellic.com) -.TP -Enjellic Systems Development -.PD -.PP -.PD 0 -.TP -Oncology Research Divsion Computing Facility -.TP -Roger Maris Cancer Center -.TP -Fargo, ND 58122 -.PD -- cgit From 3621234f9865b593c401137853cb54cc67939357 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 7 Apr 2008 16:19:36 +0200 Subject: smtp response codes are now correctly checked --- plugins/ommail/ommail.c | 108 +++++++++++++++++++++--------------------------- rsyslog.h | 1 + 2 files changed, 48 insertions(+), 61 deletions(-) diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c index c4c2a987..c4a504c5 100644 --- a/plugins/ommail/ommail.c +++ b/plugins/ommail/ommail.c @@ -152,45 +152,6 @@ finalize_it: } -#if 0 -/* Initialize TCP socket (for sender), new socket is returned in - * pSock if all goes well. - */ -static rsRetVal -CreateSocket(struct addrinfo *addrDest, int *pSock) -{ - DEFiRet; - int fd; - struct addrinfo *r; - char errStr[1024]; - - r = addrDest; - - while(r != NULL) { - fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol); - if(fd != -1) { - if(connect(fd, r->ai_addr, r->ai_addrlen) != 0) { - dbgprintf("create tcp connection failed, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr))); - } else { - *pSock = fd; - FINALIZE; - } - close(fd); - } else { - dbgprintf("couldn't create send socket, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr))); - } - r = r->ai_next; - } - - dbgprintf("no working socket could be obtained"); - iRet = RS_RET_NO_SOCKET; - -finalize_it: - RETiRet; -} -#endif - - /* open a connection to the mail server * rgerhards, 2008-04-04 */ @@ -253,8 +214,6 @@ Send(int sock, char *msg, size_t len) do { lenSend = send(sock, msg + offsBuf, len - offsBuf, 0); - dbgprintf("TCP sent %ld bytes, requested %ld\n", (long) lenSend, (long) len); - if(lenSend == -1) { if(errno != EAGAIN) { dbgprintf("message not (tcp)send, errno %d", errno); @@ -271,31 +230,62 @@ finalize_it: RETiRet; } -/* read response from server + +/* read response line from server */ static rsRetVal -readResponse(instanceData *pData) +readResponseLn(instanceData *pData, char *pLn, size_t lenLn) { DEFiRet; - char buf[128]; - int i = 0; + size_t i = 0; char c; assert(pData != NULL); + assert(pLn != NULL); do { CHKiRet(getRcvChar(pData, &c)); if(c == '\n') break; - buf[i++] = c; + if(i < (lenLn - 1)) /* if line is too long, we simply discard the rest */ + pLn[i++] = c; } while(1); + pLn[i] = '\0'; + dbgprintf("smtp server response: %s\n", pLn); /* do not remove, this is helpful in troubleshooting SMTP probs! */ - finalize_it: - buf[i] = '\0'; + RETiRet; +} -dbgprintf("iRet %d, server response: %s\n", iRet, buf); +/* read numerical response code from server and compare it to requried response code. + * If they two don't match, return RS_RET_SMTP_ERROR. + * rgerhards, 2008-04-07 + */ +static rsRetVal +readResponse(instanceData *pData, int *piState, int iExpected) +{ + DEFiRet; + int bCont; + char buf[128]; + + assert(pData != NULL); + assert(piState != NULL); + + bCont = 1; + do { + CHKiRet(readResponseLn(pData, buf, sizeof(buf))); + if(buf[3] != '-') { /* last or only response line? */ + bCont = 0; + *piState = buf[0] - '0'; + *piState = *piState * 10 + buf[1] - '0'; + *piState = *piState * 10 + buf[2] - '0'; + if(*piState != iExpected) + ABORT_FINALIZE(RS_RET_SMTP_ERROR); + } + } while(bCont); + +finalize_it: RETiRet; } @@ -308,29 +298,31 @@ static rsRetVal sendSMTP(instanceData *pData, uchar *body) { DEFiRet; + int iState; /* SMTP state */ assert(pData != NULL); - readResponse(pData); CHKiRet(serverConnect(pData)); + CHKiRet(readResponse(pData, &iState, 220)); CHKiRet(Send(pData->md.smtp.sock, "HELO ", 5)); CHKiRet(Send(pData->md.smtp.sock, (char*)LocalHostName, strlen((char*)LocalHostName))); CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); - readResponse(pData); + CHKiRet(readResponse(pData, &iState, 250)); CHKiRet(Send(pData->md.smtp.sock, "MAIL FROM: <", sizeof("MAIL FROM: <") - 1)); CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszFrom, strlen((char*)pData->md.smtp.pszFrom))); CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); - readResponse(pData); + CHKiRet(readResponse(pData, &iState, 250)); CHKiRet(Send(pData->md.smtp.sock, "RCPT TO: <", sizeof("RCPT TO: <") - 1)); CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszTo, strlen((char*)pData->md.smtp.pszTo))); CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); - readResponse(pData); + CHKiRet(readResponse(pData, &iState, 250)); CHKiRet(Send(pData->md.smtp.sock, "DATA\r\n", sizeof("DATA\r\n") - 1)); + CHKiRet(readResponse(pData, &iState, 354)); /* now come the data part */ /* header */ @@ -353,10 +345,10 @@ sendSMTP(instanceData *pData, uchar *body) /* end of data, back to envelope transaction */ CHKiRet(Send(pData->md.smtp.sock, "\r\n.\r\n", sizeof("\r\n.\r\n") - 1)); - readResponse(pData); + CHKiRet(readResponse(pData, &iState, 250)); CHKiRet(Send(pData->md.smtp.sock, "QUIT\r\n", sizeof("QUIT\r\n") - 1)); - readResponse(pData); + CHKiRet(readResponse(pData, &iState, 221)); close(pData->md.smtp.sock); pData->md.smtp.sock = -1; @@ -392,10 +384,6 @@ BEGINdoAction CODESTARTdoAction dbgprintf(" Mail\n"); -// if(!pData->bIsConnected) { -// CHKiRet(doConnect(pData)); -// } - /* forward */ iRet = sendSMTP(pData, ppString[0]); if(iRet != RS_RET_OK) { @@ -403,8 +391,6 @@ CODESTARTdoAction dbgprintf("error sending mail, suspending\n"); iRet = RS_RET_SUSPENDED; } - -finalize_it: ENDdoAction diff --git a/rsyslog.h b/rsyslog.h index 56140aaf..b52e08b1 100644 --- a/rsyslog.h +++ b/rsyslog.h @@ -168,6 +168,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_MODULE_LOAD_ERR_NO_INIT = -2067, /**< module could not be loaded - init() missing */ RS_RET_MODULE_LOAD_ERR_INIT_FAILED = -2068, /**< module could not be loaded - init() failed */ RS_RET_NO_SOCKET = -2069, /**< socket could not be obtained or was not provided */ + RS_RET_SMTP_ERROR = -2070, /**< error during SMTP transation */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ -- cgit From d9dd85d4dce0eedd6ed75a28af5939858b852f7a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 8 Apr 2008 09:39:21 +0200 Subject: clean implementation of smtp protcol and rsyslog retries --- plugins/ommail/ommail.c | 94 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 28 deletions(-) diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c index c4a504c5..8d7adfa9 100644 --- a/plugins/ommail/ommail.c +++ b/plugins/ommail/ommail.c @@ -36,20 +36,19 @@ #include #include #include +#include #include #include "syslogd.h" #include "syslogd-types.h" #include "srUtils.h" #include "cfsysline.h" #include "module-template.h" -#include "errmsg.h" MODULE_TYPE_OUTPUT /* internal structures */ DEF_OMOD_STATIC_DATA -DEFobjCurrIf(errmsg) static uchar *pszSrv = NULL; static uchar *pszSrvPort = NULL; @@ -152,6 +151,24 @@ finalize_it: } +/* close the mail server connection + * rgerhards, 2008-04-08 + */ +static rsRetVal +serverDisconnect(instanceData *pData) +{ + DEFiRet; + assert(pData != NULL); + + if(pData->md.smtp.sock != -1) { + close(pData->md.smtp.sock); + pData->md.smtp.sock = -1; + } + + RETiRet; +} + + /* open a connection to the mail server * rgerhards, 2008-04-04 */ @@ -275,6 +292,10 @@ readResponse(instanceData *pData, int *piState, int iExpected) bCont = 1; do { CHKiRet(readResponseLn(pData, buf, sizeof(buf))); + /* note: the code below is not 100% clean as we may have received less than 4 characters. + * However, as we have a fixed size this will not create a vulnerability. An error will + * also most likely be generated, so it is quite acceptable IMHO -- rgerhards, 2008-04-08 + */ if(buf[3] != '-') { /* last or only response line? */ bCont = 0; *piState = buf[0] - '0'; @@ -290,8 +311,25 @@ finalize_it: } +/* create a timestamp suitable for use with the Date: SMTP body header + * rgerhards, 2008-04-08 + */ +static void +mkSMTPTimestamp(uchar *pszBuf, size_t lenBuf) +{ + time_t tCurr; + struct tm tmCurr; + static const char szDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + static const char szMonth[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + time(&tCurr); + gmtime_r(&tCurr, &tmCurr); + snprintf((char*)pszBuf, lenBuf, "Date: %s, %2d %s %4d %2d:%02d:%02d UT\r\n", szDay[tmCurr.tm_wday], tmCurr.tm_mday, + szMonth[tmCurr.tm_mon], tmCurr.tm_year, tmCurr.tm_hour, tmCurr.tm_min, tmCurr.tm_sec); +} + + /* send a message via SMTP - * TODO: care about the result codes, we can't do it that blindly ;) * rgerhards, 2008-04-04 */ static rsRetVal @@ -299,10 +337,10 @@ sendSMTP(instanceData *pData, uchar *body) { DEFiRet; int iState; /* SMTP state */ + uchar szDateBuf[64]; assert(pData != NULL); - CHKiRet(serverConnect(pData)); CHKiRet(readResponse(pData, &iState, 220)); @@ -326,6 +364,9 @@ sendSMTP(instanceData *pData, uchar *body) /* now come the data part */ /* header */ + mkSMTPTimestamp(szDateBuf, sizeof(szDateBuf)); + CHKiRet(Send(pData->md.smtp.sock, (char*)szDateBuf, strlen((char*)szDateBuf))); + CHKiRet(Send(pData->md.smtp.sock, "From: <", sizeof("From: <") - 1)); CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszFrom, strlen((char*)pData->md.smtp.pszFrom))); CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); @@ -338,6 +379,8 @@ sendSMTP(instanceData *pData, uchar *body) CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszSubject, strlen((char*)pData->md.smtp.pszSubject))); CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); + CHKiRet(Send(pData->md.smtp.sock, "X-Mailer: rsyslog-immail\r\n", sizeof("x-mailer: rsyslog-immail\r\n") - 1)); + CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); /* indicate end of header */ /* body */ @@ -350,33 +393,32 @@ sendSMTP(instanceData *pData, uchar *body) CHKiRet(Send(pData->md.smtp.sock, "QUIT\r\n", sizeof("QUIT\r\n") - 1)); CHKiRet(readResponse(pData, &iState, 221)); - close(pData->md.smtp.sock); - pData->md.smtp.sock = -1; + /* we are finished, a new connection is created for each request, so let's close it now */ + CHKiRet(serverDisconnect(pData)); finalize_it: RETiRet; } - -/* connect to server - * rgerhards, 2008-04-04 +/* in tryResume we check if we can connect to the server in question. If that is OK, + * we close the connection without doing any actual SMTP transaction. It will be + * reopened during the actual send process. This may not be the best way to do it if + * there is a problem inside the SMTP transaction. However, we can't find that out without + * actually initiating something, and that would be bad. The logic here helps us + * correctly recover from an unreachable/down mail server, which is probably the majority + * of problem cases. For SMTP transaction problems, we will do lots of retries, but if it + * is a temporary problem, it will be fixed anyhow. So I consider this implementation to + * be clean enough, especially as I think other approaches have other weaknesses. + * rgerhards, 2008-04-08 */ -static rsRetVal doConnect(instanceData *pData) -{ - DEFiRet; - - iRet = serverConnect(pData); - if(iRet == RS_RET_IO_ERROR) - iRet = RS_RET_SUSPENDED; - - RETiRet; -} - - BEGINtryResume CODESTARTtryResume - iRet = doConnect(pData); + CHKiRet(serverConnect(pData)); + CHKiRet(serverDisconnect(pData)); /* if we fail, we will never reach this line */ +finalize_it: + if(iRet == RS_RET_IO_ERROR) + iRet = RS_RET_SUSPENDED; ENDtryResume @@ -421,10 +463,6 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) /* process template */ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_TraditionalForwardFormat")); - - /* TODO: do we need to call freeInstance if we failed - this is a general question for - * all output modules. I'll address it later as the interface evolves. rgerhards, 2007-07-25 - */ CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct @@ -465,7 +503,6 @@ CODESTARTmodExit freeConfigVariables(); /* release what we no longer need */ - objRelease(errmsg, CORE_COMPONENT); ENDmodExit @@ -490,7 +527,8 @@ CODESTARTmodInit *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr /* tell which objects we need */ - CHKiRet(objUse(errmsg, CORE_COMPONENT)); + /* so far: none */ + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpserver", 0, eCmdHdlrGetWord, NULL, &pszSrv, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpport", 0, eCmdHdlrGetWord, NULL, &pszSrvPort, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailfrom", 0, eCmdHdlrGetWord, NULL, &pszFrom, STD_LOADABLE_MODULE_ID)); -- cgit From 160ab44ef91a19f7bd92afb629a8a06a5fe34fc4 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 8 Apr 2008 10:36:48 +0200 Subject: finishing core ommail plugin --- plugins/ommail/ommail.c | 105 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 85 insertions(+), 20 deletions(-) diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c index 8d7adfa9..944a2870 100644 --- a/plugins/ommail/ommail.c +++ b/plugins/ommail/ommail.c @@ -1,6 +1,12 @@ /* ommail.c * - * This is an implementation of a mail sending output module. + * This is an implementation of a mail sending output module. So far, we + * only support direct SMTP, that is talking to a SMTP server. In the long + * term, support for using sendmail should also be implemented. Please note + * that the SMTP protocol implementation is a very bare one. We support + * RFC821/822 messages, without any authentication and any other nice + * features (no MIME, no nothing). It is assumed that proper firewalling + * and/or STMP server configuration is used together with this module. * * NOTE: read comments in module-template.h to understand how this file * works! @@ -55,16 +61,18 @@ static uchar *pszSrvPort = NULL; static uchar *pszFrom = NULL; static uchar *pszTo = NULL; static uchar *pszSubject = NULL; +static int bEnableBody = 1; /* should a mail body be generated? (set to 0 eg for SMS gateways) */ typedef struct _instanceData { int iMode; /* 0 - smtp, 1 - sendmail */ + int bHaveSubject; /* is a subject configured? (if so, it is the second string provided by rsyslog core) */ + int bEnableBody; /* is a body configured? (if so, it is the second string provided by rsyslog core) */ union { struct { uchar *pszSrv; uchar *pszSrvPort; uchar *pszFrom; uchar *pszTo; - uchar *pszSubject; char RcvBuf[1024]; /* buffer for receiving server responses */ size_t lenRcvBuf; size_t iRcvBuf; /* current index into the rcvBuf (buf empty if iRcvBuf == lenRcvBuf) */ @@ -97,8 +105,6 @@ CODESTARTfreeInstance free(pData->md.smtp.pszFrom); if(pData->md.smtp.pszTo != NULL) free(pData->md.smtp.pszTo); - if(pData->md.smtp.pszSubject != NULL) - free(pData->md.smtp.pszSubject); } ENDfreeInstance @@ -215,7 +221,6 @@ finalize_it: } - /* send text to the server, blocking send */ static rsRetVal Send(int sock, char *msg, size_t len) @@ -248,6 +253,57 @@ finalize_it: } +/* send body text to the server, blocking send + * The body is special in that we must escape a leading dot inside a line + */ +static rsRetVal +bodySend(instanceData *pData, char *msg, size_t len) +{ + DEFiRet; + char szBuf[2048]; + size_t iSrc; + size_t iBuf = 0; + int bHadCR = 0; + int bInStartOfLine = 1; + + assert(pData != NULL); + assert(msg != NULL); + + for(iSrc = 0 ; iSrc < len ; ++iSrc) { + if(iBuf >= sizeof(szBuf) - 1) { /* one is reserved for our extra dot */ + CHKiRet(Send(pData->md.smtp.sock, szBuf, iBuf)); + iBuf = 0; + } + szBuf[iBuf++] = msg[iSrc]; + switch(msg[iSrc]) { + case '\r': + bHadCR = 1; + break; + case '\n': + if(bHadCR) + bInStartOfLine = 1; + bHadCR = 0; + break; + case '.': + if(bInStartOfLine) + szBuf[iBuf++] = '.'; /* space is always reserved for this! */ + /*FALLTHROUGH*/ + default: + bInStartOfLine = 0; + bHadCR = 0; + break; + } + } + + if(iBuf > 0) { /* incomplete buffer to send (the *usual* case)? */ + CHKiRet(Send(pData->md.smtp.sock, szBuf, iBuf)); + } + +finalize_it: + RETiRet; +} + + /* read response line from server */ static rsRetVal @@ -325,7 +381,7 @@ mkSMTPTimestamp(uchar *pszBuf, size_t lenBuf) time(&tCurr); gmtime_r(&tCurr, &tmCurr); snprintf((char*)pszBuf, lenBuf, "Date: %s, %2d %s %4d %2d:%02d:%02d UT\r\n", szDay[tmCurr.tm_wday], tmCurr.tm_mday, - szMonth[tmCurr.tm_mon], tmCurr.tm_year, tmCurr.tm_hour, tmCurr.tm_min, tmCurr.tm_sec); + szMonth[tmCurr.tm_mon], 1900 + tmCurr.tm_year, tmCurr.tm_hour, tmCurr.tm_min, tmCurr.tm_sec); } @@ -333,7 +389,7 @@ mkSMTPTimestamp(uchar *pszBuf, size_t lenBuf) * rgerhards, 2008-04-04 */ static rsRetVal -sendSMTP(instanceData *pData, uchar *body) +sendSMTP(instanceData *pData, uchar *body, uchar *subject) { DEFiRet; int iState; /* SMTP state */ @@ -376,7 +432,7 @@ sendSMTP(instanceData *pData, uchar *body) CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); CHKiRet(Send(pData->md.smtp.sock, "Subject: ", sizeof("Subject: ") - 1)); - CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszSubject, strlen((char*)pData->md.smtp.pszSubject))); + CHKiRet(Send(pData->md.smtp.sock, (char*)subject, strlen((char*)subject))); CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); CHKiRet(Send(pData->md.smtp.sock, "X-Mailer: rsyslog-immail\r\n", sizeof("x-mailer: rsyslog-immail\r\n") - 1)); @@ -384,7 +440,8 @@ sendSMTP(instanceData *pData, uchar *body) CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); /* indicate end of header */ /* body */ - CHKiRet(Send(pData->md.smtp.sock, (char*)body, strlen((char*) body))); + if(pData->bEnableBody) + CHKiRet(bodySend(pData, (char*)body, strlen((char*) body))); /* end of data, back to envelope transaction */ CHKiRet(Send(pData->md.smtp.sock, "\r\n.\r\n", sizeof("\r\n.\r\n") - 1)); @@ -427,7 +484,11 @@ CODESTARTdoAction dbgprintf(" Mail\n"); /* forward */ - iRet = sendSMTP(pData, ppString[0]); + if(pData->bHaveSubject) + iRet = sendSMTP(pData, ppString[0], ppString[1]); + else + iRet = sendSMTP(pData, ppString[0], (uchar*)"message from rsyslog"); + if(iRet != RS_RET_OK) { /* error! */ dbgprintf("error sending mail, suspending\n"); @@ -438,7 +499,6 @@ ENDdoAction BEGINparseSelectorAct CODESTARTparseSelectorAct -CODE_STD_STRING_REQUESTparseSelectorAct(1) if(!strncmp((char*) p, ":ommail:", sizeof(":ommail:") - 1)) { p += sizeof(":ommail:") - 1; /* eat indicator sequence (-1 because of '\0'!) */ } else { @@ -450,19 +510,26 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) FINALIZE; /* TODO: check strdup() result */ + if(pszSubject == NULL) { + /* if no subject is configured, we need just one template string */ + CODE_STD_STRING_REQUESTparseSelectorAct(1) + } else { + CODE_STD_STRING_REQUESTparseSelectorAct(2) + pData->bHaveSubject = 1; + CHKiRet(OMSRsetEntry(*ppOMSR, 1, (uchar*)strdup((char*) pszSubject), OMSR_NO_RQD_TPL_OPTS)); + } if(pszSrv != NULL) pData->md.smtp.pszSrv = (uchar*) strdup((char*)pszSrv); if(pszSrvPort != NULL) pData->md.smtp.pszSrvPort = (uchar*) strdup((char*)pszSrvPort); - if(pszSrvPort != NULL) + if(pszFrom != NULL) pData->md.smtp.pszFrom = (uchar*) strdup((char*)pszFrom); - if(pszSrvPort != NULL) + if(pszTo != NULL) pData->md.smtp.pszTo = (uchar*) strdup((char*)pszTo); - if(pszSrvPort != NULL) - pData->md.smtp.pszSubject = (uchar*) strdup((char*)pszSubject); + pData->bEnableBody = bEnableBody; /* process template */ - CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_TraditionalForwardFormat")); + CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_FileFormat")); CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct @@ -488,10 +555,6 @@ static rsRetVal freeConfigVariables(void) free(pszTo); pszTo = NULL; } - if(pszSubject != NULL) { - free(pszSubject); - pszSubject = NULL; - } RETiRet; } @@ -517,6 +580,7 @@ ENDqueryEtryPt static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) { DEFiRet; + bEnableBody = 1; iRet = freeConfigVariables(); RETiRet; } @@ -534,6 +598,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailfrom", 0, eCmdHdlrGetWord, NULL, &pszFrom, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailto", 0, eCmdHdlrGetWord, NULL, &pszTo, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsubject", 0, eCmdHdlrGetWord, NULL, &pszSubject, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailenablebody", 0, eCmdHdlrBinary, NULL, &bEnableBody, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr( (uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit -- cgit From 413fba03dc88bafb581554bcb07eacfdb9327588 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 8 Apr 2008 11:48:07 +0200 Subject: finalized mail output support --- doc/features.html | 4 +- doc/ommail.html | 107 +++++++++++++++++++++++++++++++++++++++++ doc/rsyslog_conf.html | 2 +- doc/rsyslog_ng_comparison.html | 18 ++++--- plugins/ommail/ommail.c | 36 +++++++++++--- rsyslog.h | 2 + 6 files changed, 154 insertions(+), 15 deletions(-) create mode 100644 doc/ommail.html diff --git a/doc/features.html b/doc/features.html index f74f2aaf..13fc34c6 100644 --- a/doc/features.html +++ b/doc/features.html @@ -23,7 +23,7 @@ to MySQL databases
  • native support for writing to Postgres databases
  • direct support for Firebird/Interbase, OpenTDS (MS SQL, Sybase), SQLLite, Ingres, Oracle, and mSQL via libdbi, -a database abstraction layer (almost as good as native)
  • +a database abstraction layer (almost as good as native)
  • native support for sending mail messages (first seen in 3.17.0)
  • support for (plain) tcp based syslog - much better reliability
  • support for sending and receiving compressed syslog messages
  • @@ -35,7 +35,7 @@ into syslog messages (one per line)
  • ability to configure backup syslog/database servers - if the primary fails, control is switched to a prioritized list of backups
  • support for receiving messages via reliable -RFC 3195 delivery
  • +RFC 3195 delivery (a bit clumpsy to build right now...)
  • ability to generate file names and directories (log targets) dynamically, based on many different properties
  • control of log output format, including ability to present diff --git a/doc/ommail.html b/doc/ommail.html new file mode 100644 index 00000000..e147e94c --- /dev/null +++ b/doc/ommail.html @@ -0,0 +1,107 @@ + +mail output module - sending syslog messages via mail + + + +

    Mail Output Module (ommail)

    +

    Module Name:    ommail

    +

    Author: Rainer Gerhards +<rgerhards@adiscon.com>

    +

    Description:

    +

    This module supports sending syslog messages via mail. Each +syslog message is sent via its own mail. Obviously, you will want to +apply rigorous filtering, otherwise your mailbox (and mail server) will +be heavily spammed. The ommail plugin is primarily meant for alerting +users. As such, it is assume that mails will only be sent in an +extremely limited number of cases.

    +

    Please note that ommail is especially well-suited to work in +tandem with imfile to +watch files for the occurence of specific things to be alerted on. So +its scope is far broader than forwarding syslog messages to mail +recipients.

    +Ommail uses two templates, one for the mail body and one for the +subject line. If neither is provided, a quite meaningless subject line +is used and the mail body will be a syslog message just as if it were +written to a file. It is expected that the users customizes both +messages. In an effort to support cell phones (including SMS gateways), +there is an option to turn off the body part at all. This is considered +to be useful to send a short alert to a pager-like device. +

    Configuration Directives:

    +
      +
    • $ActionMailSMTPServer
      +Name or IP address of the SMTP server to be used. Must currently be +set. The default is 127.0.0.1, the SMTP server on the local machine. +Obviously it is not good to expect one to be present on each machine, +so this value should be specified.
      +
    • +
    • $ActionMailSMTPPort
      +Port number or name of the SMTP port to be used. The default is 25, the +standard SMTP port.
    • +
    • $ActionMailFrom
      +The email address used as the senders address. There is no default.
    • +
    • $ActionMailTo
      +The recipients email address. There is no default.
    • +
    • $ActionMailSubject
      +The name of the template +to be used as the mail subject. If this is not specified, a more or +less meaningless mail subject is generated (we don't tell you the exact +text because that can change - if you want to have something specific, +configure it!).
    • +
    • $ActionMailEnableBody
      +Setting this to "off" permits to exclude the actual message body. This +may be useful for pager-like devices or cell phone SMS messages. The +default is "on", which is appropriate for allmost all cases. Turn it +off only if you know exactly what you do!
    • +
    +Caveats/Known Bugs: +

    The current ommail implementation supports SMTP-direct mode +only. In that mode, the plugin talks to the mail server via SMTP +protocol. No other process is involved. This mode offers best +reliability as it is not depending on any external entity except the +mail server. Mail server downtime is acceptable if the action is put +onto its own action queue, so that it may wait for the SMTP server to +come back online. However, the module implements only the bare SMTP +essentials. Most importantly, it does not provide any authentication +capabilities. So your mail server must be configured to accept incoming +mail from ommail without any authentication needs (this may be change +in the future as need arises, but you may also be referred to +sendmail-mode).

    +

    In theory, ommail should also offer a mode where it uses the +sendmail utility to send its mail (sendmail-mode). +This is somewhat less reliable (because we depend on an entity we do +not have close control over - sendmail). It also requires dramatically +more system ressources, as we need to load the external process (but +that should be no problem given the expected infrequent number of calls +into this plugin). The big advantage of sendmail mode is that it +supports all the bells and whistles of a full-blown SMTP implementation +and may even work for local delivery without a SMTP server being +present. Sendmail mode will be implemented as need arises. So if you +need it, please drop us a line (I nobody does, sendmail mode will +probably never be implemented).

    +

    Sample:

    +

    The following sample alerts the operator if the string "hard +disk fatal failure" is present inside a syslog message. The mail server +at mail.example.net is used and the subject shall be "disk problem on +<hostname>". Note how \r\n is included inside the body +text +to create line breaks.
    +

    + +

    [rsyslog.conf overview] +[manual index] [rsyslog site]

    +

    This documentation is part of the +rsyslog +project.
    +Copyright © 2008 by Rainer +Gerhards and +Adiscon. +Released under the GNU GPL version 3 or higher.

    + \ No newline at end of file diff --git a/doc/rsyslog_conf.html b/doc/rsyslog_conf.html index 2a0f0c60..481abb38 100644 --- a/doc/rsyslog_conf.html +++ b/doc/rsyslog_conf.html @@ -32,7 +32,7 @@ trap output module
  • omrelp - RELP output module
  • ompgsql - output module for PostgreSQL
  • omlibdbi - generic database output module (Firebird/Interbase, MS SQL, Sybase, -SQLLite, Ingres, Oracle, mSQL)
  • +SQLLite, Ingres, Oracle, mSQL)
  • ommail - permits rsyslog to alert folks by mail if something important happens
  • imfile -  input module for text files
  • imrelp - RELP input module
  • imudp - udp syslog message input
  • diff --git a/doc/rsyslog_ng_comparison.html b/doc/rsyslog_ng_comparison.html index 4ee8c10b..28413337 100644 --- a/doc/rsyslog_ng_comparison.html +++ b/doc/rsyslog_ng_comparison.html @@ -1,11 +1,11 @@ - -rsyslog vs. syslog-ng - a comparison +rsyslog vs. syslog-ng - a comparison +

    rsyslog vs. syslog-ng

    Written by Rainer Gerhards -(2008-02-28)

    +(2008-04-08)

    We have often been asked about a comparison sheet between rsyslog and syslog-ng. Unfortunately, I do not know much about syslog-ng, I did not even use it once. Also, there seems to be no @@ -341,7 +341,9 @@ be placed on different disk

    - + @@ -424,6 +426,10 @@ including ability to present channel and priority as visible log data + + + + @@ -572,6 +578,6 @@ feature sheet. I have not yet been able to fully work through it. In the mean time, you may want to read it in parallel. It is available at Balabit's site.

    -

    This document is current as of 2008-04-07 and definitely +

    This document is current as of 2008-04-08 and definitely incomplete (I did not yet manage to complete it!).

    - + \ No newline at end of file diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c index 944a2870..218c73c9 100644 --- a/plugins/ommail/ommail.c +++ b/plugins/ommail/ommail.c @@ -49,12 +49,14 @@ #include "srUtils.h" #include "cfsysline.h" #include "module-template.h" +#include "errmsg.h" MODULE_TYPE_OUTPUT /* internal structures */ DEF_OMOD_STATIC_DATA +DEFobjCurrIf(errmsg) static uchar *pszSrv = NULL; static uchar *pszSrvPort = NULL; @@ -183,15 +185,27 @@ serverConnect(instanceData *pData) { struct addrinfo *res = NULL; struct addrinfo hints; + char *smtpPort; + char *smtpSrv; char errStr[1024]; DEFiRet; assert(pData != NULL); + if(pData->md.smtp.pszSrv == NULL) + smtpSrv = "127.0.0.1"; + else + smtpSrv = (char*)pData->md.smtp.pszSrv; + + if(pData->md.smtp.pszSrvPort == NULL) + smtpPort = "25"; + else + smtpPort = (char*)pData->md.smtp.pszSrvPort; + memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* TODO: make configurable! */ hints.ai_socktype = SOCK_STREAM; - if(getaddrinfo((char*)pData->md.smtp.pszSrv, (char*)pData->md.smtp.pszSrvPort, &hints, &res) != 0) { + if(getaddrinfo(smtpSrv, smtpPort, &hints, &res) != 0) { dbgprintf("error %d in getaddrinfo\n", errno); ABORT_FINALIZE(RS_RET_IO_ERROR); } @@ -510,6 +524,19 @@ CODESTARTparseSelectorAct FINALIZE; /* TODO: check strdup() result */ + + if(pszFrom == NULL) { + errmsg.LogError(NO_ERRCODE, "no sender address given - specify $ActionMailFrom"); + ABORT_FINALIZE(RS_RET_MAIL_NO_FROM); + } + if(pszTo == NULL) { + errmsg.LogError(NO_ERRCODE, "no recipient address given - specify $ActionMailTo"); + ABORT_FINALIZE(RS_RET_MAIL_NO_TO); + } + + pData->md.smtp.pszFrom = (uchar*) strdup((char*)pszFrom); + pData->md.smtp.pszTo = (uchar*) strdup((char*)pszTo); + if(pszSubject == NULL) { /* if no subject is configured, we need just one template string */ CODE_STD_STRING_REQUESTparseSelectorAct(1) @@ -522,10 +549,6 @@ CODESTARTparseSelectorAct pData->md.smtp.pszSrv = (uchar*) strdup((char*)pszSrv); if(pszSrvPort != NULL) pData->md.smtp.pszSrvPort = (uchar*) strdup((char*)pszSrvPort); - if(pszFrom != NULL) - pData->md.smtp.pszFrom = (uchar*) strdup((char*)pszFrom); - if(pszTo != NULL) - pData->md.smtp.pszTo = (uchar*) strdup((char*)pszTo); pData->bEnableBody = bEnableBody; /* process template */ @@ -566,6 +589,7 @@ CODESTARTmodExit freeConfigVariables(); /* release what we no longer need */ + objRelease(errmsg, CORE_COMPONENT); ENDmodExit @@ -591,7 +615,7 @@ CODESTARTmodInit *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr /* tell which objects we need */ - /* so far: none */ + CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpserver", 0, eCmdHdlrGetWord, NULL, &pszSrv, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpport", 0, eCmdHdlrGetWord, NULL, &pszSrvPort, STD_LOADABLE_MODULE_ID)); diff --git a/rsyslog.h b/rsyslog.h index b52e08b1..93b5c149 100644 --- a/rsyslog.h +++ b/rsyslog.h @@ -169,6 +169,8 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_MODULE_LOAD_ERR_INIT_FAILED = -2068, /**< module could not be loaded - init() failed */ RS_RET_NO_SOCKET = -2069, /**< socket could not be obtained or was not provided */ RS_RET_SMTP_ERROR = -2070, /**< error during SMTP transation */ + RS_RET_MAIL_NO_TO = -2071, /**< recipient for mail destination is missing */ + RS_RET_MAIL_NO_FROM = -2072, /**< sender for mail destination is missing */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ -- cgit From d2523072aaf7a7a98bf92a64daf6287fad9072c3 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 8 Apr 2008 11:53:24 +0200 Subject: added native mail functionality --- ChangeLog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 876f4130..7861f88d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ --------------------------------------------------------------------------- -Version 3.17.0 (rgerhards), 2008-04-?? -- FEATURE FOCUS for 3.17 is TLS over plain TCP syslog +Version 3.17.0 (rgerhards), 2008-04-08 +- added native ability to send mail messages - removed no longer needed file relptuil.c/.h - bugfix: memory leaks in script engine - bugfix: zero-length strings were not supported in object -- cgit From 185bc5f8e1bacb43cfd7f0fa555aa61577157602 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 8 Apr 2008 12:54:09 +0200 Subject: implemented $ActionExecOnlyOnceEveryInterval config directive --- ChangeLog | 1 + action.c | 17 ++++++++++- action.h | 4 ++- doc/ommail.html | 22 ++++++++++++-- doc/rsyslog_conf.html | 81 ++++++++++++++++++++++++++++++++++++++------------- syslogd.c | 3 ++ syslogd.h | 1 + 7 files changed, 104 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 00abf02d..20e5ff70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ Version 3.17.0 (rgerhards), 2008-04-08 - added native ability to send mail messages - removed no longer needed file relptuil.c/.h +- added $ActionExecOnlyOnceEveryInterval config directive - bugfix: memory leaks in script engine - bugfix: zero-length strings were not supported in object deserializer diff --git a/action.c b/action.c index 30bf3c92..39c37b5b 100644 --- a/action.c +++ b/action.c @@ -504,6 +504,7 @@ actionWriteToAction(action_t *pAction) { msg_t *pMsgSave; /* to save current message pointer, necessary to restore it in case it needs to be updated (e.g. repeated msgs) */ + time_t now; DEFiRet; pMsgSave = NULL; /* indicate message poiner not saved */ @@ -542,7 +543,20 @@ actionWriteToAction(action_t *pAction) dbgprintf("Called action, logging to %s", module.GetStateName(pAction->pMod)); - time(&pAction->f_time); /* we need this for message repeation processing */ + time(&now); /* we need this for message repeation processing AND $ActionExecOnlyOnceEveryInterval */ + /* now check if we need to drop the message because otherwise the action would be too + * frequently called. -- rgerhards, 2008-04-08 + */ + if(pAction->f_time != 0 && pAction->iSecsExecOnceInterval + pAction->tLastExec > now) { + /* in this case we need to discard the message - its not yet time to exec the action */ + dbgprintf("action not yet ready again to be executed, onceInterval %d, tCurr %d, tNext %d\n", + (int) pAction->iSecsExecOnceInterval, (int) now, + (int) (pAction->iSecsExecOnceInterval + pAction->tLastExec)); + FINALIZE; + } + + pAction->tLastExec = now; /* we need this OnceInterval */ + pAction->f_time = now; /* we need this for message repeation processing */ /* When we reach this point, we have a valid, non-disabled action. * So let's enqueue our message for execution. -- rgerhards, 2007-07-24 @@ -718,6 +732,7 @@ addAction(action_t **ppAction, modInfo_t *pMod, void *pModData, omodStringReques pAction->pMod = pMod; pAction->pModData = pModData; pAction->bExecWhenPrevSusp = bActExecWhenPrevSusp; + pAction->iSecsExecOnceInterval = iActExecOnceInterval; /* check if we can obtain the template pointers - TODO: move to separate function? */ pAction->iNumTpls = OMSRgetEntryCount(pOMSR); diff --git a/action.h b/action.h index 1fa05c15..99108aab 100644 --- a/action.h +++ b/action.h @@ -39,8 +39,10 @@ extern int glbliActionResumeRetryCount; /* the following struct defines the action object data structure */ struct action_s { - time_t f_time; /* time this was last written */ + time_t f_time; /* used for "message repeated n times" - be careful, old, old code */ + time_t tLastExec; /* time this action was last executed */ int bExecWhenPrevSusp;/* execute only when previous action is suspended? */ + int iSecsExecOnceInterval; /* if non-zero, minimum seconds to wait until action is executed again */ short bEnabled; /* is the related action enabled (1) or disabled (0)? */ short bSuspended; /* is the related action temporarily suspended? */ time_t ttResumeRtry; /* when is it time to retry the resume? */ diff --git a/doc/ommail.html b/doc/ommail.html index e147e94c..74fab739 100644 --- a/doc/ommail.html +++ b/doc/ommail.html @@ -25,7 +25,16 @@ is used and the mail body will be a syslog message just as if it were written to a file. It is expected that the users customizes both messages. In an effort to support cell phones (including SMS gateways), there is an option to turn off the body part at all. This is considered -to be useful to send a short alert to a pager-like device. +to be useful to send a short alert to a pager-like device.
    +
    +It is highly recommended to use the  "$ActionExecOnlyOnceEveryInterval +<seconds>" directive to limit the amount of +mails that potentially be generated. With it, mails are sent at most in +a <seconds> interval. This may be your life safer. And +remember that an hour has 3,600 seconds, so if you would like to +receive mails at most once every two hours, include a +"$ActionExecOnlyOnceEveryInterval 7200" immediately before the ommail +action. Messages sent more frequently are simpy discarded.

    Configuration Directives:

    • $ActionMailSMTPServer
      @@ -84,15 +93,22 @@ disk fatal failure" is present inside a syslog message. The mail server at mail.example.net is used and the subject shall be "disk problem on <hostname>". Note how \r\n is included inside the body text -to create line breaks.
      +to create line breaks. A message is sent at most once every 6 hours, +any other messages are silently discarded (or, to be precise, not being +forwarded - they are still being processed by the rest of the +configuration file).

      -

      [rsyslog.conf overview] diff --git a/doc/rsyslog_conf.html b/doc/rsyslog_conf.html index 481abb38..8967f671 100644 --- a/doc/rsyslog_conf.html +++ b/doc/rsyslog_conf.html @@ -1,5 +1,7 @@ -rsyslog.conf file +rsyslog.conf file + +

      rsyslog.conf configuration file

      This document is currently being enhanced. Please @@ -26,22 +28,30 @@ number of modules. Here is the entry point to their documentation and what they do (list is currently not complete)

      • omsnmp - SNMP -trap output module
      • omrelp - RELP output module
      • +trap output module +
      • omrelp - RELP +output module
      • omgss - output module for GSS-enabled syslog
      • ommysql - output module for MySQL
      • ompgsql - output module for PostgreSQL
      • omlibdbi - generic database output module (Firebird/Interbase, MS SQL, Sybase, -SQLLite, Ingres, Oracle, mSQL)
      • ommail - permits rsyslog to alert folks by mail if something important happens
      • +SQLLite, Ingres, Oracle, mSQL) +
      • ommail - +permits rsyslog to alert folks by mail if something important happens
      • imfile --  input module for text files
      • imrelp - RELP input module
      • +-  input module for text files +
      • imrelp - RELP +input module
      • imudp - udp syslog message input
      • imtcp - input plugin for plain tcp syslog
      • imgssapi - input plugin for plain tcp and GSS-enable syslog
      • immark - support for mark messages
      • -
      • imklog - kernel logging
      • imuxsock - unix sockets, including the system log socket
      • +
      • imklog - kernel logging
      • +
      • imuxsock - +unix sockets, including the system log socket

      Please note that each module provides configuration directives, which are NOT necessarily being listed below. Also @@ -64,7 +74,19 @@ unstable...). So you have been warned ;)

      many parameter settings modify queue parameters. If in doubt, use the default, it is usually well-chosen and applicable in most cases.

        -
      • $ActionExecOnlyWhenPreviousIsSuspended
      • $ActionFileDefaultTemplate [templateName] - sets a new default template for file actions
      • $ActionFileEnableSync [on/off] - enables file syncing capability of omfile
      • $ActionForwardDefaultTemplate [templateName] - sets a new default template for UDP and plain TCP forwarding action
      • $ActionGSSForwardDefaultTemplate [templateName] - sets a new default template for GSS-API forwarding action
      • +
      • $ActionExecOnlyWhenPreviousIsSuspended
      • +
      • $ActionExecOnlyOnceEveryInterval <seconds> - +execute action only if the last execute is at last +<seconds> seconds in the past (more info in ommail, +but may be used with any action)
      • +
      • $ActionFileDefaultTemplate [templateName] - sets a new +default template for file actions
      • +
      • $ActionFileEnableSync [on/off] - enables file +syncing capability of omfile
      • +
      • $ActionForwardDefaultTemplate [templateName] - sets a new +default template for UDP and plain TCP forwarding action
      • +
      • $ActionGSSForwardDefaultTemplate [templateName] - sets a +new default template for GSS-API forwarding action
      • $ActionQueueCheckpointInterval <number>
      • $ActionQueueDequeueSlowdown <number> [number is timeout in microseconds (1000000us is 1sec!), @@ -98,7 +120,8 @@ default 60000 (1 minute)]
      • worker threads, default 1, recommended 1
      • $ActionQueueWorkerThreadMinumumMessages <number>, default 100
      • -
      • $ActionResumeInterval
      • $ActionResumeRetryCount <number> [default 0, +
      • $ActionResumeInterval
      • +
      • $ActionResumeRetryCount <number> [default 0, -1 means eternal]
      • $AllowedSender
      • $ControlCharacterEscapePrefix
      • @@ -166,11 +189,11 @@ worker threads, default 1, recommended 1 (immark)
      • $ModDir
      • $ModLoad
      • -
      • $RepeatedMsgReduction
      • $ResetConfigVariables
      • $WorkDirectory <name> (directory for spool -and other work files)
      • $UDPServerAddress <IP> (imudp) -- local IP +and other work files)
      • +
      • $UDPServerAddress <IP> (imudp) -- local IP address (or name) the UDP listens should bind to
      • $UDPServerRun <port> (imudp) -- former -r<port> option, default 514, start UDP server on this @@ -302,18 +325,29 @@ template:

        DynFile,"/var/log/system-%HOSTNAME%.log"

        This template can then be used when defining an output selector line. It will result in something like -"/var/log/system-localhost.log"

        Template +"/var/log/system-localhost.log"

        +

        Template names beginning with "RSYSLOG_" are reserved for rsyslog use. Do NOT use them if, otherwise you may receive a conflict in the future (and quite unpredictable behaviour). There is a small set of pre-defined -templates that you can use without the need to define it:

        • RSYSLOG_TraditionalFileFormat - the "old style" default log file format with low-precision timestamps
        • RSYSLOG_FileFormat - a modern-style logfile format similar to TraditionalFileFormat, buth with high-precision timestamps and timezone information
        • RSYSLOG_TraditionalForwardFormat +templates that you can use without the need to define it:

          +
            +
          • RSYSLOG_TraditionalFileFormat +- the "old style" default log file format with low-precision timestamps
          • +
          • RSYSLOG_FileFormat +- a modern-style logfile format similar to TraditionalFileFormat, buth +with high-precision timestamps and timezone information
          • +
          • RSYSLOG_TraditionalForwardFormat - the traditional forwarding format with low-precision timestamps. Most -useful if you send messages to other syslogd's or rsyslogd below -version 3.12.5.
          • RSYSLOG_ForwardFormat +useful if you send messages to other syslogd's or rsyslogd +below +version 3.12.5.
          • +
          • RSYSLOG_ForwardFormat - a new high-precision forwarding format very similar to the traditional one, but with high-precision timestamps and timezone information. Recommended to be used when sending messages to rsyslog -3.12.5 or above.
          • RSYSLOG_SyslogProtocol23Format +3.12.5 or above.
          • +
          • RSYSLOG_SyslogProtocol23Format - the format specified in IETF's internet-draft ietf-syslog-protocol-23, which is assumed to be come the new syslog standard RFC. This format includes several improvements. The rsyslog @@ -321,7 +355,8 @@ message parser understands this format, so you can use it together with all relatively recent versions of rsyslog. Other syslogd's may get hopelessly confused if receiving that format, so check before you use it. Note that the format is unlikely to change when the final RFC comes -out, but this may happen.
          +out, but this may happen.
        • +

        Output Channels

        Output Channels are a new concept first introduced in rsyslog 0.9.0. As of this writing, it is most likely that they will @@ -524,7 +559,8 @@ once they are implemented, it can make very much sense

    - @@ -567,10 +603,12 @@ code), this can be done easily by:

    "ID-4711". Please note that the comparison is case-sensitive, so it would not match if "id-4711" would be contained in the message.

    :msg, regex, "fatal .* error"

    -

    This filter uses a POSIX regular expression. It matches when the +

    This filter uses a POSIX regular expression. It matches when +the string contains the words "fatal" and "error" with anything in between (e.g. "fatal net error" and "fatal lib error" but not "fatal error" as -two spaces are required by the regular expression!).

    Getting property-based filters right can sometimes be +two spaces are required by the regular expression!).

    +

    Getting property-based filters right can sometimes be challenging. In order to help you do it with as minimal effort as possible, rsyslogd spits out debug information for all property-based filters during their evaluation. To enable this, run rsyslogd in @@ -635,9 +673,12 @@ startswith 'DEVNAME' and not ($msg contains 'error1' or $msg contains 'error0') then /var/log/somelog
    -
    If you would like to do case-insensitive comparisons, use +
    +If you would like to do case-insensitive comparisons, use "contains_i" instead of "contains" and "startswith_i" instead of -"startswith".

    Note that regular expressions are currently NOT +"startswith".
    +
    +Note that regular expressions are currently NOT supported in expression-based filters. These will be added later when function support is added to the expression engine (the reason is that regular expressions will be a separate loadable module, which requires diff --git a/syslogd.c b/syslogd.c index 778fd713..b56c2f39 100644 --- a/syslogd.c +++ b/syslogd.c @@ -301,6 +301,7 @@ static uchar cCCEscapeChar = '\\';/* character to be used to start an escape seq static int bEscapeCCOnRcv = 1; /* escape control characters on reception: 0 - no, 1 - yes */ int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */ int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */ +int iActExecOnceInterval = 0; /* execute action once every nn seconds */ uchar *pszWorkDir = NULL;/* name of rsyslog's spool directory (without trailing slash) */ uchar *glblModPath = NULL; /* module load path - only used during initial init, only settable via -M command line option */ /* end global config file state variables */ @@ -379,6 +380,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a { cCCEscapeChar = '#'; bActExecWhenPrevSusp = 0; + iActExecOnceInterval = 0; bDebugPrintTemplateList = 1; bDebugPrintCfSysLineHandlerList = 1; bDebugPrintModuleList = 1; @@ -2692,6 +2694,7 @@ static rsRetVal loadBuildInModules(void) CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimeend", 0, eCmdHdlrInt, NULL, &iMainMsgQueueDeqtWinToHr, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgreduction", 0, eCmdHdlrBinary, NULL, &bReduceRepeatMsgs, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlywhenpreviousissuspended", 0, eCmdHdlrBinary, NULL, &bActExecWhenPrevSusp, NULL)); + CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlyonceeveryinterval", 0, eCmdHdlrInt, NULL, &iActExecOnceInterval, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt, setActionResumeInterval, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, NULL, &cCCEscapeChar, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, NULL, &bEscapeCCOnRcv, NULL)); diff --git a/syslogd.h b/syslogd.h index 4eefd325..cbb4bb05 100644 --- a/syslogd.h +++ b/syslogd.h @@ -149,6 +149,7 @@ extern char ctty[]; extern int MarkInterval; extern int bReduceRepeatMsgs; extern int bActExecWhenPrevSusp; +extern int iActExecOnceInterval; /* Intervals at which we flush out "message repeated" messages, * in seconds after previous message is logged. After each flush, -- cgit From b544865bed0b94bdaac4cdfd550a8dd5ab9bfccb Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 8 Apr 2008 18:24:42 +0200 Subject: preparing for 3.17.0 release --- ChangeLog | 2 ++ doc/status.html | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1f7f0f4a..330f4b3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,6 +24,8 @@ Version 3.17.0 (rgerhards), 2008-04-08 easier to work with non-standard module library locations. Thanks to varmojfekoj for suggesting this change. Matches bugzilla bug 55. - bugfix: some messages were emited without hostname +Plus a number of bugfixes that were applied to v3-stable and beta +branches (not mentioned here in detail). --------------------------------------------------------------------------- Version 3.15.1 (rgerhards), 2008-04-?? - bugfix: some messages were emited without hostname diff --git a/doc/status.html b/doc/status.html index 5ab6ea05..5b3b377a 100644 --- a/doc/status.html +++ b/doc/status.html @@ -2,10 +2,14 @@ rsyslog status page

    rsyslog status page

    -

    This page reflects the status as of 2008-04-07.

    +

    This page reflects the status as of 2008-04-08.

    Current Releases

    -

    development: 3.15.0 - +

    development: 3.17.0 - +change log - +download

    + +

    beta: 3.15.0 - change log - download

    -- cgit From 6b26252a4ce7baa96ea76d8bd4f2717329d8ae6c Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 8 Apr 2008 18:39:33 +0200 Subject: bumped version number --- ChangeLog | 2 ++ configure.ac | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 330f4b3f..e9fadf12 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ --------------------------------------------------------------------------- +Version 3.17.1 (rgerhards), 2008-04-?? +--------------------------------------------------------------------------- Version 3.17.0 (rgerhards), 2008-04-08 - added native ability to send mail messages - removed no longer needed file relptuil.c/.h diff --git a/configure.ac b/configure.ac index a938eae2..1516ef71 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([rsyslog],[3.17.0],[rsyslog@lists.adiscon.com]) +AC_INIT([rsyslog],[3.17.1],[rsyslog@lists.adiscon.com]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([syslogd.c]) AC_CONFIG_HEADERS([config.h]) -- cgit From 9b5fa059d026777ca9d95b66b17d95296fd6c1ff Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 8 Apr 2008 18:47:00 +0200 Subject: typo fix --- doc/ommail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ommail.html b/doc/ommail.html index 74fab739..ec5c5258 100644 --- a/doc/ommail.html +++ b/doc/ommail.html @@ -108,7 +108,7 @@ $ActionMailSubject mailSubject # make sure we receive a mail only once in six # hours (21,600 seconds ;)) $ActionExecOnlyOnceEveryInterval 21600 -# the if ... then ... mailbody mus be on one line! +# the if ... then ... mailBody mus be on one line! if $msg contains 'hard disk fatal failure' then :ommail:;mailBody

    [rsyslog.conf overview] -- cgit From a61f8543ff89a9eef1bef1686fff1035f5f79249 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 9 Apr 2008 08:11:22 +0200 Subject: our BSD define conflicted with a BSD system define renamed to OS_BSD --- configure.ac | 2 +- net.c | 8 ++++---- net.h | 2 +- omusrmsg.c | 6 +++--- syslogd.c | 2 +- tcpsrv.c | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index 1516ef71..586f03e3 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ case "${host}" in *-*-linux*) ;; *-*-*darwin*|*-*-freebsd*|*-*-netbsd*|*-*-openbsd*) - AC_DEFINE([BSD], [1], [Description]) + AC_DEFINE([OS_BSD], [1], [Description]) ;; esac diff --git a/net.c b/net.c index ab669323..d0c51021 100644 --- a/net.c +++ b/net.c @@ -580,7 +580,7 @@ static int isAllowedSender(struct AllowedSenders *pAllowRoot, struct sockaddr *p static int should_use_so_bsdcompat(void) { -#ifndef BSD +#ifndef OS_BSD static int init_done; static int so_bsdcompat_is_obsolete; @@ -608,9 +608,9 @@ should_use_so_bsdcompat(void) so_bsdcompat_is_obsolete = 1; } return !so_bsdcompat_is_obsolete; -#else /* #ifndef BSD */ +#else /* #ifndef OS_BSD */ return 1; -#endif /* #ifndef BSD */ +#endif /* #ifndef OS_BSD */ } #ifndef SO_BSDCOMPAT /* this shall prevent compiler errors due to undfined name */ @@ -948,7 +948,7 @@ int *create_udp_socket(uchar *hostname, uchar *pszPort, int bIsServer) /* We need to enable BSD compatibility. Otherwise an attacker * could flood our log files by sending us tons of ICMP errors. */ -#if !defined(BSD) && !defined(__hpux) +#if !defined(OS_BSD) && !defined(__hpux) if (should_use_so_bsdcompat()) { if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT, (char *) &on, sizeof(on)) < 0) { diff --git a/net.h b/net.h index 2004dcfc..6c3afb51 100644 --- a/net.h +++ b/net.h @@ -34,7 +34,7 @@ #define ADDR_NAME 0x01 /* address is hostname wildcard) */ #define ADDR_PRI6 0x02 /* use IPv6 address prior to IPv4 when resolving */ -#ifdef BSD +#ifdef OS_BSD # ifndef _KERNEL # define s6_addr32 __u6_addr.__u6_addr32 # endif diff --git a/omusrmsg.c b/omusrmsg.c index c4008140..42d3291d 100644 --- a/omusrmsg.c +++ b/omusrmsg.c @@ -119,7 +119,7 @@ static void endtty() * BSD because they are not available there. We only emulate what we actually * need! rgerhards 2005-03-18 */ -#ifdef BSD +#ifdef OS_BSD static FILE *BSD_uf = NULL; void setutent(void) { @@ -145,7 +145,7 @@ void endutent(void) fclose(BSD_uf); BSD_uf = NULL; } -#endif +#endif /* #ifdef OS_BSD */ /* @@ -209,7 +209,7 @@ static rsRetVal wallmsg(uchar* pMsg, instanceData *pData) /* is this slot used? */ if (ut.ut_name[0] == '\0') continue; -#ifndef BSD +#ifndef OS_BSD if (ut.ut_type != USER_PROCESS) continue; #endif diff --git a/syslogd.c b/syslogd.c index 59fbbc29..8f5aa5ef 100644 --- a/syslogd.c +++ b/syslogd.c @@ -216,7 +216,7 @@ static rsRetVal GlobalClassExit(void); #if defined(SYSLOGD_PIDNAME) # undef _PATH_LOGPID # if defined(FSSTND) -# ifdef BSD +# ifdef OS_BSD # define _PATH_VARRUN "/var/run/" # endif # if defined(__sun) || defined(__hpux) diff --git a/tcpsrv.c b/tcpsrv.c index ae5f3371..955fb9b5 100644 --- a/tcpsrv.c +++ b/tcpsrv.c @@ -327,7 +327,7 @@ static int *create_tcp_socket(tcpsrv_t *pThis) /* We need to enable BSD compatibility. Otherwise an attacker * could flood our log files by sending us tons of ICMP errors. */ -#ifndef BSD +#ifndef OS_BSD if(net.should_use_so_bsdcompat()) { if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT, (char *) &on, sizeof(on)) < 0) { -- cgit From 838072a22f5a98e150dbab055eba28453238109f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 8 Apr 2008 23:34:14 +0200 Subject: changed imklog to a driver interface imklog now uses os-specific drivers. The initial "set" contains the linux driver. This is a prequisite for BSD klog, which can now be implemented on that driver interface. --- plugins/imklog/Makefile.am | 2 +- plugins/imklog/imklog.c | 499 +++--------------------------------------- plugins/imklog/imklog.h | 25 ++- plugins/imklog/ksym.c | 22 +- plugins/imklog/linux.c | 533 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 599 insertions(+), 482 deletions(-) create mode 100644 plugins/imklog/linux.c diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am index 11e00962..49bbbc70 100644 --- a/plugins/imklog/Makefile.am +++ b/plugins/imklog/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = imklog.la -imklog_la_SOURCES = imklog.c imklog.h module.h ksym.c ksyms.h ksym_mod.c +imklog_la_SOURCES = imklog.c linux.c imklog.h module.h ksym.c ksyms.h ksym_mod.c imklog_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) imklog_la_LDFLAGS = -module -avoid-version imklog_la_LIBADD = diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index bfea8c6f..972e93db 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -1,14 +1,24 @@ -/* The kernel log input module for Linux. This file heavily - * borrows from the klogd daemon provided by the sysklogd project. - * Many thanks for this piece of software. +/* The kernel log module. + * + * This is an abstracted module. As Linux and BSD kernel log is conceptually the + * same, we do not do different input plugins for them but use + * imklog in both cases, just with different "backend drivers" for + * the different platforms. This also enables a rsyslog.conf to + * be used on multiple platforms without the need to take care of + * what the kernel log is coming from. + * + * See platform-specific files (e.g. linux.c, bsd.c) in the plugin's + * working directory. For other systems with similar kernel logging + * functionality, no new input plugin shall be written but rather a + * driver be developed for imklog. Please note that imklog itself is + * mostly concerned with handling the interface. Any real action happens + * in the drivers, as things may be pretty different on different + * platforms. * * Please note that this file replaces the klogd daemon that was * also present in pre-v3 versions of rsyslog. * - * I have begun to convert this to an input module on 2007-12-17. - * IMPORTANT: more than a single instance is currently not supported. This - * needs to be revisited once the config file and input module interface - * supports multiple instances! + * Copyright (C) 2008 by Rainer Gerhards and Adiscon GmbH * * This file is part of rsyslog. * @@ -49,17 +59,17 @@ DEF_IMOD_STATIC_DATA /* configuration settings TODO: move to instance data? */ int dbgPrintSymbols = 0; /* this one is extern so the helpers can access it! */ -static int symbols_twice = 0; -static int use_syscall = 0; -static int symbol_lookup = 1; +int symbols_twice = 0; +int use_syscall = 0; +int symbol_lookup = 1; /* TODO: configuration for the following directives must be implemented. It * was not done yet because we either do not yet have a config handler for * that type or I thought it was acceptable to push it to a later stage when * I gained more handson experience with the input module interface (and the * changes resulting from that). -- rgerhards, 2007-12-20 */ -static char *symfile = NULL; -static int console_log_level = -1; +char *symfile = NULL; +int console_log_level = -1; /* Includes. */ @@ -74,39 +84,11 @@ static int console_log_level = -1; #include #include -#include "ksyms.h" #define __LIBRARY__ #include -#if !defined(__GLIBC__) -# define __NR_ksyslog __NR_syslog -_syscall3(int,ksyslog,int, type, char *, buf, int, len); -#else -#include -#define ksyslog klogctl -#endif - - - -#ifndef _PATH_KLOG -#define _PATH_KLOG "/proc/kmsg" -#endif - -#define LOG_BUFFER_SIZE 4096 -#define LOG_LINE_LENGTH 1000 - -static int kmsg; -static char log_buffer[LOG_BUFFER_SIZE]; - -static enum LOGSRC {none, proc, kernel} logsrc; - - - -/* Function prototypes. */ -extern int ksyslog(int type, char *buf, int len); - /* Write a message to the message queue. * returns -1 if it fails, something else otherwise @@ -161,7 +143,7 @@ rsRetVal Syslog(int priority, char *fmt, ...) char *argl; /* Output using syslog. */ - if (!strcmp(fmt, "%s")) { + if(!strcmp(fmt, "%s")) { va_start(ap, fmt); argl = va_arg(ap, char *); if (argl[0] == '<' && argl[1] && argl[2] == '>') { @@ -206,385 +188,6 @@ rsRetVal Syslog(int priority, char *fmt, ...) } -static void CloseLogSrc(void) -{ - /* Turn on logging of messages to console, but only if we had the -c - * option -- rgerhards, 2007-08-01 - */ - if (console_log_level != -1) - ksyslog(7, NULL, 0); - - /* Shutdown the log sources. */ - switch ( logsrc ) - { - case kernel: - ksyslog(0, 0, 0); - Syslog(LOG_INFO, "Kernel logging (ksyslog) stopped."); - break; - case proc: - close(kmsg); - Syslog(LOG_INFO, "Kernel logging (proc) stopped."); - break; - case none: - break; - } - - return; -} - - -static enum LOGSRC GetKernelLogSrc(void) -{ - auto struct stat sb; - - /* Set level of kernel console messaging.. */ - if ( (console_log_level != -1) && - (ksyslog(8, NULL, console_log_level) < 0) && - (errno == EINVAL) ) - { - /* - * An invalid arguement error probably indicates that - * a pre-0.14 kernel is being run. At this point we - * issue an error message and simply shut-off console - * logging completely. - */ - Syslog(LOG_WARNING, "Cannot set console log level - disabling " - "console output."); - } - - /* - * First do a stat to determine whether or not the proc based - * file system is available to get kernel messages from. - */ - if ( use_syscall || - ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) ) - { - /* Initialize kernel logging. */ - ksyslog(1, NULL, 0); - Syslog(LOG_INFO, "imklogd %s, log source = ksyslog " - "started.", VERSION); - return(kernel); - } - - if ( (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 ) - { - char sz[512]; - snprintf(sz, sizeof(sz), "imklog: Cannot open proc file system, %d - %s.\n", errno, strerror(errno)); - logmsgInternal(LOG_SYSLOG|LOG_ERR, sz, ADDDATE); - ksyslog(7, NULL, 0); /* TODO: check this, implement more */ - return(none); - } - - Syslog(LOG_INFO, "imklog %s, log source = %s started.", \ - VERSION, _PATH_KLOG); - return(proc); -} - - -/* Copy characters from ptr to line until a char in the delim - * string is encountered or until min( space, len ) chars have - * been copied. - * - * Returns the actual number of chars copied. - */ -static int copyin( char *line, int space, - const char *ptr, int len, - const char *delim ) -{ - auto int i; - auto int count; - - count = len < space ? len : space; - - for(i=0; i]", - * where "aaaaaa" is the address. These are replaced with - * "[symbolname+offset/size]" in the output line - symbolname, - * offset, and size come from the kernel symbol table. - * - * If a kernel symbol happens to fall at the end of a message close - * in length to LOG_LINE_LENGTH, the symbol will not be expanded. - * (This should never happen, since the kernel should never generate - * messages that long. - * - * To preserve the original addresses, lines containing kernel symbols - * are output twice. Once with the symbols converted and again with the - * original text. Just in case somebody wants to run their own Oops - * analysis on the syslog, e.g. ksymoops. - */ -static void LogLine(char *ptr, int len) -{ - enum parse_state_enum { - PARSING_TEXT, - PARSING_SYMSTART, /* at < */ - PARSING_SYMBOL, - PARSING_SYMEND /* at ] */ - }; - - static char line_buff[LOG_LINE_LENGTH]; - - static char *line =line_buff; - static enum parse_state_enum parse_state = PARSING_TEXT; - static int space = sizeof(line_buff)-1; - - static char *sym_start; /* points at the '<' of a symbol */ - - auto int delta = 0; /* number of chars copied */ - auto int symbols_expanded = 0; /* 1 if symbols were expanded */ - auto int skip_symbol_lookup = 0; /* skip symbol lookup on this pass */ - auto char *save_ptr = ptr; /* save start of input line */ - auto int save_len = len; /* save length at start of input line */ - - while( len > 0 ) - { - if( space == 0 ) /* line buffer is full */ - { - /* - ** Line too long. Start a new line. - */ - *line = 0; /* force null terminator */ - - dbgprintf("Line buffer full:\n"); - dbgprintf("\tLine: %s\n", line); - - Syslog( LOG_INFO, "%s", line_buff ); - line = line_buff; - space = sizeof(line_buff)-1; - parse_state = PARSING_TEXT; - symbols_expanded = 0; - skip_symbol_lookup = 0; - save_ptr = ptr; - save_len = len; - } - - switch( parse_state ) - { - case PARSING_TEXT: - delta = copyin( line, space, ptr, len, "\n[" ); - line += delta; - ptr += delta; - space -= delta; - len -= delta; - - if( space == 0 || len == 0 ) - { - break; /* full line_buff or end of input buffer */ - } - - if( *ptr == '\0' ) /* zero byte */ - { - ptr++; /* skip zero byte */ - space -= 1; - len -= 1; - - break; - } - - if( *ptr == '\n' ) /* newline */ - { - ptr++; /* skip newline */ - space -= 1; - len -= 1; - - *line = 0; /* force null terminator */ - Syslog( LOG_INFO, "%s", line_buff ); - line = line_buff; - space = sizeof(line_buff)-1; - if (symbols_twice) { - if (symbols_expanded) { - /* reprint this line without symbol lookup */ - symbols_expanded = 0; - skip_symbol_lookup = 1; - ptr = save_ptr; - len = save_len; - } - else - { - skip_symbol_lookup = 0; - save_ptr = ptr; - save_len = len; - } - } - break; - } - if( *ptr == '[' ) /* possible kernel symbol */ - { - *line++ = *ptr++; - space -= 1; - len -= 1; - if (!skip_symbol_lookup) - parse_state = PARSING_SYMSTART; /* at < */ - break; - } - /* Now that line_buff is no longer fed to *printf as format - * string, '%'s are no longer "dangerous". - */ - break; - - case PARSING_SYMSTART: - if( *ptr != '<' ) - { - parse_state = PARSING_TEXT; /* not a symbol */ - break; - } - - /* - ** Save this character for now. If this turns out to - ** be a valid symbol, this char will be replaced later. - ** If not, we'll just leave it there. - */ - - sym_start = line; /* this will point at the '<' */ - - *line++ = *ptr++; - space -= 1; - len -= 1; - parse_state = PARSING_SYMBOL; /* symbol... */ - break; - - case PARSING_SYMBOL: - delta = copyin( line, space, ptr, len, ">\n[" ); - line += delta; - ptr += delta; - space -= delta; - len -= delta; - if( space == 0 || len == 0 ) - { - break; /* full line_buff or end of input buffer */ - } - if( *ptr != '>' ) - { - parse_state = PARSING_TEXT; - break; - } - - *line++ = *ptr++; /* copy the '>' */ - space -= 1; - len -= 1; - - parse_state = PARSING_SYMEND; - - break; - - case PARSING_SYMEND: - if( *ptr != ']' ) - { - parse_state = PARSING_TEXT; /* not a symbol */ - break; - } - - /* - ** It's really a symbol! Replace address with the - ** symbol text. - */ - { - auto int sym_space; - - unsigned long value; - auto struct symbol sym; - auto char *symbol; - - *(line-1) = 0; /* null terminate the address string */ - value = strtoul(sym_start+1, (char **) 0, 16); - *(line-1) = '>'; /* put back delim */ - - if ( !symbol_lookup || (symbol = LookupSymbol(value, &sym)) == (char *)0 ) - { - parse_state = PARSING_TEXT; - break; - } - - /* - ** verify there is room in the line buffer - */ - sym_space = space + ( line - sym_start ); - if( (unsigned) sym_space < strlen(symbol) + 30 ) /*(30 should be overkill)*/ - { - parse_state = PARSING_TEXT; /* not enough space */ - break; - } - - delta = sprintf( sym_start, "%s+%d/%d]", - symbol, sym.offset, sym.size ); - - space = sym_space + delta; - line = sym_start + delta; - symbols_expanded = 1; - } - ptr++; - len--; - parse_state = PARSING_TEXT; - break; - - default: /* Can't get here! */ - parse_state = PARSING_TEXT; - - } - } - - return; -} - - -static void LogKernelLine(void) -{ - auto int rdcnt; - - /* - * Zero-fill the log buffer. This should cure a multitude of - * problems with klogd logging the tail end of the message buffer - * which will contain old messages. Then read the kernel log - * messages into this fresh buffer. - */ - memset(log_buffer, '\0', sizeof(log_buffer)); - if ( (rdcnt = ksyslog(2, log_buffer, sizeof(log_buffer)-1)) < 0 ) - { - char sz[512]; - if(errno == EINTR) - return; - snprintf(sz, sizeof(sz), "imklog: Error return from sys_sycall: %d - %s\n", errno, strerror(errno)); - logmsgInternal(LOG_SYSLOG|LOG_ERR, sz, ADDDATE); - } - else - LogLine(log_buffer, rdcnt); - return; -} - - -static void LogProcLine(void) -{ - auto int rdcnt; - - /* - * Zero-fill the log buffer. This should cure a multitude of - * problems with klogd logging the tail end of the message buffer - * which will contain old messages. Then read the kernel messages - * from the message pseudo-file into this fresh buffer. - */ - memset(log_buffer, '\0', sizeof(log_buffer)); - if ( (rdcnt = read(kmsg, log_buffer, sizeof(log_buffer)-1)) < 0 ) - { - if ( errno == EINTR ) - return; - Syslog(LOG_ERR, "Cannot read proc file system: %d - %s.", errno, strerror(errno)); - } - else - LogLine(log_buffer, rdcnt); - - return; -} - - BEGINrunInput CODESTARTrunInput /* this is an endless loop - it is terminated when the thread is @@ -592,59 +195,25 @@ CODESTARTrunInput * right into the sleep below. */ while(!pThrd->bShallStop) { - /* we do not need to handle the RS_RET_TERMINATE_NOW case any - * special because we just need to terminate. This may be different - * if a cleanup is needed. But for now, we can just use CHKiRet(). - * rgerhards, 2007-12-17 + /* klogLogKMsg() waits for the next kernel message, obtains it + * and then submits it to the rsyslog main queue. + * rgerhards, 2008-04-09 */ - switch ( logsrc ) - { - case kernel: - LogKernelLine(); - break; - case proc: - LogProcLine(); - break; - case none: - /* TODO: We need to handle this case here somewhat more intelligent - * This is now at least partly done - code should never reach this point - * as willRun() already checked for the "none" status -- rgerhards, 2007-12-17 - */ - pause(); - break; - } + CHKiRet(klogLogKMsg()); } - RETiRet; +finalize_it: ENDrunInput BEGINwillRun - /* Initialize this module. If that fails, we tell the engine we don't like to run */ - /* Determine where kernel logging information is to come from. */ - logsrc = GetKernelLogSrc(); - if(logsrc == none) { - iRet = RS_RET_NO_KERNEL_LOGSRC; - } else { - if (symbol_lookup) { - symbol_lookup = (InitKsyms(symfile) == 1); - symbol_lookup |= InitMsyms(); - if (symbol_lookup == 0) { - Syslog(LOG_WARNING, "cannot find any symbols, turning off symbol lookups\n"); - } - } - } CODESTARTwillRun + iRet = klogWillRun(); ENDwillRun BEGINafterRun CODESTARTafterRun - /* cleanup here */ - if(logsrc != none) - CloseLogSrc(); - - DeinitKsyms(); - DeinitMsyms(); + iRet = klogAfterRun(); ENDafterRun @@ -678,11 +247,5 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogusesyscallinterface", 0, eCmdHdlrBinary, NULL, &use_syscall, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit -/* - * Local variables: - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - * vi:set ai: +/* vim:set ai: */ diff --git a/plugins/imklog/imklog.h b/plugins/imklog/imklog.h index 71525a79..0ac25d6c 100644 --- a/plugins/imklog/imklog.h +++ b/plugins/imklog/imklog.h @@ -2,8 +2,10 @@ * These are the definitions for the klog message generation module. * * File begun on 2007-12-17 by RGerhards + * Major change: 2008-04-09: switched to a driver interface for + * several platforms * - * Copyright 2007 Rainer Gerhards and Adiscon GmbH. + * Copyright 2007-2008 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * @@ -28,7 +30,26 @@ #include "rsyslog.h" #include "syslogd.h" -/* global variables */ +/* interface to "drivers" + * the platform specific drivers must implement these entry points. Only one + * driver may be active at any given time, thus we simply rely on the linker + * to resolve the addresses. + * rgerhards, 2008-04-09 + */ +rsRetVal klogLogKMsg(void); +rsRetVal klogWillRun(void); +rsRetVal klogAfterRun(void); + +/* the following data members may be accessed by the "drivers" + * I admit this is not the cleanest way to doing things, but I honestly + * believe it is appropriate for the job that needs to be done. + * rgerhards, 2008-04-09 + */ +extern int symbols_twice; +extern int use_syscall; +extern int symbol_lookup; +extern char *symfile; +extern int console_log_level; extern int dbgPrintSymbols; /* prototypes */ diff --git a/plugins/imklog/ksym.c b/plugins/imklog/ksym.c index b7d5903e..716ad926 100644 --- a/plugins/imklog/ksym.c +++ b/plugins/imklog/ksym.c @@ -296,7 +296,7 @@ static char *FindSymbolFile(void) **mf = system_maps; auto struct utsname utsname; - static char symfile[100]; + static char mysymfile[100]; auto FILE *sym_file = (FILE *) 0; @@ -309,19 +309,19 @@ static char *FindSymbolFile(void) for(mf = system_maps; *mf != (char *) 0 && file == (char *) 0; ++mf) { - snprintf(symfile, sizeof(symfile), "%s-%s", *mf, utsname.release); - dbgprintf("Trying %s.\n", symfile); - if ( (sym_file = fopen(symfile, "r")) != (FILE *) 0 ) { - if (CheckMapVersion(symfile) == 1) - file = symfile; + snprintf(mysymfile, sizeof(mysymfile), "%s-%s", *mf, utsname.release); + dbgprintf("Trying %s.\n", mysymfile); + if ( (sym_file = fopen(mysymfile, "r")) != (FILE *) 0 ) { + if (CheckMapVersion(mysymfile) == 1) + file = mysymfile; fclose(sym_file); } if (sym_file == (FILE *) 0 || file == (char *) 0) { - sprintf (symfile, "%s", *mf); - dbgprintf("Trying %s.\n", symfile); - if ( (sym_file = fopen(symfile, "r")) != (FILE *) 0 ) { - if (CheckMapVersion(symfile) == 1) - file = symfile; + sprintf (mysymfile, "%s", *mf); + dbgprintf("Trying %s.\n", mysymfile); + if ( (sym_file = fopen(mysymfile, "r")) != (FILE *) 0 ) { + if (CheckMapVersion(mysymfile) == 1) + file = mysymfile; fclose(sym_file); } } diff --git a/plugins/imklog/linux.c b/plugins/imklog/linux.c new file mode 100644 index 00000000..ce2ef4eb --- /dev/null +++ b/plugins/imklog/linux.c @@ -0,0 +1,533 @@ +/* klog for linux, based on the FreeBSD syslogd implementation. + * + * This contains OS-specific functionality to read the BSD + * kernel log. For a general overview, see head comment in + * imklog.c. + * + * This file heavily borrows from the klogd daemon provided by + * the sysklogd project. Many thanks for this piece of software. + * + * This file is part of rsyslog. + * + * Rsyslog 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, either version 3 of the License, or + * (at your option) any later version. + * + * Rsyslog 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 Rsyslog. If not, see . + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. +*/ +#include "config.h" +#include "rsyslog.h" +#include +#include +#include +#include +#include +#include +#include "syslogd.h" +#include "cfsysline.h" +#include "template.h" +#include "msg.h" +#include "module-template.h" +#include "imklog.h" + + +/* Includes. */ +#include +#include +#include +#include + +#if HAVE_TIME_H +# include +#endif + +#include +#include +#include "ksyms.h" + +#define __LIBRARY__ +#include + + +#if !defined(__GLIBC__) +# define __NR_ksyslog __NR_syslog +_syscall3(int,ksyslog,int, type, char *, buf, int, len); +#else +#include +#define ksyslog klogctl +#endif + + + +#ifndef _PATH_KLOG +#define _PATH_KLOG "/proc/kmsg" +#endif + +#define LOG_BUFFER_SIZE 4096 +#define LOG_LINE_LENGTH 1000 + +static int kmsg; +static char log_buffer[LOG_BUFFER_SIZE]; + +static enum LOGSRC {none, proc, kernel} logsrc; + + +/* Function prototypes. */ +extern int ksyslog(int type, char *buf, int len); + + +static void CloseLogSrc(void) +{ + /* Turn on logging of messages to console, but only if we had the -c + * option -- rgerhards, 2007-08-01 + */ + if (console_log_level != -1) + ksyslog(7, NULL, 0); + + /* Shutdown the log sources. */ + switch ( logsrc ) + { + case kernel: + ksyslog(0, 0, 0); + Syslog(LOG_INFO, "Kernel logging (ksyslog) stopped."); + break; + case proc: + close(kmsg); + Syslog(LOG_INFO, "Kernel logging (proc) stopped."); + break; + case none: + break; + } + + return; +} + + +static enum LOGSRC GetKernelLogSrc(void) +{ + auto struct stat sb; + + /* Set level of kernel console messaging.. */ + if ( (console_log_level != -1) && + (ksyslog(8, NULL, console_log_level) < 0) && + (errno == EINVAL) ) + { + /* + * An invalid arguement error probably indicates that + * a pre-0.14 kernel is being run. At this point we + * issue an error message and simply shut-off console + * logging completely. + */ + Syslog(LOG_WARNING, "Cannot set console log level - disabling " + "console output."); + } + + /* + * First do a stat to determine whether or not the proc based + * file system is available to get kernel messages from. + */ + if ( use_syscall || + ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) ) + { + /* Initialize kernel logging. */ + ksyslog(1, NULL, 0); + Syslog(LOG_INFO, "imklogd %s, log source = ksyslog " + "started.", VERSION); + return(kernel); + } + + if ( (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 ) + { + char sz[512]; + snprintf(sz, sizeof(sz), "imklog: Cannot open proc file system, %d - %s.\n", errno, strerror(errno)); + logmsgInternal(LOG_SYSLOG|LOG_ERR, sz, ADDDATE); + ksyslog(7, NULL, 0); /* TODO: check this, implement more */ + return(none); + } + + Syslog(LOG_INFO, "imklog %s, log source = %s started.", \ + VERSION, _PATH_KLOG); + return(proc); +} + + +/* Copy characters from ptr to line until a char in the delim + * string is encountered or until min( space, len ) chars have + * been copied. + * + * Returns the actual number of chars copied. + */ +static int copyin( char *line, int space, + const char *ptr, int len, + const char *delim ) +{ + auto int i; + auto int count; + + count = len < space ? len : space; + + for(i=0; i]", + * where "aaaaaa" is the address. These are replaced with + * "[symbolname+offset/size]" in the output line - symbolname, + * offset, and size come from the kernel symbol table. + * + * If a kernel symbol happens to fall at the end of a message close + * in length to LOG_LINE_LENGTH, the symbol will not be expanded. + * (This should never happen, since the kernel should never generate + * messages that long. + * + * To preserve the original addresses, lines containing kernel symbols + * are output twice. Once with the symbols converted and again with the + * original text. Just in case somebody wants to run their own Oops + * analysis on the syslog, e.g. ksymoops. + */ +static void LogLine(char *ptr, int len) +{ + enum parse_state_enum { + PARSING_TEXT, + PARSING_SYMSTART, /* at < */ + PARSING_SYMBOL, + PARSING_SYMEND /* at ] */ + }; + + static char line_buff[LOG_LINE_LENGTH]; + + static char *line =line_buff; + static enum parse_state_enum parse_state = PARSING_TEXT; + static int space = sizeof(line_buff)-1; + + static char *sym_start; /* points at the '<' of a symbol */ + + auto int delta = 0; /* number of chars copied */ + auto int symbols_expanded = 0; /* 1 if symbols were expanded */ + auto int skip_symbol_lookup = 0; /* skip symbol lookup on this pass */ + auto char *save_ptr = ptr; /* save start of input line */ + auto int save_len = len; /* save length at start of input line */ + + while( len > 0 ) + { + if( space == 0 ) /* line buffer is full */ + { + /* + ** Line too long. Start a new line. + */ + *line = 0; /* force null terminator */ + + dbgprintf("Line buffer full:\n"); + dbgprintf("\tLine: %s\n", line); + + Syslog( LOG_INFO, "%s", line_buff ); + line = line_buff; + space = sizeof(line_buff)-1; + parse_state = PARSING_TEXT; + symbols_expanded = 0; + skip_symbol_lookup = 0; + save_ptr = ptr; + save_len = len; + } + + switch( parse_state ) + { + case PARSING_TEXT: + delta = copyin( line, space, ptr, len, "\n[" ); + line += delta; + ptr += delta; + space -= delta; + len -= delta; + + if( space == 0 || len == 0 ) + { + break; /* full line_buff or end of input buffer */ + } + + if( *ptr == '\0' ) /* zero byte */ + { + ptr++; /* skip zero byte */ + space -= 1; + len -= 1; + + break; + } + + if( *ptr == '\n' ) /* newline */ + { + ptr++; /* skip newline */ + space -= 1; + len -= 1; + + *line = 0; /* force null terminator */ + Syslog( LOG_INFO, "%s", line_buff ); + line = line_buff; + space = sizeof(line_buff)-1; + if (symbols_twice) { + if (symbols_expanded) { + /* reprint this line without symbol lookup */ + symbols_expanded = 0; + skip_symbol_lookup = 1; + ptr = save_ptr; + len = save_len; + } + else + { + skip_symbol_lookup = 0; + save_ptr = ptr; + save_len = len; + } + } + break; + } + if( *ptr == '[' ) /* possible kernel symbol */ + { + *line++ = *ptr++; + space -= 1; + len -= 1; + if (!skip_symbol_lookup) + parse_state = PARSING_SYMSTART; /* at < */ + break; + } + /* Now that line_buff is no longer fed to *printf as format + * string, '%'s are no longer "dangerous". + */ + break; + + case PARSING_SYMSTART: + if( *ptr != '<' ) + { + parse_state = PARSING_TEXT; /* not a symbol */ + break; + } + + /* + ** Save this character for now. If this turns out to + ** be a valid symbol, this char will be replaced later. + ** If not, we'll just leave it there. + */ + + sym_start = line; /* this will point at the '<' */ + + *line++ = *ptr++; + space -= 1; + len -= 1; + parse_state = PARSING_SYMBOL; /* symbol... */ + break; + + case PARSING_SYMBOL: + delta = copyin( line, space, ptr, len, ">\n[" ); + line += delta; + ptr += delta; + space -= delta; + len -= delta; + if( space == 0 || len == 0 ) + { + break; /* full line_buff or end of input buffer */ + } + if( *ptr != '>' ) + { + parse_state = PARSING_TEXT; + break; + } + + *line++ = *ptr++; /* copy the '>' */ + space -= 1; + len -= 1; + + parse_state = PARSING_SYMEND; + + break; + + case PARSING_SYMEND: + if( *ptr != ']' ) + { + parse_state = PARSING_TEXT; /* not a symbol */ + break; + } + + /* + ** It's really a symbol! Replace address with the + ** symbol text. + */ + { + auto int sym_space; + + unsigned long value; + auto struct symbol sym; + auto char *symbol; + + *(line-1) = 0; /* null terminate the address string */ + value = strtoul(sym_start+1, (char **) 0, 16); + *(line-1) = '>'; /* put back delim */ + + if ( !symbol_lookup || (symbol = LookupSymbol(value, &sym)) == (char *)0 ) + { + parse_state = PARSING_TEXT; + break; + } + + /* + ** verify there is room in the line buffer + */ + sym_space = space + ( line - sym_start ); + if( (unsigned) sym_space < strlen(symbol) + 30 ) /*(30 should be overkill)*/ + { + parse_state = PARSING_TEXT; /* not enough space */ + break; + } + + delta = sprintf( sym_start, "%s+%d/%d]", + symbol, sym.offset, sym.size ); + + space = sym_space + delta; + line = sym_start + delta; + symbols_expanded = 1; + } + ptr++; + len--; + parse_state = PARSING_TEXT; + break; + + default: /* Can't get here! */ + parse_state = PARSING_TEXT; + + } + } + + return; +} + + +static void LogKernelLine(void) +{ + auto int rdcnt; + + /* + * Zero-fill the log buffer. This should cure a multitude of + * problems with klogd logging the tail end of the message buffer + * which will contain old messages. Then read the kernel log + * messages into this fresh buffer. + */ + memset(log_buffer, '\0', sizeof(log_buffer)); + if ( (rdcnt = ksyslog(2, log_buffer, sizeof(log_buffer)-1)) < 0 ) + { + char sz[512]; + if(errno == EINTR) + return; + snprintf(sz, sizeof(sz), "imklog: Error return from sys_sycall: %d - %s\n", errno, strerror(errno)); + logmsgInternal(LOG_SYSLOG|LOG_ERR, sz, ADDDATE); + } + else + LogLine(log_buffer, rdcnt); + return; +} + + +static void LogProcLine(void) +{ + auto int rdcnt; + + /* + * Zero-fill the log buffer. This should cure a multitude of + * problems with klogd logging the tail end of the message buffer + * which will contain old messages. Then read the kernel messages + * from the message pseudo-file into this fresh buffer. + */ + memset(log_buffer, '\0', sizeof(log_buffer)); + if ( (rdcnt = read(kmsg, log_buffer, sizeof(log_buffer)-1)) < 0 ) { + if ( errno == EINTR ) + return; + Syslog(LOG_ERR, "Cannot read proc file system: %d - %s.", errno, strerror(errno)); + } else { + LogLine(log_buffer, rdcnt); + } + + return; +} + + +/* to be called in the module's WillRun entry point + * rgerhards, 2008-04-09 + */ +rsRetVal klogLogKMsg(void) +{ + DEFiRet; + switch(logsrc) { + case kernel: + LogKernelLine(); + break; + case proc: + LogProcLine(); + break; + case none: + /* TODO: We need to handle this case here somewhat more intelligent + * This is now at least partly done - code should never reach this point + * as willRun() already checked for the "none" status -- rgerhards, 2007-12-17 + */ + pause(); + break; + } + RETiRet; +} + + +/* to be called in the module's WillRun entry point + * rgerhards, 2008-04-09 + */ +rsRetVal klogWillRun(void) +{ + DEFiRet; + /* Initialize this module. If that fails, we tell the engine we don't like to run */ + /* Determine where kernel logging information is to come from. */ + logsrc = GetKernelLogSrc(); + if(logsrc == none) { + iRet = RS_RET_NO_KERNEL_LOGSRC; + } else { + if (symbol_lookup) { + symbol_lookup = (InitKsyms(symfile) == 1); + symbol_lookup |= InitMsyms(); + if (symbol_lookup == 0) { + Syslog(LOG_WARNING, "cannot find any symbols, turning off symbol lookups\n"); + } + } + } + + RETiRet; +} + + +/* to be called in the module's AfterRun entry point + * rgerhards, 2008-04-09 + */ +rsRetVal klogAfterRun(void) +{ + DEFiRet; + /* cleanup here */ + if(logsrc != none) + CloseLogSrc(); + + DeinitKsyms(); + DeinitMsyms(); + + RETiRet; +} + +/* vi:set ai: + */ -- cgit From d15985bc4065b4c65f491e6a829379687b2f52f1 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 9 Apr 2008 12:36:09 +0200 Subject: pulled FreeBSD's klog functionality as a base --- plugins/imklog/bsd.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 plugins/imklog/bsd.c diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c new file mode 100644 index 00000000..25391980 --- /dev/null +++ b/plugins/imklog/bsd.c @@ -0,0 +1,151 @@ +/* klog for BSD, based on the FreeBSD syslogd implementation. + * + * This contains OS-specific functionality to read the BSD + * kernel log. For a general overview, see head comment in + * imklog.c. + * + * Copyright (C) 2008 by Rainer Gerhards for the modifications of + * the original FreeBSD sources. + * + * I would like to express my gratitude to those folks which + * layed an important foundation for rsyslog to build on. + * + * This file is part of rsyslog. + * + * Rsyslog 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, either version 3 of the License, or + * (at your option) any later version. + * + * Rsyslog 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 Rsyslog. If not, see . + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + * + * This file is based on earlier work included in the FreeBSD sources. We + * integrated it into the rsyslog project. The copyright below applies, and + * I also reproduce the original license under which we aquired the code: + * + * Copyright (c) 1983, 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * If you would like to use the code under the BSD license, you should + * aquire your own copy of BSD's syslogd, from which we have taken it. The + * code in this file is modified and may only be used under the terms of + * the GPLv3+ as specified above. + */ + + +/* open the kernel log -- rger */ +static void openKLog(void) +{ + if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) >= 0) + if (fcntl(fklog, F_SETFL, O_NONBLOCK) < 0) + fklog = -1; + if (fklog < 0) + dprintf("can't open %s (%d)\n", _PATH_KLOG, errno); +} + + +static int fklog = -1; /* /dev/klog */ +/* + * Read /dev/klog while data are available, split into lines. + */ +static void +readklog(void) +{ + char *p, *q, line[MAXLINE + 1]; + int len, i; + + len = 0; + for (;;) { + i = read(fklog, line + len, MAXLINE - 1 - len); + if (i > 0) { + line[i + len] = '\0'; + } else { + if (i < 0 && errno != EINTR && errno != EAGAIN) { + logerror("klog"); + fklog = -1; + } + break; + } + + for (p = line; (q = strchr(p, '\n')) != NULL; p = q + 1) { + *q = '\0'; + printsys(p); + } + len = strlen(p); + if (len >= MAXLINE - 1) { + printsys(p); + len = 0; + } + if (len > 0) + memmove(line, p, len + 1); + } + if (len > 0) + printsys(line); +} + +/* + * Take a raw input line from /dev/klog, format similar to syslog(). + */ +static void +printsys(char *msg) +{ + char *p, *q; + long n; + int flags, isprintf, pri; + + flags = ISKERNEL | SYNC_FILE | ADDDATE; /* fsync after write */ + p = msg; + pri = DEFSPRI; + isprintf = 1; + if (*p == '<') { + errno = 0; + n = strtol(p + 1, &q, 10); + if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) { + p = q + 1; + pri = n; + isprintf = 0; + } + } + /* + * Kernel printf's and LOG_CONSOLE messages have been displayed + * on the console already. + */ + if (isprintf || (pri & LOG_FACMASK) == LOG_CONSOLE) + flags |= IGN_CONS; + if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) + pri = DEFSPRI; + logmsg(pri, p, LocalHostName, flags); +} + -- cgit From c565a7e847aeb58ddcd1bdbd006597953a4dea31 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 9 Apr 2008 12:46:57 +0200 Subject: updated build system to detect correct klog driver --- configure.ac | 7 +++++-- plugins/imklog/Makefile.am | 11 ++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 586f03e3..d330ea82 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,8 @@ case "${host}" in *-*-linux*) ;; *-*-*darwin*|*-*-freebsd*|*-*-netbsd*|*-*-openbsd*) - AC_DEFINE([OS_BSD], [1], [Description]) + AC_DEFINE([OS_BSD], [1], [Indicator for a BSD OS]) + os_bsd = "yes" ;; esac @@ -202,7 +203,9 @@ AC_ARG_ENABLE(klog, esac], [enable_klog="yes"] ) -AM_CONDITIONAL(ENABLE_IMKLOGD, test x$enable_klog = xyes) +AM_CONDITIONAL(ENABLE_IMKLOGD, test x$enable_klog = xyes) +AM_CONDITIONAL(ENABLE_IMKLOG_BSD, test x$os_bsd = xyes) +AM_CONDITIONAL(ENABLE_IMKLOG_LINUX, test x$os_bsd = x) # # SYSLOG_UNIXAF diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am index 49bbbc70..946576fe 100644 --- a/plugins/imklog/Makefile.am +++ b/plugins/imklog/Makefile.am @@ -1,6 +1,15 @@ pkglib_LTLIBRARIES = imklog.la -imklog_la_SOURCES = imklog.c linux.c imklog.h module.h ksym.c ksyms.h ksym_mod.c +imklog_la_SOURCES = imklog.c imklog.h module.h ksym.c ksyms.h ksym_mod.c + +# select klog "driver" +if ENABLE_IMKLOG_LINUX +imklog_la_SOURCES += linux.c +endif +if ENABLE_IMKLOG_BSD +imklog_la_SOURCES += bsd.c +endif + imklog_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) imklog_la_LDFLAGS = -module -avoid-version imklog_la_LIBADD = -- cgit From b0a4df43e4434a1eeb3f23c2c5a4b0cdd2fbddda Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 9 Apr 2008 09:00:13 +0200 Subject: fixed build system for BSD It's a hack, but at least it works now - on BSD. Will check later if it is fine on Linux, too. Any better method of doing things is happily accepted ;) --- configure.ac | 4 +--- modules.c | 3 +++ plugins/imklog/Makefile.am | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index d330ea82..68158c46 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ case "${host}" in ;; *-*-*darwin*|*-*-freebsd*|*-*-netbsd*|*-*-openbsd*) AC_DEFINE([OS_BSD], [1], [Indicator for a BSD OS]) - os_bsd = "yes" + AM_CONDITIONAL(ENABLE_IMKLOG_BSD, test x = x) ;; esac @@ -204,8 +204,6 @@ AC_ARG_ENABLE(klog, [enable_klog="yes"] ) AM_CONDITIONAL(ENABLE_IMKLOGD, test x$enable_klog = xyes) -AM_CONDITIONAL(ENABLE_IMKLOG_BSD, test x$os_bsd = xyes) -AM_CONDITIONAL(ENABLE_IMKLOG_LINUX, test x$os_bsd = x) # # SYSLOG_UNIXAF diff --git a/modules.c b/modules.c index 623a2f10..7eb52575 100644 --- a/modules.c +++ b/modules.c @@ -39,6 +39,9 @@ #include #include #include +#ifdef OS_BSD +# include "libgen.h" +#endif #include /* TODO: replace this with the libtools equivalent! */ diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am index 946576fe..511cd9be 100644 --- a/plugins/imklog/Makefile.am +++ b/plugins/imklog/Makefile.am @@ -1,13 +1,13 @@ pkglib_LTLIBRARIES = imklog.la -imklog_la_SOURCES = imklog.c imklog.h module.h ksym.c ksyms.h ksym_mod.c +imklog_la_SOURCES = imklog.c imklog.h # select klog "driver" -if ENABLE_IMKLOG_LINUX -imklog_la_SOURCES += linux.c -endif if ENABLE_IMKLOG_BSD imklog_la_SOURCES += bsd.c +else +# we assume this now is Linux (yes, some help with the build system is appreciated ;)) +imklog_la_SOURCES += linux.c module.h ksym.c ksyms.h ksym_mod.c endif imklog_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) -- cgit From 0b447f310ac057ba59f0238f5bd663c993a823c2 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 9 Apr 2008 09:06:40 +0200 Subject: implemented klog driver for BSD --- ChangeLog | 1 + configure.ac | 2 +- plugins/imklog/bsd.c | 107 ++++++++++++++++++++++++++++-------------------- plugins/imklog/imklog.c | 7 ++-- plugins/imklog/imklog.h | 2 +- plugins/imklog/linux.c | 3 +- 6 files changed, 70 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index e9fadf12..23dfada7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ --------------------------------------------------------------------------- Version 3.17.1 (rgerhards), 2008-04-?? +- implemented klogd functionality for BSD --------------------------------------------------------------------------- Version 3.17.0 (rgerhards), 2008-04-08 - added native ability to send mail messages diff --git a/configure.ac b/configure.ac index 68158c46..5290edb4 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([rsyslog],[3.17.1],[rsyslog@lists.adiscon.com]) +AC_INIT([rsyslog],[3.17.1-bsd],[rsyslog@lists.adiscon.com]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([syslogd.c]) AC_CONFIG_HEADERS([config.h]) diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c index 25391980..c1595669 100644 --- a/plugins/imklog/bsd.c +++ b/plugins/imklog/bsd.c @@ -64,21 +64,47 @@ * the GPLv3+ as specified above. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include -/* open the kernel log -- rger */ -static void openKLog(void) +#include "rsyslog.h" +#include "imklog.h" + +/* globals */ +static int fklog = -1; /* /dev/klog */ + +#ifndef _PATH_KLOG +# define _PATH_KLOG "/dev/klog" +#endif + +/* open the kernel log - will be called inside the willRun() imklog + * entry point. -- rgerhards, 20080-04-09 + */ +rsRetVal +klogWillRun(void) { - if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) >= 0) - if (fcntl(fklog, F_SETFL, O_NONBLOCK) < 0) - fklog = -1; - if (fklog < 0) - dprintf("can't open %s (%d)\n", _PATH_KLOG, errno); + DEFiRet; + + fklog = open(_PATH_KLOG, O_RDONLY, 0); + if (fklog < 0) { + dbgprintf("can't open %s (%d)\n", _PATH_KLOG, errno); + iRet = RS_RET_ERR; // TODO: better error code + } + + RETiRet; } -static int fklog = -1; /* /dev/klog */ -/* - * Read /dev/klog while data are available, split into lines. +/* Read /dev/klog while data are available, split into lines. + * Contrary to standard BSD syslogd, we do a blocking read. We can + * afford this as imklog is running on its own threads. So if we have + * a single file, it really doesn't matter if we wait inside a 1-file + * select or the read() directly. */ static void readklog(void) @@ -88,12 +114,15 @@ readklog(void) len = 0; for (;;) { + dbgprintf("----------imklog waiting for kernel log line\n"); i = read(fklog, line + len, MAXLINE - 1 - len); if (i > 0) { line[i + len] = '\0'; } else { if (i < 0 && errno != EINTR && errno != EAGAIN) { - logerror("klog"); + Syslog(LOG_ERR, + "imklog error %d reading kernel log - shutting down imklog", + errno); fklog = -1; } break; @@ -101,51 +130,41 @@ readklog(void) for (p = line; (q = strchr(p, '\n')) != NULL; p = q + 1) { *q = '\0'; - printsys(p); + Syslog(LOG_INFO, "%s", p); } len = strlen(p); if (len >= MAXLINE - 1) { - printsys(p); + Syslog(LOG_INFO, "%s", p); len = 0; } if (len > 0) memmove(line, p, len + 1); } if (len > 0) - printsys(line); + Syslog(LOG_INFO, "%s", line); } -/* - * Take a raw input line from /dev/klog, format similar to syslog(). + +/* to be called in the module's AfterRun entry point + * rgerhards, 2008-04-09 */ -static void -printsys(char *msg) +rsRetVal klogAfterRun(void) { - char *p, *q; - long n; - int flags, isprintf, pri; - - flags = ISKERNEL | SYNC_FILE | ADDDATE; /* fsync after write */ - p = msg; - pri = DEFSPRI; - isprintf = 1; - if (*p == '<') { - errno = 0; - n = strtol(p + 1, &q, 10); - if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) { - p = q + 1; - pri = n; - isprintf = 0; - } - } - /* - * Kernel printf's and LOG_CONSOLE messages have been displayed - * on the console already. - */ - if (isprintf || (pri & LOG_FACMASK) == LOG_CONSOLE) - flags |= IGN_CONS; - if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) - pri = DEFSPRI; - logmsg(pri, p, LocalHostName, flags); + DEFiRet; + if(fklog != -1) + close(fklog); + RETiRet; } + + +/* to be called in the module's WillRun entry point, this is the main + * "message pull" mechanism. + * rgerhards, 2008-04-09 + */ +rsRetVal klogLogKMsg(void) +{ + DEFiRet; + readklog(); + RETiRet; +} diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index 972e93db..7f5c3cec 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -142,13 +142,12 @@ rsRetVal Syslog(int priority, char *fmt, ...) va_list ap; char *argl; - /* Output using syslog. */ + /* Output using syslog */ if(!strcmp(fmt, "%s")) { va_start(ap, fmt); argl = va_arg(ap, char *); - if (argl[0] == '<' && argl[1] && argl[2] == '>') { - switch ( argl[1] ) - { + if(argl[0] == '<' && argl[1] && argl[2] == '>') { + switch(argl[1]) { case '0': priority = LOG_EMERG; break; diff --git a/plugins/imklog/imklog.h b/plugins/imklog/imklog.h index 0ac25d6c..2fea879f 100644 --- a/plugins/imklog/imklog.h +++ b/plugins/imklog/imklog.h @@ -59,7 +59,7 @@ extern int InitMsyms(void); extern void DeinitMsyms(void); extern char * ExpandKadds(char *, char *); extern void SetParanoiaLevel(int); -extern void vsyslog(int pri, const char *fmt, va_list ap); +//TODO: remove? extern void vsyslog(int pri, const char *fmt, va_list ap); rsRetVal Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3))); #endif /* #ifndef IMKLOG_H_INCLUDED */ diff --git a/plugins/imklog/linux.c b/plugins/imklog/linux.c index ce2ef4eb..dc669b15 100644 --- a/plugins/imklog/linux.c +++ b/plugins/imklog/linux.c @@ -154,8 +154,7 @@ static enum LOGSRC GetKernelLogSrc(void) return(none); } - Syslog(LOG_INFO, "imklog %s, log source = %s started.", \ - VERSION, _PATH_KLOG); + Syslog(LOG_INFO, "imklog %s, log source = %s started.", VERSION, _PATH_KLOG); return(proc); } -- cgit From a6bc115d50519af6c171acacf9e41194a8dc82c5 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 9 Apr 2008 16:28:31 +0200 Subject: fixed klog platform selection on linux --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 5290edb4..12d6896a 100644 --- a/configure.ac +++ b/configure.ac @@ -21,6 +21,7 @@ AC_CANONICAL_HOST case "${host}" in *-*-linux*) + AM_CONDITIONAL(ENABLE_IMKLOG_BSD, test x = y) ;; *-*-*darwin*|*-*-freebsd*|*-*-netbsd*|*-*-openbsd*) AC_DEFINE([OS_BSD], [1], [Indicator for a BSD OS]) -- cgit From 79e5decff290722f3e8de742f82ef6fe8bb63eb4 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 9 Apr 2008 17:56:51 +0200 Subject: updated status after 3.14.2 release --- doc/status.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/status.html b/doc/status.html index 5b3b377a..98bb4f90 100644 --- a/doc/status.html +++ b/doc/status.html @@ -2,23 +2,23 @@ rsyslog status page

    rsyslog status page

    -

    This page reflects the status as of 2008-04-08.

    +

    This page reflects the status as of 2008-04-09.

    Current Releases

    development: 3.17.0 - change log - -download

    +download -

    beta: 3.15.0 - +
    beta: 3.15.0 - change log - download

    -

    v3 stable: 3.14.0 - change log - -download +

    v3 stable: 3.14.2 - change log - +download
    v2 stable: 2.0.4 - change log - download -
    v0 and v1 are depricated and no longer supported. If you absolutely do not like to +
    v0 and v1 are deprecated and no longer supported. If you absolutely do not like to upgrade, you may consider purchasing a commercial rsyslog support package. Just let us point out that it is really not a good idea to still run a v0 version. -- cgit From a7860f4dab1afcf94698bc2f52413e94eed64b52 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 10 Apr 2008 09:31:35 +0200 Subject: removed dependency on MAXHOSTNAMELEN as much as it made sense. GNU/Hurd does not define it (because it has no limit), and we have taken care for cases where it is undefined now. However, some very few places remain where IMHO it currently is not worth fixing the code. If it is not defined, we have used a generous value of 1K, which is above IETF RFC's on hostname length at all. The memory consumption is no issue, as there are only a handful of this buffers allocated *per run* -- that's also the main reason why we consider it not worth to be fixed any further. --- ChangeLog | 8 ++++++++ configure.ac | 16 ++++++++++++++++ net.c | 39 +++++++++++++++++++++++++++++++++++++++ net.h | 3 ++- omfwd.c | 12 ++++++++---- plugins/omgssapi/omgssapi.c | 17 ++++++++++------- plugins/omrelp/omrelp.c | 12 ++++++++---- syslogd.c | 20 ++++++++++++-------- syslogd.h | 2 +- 9 files changed, 104 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index b207a979..551b7278 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ --------------------------------------------------------------------------- Version 3.17.1 (rgerhards), 2008-04-?? +- removed dependency on MAXHOSTNAMELEN as much as it made sense. + GNU/Hurd does not define it (because it has no limit), and we have taken + care for cases where it is undefined now. However, some very few places + remain where IMHO it currently is not worth fixing the code. If it is + not defined, we have used a generous value of 1K, which is above IETF + RFC's on hostname length at all. The memory consumption is no issue, as + there are only a handful of this buffers allocated *per run* -- that's + also the main reason why we consider it not worth to be fixed any further. --------------------------------------------------------------------------- Version 3.17.0 (rgerhards), 2008-04-08 - added native ability to send mail messages diff --git a/configure.ac b/configure.ac index 1516ef71..4f3459c3 100644 --- a/configure.ac +++ b/configure.ac @@ -83,6 +83,22 @@ AC_FUNC_STRERROR_R AC_FUNC_VPRINTF AC_CHECK_FUNCS([flock basename alarm clock_gettime gethostbyname gethostname gettimeofday localtime_r memset mkdir regcomp select setid socket strcasecmp strchr strdup strerror strndup strnlen strrchr strstr strtol strtoul uname ttyname_r]) +# Check for MAXHOSTNAMELEN +AC_MSG_CHECKING(for MAXHOSTNAMELEN) +AC_TRY_COMPILE([ + #include + ], [ + return MAXHOSTNAMELEN; + ] + , + AC_MSG_RESULT(yes) + , + # note: we use 1024 here, which should be far more than needed by any system. If that's too low, we simply + # life with the need to change it. Most of the code doesn't need it anyways, but there are a few places + # where it actually is needed and it makes no sense to change them. + AC_DEFINE(MAXHOSTNAMELEN, 1024, [Define with a value if your does not define MAXHOSTNAMELEN]) + AC_MSG_RESULT(no; defined as 64) +) # Large file support AC_ARG_ENABLE(largefile, diff --git a/net.c b/net.c index ab669323..43e13eb3 100644 --- a/net.c +++ b/net.c @@ -852,6 +852,44 @@ finalize_it: } +/* get the name of the local host. A pointer to a character pointer is passed + * in, which on exit points to the local hostname. This buffer is dynamically + * allocated and must be free()ed by the caller. If the functions returns an + * error, the pointer is NULL. This function is based on GNU/Hurd's localhostname + * function. + * rgerhards, 20080-04-10 + */ +static rsRetVal +getLocalHostname(uchar **ppName) +{ + DEFiRet; + uchar *buf = NULL; + size_t buf_len = 0; + + assert(ppName != NULL); + + do { + if(buf == NULL) { + buf_len = 128; /* Initial guess */ + CHKmalloc(buf = malloc(buf_len)); + } else { + buf_len += buf_len; + CHKmalloc(buf = realloc (buf, buf_len)); + } + } while((gethostname((char*)buf, buf_len) == 0 && !memchr (buf, '\0', buf_len)) || errno == ENAMETOOLONG); + + *ppName = buf; + buf = NULL; + +finalize_it: + if(iRet != RS_RET_OK) { + if(buf != NULL) + free(buf); + } + RETiRet; +} + + /* closes the UDP listen sockets (if they exist) and frees * all dynamically assigned memory. */ @@ -1047,6 +1085,7 @@ CODESTARTobjQueryInterface(net) pIf->closeUDPListenSockets = closeUDPListenSockets; pIf->isAllowedSender = isAllowedSender; pIf->should_use_so_bsdcompat = should_use_so_bsdcompat; + pIf->getLocalHostname = getLocalHostname; finalize_it: ENDobjQueryInterface(net) diff --git a/net.h b/net.h index 2004dcfc..1b6dbcb6 100644 --- a/net.h +++ b/net.h @@ -97,6 +97,7 @@ BEGINinterface(net) /* name must also be changed in ENDinterface macro! */ int *(*create_udp_socket)(uchar *hostname, uchar *LogPort, int bIsServer); void (*closeUDPListenSockets)(int *finet); int (*isAllowedSender)(struct AllowedSenders *pAllowRoot, struct sockaddr *pFrom, const char *pszFromHost); + rsRetVal (*getLocalHostname)(uchar**); int (*should_use_so_bsdcompat)(void); /* data memebers - these should go away over time... TODO */ int *pACLAddHostnameOnFail; /* add hostname to acl when DNS resolving has failed */ @@ -105,7 +106,7 @@ BEGINinterface(net) /* name must also be changed in ENDinterface macro! */ struct AllowedSenders *pAllowedSenders_TCP; struct AllowedSenders *pAllowedSenders_GSS; ENDinterface(net) -#define netCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ +#define netCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObj(net); diff --git a/omfwd.c b/omfwd.c index 19d09379..67ef4b64 100644 --- a/omfwd.c +++ b/omfwd.c @@ -71,7 +71,7 @@ DEFobjCurrIf(net) DEFobjCurrIf(tcpclt) typedef struct _instanceData { - char f_hname[MAXHOSTNAMELEN+1]; + char *f_hname; short sock; /* file descriptor */ int *pSockArray; /* sockets to use for UDP */ enum { /* TODO: we shoud revisit these definitions */ @@ -145,6 +145,9 @@ CODESTARTfreeInstance tcpclt.Destruct(&pData->pTCPClt); } + if(pData->f_hname != NULL) + free(pData->f_hname); + ENDfreeInstance @@ -540,10 +543,11 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) /* TODO: make this if go away! */ if(*p == ';') { *p = '\0'; /* trick to obtain hostname (later)! */ - strcpy(pData->f_hname, (char*) q); + CHKmalloc(pData->f_hname = strdup((char*) q)); *p = ';'; - } else - strcpy(pData->f_hname, (char*) q); + } else { + CHKmalloc(pData->f_hname = strdup((char*) q)); + } /* process template */ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, diff --git a/plugins/omgssapi/omgssapi.c b/plugins/omgssapi/omgssapi.c index 9a7e8ab9..8c6a2006 100644 --- a/plugins/omgssapi/omgssapi.c +++ b/plugins/omgssapi/omgssapi.c @@ -4,7 +4,7 @@ * NOTE: read comments in module-template.h to understand how this file * works! * - * Copyright 2007 Rainer Gerhards and Adiscon GmbH. + * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * @@ -79,7 +79,7 @@ DEFobjCurrIf(gssutil) DEFobjCurrIf(tcpclt) typedef struct _instanceData { - char f_hname[MAXHOSTNAMELEN+1]; + char *f_hname; short sock; /* file descriptor */ enum { /* TODO: we shoud revisit these definitions */ eDestFORW, @@ -162,6 +162,9 @@ CODESTARTfreeInstance tcpclt.Destruct(&pData->pTCPClt); if(pData->sock >= 0) close(pData->sock); + + if(pData->f_hname != NULL) + free(pData->f_hname); ENDfreeInstance @@ -592,10 +595,11 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) /* TODO: make this if go away! */ if(*p == ';') { *p = '\0'; /* trick to obtain hostname (later)! */ - strcpy(pData->f_hname, (char*) q); + CHKmalloc(pData->f_hname = strdup((char*) q)); *p = ';'; - } else - strcpy(pData->f_hname, (char*) q); + } else { + CHKmalloc(pData->f_hname = strdup((char*) q)); + } /* process template */ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, @@ -701,6 +705,5 @@ CODEmodInit_QueryRegCFSLineHdlr ENDmodInit #endif /* #ifdef USE_GSSAPI */ -/* - * vi:set ai: +/* vi:set ai: */ diff --git a/plugins/omrelp/omrelp.c b/plugins/omrelp/omrelp.c index 39d25812..04571682 100644 --- a/plugins/omrelp/omrelp.c +++ b/plugins/omrelp/omrelp.c @@ -53,7 +53,7 @@ DEFobjCurrIf(errmsg) static relpEngine_t *pRelpEngine; /* our relp engine */ typedef struct _instanceData { - char f_hname[MAXHOSTNAMELEN+1]; + char *f_hname; int compressionLevel; /* 0 - no compression, else level for zlib */ char *port; int bInitialConnect; /* is this the initial connection request of our module? (0-no, 1-yes) */ @@ -98,6 +98,9 @@ CODESTARTfreeInstance if(pData->pRelpClt != NULL) relpEngineCltDestruct(pRelpEngine, &pData->pRelpClt); + if(pData->f_hname != NULL) + free(pData->f_hname); + ENDfreeInstance @@ -284,10 +287,11 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) /* TODO: make this if go away! */ if(*p == ';') { *p = '\0'; /* trick to obtain hostname (later)! */ - strcpy(pData->f_hname, (char*) q); + CHKmalloc(pData->f_hname = strdup((char*) q)); *p = ';'; - } else - strcpy(pData->f_hname, (char*) q); + } else { + CHKmalloc(pData->f_hname = strdup((char*) q)); + } /* process template */ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_ForwardFormat")); diff --git a/syslogd.c b/syslogd.c index 59fbbc29..65f93c78 100644 --- a/syslogd.c +++ b/syslogd.c @@ -306,7 +306,7 @@ uchar *pszWorkDir = NULL;/* name of rsyslog's spool directory (without trailing uchar *glblModPath = NULL; /* module load path - only used during initial init, only settable via -M command line option */ /* end global config file state variables */ -char LocalHostName[MAXHOSTNAMELEN+1];/* our hostname - read-only after startup */ +uchar *LocalHostName;/* our hostname - read-only after startup */ char *LocalDomain; /* our local domain name - read-only after startup */ int MarkInterval = 20 * 60; /* interval between marks in seconds - read-only after startup */ int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both), set via cmdline */ @@ -897,8 +897,8 @@ logmsgInternal(int pri, char *msg, int flags) CHKiRet(msgConstruct(&pMsg)); MsgSetUxTradMsg(pMsg, msg); MsgSetRawMsg(pMsg, msg); - MsgSetHOSTNAME(pMsg, LocalHostName); - MsgSetRcvFrom(pMsg, LocalHostName); + MsgSetHOSTNAME(pMsg, (char*)LocalHostName); + MsgSetRcvFrom(pMsg, (char*)LocalHostName); MsgSetTAG(pMsg, "rsyslogd:"); pMsg->iFacility = LOG_FAC(pri); pMsg->iSeverity = LOG_PRI(pri); @@ -1863,6 +1863,8 @@ freeAllDynMemForTermination(void) free(pszMainMsgQFName); if(pModDir != NULL) free(pModDir); + if(LocalHostName != NULL) + free(LocalHostName); } @@ -3164,8 +3166,8 @@ int realMain(int argc, char **argv) /* get our host and domain names - we need to do this early as we may emit * error log messages, which need the correct hostname. -- rgerhards, 2008-04-04 */ - gethostname(LocalHostName, sizeof(LocalHostName)); - if((p = strchr(LocalHostName, '.'))) { + net.getLocalHostname(&LocalHostName); + if((p = strchr((char*)LocalHostName, '.'))) { *p++ = '\0'; LocalDomain = p; } else { @@ -3184,17 +3186,19 @@ int realMain(int argc, char **argv) /* TODO: gethostbyname() is not thread-safe, but replacing it is * not urgent as we do not run on multiple threads here. rgerhards, 2007-09-25 */ - hent = gethostbyname(LocalHostName); + hent = gethostbyname((char*)LocalHostName); if(hent) { - snprintf(LocalHostName, sizeof(LocalHostName), "%s", hent->h_name); + free(LocalHostName); + CHKmalloc(LocalHostName = (uchar*)strdup(hent->h_name)); - if ( (p = strchr(LocalHostName, '.')) ) + if((p = strchr((char*)LocalHostName, '.'))) { *p++ = '\0'; LocalDomain = p; } } } +dbgprintf("LocalHostname: '%s'\n", LocalHostName); /* Convert to lower case to recognize the correct domain laterly */ for (p = (char *)LocalDomain ; *p ; p++) diff --git a/syslogd.h b/syslogd.h index cbb4bb05..46de8d28 100644 --- a/syslogd.h +++ b/syslogd.h @@ -134,7 +134,7 @@ rsRetVal logmsgInternal(int pri, char *msg, int flags); void logmsg(msg_t *pMsg, int flags); rsRetVal submitMsg(msg_t *pMsg); extern int glblHadMemShortage; /* indicates if we had memory shortage some time during the run */ -extern char LocalHostName[]; +extern uchar *LocalHostName; extern int family; extern int NoHops; extern int send_to_all; -- cgit From cac432e7cb65ea4694a183823267cbcd67e97ad6 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Thu, 10 Apr 2008 09:52:37 +0200 Subject: Add missing include bsd.c uses strchr, strlen and memmove, so include string.h Signed-off-by: Rainer Gerhards --- plugins/imklog/bsd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c index c1595669..9989d5fb 100644 --- a/plugins/imklog/bsd.c +++ b/plugins/imklog/bsd.c @@ -71,6 +71,7 @@ #include #include #include +#include #include "rsyslog.h" #include "imklog.h" -- cgit From afb66b5c6dcf1287999d4610361242c65404b858 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Thu, 10 Apr 2008 09:53:45 +0200 Subject: Rename ENABLE_IMKLOGD to ENABLE_IMKLOG Signed-off-by: Rainer Gerhards --- Makefile.am | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 6aea7600..eb7a32d7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -182,7 +182,7 @@ SUBDIRS = . doc SUBDIRS += plugins/immark plugins/imuxsock plugins/imtcp plugins/imudp plugins/omtesting -if ENABLE_IMKLOGD +if ENABLE_IMKLOG SUBDIRS += plugins/imklog endif diff --git a/configure.ac b/configure.ac index 12d6896a..5d7c46e6 100644 --- a/configure.ac +++ b/configure.ac @@ -204,7 +204,7 @@ AC_ARG_ENABLE(klog, esac], [enable_klog="yes"] ) -AM_CONDITIONAL(ENABLE_IMKLOGD, test x$enable_klog = xyes) +AM_CONDITIONAL(ENABLE_IMKLOG, test x$enable_klog = xyes) # # SYSLOG_UNIXAF -- cgit From f786054cdc128f69fcf5deea191c01de77bd1342 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Thu, 10 Apr 2008 09:56:19 +0200 Subject: Add ENABLE_IMKLOG_LINUX Signed-off-by: Rainer Gerhards --- configure.ac | 8 +++++--- plugins/imklog/Makefile.am | 5 +++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 5d7c46e6..2ca1e075 100644 --- a/configure.ac +++ b/configure.ac @@ -21,11 +21,11 @@ AC_CANONICAL_HOST case "${host}" in *-*-linux*) - AM_CONDITIONAL(ENABLE_IMKLOG_BSD, test x = y) + os_type="linux" ;; *-*-*darwin*|*-*-freebsd*|*-*-netbsd*|*-*-openbsd*) AC_DEFINE([OS_BSD], [1], [Indicator for a BSD OS]) - AM_CONDITIONAL(ENABLE_IMKLOG_BSD, test x = x) + os_type="bsd" ;; esac @@ -205,6 +205,8 @@ AC_ARG_ENABLE(klog, [enable_klog="yes"] ) AM_CONDITIONAL(ENABLE_IMKLOG, test x$enable_klog = xyes) +AM_CONDITIONAL(ENABLE_IMKLOG_BSD, test x$os_type = xbsd) +AM_CONDITIONAL(ENABLE_IMKLOG_LINUX, test x$os_type = xlinux) # # SYSLOG_UNIXAF @@ -621,7 +623,7 @@ echo "****************************************************" echo "rsyslog will be compiled with the following settings:" echo echo "Multithreading support enabled: $enable_pthreads" -echo "Klog functionality enabled: $enable_klog" +echo "Klog functionality enabled: $enable_klog ($os_type)" echo "Regular expressions support enabled: $enable_regexp" echo "Zlib compression support enabled: $enable_zlib" echo "MySql support enabled: $enable_mysql" diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am index 511cd9be..f4cd771b 100644 --- a/plugins/imklog/Makefile.am +++ b/plugins/imklog/Makefile.am @@ -5,8 +5,9 @@ imklog_la_SOURCES = imklog.c imklog.h # select klog "driver" if ENABLE_IMKLOG_BSD imklog_la_SOURCES += bsd.c -else -# we assume this now is Linux (yes, some help with the build system is appreciated ;)) +endif + +if ENABLE_IMKLOG_LINUX imklog_la_SOURCES += linux.c module.h ksym.c ksyms.h ksym_mod.c endif -- cgit From d041cdd05007593624b83df85c4fe0357d330c10 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 10 Apr 2008 12:16:05 +0200 Subject: removed trailing whitespace --- plugins/imklog/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am index f4cd771b..246b3306 100644 --- a/plugins/imklog/Makefile.am +++ b/plugins/imklog/Makefile.am @@ -7,7 +7,7 @@ if ENABLE_IMKLOG_BSD imklog_la_SOURCES += bsd.c endif -if ENABLE_IMKLOG_LINUX +if ENABLE_IMKLOG_LINUX imklog_la_SOURCES += linux.c module.h ksym.c ksyms.h ksym_mod.c endif -- cgit From 890f782323849b2ae01cd705312d54a4a0e348fe Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 11 Apr 2008 17:33:13 +0200 Subject: some cleanup --- expr.c | 2 +- obj-types.h | 2 +- obj.c | 3 +-- obj.h | 4 ++-- outchannel.c | 51 +++++++++++++++++++++++------------------ parse.c | 55 +++++++++++++++++++-------------------------- plugins/imfile/imfile.c | 2 +- plugins/imklog/imklog.c | 2 +- plugins/imuxsock/imuxsock.c | 2 +- syslogd.c | 1 - template.c | 48 +++++++++++++++++---------------------- template.h | 2 +- 12 files changed, 81 insertions(+), 93 deletions(-) diff --git a/expr.c b/expr.c index 5c11b756..6164ef1f 100644 --- a/expr.c +++ b/expr.c @@ -335,7 +335,7 @@ ENDobjConstruct(expr) /* ConstructionFinalizer * rgerhards, 2008-01-09 */ -rsRetVal exprConstructFinalize(expr_t *pThis) +rsRetVal exprConstructFinalize(expr_t __attribute__((unused)) *pThis) { DEFiRet; diff --git a/obj-types.h b/obj-types.h index afbe1a8b..4cd45153 100644 --- a/obj-types.h +++ b/obj-types.h @@ -210,7 +210,7 @@ rsRetVal objName##ClassExit(void) \ #define CODESTARTObjClassExit(objName) #define ENDObjClassExit(objName) \ - iRet = obj.UnregisterObj((uchar*)#objName, pObjInfoOBJ); \ + iRet = obj.UnregisterObj((uchar*)#objName); \ RETiRet; \ } diff --git a/obj.c b/obj.c index 3485803d..1a99aeaa 100644 --- a/obj.c +++ b/obj.c @@ -1089,14 +1089,13 @@ finalize_it: * rgerhards, 2008-03-10 */ static rsRetVal -UnregisterObj(uchar *pszObjName, objInfo_t *pInfo) +UnregisterObj(uchar *pszObjName) { DEFiRet; int bFound; int i; assert(pszObjName != NULL); - assert(pInfo != NULL); bFound = 0; i = 0; diff --git a/obj.h b/obj.h index 87c6c91d..29ad2ae4 100644 --- a/obj.h +++ b/obj.h @@ -104,13 +104,13 @@ BEGINinterface(obj) /* name must also be changed in ENDinterface macro! */ rsRetVal (*SerializeProp)(strm_t *pStrm, uchar *pszPropName, propType_t propType, void *pUsr); rsRetVal (*EndSerialize)(strm_t *pStrm); rsRetVal (*RegisterObj)(uchar *pszObjName, objInfo_t *pInfo); - rsRetVal (*UnregisterObj)(uchar *pszObjName, objInfo_t *pInfo); + rsRetVal (*UnregisterObj)(uchar *pszObjName); rsRetVal (*Deserialize)(void *ppObj, uchar *pszTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t*,void*), void *pUsr); rsRetVal (*DeserializePropBag)(obj_t *pObj, strm_t *pStrm); rsRetVal (*SetName)(obj_t *pThis, uchar *pszName); uchar * (*GetName)(obj_t *pThis); ENDinterface(obj) -#define objCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ +#define objCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */ /* prototypes */ diff --git a/outchannel.c b/outchannel.c index 394371f0..d013ea08 100644 --- a/outchannel.c +++ b/outchannel.c @@ -91,12 +91,12 @@ static void skip_Comma(char **pp) /* helper to ochAddLine. Parses a comma-delimited field * The field is delimited by SP or comma. Leading whitespace * is "eaten" and does not become part of the field content. - * returns: 0 - ok, 1 - failure */ -static int get_Field(uchar **pp, uchar **pField) +static rsRetVal get_Field(uchar **pp, uchar **pField) { + DEFiRet; register uchar *p; - cstr_t *pStrB; + cstr_t *pStrB = NULL; assert(pp != NULL); assert(*pp != NULL); @@ -105,21 +105,25 @@ static int get_Field(uchar **pp, uchar **pField) skip_Comma((char**)pp); p = *pp; - if(rsCStrConstruct(&pStrB) != RS_RET_OK) - return 1; + CHKiRet(rsCStrConstruct(&pStrB)); rsCStrSetAllocIncrement(pStrB, 32); /* copy the field */ while(*p && *p != ' ' && *p != ',') { - rsCStrAppendChar(pStrB, *p++); + CHKiRet(rsCStrAppendChar(pStrB, *p++)); } *pp = p; - rsCStrFinish(pStrB); - if(rsCStrConvSzStrAndDestruct(pStrB, pField, 0) != RS_RET_OK) - return 1; + CHKiRet(rsCStrFinish(pStrB)); + CHKiRet(rsCStrConvSzStrAndDestruct(pStrB, pField, 0)); - return 0; +finalize_it: + if(iRet != RS_RET_OK) { + if(pStrB != NULL) + rsCStrDestruct(&pStrB); + } + + RETiRet; } @@ -156,12 +160,12 @@ static int get_off_t(uchar **pp, off_t *pOff_t) * current position to the end of line and returns it * to the caller. Leading white space is removed, but * not trailing. - * returns: 0 - ok, 1 - failure */ -static inline int get_restOfLine(uchar **pp, uchar **pBuf) +static inline rsRetVal get_restOfLine(uchar **pp, uchar **pBuf) { + DEFiRet; register uchar *p; - cstr_t *pStrB; + cstr_t *pStrB = NULL; assert(pp != NULL); assert(*pp != NULL); @@ -170,21 +174,25 @@ static inline int get_restOfLine(uchar **pp, uchar **pBuf) skip_Comma((char**)pp); p = *pp; - if(rsCStrConstruct(&pStrB) != RS_RET_OK) - return 1; + CHKiRet(rsCStrConstruct(&pStrB)); rsCStrSetAllocIncrement(pStrB, 32); /* copy the field */ while(*p) { - rsCStrAppendChar(pStrB, *p++); + CHKiRet(rsCStrAppendChar(pStrB, *p++)); } *pp = p; - rsCStrFinish(pStrB); - if(rsCStrConvSzStrAndDestruct(pStrB, pBuf, 0) != RS_RET_OK) - return 1; + CHKiRet(rsCStrFinish(pStrB)); + CHKiRet(rsCStrConvSzStrAndDestruct(pStrB, pBuf, 0)); - return 0; +finalize_it: + if(iRet != RS_RET_OK) { + if(pStrB != NULL) + rsCStrDestruct(&pStrB); + } + + RETiRet; } @@ -291,6 +299,5 @@ void ochPrintList(void) pOch = pOch->pNext; /* done, go next */ } } -/* - * vi:set ai: +/* vi:set ai: */ diff --git a/parse.c b/parse.c index 5239b540..171e5355 100644 --- a/parse.c +++ b/parse.c @@ -244,7 +244,7 @@ rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrim { DEFiRet; register unsigned char *pC; - cstr_t *pCStr; + cstr_t *pCStr = NULL; rsCHECKVALIDOBJECT(pThis, OIDrsPars); @@ -255,12 +255,8 @@ rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrim pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; - while(pThis->iCurrPos < rsCStrLen(pThis->pCStr) - && *pC != cDelim) { - if((iRet = rsCStrAppendChar(pCStr, bConvLower ? tolower(*pC) : *pC)) != RS_RET_OK) { - rsCStrDestruct(&pCStr); - FINALIZE; - } + while(pThis->iCurrPos < rsCStrLen(pThis->pCStr) && *pC != cDelim) { + CHKiRet(rsCStrAppendChar(pCStr, bConvLower ? tolower(*pC) : *pC)); ++pThis->iCurrPos; ++pC; } @@ -272,22 +268,21 @@ rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrim /* We got the string, now take it and see if we need to * remove anything at its end. */ - if((iRet = rsCStrFinish(pCStr)) != RS_RET_OK) { - rsCStrDestruct (&pCStr); - FINALIZE; - } + CHKiRet(rsCStrFinish(pCStr)); if(bTrimTrailing) { - if((iRet = rsCStrTrimTrailingWhiteSpace(pCStr)) - != RS_RET_OK) { - rsCStrDestruct (&pCStr); - FINALIZE; - } + CHKiRet(rsCStrTrimTrailingWhiteSpace(pCStr)); } /* done! */ *ppCStr = pCStr; + finalize_it: + if(iRet != RS_RET_OK) { + if(pCStr != NULL) + rsCStrDestruct(&pCStr); + } + RETiRet; } @@ -309,13 +304,12 @@ finalize_it: rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr) { register unsigned char *pC; - cstr_t *pCStr; + cstr_t *pCStr = NULL; DEFiRet; rsCHECKVALIDOBJECT(pThis, OIDrsPars); - if((iRet = parsSkipAfterChar(pThis, '"')) != RS_RET_OK) - FINALIZE; + CHKiRet(parsSkipAfterChar(pThis, '"')); pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; /* OK, we most probably can obtain a value... */ @@ -332,16 +326,10 @@ rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr) * to the output buffer (but do not rely on this, * we might later introduce other things, like \007! */ - if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) { - rsCStrDestruct(&pCStr); - FINALIZE; - } + CHKiRet(rsCStrAppendChar(pCStr, *pC)); } } else { /* regular character */ - if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) { - rsCStrDestruct (&pCStr); - FINALIZE; - } + CHKiRet(rsCStrAppendChar(pCStr, *pC)); } ++pThis->iCurrPos; ++pC; @@ -351,19 +339,22 @@ rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr) ++pThis->iCurrPos; /* 'eat' trailing quote */ } else { /* error - improperly quoted string! */ - rsCStrDestruct (&pCStr); + rsCStrDestruct(&pCStr); ABORT_FINALIZE(RS_RET_MISSING_TRAIL_QUOTE); } /* We got the string, let's finish it... */ - if((iRet = rsCStrFinish(pCStr)) != RS_RET_OK) { - rsCStrDestruct (&pCStr); - FINALIZE; - } + CHKiRet(rsCStrFinish(pCStr)); /* done! */ *ppCStr = pCStr; + finalize_it: + if(iRet != RS_RET_OK) { + if(pCStr != NULL) + rsCStrDestruct(&pCStr); + } + RETiRet; } diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 162cab9f..61b50d06 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -95,7 +95,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); - MsgSetHOSTNAME(pMsg, LocalHostName); + MsgSetHOSTNAME(pMsg, (char*)LocalHostName); MsgSetTAG(pMsg, (char*)pInfo->pszTag); pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index bfea8c6f..65a05229 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -133,7 +133,7 @@ static rsRetVal writeSyslogV(int iPRI, const char *szFmt, va_list va) /* here we must create our message object and supply it to the message queue */ - CHKiRet(parseAndSubmitMessage(LocalHostName, msgBuf, strlen(msgBuf), MSG_DONT_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY)); + CHKiRet(parseAndSubmitMessage((char*)LocalHostName, msgBuf, strlen(msgBuf), MSG_DONT_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY)); finalize_it: RETiRet; diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c index 3cdcbf0a..f8798039 100644 --- a/plugins/imuxsock/imuxsock.c +++ b/plugins/imuxsock/imuxsock.c @@ -181,7 +181,7 @@ static rsRetVal readSocket(int fd, int bParseHost, int flags) iRcvd = recv(fd, line, MAXLINE - 1, 0); dbgprintf("Message from UNIX socket: #%d\n", fd); if (iRcvd > 0) { - parseAndSubmitMessage(LocalHostName, line, iRcvd, bParseHost, flags, eFLOWCTL_LIGHT_DELAY); + parseAndSubmitMessage((char*)LocalHostName, line, iRcvd, bParseHost, flags, eFLOWCTL_LIGHT_DELAY); } else if (iRcvd < 0 && errno != EINTR) { char errStr[1024]; rs_strerror_r(errno, errStr, sizeof(errStr)); diff --git a/syslogd.c b/syslogd.c index 65f93c78..aee945f5 100644 --- a/syslogd.c +++ b/syslogd.c @@ -3198,7 +3198,6 @@ int realMain(int argc, char **argv) } } } -dbgprintf("LocalHostname: '%s'\n", LocalHostName); /* Convert to lower case to recognize the correct domain laterly */ for (p = (char *)LocalDomain ; *p ; p++) diff --git a/template.c b/template.c index 0eea4572..844c5aec 100644 --- a/template.c +++ b/template.c @@ -188,11 +188,13 @@ static void doSQLEmergencyEscape(register uchar *p, int escapeMode) * new parameter escapeMode is 0 - standard sql, 1 - "smart" engines * 2005-09-22 rgerhards */ -void doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode) +rsRetVal +doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode) { + DEFiRet; uchar *p; int iLen; - cstr_t *pStrB; + cstr_t *pStrB = NULL; uchar *pszGenerated; assert(pp != NULL); @@ -210,44 +212,25 @@ void doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int es /* when we get out of the loop, we are either at the * string terminator or the first \'. */ if(*p == '\0') - return; /* nothing to do in this case! */ + FINALIZE; /* nothing to do in this case! */ p = *pp; iLen = *pLen; - if(rsCStrConstruct(&pStrB) != RS_RET_OK) { - /* oops - no mem ... Do emergency... */ - doSQLEmergencyEscape(p, escapeMode); - return; - } + CHKiRet(rsCStrConstruct(&pStrB)); while(*p) { if(*p == '\'') { - if(rsCStrAppendChar(pStrB, (escapeMode == 0) ? '\'' : '\\') != RS_RET_OK) { - doSQLEmergencyEscape(*pp, escapeMode); - rsCStrDestruct(&pStrB); - return; - } + CHKiRet(rsCStrAppendChar(pStrB, (escapeMode == 0) ? '\'' : '\\')); iLen++; /* reflect the extra character */ } else if((escapeMode == 1) && (*p == '\\')) { - if(rsCStrAppendChar(pStrB, '\\') != RS_RET_OK) { - doSQLEmergencyEscape(*pp, escapeMode); - rsCStrDestruct(&pStrB); - return; - } + CHKiRet(rsCStrAppendChar(pStrB, '\\')); iLen++; /* reflect the extra character */ } - if(rsCStrAppendChar(pStrB, *p) != RS_RET_OK) { - doSQLEmergencyEscape(*pp, escapeMode); - rsCStrDestruct(&pStrB); - return; - } + CHKiRet(rsCStrAppendChar(pStrB, *p)); ++p; } - rsCStrFinish(pStrB); - if(rsCStrConvSzStrAndDestruct(pStrB, &pszGenerated, 0) != RS_RET_OK) { - doSQLEmergencyEscape(*pp, escapeMode); - return; - } + CHKiRet(rsCStrFinish(pStrB)); + CHKiRet(rsCStrConvSzStrAndDestruct(pStrB, &pszGenerated, 0)); if(*pbMustBeFreed) free(*pp); /* discard previous value */ @@ -255,6 +238,15 @@ void doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int es *pp = pszGenerated; *pLen = iLen; *pbMustBeFreed = 1; + +finalize_it: + if(iRet != RS_RET_OK) { + doSQLEmergencyEscape(*pp, escapeMode); + if(pStrB != NULL) + rsCStrDestruct(&pStrB); + } + + RETiRet; } diff --git a/template.h b/template.h index eb9f3045..e63e544b 100644 --- a/template.h +++ b/template.h @@ -109,7 +109,7 @@ void tplLastStaticInit(struct template *tpl); * rgerhards, 2007-08-06 */ rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar** ppSz); -void doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode); +rsRetVal doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode); #endif /* #ifndef TEMPLATE_H_INCLUDED */ /* vim:set ai: -- cgit From 63d4de81ec485425231676d53813ff465249e800 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 11 Apr 2008 20:21:02 +0200 Subject: enhanced legacy syslog parser to handle slightly malformed messages Those with a space in front of the timestamp - at least HP procurve is known to do that and I won't outrule that others also do it. The change looks quite unintrusive and so we added it to the parser. --- ChangeLog | 4 ++++ syslogd.c | 13 ++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 551b7278..7f181ce2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,10 @@ Version 3.17.1 (rgerhards), 2008-04-?? RFC's on hostname length at all. The memory consumption is no issue, as there are only a handful of this buffers allocated *per run* -- that's also the main reason why we consider it not worth to be fixed any further. +- enhanced legacy syslog parser to handle slightly malformed messages + (with a space in front of the timestamp) - at least HP procurve is + known to do that and I won't outrule that others also do it. The + change looks quite unintrusive and so we added it to the parser. --------------------------------------------------------------------------- Version 3.17.0 (rgerhards), 2008-04-08 - added native ability to send mail messages diff --git a/syslogd.c b/syslogd.c index aee945f5..9bd852bb 100644 --- a/syslogd.c +++ b/syslogd.c @@ -1390,11 +1390,18 @@ static int parseLegacySyslogMsg(msg_t *pMsg, int flags) /* Check to see if msg contains a timestamp. We stary trying with a * high-precision one... */ - if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse) == TRUE) + if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse) == TRUE) { /* we are done - parse pointer is moved by ParseTIMESTAMP3339 */; - else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), p2parse) == TRUE) + } else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), p2parse) == TRUE) { p2parse += 16; - else { + } else if(*p2parse == ' ') { /* try to see if it is slighly malformed - HP procurve seems to do that sometimes */ + if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), p2parse+1) == TRUE) { + /* indeed, we got it! */ + p2parse += 17; + } else { + flags |= ADDDATE; + } + } else { flags |= ADDDATE; } -- cgit From 9030b96c7b0b1b44915ff13384bc2ccbeeaf0626 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Sat, 12 Apr 2008 16:55:04 +0200 Subject: implemented high precision timestamps for the kernel log. Thanks to Michael Biebl for pointing out that the kernel log did not have them. --- ChangeLog | 2 ++ plugins/imfile/imfile.c | 3 ++ plugins/imklog/imklog.c | 77 ++++++++++++++++++++++--------------------------- 3 files changed, 40 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index 23dfada7..2a4d7d50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ --------------------------------------------------------------------------- Version 3.17.1 (rgerhards), 2008-04-?? - implemented klogd functionality for BSD +- implemented high precision timestamp for the kernel log. Thanks to + Michale Biebl for pointing out that the kernel log did not have them. --------------------------------------------------------------------------- Version 3.17.0 (rgerhards), 2008-04-08 - added native ability to send mail messages diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 162cab9f..54669641 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -379,6 +379,9 @@ ENDafterRun */ BEGINmodExit CODESTARTmodExit + /* release objects we used */ + objRelease(datetime, CORE_COMPONENT); + objRelease(errmsg, CORE_COMPONENT); ENDmodExit diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index 7f5c3cec..754d655d 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -45,17 +45,23 @@ #include #include #include +#include +#include + #include "syslogd.h" #include "cfsysline.h" #include "template.h" +#include "obj.h" #include "msg.h" #include "module-template.h" +#include "datetime.h" #include "imklog.h" MODULE_TYPE_INPUT /* Module static data */ DEF_IMOD_STATIC_DATA +DEFobjCurrIf(datetime) /* configuration settings TODO: move to instance data? */ int dbgPrintSymbols = 0; /* this one is extern so the helpers can access it! */ @@ -82,58 +88,39 @@ int console_log_level = -1; # include #endif -#include -#include - #define __LIBRARY__ #include - -/* Write a message to the message queue. - * returns -1 if it fails, something else otherwise +/* enqueue the the kernel message into the message queue. + * The provided msg string is not freed - thus must be done + * by the caller. + * rgerhards, 2008-04-12 */ -static rsRetVal writeSyslogV(int iPRI, const char *szFmt, va_list va) +static rsRetVal enqMsg(uchar *msg, int iFacility, int iSeverity) { DEFiRet; - int iChars; - int iLen; - time_t tNow; - char msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */ - - assert(szFmt != NULL); - - /* build the message */ - time(&tNow); - /* we can use sprintf safely below, because we know the size of the constants. - * By doing so, we save some cpu cycles and code complexity (for unnecessary - * error checking). - */ - iLen = sprintf(msgBuf, "<%d>%.15s kernel: ", iPRI, ctime(&tNow) + 4); - - iChars = vsnprintf(msgBuf + iLen, sizeof(msgBuf) / sizeof(char) - iLen, szFmt, va); - - /* here we must create our message object and supply it to the message queue - */ - CHKiRet(parseAndSubmitMessage(LocalHostName, msgBuf, strlen(msgBuf), MSG_DONT_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY)); + msg_t *pMsg; + + assert(msg != NULL); + + CHKiRet(msgConstruct(&pMsg)); + MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); + MsgSetUxTradMsg(pMsg, (char*)msg); + MsgSetRawMsg(pMsg, (char*)msg); + MsgSetMSG(pMsg, (char*)msg); + MsgSetHOSTNAME(pMsg, LocalHostName); + MsgSetTAG(pMsg, "kernel:"); + pMsg->iFacility = LOG_FAC(iFacility); + pMsg->iSeverity = LOG_PRI(iSeverity); + pMsg->bParseHOSTNAME = 0; + datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */ + CHKiRet(submitMsg(pMsg)); finalize_it: RETiRet; } -/* And now the same with variable arguments */ -static int writeSyslog(int iPRI, const char *szFmt, ...) -{ - int iRet; - va_list va; - - assert(szFmt != NULL); - va_start(va, szFmt); - iRet = writeSyslogV(iPRI, szFmt, va); - va_end(va); - - return(iRet); -} rsRetVal Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3))); rsRetVal Syslog(int priority, char *fmt, ...) @@ -141,6 +128,7 @@ rsRetVal Syslog(int priority, char *fmt, ...) DEFiRet; va_list ap; char *argl; + char msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */ /* Output using syslog */ if(!strcmp(fmt, "%s")) { @@ -175,12 +163,13 @@ rsRetVal Syslog(int priority, char *fmt, ...) } argl += 3; } - iRet = writeSyslog(priority, fmt, argl); + iRet = enqMsg((uchar*)argl, LOG_KERN, priority); va_end(ap); } else { va_start(ap, fmt); - iRet = writeSyslogV(priority, fmt, ap); + vsnprintf(msgBuf, sizeof(msgBuf) / sizeof(char), fmt, ap); va_end(ap); + iRet = enqMsg((uchar*)msgBuf, LOG_KERN, priority); } RETiRet; @@ -218,6 +207,8 @@ ENDafterRun BEGINmodExit CODESTARTmodExit + /* release objects we used */ + objRelease(datetime, CORE_COMPONENT); ENDmodExit @@ -240,6 +231,8 @@ BEGINmodInit() CODESTARTmodInit *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr + CHKiRet(objUse(datetime, CORE_COMPONENT)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"debugprintkernelsymbols", 0, eCmdHdlrBinary, NULL, &dbgPrintSymbols, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbollookup", 0, eCmdHdlrBinary, NULL, &symbol_lookup, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbolstwice", 0, eCmdHdlrBinary, NULL, &symbols_twice, STD_LOADABLE_MODULE_ID)); -- cgit From af26ba581643463ec59a7b9fd69f5ffbed347d0a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 14 Apr 2008 08:20:49 +0200 Subject: fixed typo --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 2a4d7d50..5c75d60c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ --------------------------------------------------------------------------- Version 3.17.1 (rgerhards), 2008-04-?? - implemented klogd functionality for BSD -- implemented high precision timestamp for the kernel log. Thanks to +- implemented high precision timestamps for the kernel log. Thanks to Michale Biebl for pointing out that the kernel log did not have them. --------------------------------------------------------------------------- Version 3.17.0 (rgerhards), 2008-04-08 -- cgit From 3669057997e7665735626fd29a40bd10e160c88f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 14 Apr 2008 12:10:00 +0200 Subject: provided ability to discard non-kernel messages present in the kernel msg buffer This obviously happens on BSD (<118> markers seen). We now have the ability to allow or prevent it, with the default being not permitted. Should not at all affect other drivers, but it is implemented on a common code basis, not on the driver layer. --- plugins/imklog/bsd.c | 2 +- plugins/imklog/imklog.c | 95 ++++++++++++++++++++++++++++++------------------- rsyslog.h | 1 + 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c index 9989d5fb..c12103f3 100644 --- a/plugins/imklog/bsd.c +++ b/plugins/imklog/bsd.c @@ -84,7 +84,7 @@ static int fklog = -1; /* /dev/klog */ #endif /* open the kernel log - will be called inside the willRun() imklog - * entry point. -- rgerhards, 20080-04-09 + * entry point. -- rgerhards, 2008-04-09 */ rsRetVal klogWillRun(void) diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index 754d655d..a5832658 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "syslogd.h" #include "cfsysline.h" @@ -68,6 +69,7 @@ int dbgPrintSymbols = 0; /* this one is extern so the helpers can access it! */ int symbols_twice = 0; int use_syscall = 0; int symbol_lookup = 1; +int bPermitNonKernel = 0; /* permit logging of messages not having LOG_KERN facility */ /* TODO: configuration for the following directives must be implemented. It * was not done yet because we either do not yet have a config handler for * that type or I thought it was acceptable to push it to a later stage when @@ -121,57 +123,77 @@ finalize_it: RETiRet; } +/* parse the PRI from a kernel message. At least BSD seems to have + * non-kernel messages inside the kernel log... + * Expected format: "". piPri is only valid if the function + * successfully returns. If there was a proper pri ppSz is advanced to the + * position right after ">". + * rgerhards, 2008-04-14 + */ +static rsRetVal +parsePRI(uchar **ppSz, int *piPri) +{ + DEFiRet; + int i; + uchar *pSz; + + assert(ppSz != NULL); + pSz = *ppSz; + assert(pSz != NULL); + assert(piPri != NULL); + + if(*pSz != '<' || !isdigit(*(pSz+1))) + ABORT_FINALIZE(RS_RET_INVALID_PRI); + + ++pSz; + i = 0; + while(isdigit(*pSz)) { + i = i * 10 + *pSz - '0'; + } + + if(*pSz != '>') + ABORT_FINALIZE(RS_RET_INVALID_PRI); + + /* OK, we have a valid PRI */ + *piPri = i; + +finalize_it: + RETiRet; +} + rsRetVal Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3))); rsRetVal Syslog(int priority, char *fmt, ...) { DEFiRet; va_list ap; - char *argl; - char msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */ + uchar msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */ + uchar *pLogMsg; + rsRetVal localRet; /* Output using syslog */ if(!strcmp(fmt, "%s")) { va_start(ap, fmt); - argl = va_arg(ap, char *); - if(argl[0] == '<' && argl[1] && argl[2] == '>') { - switch(argl[1]) { - case '0': - priority = LOG_EMERG; - break; - case '1': - priority = LOG_ALERT; - break; - case '2': - priority = LOG_CRIT; - break; - case '3': - priority = LOG_ERR; - break; - case '4': - priority = LOG_WARNING; - break; - case '5': - priority = LOG_NOTICE; - break; - case '6': - priority = LOG_INFO; - break; - case '7': - default: - priority = LOG_DEBUG; - } - argl += 3; - } - iRet = enqMsg((uchar*)argl, LOG_KERN, priority); + pLogMsg = va_arg(ap, uchar *); + localRet = parsePRI(&pLogMsg, &priority); + if(localRet != RS_RET_INVALID_PRI && localRet != RS_RET_OK) + FINALIZE; + /* if we don't get the pri, we use whatever we were supplied */ va_end(ap); - } else { + } else { /* TODO: I think we can remove this once we pull in the errmsg object -- rgerhards, 2008-04-14 */ va_start(ap, fmt); - vsnprintf(msgBuf, sizeof(msgBuf) / sizeof(char), fmt, ap); + vsnprintf((char*)msgBuf, sizeof(msgBuf) / sizeof(char), fmt, ap); + pLogMsg = msgBuf; va_end(ap); - iRet = enqMsg((uchar*)msgBuf, LOG_KERN, priority); } + /* ignore non-kernel messages if not permitted */ + if(bPermitNonKernel == 0 && LOG_FAC(priority) != LOG_KERN) + FINALIZE; /* silently ignore */ + + iRet = enqMsg((uchar*)pLogMsg, LOG_FAC(priority), LOG_PRI(priority)); + +finalize_it: RETiRet; } @@ -237,6 +259,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbollookup", 0, eCmdHdlrBinary, NULL, &symbol_lookup, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbolstwice", 0, eCmdHdlrBinary, NULL, &symbols_twice, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogusesyscallinterface", 0, eCmdHdlrBinary, NULL, &use_syscall, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogpermitnonkernelfacility", 0, eCmdHdlrBinary, NULL, &bPermitNonKernel, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit /* vim:set ai: diff --git a/rsyslog.h b/rsyslog.h index 93b5c149..2249e040 100644 --- a/rsyslog.h +++ b/rsyslog.h @@ -171,6 +171,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_SMTP_ERROR = -2070, /**< error during SMTP transation */ RS_RET_MAIL_NO_TO = -2071, /**< recipient for mail destination is missing */ RS_RET_MAIL_NO_FROM = -2072, /**< sender for mail destination is missing */ + RS_RET_INVALID_PRI = -2073, /**< PRI value is invalid */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ -- cgit From f8dff16a4a1d606f41d738f7381649282c74ca25 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 14 Apr 2008 14:44:32 +0200 Subject: cleanup of imklog + addtl. config directives - implemented $KLogInternalMsgFacility config directive - implemented $KLogPermitNonKernelFacility config directive - modified internal interfaces --- ChangeLog | 4 +++ plugins/imklog/bsd.c | 18 ++++++++--- plugins/imklog/imklog.c | 76 +++++++++++++++++++++++------------------------ plugins/imklog/imklog.h | 7 +++-- plugins/imklog/ksym.c | 32 ++++++++++---------- plugins/imklog/ksym_mod.c | 12 ++++---- plugins/imklog/linux.c | 46 +++++++++++++++++----------- 7 files changed, 112 insertions(+), 83 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5c75d60c..ff1cbd3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,10 @@ Version 3.17.1 (rgerhards), 2008-04-?? - implemented klogd functionality for BSD - implemented high precision timestamps for the kernel log. Thanks to Michale Biebl for pointing out that the kernel log did not have them. +- provided ability to discard non-kernel messages if they are present + in the kernel log (seems to happen on BSD) +- implemented $KLogInternalMsgFacility config directive +- implemented $KLogPermitNonKernelFacility config directive --------------------------------------------------------------------------- Version 3.17.0 (rgerhards), 2008-04-08 - added native ability to send mail messages diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c index c12103f3..c5b79541 100644 --- a/plugins/imklog/bsd.c +++ b/plugins/imklog/bsd.c @@ -121,7 +121,7 @@ readklog(void) line[i + len] = '\0'; } else { if (i < 0 && errno != EINTR && errno != EAGAIN) { - Syslog(LOG_ERR, + imklogLogIntMsg(LOG_ERR, "imklog error %d reading kernel log - shutting down imklog", errno); fklog = -1; @@ -131,18 +131,18 @@ readklog(void) for (p = line; (q = strchr(p, '\n')) != NULL; p = q + 1) { *q = '\0'; - Syslog(LOG_INFO, "%s", p); + Syslog(LOG_INFO, p); } len = strlen(p); if (len >= MAXLINE - 1) { - Syslog(LOG_INFO, "%s", p); + Syslog(LOG_INFO, p); len = 0; } if (len > 0) memmove(line, p, len + 1); } if (len > 0) - Syslog(LOG_INFO, "%s", line); + Syslog(LOG_INFO, line); } @@ -169,3 +169,13 @@ rsRetVal klogLogKMsg(void) readklog(); RETiRet; } + + +/* provide the (system-specific) default facility for internal messages + * rgerhards, 2008-04-14 + */ +int +klogFacilIntMsg(void) +{ + return LOG_SYSLOG; +} diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index a5832658..e6bd2326 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -39,19 +39,14 @@ */ #include "config.h" #include "rsyslog.h" -#include #include #include -#include #include -#include #include -#include #include #include "syslogd.h" #include "cfsysline.h" -#include "template.h" #include "obj.h" #include "msg.h" #include "module-template.h" @@ -70,6 +65,7 @@ int symbols_twice = 0; int use_syscall = 0; int symbol_lookup = 1; int bPermitNonKernel = 0; /* permit logging of messages not having LOG_KERN facility */ +int iFacilIntMsg; /* the facility to use for internal messages (set by driver) */ /* TODO: configuration for the following directives must be implemented. It * was not done yet because we either do not yet have a config handler for * that type or I thought it was acceptable to push it to a later stage when @@ -80,31 +76,19 @@ char *symfile = NULL; int console_log_level = -1; -/* Includes. */ -#include -#include -#include -#include - -#if HAVE_TIME_H -# include -#endif - -#define __LIBRARY__ -#include - - /* enqueue the the kernel message into the message queue. * The provided msg string is not freed - thus must be done * by the caller. * rgerhards, 2008-04-12 */ -static rsRetVal enqMsg(uchar *msg, int iFacility, int iSeverity) +static rsRetVal +enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity) { DEFiRet; msg_t *pMsg; assert(msg != NULL); + assert(pszTag != NULL); CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); @@ -112,7 +96,7 @@ static rsRetVal enqMsg(uchar *msg, int iFacility, int iSeverity) MsgSetRawMsg(pMsg, (char*)msg); MsgSetMSG(pMsg, (char*)msg); MsgSetHOSTNAME(pMsg, LocalHostName); - MsgSetTAG(pMsg, "kernel:"); + MsgSetTAG(pMsg, (char*)pszTag); pMsg->iFacility = LOG_FAC(iFacility); pMsg->iSeverity = LOG_PRI(iSeverity); pMsg->bParseHOSTNAME = 0; @@ -162,36 +146,47 @@ finalize_it: } -rsRetVal Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3))); -rsRetVal Syslog(int priority, char *fmt, ...) +/* log an imklog-internal message + * rgerhards, 2008-04-14 + */ +rsRetVal imklogLogIntMsg(int priority, char *fmt, ...) { DEFiRet; va_list ap; uchar msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */ uchar *pLogMsg; + + va_start(ap, fmt); + vsnprintf((char*)msgBuf, sizeof(msgBuf) / sizeof(char), fmt, ap); + pLogMsg = msgBuf; + va_end(ap); + + iRet = enqMsg((uchar*)pLogMsg, (uchar*) ((iFacilIntMsg == LOG_KERN) ? "kernel:" : "imklog:"), + iFacilIntMsg, LOG_PRI(priority)); + + RETiRet; +} + + +/* log a kernel message + * rgerhards, 2008-04-14 + */ +rsRetVal Syslog(int priority, uchar *pMsg) +{ + DEFiRet; rsRetVal localRet; /* Output using syslog */ - if(!strcmp(fmt, "%s")) { - va_start(ap, fmt); - pLogMsg = va_arg(ap, uchar *); - localRet = parsePRI(&pLogMsg, &priority); - if(localRet != RS_RET_INVALID_PRI && localRet != RS_RET_OK) - FINALIZE; - /* if we don't get the pri, we use whatever we were supplied */ - va_end(ap); - } else { /* TODO: I think we can remove this once we pull in the errmsg object -- rgerhards, 2008-04-14 */ - va_start(ap, fmt); - vsnprintf((char*)msgBuf, sizeof(msgBuf) / sizeof(char), fmt, ap); - pLogMsg = msgBuf; - va_end(ap); - } + localRet = parsePRI(&pMsg, &priority); + if(localRet != RS_RET_INVALID_PRI && localRet != RS_RET_OK) + FINALIZE; + /* if we don't get the pri, we use whatever we were supplied */ /* ignore non-kernel messages if not permitted */ if(bPermitNonKernel == 0 && LOG_FAC(priority) != LOG_KERN) FINALIZE; /* silently ignore */ - iRet = enqMsg((uchar*)pLogMsg, LOG_FAC(priority), LOG_PRI(priority)); + iRet = enqMsg((uchar*)pMsg, (uchar*) "kernel:", LOG_FAC(priority), LOG_PRI(priority)); finalize_it: RETiRet; @@ -246,6 +241,8 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a use_syscall = 0; symfile = NULL; symbol_lookup = 1; + bPermitNonKernel = 0; + iFacilIntMsg = klogFacilIntMsg(); return RS_RET_OK; } @@ -255,11 +252,14 @@ CODESTARTmodInit CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(datetime, CORE_COMPONENT)); + iFacilIntMsg = klogFacilIntMsg(); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"debugprintkernelsymbols", 0, eCmdHdlrBinary, NULL, &dbgPrintSymbols, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbollookup", 0, eCmdHdlrBinary, NULL, &symbol_lookup, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbolstwice", 0, eCmdHdlrBinary, NULL, &symbols_twice, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogusesyscallinterface", 0, eCmdHdlrBinary, NULL, &use_syscall, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogpermitnonkernelfacility", 0, eCmdHdlrBinary, NULL, &bPermitNonKernel, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"kloginternalmsgfacility", 0, eCmdHdlrFacility, NULL, &iFacilIntMsg, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit /* vim:set ai: diff --git a/plugins/imklog/imklog.h b/plugins/imklog/imklog.h index 2fea879f..a37ecc9e 100644 --- a/plugins/imklog/imklog.h +++ b/plugins/imklog/imklog.h @@ -39,6 +39,7 @@ rsRetVal klogLogKMsg(void); rsRetVal klogWillRun(void); rsRetVal klogAfterRun(void); +int klogFacilIntMsg(void); /* the following data members may be accessed by the "drivers" * I admit this is not the cleanest way to doing things, but I honestly @@ -52,6 +53,10 @@ extern char *symfile; extern int console_log_level; extern int dbgPrintSymbols; +/* the functions below may be called by the drivers */ +rsRetVal imklogLogIntMsg(int priority, char *fmt, ...) __attribute__((format(printf,2, 3))); +rsRetVal Syslog(int priority, uchar *msg); + /* prototypes */ extern int InitKsyms(char *); extern void DeinitKsyms(void); @@ -59,8 +64,6 @@ extern int InitMsyms(void); extern void DeinitMsyms(void); extern char * ExpandKadds(char *, char *); extern void SetParanoiaLevel(int); -//TODO: remove? extern void vsyslog(int pri, const char *fmt, va_list ap); -rsRetVal Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3))); #endif /* #ifndef IMKLOG_H_INCLUDED */ /* vi:set ai: diff --git a/plugins/imklog/ksym.c b/plugins/imklog/ksym.c index 716ad926..1c2af124 100644 --- a/plugins/imklog/ksym.c +++ b/plugins/imklog/ksym.c @@ -185,18 +185,18 @@ extern int InitKsyms(char *mapfile) if ( mapfile != (char *) 0 ) { if ( (sym_file = fopen(mapfile, "r")) == (FILE *) 0 ) { - Syslog(LOG_WARNING, "Cannot open map file: %s.", mapfile); + imklogLogIntMsg(LOG_WARNING, "Cannot open map file: %s.", mapfile); return(0); } } else { if ( (mapfile = FindSymbolFile()) == (char *) 0 ) { - Syslog(LOG_WARNING, "Cannot find map file."); + imklogLogIntMsg(LOG_WARNING, "Cannot find map file."); dbgprintf("Cannot find map file.\n"); return(0); } if ( (sym_file = fopen(mapfile, "r")) == (FILE *) 0 ) { - Syslog(LOG_WARNING, "Cannot open map file."); + imklogLogIntMsg(LOG_WARNING, "Cannot open map file."); dbgprintf("Cannot open map file.\n"); return(0); } @@ -213,7 +213,7 @@ extern int InitKsyms(char *mapfile) */ while ( !feof(sym_file) ) { if ( fscanf(sym_file, "%lx %c %s\n", &address, &type, sym) != 3 ) { - Syslog(LOG_ERR, "Error in symbol table input (#1)."); + imklogLogIntMsg(LOG_ERR, "Error in symbol table input (#1)."); fclose(sym_file); return(0); } @@ -221,7 +221,7 @@ extern int InitKsyms(char *mapfile) dbgprintf("Address: %lx, Type: %c, Symbol: %s\n", address, type, sym); if ( AddSymbol(address, sym) == 0 ) { - Syslog(LOG_ERR, "Error adding symbol - %s.", sym); + imklogLogIntMsg(LOG_ERR, "Error adding symbol - %s.", sym); fclose(sym_file); return(0); } @@ -231,19 +231,19 @@ extern int InitKsyms(char *mapfile) } - Syslog(LOG_INFO, "Loaded %d symbols from %s.", num_syms, mapfile); + imklogLogIntMsg(LOG_INFO, "Loaded %d symbols from %s.", num_syms, mapfile); switch(version) { case -1: - Syslog(LOG_WARNING, "Symbols do not match kernel version."); + imklogLogIntMsg(LOG_WARNING, "Symbols do not match kernel version."); num_syms = 0; break; case 0: - Syslog(LOG_WARNING, "Cannot verify that symbols match kernel version."); + imklogLogIntMsg(LOG_WARNING, "Cannot verify that symbols match kernel version."); break; case 1: - Syslog(LOG_INFO, "Symbols match kernel version %s.", vstring); + imklogLogIntMsg(LOG_INFO, "Symbols match kernel version %s.", vstring); break; } @@ -301,7 +301,7 @@ static char *FindSymbolFile(void) auto FILE *sym_file = (FILE *) 0; if ( uname(&utsname) < 0 ) { - Syslog(LOG_ERR, "Cannot get kernel version information."); + imklogLogIntMsg(LOG_ERR, "Cannot get kernel version information."); return(0); } @@ -410,13 +410,13 @@ static int CheckVersion(char *version) * version level. */ if ( uname(&utsname) < 0 ) { - Syslog(LOG_ERR, "Cannot get kernel version information."); + imklogLogIntMsg(LOG_ERR, "Cannot get kernel version information."); return(0); } dbgprintf("Comparing kernel %s with symbol table %s.\n", utsname.release, vstring); if ( sscanf (utsname.release, "%d.%d.%d", &major, &minor, &patch) < 3 ) { - Syslog(LOG_ERR, "Kernel send bogus release string `%s'.", utsname.release); + imklogLogIntMsg(LOG_ERR, "Kernel send bogus release string `%s'.", utsname.release); return(0); } @@ -470,12 +470,12 @@ static int CheckMapVersion(char *fname) * now need to search this file and look for version * information. */ - Syslog(LOG_INFO, "Inspecting %s", fname); + imklogLogIntMsg(LOG_INFO, "Inspecting %s", fname); version = 0; while ( !feof(sym_file) && (version == 0) ) { if ( fscanf(sym_file, "%lx %c %s\n", &address, &type, sym) != 3 ) { - Syslog(LOG_ERR, "Error in symbol table input (#2)."); + imklogLogIntMsg(LOG_ERR, "Error in symbol table input (#2)."); fclose(sym_file); return(0); } @@ -487,7 +487,7 @@ static int CheckMapVersion(char *fname) switch ( version ) { case -1: - Syslog(LOG_ERR, "Symbol table has incorrect version number.\n"); + imklogLogIntMsg(LOG_ERR, "Symbol table has incorrect version number.\n"); break; case 0: dbgprintf("No version information found.\n"); @@ -684,7 +684,7 @@ extern char *ExpandKadds(char *line, char *el) */ if ( i_am_paranoid && (strstr(line, "Oops:") != (char *) 0) && !InitMsyms() ) - Syslog(LOG_WARNING, "Cannot load kernel module symbols.\n"); + imklogLogIntMsg(LOG_WARNING, "Cannot load kernel module symbols.\n"); /* diff --git a/plugins/imklog/ksym_mod.c b/plugins/imklog/ksym_mod.c index 11535a5f..bef810b4 100644 --- a/plugins/imklog/ksym_mod.c +++ b/plugins/imklog/ksym_mod.c @@ -158,10 +158,10 @@ extern int InitMsyms(void) if ( ksyms == NULL ) { if ( errno == ENOENT ) - Syslog(LOG_INFO, "No module symbols loaded - " + imklogLogIntMsg(LOG_INFO, "No module symbols loaded - " "kernel modules not enabled.\n"); else - Syslog(LOG_ERR, "Error loading kernel symbols " \ + imklogLogIntMsg(LOG_ERR, "Error loading kernel symbols " \ "- %s\n", strerror(errno)); fclose(ksyms); return(0); @@ -201,9 +201,9 @@ extern int InitMsyms(void) } if ( rtn == 0 ) - Syslog(LOG_INFO, "No module symbols loaded."); + imklogLogIntMsg(LOG_INFO, "No module symbols loaded."); else - Syslog(LOG_INFO, "Loaded %d %s from %d module%s", rtn, \ + imklogLogIntMsg(LOG_INFO, "Loaded %d %s from %d module%s", rtn, \ (rtn == 1) ? "symbol" : "symbols", \ num_modules, (num_modules == 1) ? "." : "s."); @@ -296,7 +296,7 @@ struct Module *AddModule(module) if ( sym_array_modules == NULL ) { - Syslog(LOG_WARNING, "Cannot allocate Module array.\n"); + imklogLogIntMsg(LOG_WARNING, "Cannot allocate Module array.\n"); return NULL; } mp = sym_array_modules; @@ -308,7 +308,7 @@ struct Module *AddModule(module) if ( mp == NULL ) { - Syslog(LOG_WARNING, "Cannot allocate Module array.\n"); + imklogLogIntMsg(LOG_WARNING, "Cannot allocate Module array.\n"); return NULL; } diff --git a/plugins/imklog/linux.c b/plugins/imklog/linux.c index dc669b15..a742a456 100644 --- a/plugins/imklog/linux.c +++ b/plugins/imklog/linux.c @@ -98,11 +98,11 @@ static void CloseLogSrc(void) { case kernel: ksyslog(0, 0, 0); - Syslog(LOG_INFO, "Kernel logging (ksyslog) stopped."); + imklogLogIntMsg(LOG_INFO, "Kernel logging (ksyslog) stopped."); break; case proc: close(kmsg); - Syslog(LOG_INFO, "Kernel logging (proc) stopped."); + imklogLogIntMsg(LOG_INFO, "Kernel logging (proc) stopped."); break; case none: break; @@ -127,7 +127,7 @@ static enum LOGSRC GetKernelLogSrc(void) * issue an error message and simply shut-off console * logging completely. */ - Syslog(LOG_WARNING, "Cannot set console log level - disabling " + imklogLogIntMsg(LOG_WARNING, "Cannot set console log level - disabling " "console output."); } @@ -140,7 +140,7 @@ static enum LOGSRC GetKernelLogSrc(void) { /* Initialize kernel logging. */ ksyslog(1, NULL, 0); - Syslog(LOG_INFO, "imklogd %s, log source = ksyslog " + imklogLogIntMsg(LOG_INFO, "imklogd %s, log source = ksyslog " "started.", VERSION); return(kernel); } @@ -154,7 +154,7 @@ static enum LOGSRC GetKernelLogSrc(void) return(none); } - Syslog(LOG_INFO, "imklog %s, log source = %s started.", VERSION, _PATH_KLOG); + imklogLogIntMsg(LOG_INFO, "imklog %s, log source = %s started.", VERSION, _PATH_KLOG); return(proc); } @@ -165,7 +165,7 @@ static enum LOGSRC GetKernelLogSrc(void) * * Returns the actual number of chars copied. */ -static int copyin( char *line, int space, +static int copyin( uchar *line, int space, const char *ptr, int len, const char *delim ) { @@ -209,13 +209,13 @@ static void LogLine(char *ptr, int len) PARSING_SYMEND /* at ] */ }; - static char line_buff[LOG_LINE_LENGTH]; + static uchar line_buff[LOG_LINE_LENGTH]; - static char *line =line_buff; + static uchar *line =line_buff; static enum parse_state_enum parse_state = PARSING_TEXT; - static int space = sizeof(line_buff)-1; + static int space = sizeof(line_buff)-1; - static char *sym_start; /* points at the '<' of a symbol */ + static uchar *sym_start; /* points at the '<' of a symbol */ auto int delta = 0; /* number of chars copied */ auto int symbols_expanded = 0; /* 1 if symbols were expanded */ @@ -235,7 +235,7 @@ static void LogLine(char *ptr, int len) dbgprintf("Line buffer full:\n"); dbgprintf("\tLine: %s\n", line); - Syslog( LOG_INFO, "%s", line_buff ); + Syslog(LOG_INFO, line_buff); line = line_buff; space = sizeof(line_buff)-1; parse_state = PARSING_TEXT; @@ -248,7 +248,7 @@ static void LogLine(char *ptr, int len) switch( parse_state ) { case PARSING_TEXT: - delta = copyin( line, space, ptr, len, "\n[" ); + delta = copyin(line, space, ptr, len, "\n[" ); line += delta; ptr += delta; space -= delta; @@ -275,7 +275,7 @@ static void LogLine(char *ptr, int len) len -= 1; *line = 0; /* force null terminator */ - Syslog( LOG_INFO, "%s", line_buff ); + Syslog(LOG_INFO, line_buff); line = line_buff; space = sizeof(line_buff)-1; if (symbols_twice) { @@ -373,7 +373,7 @@ static void LogLine(char *ptr, int len) auto char *symbol; *(line-1) = 0; /* null terminate the address string */ - value = strtoul(sym_start+1, (char **) 0, 16); + value = strtoul((char*)(sym_start+1), (char **) 0, 16); *(line-1) = '>'; /* put back delim */ if ( !symbol_lookup || (symbol = LookupSymbol(value, &sym)) == (char *)0 ) @@ -392,7 +392,8 @@ static void LogLine(char *ptr, int len) break; } - delta = sprintf( sym_start, "%s+%d/%d]", + // TODO: sprintf!!!! + delta = sprintf( (char*) sym_start, "%s+%d/%d]", symbol, sym.offset, sym.size ); space = sym_space + delta; @@ -453,7 +454,7 @@ static void LogProcLine(void) if ( (rdcnt = read(kmsg, log_buffer, sizeof(log_buffer)-1)) < 0 ) { if ( errno == EINTR ) return; - Syslog(LOG_ERR, "Cannot read proc file system: %d - %s.", errno, strerror(errno)); + imklogLogIntMsg(LOG_ERR, "Cannot read proc file system: %d - %s.", errno, strerror(errno)); } else { LogLine(log_buffer, rdcnt); } @@ -503,7 +504,7 @@ rsRetVal klogWillRun(void) symbol_lookup = (InitKsyms(symfile) == 1); symbol_lookup |= InitMsyms(); if (symbol_lookup == 0) { - Syslog(LOG_WARNING, "cannot find any symbols, turning off symbol lookups\n"); + imklogLogIntMsg(LOG_WARNING, "cannot find any symbols, turning off symbol lookups\n"); } } } @@ -528,5 +529,16 @@ rsRetVal klogAfterRun(void) RETiRet; } + +/* provide the (system-specific) default facility for internal messages + * rgerhards, 2008-04-14 + */ +int +klogFacilIntMsg(void) +{ + return LOG_KERN; +} + + /* vi:set ai: */ -- cgit From 318be337dd7f3ce1c1a308712e308f5b56ce9027 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 14 Apr 2008 13:35:19 +0200 Subject: fix compiler warning on char/uchar --- plugins/imklog/bsd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c index c5b79541..39b644c0 100644 --- a/plugins/imklog/bsd.c +++ b/plugins/imklog/bsd.c @@ -131,18 +131,18 @@ readklog(void) for (p = line; (q = strchr(p, '\n')) != NULL; p = q + 1) { *q = '\0'; - Syslog(LOG_INFO, p); + Syslog(LOG_INFO, (uchar*) p); } len = strlen(p); if (len >= MAXLINE - 1) { - Syslog(LOG_INFO, p); + Syslog(LOG_INFO, (uchar*)p); len = 0; } if (len > 0) memmove(line, p, len + 1); } if (len > 0) - Syslog(LOG_INFO, line); + Syslog(LOG_INFO, (uchar*)line); } -- cgit From b9198d251218f13803cf121c4ef5f69a0e850d24 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 15 Apr 2008 09:08:46 +0200 Subject: improved doc for imklog --- doc/Makefile.am | 3 +++ doc/imklog.html | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ doc/rsyslog_conf.html | 17 +++---------- 3 files changed, 76 insertions(+), 13 deletions(-) create mode 100644 doc/imklog.html diff --git a/doc/Makefile.am b/doc/Makefile.am index aa4e8a7d..7055cbc4 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -32,6 +32,9 @@ html_files = \ imfile.html \ imtcp.html \ imgssapi.html \ + imrelp.html \ + imuxsock.html \ + imgklog.html \ professional_support.html \ queues.html \ queueWorkerLogic.dia \ diff --git a/doc/imklog.html b/doc/imklog.html new file mode 100644 index 00000000..92c1881a --- /dev/null +++ b/doc/imklog.html @@ -0,0 +1,69 @@ + + +Kernel Log Input Module (imklog) + + + +

    Kernel Log Input Module

    +

    Module Name:    imklog

    +

    Author: Rainer Gerhards +<rgerhards@adiscon.com>

    +

    Description:

    +

    Reads messages from the kernel log and submits them to the +syslog engine.

    +

    Configuration Directives:

    +
      +
    • $KLogInternalMsgFacility +<facility>
      +The facility which messages internally generated by imklog will have. +imklog generates some messages of itself (e.g. on problems, startup and +shutdown) and these do not stem from the kernel. Historically, under +Linux, these too have "kern" facility. Thus, on Linux platforms the +default is "kern" while on others it is "syslogd". You usually do not +need to specify this configuratin directive - it is included primarily +for few limited cases where it is needed for good reason. Bottom line: +if you don't have a good idea why you should use this setting, do not +touch it.
    • +
    • $KLogPermitNonKernelFacility +[on/off]
      +
      At least under BSD the kernel log may contain entries +with non-kernel facilities. This setting controls how those are +handled. The default is "off", in which case these messages are +ignored. Switch it to on to submit non-kernel messages to rsyslog +processing.
    • +
    • $DebugPrintKernelSymbols +(imklog) [on/off]
      +Linux only, ignored on other platforms (but may be specified)
    • +
    • $klogSymbolLookup (imklog) [on/off] -- +former klogd -x option
      +Linux only, ignored on other platforms (but may be specified)
    • +
    • $klogUseSyscallInterface (imklog)  [on/off] +-- former klogd -2 option
      +Linux only, ignored on other platforms (but may be specified)
    • +
    • $klogSymbolsTwice (imklog) [on/off] -- +former klogd -s option
      +Linux only, ignored on other platforms (but may be specified)
      +
    • +
    +Caveats/Known Bugs: +

    This is obviously platform specific and requires platform +drivers. +Currently, imklog functionality is available on Linux and BSD.

    +

    Sample:

    +

    The following sample pulls messages from the kernel log. All +parameters are left by default, which is usually a good idea. Please +note that loading the plugin is sufficient to activate it. No directive +is needed to start pulling kernel messages.
    +

    + +

    [rsyslog.conf overview] +[manual index] [rsyslog site]

    +

    This documentation is part of the +rsyslog +project.
    +Copyright © 2008 by Rainer +Gerhards and +Adiscon. +Released under the GNU GPL version 3 or higher.

    + \ No newline at end of file diff --git a/doc/rsyslog_conf.html b/doc/rsyslog_conf.html index 8967f671..9325f73c 100644 --- a/doc/rsyslog_conf.html +++ b/doc/rsyslog_conf.html @@ -1,7 +1,5 @@ -rsyslog.conf file - - +rsyslog.conf file

    rsyslog.conf configuration file

    This document is currently being enhanced. Please @@ -49,7 +47,7 @@ plugin for plain tcp syslog

  • imgssapi - input plugin for plain tcp and GSS-enable syslog
  • immark - support for mark messages
  • -
  • imklog - kernel logging
  • +
  • imklog - kernel logging
  • imuxsock - unix sockets, including the system log socket
  • @@ -126,7 +124,7 @@ worker threads, default 1, recommended 1
  • $AllowedSender
  • $ControlCharacterEscapePrefix
  • $DebugPrintCFSyslineHandlerList
  • -
  • $DebugPrintKernelSymbols (imklog) [on/off]
  • +
  • $DebugPrintModuleList
  • $DebugPrintTemplateList
  • $DirCreateMode
  • @@ -143,14 +141,7 @@ worker threads, default 1, recommended 1
  • $GssForwardServiceName
  • $GssListenServiceName
  • $GssMode
  • -
  • $IncludeConfig
  • -
  • $klogSymbolLookup (imklog) [on/off] -- -former klogd -x option
  • -
  • $klogUseSyscallInterface (imklog)  [on/off] --- former klogd -2 option
  • -
  • $klogSymbolsTwice (imklog) [on/off] -- -former klogd -s option
  • -
  • $MainMsgQueueCheckpointInterval <number>
  • +
  • $IncludeConfig
  • MainMsgQueueCheckpointInterval <number>
  • $MainMsgQueueDequeueSlowdown <number> [number is timeout in microseconds (1000000us is 1sec!), default 0 (no delay). Simple rate-limiting!]
  • -- cgit From 0e83bd69fcce2359d1d25022d1cc1263e42219a9 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 15 Apr 2008 15:19:53 +0200 Subject: final work for release of v3.17.1 --- ChangeLog | 4 +++- configure.ac | 2 +- doc/Makefile.am | 2 +- doc/imgssapi.html | 6 ++++-- doc/manual.html | 5 +++-- doc/status.html | 14 +++++++------- plugins/imklog/imklog.c | 2 +- 7 files changed, 20 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 785aab69..29c12e9c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,11 +14,13 @@ Version 3.17.1 (rgerhards), 2008-04-15 change looks quite unintrusive and so we added it to the parser. - implemented klogd functionality for BSD - implemented high precision timestamps for the kernel log. Thanks to - Michale Biebl for pointing out that the kernel log did not have them. + Michael Biebl for pointing out that the kernel log did not have them. - provided ability to discard non-kernel messages if they are present in the kernel log (seems to happen on BSD) - implemented $KLogInternalMsgFacility config directive - implemented $KLogPermitNonKernelFacility config directive +Plus a number of bugfixes that were applied to v3-stable and beta +branches (not mentioned here in detail). --------------------------------------------------------------------------- Version 3.17.0 (rgerhards), 2008-04-08 - added native ability to send mail messages diff --git a/configure.ac b/configure.ac index e3cfd9fc..2a5ef16b 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([rsyslog],[3.17.1-bsd],[rsyslog@lists.adiscon.com]) +AC_INIT([rsyslog],[3.17.1],[rsyslog@lists.adiscon.com]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([syslogd.c]) AC_CONFIG_HEADERS([config.h]) diff --git a/doc/Makefile.am b/doc/Makefile.am index 0179c21f..6eb82b81 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -33,7 +33,7 @@ html_files = \ imgssapi.html \ imrelp.html \ imuxsock.html \ - imgklog.html \ + imklog.html \ professional_support.html \ queues.html \ queueWorkerLogic.dia \ diff --git a/doc/imgssapi.html b/doc/imgssapi.html index af15e59e..cf16eb01 100644 --- a/doc/imgssapi.html +++ b/doc/imgssapi.html @@ -10,7 +10,9 @@

    Description:

    Provides the ability to receive syslog messages from the network protected via Kerberos 5 encryption and authentication. This -module also accept plain tcp syslog messages on the same port if configured to do so. If you need just plain tcp, use  imtcp instead.

    +module also accept plain tcp syslog messages on the same port if configured to do so. If you need just plain tcp, use imtcp instead.

    +

    There is also an overview of gssapi support in rsyslog available. We recommend reading +it before digging into the configuration parameters.

    Configuration Directives:

    diff --git a/doc/status.html b/doc/status.html index 98bb4f90..63a3f588 100644 --- a/doc/status.html +++ b/doc/status.html @@ -2,16 +2,16 @@ rsyslog status page

    rsyslog status page

    -

    This page reflects the status as of 2008-04-09.

    +

    This page reflects the status as of 2008-04-15.

    Current Releases

    -

    development: 3.17.0 - -change log - -download +

    development: 3.17.1 - +change log - +download -
    beta: 3.15.0 - -change log - -download

    +
    beta: 3.15.1 - +change log - +download

    v3 stable: 3.14.2 - change log - download diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index e6bd2326..c6fb1592 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -95,7 +95,7 @@ enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity) MsgSetUxTradMsg(pMsg, (char*)msg); MsgSetRawMsg(pMsg, (char*)msg); MsgSetMSG(pMsg, (char*)msg); - MsgSetHOSTNAME(pMsg, LocalHostName); + MsgSetHOSTNAME(pMsg, (char*)LocalHostName); MsgSetTAG(pMsg, (char*)pszTag); pMsg->iFacility = LOG_FAC(iFacility); pMsg->iSeverity = LOG_PRI(iSeverity); -- cgit From 11a526bcee95dab6a5bf2cc25a07dc6d65eaa177 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 15 Apr 2008 18:21:59 +0200 Subject: bumped version number --- ChangeLog | 2 ++ configure.ac | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 29c12e9c..2749418a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ --------------------------------------------------------------------------- +Version 3.17.2 (rgerhards), 2008-04-?? +--------------------------------------------------------------------------- Version 3.17.1 (rgerhards), 2008-04-15 - removed dependency on MAXHOSTNAMELEN as much as it made sense. GNU/Hurd does not define it (because it has no limit), and we have taken diff --git a/configure.ac b/configure.ac index 2a5ef16b..8a5f6222 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([rsyslog],[3.17.1],[rsyslog@lists.adiscon.com]) +AC_INIT([rsyslog],[3.17.2],[rsyslog@lists.adiscon.com]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([syslogd.c]) AC_CONFIG_HEADERS([config.h]) -- cgit

    UxTradMsguxtradmsg will disappear soon - do NOT use!
    HOSTNAMEhostname hostname from the message
    alias for HOSTNAME
    FROMHOSTfromhost hostname of the system the message was received from (in a relay chain, this is the system immediately in front of us and not necessarily the original sender)
    PRIpri PRI part of the message - undecoded (single value)
    PRI-textpri-text the PRI part of the message in a textual form (e.g. "syslog.info")
    IUTiut the monitorware InfoUnitType - used when talking to a MonitorWare backend (also for phpLogCon)
    TIMESTAMPtimestamp alias for timereported
    PROTOCOL-VERSIONprotocol-version The contents of the PROTCOL-VERSION field from IETF draft draft-ietf-syslog-protcol
    STRUCTURED-DATAstructured-data The contents of the STRUCTURED-DATA field from IETF draft draft-ietf-syslog-protocol
    APP-NAMEapp-name The contents of the APP-NAME field from IETF draft draft-ietf-syslog-protocol
    PROCIDprocid The contents of the PROCID field from IETF draft draft-ietf-syslog-protocol
    MSGIDmsgid The contents of the MSGID field from IETF draft draft-ietf-syslog-protocol
    $NOW$now The current date stamp in the format YYYY-MM-DD
    $YEAR$year The current year (4-digit)
    $MONTH$month The current month (2-digit)
    $DAY$day The current day of the month (2-digit)
    $HOUR$hour The current hour in military (24 hour) time (2-digit)
    $HHOUR$hhour The current half hour we are in. From minute 0 to 29, this is always 0 while from 30 to 59 it is always 1.
    $QHOUR$qhour The current quarter hour we are in. Much like $HHOUR, but values range from 0 to 3 (for the four quater hours that are in each hour)
    $MINUTE$minute The current minute (2-digit)
    yes
    syslog over RELP
    truly reliable message delivery (Why is plain tcp syslog not reliable?)
    syslog over RELP
    +truly reliable message delivery (Why +is plain tcp syslog not reliable?)
    yes no
    no
    ability to process spooled +messages only during a configured timeframe (e.g. process messages only +during off-peak hours, during peak hours they are enqueued only)yes
    (can independently be configured for the main queue and each action queue)
    no
    ability to configure backup syslog/database servers yesability to process spooled messages only during a configured timeframe (e.g. process messages only during off-peak hours, during peak hours they are enqueued only)yes
    (can independently be configured for the main queue and each action queue)
    yes
    +(can independently be configured for the main queue and each action +queue)
    no
    yes not sure...
    native ability to send mail messagesyes (ommail, introduced in 3.17.0)not sure...
    good timestamp format control; at a minimum, ISO 8601/RFC 3339 second-resolution UTC zone
    regexCompares the property against the provided POSIX regular +Compares the property against the provided POSIX +regular expression.