summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog47
-rw-r--r--Makefile.am149
-rw-r--r--action.c4
-rw-r--r--conf.c9
-rw-r--r--configure.ac124
-rw-r--r--contrib/gnutls/ca.pem14
-rw-r--r--contrib/gnutls/cert.pem33
-rw-r--r--contrib/gnutls/key.pem15
-rw-r--r--dirty.h81
-rw-r--r--doc/Makefile.am3
-rw-r--r--doc/features.html39
-rw-r--r--doc/im3195.html46
-rw-r--r--doc/manual.html4
-rw-r--r--doc/property_replacer.html10
-rw-r--r--doc/rsyslog_conf.html24
-rw-r--r--doc/rsyslog_ng_comparison.html33
-rw-r--r--doc/rsyslog_stunnel.html488
-rw-r--r--doc/rsyslog_tls.html170
-rw-r--r--doc/src/queueWorkerLogic.dia (renamed from doc/queueWorkerLogic.dia)bin3334 -> 3334 bytes
-rw-r--r--doc/src/tls.diabin0 -> 4656 bytes
-rw-r--r--doc/status.html18
-rw-r--r--glbl.h40
-rw-r--r--gss-misc.c4
-rw-r--r--liblogging-stub.h26
-rw-r--r--omfwd.c644
-rw-r--r--outchannel.c2
-rw-r--r--parse.c2
-rw-r--r--parse.h19
-rw-r--r--plugins/im3195/Makefile.am8
-rw-r--r--plugins/im3195/im3195.c167
-rw-r--r--plugins/imfile/Makefile.am2
-rw-r--r--plugins/imfile/imfile.c12
-rw-r--r--plugins/imgssapi/Makefile.am2
-rw-r--r--plugins/imgssapi/imgssapi.c29
-rw-r--r--plugins/imklog/Makefile.am2
-rw-r--r--plugins/imklog/imklog.c12
-rw-r--r--plugins/imklog/imklog.h2
-rw-r--r--plugins/imklog/linux.c11
-rw-r--r--plugins/immark/Makefile.am2
-rw-r--r--plugins/immark/immark.c4
-rw-r--r--plugins/imrelp/Makefile.am2
-rw-r--r--plugins/imrelp/imrelp.c6
-rw-r--r--plugins/imtcp/Makefile.am2
-rw-r--r--plugins/imtcp/imtcp.c28
-rw-r--r--plugins/imtemplate/Makefile.am2
-rw-r--r--plugins/imudp/Makefile.am2
-rw-r--r--plugins/imudp/imudp.c13
-rw-r--r--plugins/imuxsock/Makefile.am2
-rw-r--r--plugins/imuxsock/imuxsock.c21
-rw-r--r--plugins/omgssapi/Makefile.am2
-rw-r--r--plugins/omgssapi/omgssapi.c35
-rw-r--r--plugins/omlibdbi/Makefile.am2
-rw-r--r--plugins/omlibdbi/omlibdbi.c2
-rw-r--r--plugins/ommail/Makefile.am2
-rw-r--r--plugins/ommail/ommail.c8
-rw-r--r--plugins/ommysql/Makefile.am2
-rw-r--r--plugins/ommysql/ommysql.c2
-rw-r--r--plugins/ompgsql/Makefile.am2
-rw-r--r--plugins/ompgsql/ompgsql.c2
-rw-r--r--plugins/omrelp/Makefile.am2
-rw-r--r--plugins/omrelp/omrelp.c8
-rw-r--r--plugins/omsnmp/Makefile.am2
-rw-r--r--plugins/omsnmp/omsnmp.c2
-rw-r--r--plugins/omtesting/Makefile.am2
-rw-r--r--plugins/omtesting/omtesting.c2
-rw-r--r--redhat/rsyslog12
-rw-r--r--redhat/rsyslog.conf26
-rw-r--r--redhat/rsyslog.init89
-rw-r--r--redhat/rsyslog.log6
-rw-r--r--redhat/rsyslog.sysconfig12
-rw-r--r--rfc3195d.884
-rw-r--r--rfc3195d.c289
-rw-r--r--runtime/Makefile.am119
-rw-r--r--runtime/atomic.h (renamed from atomic.h)15
-rw-r--r--runtime/cfsysline.c (renamed from cfsysline.c)16
-rw-r--r--runtime/cfsysline.h (renamed from cfsysline.h)15
-rw-r--r--runtime/ctok.c (renamed from ctok.c)0
-rw-r--r--runtime/ctok.h (renamed from ctok.h)0
-rw-r--r--runtime/ctok_token.c (renamed from ctok_token.c)0
-rw-r--r--runtime/ctok_token.h (renamed from ctok_token.h)0
-rw-r--r--runtime/datetime.c (renamed from datetime.c)15
-rw-r--r--runtime/datetime.h (renamed from datetime.h)15
-rw-r--r--runtime/debug.c (renamed from debug.c)17
-rw-r--r--runtime/debug.h (renamed from debug.h)15
-rw-r--r--runtime/errmsg.c (renamed from errmsg.c)29
-rw-r--r--runtime/errmsg.h (renamed from errmsg.h)15
-rw-r--r--runtime/expr.c (renamed from expr.c)0
-rw-r--r--runtime/expr.h (renamed from expr.h)0
-rw-r--r--runtime/glbl.c267
-rw-r--r--runtime/glbl.h62
-rw-r--r--runtime/linkedlist.c (renamed from linkedlist.c)19
-rw-r--r--runtime/linkedlist.h (renamed from linkedlist.h)17
-rw-r--r--runtime/module-template.h (renamed from module-template.h)15
-rw-r--r--runtime/modules.c (renamed from modules.c)29
-rw-r--r--runtime/modules.h (renamed from modules.h)18
-rw-r--r--runtime/msg.c (renamed from msg.c)70
-rw-r--r--runtime/msg.h (renamed from msg.h)19
-rw-r--r--runtime/net.c (renamed from net.c)83
-rw-r--r--runtime/net.h (renamed from net.h)30
-rw-r--r--runtime/netstrm.c309
-rw-r--r--runtime/netstrm.h70
-rw-r--r--runtime/netstrms.c276
-rw-r--r--runtime/netstrms.h57
-rw-r--r--runtime/nsd.h73
-rw-r--r--runtime/nsd_gtls.c727
-rw-r--r--runtime/nsd_gtls.h59
-rw-r--r--runtime/nsd_ptcp.c693
-rw-r--r--runtime/nsd_ptcp.h47
-rw-r--r--runtime/nsdsel_gtls.c235
-rw-r--r--runtime/nsdsel_gtls.h42
-rw-r--r--runtime/nsdsel_ptcp.c196
-rw-r--r--runtime/nsdsel_ptcp.h44
-rw-r--r--runtime/nssel.c227
-rw-r--r--runtime/nssel.h56
-rw-r--r--runtime/obj-types.h (renamed from obj-types.h)59
-rw-r--r--runtime/obj.c (renamed from obj.c)32
-rw-r--r--runtime/obj.h (renamed from obj.h)15
-rw-r--r--runtime/objomsr.c (renamed from objomsr.c)18
-rw-r--r--runtime/objomsr.h (renamed from objomsr.h)15
-rw-r--r--runtime/queue.c (renamed from queue.c)17
-rw-r--r--runtime/queue.h (renamed from queue.h)0
-rw-r--r--runtime/regexp.c (renamed from regexp.c)0
-rw-r--r--runtime/regexp.h (renamed from regexp.h)0
-rw-r--r--runtime/rsyslog.c237
-rw-r--r--runtime/rsyslog.h (renamed from rsyslog.h)102
-rw-r--r--runtime/srUtils.h (renamed from srUtils.h)16
-rw-r--r--runtime/srutils.c (renamed from srUtils.c)66
-rw-r--r--runtime/stream.c (renamed from stream.c)1
-rw-r--r--runtime/stream.h (renamed from stream.h)0
-rw-r--r--runtime/stringbuf.c (renamed from stringbuf.c)17
-rw-r--r--runtime/stringbuf.h (renamed from stringbuf.h)15
-rw-r--r--runtime/sync.c (renamed from sync.c)0
-rw-r--r--runtime/sync.h (renamed from sync.h)0
-rw-r--r--runtime/syslogd-types.h (renamed from syslogd-types.h)19
-rw-r--r--runtime/sysvar.c (renamed from sysvar.c)0
-rw-r--r--runtime/sysvar.h (renamed from sysvar.h)0
-rw-r--r--runtime/var.c (renamed from var.c)0
-rw-r--r--runtime/var.h (renamed from var.h)0
-rw-r--r--runtime/vm.c (renamed from vm.c)0
-rw-r--r--runtime/vm.h (renamed from vm.h)0
-rw-r--r--runtime/vmop.c (renamed from vmop.c)0
-rw-r--r--runtime/vmop.h (renamed from vmop.h)0
-rw-r--r--runtime/vmprg.c (renamed from vmprg.c)0
-rw-r--r--runtime/vmprg.h (renamed from vmprg.h)0
-rw-r--r--runtime/vmstk.c (renamed from vmstk.c)0
-rw-r--r--runtime/vmstk.h (renamed from vmstk.h)0
-rw-r--r--runtime/wti.c (renamed from wti.c)1
-rw-r--r--runtime/wti.h (renamed from wti.h)0
-rw-r--r--runtime/wtp.c (renamed from wtp.c)1
-rw-r--r--runtime/wtp.h (renamed from wtp.h)0
-rw-r--r--tcpclt.c4
-rw-r--r--tcpclt.h1
-rw-r--r--tcps_sess.c99
-rw-r--r--tcps_sess.h18
-rw-r--r--tcpsrv.c456
-rw-r--r--tcpsrv.h22
-rw-r--r--tcpsyslog.c55
-rw-r--r--tcpsyslog.h38
-rw-r--r--template.c2
-rw-r--r--threads.c2
-rw-r--r--threads.h5
-rw-r--r--tools/Makefile.am44
-rwxr-xr-xtools/gnutls/cert-gen-selfsigned6
-rwxr-xr-xtools/gnutls/cert-show-fingerprint6
-rw-r--r--tools/iminternal.c (renamed from iminternal.c)0
-rw-r--r--tools/iminternal.h (renamed from iminternal.h)0
-rw-r--r--tools/omdiscard.c (renamed from omdiscard.c)0
-rw-r--r--tools/omdiscard.h (renamed from omdiscard.h)0
-rw-r--r--tools/omfile.c (renamed from omfile.c)8
-rw-r--r--tools/omfile.h (renamed from omfile.h)0
-rw-r--r--tools/omfwd.c639
-rw-r--r--tools/omfwd.h (renamed from omfwd.h)0
-rw-r--r--tools/omshell.c (renamed from omshell.c)0
-rw-r--r--tools/omshell.h (renamed from omshell.h)0
-rw-r--r--tools/omusrmsg.c (renamed from omusrmsg.c)0
-rw-r--r--tools/omusrmsg.h (renamed from omusrmsg.h)0
-rw-r--r--tools/pidfile.c (renamed from pidfile.c)0
-rw-r--r--tools/pidfile.h (renamed from pidfile.h)0
-rw-r--r--tools/rsyslog.conf.5 (renamed from rsyslog.conf.5)0
-rw-r--r--tools/rsyslogd.8 (renamed from rsyslogd.8)0
-rw-r--r--tools/syslogd.c (renamed from syslogd.c)273
-rw-r--r--tools/syslogd.h (renamed from syslogd.h)73
182 files changed, 6490 insertions, 2877 deletions
diff --git a/ChangeLog b/ChangeLog
index 76afaa4a..71faebc1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,50 @@
+---------------------------------------------------------------------------
+Version 3.19.2 (rgerhards), 2008-05-16
+- bugfix: TCP input modules did incorrectly set fromhost property
+ (always blank)
+- bugfix: imklog did not set fromhost property
+- added "fromhost-ip" property
+ Note that adding this property changes the on-disk format for messages.
+ However, that should not have any bad effect on existing spool files.
+ But you will run into trouble if you create a spool file with this
+ version and then try to process it with an older one (after a downgrade).
+ Don't do that ;)
+- added "RSYSLOG_DebugFormat" canned template
+- bugfix: hostname and fromhost were swapped when a persisted message
+ (in queued mode) was read in
+- bugfix: lmtcpclt, lmtcpsrv and lmgssutil did all link to the static
+ runtime library, resulting in a large size increase (and potential
+ "interesting" effects). Thanks to Michael Biebel for reporting the size
+ issue.
+- bugfix: TLS server went into an endless loop in some situations.
+ Thanks to Michael Biebl for reporting the problem.
+- fixed potential segfault due to invalid call to cfsysline
+ thanks to varmojfekoj for the patch
+---------------------------------------------------------------------------
+Version 3.19.1 (rgerhards), 2008-05-07
+- configure help for --enable-gnutls wrong - said default is "yes" but
+ default actually is "no" - thanks to darix for pointing this out
+- file dirty.h was missing - thanks to darix for pointing this out
+- bugfix: man files were not properly distributed - thanks to
+ darix for reporting and to Michael Biebl for help with the fix
+- some minor cleanup
+---------------------------------------------------------------------------
+Version 3.19.0 (rgerhards), 2008-05-06
+- begins new devel branch version
+- implemented TLS for plain tcp syslog (this is also the world's first
+ implementation of IETF's upcoming syslog-transport-tls draft)
+- partly rewritten and improved omfwd among others, now loads TCP
+ code only if this is actually necessary
+- split of a "runtime library" for rsyslog - this is not yet a clean
+ model, because some modularization is still outstanding. In theory,
+ this shall enable other utilities but rsyslogd to use the same
+ runtime
+- implemented im3195, the RFC3195 input as a plugin
+- changed directory structure, files are now better organized
+- a lot of cleanup in regard to modularization
+- -c option no longer must be the first option - thanks to varmjofekoj
+ for the patch
+---------------------------------------------------------------------------
Version 3.17.2 (rgerhards), 2008-05-04
- this version is the new beta, based on 3.17.1 devel feature set
- merged in imklog bug fix from v3-stable (3.16.1)
diff --git a/Makefile.am b/Makefile.am
index 0e75710c..61edc634 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,125 +1,9 @@
-#sbin_PROGRAMS = rfc3195d rsyslogd
sbin_PROGRAMS =
-man_MANS =
-
-if ENABLE_RSYSLOGD
-sbin_PROGRAMS += rsyslogd
-rsyslogd_SOURCES = \
- datetime.c \
- datetime.h \
- errmsg.c \
- errmsg.h \
- syslogd.c \
- syslogd.h \
- sysvar.c \
- sysvar.h \
- vm.c \
- vm.h \
- vmstk.c \
- vmstk.h \
- vmprg.c \
- vmprg.h \
- vmop.c \
- vmop.h \
- debug.c \
- debug.h \
- glbl.h \
- pidfile.c \
- pidfile.h \
- template.c \
- outchannel.c \
- stringbuf.c \
- stringbuf.h \
- srUtils.c \
- srUtils.h \
- parse.c \
- parse.h \
- syslogd-types.h \
- template.h \
- outchannel.h \
- liblogging-stub.h \
- threads.c \
- threads.h \
- stream.c \
- stream.h \
- var.c \
- var.h \
- wtp.c \
- wtp.h \
- wti.c \
- wti.h \
- queue.c \
- queue.h \
- sync.c \
- sync.h \
- obj.c \
- obj.h \
- obj-types.h \
- msg.c \
- msg.h \
- expr.c \
- expr.h \
- ctok.c \
- ctok.h \
- ctok_token.c \
- ctok_token.h \
- conf.c \
- conf.h \
- omshell.c \
- omshell.h \
- omusrmsg.c \
- omusrmsg.h \
- omfwd.c \
- omfwd.h \
- tcpsyslog.c \
- tcpsyslog.h \
- omfile.c \
- omfile.h \
- omdiscard.c \
- omdiscard.h \
- modules.c \
- modules.h \
- module-template.h \
- objomsr.c \
- objomsr.h \
- cfsysline.c \
- cfsysline.h \
- linkedlist.c \
- linkedlist.h \
- iminternal.c \
- iminternal.h \
- action.c \
- action.h \
- atomic.h
-
-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
pkglib_LTLIBRARIES =
-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
-
if ENABLE_INET
-pkglib_LTLIBRARIES += lmnet.la lmtcpsrv.la lmtcpclt.la
-#
-# network support
-#
-lmnet_la_SOURCES = net.c net.h
-lmnet_la_CPPFLAGS = $(pthreads_cflags)
-lmnet_la_LDFLAGS = -module -avoid-version
-lmnet_la_LIBADD =
+pkglib_LTLIBRARIES += lmtcpsrv.la lmtcpclt.la
#
#
# TCP (stream) server support
@@ -129,7 +13,7 @@ lmtcpsrv_la_SOURCES = \
tcps_sess.h \
tcpsrv.c \
tcpsrv.h
-lmtcpsrv_la_CPPFLAGS = $(pthreads_cflags)
+lmtcpsrv_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
lmtcpsrv_la_LDFLAGS = -module -avoid-version
lmtcpsrv_la_LIBADD =
@@ -139,30 +23,19 @@ lmtcpsrv_la_LIBADD =
lmtcpclt_la_SOURCES = \
tcpclt.c \
tcpclt.h
-lmtcpclt_la_CPPFLAGS = $(pthreads_cflags)
+lmtcpclt_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
lmtcpclt_la_LDFLAGS = -module -avoid-version
lmtcpclt_la_LIBADD =
endif # if ENABLE_INET
#
-# regular expression support
-#
-if ENABLE_REGEXP
-pkglib_LTLIBRARIES += lmregexp.la
-lmregexp_la_SOURCES = regexp.c regexp.h
-lmregexp_la_CPPFLAGS = $(pthreads_cflags)
-lmregexp_la_LDFLAGS = -module -avoid-version
-lmregexp_la_LIBADD =
-endif
-
-#
# gssapi support
#
if ENABLE_GSSAPI
pkglib_LTLIBRARIES += lmgssutil.la
lmgssutil_la_SOURCES = gss-misc.c gss-misc.h
-lmgssutil_la_CPPFLAGS = $(pthreads_cflags)
+lmgssutil_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
lmgssutil_la_LDFLAGS = -module -avoid-version
lmgssutil_la_LIBADD = $(gss_libs)
endif
@@ -177,12 +50,18 @@ EXTRA_DIST = \
contrib/README \
rsyslog.conf \
COPYING.LESSER \
- $(man_MANS)
+ contrib/gnutls/ca.pem \
+ contrib/gnutls/cert.pem \
+ contrib/gnutls/key.pem
-SUBDIRS = . doc
+SUBDIRS = doc runtime .
SUBDIRS += plugins/immark plugins/imuxsock plugins/imtcp plugins/imudp plugins/omtesting
+if ENABLE_RSYSLOGD
+SUBDIRS += tools
+endif
+
if ENABLE_IMKLOG
SUBDIRS += plugins/imklog
endif
@@ -222,3 +101,7 @@ endif
if ENABLE_MAIL
SUBDIRS += plugins/ommail
endif
+
+if ENABLE_RFC3195
+SUBDIRS += plugins/im3195
+endif
diff --git a/action.c b/action.c
index 39c37b5b..216a7804 100644
--- a/action.c
+++ b/action.c
@@ -34,7 +34,7 @@
#include <time.h>
#include <errno.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "template.h"
#include "action.h"
#include "modules.h"
@@ -541,7 +541,7 @@ actionWriteToAction(action_t *pAction)
pAction->f_pMsg = pMsg; /* use the new msg (pointer will be restored below) */
}
- dbgprintf("Called action, logging to %s", module.GetStateName(pAction->pMod));
+ dbgprintf("Called action, logging to %s\n", module.GetStateName(pAction->pMod));
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
diff --git a/conf.c b/conf.c
index e11c609f..78895272 100644
--- a/conf.c
+++ b/conf.c
@@ -45,7 +45,8 @@
#endif
#include "rsyslog.h"
-#include "syslogd.h"
+#include "syslogd.h" /* this actually *is* part of the syslogd! */
+#include "dirty.h"
#include "parse.h"
#include "action.h"
#include "template.h"
@@ -57,6 +58,10 @@
#include "stringbuf.h"
#include "srUtils.h"
#include "errmsg.h"
+#include "net.h"
+#include "expr.h"
+#include "ctok.h"
+#include "ctok_token.h"
/* forward definitions */
@@ -501,7 +506,6 @@ rsRetVal cflineParseTemplateName(uchar** pp, omodStringRequest_t *pOMSR, int iEn
} else {
/* template specified, pick it up */
if(rsCStrConstruct(&pStrB) != RS_RET_OK) {
- glblHadMemShortage = 1;
iRet = RS_RET_OUT_OF_MEMORY;
goto finalize_it;
}
@@ -564,6 +568,7 @@ cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pOMSR, int
* passed back to the caller.
* rgerhards 2005-09-15
*/
+/* GPLv3 - stems back to sysklogd */
static rsRetVal cflineProcessTradPRIFilter(uchar **pline, register selector_t *f)
{
uchar *p;
diff --git a/configure.ac b/configure.ac
index 8a5f6222..a352da31 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,9 +2,9 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([rsyslog],[3.17.2],[rsyslog@lists.adiscon.com])
+AC_INIT([rsyslog],[3.19.2],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE
-AC_CONFIG_SRCDIR([syslogd.c])
+AC_CONFIG_SRCDIR([ChangeLog])
AC_CONFIG_HEADERS([config.h])
AC_GNU_SOURCE
@@ -433,42 +433,6 @@ 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@:>@])],
@@ -498,6 +462,63 @@ AC_SUBST(snmp_cflags)
AC_SUBST(snmp_libs)
+# GNUtls support
+AC_ARG_ENABLE(gnutls,
+ [AS_HELP_STRING([--enable-gnutls],[Enable GNU TLS support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_gnutls="yes" ;;
+ no) enable_gnutls="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-gnutls) ;;
+ esac],
+ [enable_gnutls=no]
+)
+if test "x$enable_gnutls" = "xyes"; then
+ AC_CHECK_HEADERS(
+ [gnutls/gnutls.h],,
+ [AC_MSG_FAILURE([GNUTls is missing])]
+ )
+ AC_CHECK_PROG(
+ [HAVE_GNUTLS_CONFIG],
+ [libgnutls-config],
+ [yes],,,
+ )
+ if test "x${HAVE_GNUTLS_CONFIG}" != "xyes"; then
+ AC_MSG_FAILURE([libgnutls-config not found in PATH])
+ fi
+ AC_CHECK_LIB(
+ [gnutls],
+ [gnutls_check_version],
+ [gnutls_cflags=`libgnutls-config --cflags`
+ gnutls_libs=`libgnutls-config --libs`
+ ],
+ [AC_MSG_FAILURE([GNU TLS library is missing])],
+ [`libgnutls-config --libs`]
+ )
+fi
+AM_CONDITIONAL(ENABLE_GNUTLS, test x$enable_gnutls = xyes)
+AC_SUBST(gnutls_cflags)
+AC_SUBST(gnutls_libs)
+
+
+# support for building the rsyslogd runtime
+AC_ARG_ENABLE(rsyslogrt,
+ [AS_HELP_STRING([--enable-rsyslogrt],[Build rsyslogrt @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_rsyslogrt="yes" ;;
+ no) enable_rsyslogrt="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-rsyslogrt) ;;
+ esac],
+ [enable_rsyslogrt=yes]
+)
+if test "x$enable_rsyslogrt" = "xyes"; then
+ rsrt_cflags="-I\$(top_srcdir)/runtime -I\$(top_srcdir)"
+ rsrt_libs="\$(top_builddir)/runtime/librsyslog.la"
+fi
+AM_CONDITIONAL(ENABLE_RSYSLOGRT, test x$enable_rsyslogrt = xyes)
+AC_SUBST(rsrt_cflags)
+AC_SUBST(rsrt_libs)
+
+
# support for NOT building rsyslogd (useful for source-based packaging systems)
AC_ARG_ENABLE(rsyslogd,
[AS_HELP_STRING([--enable-rsyslogd],[Build rsyslogd @<:@default=yes@:>@])],
@@ -542,7 +563,6 @@ AC_SUBST(RELP_CFLAGS)
AC_SUBST(RELP_LIBS)
# RFC 3195 support
-# WARNING: THIS IS NOT REALLY PRESENT YET - needs to be build manually!
AC_ARG_ENABLE(rfc3195,
[AS_HELP_STRING([--enable-rfc3195],[Enable RFC3195 support @<:@default=no@:>@])],
[case "${enableval}" in
@@ -553,25 +573,11 @@ AC_ARG_ENABLE(rfc3195,
[enable_rfc3195=no]
)
if test "x$enable_rfc3195" = "xyes"; then
- AC_CHECK_HEADERS(
- [librfc3195.h],,
- [AC_MSG_FAILURE([RFC3195 library is missing (no headers)])]
- )
-# I don't know how to tell that librfc3195 needs -lrt, so I disable
-# this check for now - the header check should work well enough...
-# rgerhards, 2008-03-25
-# AC_CHECK_LIB(
-# [rfc3195],
-# [rfc3195EngineGetVersion],
-# [rfc3195_cflags=""
- rfc3195_libs="-lrfc3195"
-# ],
-# [AC_MSG_FAILURE([RFC3195 library is missing])]
-# )
+ PKG_CHECK_MODULES(LIBLOGGING, liblogging >= 0.7.1)
fi
AM_CONDITIONAL(ENABLE_RFC3195, test x$enable_rfc3195 = xyes)
-AC_SUBST(rfc3195_cflags)
-AC_SUBST(rfc3195_libs)
+AC_SUBST(RFC3195_CFLAGS)
+AC_SUBST(RFC3195_LIBS)
# settings for the template input module; copy and modify this code
@@ -615,9 +621,12 @@ AM_CONDITIONAL(ENABLE_IMTEMPLATE, test x$enable_imtemplate = xyes)
AC_CONFIG_FILES([Makefile \
+ runtime/Makefile \
+ tools/Makefile \
doc/Makefile \
plugins/imudp/Makefile \
plugins/imtcp/Makefile \
+ plugins/im3195/Makefile \
plugins/imgssapi/Makefile \
plugins/imuxsock/Makefile \
plugins/immark/Makefile \
@@ -652,10 +661,11 @@ echo "file input module enabled: $enable_imfile"
echo "input template module will be compiled: $enable_imtemplate"
echo "Large file support enabled: $enable_largefile"
echo "Networking support enabled: $enable_inet"
+echo "GnuTLS network stream driver enabled: $enable_gnutls"
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 "rsyslog runtime will be built: $enable_rsyslogrt"
echo "rsyslogd will be built: $enable_rsyslogd"
diff --git a/contrib/gnutls/ca.pem b/contrib/gnutls/ca.pem
new file mode 100644
index 00000000..747250ca
--- /dev/null
+++ b/contrib/gnutls/ca.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaegAwIBAgIBADALBgkqhkiG9w0BAQUwRTELMAkGA1UEBhMCR1IxDDAK
+BgNVBAoTA0ZTRjEPMA0GA1UECxMGR05VVExTMRcwFQYDVQQDEw5HTlVUTFMgVEVT
+VCBDQTAeFw0wNDA2MjgyMjQ0MDBaFw0wNzAzMjQyMjQ0MDBaMEUxCzAJBgNVBAYT
+AkdSMQwwCgYDVQQKEwNGU0YxDzANBgNVBAsTBkdOVVRMUzEXMBUGA1UEAxMOR05V
+VExTIFRFU1QgQ0EwgZwwCwYJKoZIhvcNAQEBA4GMADCBiAKBgMK0cY9Tap5F7DXX
+tu7HpHlZtu+zqfofyLJSIBpUdbiwFIGzB486stbog0mpiy32mGIG5hNlpcRMJMVm
+MmZ1RueqQWR+vdDroBoV199zAZQVww1NmmHi/Wtxa6x9SsXdya+SnoC8KI/V3EKx
+gYG0hYAuYWNA9JnntTU0xCwWOBaPAgMBAAGjQzBBMA8GA1UdEwEB/wQFMAMBAf8w
+DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUeesbb6Nm5nnh0eK129onBkUpCkgw
+CwYJKoZIhvcNAQEFA4GBAGCCzUSCVZOXffm/KFxbyT2Lrltyzqlr0Oknp55eNAIk
+fy+m/viSOmoTCaK9Gmtk3eMAxIeZ8U7TDKrbrxx/NSsggbypqa3EMMwr2JH9kzAZ
+eluQ0vEVqfvRq5jzjuORYYhl7VgqpU0/ctvI3b+9tCZAOCcUX0HPvNweAzYjnkDi
+-----END CERTIFICATE-----
diff --git a/contrib/gnutls/cert.pem b/contrib/gnutls/cert.pem
new file mode 100644
index 00000000..88910725
--- /dev/null
+++ b/contrib/gnutls/cert.pem
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIICmDCCAgOgAwIBAgIBAjALBgkqhkiG9w0BAQUwUjELMAkGA1UEBhMCR1IxDDAK
+BgNVBAoTA0ZTRjEPMA0GA1UECxMGR05VVExTMSQwIgYDVQQDExtHTlVUTFMgSU5U
+RVJNRURJQVRFIFRFU1QgQ0EwHhcNMDQwNjI4MjI0NzAwWhcNMDcwMzIyMjI0NzAw
+WjBJMQswCQYDVQQGEwJHUjEMMAoGA1UEChMDRlNGMQ8wDQYDVQQLEwZHTlVUTFMx
+GzAZBgNVBAMTEkdOVVRMUyBURVNUIFNFUlZFUjCBnDALBgkqhkiG9w0BAQEDgYwA
+MIGIAoGA1chUqA9ib8S5GKd29B9d1rwgUncFhJPu0+RK8kOyOsV3qBdtdWeBSiGW
+So1RHkcmV9BlbUtmuHioAUkZPSo8gtoEy3JpSemW221BsjwITjGeZxZsb+4C/U2X
+HUIlO+jqBK5VYbpNXkP/2ofMkWWAZyKnI+PMIfFvv/cASsI0k48CAwEAAaOBjTCB
+ijAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDATBgNVHSUEDDAK
+BggrBgEFBQcDATAPBgNVHQ8BAf8EBQMDB6AAMB0GA1UdDgQWBBTIZD/hlqUB89OE
+AwonwqGflkHtijAfBgNVHSMEGDAWgBQ2tS+xHdrw3r4o20MwGkLdzh5UlDALBgkq
+hkiG9w0BAQUDgYEAWPpWlUlvzDZRbpneYw8d6Q8On/ZPmSYBCm38vTKPEoNA6lW1
+WIc3Vbw5zOeSfDLifIWV2W/MqyjDo9MeWvSKpcUfRfibpXBgbA4RAGW0j2K1JQmE
+gP3k1vMicYzn5EglhZjoa9I+36a90vJraqzHQ7DrKtW0FDfW2GREzSh9RV8=
+-----END CERTIFICATE-----
+
+-----BEGIN CERTIFICATE-----
+MIICajCCAdWgAwIBAgIBATALBgkqhkiG9w0BAQUwRTELMAkGA1UEBhMCR1IxDDAK
+BgNVBAoTA0ZTRjEPMA0GA1UECxMGR05VVExTMRcwFQYDVQQDEw5HTlVUTFMgVEVT
+VCBDQTAeFw0wNDA2MjgyMjQ2MDBaFw0wNzAzMjMyMjQ2MDBaMFIxCzAJBgNVBAYT
+AkdSMQwwCgYDVQQKEwNGU0YxDzANBgNVBAsTBkdOVVRMUzEkMCIGA1UEAxMbR05V
+VExTIElOVEVSTUVESUFURSBURVNUIENBMIGcMAsGCSqGSIb3DQEBAQOBjAAwgYgC
+gYC0JKSLzHuiWK66XYOJk6AxDBo94hdCFnfIor7xnZkqTgiUQZhk9HDVmmz1+tLd
+yJk6r9PK+WMDDBkSOvT+SmQNd9mL2JzI+bJWwoB77aJ7vUI3/9+ugtffiapnX6wx
+vLyAxeJRyN0Q3oBHc6N2dJo9z1NHoFe8xipXXHOdxU1DAwIDAQABo2QwYjAPBgNV
+HRMBAf8EBTADAQH/MA8GA1UdDwEB/wQFAwMHBAAwHQYDVR0OBBYEFDa1L7Ed2vDe
+vijbQzAaQt3OHlSUMB8GA1UdIwQYMBaAFHnrG2+jZuZ54dHitdvaJwZFKQpIMAsG
+CSqGSIb3DQEBBQOBgQCi/SI37DrGCeZhtGhU2AyZFaqskRoFt4zAb9UYaGZaYEh5
+0VUZsA/Ol8jiiQTtiCokZswhSsn+2McZmcspKigsY2aEBrry+TGFWMnYu5j5kcwP
+1nVuHxLRwLt2rIsjgkeSNdHr8XHKi9/Roz/Gj86OnBAHwPt8WHfHK+63cMX1WA==
+-----END CERTIFICATE-----
+
diff --git a/contrib/gnutls/key.pem b/contrib/gnutls/key.pem
new file mode 100644
index 00000000..1e80b2e5
--- /dev/null
+++ b/contrib/gnutls/key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICWwIBAAKBgQDVyFSoD2JvxLkYp3b0H13WvCBSdwWEk+7T5EryQ7I6xXeoF211
+Z4FKIZZKjVEeRyZX0GVtS2a4eKgBSRk9KjyC2gTLcmlJ6ZbbbUGyPAhOMZ5nFmxv
+7gL9TZcdQiU76OoErlVhuk1eQ//ah8yRZYBnIqcj48wh8W+/9wBKwjSTjwIDAQAB
+AoGAAn2Ueua++1Vb4K0mxh5NbhCAAeXwEwTULfTFaMAgJe4iADvRoyIDEBWHFjRC
+QyuKB1DetaDAwBprvqQW3q8MyGYD7P9h85Wfu/hpIYKTw9hNeph420aE8WXw2ygl
+TkJz3bzkMrXe/WjdhS1kTt8avCNQR/p0jM/UHvNze4oLc1ECQQDfammiczQFtj+F
+uf3CNcYwp5XNumF+pubdGb+UHUiHyCuVQxvm+LXgq8wXV/uXFLrp7FQFLCDQf0ji
+KDB2YQvRAkEA9PY/2AaGsU7j8ePwQbxCkwuj3hY6O6aNLIGxKxwZrzbob26c+tQk
+/++e0IXusIscBvcRV1Kg8Ff6fnw7/AdhXwJAG8qVbOuRmGk0BkwuFmPoeW3vNQgR
+X96O7po0qPBqVdRAU2rvzYtkCFxYqq0ilI0ekZtAfKxbeykaQaRkkKPaoQJAcifP
+yWJ/tu8z4DM7Ka+pFqTMwIllM1U3vFtv3LXezDE7AGDCyHKdB7MXcPXqj6nmCLMi
+swwiLLahAOBnUqk6xwJAJQ4pGcFFlCiIiVsq0wYSYmZUcRpSIInEQ0f8/xN6J22Z
+siP5vnJM3F7R6ciYTt2gzNci/W9cdZI2HxskkO5lbQ==
+-----END RSA PRIVATE KEY-----
diff --git a/dirty.h b/dirty.h
new file mode 100644
index 00000000..2782eea8
--- /dev/null
+++ b/dirty.h
@@ -0,0 +1,81 @@
+/* This file is an aid to support non-modular object accesses
+ * while we do not have fully modularized everything. Once this is
+ * done, this file can (and should) be deleted. Presence of it
+ * also somewhat indicates that the runtime library is not really
+ * yet a runtime library, because it depends on some functionality
+ * residing somewhere else.
+ *
+ * Copyright 2007, 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 <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef DIRTY_H_INCLUDED
+#define DIRTY_H_INCLUDED 1
+
+#define MAXLINE 2048 /* maximum line length */
+
+/* Flags to logmsg().
+ */
+#define NOFLAG 0x000 /* no flag is set (to be used when a flag must be specified and none is required) */
+#define INTERNAL_MSG 0x001 /* msg generated by logmsgInternal() --> special handling */
+/* NO LONGER USED: #define SYNC_FILE 0x002 / * do fsync on file after printing */
+#define ADDDATE 0x004 /* add a date to the message */
+#define MARK 0x008 /* this message is a mark */
+
+#define MSG_PARSE_HOSTNAME 1
+#define MSG_DONT_PARSE_HOSTNAME 0
+
+rsRetVal submitMsg(msg_t *pMsg);
+rsRetVal logmsgInternal(int pri, uchar *msg, int flags);
+rsRetVal parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int bParseHost, int flags, flowControl_t flowCtlType);
+
+/* TODO: the following 2 need to go in conf obj interface... */
+rsRetVal cflineParseTemplateName(uchar** pp, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *dfltTplName);
+rsRetVal cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *pszTpl);
+
+/* Intervals at which we flush out "message repeated" messages,
+ * in seconds after previous message is logged. After each flush,
+ * we move to the next interval until we reach the largest.
+ * TODO: move this to action object! Only action.c and syslogd.c use it.
+ */
+extern int bActExecWhenPrevSusp;
+extern int iActExecOnceInterval;
+extern int MarkInterval;
+extern int repeatinterval[2];
+extern int bReduceRepeatMsgs;
+#define MAXREPEAT ((int)((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1))
+#define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
+#define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \
+ (f)->f_repeatcount = MAXREPEAT; \
+ }
+#ifdef USE_NETZIP
+/* config param: minimum message size to try compression. The smaller
+ * the message, the less likely is any compression gain. We check for
+ * gain before we submit the message. But to do so we still need to
+ * do the (costly) compress() call. The following setting sets a size
+ * for which no call to compress() is done at all. This may result in
+ * a few more bytes being transmited but better overall performance.
+ * Note: I have not yet checked the minimum UDP packet size. It might be
+ * that we do not save anything by compressing very small messages, because
+ * UDP might need to pad ;)
+ * rgerhards, 2006-11-30
+ */
+#define MIN_SIZE_FOR_COMPRESS 60
+#endif
+
+#endif /* #ifndef DIRTY_H_INCLUDED */
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 6eb82b81..da2e2328 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -21,6 +21,7 @@ html_files = \
rsyslog_high_database_rate.html \
rsyslog_php_syslog_ng.html \
rsyslog_recording_pri.html \
+ rsyslog_tls.html \
rsyslog_stunnel.html \
syslog-protocol.html \
version_naming.html \
@@ -36,7 +37,7 @@ html_files = \
imklog.html \
professional_support.html \
queues.html \
- queueWorkerLogic.dia \
+ src/queueWorkerLogic.dia \
queueWorkerLogic.jpg \
queueWorkerLogic_small.jpg \
rainerscript.html \
diff --git a/doc/features.html b/doc/features.html
index 13fc34c6..2b3b31d9 100644
--- a/doc/features.html
+++ b/doc/features.html
@@ -1,5 +1,7 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html><head><title>rsyslog features</title></head>
+<html><head><title>rsyslog features</title>
+
+</head>
<body>
<h1>RSyslog - Features</h1>
<p><b>This page lists both current features as well as
@@ -23,13 +25,18 @@ to MySQL databases</a></li>
<li> native support for writing to Postgres databases</li>
<li>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)</li><li>native support for <a href="ommail.html">sending mail messages</a> (first seen in 3.17.0)</li>
+a database abstraction layer (almost as good as native)</li>
+<li>native support for <a href="ommail.html">sending
+mail messages</a> (first seen in 3.17.0)</li>
<li>support for (plain) tcp based syslog - much better
reliability</li>
<li>support for sending and receiving compressed syslog messages</li>
<li>support for on-demand on-disk spooling of messages that can
not be processed fast enough (a great feature for <a href="rsyslog_high_database_rate.html">writing massive
-amounts of syslog messages to a database</a>)</li><li>support for selectively <a href="http://wiki.rsyslog.com/index.php/OffPeakHours">processing messages only during specific timeframes</a> and spooling them to disk otherwise</li>
+amounts of syslog messages to a database</a>)</li>
+<li>support for selectively <a href="http://wiki.rsyslog.com/index.php/OffPeakHours">processing
+messages only during specific timeframes</a> and spooling them to
+disk otherwise</li>
<li>ability to monitor text files and convert their contents
into syslog messages (one per line)</li>
<li>ability to configure backup syslog/database servers - if
@@ -49,8 +56,9 @@ substrings</li>
command execution</li>
<li>support for running multiple rsyslogd instances on a single
machine</li>
-<li>support for <a href="rsyslog_stunnel.html">
-ssl-protected syslog</a> (via stunnel)</li>
+<li>support for <a href="rsyslog_tls.html">TLS-protected
+syslog</a> (both <a href="rsyslog_tls.html">natively</a>
+and via <a href="rsyslog_stunnel.html">stunnel</a>)</li>
<li>ability to filter on any part of the message, not just
facility and severity</li>
<li>ability to use regular expressions in filters</li>
@@ -70,8 +78,7 @@ high log volume on multicore machines)</li>
compliant messages (it is volatile because standardization is currently
underway and this is a proof-of-concept implementation to aid this
effort)</li>
-<li> experimental support for syslog-transport-tls based
-framing on syslog/tcp connections</li>
+<li> world's first implementation of syslog-transport-tls</li>
<li> the sysklogd's klogd functionality is implemented as the <i>imklog</i>
input plug-in. So rsyslog is a full replacement for the sysklogd package</li>
<li> support for IPv6</li>
@@ -90,7 +97,13 @@ via custom plugins</li>
<li>support for arbitrary complex boolean, string and
arithmetic expressions in message filters</li>
</ul>
-<p>&nbsp;</p>
+<h2>World's first</h2>
+Rsyslog has an interesting number of "world's firsts" - things that
+were implemented for the first time ever in rsyslog. Some of them are still features not available elsewhere.<br><ul>
+<li>world's first implementation of IETF I-D syslog-protocol (February 2006, version 1.12.2 and above)</li><li>world's first implementation of dynamic syslog on-the-wire compression (December 2006, version 1.13.0 and above)</li><li>world's first open-source implementation of a disk-queueing syslogd (January 2008, version 3.11.0 and above)</li>
+<li>world's first implementation of IETF I-D
+syslog-transport-tls (May 2008, version 3.19.0 and above)</li>
+</ul>
<h2>Upcoming Features</h2>
<p>The list below is something like a repository of ideas we'd
like to implement. Features on this list are typically NOT scheduled
@@ -101,17 +114,13 @@ typically within reach of implementation. Users are encouraged to
submit feature requests there (or via our forums). If we like them but
they look quite long-lived (aka "not soon to be implemented"), they
will possibly be migrated to this list here and at some time moved back
-to the sourceforge tracker.</p>
+to the bugzilla tracker.</p>
<ul>
-<li>implement native email-functionality in selector (probably
-best done as a plug-in)</li>
<li>port it to more *nix variants (eg AIX and HP UX) - this
needs volunteers with access to those machines and knowledge </li>
-<li>support for native SSL enryption of plain tcp syslog
-sessions. This will most probably happen based on syslog-transport-tls.</li>
<li>pcre filtering - maybe (depending on feedback)&nbsp; -
simple regex already partly added. So far, this seems sufficient so
-that there is no urgent need to do pcre</li>
+that there is no urgent need to do pcre. If done, it will be a loadable RainerScript function.</li>
<li>support for <a href="http://www.monitorware.com/Common/en/glossary/rfc3195.php">RFC
3195</a> as a sender - this is currently unlikely to happen,
because there is no real demand for it. Any work on RFC 3195 has been
@@ -124,4 +133,4 @@ future of RFC 3195 in rsyslog</a>.</li>
<p>To see when each feature was added, see the
<a href="http://www.rsyslog.com/Topic4.phtml">rsyslog
change log</a> (online only).</p>
-</body></html> \ No newline at end of file
+</body></html>
diff --git a/doc/im3195.html b/doc/im3195.html
new file mode 100644
index 00000000..d6f2f2ed
--- /dev/null
+++ b/doc/im3195.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<title>RFC3195 Input Module (im3195)</title>
+
+</head>
+<body>
+<h1>RFC3195 Input Module</h1>
+<p><b>Module Name:&nbsp;&nbsp;&nbsp; im3195</b></p>
+<p><b>Author: </b>Rainer Gerhards
+&lt;rgerhards@adiscon.com&gt;</p>
+<p><b>Description</b>:</p>
+<p>Receives syslog messages via RFC 3195. The RAW profile is fully implemented and the
+COOKED profile is provided in an experimental state. This module uses
+<a href="http://www.liblogging.org">liblogging</a> for the actual protocol handling.</p>
+<p><b>Configuration Directives</b>:</p>
+<ul>
+<li><strong>$Input3195ListenPort &lt;port&gt;</strong><br>
+The port on which imklog listens for RFC 3195 messages. The default port is 601
+(the IANA-assigned port)</li>
+</ul>
+<b>Caveats/Known Bugs:</b>
+<p>Due to no demand at all for RFC3195, we have converted rfc3195d
+to this input module, but we have NOT conducted any testing. Also,
+the module does not yet properly handle the recovery case. If someone
+intends to put this module into production, good testing should be
+cunducted. It also is a good idea to notify the rsyslog project that you intend to use
+it in production. In this case, we'll probably give the module another
+cleanup. We don't do this now because so far it looks just like a big
+waste of time.
+<p>Currently only a single listener can be defined. That one binds to all interfaces.</p>
+<p><b>Sample:</b></p>
+<p>The following sample accepts syslog messages via RFC 3195 on port 1601.
+<br>
+</p>
+<textarea rows="15" cols="60">$ModLoad im3195
+$Input3195ListenPort 1601
+</textarea>
+<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>]
+[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
+<p><font size="2">This documentation is part of the
+<a href="http://www.rsyslog.com/">rsyslog</a> project.<br>
+Copyright &copy; 2008 by <a href="http://www.gerhards.net/rainer">Rainer
+Gerhards</a> and
+<a href="http://www.adiscon.com/">Adiscon</a>.
+Released under the GNU GPL version 3 or higher.</font></p>
+</body></html>
diff --git a/doc/manual.html b/doc/manual.html
index 1719ef5e..84be70d3 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -11,12 +11,12 @@ control, high precision timestamps, queued operations and the ability to filter
part.</b>
It is quite compatible to stock sysklogd and can be used as a drop-in
replacement. Its <a href="features.html">
-advanced features</a> make it suitable for enterprise-class, <a href="rsyslog_stunnel.html">encryption protected syslog</a>
+advanced features</a> make it suitable for enterprise-class, <a href="rsyslog_tls.html">encryption protected syslog</a>
relay chains while at the same time being very easy to setup for the
novice user. And as we know what enterprise users really need, there is
also <a href="professional_support.html">professional
rsyslog support</a> available directly from the source!</p>
-<p><b>This documentation is for version 3.17.2 (devel branch) of rsyslog.</b>
+<p><b>This documentation is for version 3.19.1 (devel branch) of rsyslog.</b>
Visit the <i> <a href="http://www.rsyslog.com/doc-status.html">rsyslog status page</a></i></b> to obtain current
version information and project status.
</p><p><b>If you like rsyslog, you might
diff --git a/doc/property_replacer.html b/doc/property_replacer.html
index a2efaede..4fa7ee4a 100644
--- a/doc/property_replacer.html
+++ b/doc/property_replacer.html
@@ -44,7 +44,13 @@ socket. Should be useful for debugging.</td>
<td><b>fromhost</b></td>
<td>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)</td>
+not necessarily the original sender). This is a DNS-resolved name, except
+if that is not possible or DNS resolution has been disabled.</td>
+</tr>
+<tr>
+<td><b>fromhost-ip</b></td>
+<td>The same as fromhost, but alsways as an IP address. Local inputs
+(like imklog) use 127.0.0.1 in this property.</td>
</tr>
<tr>
<td><b>syslogtag</b></td>
@@ -286,4 +292,4 @@ to record severity and facility of a message)</li>
<li><a href="rsyslog_conf.html">Configuration file
syntax</a>, this is where you actually use the property replacer.</li>
</ul>
-</body></html> \ No newline at end of file
+</body></html>
diff --git a/doc/rsyslog_conf.html b/doc/rsyslog_conf.html
index 9325f73c..a78a70c1 100644
--- a/doc/rsyslog_conf.html
+++ b/doc/rsyslog_conf.html
@@ -50,6 +50,8 @@ input plugin for plain tcp and GSS-enable syslog</li>
<li><a href="imklog.html">imklog</a> - kernel logging</li>
<li><a href="imuxsock.html">imuxsock</a> -
unix sockets, including the system log socket</li>
+<li><a href="im3195.html">im3195</a> -
+accepts syslog messages via RFC 3195</li>
</ul>
<p>Please note that each module provides configuration
directives, which are NOT necessarily being listed below. Also
@@ -114,19 +116,23 @@ default 60000 (1 minute)]</li>
<li>$ActionQueueType [FixedArray/LinkedList/<b>Direct</b>/Disk]</li>
<li>$ActionQueueSaveOnShutdown&nbsp; [on/<b>off</b>]
</li>
-<li>$ActionQueueWorkerThreads &lt;number&gt;, num
-worker threads, default 1, recommended 1</li>
-<li>$ActionQueueWorkerThreadMinumumMessages
-&lt;number&gt;, default 100</li>
+<li>$ActionQueueWorkerThreads &lt;number&gt;, num worker threads, default 1, recommended 1</li>
+<li>$ActionQueueWorkerThreadMinumumMessages &lt;number&gt;, default 100</li>
<li><a href="rsconf1_actionresumeinterval.html">$ActionResumeInterval</a></li>
-<li>$ActionResumeRetryCount &lt;number&gt; [default 0,
--1 means eternal]</li>
+<li>$ActionResumeRetryCount &lt;number&gt; [default 0, -1 means eternal]</li>
+<li>$ActionSendStreamDriver &lt;driver basename&gt; just like $DefaultNetstreamDriver, but for the specific action
+<li>$ActionSendStreamDriverMode &lt;mode&gt;, default 0, mode to use with the stream driver
+(driver-specific)</li>
<li><a href="rsconf1_allowedsender.html">$AllowedSender</a></li>
<li><a href="rsconf1_controlcharacterescapeprefix.html">$ControlCharacterEscapePrefix</a></li>
<li><a href="rsconf1_debugprintcfsyslinehandlerlist.html">$DebugPrintCFSyslineHandlerList</a></li>
<li><a href="rsconf1_debugprintmodulelist.html">$DebugPrintModuleList</a></li>
<li><a href="rsconf1_debugprinttemplatelist.html">$DebugPrintTemplateList</a></li>
+<li>$DefaultNetstreamDriver &lt;drivername&gt;, default lmnsd_ptcp, use lmnsd_gtls for TLS protection</li>
+<li>$DefaultNetstreamDriverCAFile &lt;/path/to/cafile.pem&gt;</li>
+<li>$DefaultNetstreamDriverCertFile &lt;/path/to/certfile.pem&gt;</li>
+<li>$DefaultNetstreamDriverKeyFile &lt;/path/to/keyfile.pem&gt;</li>
<li><a href="rsconf1_dircreatemode.html">$DirCreateMode</a></li>
<li><a href="rsconf1_dirgroup.html">$DirGroup</a></li>
<li><a href="rsconf1_dirowner.html">$DirOwner</a></li>
@@ -347,6 +353,10 @@ 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.</li>
+<li><span style="font-weight: bold;">RSYSLOG_DebugFormat</span>
+- a special format used for troubleshooting property problems. This format
+is meant to be written to a log file. Do <b>not</b> use for production or remote
+forwarding.</li>
</ul>
<h2>Output Channels</h2>
<p>Output Channels are a new concept first introduced in rsyslog
@@ -1190,4 +1200,4 @@ additional
and database support). For obvious reasons, the syntax for defining
such features is available in rsyslogd, only.<br>
&nbsp;</p>
-</body></html> \ No newline at end of file
+</body></html>
diff --git a/doc/rsyslog_ng_comparison.html b/doc/rsyslog_ng_comparison.html
index 28413337..72fee210 100644
--- a/doc/rsyslog_ng_comparison.html
+++ b/doc/rsyslog_ng_comparison.html
@@ -1,11 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html><head><title>rsyslog vs. syslog-ng - a comparison</title>
-
-</head>
+<html><head><title>rsyslog vs. syslog-ng - a comparison</title></head>
<body>
<h1>rsyslog vs. syslog-ng</h1>
<p><small><i>Written by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a>
-(2008-04-08)</i></small></p>
+(2008-05-06)</i></small></p>
<p>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
@@ -57,7 +55,7 @@ comparison sheet, so please don't be shy ;)</p>
</tr>
<tr>
<td valign="top">RFC 3195/BEEP</td>
-<td valign="top">yes (needs separate build process)</td>
+<td valign="top">yes (via <a href="im3195.html">im3195</a>)</td>
<td valign="top">no</td>
<td></td>
</tr>
@@ -101,7 +99,7 @@ Network (Protocol) Support</b><br>
<tr>
<td valign="top">support for GSS-API</td>
<td valign="top">yes</td>
-<td valign="top">no (?)</td>
+<td valign="top">no</td>
</tr>
<tr>
<td valign="top">ability to limit the allowed
@@ -141,20 +139,24 @@ reliable <a href="http://www.monitorware.com/Common/en/glossary/rfc3195.php">RFC
<td valign="top">no</td>
</tr>
<tr>
-<td valign="top">support for <a href="rsyslog_stunnel.html">ssl-protected
+<td valign="top">support for <a href="rsyslog_tls.html">TLS/SSL-protected
syslog</a> </td>
-<td valign="top"><a href="rsyslog_stunnel.html">via
+<td valign="top"><a href="rsyslog_tls.html">natively</a> (since 3.19.0)<br><a href="rsyslog_stunnel.html">via
stunnel</a></td>
<td valign="top">via stunnel<br>
paid edition natively</td>
</tr>
<tr>
-<td valign="top">support for IETF's new
-syslog-protocol draft</td>
+<td valign="top">support for IETF's new syslog-protocol draft</td>
<td valign="top">yes</td>
<td valign="top">no</td>
</tr>
<tr>
+<td valign="top">support for IETF's new syslog-transport-tls draft</td>
+<td valign="top">yes<br>(since 3.19.0 - world's first implementation)</td>
+<td valign="top">no</td>
+</tr>
+<tr>
<td valign="top">support for IPv6</td>
<td valign="top">yes</td>
<td valign="top">yes</td>
@@ -162,7 +164,7 @@ syslog-protocol draft</td>
<tr>
<td valign="top">native ability to send SNMP traps</td>
<td valign="top">yes</td>
-<td valign="top">?</td>
+<td valign="top">no</td>
</tr>
<tr>
<td valign="top">ability to preserve the original
@@ -426,8 +428,10 @@ including ability to present channel and priority as visible log data</td>
<td valign="top">yes</td>
<td valign="top">not sure...</td>
</tr>
-<tr><td valign="top">native ability to send mail messages</td>
-<td valign="top">yes (<a href="ommail.html">ommail</a>, introduced in 3.17.0)</td>
+<tr>
+<td valign="top">native ability to send mail messages</td>
+<td valign="top">yes (<a href="ommail.html">ommail</a>,
+introduced in 3.17.0)</td>
<td valign="top">not sure...</td>
</tr>
<tr>
@@ -578,6 +582,5 @@ 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
<a href="http://www.balabit.com/network-security/syslog-ng/features/detailed/">Balabit's
site</a>.</p>
-<p>This document is current as of 2008-04-08 and definitely
-incomplete (I did not yet manage to complete it!).</p>
+
</body></html> \ No newline at end of file
diff --git a/doc/rsyslog_stunnel.html b/doc/rsyslog_stunnel.html
index 9d944521..104a672e 100644
--- a/doc/rsyslog_stunnel.html
+++ b/doc/rsyslog_stunnel.html
@@ -1,248 +1,240 @@
-<html><head>
-<title>SSL Encrypting syslog with stunnel</title>
-<meta name="KEYWORDS" content="syslog encryption, rsyslog, stunnel, secure syslog, tcp, reliable, howto, ssl">
-</head>
-<body>
-<h1>SSL Encrypting Syslog with Stunnel</h1>
- <P><small><i>Written by
- <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer
- Gerhards</a> (2005-07-22)</i></small></P>
-<h2>Abstract</h2>
-<p><i><b>In this paper, I describe how to encrypt <a href="http://www.monitorware.com/en/topics/syslog/">syslog</a>
-messages on the network.</b> Encryption
-is vital to keep the confidiental content of syslog messages secure. I describe the overall
-approach and provide an HOWTO do it with the help of
-<a href="http://www.rsyslog.com">rsyslogd</a> and <a href="http://www.stunnel.org">stunnel</a>.</i></p>
-<h2>Background</h2>
-<P><b>Syslog is a
-clear-text protocol. That means anyone with a sniffer can have
-a peek at your data.</b> In some environments, this is no problem at all. In
-others, it is a huge setback, probably even preventing deployment of syslog
-solutions. Thankfully, there is an easy way to encrypt syslog communication. I
-will describe one approach in this paper.</P>
-<P>The most straigthforward solution would be that the syslogd itself encrypts
-messages. Unfortuantely, encryption is only standardized in
-<a href="http://www.monitorware.com/Common/en/glossary/rfc3195.php">RFC 3195</a>. But there
-is currently no syslogd that implements RFC 3195's encryption features,
-so this route leads to nothing. Another approach would be to use vendor- or
-project-specific syslog extensions. There are a few around, but the problem here
-is that they have compatibility issues. However, there is one surprisingly easy
-and interoperable solution: though not standardized, many vendors and projects
-implement plain tcp syslog. In a nutshell, plain tcp syslog is a mode where
-standard syslog messages are transmitted via tcp and records are separated by
-newline characters. This mode is supported by all major syslogd's (both on Linux/Unix
-and Windows) as well as log sources (for example,
-<a href="http://www.eventreporter.com/en/">EventReporter</a> for Windows
-Event Log forwarding). Plain tcp syslog offers reliability, but it does not
-offer encryption in itself. However, since it operates on a tcp stream, it is now easy
-to add encryption. There are various ways to do that. In this paper, I will
-describe how it is done with stunnel (an
-other alternative would be <a href="http://en.wikipedia.org/wiki/IPSec">IPSec</a>, for example).</P>
-<P>Stunnel is open source and it is available both for Unix/Linux and Windows.
-It provides a way to
- use ssl communication for any non-ssl aware client and server - in this case,
- our syslogd.</P>
- <P>Stunnel works much like a wrapper. Both on the client and on the server machine,
- tunnel portals are created. The non-ssl aware client and server software is
- configured to not directly talk to the remote partner, but to the local
- (s)tunnel portal instead. Stunnel, in turn, takes the data received from the
- client, encrypts it via ssl, sends it to the remote tunnel portal and that
- remote portal sends it to the recipient process on the remote machine. The
- transfer to the portals is done via unencrypted communication. As such,
- it is vital that
- the portal and the respective program that is talking to it are on the same
- machine, otherwise data would travel partly unencrypted. Tunneling, as done by stunnel,
- requires connection oriented communication. This is why you need to use
- tcp-based syslog. As a side-note, you can also encrypt a plain-text RFC
- 3195 session via stunnel, though this definitely is not what the
- protocol designers had on their mind ;)</P>
-<P>In the rest of this document, I assume that you use rsyslog on both the
-client and the server. For the samples, I use <a href="http://www.debian.org/">Debian</a>.
-Interestingly, there are
-some annoying differences between stunnel implementations. For example, on
-Debian a comment line starts with a semicolon (';'). On
-<a href="http://www.redhat.com">Red Hat</a>, it starts with
-a hash sign ('#'). So you need to watch out for subtle issues when setting up
-your system.</P>
-<h2>Overall System Setup</h2>
-<P>In ths paper, I assume two machines, one named &quot;client&quot; and the other named &quot;server&quot;.
-It is obvious that, in practice, you will probably have multiple clients but
-only one server. Syslog traffic shall be transmitted via stunnel over the
-network. Port 60514 is to be used for that purpose. The machines are set up as
-follows:</P>
-<P><b>Client</b></P>
-<ul>
- <li>rsyslog forwards&nbsp; message to stunnel local portal at port 61514</li>
- <li>local stunnel forwards data via the network to port 60514 to its remote
- peer</li>
-</ul>
-<P><b>Server</b></P>
-<ul>
- <li>stunnel listens on port 60514 to connections from its client peers</li>
- <li>all connections are forwarded to the locally-running rsyslog listening
- at port 61514</li>
-</ul>
-<h2>Setting up the system</h2>
-<P>For Debian, you need the &quot;stunnel4&quot; package. The &quot;stunnel&quot; package is the
-older 3.x release, which will not support the configuration I describe below.
-Other distributions might have other names. For example, on Red Hat it is just &quot;stunnel&quot;.
-Make sure that you install the appropriate package on both the client and the
-server. It is also a good idea to check if there are updates for either stunnel
-or openssl (which stunnel uses) - there are often security fixes available and
-often the latest fixes are not included in the default package.</P>
-<P>In my sample setup, I use only the bare minimum of options. For example, I do
-not make the server check client cerficiates. Also, I do not talk much about
-certificates at all. If you intend to really secure your system, you should
-probably learn about certificates and how to manage and deploy them. This is
-beyond the scope of this paper. For additional information,
-<a href="http://www.stunnel.org/faq/certs.html">
-http://www.stunnel.org/faq/certs.html</a> is a good starting point.</P>
-<P>You also need to install rsyslogd on both machines. Do this before starting
-with the configuration. You should also familarize yourself with its
-configuration file syntax, so that you know which actions you can trigger with
-it. Rsyslogd can work as a drop-in replacement for stock
-<a href="http://www.infodrom.org/projects/sysklogd/">sysklogd</a>. So if you know
-the standard syslog.conf syntax, you do not need to learn any more to follow
-this paper.</P>
-<h3>Server Setup</h3>
-<P>At the server, you need to have a digital certificate. That certificate
-enables SSL operation, as it provides the necessary crypto keys being used to
-secure the connection. Many versions of stunnel come with a default certificate,
-often found in /etc/stunnel/stunnel.pem. If you have it, it is good for testing
-only. If you use it in production, it is very easy to break into your secure
-channel as everybody is able to get hold of your private key. I didn't find an
-stunnel.pem on my Debian machine. I guess the Debian folks removed it because of
-its insecurity.</P>
-<P>You can create your own certificate with a simple openssl tool - you need to
-do it if you have none and I highly recommend to create one in any case. To
-create it, cd to /etc/stunnel and type:</P>
-<p><blockquote><code>openssl req -new -x509 -days 3650 -nodes -out
-stunnel.pem -keyout stunnel.pem</code></blockquote></p>
-<P>That command will ask you a number of questions. Provide some answer for
-them. If you are unsure, read
-<a href="http://www.stunnel.org/faq/certs.html">
-http://www.stunnel.org/faq/certs.html</a>. After the command has finished, you
-should have a usable stunnel.pem in your working directory.</P>
-<P>Next is to create a configuration file for stunnel. It will direct stunnel
-what to do. You can used the following basic file:</P>
-<P><blockquote><code><pre>; Certificate/key is needed in server mode
-cert = /etc/stunnel/stunnel.pem
-
-<i>; Some debugging stuff useful for troubleshooting
-debug = 7
-foreground=yes</i>
-
-[ssyslog]
-accept = 60514
-connect = 61514</pre>
-</code></blockquote></P>
-<p>Save this file to e.g. /etc/stunnel/syslog-server.conf. Please note that the
-settings in <i>italics</i> are for debugging only. They run stunnel
-with a lot of debug information in the foreground. This is very valuable while
-you setup the system - and very useless once everything works well. So be sure
-to remove these lines when going to production.</p>
-<p>Finally, you need to start the stunnel daemon. Under Debian, this is done via
-&quot;stunnel /etc/stunnel/syslog.server.conf&quot;. If you have enabled the debug
-settings, you will immediately see a lot of nice messages.</p>
-<p>Now you have stunnel running, but it obviously unable to talk to rsyslog -
-because it is not yet running. If not already done, configure it so that it does
-everything you want. If in doubt, you can simply copy /etc/syslog.conf to /etc/rsyslog.conf
-and you probably have what you want. The really important thing in rsyslogd
-configuration is that you must make it listen to tcp port 61514 (remember: this
-is where stunnel send the messages to). Thankfully, this is easy to achive: just
-add &quot;-t 61514&quot; to the rsyslogd startup options in your system startup script.
-After done so, start (or restart) rsyslogd.</p>
-<p>The server should now be fully operational.</p>
-<h3>Client Setup</h3>
-<P>The client setup is simpler. Most importantly, you do not need a certificate
-(of course, you can use one if you would like to authenticate the client, but
-this is beyond the scope of this paper). So the basic thing you need to do is
-create the stunnel configuration file.</P>
-<P><blockquote><code><pre><i>; Some debugging stuff useful for troubleshooting
-debug = 7
-foreground=yes</i>
-
-<b>client=yes</b>
-
-[ssyslog]
-accept = 127.0.0.1:61514
-connect = <font color="#FF0000">192.0.2.1</font>:60514
-</pre>
-</code></blockquote></P>
-<P>Again, the text in <i>italics</i> is for debugging purposes only. I suggest
-you leave it in during your initial testing and then remove it. The most
-important difference to the server configuration outlined above is the &quot;client=yes&quot;
-directive. It is what makes this stunnel behave like a client. The accept
-directive binds stunnel only to the local host, so that it is protected from
-receiving messages from the network (somebody might fake to be the local sender).
-The address &quot;192.0.2.1&quot; is the address of the server machine. You must change it
-to match your configuration. Save this file to /etc/stunnel/syslog-client.conf.</P>
-<P>Then, start stunnel via &quot;stunnel4 /etc/stunnel/syslog-client.conf&quot;.&nbsp; Now
-you should see some startup messages. If no errors appear, you have a running
-client stunnel instance.</P>
-<P>Finally, you need to tell rsyslogd to send data to the remote host. In stock
-syslogd, you do this via the &quot;@host&quot; forwarding directive. The same works with
-rsyslog, but it suppports extensions to use tcp. Add the following line to your
-/etc/rsyslog.conf:</P>
-<P><blockquote><code><pre>*.* @<font color="#FF0000">@</font>127.0.0.1:61514
-</pre>
-</code></blockquote><i></P>
-
-</i>
-
-<P>Please note the double at-sign (@@). This is no typo. It tells rsyslog to use
-tcp instead of udp delivery. In this sample, all messages are forwarded to the
-remote host. Obviously, you may want to limit this via the usual rsyslog.conf
-settings (if in doubt, use man rsyslog.con).</P>
-<P>You do not need to add any special startup settings to rsyslog on the client.
-Start or restart rsyslog so that the new configuration setting takes place.</P>
-<h3>Done</h3>
-<P>After following these steps, you should have a working secure syslog
-forwarding system. To verify, you can type &quot;logger test&quot; or a similar smart
-command on the client. It should show up in the respective server log file. If
-you dig out you sniffer, you should see that the traffic on the wire is actually
-protected. In the configuration use above, the two stunnel endpoints should be
-quite chatty, so that you can follow the action going on on your system.</P>
-<P>If you have only basic security needs, you can probably just remove the debug
-settings and take the rest of the configuration to production. If you are
-security-sensitve, you should have a look at the various stunnel settings that
-help you further secure the system.</P>
-<h2>Preventing Systems from talking directly to the rsyslog Server</h2>
-<P>It is possible that remote systems (or attackers) talk to the rsyslog server
-by directly connecting to its port 61514. Currently (July of 2005), rsyslog does
-not offer the ability to bind to the local host, only. This feature is planned,
-but as long as it is missing, rsyslog must be protected via a firewall. This can
-easily be done via e.g iptables. Just be sure not to forget it.</P>
-<h2>Conclusion</h2>
-<P>With minumal effort, you can set up a secure logging infrastructure employing
-ssl encrypted syslog message transmission. As a side note, you also have the
-benefit of reliable tcp delivery which is far less prone to message loss than
-udp.</P>
-<h3>Feedback requested</h3>
-<P>I would appreciate feedback on this tutorial. If you have additional ideas,
-comments or find bugs (I *do* bugs - no way... ;)), please
-<a href="mailto:rgerhards@adiscon.com">let me know</a>.</P>
-<h2>Revision History</h2>
-<ul>
- <li>2005-07-22 *
- <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> * Initial Version created</li>
- <li>2005-07-26 *
- <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> * Some text brush-up, hyperlinks added</li>
- <li>2005-08-03 *
- <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>
- * license added</li>
-</ul>
-<h2>Copyright</h2>
-<p>Copyright (c) 2005
-<a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> and
-<a href="http://www.adiscon.com/en/">Adiscon</a>.</p>
-<p> Permission is granted to copy, distribute and/or modify this document
- under the terms of the GNU Free Documentation License, Version 1.2
- or any later version published by the Free Software Foundation;
- with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
- Texts. A copy of the license can be viewed at
-<a href="http://www.gnu.org/copyleft/fdl.html">
-http://www.gnu.org/copyleft/fdl.html</a>.</p>
-
-</body>
-</html> \ No newline at end of file
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+
+<title>SSL Encrypting syslog with stunnel</title><meta name="KEYWORDS" content="syslog encryption, rsyslog, stunnel, secure syslog, tcp, reliable, howto, ssl"></head><body>
+<h1>SSL Encrypting Syslog with Stunnel</h1>
+ <p><small><i>Written by
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer
+ Gerhards</a> (2005-07-22)</i></small></p>
+<h2>Abstract</h2>
+<p><i><b>In this paper, I describe how to encrypt <a href="http://www.monitorware.com/en/topics/syslog/">syslog</a>
+messages on the network.</b> Encryption
+is vital to keep the confidiental content of syslog messages secure. I describe the overall
+approach and provide an HOWTO do it with the help of
+<a href="http://www.rsyslog.com">rsyslogd</a> and <a href="http://www.stunnel.org">stunnel</a>.</i></p><p><span style="font-weight: bold;">Please note that starting with rsyslog 3.19.0, </span><a style="font-weight: bold;" href="rsyslog_tls.html">rsyslog provides native TLS/SSL encryption</a><span style="font-weight: bold;"> <span style="font-style: italic;">without</span> the need of stunnel. </span>I
+strongly recomend to use that feature instead of stunnel. The stunnel
+documentation here is mostly provided for backwards compatibility. New
+deployments are advised to use native TLS mode.<i></i></p>
+<h2>Background</h2>
+<p><b>Syslog is a
+clear-text protocol. That means anyone with a sniffer can have
+a peek at your data.</b> In some environments, this is no problem at all. In
+others, it is a huge setback, probably even preventing deployment of syslog
+solutions. Thankfully, there is an easy way to encrypt syslog communication. I
+will describe one approach in this paper.</p>
+<p>The most straigthforward solution would be that the syslogd itself encrypts
+messages. Unfortuantely, encryption is only standardized in
+<a href="http://www.monitorware.com/Common/en/glossary/rfc3195.php">RFC 3195</a>. But there
+is currently no syslogd that implements RFC 3195's encryption features,
+so this route leads to nothing. Another approach would be to use vendor- or
+project-specific syslog extensions. There are a few around, but the problem here
+is that they have compatibility issues. However, there is one surprisingly easy
+and interoperable solution: though not standardized, many vendors and projects
+implement plain tcp syslog. In a nutshell, plain tcp syslog is a mode where
+standard syslog messages are transmitted via tcp and records are separated by
+newline characters. This mode is supported by all major syslogd's (both on Linux/Unix
+and Windows) as well as log sources (for example,
+<a href="http://www.eventreporter.com/en/">EventReporter</a> for Windows
+Event Log forwarding). Plain tcp syslog offers reliability, but it does not
+offer encryption in itself. However, since it operates on a tcp stream, it is now easy
+to add encryption. There are various ways to do that. In this paper, I will
+describe how it is done with stunnel (an
+other alternative would be <a href="http://en.wikipedia.org/wiki/IPSec">IPSec</a>, for example).</p>
+<p>Stunnel is open source and it is available both for Unix/Linux and Windows.
+It provides a way to
+ use ssl communication for any non-ssl aware client and server - in this case,
+ our syslogd.</p>
+ <p>Stunnel works much like a wrapper. Both on the client and on the server machine,
+ tunnel portals are created. The non-ssl aware client and server software is
+ configured to not directly talk to the remote partner, but to the local
+ (s)tunnel portal instead. Stunnel, in turn, takes the data received from the
+ client, encrypts it via ssl, sends it to the remote tunnel portal and that
+ remote portal sends it to the recipient process on the remote machine. The
+ transfer to the portals is done via unencrypted communication. As such,
+ it is vital that
+ the portal and the respective program that is talking to it are on the same
+ machine, otherwise data would travel partly unencrypted. Tunneling, as done by stunnel,
+ requires connection oriented communication. This is why you need to use
+ tcp-based syslog. As a side-note, you can also encrypt a plain-text RFC
+ 3195 session via stunnel, though this definitely is not what the
+ protocol designers had on their mind ;)</p>
+<p>In the rest of this document, I assume that you use rsyslog on both the
+client and the server. For the samples, I use <a href="http://www.debian.org/">Debian</a>.
+Interestingly, there are
+some annoying differences between stunnel implementations. For example, on
+Debian a comment line starts with a semicolon (';'). On
+<a href="http://www.redhat.com">Red Hat</a>, it starts with
+a hash sign ('#'). So you need to watch out for subtle issues when setting up
+your system.</p>
+<h2>Overall System Setup</h2>
+<p>In ths paper, I assume two machines, one named "client" and the other named "server".
+It is obvious that, in practice, you will probably have multiple clients but
+only one server. Syslog traffic shall be transmitted via stunnel over the
+network. Port 60514 is to be used for that purpose. The machines are set up as
+follows:</p>
+<p><b>Client</b></p>
+<ul>
+ <li>rsyslog forwards&nbsp; message to stunnel local portal at port 61514</li>
+ <li>local stunnel forwards data via the network to port 60514 to its remote
+ peer</li>
+</ul>
+<p><b>Server</b></p>
+<ul>
+ <li>stunnel listens on port 60514 to connections from its client peers</li>
+ <li>all connections are forwarded to the locally-running rsyslog listening
+ at port 61514</li>
+</ul>
+<h2>Setting up the system</h2>
+<p>For Debian, you need the "stunnel4" package. The "stunnel" package is the
+older 3.x release, which will not support the configuration I describe below.
+Other distributions might have other names. For example, on Red Hat it is just "stunnel".
+Make sure that you install the appropriate package on both the client and the
+server. It is also a good idea to check if there are updates for either stunnel
+or openssl (which stunnel uses) - there are often security fixes available and
+often the latest fixes are not included in the default package.</p>
+<p>In my sample setup, I use only the bare minimum of options. For example, I do
+not make the server check client cerficiates. Also, I do not talk much about
+certificates at all. If you intend to really secure your system, you should
+probably learn about certificates and how to manage and deploy them. This is
+beyond the scope of this paper. For additional information,
+<a href="http://www.stunnel.org/faq/certs.html">
+http://www.stunnel.org/faq/certs.html</a> is a good starting point.</p>
+<p>You also need to install rsyslogd on both machines. Do this before starting
+with the configuration. You should also familarize yourself with its
+configuration file syntax, so that you know which actions you can trigger with
+it. Rsyslogd can work as a drop-in replacement for stock
+<a href="http://www.infodrom.org/projects/sysklogd/">sysklogd</a>. So if you know
+the standard syslog.conf syntax, you do not need to learn any more to follow
+this paper.</p>
+<h3>Server Setup</h3>
+<p>At the server, you need to have a digital certificate. That certificate
+enables SSL operation, as it provides the necessary crypto keys being used to
+secure the connection. Many versions of stunnel come with a default certificate,
+often found in /etc/stunnel/stunnel.pem. If you have it, it is good for testing
+only. If you use it in production, it is very easy to break into your secure
+channel as everybody is able to get hold of your private key. I didn't find an
+stunnel.pem on my Debian machine. I guess the Debian folks removed it because of
+its insecurity.</p>
+<p>You can create your own certificate with a simple openssl tool - you need to
+do it if you have none and I highly recommend to create one in any case. To
+create it, cd to /etc/stunnel and type:</p>
+<p></p><blockquote><code>openssl req -new -x509 -days 3650 -nodes -out
+stunnel.pem -keyout stunnel.pem</code></blockquote><p></p>
+<p>That command will ask you a number of questions. Provide some answer for
+them. If you are unsure, read
+<a href="http://www.stunnel.org/faq/certs.html">
+http://www.stunnel.org/faq/certs.html</a>. After the command has finished, you
+should have a usable stunnel.pem in your working directory.</p>
+<p>Next is to create a configuration file for stunnel. It will direct stunnel
+what to do. You can used the following basic file:</p>
+<p></p><blockquote><code></code><pre>; Certificate/key is needed in server mode<br>cert = /etc/stunnel/stunnel.pem<br><br><i>; Some debugging stuff useful for troubleshooting<br>debug = 7<br>foreground=yes</i>
+
+[ssyslog]
+accept = 60514
+connect = 61514</pre>
+</blockquote><p></p>
+<p>Save this file to e.g. /etc/stunnel/syslog-server.conf. Please note that the
+settings in <i>italics</i> are for debugging only. They run stunnel
+with a lot of debug information in the foreground. This is very valuable while
+you setup the system - and very useless once everything works well. So be sure
+to remove these lines when going to production.</p>
+<p>Finally, you need to start the stunnel daemon. Under Debian, this is done via
+"stunnel /etc/stunnel/syslog.server.conf". If you have enabled the debug
+settings, you will immediately see a lot of nice messages.</p>
+<p>Now you have stunnel running, but it obviously unable to talk to rsyslog -
+because it is not yet running. If not already done, configure it so that it does
+everything you want. If in doubt, you can simply copy /etc/syslog.conf to /etc/rsyslog.conf
+and you probably have what you want. The really important thing in rsyslogd
+configuration is that you must make it listen to tcp port 61514 (remember: this
+is where stunnel send the messages to). Thankfully, this is easy to achive: just
+add "-t 61514" to the rsyslogd startup options in your system startup script.
+After done so, start (or restart) rsyslogd.</p>
+<p>The server should now be fully operational.</p>
+<h3>Client Setup</h3>
+<p>The client setup is simpler. Most importantly, you do not need a certificate
+(of course, you can use one if you would like to authenticate the client, but
+this is beyond the scope of this paper). So the basic thing you need to do is
+create the stunnel configuration file.</p>
+<p></p><blockquote><code></code><pre><i>; Some debugging stuff useful for troubleshooting<br>debug = 7<br>foreground=yes</i>
+
+<b>client=yes</b>
+
+[ssyslog]
+accept = 127.0.0.1:61514
+connect = <font color="#ff0000">192.0.2.1</font>:60514<br></pre>
+</blockquote><p></p>
+<p>Again, the text in <i>italics</i> is for debugging purposes only. I suggest
+you leave it in during your initial testing and then remove it. The most
+important difference to the server configuration outlined above is the "client=yes"
+directive. It is what makes this stunnel behave like a client. The accept
+directive binds stunnel only to the local host, so that it is protected from
+receiving messages from the network (somebody might fake to be the local sender).
+The address "192.0.2.1" is the address of the server machine. You must change it
+to match your configuration. Save this file to /etc/stunnel/syslog-client.conf.</p>
+<p>Then, start stunnel via "stunnel4 /etc/stunnel/syslog-client.conf".&nbsp; Now
+you should see some startup messages. If no errors appear, you have a running
+client stunnel instance.</p>
+<p>Finally, you need to tell rsyslogd to send data to the remote host. In stock
+syslogd, you do this via the "@host" forwarding directive. The same works with
+rsyslog, but it suppports extensions to use tcp. Add the following line to your
+/etc/rsyslog.conf:</p>
+<p></p><blockquote><code></code><pre>*.* @<font color="#ff0000">@</font>127.0.0.1:61514<br></pre>
+</blockquote><i><p></p>
+
+</i>
+
+<p>Please note the double at-sign (@@). This is no typo. It tells rsyslog to use
+tcp instead of udp delivery. In this sample, all messages are forwarded to the
+remote host. Obviously, you may want to limit this via the usual rsyslog.conf
+settings (if in doubt, use man rsyslog.con).</p>
+<p>You do not need to add any special startup settings to rsyslog on the client.
+Start or restart rsyslog so that the new configuration setting takes place.</p>
+<h3>Done</h3>
+<p>After following these steps, you should have a working secure syslog
+forwarding system. To verify, you can type "logger test" or a similar smart
+command on the client. It should show up in the respective server log file. If
+you dig out you sniffer, you should see that the traffic on the wire is actually
+protected. In the configuration use above, the two stunnel endpoints should be
+quite chatty, so that you can follow the action going on on your system.</p>
+<p>If you have only basic security needs, you can probably just remove the debug
+settings and take the rest of the configuration to production. If you are
+security-sensitve, you should have a look at the various stunnel settings that
+help you further secure the system.</p>
+<h2>Preventing Systems from talking directly to the rsyslog Server</h2>
+<p>It is possible that remote systems (or attackers) talk to the rsyslog server
+by directly connecting to its port 61514. Currently (July of 2005), rsyslog does
+not offer the ability to bind to the local host, only. This feature is planned,
+but as long as it is missing, rsyslog must be protected via a firewall. This can
+easily be done via e.g iptables. Just be sure not to forget it.</p>
+<h2>Conclusion</h2>
+<p>With minumal effort, you can set up a secure logging infrastructure employing
+ssl encrypted syslog message transmission. As a side note, you also have the
+benefit of reliable tcp delivery which is far less prone to message loss than
+udp.</p>
+<h3>Feedback requested</h3>
+<p>I would appreciate feedback on this tutorial. If you have additional ideas,
+comments or find bugs (I *do* bugs - no way... ;)), please
+<a href="mailto:rgerhards@adiscon.com">let me know</a>.</p>
+<h2>Revision History</h2>
+<ul>
+ <li>2005-07-22 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> * Initial Version created</li>
+ <li>2005-07-26 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> * Some text brush-up, hyperlinks added</li>
+ <li>2005-08-03 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>
+ * license added</li><li>2008-05-05 * <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>
+ * updated to reflect native TLS capability of rsyslog 3.19.0 and above</li>
+</ul>
+<h2>Copyright</h2>
+<p>Copyright (c) 2008 <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> and
+<a href="http://www.adiscon.com/en/">Adiscon</a>.</p>
+<p> Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.2
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ Texts. A copy of the license can be viewed at
+<a href="http://www.gnu.org/copyleft/fdl.html">
+http://www.gnu.org/copyleft/fdl.html</a>.</p>
+
+</body></html> \ No newline at end of file
diff --git a/doc/rsyslog_tls.html b/doc/rsyslog_tls.html
new file mode 100644
index 00000000..c0ebb9c8
--- /dev/null
+++ b/doc/rsyslog_tls.html
@@ -0,0 +1,170 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><title>TLS (SSL) Encrypting syslog</title>
+
+<meta name="KEYWORDS" content="syslog encryption, rsyslog, secure syslog, tcp, reliable, howto, ssl, tls">
+</head>
+<body>
+<h1>Encrypting Syslog Traffic with TLS (SSL)</h1>
+<p><small><i>Written by <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer
+Gerhards</a> (2008-05-06)</i></small></p>
+<h2>Abstract</h2>
+<p><i><b>In this paper, I describe how to encrypt <a href="http://www.monitorware.com/en/topics/syslog/">syslog</a>
+messages on the network.</b> Encryption
+is vital to keep the confidiental content of syslog messages secure. I
+describe the overall
+approach and provide an HOWTO do it with <a href="http://www.rsyslog.com">rsyslog's</a> TLS
+features.&nbsp;</i></p><p>Please
+note that TLS is the more secure successor of SSL. While people often
+talk about "SSL encryption" they actually mean "TLS encryption". So
+don't look any further if you look for how to SSL-encrypt syslog. You
+have found the right spot.<i></i></p>
+<h2>Background</h2>
+<p><b>Traditional syslog is a clear-text protocol. That
+means anyone with a sniffer can have a peek at your data.</b> In
+some environments, this is no problem at all. In others, it is a huge
+setback, probably even preventing deployment of syslog solutions.
+Thankfully, there are easy ways to encrypt syslog
+communication.&nbsp;</p>
+The traditional approach involves <a href="rsyslog_stunnel.html">running
+a wrapper like stunnel around the syslog session</a>. This works
+quite well and is in widespread use. However, it is not thightly
+coupled with the main syslogd and some, even severe, problems can
+result from this (follow a mailing list thread that describes <a href="http://lists.adiscon.net/pipermail/rsyslog/2008-March/000580.html">total
+loss of syslog messages due to stunnel mode</a> and the <a href="http://rgerhards.blogspot.com/2008/04/on-unreliability-of-plain-tcp-syslog.html">unreliability
+of TCP syslog</a>).
+<p><a href="gssapi.html">Rsyslog supports syslog via
+GSSAP</a>I since long to overcome these limitatinos. However,
+syslog via GSSAPI is a rsyslog-exclusive transfer mode and it requires
+a proper Kerberos environment. As such, it isn't a really universal
+solution. The <a href="http://www.ietf.org/">IETF</a> has begun standardizing syslog over plain tcp over
+TLS for a while now. While I am not fully satisfied with the results so
+far, this obviously has the&nbsp; potential to become the long-term
+solution. The Internet Draft in question, syslog-transport-tls has been
+dormant for some time but is now (May of 2008) again being worked on. I
+expect it to turn into a RFC within the next 12 month (but don't take
+this for granted ;)). I didn't want to wait for it, because there
+obviously is need for TLS syslog right now (and, honestly, I have waited long enough...). Consequently, I have
+implemented the current draft, with some interpretations I made (there
+will be a compliance doc soon). So in essence, a TLS-protected syslog
+transfer mode is available right now. As a side-note, Rsyslog is&nbsp;the world's first
+implementation of syslog-transport-tls.</p>
+<p>Please note that in theory it should be compatible with other,
+non IETF syslog-transport-tls implementations. If you would like to run
+it with something else, please let us know so that we can create a
+compatibility list (and implement compatbility where it doesn't yet
+exist).&nbsp;</p>
+<h2>Overall System Setup</h2>
+<p>Encryption requires a reliable stream. So It will not work
+over UDP syslog. In rsyslog, network transports utilize a so-called
+"network stream layer" (netstream for short). This layer provides a
+unified view of the transport to the application layer. The plain TCP
+syslog sender and receiver are the upper layer. The driver layer
+currently consists of the "ptcp" and "gtls" library plugins. "ptcp"
+stands for "plain tcp" and is used for unencrypted message transfer. It
+is also used internally by the gtls driver, so it must always be
+present on a system. The "gtls" driver is for GnutTLS, a TLS library.
+It is used for encrypted message transfer. In the future, additional
+drivers will become available (most importantly, we would like to
+include a driver for NSS).</p>
+<p>What you need to do to build an encrypted syslog channel is to
+simply use the proper netstream drivers on both the client and the
+server. Client, in the sense of this document, is the rsyslog system
+that is sending syslog messages to a remote (central) loghost, which is
+called the server. In short, the setup is as follows:</p>
+<p><b>Client</b></p>
+<ul>
+<li>forwards messages via plain tcp syslog using gtls netstream
+driver to central sever on port 10514<br>
+</li>
+</ul>
+<p><b>Server</b></p>
+<ul>
+<li>accept incoming messages via plain tcp syslog using gtls
+netstream driver on port 10514</li>
+</ul>
+<h2>Setting up the system</h2>
+<h3>Server Setup</h3>
+<p>At the server, you need to have a digital certificate. That
+certificate enables SSL operation, as it provides the necessary crypto
+keys being used to secure the connection. There is a set of default
+certificates in ./contrib/gnutls. These are key.pem and cert.pem. These
+are&nbsp;good for testing. If you use it in production,
+it is very easy to break into your secure channel as everybody is able
+to get hold of your private key. So it is&nbsp;a good idea to
+generate the key and certificate yourself.</p>
+<p>You also need a root CA certificate. Again, there is a sample
+CA certificate in ./contrib/gnutls, named ca.cert. It is suggested to
+generate your own.</p>
+<p>To configure the server, you need to tell it where are its
+certificate files, to use the gtls driver and start up a listener. This
+is done as follows:<br>
+</p>
+<blockquote><code></code>
+<pre># make gtls driver the default<br>$DefaultNetstreamDriver gtls<br><br># certificate files<br>$DefaultNetstreamDriverCAFile /path/to/contrib/gnutls/ca.pem<br>$DefaultNetstreamDriverCertFile /path/to/contrib/gnutls/cert.pem<br>$DefaultNetstreamDriverKeyFile /path/to/contrib/gnutls/key.pem<br><br>$ModLoad /home/rger/proj/rsyslog/plugins/imtcp/.libs/imtcp # load listener<br><br>$InputTCPServerStreamDriverMode 1 # run driver in TLS-only mode<br>$InputTCPServerRun 10514 # start up listener at port 10514<br></pre>
+</blockquote>
+This is all you need to do. You can use the rest of your rsyslog.conf
+together with this configuration. The way messages are received does
+not interfer with any other option, so you are able to do anything else
+you like without any restrictions.
+<p>Restart (or HUP) rsyslogd. The server should now be fully
+operational.</p>
+<h3>Client Setup</h3>
+<p>The client setup is equally&nbsp;simple. You need less
+certificates, just the CA cert.&nbsp;</p>
+<blockquote>
+<pre># certificate files - just CA for a client<br>$DefaultNetstreamDriverCAFile /path/to/contrib/gnutls/ca.pem<br><br># set up the action<br>$DefaultNetstreamDriver gtls # use gtls netstream driver<br>$ActionSendStreamDriverMode 1 # require TLS for the connection<br>*.* @@(o)server.example.net:10514 # send (all) messages<br><br></pre>
+</blockquote>
+<p>Note that we use the regular TCP forwarding syntax (@@) here.
+There is nothing special, because the encryption is handled by the
+netstream driver. So I have just forwarded every message (*.*) for
+simplicity - you can use any of rsyslog's filtering capabilities (like
+epxression-based filters or regular expressions). Note that the "(o)"
+part is not strictly necessary. It selects octet-based framing, which
+provides compatiblity to IETF's syslog-transport-tls draft. Besides
+compatibility, this is also a more reliable transfer mode, so I suggest
+to always use it.</p>
+<h3>Done</h3>
+<p>After
+following these steps, you should have a working secure
+syslog forwarding system. To verify, you can type "logger test" or a
+similar "smart" command on the client. It should show up in the
+respective server log file. If you dig out your sniffer, you should see
+that the traffic on the wire is actually protected.</p><h3>Limitations</h3>
+<p>The current implementation has a number of limitations. These are
+being worked on. Most importantly, neither the client nor the server
+are authenticated. So while the message transfer is encrypted, you can
+not be sure which peer you are talking to. Please note that this is a
+limitation found in most real-world SSL syslog systems. Of course, that
+is not an excuse for not yet providing this feature - but it tells you
+that it is acceptable and can be worked around by proper firewalling,
+ACLs and other organizational measures. Mutual authentication will be
+added shortly to rsyslog.</p><p>Secondly, the plain tcp syslog listener
+can currently listen to a single port, in a single mode. So if you use
+a TLS-based listener, you can not run unencrypted syslog on the same
+instance at the same time. A work-around is to run a second rsyslogd
+instance. This limitation, too, is scheduled to be removed soon.</p><p>The
+RELP transport can currently not be protected by TLS. A work-around is
+to use stunnel. TLS support for RELP will be added once plain TCP
+syslog has sufficiently matured.</p><h2>Conclusion</h2>
+<p>With minumal effort, you can set up a secure logging
+infrastructure employing TLS encrypted syslog message transmission.</p>
+<h3>Feedback requested</h3>
+<p>I would appreciate feedback on this tutorial. If you have
+additional ideas, comments or find bugs (I *do* bugs - no way... ;)),
+please
+<a href="mailto:rgerhards@adiscon.com">let me know</a>.</p>
+<h2>Revision History</h2>
+<ul>
+<li>2008-05-06 * <a href="http://www.gerhards.net/rainer">Rainer
+Gerhards</a> * Initial Version created</li></ul>
+<h2>Copyright</h2>
+<p>Copyright (c) 2008 <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer
+Gerhards</a> and
+<a href="http://www.adiscon.com/en/">Adiscon</a>.</p>
+<p> Permission is granted to copy, distribute and/or modify this
+document under the terms of the GNU Free Documentation License, Version
+1.2 or any later version published by the Free Software Foundation;
+with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+Texts. A copy of the license can be viewed at
+<a href="http://www.gnu.org/copyleft/fdl.html">http://www.gnu.org/copyleft/fdl.html</a>.</p>
+</body></html> \ No newline at end of file
diff --git a/doc/queueWorkerLogic.dia b/doc/src/queueWorkerLogic.dia
index 068ea50c..068ea50c 100644
--- a/doc/queueWorkerLogic.dia
+++ b/doc/src/queueWorkerLogic.dia
Binary files differ
diff --git a/doc/src/tls.dia b/doc/src/tls.dia
new file mode 100644
index 00000000..77e5d185
--- /dev/null
+++ b/doc/src/tls.dia
Binary files differ
diff --git a/doc/status.html b/doc/status.html
index 63a3f588..3393c68c 100644
--- a/doc/status.html
+++ b/doc/status.html
@@ -2,19 +2,19 @@
<html><head><title>rsyslog status page</title></head>
<body>
<h2>rsyslog status page</h2>
-<p>This page reflects the status as of 2008-04-15.</p>
+<p>This page reflects the status as of 2008-05-07.</p>
<h2>Current Releases</h2>
-<p><b>development:</b> 3.17.1 -
-<a href="http://www.rsyslog.com/Article213.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-98.phtml">download</a>
+<p><b>development:</b> 3.19.1 -
+<a href="http://www.rsyslog.com/Article223.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-103.phtml">download</a>
-<br><b>beta:</b> 3.15.1 -
-<a href="http://www.rsyslog.com/Article210.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-97.phtml">download</a></p>
+<br><b>beta:</b> 3.17.2 -
+<a href="http://www.rsyslog.com/Article220.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-101.phtml">download</a></p>
-<p><b>v3 stable:</b> 3.14.2 - <a href="http://www.rsyslog.com/Article209.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-96.phtml">download</a>
+<p><b>v3 stable:</b> 3.16.1 - <a href="http://www.rsyslog.com/Article218.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-100.phtml">download</a>
<br><b>v2 stable:</b> 2.0.4 - <a href="http://www.rsyslog.com/Article197.phtml">change log</a> -
<a href="http://www.rsyslog.com/Downloads-index-req-getit-lid-90.phtml">download</a>
diff --git a/glbl.h b/glbl.h
deleted file mode 100644
index 6d08ddd5..00000000
--- a/glbl.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Definition of globally-accessible data items.
- *
- * This module provides access methods to items of global scope. Most often,
- * these globals serve as defaults to initialize local settings. Currently,
- * many of them are either constants or global variable references. However,
- * this module provides the necessary hooks to change that at any time.
- *
- * Please note that there currently is no glbl.c file as we do not yet
- * have any implementations.
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- */
-
-#ifndef GLOBALS_H_INCLUDED
-#define GLOBALS_H_INCLUDED
-
-#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)
-
-#endif /* #ifndef GLOBALS_H_INCLUDED */
diff --git a/gss-misc.c b/gss-misc.c
index a80f2e6b..4f0df748 100644
--- a/gss-misc.c
+++ b/gss-misc.c
@@ -41,14 +41,12 @@
#include <fcntl.h>
#endif
#include <gssapi/gssapi.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "syslogd-types.h"
#include "srUtils.h"
#include "net.h"
-#include "omfwd.h"
#include "template.h"
#include "msg.h"
-#include "tcpsyslog.h"
#include "module-template.h"
#include "obj.h"
#include "errmsg.h"
diff --git a/liblogging-stub.h b/liblogging-stub.h
deleted file mode 100644
index 03315f08..00000000
--- a/liblogging-stub.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* This is a (now *very slim*) stub for some liblogging
- * code we use in rsyslog.
- *
- * Copyright (C) 2004, 2007 by 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 <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- */
-#ifndef __LIB3195_LIBLOGGINGSTUB_H_INCLUDED__
-#define __LIB3195_LIBLOGGINGSTUB_H_INCLUDED__ 1
-#include <stdio.h>
-#endif
diff --git a/omfwd.c b/omfwd.c
deleted file mode 100644
index 67ef4b64..00000000
--- a/omfwd.c
+++ /dev/null
@@ -1,644 +0,0 @@
-/* omfwd.c
- * This is the implementation of the build-in forwarding output module.
- *
- * NOTE: read comments in module-template.h to understand how this file
- * works!
- *
- * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
- * This file is under development and has not yet arrived at being fully
- * self-contained and a real object. So far, it is mostly an excerpt
- * of the "old" message code without any modifications. However, it
- * helps to have things at the right place one we go to the meat of it.
- *
- * Copyright 2007 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 <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- */
-#include "config.h"
-#ifdef SYSLOG_INET
-#include "rsyslog.h"
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <fnmatch.h>
-#include <assert.h>
-#include <errno.h>
-#include <ctype.h>
-#include <unistd.h>
-#ifdef USE_NETZIP
-#include <zlib.h>
-#endif
-#include <pthread.h>
-#include "syslogd.h"
-#include "syslogd-types.h"
-#include "srUtils.h"
-#include "net.h"
-#include "omfwd.h"
-#include "template.h"
-#include "msg.h"
-#include "tcpsyslog.h"
-#include "tcpclt.h"
-#include "cfsysline.h"
-#include "module-template.h"
-#include "errmsg.h"
-
-MODULE_TYPE_OUTPUT
-
-/* internal structures
- */
-DEF_OMOD_STATIC_DATA
-DEFobjCurrIf(errmsg)
-DEFobjCurrIf(net)
-DEFobjCurrIf(tcpclt)
-
-typedef struct _instanceData {
- char *f_hname;
- short sock; /* file descriptor */
- int *pSockArray; /* sockets to use for UDP */
- enum { /* TODO: we shoud revisit these definitions */
- eDestFORW,
- eDestFORW_SUSP,
- eDestFORW_UNKN
- } eDestState;
- struct addrinfo *f_addr;
- int compressionLevel; /* 0 - no compression, else level for zlib */
- char *port;
- int protocol;
-# define FORW_UDP 0
-# define FORW_TCP 1
- /* following fields for TCP-based delivery */
- time_t ttSuspend; /* time selector was suspended */
- tcpclt_t *pTCPClt; /* our tcpclt object */
-} instanceData;
-
-/* config data */
-static uchar *pszTplName = NULL; /* name of the default template to use */
-
-
-/* get the syslog forward port from selector_t. The passed in
- * struct must be one that is setup for forwarding.
- * rgerhards, 2007-06-28
- * We may change the implementation to try to lookup the port
- * if it is unspecified. So far, we use the IANA default auf 514.
- */
-static char *getFwdSyslogPt(instanceData *pData)
-{
- assert(pData != NULL);
- if(pData->port == NULL)
- return("514");
- else
- return(pData->port);
-}
-
-BEGINcreateInstance
-CODESTARTcreateInstance
- pData->sock = -1;
-ENDcreateInstance
-
-
-BEGINisCompatibleWithFeature
-CODESTARTisCompatibleWithFeature
- if(eFeat == sFEATURERepeatedMsgReduction)
- iRet = RS_RET_OK;
-ENDisCompatibleWithFeature
-
-
-BEGINfreeInstance
-CODESTARTfreeInstance
- switch (pData->eDestState) {
- case eDestFORW:
- case eDestFORW_SUSP:
- freeaddrinfo(pData->f_addr);
- /* fall through */
- case eDestFORW_UNKN:
- if(pData->port != NULL)
- free(pData->port);
- break;
- }
-
- /* final cleanup */
- if(pData->sock >= 0)
- close(pData->sock);
- if(pData->pSockArray != NULL)
- net.closeUDPListenSockets(pData->pSockArray);
-
- if(pData->protocol == FORW_TCP) {
- tcpclt.Destruct(&pData->pTCPClt);
- }
-
- if(pData->f_hname != NULL)
- free(pData->f_hname);
-
-ENDfreeInstance
-
-
-BEGINdbgPrintInstInfo
-CODESTARTdbgPrintInstInfo
- printf("%s", pData->f_hname);
-ENDdbgPrintInstInfo
-
-
-/* Send a message via UDP
- * rgehards, 2007-12-20
- */
-static rsRetVal UDPSend(instanceData *pData, char *msg, size_t len)
-{
- DEFiRet;
- struct addrinfo *r;
- int i;
- unsigned lsent = 0;
- int bSendSuccess;
-
- if(pData->pSockArray != NULL) {
- /* we need to track if we have success sending to the remote
- * peer. Success is indicated by at least one sendto() call
- * succeeding. We track this be bSendSuccess. We can not simply
- * rely on lsent, as a call might initially work, but a later
- * call fails. Then, lsent has the error status, even though
- * the sendto() succeeded.
- * rgerhards, 2007-06-22
- */
- bSendSuccess = FALSE;
- for (r = pData->f_addr; r; r = r->ai_next) {
- for (i = 0; i < *pData->pSockArray; i++) {
- lsent = sendto(pData->pSockArray[i+1], msg, len, 0, r->ai_addr, r->ai_addrlen);
- if (lsent == len) {
- bSendSuccess = TRUE;
- break;
- } else {
- int eno = errno;
- char errStr[1024];
- dbgprintf("sendto() error: %d = %s.\n",
- eno, rs_strerror_r(eno, errStr, sizeof(errStr)));
- }
- }
- if (lsent == len && !send_to_all)
- break;
- }
- /* finished looping */
- if (bSendSuccess == FALSE) {
- dbgprintf("error forwarding via udp, suspending\n");
- iRet = RS_RET_SUSPENDED;
- }
- }
-
- RETiRet;
-}
-
-/* CODE FOR SENDING TCP MESSAGES */
-
-
-/* Send a frame via plain TCP protocol
- * rgerhards, 2007-12-28
- */
-static rsRetVal TCPSendFrame(void *pvData, char *msg, size_t len)
-{
- DEFiRet;
- ssize_t lenSend;
- instanceData *pData = (instanceData *) pvData;
-
- lenSend = send(pData->sock, msg, len, 0);
- dbgprintf("TCP sent %ld bytes, requested %ld\n", (long) lenSend, (long) len);
-
- if(lenSend == -1) {
- /* we have an error case - check what we can live with */
- switch(errno) {
- case EMSGSIZE:
- dbgprintf("message not (tcp)send, too large\n");
- /* This is not a real error, so it is not flagged as one */
- break;
- default:
- dbgprintf("message not (tcp)send");
- iRet = RS_RET_TCP_SEND_ERROR;
- break;
- }
- } else if(lenSend != (ssize_t) len) {
- /* no real error, could "just" not send everything...
- * For the time being, we ignore this...
- * rgerhards, 2005-10-25
- */
- dbgprintf("message not completely (tcp)send, ignoring %ld\n", (long) lenSend);
- usleep(1000); /* experimental - might be benefitial in this situation */
- /* TODO: we need to revisit this code -- rgerhards, 2007-12-28 */
- }
-
- RETiRet;
-}
-
-
-/* This function is called immediately before a send retry is attempted.
- * It shall clean up whatever makes sense.
- * rgerhards, 2007-12-28
- */
-static rsRetVal TCPSendPrepRetry(void *pvData)
-{
- DEFiRet;
- instanceData *pData = (instanceData *) pvData;
-
- assert(pData != NULL);
- close(pData->sock);
- pData->sock = -1;
- RETiRet;
-}
-
-
-/* initialies everything so that TCPSend can work.
- * rgerhards, 2007-12-28
- */
-static rsRetVal TCPSendInit(void *pvData)
-{
- DEFiRet;
- instanceData *pData = (instanceData *) pvData;
-
- assert(pData != NULL);
- if(pData->sock < 0) {
- if((pData->sock = tcpclt.CreateSocket(pData->f_addr)) < 0)
- iRet = RS_RET_TCP_SOCKCREATE_ERR;
- }
-
- RETiRet;
-}
-
-
-/* try to resume connection if it is not ready
- * rgerhards, 2007-08-02
- */
-static rsRetVal doTryResume(instanceData *pData)
-{
- DEFiRet;
- struct addrinfo *res;
- struct addrinfo hints;
- unsigned e;
-
- switch (pData->eDestState) {
- case eDestFORW_SUSP:
- iRet = RS_RET_OK; /* the actual check happens during doAction() only */
- pData->eDestState = eDestFORW;
- break;
-
- case eDestFORW_UNKN:
- /* The remote address is not yet known and needs to be obtained */
- dbgprintf(" %s\n", pData->f_hname);
- memset(&hints, 0, sizeof(hints));
- /* port must be numeric, because config file syntax requests this */
- /* TODO: this code is a duplicate from cfline() - we should later create
- * a common function.
- */
- hints.ai_flags = AI_NUMERICSERV;
- hints.ai_family = family;
- hints.ai_socktype = pData->protocol == FORW_UDP ? SOCK_DGRAM : SOCK_STREAM;
- if((e = getaddrinfo(pData->f_hname,
- getFwdSyslogPt(pData), &hints, &res)) == 0) {
- dbgprintf("%s found, resuming.\n", pData->f_hname);
- pData->f_addr = res;
- pData->eDestState = eDestFORW;
- } else {
- iRet = RS_RET_SUSPENDED;
- }
- break;
- case eDestFORW:
- /* rgerhards, 2007-09-11: this can not happen, but I've included it to
- * a) make the compiler happy, b) detect any logic errors */
- assert(0);
- break;
- }
-
- RETiRet;
-}
-
-
-BEGINtryResume
-CODESTARTtryResume
- iRet = doTryResume(pData);
-ENDtryResume
-
-BEGINdoAction
- char *psz; /* temporary buffering */
- register unsigned l;
-CODESTARTdoAction
- switch (pData->eDestState) {
- case eDestFORW_SUSP:
- dbgprintf("internal error in omfwd.c, eDestFORW_SUSP in doAction()!\n");
- iRet = RS_RET_SUSPENDED;
- break;
-
- case eDestFORW_UNKN:
- dbgprintf("doAction eDestFORW_UNKN\n");
- iRet = doTryResume(pData);
- break;
-
- case eDestFORW:
- dbgprintf(" %s:%s/%s\n", pData->f_hname, getFwdSyslogPt(pData),
- pData->protocol == FORW_UDP ? "udp" : "tcp");
- /* with UDP, check if the socket is there and, if not, alloc
- * it. TODO: there should be a better place for that code.
- * rgerhards, 2007-12-26
- */
- if(pData->protocol == FORW_UDP) {
- if(pData->pSockArray == NULL) {
- pData->pSockArray = net.create_udp_socket((uchar*)pData->f_hname, NULL, 0);
- }
- }
- pData->ttSuspend = time(NULL);
- psz = (char*) ppString[0];
- l = strlen((char*) psz);
- if (l > MAXLINE)
- l = MAXLINE;
-
-# ifdef USE_NETZIP
- /* Check if we should compress and, if so, do it. We also
- * check if the message is large enough to justify compression.
- * The smaller the message, the less likely is a gain in compression.
- * To save CPU cycles, we do not try to compress very small messages.
- * What "very small" means needs to be configured. Currently, it is
- * hard-coded but this may be changed to a config parameter.
- * rgerhards, 2006-11-30
- */
- if(pData->compressionLevel && (l > MIN_SIZE_FOR_COMPRESS)) {
- Bytef out[MAXLINE+MAXLINE/100+12] = "z";
- uLongf destLen = sizeof(out) / sizeof(Bytef);
- uLong srcLen = l;
- int ret;
- ret = compress2((Bytef*) out+1, &destLen, (Bytef*) psz,
- srcLen, pData->compressionLevel);
- dbgprintf("Compressing message, length was %d now %d, return state %d.\n",
- l, (int) destLen, ret);
- if(ret != Z_OK) {
- /* if we fail, we complain, but only in debug mode
- * Otherwise, we are silent. In any case, we ignore the
- * failed compression and just sent the uncompressed
- * data, which is still valid. So this is probably the
- * best course of action.
- * rgerhards, 2006-11-30
- */
- dbgprintf("Compression failed, sending uncompressed message\n");
- } else if(destLen+1 < l) {
- /* only use compression if there is a gain in using it! */
- dbgprintf("there is gain in compression, so we do it\n");
- psz = (char*) out;
- l = destLen + 1; /* take care for the "z" at message start! */
- }
- ++destLen;
- }
-# endif
-
- if(pData->protocol == FORW_UDP) {
- /* forward via UDP */
- CHKiRet(UDPSend(pData, psz, l));
- } else {
- /* forward via TCP */
- rsRetVal ret;
- ret = tcpclt.Send(pData->pTCPClt, pData, psz, l);
- if(ret != RS_RET_OK) {
- /* error! */
- dbgprintf("error forwarding via tcp, suspending\n");
- pData->eDestState = eDestFORW_SUSP;
- iRet = RS_RET_SUSPENDED;
- }
- }
- break;
- }
-finalize_it:
-ENDdoAction
-
-
-BEGINparseSelectorAct
- uchar *q;
- int i;
- int error;
- int bErr;
- struct addrinfo hints, *res;
- TCPFRAMINGMODE tcp_framing = TCP_FRAMING_OCTET_STUFFING;
-CODESTARTparseSelectorAct
-CODE_STD_STRING_REQUESTparseSelectorAct(1)
- if(*p == '@') {
- if((iRet = createInstance(&pData)) != RS_RET_OK)
- goto finalize_it;
- ++p; /* eat '@' */
- if(*p == '@') { /* indicator for TCP! */
- pData->protocol = FORW_TCP;
- ++p; /* eat this '@', too */
- } else {
- pData->protocol = FORW_UDP;
- }
- /* we are now after the protocol indicator. Now check if we should
- * use compression. We begin to use a new option format for this:
- * @(option,option)host:port
- * The first option defined is "z[0..9]" where the digit indicates
- * the compression level. If it is not given, 9 (best compression) is
- * assumed. An example action statement might be:
- * @@(z5,o)127.0.0.1:1400
- * Which means send via TCP with medium (5) compresion (z) to the local
- * host on port 1400. The '0' option means that octet-couting (as in
- * IETF I-D syslog-transport-tls) is to be used for framing (this option
- * applies to TCP-based syslog only and is ignored when specified with UDP).
- * That is not yet implemented.
- * rgerhards, 2006-12-07
- */
- if(*p == '(') {
- /* at this position, it *must* be an option indicator */
- do {
- ++p; /* eat '(' or ',' (depending on when called) */
- /* check options */
- if(*p == 'z') { /* compression */
-# ifdef USE_NETZIP
- ++p; /* eat */
- if(isdigit((int) *p)) {
- int iLevel;
- iLevel = *p - '0';
- ++p; /* eat */
- pData->compressionLevel = iLevel;
- } else {
- errmsg.LogError(NO_ERRCODE, "Invalid compression level '%c' specified in "
- "forwardig action - NOT turning on compression.",
- *p);
- }
-# else
- errmsg.LogError(NO_ERRCODE, "Compression requested, but rsyslogd is not compiled "
- "with compression support - request ignored.");
-# endif /* #ifdef USE_NETZIP */
- } else if(*p == 'o') { /* octet-couting based TCP framing? */
- ++p; /* eat */
- /* no further options settable */
- tcp_framing = TCP_FRAMING_OCTET_COUNTING;
- } else { /* invalid option! Just skip it... */
- errmsg.LogError(NO_ERRCODE, "Invalid option %c in forwarding action - ignoring.", *p);
- ++p; /* eat invalid option */
- }
- /* the option processing is done. We now do a generic skip
- * to either the next option or the end of the option
- * block.
- */
- while(*p && *p != ')' && *p != ',')
- ++p; /* just skip it */
- } while(*p && *p == ','); /* Attention: do.. while() */
- if(*p == ')')
- ++p; /* eat terminator, on to next */
- else
- /* we probably have end of string - leave it for the rest
- * of the code to handle it (but warn the user)
- */
- errmsg.LogError(NO_ERRCODE, "Option block not terminated in forwarding action.");
- }
- /* extract the host first (we do a trick - we replace the ';' or ':' with a '\0')
- * now skip to port and then template name. rgerhards 2005-07-06
- */
- for(q = p ; *p && *p != ';' && *p != ':' ; ++p)
- /* JUST SKIP */;
-
- pData->port = NULL;
- if(*p == ':') { /* process port */
- uchar * tmp;
-
- *p = '\0'; /* trick to obtain hostname (later)! */
- tmp = ++p;
- for(i=0 ; *p && isdigit((int) *p) ; ++p, ++i)
- /* SKIP AND COUNT */;
- pData->port = malloc(i + 1);
- if(pData->port == NULL) {
- errmsg.LogError(NO_ERRCODE, "Could not get memory to store syslog forwarding port, "
- "using default port, results may not be what you intend\n");
- /* we leave f_forw.port set to NULL, this is then handled by
- * getFwdSyslogPt().
- */
- } else {
- memcpy(pData->port, tmp, i);
- *(pData->port + i) = '\0';
- }
- }
-
- /* now skip to template */
- bErr = 0;
- while(*p && *p != ';') {
- if(*p && *p != ';' && !isspace((int) *p)) {
- if(bErr == 0) { /* only 1 error msg! */
- bErr = 1;
- errno = 0;
- errmsg.LogError(NO_ERRCODE, "invalid selector line (port), probably not doing "
- "what was intended");
- }
- }
- ++p;
- }
-
- /* TODO: make this if go away! */
- if(*p == ';') {
- *p = '\0'; /* trick to obtain hostname (later)! */
- CHKmalloc(pData->f_hname = strdup((char*) q));
- *p = ';';
- } else {
- CHKmalloc(pData->f_hname = strdup((char*) q));
- }
-
- /* process template */
- CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
- (pszTplName == NULL) ? (uchar*)"RSYSLOG_TraditionalForwardFormat" : pszTplName));
-
- /* first set the pData->eDestState */
- memset(&hints, 0, sizeof(hints));
- /* port must be numeric, because config file syntax requests this */
- hints.ai_flags = AI_NUMERICSERV;
- hints.ai_family = family;
- hints.ai_socktype = pData->protocol == FORW_UDP ? SOCK_DGRAM : SOCK_STREAM;
- if( (error = getaddrinfo(pData->f_hname, getFwdSyslogPt(pData), &hints, &res)) != 0) {
- pData->eDestState = eDestFORW_UNKN;
- pData->ttSuspend = time(NULL);
- } else {
- pData->eDestState = eDestFORW;
- pData->f_addr = res;
- }
- /*
- * Otherwise the host might be unknown due to an
- * inaccessible nameserver (perhaps on the same
- * host). We try to get the ip number later, like
- * FORW_SUSP.
- */
- if(pData->protocol == FORW_TCP) {
- /* create our tcpclt */
- CHKiRet(tcpclt.Construct(&pData->pTCPClt));
- /* and set callbacks */
- CHKiRet(tcpclt.SetSendInit(pData->pTCPClt, TCPSendInit));
- CHKiRet(tcpclt.SetSendFrame(pData->pTCPClt, TCPSendFrame));
- CHKiRet(tcpclt.SetSendPrepRetry(pData->pTCPClt, TCPSendPrepRetry));
- CHKiRet(tcpclt.SetFraming(pData->pTCPClt, tcp_framing));
- }
-
- } else {
- iRet = RS_RET_CONFLINE_UNPROCESSED;
- }
-
- /* TODO: do we need to call freeInstance if we failed - this is a general question for
- * all output modules. I'll address it lates as the interface evolves. rgerhards, 2007-07-25
- */
-CODE_STD_FINALIZERparseSelectorAct
-ENDparseSelectorAct
-
-
-BEGINmodExit
-CODESTARTmodExit
- /* release what we no longer need */
- objRelease(errmsg, CORE_COMPONENT);
- objRelease(net, LM_NET_FILENAME);
- objRelease(tcpclt, LM_TCPCLT_FILENAME);
-
- if(pszTplName != NULL) {
- free(pszTplName);
- pszTplName = NULL;
- }
-ENDmodExit
-
-
-BEGINqueryEtryPt
-CODESTARTqueryEtryPt
-CODEqueryEtryPt_STD_OMOD_QUERIES
-ENDqueryEtryPt
-
-
-/* Reset config variables for this module to default values.
- * rgerhards, 2008-03-28
- */
-static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
-{
- if(pszTplName != NULL) {
- free(pszTplName);
- pszTplName = NULL;
- }
-
- return RS_RET_OK;
-}
-
-
-BEGINmodInit(Fwd)
-CODESTARTmodInit
- *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
-CODEmodInit_QueryRegCFSLineHdlr
- CHKiRet(objUse(errmsg, CORE_COMPONENT));
- CHKiRet(objUse(net, LM_NET_FILENAME));
- CHKiRet(objUse(tcpclt, LM_TCPCLT_FILENAME));
-
- CHKiRet(regCfSysLineHdlr((uchar *)"actionforwarddefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszTplName, NULL));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
-ENDmodInit
-
-#endif /* #ifdef SYSLOG_INET */
-/* vim:set ai:
- */
diff --git a/outchannel.c b/outchannel.c
index d013ea08..5c348b63 100644
--- a/outchannel.c
+++ b/outchannel.c
@@ -37,7 +37,7 @@
#include <assert.h>
#include "stringbuf.h"
#include "outchannel.h"
-#include "syslogd.h"
+#include "dirty.h"
static struct outchannel *ochRoot = NULL; /* the root of the outchannel list */
static struct outchannel *ochLast = NULL; /* points to the last element of the outchannel list */
diff --git a/parse.c b/parse.c
index 171e5355..58458d62 100644
--- a/parse.c
+++ b/parse.c
@@ -3,7 +3,7 @@
*
* begun 2005-09-15 rgerhards
*
- * Copyright 2005
+ * Copyright 2005-2008
* Rainer Gerhards and Adiscon GmbH. All Rights Reserved.
*
* This file is part of rsyslog.
diff --git a/parse.h b/parse.h
index b7ac950d..0fe2bb74 100644
--- a/parse.h
+++ b/parse.h
@@ -101,24 +101,9 @@ int parsIsAtEndOfParseString(rsParsObj *pThis);
int parsGetCurrentPosition(rsParsObj *pThis);
char parsPeekAtCharAtParsPtr(rsParsObj *pThis);
#ifdef SYSLOG_INET
-rsRetVal parsAddrWithBits(rsParsObj *pThis, struct NetAddr **pIP, int *pBits);
-#endif
-
-#if 0 /* later! - but leave it in in case we need it some day... */
-/* Parse a property
- * This is a complex parsing routine. It parses an property
- * entry suitable for use in the property replacer. It is currently
- * just an idea if this should be a parser function.
- */
-parsRet parsProp(parseObj *pThis, ?? **pPropEtry);
+rsRetVal parsAddrWithBits(rsParsObj *pThis, netAddr_t **pIP, int *pBits);
#endif
#endif
-/*
- * Local variables:
- * c-indent-level: 8
- * c-basic-offset: 8
- * tab-width: 8
- * End:
- * vi:set ai:
+/* vim:set ai:
*/
diff --git a/plugins/im3195/Makefile.am b/plugins/im3195/Makefile.am
new file mode 100644
index 00000000..bfceb71e
--- /dev/null
+++ b/plugins/im3195/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = im3195.la
+
+im3195_la_SOURCES = im3195.c
+im3195_la_CPPFLAGS = $(rsrt_cflags) $(pthreads_cflags) $(LIBLOGGING_CFLAGS)
+im3195_la_LDFLAGS = -module -avoid-version
+im3195_la_LIBADD = $(LIBLOGGING_LIBS)
+
+EXTRA_DIST =
diff --git a/plugins/im3195/im3195.c b/plugins/im3195/im3195.c
new file mode 100644
index 00000000..d9c220b2
--- /dev/null
+++ b/plugins/im3195/im3195.c
@@ -0,0 +1,167 @@
+/**
+ * The rfc3195 input module.
+ *
+ * Please note that this file replaces the rfc3195d daemon that was
+ * also present in pre-v3 versions of rsyslog.
+ *
+ * WARNING: due to no demand at all for RFC3195, we have converted rfc3195d
+ * to this input module, but we have NOT conducted any testing. Also,
+ * the module does not yet properly handle the recovery case. If someone
+ * intends to put this module into production, good testing should be
+ * made and it also is a good idea to notify me that you intend to use
+ * it in production. In this case, I'll probably give the module another
+ * cleanup. I don't do this now because so far it looks just like a big
+ * waste of time. -- rgerhards, 2008-04-16
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ *
+ * Copyright 2003-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 <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/errno.h>
+#include <assert.h>
+#include "rsyslog.h"
+#include "dirty.h"
+#include "liblogging/liblogging.h"
+#include "liblogging/srAPI.h"
+#include "liblogging/syslogmessage.h"
+#include "module-template.h"
+#include "cfsysline.h"
+#include "errmsg.h"
+
+MODULE_TYPE_INPUT
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(errmsg)
+
+/* configuration settings */
+static int listenPort = 601;
+
+/* we use a global API object below, because this listener is
+ * not very complex. As such, this hack should not harm anything.
+ * rgerhards, 2005-10-12
+ */
+static srAPIObj* pAPI;
+
+
+/* This method is called when a message has been fully received.
+ * It passes the received message to the rsyslog main message
+ * queue. Please note that this callback is synchronous, thus
+ * liblogging will be on hold until it returns. This is important
+ * to note because in an error case we might stay in this code
+ * for an extended amount of time. So far, we think this is the
+ * best solution, but real-world experience might tell us a
+ * different truth ;)
+ */
+void OnReceive(srAPIObj __attribute__((unused)) *pMyAPI, srSLMGObj* pSLMG)
+{
+ uchar *pszRawMsg;
+ uchar *fromHost = (uchar*) "[unset]"; /* TODO: get hostname */
+ uchar *fromHostIP = (uchar*) "[unset]"; /* TODO: get hostname */
+
+ srSLMGGetRawMSG(pSLMG, &pszRawMsg);
+
+ parseAndSubmitMessage(fromHost, fromHostIP, pszRawMsg, strlen((char*)pszRawMsg),
+ MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_FULL_DELAY);
+}
+
+
+BEGINrunInput
+CODESTARTrunInput
+ /* this is an endless loop - it is terminated when the thread is
+ * signalled to do so. This, however, is handled by the framework,
+ * right into the sleep below.
+ */
+ while(!pThrd->bShallStop) {
+ /* now move the listener to running state. Control will only
+ * return after SIGUSR1.
+ */
+ if((iRet = srAPIRunListener(pAPI)) != SR_RET_OK) {
+ errmsg.LogError(NO_ERRCODE, "error %d running liblogging listener - im3195 is defunct", iRet);
+ FINALIZE; /* this causes im3195 to become defunct; TODO: recovery handling */
+ }
+ }
+finalize_it:
+ENDrunInput
+
+
+BEGINwillRun
+CODESTARTwillRun
+ if((pAPI = srAPIInitLib()) == NULL) {
+ errmsg.LogError(NO_ERRCODE, "error initializing liblogging - im3195 is defunct");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if((iRet = srAPISetOption(pAPI, srOPTION_BEEP_LISTENPORT, listenPort)) != SR_RET_OK) {
+ errmsg.LogError(NO_ERRCODE, "error %d setting liblogging listen port - im3195 is defunct", iRet);
+ FINALIZE;
+ }
+
+ if((iRet = srAPISetupListener(pAPI, OnReceive)) != SR_RET_OK) {
+ errmsg.LogError(NO_ERRCODE, "error %d setting up liblogging listener - im3195 is defunct", iRet);
+ FINALIZE;
+ }
+
+finalize_it:
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ dbgprintf("Shutting down rfc3195d. Be patient, this can take up to 30 seconds...\n");
+ srAPIShutdownListener(pAPI);
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ srAPIExitLib(pAPI); /* terminate liblogging */
+ /* release objects we used */
+ objRelease(errmsg, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+ENDqueryEtryPt
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ listenPort = 601;
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"input3195listenport", 0, eCmdHdlrInt, NULL, &listenPort, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+/* vim:set ai:
+ */
diff --git a/plugins/imfile/Makefile.am b/plugins/imfile/Makefile.am
index 23b64d1b..a4011d12 100644
--- a/plugins/imfile/Makefile.am
+++ b/plugins/imfile/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = imfile.la
imfile_la_SOURCES = imfile.c
-imfile_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+imfile_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
imfile_la_LDFLAGS = -module -avoid-version
imfile_la_LIBADD =
diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
index 75e54f04..a5f1cc8f 100644
--- a/plugins/imfile/imfile.c
+++ b/plugins/imfile/imfile.c
@@ -36,13 +36,14 @@
# include <sys/stat.h>
#endif
#include "rsyslog.h" /* error codes etc... */
-#include "syslogd.h"
+#include "dirty.h"
#include "cfsysline.h" /* access to config file objects */
#include "module-template.h" /* generic module interface code - very important, read it! */
#include "srUtils.h" /* some utility functions */
#include "msg.h"
#include "stream.h"
#include "errmsg.h"
+#include "glbl.h"
#include "datetime.h"
MODULE_TYPE_INPUT /* must be present for input modules, do not remove */
@@ -52,6 +53,7 @@ MODULE_TYPE_INPUT /* must be present for input modules, do not remove */
/* Module static data */
DEF_IMOD_STATIC_DATA /* must be present, starts static data */
DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
DEFobjCurrIf(datetime)
typedef struct fileInfo_s {
@@ -95,7 +97,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, (char*)LocalHostName);
+ MsgSetHOSTNAME(pMsg, (char*)glbl.GetLocalHostName());
MsgSetTAG(pMsg, (char*)pInfo->pszTag);
pMsg->iFacility = LOG_FAC(pInfo->iFacility);
pMsg->iSeverity = LOG_PRI(pInfo->iSeverity);
@@ -121,7 +123,7 @@ openFile(fileInfo_t *pThis)
/* Construct file name */
lenSFNam = snprintf((char*)pszSFNam, sizeof(pszSFNam) / sizeof(uchar), "%s/%s",
- (char*) glblGetWorkDir(), (char*)pThis->pszStateFile);
+ (char*) glbl.GetWorkDir(), (char*)pThis->pszStateFile);
/* check if the file exists */
if(stat((char*) pszSFNam, &stat_buf) == -1) {
@@ -334,7 +336,7 @@ persistStrmState(fileInfo_t *pInfo)
/* TODO: create a function persistObj in obj.c? */
CHKiRet(strmConstruct(&psSF));
- CHKiRet(strmSetDir(psSF, glblGetWorkDir(), strlen((char*)glblGetWorkDir())));
+ CHKiRet(strmSetDir(psSF, glbl.GetWorkDir(), strlen((char*)glbl.GetWorkDir())));
CHKiRet(strmSettOperationsMode(psSF, STREAMMODE_WRITE));
CHKiRet(strmSetiAddtlOpenFlags(psSF, O_TRUNC));
CHKiRet(strmSetsType(psSF, STREAMTYPE_FILE_SINGLE));
@@ -381,6 +383,7 @@ BEGINmodExit
CODESTARTmodExit
/* release objects we used */
objRelease(datetime, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
ENDmodExit
@@ -488,6 +491,7 @@ CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
CHKiRet(objUse(datetime, CORE_COMPONENT));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord,
diff --git a/plugins/imgssapi/Makefile.am b/plugins/imgssapi/Makefile.am
index 42a243f4..a5cce320 100644
--- a/plugins/imgssapi/Makefile.am
+++ b/plugins/imgssapi/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = imgssapi.la
imgssapi_la_SOURCES = imgssapi.c
-imgssapi_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+imgssapi_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
imgssapi_la_LDFLAGS = -module -avoid-version
imgssapi_la_LIBADD = $(gss_libs)
diff --git a/plugins/imgssapi/imgssapi.c b/plugins/imgssapi/imgssapi.c
index 74d5d5c5..48cc99a2 100644
--- a/plugins/imgssapi/imgssapi.c
+++ b/plugins/imgssapi/imgssapi.c
@@ -45,7 +45,7 @@
#endif
#include <gssapi/gssapi.h>
#include "rsyslog.h"
-#include "syslogd.h"
+#include "dirty.h"
#include "cfsysline.h"
#include "module-template.h"
#include "net.h"
@@ -54,6 +54,7 @@
#include "tcpsrv.h"
#include "tcps_sess.h"
#include "errmsg.h"
+#include "netstrm.h"
MODULE_TYPE_INPUT
@@ -77,6 +78,7 @@ DEFobjCurrIf(tcpsrv)
DEFobjCurrIf(tcps_sess)
DEFobjCurrIf(gssutil)
DEFobjCurrIf(errmsg)
+DEFobjCurrIf(netstrm)
DEFobjCurrIf(net)
static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change for multiple instances */
@@ -241,11 +243,12 @@ onErrClose(tcps_sess_t *pSess)
/* open the listen sockets */
-static int*
+static rsRetVal
doOpenLstnSocks(tcpsrv_t *pSrv)
{
int *pRet = NULL;
gsssrv_t *pGSrv;
+ DEFiRet;
ISOBJ_TYPE_assert(pSrv, tcpsrv);
pGSrv = pSrv->pUsr;
@@ -261,20 +264,20 @@ doOpenLstnSocks(tcpsrv_t *pSrv)
}
if(pGSrv->allowedMethods) {
/* fallback to plain TCP */
- if((pRet = tcpsrv.create_tcp_socket(pSrv)) != NULL) {
- dbgprintf("Opened %d syslog TCP port(s).\n", *pRet);
- }
+ CHKiRet(tcpsrv.create_tcp_socket(pSrv));
+ dbgprintf("Opened %d syslog TCP port(s).\n", *pRet);
}
}
- return pRet;
+finalize_it:
+ RETiRet;
}
static int
doRcvData(tcps_sess_t *pSess, char *buf, size_t lenBuf)
{
- int state;
+ ssize_t state;
int allowedMethods;
gss_sess_t *pGSess;
@@ -285,8 +288,10 @@ doRcvData(tcps_sess_t *pSess, char *buf, size_t lenBuf)
allowedMethods = pGSess->allowedMethods;
if(allowedMethods & ALLOWEDMETHOD_GSS)
state = TCPSessGSSRecv(pSess, buf, lenBuf);
- else
- state = recv(pSess->sock, buf, lenBuf, 0);
+ else {
+ if(netstrm.Rcv(pSess->pStrm, (uchar*) buf, &state) != RS_RET_OK)
+ state = -1; // TODO: move this function to an iRet interface! 2008-05-05
+ }
return state;
}
@@ -391,7 +396,7 @@ OnSessAcceptGSS(tcpsrv_t *pThis, tcps_sess_t *pSess)
dbgprintf("GSS-API Trying to accept TCP session %p\n", pSess);
- fdSess = pSess->sock; // TODO: method access!
+ CHKiRet(netstrm.GetSock(pSess->pStrm, &fdSess)); // TODO: method access!
if (allowedMethods & ALLOWEDMETHOD_TCP) {
int len;
fd_set fds;
@@ -537,7 +542,7 @@ int TCPSessGSSRecv(tcps_sess_t *pSess, void *buf, size_t buf_len)
assert(pSess->pUsr != NULL);
pGSess = (gss_sess_t*) pSess->pUsr;
- fdSess = pSess->sock;
+ netstrm.GetSock(pSess->pStrm, &fdSess); // TODO: method access, CHKiRet!
if ((state = gssutil.recv_token(fdSess, &xmit_buf)) <= 0)
return state;
@@ -638,6 +643,7 @@ CODESTARTmodExit
objRelease(tcpsrv, LM_TCPSRV_FILENAME);
objRelease(gssutil, LM_GSSUTIL_FILENAME);
objRelease(errmsg, CORE_COMPONENT);
+ objRelease(netstrm, LM_NETSTRM_FILENAME);
objRelease(net, LM_NET_FILENAME);
ENDmodExit
@@ -684,6 +690,7 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(tcpsrv, LM_TCPSRV_FILENAME));
CHKiRet(objUse(gssutil, LM_GSSUTIL_FILENAME));
CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(netstrm, LM_NETSTRM_FILENAME));
CHKiRet(objUse(net, LM_NET_FILENAME));
/* register config file handlers */
diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am
index 246b3306..8f50cfb2 100644
--- a/plugins/imklog/Makefile.am
+++ b/plugins/imklog/Makefile.am
@@ -11,6 +11,6 @@ if ENABLE_IMKLOG_LINUX
imklog_la_SOURCES += linux.c module.h ksym.c ksyms.h ksym_mod.c
endif
-imklog_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+imklog_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
imklog_la_LDFLAGS = -module -avoid-version
imklog_la_LIBADD =
diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c
index c6fb1592..5bd99d9e 100644
--- a/plugins/imklog/imklog.c
+++ b/plugins/imklog/imklog.c
@@ -45,21 +45,23 @@
#include <stdarg.h>
#include <ctype.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "cfsysline.h"
#include "obj.h"
#include "msg.h"
#include "module-template.h"
#include "datetime.h"
#include "imklog.h"
+#include "glbl.h"
MODULE_TYPE_INPUT
/* Module static data */
DEF_IMOD_STATIC_DATA
DEFobjCurrIf(datetime)
+DEFobjCurrIf(glbl)
-/* configuration settings TODO: move to instance data? */
+/* configuration settings */
int dbgPrintSymbols = 0; /* this one is extern so the helpers can access it! */
int symbols_twice = 0;
int use_syscall = 0;
@@ -95,7 +97,9 @@ enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity)
MsgSetUxTradMsg(pMsg, (char*)msg);
MsgSetRawMsg(pMsg, (char*)msg);
MsgSetMSG(pMsg, (char*)msg);
- MsgSetHOSTNAME(pMsg, (char*)LocalHostName);
+ MsgSetRcvFrom(pMsg, (char*)glbl.GetLocalHostName());
+ MsgSetRcvFromIP(pMsg, (uchar*)"127.0.0.1");
+ MsgSetHOSTNAME(pMsg, (char*)glbl.GetLocalHostName());
MsgSetTAG(pMsg, (char*)pszTag);
pMsg->iFacility = LOG_FAC(iFacility);
pMsg->iSeverity = LOG_PRI(iSeverity);
@@ -225,6 +229,7 @@ ENDafterRun
BEGINmodExit
CODESTARTmodExit
/* release objects we used */
+ objRelease(glbl, CORE_COMPONENT);
objRelease(datetime, CORE_COMPONENT);
ENDmodExit
@@ -251,6 +256,7 @@ CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
iFacilIntMsg = klogFacilIntMsg();
diff --git a/plugins/imklog/imklog.h b/plugins/imklog/imklog.h
index a37ecc9e..0847140b 100644
--- a/plugins/imklog/imklog.h
+++ b/plugins/imklog/imklog.h
@@ -28,7 +28,7 @@
#define IMKLOG_H_INCLUDED 1
#include "rsyslog.h"
-#include "syslogd.h"
+#include "dirty.h"
/* interface to "drivers"
* the platform specific drivers must implement these entry points. Only one
diff --git a/plugins/imklog/linux.c b/plugins/imklog/linux.c
index 31dae2cd..853c8b2c 100644
--- a/plugins/imklog/linux.c
+++ b/plugins/imklog/linux.c
@@ -32,7 +32,6 @@
#include <signal.h>
#include <string.h>
#include <pthread.h>
-#include "syslogd.h"
#include "cfsysline.h"
#include "template.h"
#include "msg.h"
@@ -147,9 +146,7 @@ static enum LOGSRC GetKernelLogSrc(void)
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);
+ imklogLogIntMsg(LOG_ERR, "imklog: Cannot open proc file system, %d.\n", errno);
ksyslog(7, NULL, 0); /* TODO: check this, implement more */
return(none);
}
@@ -428,11 +425,9 @@ static void LogKernelLine(void)
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);
+ imklogLogIntMsg(LOG_ERR, "imklog Error return from sys_sycall: %d\n", errno);
}
else
LogLine(log_buffer, rdcnt);
@@ -504,7 +499,7 @@ rsRetVal klogWillRun(void)
symbol_lookup = (InitKsyms(symfile) == 1);
symbol_lookup |= InitMsyms();
if (symbol_lookup == 0) {
- //dbgprintf("cannot find any symbols, turning off symbol lookups\n");
+ dbgprintf("cannot find any symbols, turning off symbol lookups\n");
imklogLogIntMsg(LOG_WARNING, "cannot find any symbols, turning off symbol lookups");
}
}
diff --git a/plugins/immark/Makefile.am b/plugins/immark/Makefile.am
index 3dc0e408..9c0f8f64 100644
--- a/plugins/immark/Makefile.am
+++ b/plugins/immark/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = immark.la
immark_la_SOURCES = immark.c immark.h
-immark_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+immark_la_CPPFLAGS = $(rsrt_cflags) -I$(top_srcdir) $(pthreads_cflags)
immark_la_LDFLAGS = -module -avoid-version
immark_la_LIBADD =
diff --git a/plugins/immark/immark.c b/plugins/immark/immark.c
index 30118de0..ebdcabe9 100644
--- a/plugins/immark/immark.c
+++ b/plugins/immark/immark.c
@@ -37,7 +37,7 @@
#include <signal.h>
#include <string.h>
#include <pthread.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "cfsysline.h"
#include "module-template.h"
@@ -75,7 +75,7 @@ CODESTARTrunInput
* rgerhards, 2007-12-17
*/
CHKiRet(thrdSleep(pThrd, iMarkMessagePeriod, 0)); /* seconds, micro seconds */
- logmsgInternal(LOG_INFO, "-- MARK --", ADDDATE|MARK);
+ logmsgInternal(LOG_INFO, (uchar*)"-- MARK --", ADDDATE|MARK);
}
finalize_it:
return iRet;
diff --git a/plugins/imrelp/Makefile.am b/plugins/imrelp/Makefile.am
index 53c9322c..a96e2b42 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) $(rsrt_cflags)
imrelp_la_LDFLAGS = -module -avoid-version
imrelp_la_LIBADD = $(RELP_LIBS)
diff --git a/plugins/imrelp/imrelp.c b/plugins/imrelp/imrelp.c
index b7308016..5c9bbce1 100644
--- a/plugins/imrelp/imrelp.c
+++ b/plugins/imrelp/imrelp.c
@@ -38,7 +38,7 @@
#include <sys/socket.h>
#include <librelp.h>
#include "rsyslog.h"
-#include "syslogd.h"
+#include "dirty.h"
#include "cfsysline.h"
#include "module-template.h"
#include "net.h"
@@ -76,12 +76,14 @@ isPermittedHost(struct sockaddr *addr, char *fromHostFQDN, void __attribute__((u
* are different from our rsRetVal. So we can simply use our own iRet system
* to fulfill the requirement.
* rgerhards, 2008-03-21
+ * TODO: we currently do not receive the remote hosts's IP. As a work-around, we
+ * use "???" for the time being. -- rgerhards, 2008-05-16
*/
static relpRetVal
onSyslogRcv(uchar *pHostname, uchar __attribute__((unused)) *pIP, uchar *pMsg, size_t lenMsg)
{
DEFiRet;
- parseAndSubmitMessage((char*)pHostname, (char*)pMsg, lenMsg, MSG_PARSE_HOSTNAME,
+ parseAndSubmitMessage(pHostname, (uchar*) "[unset]", pMsg, lenMsg, MSG_PARSE_HOSTNAME,
NOFLAG, eFLOWCTL_LIGHT_DELAY);
RETiRet;
diff --git a/plugins/imtcp/Makefile.am b/plugins/imtcp/Makefile.am
index fe43cd98..de746a95 100644
--- a/plugins/imtcp/Makefile.am
+++ b/plugins/imtcp/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = imtcp.la
imtcp_la_SOURCES = imtcp.c
-imtcp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+imtcp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
imtcp_la_LDFLAGS = -module -avoid-version
imtcp_la_LIBADD =
diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c
index 7baa95f2..971d3aec 100644
--- a/plugins/imtcp/imtcp.c
+++ b/plugins/imtcp/imtcp.c
@@ -39,10 +39,12 @@
#include <fcntl.h>
#endif
#include "rsyslog.h"
-#include "syslogd.h"
+#include "dirty.h"
#include "cfsysline.h"
#include "module-template.h"
#include "net.h"
+#include "netstrm.h"
+#include "errmsg.h"
#include "tcpsrv.h"
MODULE_TYPE_INPUT
@@ -52,12 +54,15 @@ DEF_IMOD_STATIC_DATA
DEFobjCurrIf(tcpsrv)
DEFobjCurrIf(tcps_sess)
DEFobjCurrIf(net)
+DEFobjCurrIf(netstrm)
+DEFobjCurrIf(errmsg)
/* Module static data */
static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change for multiple instances */
/* config settings */
static int iTCPSessMax = 200; /* max number of sessions */
+static int iStrmDrvrMode = 0; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
/* callbacks */
@@ -70,7 +75,7 @@ isPermittedHost(struct sockaddr *addr, char *fromHostFQDN, void __attribute__((u
}
-static int*
+static rsRetVal
doOpenLstnSocks(tcpsrv_t *pSrv)
{
ISOBJ_TYPE_assert(pSrv, tcpsrv);
@@ -81,10 +86,12 @@ doOpenLstnSocks(tcpsrv_t *pSrv)
static int
doRcvData(tcps_sess_t *pSess, char *buf, size_t lenBuf)
{
- int state;
+ ssize_t state;
assert(pSess != NULL);
- state = recv(pSess->sock, buf, lenBuf, 0);
+ state = lenBuf;
+ if(netstrm.Rcv(pSess->pStrm, (uchar*) buf, &state) != RS_RET_OK)
+ state = -1; // TODO: move this function to an iRet interface! 2008-04-23
return state;
}
@@ -125,11 +132,17 @@ static rsRetVal addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVa
CHKiRet(tcpsrv.SetCBOpenLstnSocks(pOurTcpsrv, doOpenLstnSocks));
CHKiRet(tcpsrv.SetCBOnRegularClose(pOurTcpsrv, onRegularClose));
CHKiRet(tcpsrv.SetCBOnErrClose(pOurTcpsrv, onErrClose));
+ CHKiRet(tcpsrv.SetDrvrMode(pOurTcpsrv, iStrmDrvrMode));
tcpsrv.configureTCPListen(pOurTcpsrv, (char *) pNewVal);
CHKiRet(tcpsrv.ConstructFinalize(pOurTcpsrv));
}
finalize_it:
+ if(iRet != RS_RET_OK) {
+ errmsg.LogError(NO_ERRCODE, "error %d trying to add listener", iRet);
+ if(pOurTcpsrv != NULL)
+ tcpsrv.Destruct(&pOurTcpsrv);
+ }
RETiRet;
}
@@ -172,8 +185,10 @@ CODESTARTmodExit
/* release objects we used */
objRelease(net, LM_NET_FILENAME);
+ objRelease(netstrm, LM_NETSTRMS_FILENAME);
objRelease(tcps_sess, LM_TCPSRV_FILENAME);
objRelease(tcpsrv, LM_TCPSRV_FILENAME);
+ objRelease(errmsg, CORE_COMPONENT);
ENDmodExit
@@ -181,6 +196,7 @@ static rsRetVal
resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
iTCPSessMax = 200;
+ iStrmDrvrMode = 0;
return RS_RET_OK;
}
@@ -199,14 +215,18 @@ CODEmodInit_QueryRegCFSLineHdlr
pOurTcpsrv = NULL;
/* request objects we use */
CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME));
CHKiRet(objUse(tcps_sess, LM_TCPSRV_FILENAME));
CHKiRet(objUse(tcpsrv, LM_TCPSRV_FILENAME));
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
/* register config file handlers */
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverrun", 0, eCmdHdlrGetWord,
addTCPListener, NULL, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpmaxsessions", 0, eCmdHdlrInt,
NULL, &iTCPSessMax, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverstreamdrivermode", 0,
+ eCmdHdlrInt, NULL, &iStrmDrvrMode, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
diff --git a/plugins/imtemplate/Makefile.am b/plugins/imtemplate/Makefile.am
index a9221817..0ea4355e 100644
--- a/plugins/imtemplate/Makefile.am
+++ b/plugins/imtemplate/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = imtemplate.la
imtemplate_la_SOURCES = imtemplate.c
-imtemplate_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+imtemplate_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
imtemplate_la_LDFLAGS = -module -avoid-version
imtemplate_la_LIBADD =
diff --git a/plugins/imudp/Makefile.am b/plugins/imudp/Makefile.am
index 53fdad16..28ee9853 100644
--- a/plugins/imudp/Makefile.am
+++ b/plugins/imudp/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = imudp.la
imudp_la_SOURCES = imudp.c
-imudp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+imudp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
imudp_la_LDFLAGS = -module -avoid-version
imudp_la_LIBADD =
diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c
index cda794c3..54dc6836 100644
--- a/plugins/imudp/imudp.c
+++ b/plugins/imudp/imudp.c
@@ -33,12 +33,13 @@
#include <unistd.h>
#include <netdb.h>
#include "rsyslog.h"
-#include "syslogd.h"
+#include "dirty.h"
#include "net.h"
#include "cfsysline.h"
#include "module-template.h"
#include "srUtils.h"
#include "errmsg.h"
+#include "glbl.h"
MODULE_TYPE_INPUT
@@ -47,6 +48,7 @@ MODULE_TYPE_INPUT
/* Module static data */
DEF_IMOD_STATIC_DATA
DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
DEFobjCurrIf(net)
static int *udpLstnSocks = NULL; /* Internet datagram sockets, first element is nbr of elements
@@ -133,6 +135,7 @@ BEGINrunInput
struct sockaddr_storage frominet;
socklen_t socklen;
uchar fromHost[NI_MAXHOST];
+ uchar fromHostIP[NI_MAXHOST];
uchar fromHostFQDN[NI_MAXHOST];
ssize_t l;
CODESTARTrunInput
@@ -180,7 +183,7 @@ CODESTARTrunInput
l = recvfrom(udpLstnSocks[i+1], (char*) pRcvBuf, MAXLINE - 1, 0,
(struct sockaddr *)&frominet, &socklen);
if (l > 0) {
- if(net.cvthname(&frominet, fromHost, fromHostFQDN) == RS_RET_OK) {
+ if(net.cvthname(&frominet, fromHost, fromHostFQDN, fromHostIP) == RS_RET_OK) {
dbgprintf("Message from inetd socket: #%d, host: %s\n",
udpLstnSocks[i+1], fromHost);
/* Here we check if a host is permitted to send us
@@ -191,11 +194,11 @@ CODESTARTrunInput
*/
if(net.isAllowedSender(net.pAllowedSenders_UDP,
(struct sockaddr *)&frominet, (char*)fromHostFQDN)) {
- parseAndSubmitMessage((char*)fromHost, (char*) pRcvBuf, l,
+ parseAndSubmitMessage(fromHost, fromHostIP, pRcvBuf, l,
MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_NO_DELAY);
} else {
dbgprintf("%s is not an allowed sender\n", (char*)fromHostFQDN);
- if(option_DisallowWarning) {
+ if(glbl.GetOption_DisallowWarning) {
errmsg.LogError(NO_ERRCODE, "UDP message from disallowed sender %s discarded",
(char*)fromHost);
}
@@ -253,6 +256,7 @@ BEGINmodExit
CODESTARTmodExit
/* release what we no longer need */
objRelease(errmsg, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
objRelease(net, LM_NET_FILENAME);
ENDmodExit
@@ -281,6 +285,7 @@ CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
CHKiRet(objUse(net, LM_NET_FILENAME));
/* register config file handlers */
diff --git a/plugins/imuxsock/Makefile.am b/plugins/imuxsock/Makefile.am
index e165bb7d..11a0ba3a 100644
--- a/plugins/imuxsock/Makefile.am
+++ b/plugins/imuxsock/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = imuxsock.la
imuxsock_la_SOURCES = imuxsock.c
-imuxsock_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+imuxsock_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
imuxsock_la_LDFLAGS = -module -avoid-version
imuxsock_la_LIBADD =
diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c
index f8798039..82fd118e 100644
--- a/plugins/imuxsock/imuxsock.c
+++ b/plugins/imuxsock/imuxsock.c
@@ -35,11 +35,13 @@
#include <unistd.h>
#include <sys/stat.h>
#include <sys/un.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "cfsysline.h"
#include "module-template.h"
#include "srUtils.h"
#include "errmsg.h"
+#include "net.h"
+#include "glbl.h"
MODULE_TYPE_INPUT
@@ -62,6 +64,7 @@ MODULE_TYPE_INPUT
/* Module static data */
DEF_IMOD_STATIC_DATA
DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
static int startIndexUxLocalSockets; /* process funix from that index on (used to
* suppress local logging. rgerhards 2005-08-01
@@ -100,8 +103,6 @@ static rsRetVal setSystemLogTimestampIgnore(void __attribute__((unused)) *pVal,
*/
static rsRetVal addLstnSocketName(void __attribute__((unused)) *pVal, uchar *pNewVal)
{
- char errStr[1024];
-
if(nfunix < MAXFUNIX) {
if(*pNewVal == ':') {
funixParseHost[nfunix] = 1;
@@ -113,9 +114,8 @@ static rsRetVal addLstnSocketName(void __attribute__((unused)) *pVal, uchar *pNe
funixn[nfunix++] = pNewVal;
}
else {
- snprintf(errStr, sizeof(errStr), "rsyslogd: Out of unix socket name descriptors, ignoring %s\n",
+ errmsg.LogError(NO_ERRCODE, "Out of unix socket name descriptors, ignoring %s\n",
pNewVal);
- logmsgInternal(LOG_SYSLOG|LOG_ERR, errStr, ADDDATE);
}
return RS_RET_OK;
@@ -176,12 +176,13 @@ static rsRetVal readSocket(int fd, int bParseHost, int flags)
{
DEFiRet;
int iRcvd;
- char line[MAXLINE +1];
+ uchar line[MAXLINE +1];
iRcvd = recv(fd, line, MAXLINE - 1, 0);
dbgprintf("Message from UNIX socket: #%d\n", fd);
if (iRcvd > 0) {
- parseAndSubmitMessage((char*)LocalHostName, line, iRcvd, bParseHost, flags, eFLOWCTL_LIGHT_DELAY);
+ parseAndSubmitMessage(glbl.GetLocalHostName(), (uchar*)"127.0.0.1", line,
+ iRcvd, bParseHost, flags, eFLOWCTL_LIGHT_DELAY);
} else if (iRcvd < 0 && errno != EINTR) {
char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
@@ -289,6 +290,8 @@ ENDafterRun
BEGINmodExit
CODESTARTmodExit
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(errmsg, CORE_COMPONENT);
ENDmodExit
@@ -319,6 +322,7 @@ CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
/* initialize funixn[] array */
for(i = 1 ; i < MAXFUNIX ; ++i) {
@@ -346,6 +350,5 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketignoremsgtimestamp", 0, eCmdHdlrBinary,
setSystemLogTimestampIgnore, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
-/*
- * vi:set ai:
+/* vim:set ai:
*/
diff --git a/plugins/omgssapi/Makefile.am b/plugins/omgssapi/Makefile.am
index 5280a1ce..c2cbe387 100644
--- a/plugins/omgssapi/Makefile.am
+++ b/plugins/omgssapi/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = omgssapi.la
omgssapi_la_SOURCES = omgssapi.c
-omgssapi_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+omgssapi_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
omgssapi_la_LDFLAGS = -module -avoid-version
omgssapi_la_LIBADD = $(gss_libs)
diff --git a/plugins/omgssapi/omgssapi.c b/plugins/omgssapi/omgssapi.c
index 28c3880b..e15c24e1 100644
--- a/plugins/omgssapi/omgssapi.c
+++ b/plugins/omgssapi/omgssapi.c
@@ -43,38 +43,27 @@
#endif
#include <pthread.h>
#include <gssapi/gssapi.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "syslogd-types.h"
#include "srUtils.h"
#include "net.h"
-#include "omfwd.h"
#include "template.h"
#include "msg.h"
-#include "tcpsyslog.h"
#include "cfsysline.h"
#include "module-template.h"
#include "gss-misc.h"
#include "tcpclt.h"
+#include "glbl.h"
#include "errmsg.h"
MODULE_TYPE_OUTPUT
-#define INET_SUSPEND_TIME 60
-/* equal to 1 minute - TODO: see if we can get rid of this now that we have
- * the retry intervals in the engine -- rgerhards, 2008-03-12
- */
-
-#define INET_RETRY_MAX 30 /* maximum of retries for gethostbyname() */
- /* was 10, changed to 30 because we reduced INET_SUSPEND_TIME by one third. So
- * this "fixes" some of implications of it (see comment on INET_SUSPEND_TIME).
- * rgerhards, 2005-07-26
- * TODO: this needs to be reviewed in spite of the new engine, too -- rgerhards, 2008-03-12
- */
/* internal structures
*/
DEF_OMOD_STATIC_DATA
DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
DEFobjCurrIf(gssutil)
DEFobjCurrIf(tcpclt)
@@ -86,11 +75,9 @@ typedef struct _instanceData {
eDestFORW_SUSP,
eDestFORW_UNKN
} eDestState;
- int iRtryCnt;
struct addrinfo *f_addr;
int compressionLevel; /* 0 - no compression, else level for zlib */
char *port;
- time_t ttSuspend; /* time selector was suspended */
tcpclt_t *pTCPClt; /* our tcpclt object */
gss_ctx_id_t gss_context;
OM_uint32 gss_flags;
@@ -174,8 +161,6 @@ CODESTARTdbgPrintInstInfo
ENDdbgPrintInstInfo
-/* CODE FOR SENDING TCP MESSAGES */
-
/* This function is called immediately before a send retry is attempted.
* It shall clean up whatever makes sense.
* rgerhards, 2007-12-28
@@ -207,9 +192,7 @@ static rsRetVal TCPSendGSSInit(void *pvData)
base = (gss_base_service_name == NULL) ? "host" : gss_base_service_name;
out_tok.length = strlen(pData->f_hname) + strlen(base) + 2;
- if ((out_tok.value = malloc(out_tok.length)) == NULL) {
- ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
- }
+ CHKmalloc(out_tok.value = malloc(out_tok.length));
strcpy(out_tok.value, base);
strcat(out_tok.value, "@");
strcat(out_tok.value, pData->f_hname);
@@ -365,13 +348,12 @@ static rsRetVal doTryResume(instanceData *pData)
* a common function.
*/
hints.ai_flags = AI_NUMERICSERV;
- hints.ai_family = family;
+ hints.ai_family = glbl.GetDefPFFamily();
hints.ai_socktype = SOCK_STREAM;
if((e = getaddrinfo(pData->f_hname,
getFwdSyslogPt(pData), &hints, &res)) == 0) {
dbgprintf("%s found, resuming.\n", pData->f_hname);
pData->f_addr = res;
- pData->iRtryCnt = 0;
pData->eDestState = eDestFORW;
} else {
iRet = RS_RET_SUSPENDED;
@@ -410,7 +392,6 @@ CODESTARTdoAction
case eDestFORW:
dbgprintf(" %s:%s/%s\n", pData->f_hname, getFwdSyslogPt(pData), "tcp-gssapi");
- pData->ttSuspend = time(NULL);
psz = (char*) ppString[0];
l = strlen((char*) psz);
if (l > MAXLINE)
@@ -609,12 +590,10 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
memset(&hints, 0, sizeof(hints));
/* port must be numeric, because config file syntax requests this */
hints.ai_flags = AI_NUMERICSERV;
- hints.ai_family = family;
+ hints.ai_family = glbl.GetDefPFFamily();
hints.ai_socktype = SOCK_STREAM;
if( (error = getaddrinfo(pData->f_hname, getFwdSyslogPt(pData), &hints, &res)) != 0) {
pData->eDestState = eDestFORW_UNKN;
- pData->iRtryCnt = INET_RETRY_MAX;
- pData->ttSuspend = time(NULL);
} else {
pData->eDestState = eDestFORW;
pData->f_addr = res;
@@ -637,6 +616,7 @@ ENDparseSelectorAct
BEGINmodExit
CODESTARTmodExit
+ objRelease(glbl, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
objRelease(gssutil, LM_GSSUTIL_FILENAME);
objRelease(tcpclt, LM_TCPCLT_FILENAME);
@@ -695,6 +675,7 @@ CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
CHKiRet(objUse(gssutil, LM_GSSUTIL_FILENAME));
CHKiRet(objUse(tcpclt, LM_TCPCLT_FILENAME));
diff --git a/plugins/omlibdbi/Makefile.am b/plugins/omlibdbi/Makefile.am
index 872fc67c..d224f9e4 100644
--- a/plugins/omlibdbi/Makefile.am
+++ b/plugins/omlibdbi/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = omlibdbi.la
omlibdbi_la_SOURCES = omlibdbi.c
-omlibdbi_la_CPPFLAGS = -I$(top_srcdir) $(libdbi_cflags) $(pthreads_cflags)
+omlibdbi_la_CPPFLAGS = -I$(top_srcdir) $(libdbi_cflags) $(pthreads_cflags) $(rsrt_cflags)
omlibdbi_la_LDFLAGS = -module -avoid-version
omlibdbi_la_LIBADD = $(libdbi_libs)
diff --git a/plugins/omlibdbi/omlibdbi.c b/plugins/omlibdbi/omlibdbi.c
index a942a453..661aee6f 100644
--- a/plugins/omlibdbi/omlibdbi.c
+++ b/plugins/omlibdbi/omlibdbi.c
@@ -40,7 +40,7 @@
#include <errno.h>
#include <time.h>
#include <dbi/dbi.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "syslogd-types.h"
#include "cfsysline.h"
#include "srUtils.h"
diff --git a/plugins/ommail/Makefile.am b/plugins/ommail/Makefile.am
index 7e9f5f13..fa470a43 100644
--- a/plugins/ommail/Makefile.am
+++ b/plugins/ommail/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = ommail.la
ommail_la_SOURCES = ommail.c
-ommail_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+ommail_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
ommail_la_LDFLAGS = -module -avoid-version
ommail_la_LIBADD =
diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c
index 218c73c9..d4158975 100644
--- a/plugins/ommail/ommail.c
+++ b/plugins/ommail/ommail.c
@@ -44,12 +44,13 @@
#include <netdb.h>
#include <time.h>
#include <sys/socket.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "syslogd-types.h"
#include "srUtils.h"
#include "cfsysline.h"
#include "module-template.h"
#include "errmsg.h"
+#include "glbl.h"
MODULE_TYPE_OUTPUT
@@ -57,6 +58,7 @@ MODULE_TYPE_OUTPUT
*/
DEF_OMOD_STATIC_DATA
DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
static uchar *pszSrv = NULL;
static uchar *pszSrvPort = NULL;
@@ -415,7 +417,7 @@ sendSMTP(instanceData *pData, uchar *body, uchar *subject)
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, (char*)glbl.GetLocalHostName(), strlen((char*)glbl.GetLocalHostName())));
CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1));
CHKiRet(readResponse(pData, &iState, 250));
@@ -589,6 +591,7 @@ CODESTARTmodExit
freeConfigVariables();
/* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
ENDmodExit
@@ -616,6 +619,7 @@ CODESTARTmodInit
CODEmodInit_QueryRegCFSLineHdlr
/* tell which objects we need */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, 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/plugins/ommysql/Makefile.am b/plugins/ommysql/Makefile.am
index 3b4e6d75..d5433a40 100644
--- a/plugins/ommysql/Makefile.am
+++ b/plugins/ommysql/Makefile.am
@@ -1,7 +1,7 @@
pkglib_LTLIBRARIES = ommysql.la
ommysql_la_SOURCES = ommysql.c ommysql.h
-ommysql_la_CPPFLAGS = -I$(top_srcdir) $(mysql_cflags) $(pthreads_cflags)
+ommysql_la_CPPFLAGS = $(rsrt_cflags) $(mysql_cflags) $(pthreads_cflags)
ommysql_la_LDFLAGS = -module -avoid-version
ommysql_la_LIBADD = $(mysql_libs)
diff --git a/plugins/ommysql/ommysql.c b/plugins/ommysql/ommysql.c
index 0522e31d..472cb10d 100644
--- a/plugins/ommysql/ommysql.c
+++ b/plugins/ommysql/ommysql.c
@@ -37,7 +37,7 @@
#include <time.h>
#include <mysql/mysql.h>
#include <mysql/errmsg.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "syslogd-types.h"
#include "srUtils.h"
#include "template.h"
diff --git a/plugins/ompgsql/Makefile.am b/plugins/ompgsql/Makefile.am
index b2e3effa..cc1c5f49 100644
--- a/plugins/ompgsql/Makefile.am
+++ b/plugins/ompgsql/Makefile.am
@@ -1,7 +1,7 @@
pkglib_LTLIBRARIES = ompgsql.la
ompgsql_la_SOURCES = ompgsql.c ompgsql.h
-ompgsql_la_CPPFLAGS = -I$(top_srcdir) $(pgsql_cflags)
+ompgsql_la_CPPFLAGS = -I$(top_srcdir) $(pgsql_cflags) $(rsrt_cflags)
ompgsql_la_LDFLAGS = -module -avoid-version
ompgsql_la_LIBADD = $(pgsql_libs)
diff --git a/plugins/ompgsql/ompgsql.c b/plugins/ompgsql/ompgsql.c
index 1d7b2eb7..77fd6a07 100644
--- a/plugins/ompgsql/ompgsql.c
+++ b/plugins/ompgsql/ompgsql.c
@@ -36,7 +36,7 @@
#include <errno.h>
#include <time.h>
#include <libpq-fe.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "syslogd-types.h"
#include "srUtils.h"
#include "template.h"
diff --git a/plugins/omrelp/Makefile.am b/plugins/omrelp/Makefile.am
index dfc2111f..f8384f42 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) $(rsrt_cflags)
omrelp_la_LDFLAGS = -module -avoid-version
omrelp_la_LIBADD = $(RELP_LIBS)
diff --git a/plugins/omrelp/omrelp.c b/plugins/omrelp/omrelp.c
index 04571682..2977053a 100644
--- a/plugins/omrelp/omrelp.c
+++ b/plugins/omrelp/omrelp.c
@@ -36,11 +36,12 @@
#include <errno.h>
#include <ctype.h>
#include <librelp.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "syslogd-types.h"
#include "srUtils.h"
#include "cfsysline.h"
#include "module-template.h"
+#include "glbl.h"
#include "errmsg.h"
MODULE_TYPE_OUTPUT
@@ -49,6 +50,7 @@ MODULE_TYPE_OUTPUT
*/
DEF_OMOD_STATIC_DATA
DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
static relpEngine_t *pRelpEngine; /* our relp engine */
@@ -118,7 +120,7 @@ static rsRetVal doConnect(instanceData *pData)
DEFiRet;
if(pData->bInitialConnect) {
- iRet = relpCltConnect(pData->pRelpClt, family, (uchar*) pData->port, (uchar*) pData->f_hname);
+ iRet = relpCltConnect(pData->pRelpClt, glbl.GetDefPFFamily(), (uchar*) pData->port, (uchar*) pData->f_hname);
if(iRet == RELP_RET_OK)
pData->bInitialConnect = 0;
} else {
@@ -311,6 +313,7 @@ CODESTARTmodExit
relpEngineDestruct(&pRelpEngine);
/* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
ENDmodExit
@@ -332,6 +335,7 @@ CODEmodInit_QueryRegCFSLineHdlr
/* tell which objects we need */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
ENDmodInit
/* vim:set ai:
diff --git a/plugins/omsnmp/Makefile.am b/plugins/omsnmp/Makefile.am
index d74f7bb4..d784faca 100644
--- a/plugins/omsnmp/Makefile.am
+++ b/plugins/omsnmp/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = omsnmp.la
omsnmp_la_SOURCES = omsnmp.c omsnmp.h
-omsnmp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+omsnmp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
omsnmp_la_LDFLAGS = -module -avoid-version
omsnmp_la_LIBADD = $(snmp_libs)
diff --git a/plugins/omsnmp/omsnmp.c b/plugins/omsnmp/omsnmp.c
index 22d48340..8af5f22a 100644
--- a/plugins/omsnmp/omsnmp.c
+++ b/plugins/omsnmp/omsnmp.c
@@ -36,7 +36,7 @@
#include <netdb.h>
#include <ctype.h>
#include <assert.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "syslogd-types.h"
#include "cfsysline.h"
#include "module-template.h"
diff --git a/plugins/omtesting/Makefile.am b/plugins/omtesting/Makefile.am
index 7e376683..8e98ca63 100644
--- a/plugins/omtesting/Makefile.am
+++ b/plugins/omtesting/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = omtesting.la
omtesting_la_SOURCES = omtesting.c
-omtesting_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+omtesting_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
omtesting_la_LDFLAGS = -module -avoid-version
omtesting_la_LIBADD =
diff --git a/plugins/omtesting/omtesting.c b/plugins/omtesting/omtesting.c
index 15d3cb80..411bcf88 100644
--- a/plugins/omtesting/omtesting.c
+++ b/plugins/omtesting/omtesting.c
@@ -49,7 +49,7 @@
#include <string.h>
#include <ctype.h>
#include <assert.h>
-#include "syslogd.h"
+#include "dirty.h"
#include "syslogd-types.h"
#include "module-template.h"
diff --git a/redhat/rsyslog b/redhat/rsyslog
deleted file mode 100644
index ee9be79b..00000000
--- a/redhat/rsyslog
+++ /dev/null
@@ -1,12 +0,0 @@
-# Options to syslogd
-# -m 0 disables 'MARK' messages.
-# -r enables logging from remote machines
-# -x disables DNS lookups on messages recieved with -r
-# See syslogd(8) for more details
-SYSLOGD_OPTIONS="-m 0"
-# Options to klogd
-# -2 prints all kernel oops messages twice; once for klogd to decode, and
-# once for processing with 'ksymoops'
-# -x disables all klogd processing of oops messages entirely
-# See klogd(8) for more details
-KLOGD_OPTIONS="-x"
diff --git a/redhat/rsyslog.conf b/redhat/rsyslog.conf
deleted file mode 100644
index 9d34c805..00000000
--- a/redhat/rsyslog.conf
+++ /dev/null
@@ -1,26 +0,0 @@
-# Log all kernel messages to the console.
-# Logging much else clutters up the screen.
-#kern.* /dev/console
-
-# Log anything (except mail) of level info or higher.
-# Don't log private authentication messages!
-*.info;mail.none;authpriv.none;cron.none /var/log/messages
-
-# The authpriv file has restricted access.
-authpriv.* /var/log/secure
-
-# Log all the mail messages in one place.
-mail.* -/var/log/maillog
-
-
-# Log cron stuff
-cron.* /var/log/cron
-
-# Everybody gets emergency messages
-*.emerg *
-
-# Save news errors of level crit and higher in a special file.
-uucp,news.crit /var/log/spooler
-
-# Save boot messages also to boot.log
-local7.* /var/log/boot.log
diff --git a/redhat/rsyslog.init b/redhat/rsyslog.init
deleted file mode 100644
index 6b6f0649..00000000
--- a/redhat/rsyslog.init
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/bin/bash
-#
-# rsyslog Starts rsyslogd/rklogd.
-#
-#
-# chkconfig: 2345 12 88
-# description: Syslog is the facility by which many daemons use to log \
-# messages to various system log files. It is a good idea to always \
-# run rsyslog.
-### BEGIN INIT INFO
-# Provides: $syslog
-# Short-Description: Enhanced system logging and kernel message trapping daemons
-# Description: Rsyslog is an enhanced multi-threaded syslogd supporting,
-# among others, MySQL, syslog/tcp, RFC 3195, permitted
-# sender lists, filtering on any message part, and fine
-# grain output format control.
-### END INIT INFO
-
-# Source function library.
-. /etc/init.d/functions
-
-RETVAL=0
-
-start() {
- [ -x /sbin/rsyslogd ] || exit 5
- [ -x /sbin/rklogd ] || exit 5
-
- # Source config
- if [ -f /etc/sysconfig/rsyslog ] ; then
- . /etc/sysconfig/rsyslog
- else
- SYSLOGD_OPTIONS="-m 0"
- KLOGD_OPTIONS="-2"
- fi
-
- umask 077
-
- echo -n $"Starting system logger (rsyslog): "
- daemon rsyslogd $SYSLOGD_OPTIONS
- RETVAL=$?
- echo
- echo -n $"Starting kernel logger (rklogd): "
- daemon rklogd $KLOGD_OPTIONS
- echo
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/rsyslog
- return $RETVAL
-}
-stop() {
- echo -n $"Shutting down kernel logger (rklogd): "
- killproc rklogd
- echo
- echo -n $"Shutting down system logger (rsyslog): "
- killproc rsyslogd
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/rsyslog
- return $RETVAL
-}
-rhstatus() {
- status rsyslogd
- status rklogd
-}
-restart() {
- stop
- start
-}
-
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- rhstatus
- ;;
- restart|reload)
- restart
- ;;
- condrestart)
- [ -f /var/lock/subsys/rsyslog ] && restart || :
- ;;
- *)
- echo $"Usage: $0 {start|stop|status|restart|condrestart}"
- exit 2
-esac
-
-exit $?
diff --git a/redhat/rsyslog.log b/redhat/rsyslog.log
deleted file mode 100644
index e0593a26..00000000
--- a/redhat/rsyslog.log
+++ /dev/null
@@ -1,6 +0,0 @@
-/var/log/messages /var/log/secure /var/log/maillog /var/log/spooler /var/log/boot.log /var/log/cron {
- sharedscripts
- postrotate
- /bin/kill -HUP `cat /var/run/rsyslogd.pid 2> /dev/null` 2> /dev/null || true
- endscript
-}
diff --git a/redhat/rsyslog.sysconfig b/redhat/rsyslog.sysconfig
deleted file mode 100644
index ee9be79b..00000000
--- a/redhat/rsyslog.sysconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-# Options to syslogd
-# -m 0 disables 'MARK' messages.
-# -r enables logging from remote machines
-# -x disables DNS lookups on messages recieved with -r
-# See syslogd(8) for more details
-SYSLOGD_OPTIONS="-m 0"
-# Options to klogd
-# -2 prints all kernel oops messages twice; once for klogd to decode, and
-# once for processing with 'ksymoops'
-# -x disables all klogd processing of oops messages entirely
-# See klogd(8) for more details
-KLOGD_OPTIONS="-x"
diff --git a/rfc3195d.8 b/rfc3195d.8
deleted file mode 100644
index ae191df6..00000000
--- a/rfc3195d.8
+++ /dev/null
@@ -1,84 +0,0 @@
-.\" Copyright 2005 Rainer Gerhards and Adiscon for the rsyslog modifications
-.\" Distributed under the GNU General Public License.
-.\"
-.TH RFC3195D 8 "02 April 2008" "Version 3.14.0" "Linux System Administration"
-.SH NAME
-rfc3195d \- RFC 3195 listener
-.SH SYNOPSIS
-.B rfc3195d
-.RB [ " \-d " ]
-.RB [ " \-p"
-.IB socket
-]
-.RB [ " \-r"
-.IB port
-]
-.RB [ " \-v " ]
-.LP
-.SH DESCRIPTION
-.B Rfc3195d
-is a utility for receiving syslog messages via RFC 3195. Both
-RAW and COOKED profiles are supported (but COOKED only without
-relay-specific PATH elements).
-rfc3195d accepts messages via RFC 3195 and forwards them to
-the local domain socket specified in the -p option
-(/dev/log3195 by default). There, the messages can be picked up
-by the system syslogd. While rfc3195d can work with any syslogd,
-we highly recommend using
-.B rsyslogd,
-because it has special handling
-for the messages forwarded by rfc3195d. To enable message
-reception in
-.B rsyslogd,
-use the "-a :/dev/log3195" command line
-option (the colon in front of the socket name tells
-.B rsyslogd
-that the messages contain hostnames - this is vital to get the
-right sender name into your logs).
-
-.B Rfc3195d
-currently has very limited functionality. Most importantly,
-it does not allow to limit the senders it receives messages from.
-Documentation is also very sparse. The situation should improve over
-time as the rsyslog project is continously being enhanced.
-.LP
-.SH OPTIONS
-.TP
-.BI "\-p " "socket"
-The socket the received messages are to be sent to. If not specified,
-/dev/log3195 is used.
-.TP
-.BI "\-r " "port"
-The listen port to use. If not specified, IANA-assigned port 601 is used.
-.TP
-.B "\-d"
-Turns on debug mode. In it, rfc3195d spits out diagnostic information
-to stdout.
-.TP
-.B "\-v"
-Print version and exit.
-.SH SIGNALS
-.B Rfc3195d
-reacts to a set of signals.
-.TP
-.B SIGTERM
-.B Rfc3195d
-terminates.
-.TP
-.B SIGUSR1
-.B Rfc3195d
-terminates.
-.LP
-.SH SEE ALSO
-.BR rsyslog.conf (5),
-.BR rsyslogd (8)
-.LP
-.SH MORE INFORMATION
-Is available on the project home page at http://www.rsyslog.com
-.LP
-.SH COLLABORATORS
-Rfc3195d uses liblogging (http://www.liblogging.org) for RFC 3195
-protocol handling.
-.PD 0
-.TP
-Rainer Gerhards <rgerhards@adiscon.com>
diff --git a/rfc3195d.c b/rfc3195d.c
deleted file mode 100644
index dd8497cb..00000000
--- a/rfc3195d.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/**
- * rfc3195d.c
- * This is an RFC 3195 listener. All data received is forwarded to
- * local UNIX domain socket, where it can be picked up by a
- * syslog daemon (like rsyslogd ;)).
- *
- * \author Rainer Gerhards <rgerhards@adiscon.com>
- *
- * Copyright 2003-2005 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 <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- */
-#include "config.h"
-
-#include <stdio.h>
-#ifndef FEATURE_RFC3195
-/* this is a trick: if RFC3195 is not to be supported, we just do an
- * error message.
- */
-int main()
-{
- fprintf(stderr, "error: not compiled with FEATURE_RFC3195 - terminating.\n");
- return(1);
-}
-#else
-#include <unistd.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include "rsyslog.h"
-#include "liblogging/liblogging.h"
-#include "liblogging/srAPI.h"
-#include "liblogging/syslogmessage.h"
-
-/* configurable params! */
-static char* pPathLogname = "/dev/log3195";
-static char *PidFile;
-static int NoFork = 0;
-static int Debug = 0;
-static int listenPort = 601;
-
-/* we use a global API object below, because this listener is
- * not very complex. As such, this hack should not harm anything.
- * rgerhards, 2005-10-12
- */
-static srAPIObj* pAPI;
-
-static int LogFile = -1; /* fd for log */
-static int connected; /* have done connect */
-static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */
-
-/* small usage info */
-static int usage()
-{
- /* The following usage line is what we intend to have - it
- * is commented out as a reminder. The one below is what we
- * currently actually do...
- fprintf(stderr, "usage: rfc3195d [-dv] [-i pidfile] [-n] [-p path]\n");
- */
- fprintf(stderr, "usage: rfc3195d [-dv] [-r port] [-p path]\n");
- exit(1);
-}
-
-/* CLOSELOG -- close the system log
- */
-static void closelog(void)
-{
- close(LogFile);
- LogFile = -1;
- connected = 0;
-}
-
-/* OPENLOG -- open system log
- */
-static void openlog()
-{
- if (LogFile == -1) {
- SyslogAddr.sa_family = AF_UNIX;
- strncpy(SyslogAddr.sa_data, pPathLogname,
- sizeof(SyslogAddr.sa_data));
- LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
- if(LogFile < 0) {
- char errStr[1024];
- printf("error opening '%s': %s\n",
- pPathLogname, rs_strerror_r(errno, errStr, sizeof(errStr)));
- }
- }
- if (LogFile != -1 && !connected &&
- connect(LogFile, &SyslogAddr, sizeof(SyslogAddr.sa_family)+
- strlen(SyslogAddr.sa_data)) != -1)
- connected = 1;
- else {
- char errStr[1024];
- printf("error connecting '%s': %s\n",
- pPathLogname, rs_strerror_r(errno, errStr, sizeof(errStr)));
- }
-}
-
-
-/* This method is called when a message has been fully received.
- * It passes the received message to the specified unix domain
- * socket. Please note that this callback is synchronous, thus
- * liblogging will be on hold until it returns. This is important
- * to note because in an error case we might stay in this code
- * for an extended amount of time. So far, we think this is the
- * best solution, but real-world experience might tell us a
- * different truth ;)
- * rgerhards 2005-10-12
- */
-void OnReceive(srAPIObj* pAPI, srSLMGObj* pSLMG)
-{
- unsigned char *pszRawMsg;
- int iRetries; /* number of retries connecting to log socket */
- int iSleep;
- int iWriteOffset;
- ssize_t nToWrite;
- ssize_t nWritten;
-
- srSLMGGetRawMSG(pSLMG, &pszRawMsg);
-
- /* we need to loop writing the message. At least in
- * theory, a single write might not send all data to the
- * syslogd. So we need to continue until everything is written.
- * Also, we need to check if there are any socket erros, in
- * which case we reconect. We will re-try indefinitely, if this
- * is not acceptable, you need to change the code.
- * rgerhards 2005-10-12
- */
- iRetries = 0;
- nToWrite = strlen(pszRawMsg);
- iWriteOffset = 0;
- while(nToWrite != 0) {
- if(LogFile < 0 || !connected)
- openlog();
- if(LogFile < 0 || !connected) {
- /* still not connected, retry */
- if(iRetries > 0) {
- iSleep = (iRetries < 30) ? iRetries : 30;
- /* we sleep a little to prevent a thight loop */
- if(Debug)
- printf("multiple retries connecting to log socket"
- " - doing sleep(%d)\n", iSleep);
- sleep(iSleep);
- }
- ++iRetries;
- } else {
- nWritten = write(LogFile, pszRawMsg, strlen(pszRawMsg));
- if(nWritten < 0) {
- /* error, recover! */
- char errStr[1024];
- printf("error writing to domain socket: %s\r\n", rs_strerror_r(errno, errStr, sizeof(errStr)));
- closelog();
- } else {
- /* prepare for (potential) next write */
- nToWrite -= nWritten;
- iWriteOffset += nWritten;
- }
- }
- }
-
- if(Debug) {
- static int largest = 0;
- int sz = strlen(pszRawMsg);
- if(sz > largest)
- largest = sz;
- printf("Msg(%d/%d):%s\n\n", largest, sz, pszRawMsg);
- }
-}
-
-
-/* As we are single-threaded in this example, we need
- * one way to shut down the listener running on this
- * single thread. We use SIG_INT to do so - it effectively
- * provides a short-lived second thread ;-)
- */
-void doShutdown(int i)
-{
- printf("Shutting down rfc3195d. Be patient, this can take up to 30 seconds...\n");
- srAPIShutdownListener(pAPI);
-}
-
-
-/* on the the real program ;) */
-int main(int argc, char* argv[])
-{
- srRetVal iRet;
- int ch;
- struct sigaction sigAct;
-
- while ((ch = getopt(argc, argv, "di:np:r:v")) != EOF)
- switch((char)ch) {
- case 'd': /* debug */
- Debug = 1;
- break;
- case 'i': /* pid file name */
- PidFile = optarg;
- break;
- case 'n': /* don't fork */
- NoFork = 1;
- break;
- case 'p': /* path to regular log socket */
- pPathLogname = optarg;
- break;
- case 'r': /* listen port */
- listenPort = atoi(optarg);
- if(listenPort < 1 || listenPort > 65535) {
- printf("Error: invalid listen port '%s', using 601 instead\n",
- optarg);
- listenPort = 601;
- }
- break;
- case 'v':
- printf("rfc3195d %s.%s (using liblogging version %d.%d.%d).\n",
- VERSION, PATCHLEVEL,
- LIBLOGGING_VERSION_MAJOR, LIBLOGGING_VERSION_MINOR,
- LIBLOGGING_VERSION_SUBMINOR);
- printf("See http://www.rsyslog.com for more information.\n");
- exit(0);
- case '?':
- default:
- usage();
- }
- if ((argc -= optind))
- usage();
-
- memset(&sigAct, 0, sizeof(sigAct));
- sigemptyset(&sigAct.sa_mask);
- sigAct.sa_handler = doShutdown;
- sigaction(SIGUSR1, &sigAct, NULL);
- sigaction(SIGTERM, &sigAct, NULL);
-
- if(!Debug)
- {
- sigAct.sa_handler = SIG_IGN;
- sigaction(SIGINT, &sigAct, NULL);
- }
-
- if((pAPI = srAPIInitLib()) == NULL)
- {
- printf("Error initializing liblogging - aborting!\n");
- exit(1);
- }
-
- if((iRet = srAPISetOption(pAPI, srOPTION_BEEP_LISTENPORT, listenPort)) != SR_RET_OK)
- {
- printf("Error %d setting listen port - aborting\n", iRet);
- exit(100);
- }
-
- if((iRet = srAPISetupListener(pAPI, OnReceive)) != SR_RET_OK)
- {
- printf("Error %d setting up listener - aborting\n", iRet);
- exit(101);
- }
-
- /* now move the listener to running state. Control will only
- * return after SIGUSR1.
- */
- if((iRet = srAPIRunListener(pAPI)) != SR_RET_OK)
- {
- printf("Error %d running the listener - aborting\n", iRet);
- exit(102);
- }
-
- /** control will reach this point after shutdown */
-
- srAPIExitLib(pAPI);
- return 0;
-}
-#endif /* #ifndef FEATURE_RFC3195 - main wrapper */
-
-/*
- * vi:set ai:
- */
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
new file mode 100644
index 00000000..a7a2b91e
--- /dev/null
+++ b/runtime/Makefile.am
@@ -0,0 +1,119 @@
+sbin_PROGRAMS =
+man_MANS =
+noinst_LTLIBRARIES = librsyslog.la
+pkglib_LTLIBRARIES =
+#pkglib_LTLIBRARIES = librsyslog.la
+
+librsyslog_la_SOURCES = \
+ rsyslog.c \
+ rsyslog.h \
+ atomic.h \
+ syslogd-types.h \
+ module-template.h \
+ obj-types.h \
+ nsd.h \
+ glbl.h \
+ glbl.c \
+ msg.c \
+ msg.h \
+ linkedlist.c \
+ linkedlist.h \
+ objomsr.c \
+ objomsr.h \
+ stringbuf.c \
+ stringbuf.h \
+ datetime.c \
+ datetime.h \
+ srutils.c \
+ srUtils.h \
+ errmsg.c \
+ errmsg.h \
+ debug.c \
+ debug.h \
+ obj.c \
+ obj.h \
+ modules.c \
+ modules.h \
+ sync.c \
+ sync.h \
+ expr.c \
+ expr.h \
+ ctok.c \
+ ctok.h \
+ ctok_token.c \
+ ctok_token.h \
+ stream.c \
+ stream.h \
+ var.c \
+ var.h \
+ wtp.c \
+ wtp.h \
+ wti.c \
+ wti.h \
+ sysvar.c \
+ sysvar.h \
+ vm.c \
+ vm.h \
+ vmstk.c \
+ vmstk.h \
+ vmprg.c \
+ vmprg.h \
+ vmop.c \
+ vmop.h \
+ queue.c \
+ queue.h \
+ cfsysline.c \
+ cfsysline.h
+
+librsyslog_la_CPPFLAGS = -D_PATH_MODDIR=\"$(pkglibdir)/\" -I$(top_srcdir) $(pthreads_cflags)
+#librsyslog_la_LDFLAGS = -module -avoid-version
+librsyslog_la_LIBADD =
+
+#
+# regular expression support
+#
+if ENABLE_REGEXP
+pkglib_LTLIBRARIES += lmregexp.la
+lmregexp_la_SOURCES = regexp.c regexp.h
+lmregexp_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
+lmregexp_la_LDFLAGS = -module -avoid-version
+lmregexp_la_LIBADD =
+endif
+
+if ENABLE_INET
+pkglib_LTLIBRARIES += lmnet.la lmnetstrms.la
+#
+# network support
+#
+lmnet_la_SOURCES = net.c net.h
+lmnet_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
+lmnet_la_LDFLAGS = -module -avoid-version
+lmnet_la_LIBADD =
+
+# network stream master class and stream factory
+lmnetstrms_la_SOURCES = netstrms.c netstrms.h netstrm.c netstrm.h nssel.c nssel.h
+lmnetstrms_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
+lmnetstrms_la_LDFLAGS = -module -avoid-version
+lmnetstrms_la_LIBADD =
+
+# netstream drivers
+
+# plain tcp driver - main driver
+pkglib_LTLIBRARIES += lmnsd_ptcp.la
+lmnsd_ptcp_la_SOURCES = nsd_ptcp.c nsd_ptcp.h nsdsel_ptcp.c nsdsel_ptcp.h
+lmnsd_ptcp_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
+lmnsd_ptcp_la_LDFLAGS = -module -avoid-version
+lmnsd_ptcp_la_LIBADD =
+endif # if ENABLE_INET
+
+#
+# GnuTLS netstream driver
+#
+if ENABLE_GNUTLS
+pkglib_LTLIBRARIES += lmnsd_gtls.la
+lmnsd_gtls_la_SOURCES = nsd_gtls.c nsd_gtls.h nsdsel_gtls.c nsdsel_gtls.h
+lmnsd_gtls_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) $(gnutls_cflags)
+lmnsd_gtls_la_LDFLAGS = -module -avoid-version
+lmnsd_gtls_la_LIBADD = $(gnutls_libs)
+endif
+
diff --git a/atomic.h b/runtime/atomic.h
index 2421c826..430ae7f0 100644
--- a/atomic.h
+++ b/runtime/atomic.h
@@ -13,22 +13,23 @@
*
* Copyright 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h" /* autotools! */
diff --git a/cfsysline.c b/runtime/cfsysline.c
index d3203ccc..ef21fb4b 100644
--- a/cfsysline.c
+++ b/runtime/cfsysline.c
@@ -7,20 +7,23 @@
*
* 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
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h"
@@ -34,7 +37,6 @@
#include <pwd.h>
#include <grp.h>
-#include "syslogd.h" /* TODO: when the module interface & library design is done, this should be able to go away */
#include "cfsysline.h"
#include "obj.h"
#include "errmsg.h"
diff --git a/cfsysline.h b/runtime/cfsysline.h
index 2eec18ab..07ab5fcd 100644
--- a/cfsysline.h
+++ b/runtime/cfsysline.h
@@ -2,22 +2,23 @@
*
* Copyright 2007 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef CFSYSLINE_H_INCLUDED
diff --git a/ctok.c b/runtime/ctok.c
index de2bd8a8..de2bd8a8 100644
--- a/ctok.c
+++ b/runtime/ctok.c
diff --git a/ctok.h b/runtime/ctok.h
index 591f0838..591f0838 100644
--- a/ctok.h
+++ b/runtime/ctok.h
diff --git a/ctok_token.c b/runtime/ctok_token.c
index 0f340675..0f340675 100644
--- a/ctok_token.c
+++ b/runtime/ctok_token.c
diff --git a/ctok_token.h b/runtime/ctok_token.h
index 346d5acd..346d5acd 100644
--- a/ctok_token.h
+++ b/runtime/ctok_token.h
diff --git a/datetime.c b/runtime/datetime.c
index a4817a6d..d72cac3c 100644
--- a/datetime.c
+++ b/runtime/datetime.c
@@ -7,22 +7,23 @@
*
* Copyright 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h"
diff --git a/datetime.h b/runtime/datetime.h
index a35dfe8a..fcb78172 100644
--- a/datetime.h
+++ b/runtime/datetime.h
@@ -2,22 +2,23 @@
*
* Copyright 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef INCLUDED_DATETIME_H
#define INCLUDED_DATETIME_H
diff --git a/debug.c b/runtime/debug.c
index 29c65cf1..f543efd8 100644
--- a/debug.c
+++ b/runtime/debug.c
@@ -15,22 +15,23 @@
*
* Copyright 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h" /* autotools! */
#include <stdio.h>
@@ -1144,8 +1145,6 @@ dbgPrintNameAdd(uchar *pName, dbgPrintName_t **ppRoot)
pEntry->pNext = *ppRoot; /* we enqueue at the front */
}
*ppRoot = pEntry;
-
-printf("Name %s added to %p\n", pName, *ppRoot);
}
diff --git a/debug.h b/runtime/debug.h
index 4dcc593a..214b7c05 100644
--- a/debug.h
+++ b/runtime/debug.h
@@ -5,22 +5,23 @@
*
* Copyright 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef DEBUG_H_INCLUDED
#define DEBUG_H_INCLUDED
diff --git a/errmsg.c b/runtime/errmsg.c
index 907046b9..1744c902 100644
--- a/errmsg.c
+++ b/runtime/errmsg.c
@@ -1,26 +1,28 @@
/* The errmsg object.
*
* Module begun 2008-03-05 by Rainer Gerhards, based on some code
- * from syslogd.c
+ * from syslogd.c. I converted this module to lgpl and have checked that
+ * all contributors agreed to that step.
*
* Copyright 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h"
@@ -31,7 +33,6 @@
#include <assert.h>
#include "rsyslog.h"
-#include "syslogd.h"
#include "obj.h"
#include "errmsg.h"
#include "sysvar.h"
@@ -81,7 +82,8 @@ LogError(int __attribute__((unused)) iErrCode, char *fmt, ... )
}
msg[sizeof(msg)/sizeof(char) - 1] = '\0'; /* just to be on the safe side... */
errno = 0;
- logmsgInternal(LOG_SYSLOG|LOG_ERR, msg, ADDDATE);
+
+ glblErrLogger((uchar*)msg);
ENDfunc
}
@@ -116,5 +118,12 @@ BEGINAbstractObjClassInit(errmsg, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* set our own handlers */
ENDObjClassInit(errmsg)
+/* Exit the class.
+ * rgerhards, 2008-04-17
+ */
+BEGINObjClassExit(errmsg, OBJ_IS_CORE_MODULE) /* class, version */
+ /* release objects we no longer need */
+ENDObjClassExit(errmsg)
+
/* vi:set ai:
*/
diff --git a/errmsg.h b/runtime/errmsg.h
index 12469581..bde6bcff 100644
--- a/errmsg.h
+++ b/runtime/errmsg.h
@@ -2,22 +2,23 @@
*
* Copyright 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef INCLUDED_ERRMSG_H
#define INCLUDED_ERRMSG_H
diff --git a/expr.c b/runtime/expr.c
index 9c357404..9c357404 100644
--- a/expr.c
+++ b/runtime/expr.c
diff --git a/expr.h b/runtime/expr.h
index 974b71ec..974b71ec 100644
--- a/expr.h
+++ b/runtime/expr.h
diff --git a/runtime/glbl.c b/runtime/glbl.c
new file mode 100644
index 00000000..20840318
--- /dev/null
+++ b/runtime/glbl.c
@@ -0,0 +1,267 @@
+/* glbl.c - this module holds global defintions and data items.
+ * These are shared among the runtime library. Their use should be
+ * limited to cases where it is actually needed. The main intension for
+ * implementing them was support for the transistion from v2 to v4
+ * (with fully modular design), but it turned out that there may also
+ * be some other good use cases besides backwards-compatibility.
+ *
+ * Module begun 2008-04-16 by Rainer Gerhards
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <assert.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "cfsysline.h"
+#include "glbl.h"
+
+/* some defaults */
+#ifndef DFLT_NETSTRM_DRVR
+# define DFLT_NETSTRM_DRVR ((uchar*)"ptcp")
+#endif
+#ifndef DFLT_NETSTRM_DRVR_CAF
+# define DFLT_NETSTRM_DRVR_CAF ((uchar*)"ca.pem")
+#endif
+#ifndef DFLT_NETSTRM_DRVR_KEYFILE
+# define DFLT_NETSTRM_DRVR_KEYFILE ((uchar*)"key.pem")
+#endif
+#ifndef DFLT_NETSTRM_DRVR_CERTFILE
+# define DFLT_NETSTRM_DRVR_CERTFILE ((uchar*)"cert.pem")
+#endif
+
+/* static data */
+DEFobjStaticHelpers
+
+/* static data
+ * For this object, these variables are obviously what makes the "meat" of the
+ * class...
+ */
+static uchar *pszWorkDir = NULL;
+static int iDefPFFamily = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */
+static int bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records during DNS lookup */
+static int option_DisallowWarning = 1; /* complain if message from disallowed sender is received */
+static int bDisableDNS = 0; /* don't look up IP addresses of remote messages */
+static uchar *LocalHostName = NULL;/* our hostname - read-only after startup */
+static uchar *LocalDomain; /* our local domain name - read-only after startup */
+static char **StripDomains = NULL;/* these domains may be stripped before writing logs - r/o after s.u., never touched by init */
+static char **LocalHosts = NULL;/* these hosts are logged with their hostname - read-only after startup, never touched by init */
+static uchar *pszDfltNetstrmDrvr = NULL; /* module name of default netstream driver */
+static uchar *pszDfltNetstrmDrvrCAF = NULL; /* default CA file for the netstrm driver */
+static uchar *pszDfltNetstrmDrvrKeyFile = NULL; /* default key file for the netstrm driver (server) */
+static uchar *pszDfltNetstrmDrvrCertFile = NULL; /* default cert file for the netstrm driver (server) */
+
+
+/* define a macro for the simple properties' set and get functions
+ * (which are always the same). This is only suitable for pretty
+ * simple cases which require neither checks nor memory allocation.
+ */
+#define SIMP_PROP(nameFunc, nameVar, dataType) \
+ SIMP_PROP_GET(nameFunc, nameVar, dataType) \
+ SIMP_PROP_SET(nameFunc, nameVar, dataType)
+#define SIMP_PROP_SET(nameFunc, nameVar, dataType) \
+static rsRetVal Set##nameFunc(dataType newVal) \
+{ \
+ nameVar = newVal; \
+ return RS_RET_OK; \
+}
+#define SIMP_PROP_GET(nameFunc, nameVar, dataType) \
+static dataType Get##nameFunc(void) \
+{ \
+ return(nameVar); \
+}
+
+SIMP_PROP(DefPFFamily, iDefPFFamily, int) /* note that in the future we may check the family argument */
+SIMP_PROP(DropMalPTRMsgs, bDropMalPTRMsgs, int)
+SIMP_PROP(Option_DisallowWarning, option_DisallowWarning, int)
+SIMP_PROP(DisableDNS, bDisableDNS, int)
+SIMP_PROP(LocalDomain, LocalDomain, uchar*)
+SIMP_PROP(StripDomains, StripDomains, char**)
+SIMP_PROP(LocalHosts, LocalHosts, char**)
+
+SIMP_PROP_SET(LocalHostName, LocalHostName, uchar*)
+SIMP_PROP_SET(DfltNetstrmDrvr, pszDfltNetstrmDrvr, uchar*) // TODO: use custom function which frees existing value
+SIMP_PROP_SET(DfltNetstrmDrvrCAF, pszDfltNetstrmDrvrCAF, uchar*) // TODO: use custom function which frees existing value
+SIMP_PROP_SET(DfltNetstrmDrvrKeyFile, pszDfltNetstrmDrvrKeyFile, uchar*) // TODO: use custom function which frees existing value
+SIMP_PROP_SET(DfltNetstrmDrvrCertFile, pszDfltNetstrmDrvrCertFile, uchar*) // TODO: use custom function which frees existing value
+
+#undef SIMP_PROP
+#undef SIMP_PROP_SET
+#undef SIMP_PROP_GET
+
+
+/* return our local hostname. if it is not set, "[localhost]" is returned
+ */
+static uchar*
+GetLocalHostName(void)
+{
+ return(LocalHostName == NULL ? (uchar*) "[localhost]" : LocalHostName);
+}
+
+
+/* return the current working directory */
+static uchar*
+GetWorkDir(void)
+{
+ return(pszWorkDir == NULL ? (uchar*) "" : pszWorkDir);
+}
+
+
+/* return the current default netstream driver */
+static uchar*
+GetDfltNetstrmDrvr(void)
+{
+ return(pszDfltNetstrmDrvr == NULL ? DFLT_NETSTRM_DRVR : pszDfltNetstrmDrvr);
+}
+
+
+/* return the current default netstream driver CA File */
+static uchar*
+GetDfltNetstrmDrvrCAF(void)
+{
+ return(pszDfltNetstrmDrvrCAF == NULL ? DFLT_NETSTRM_DRVR_CAF : pszDfltNetstrmDrvrCAF);
+}
+
+
+/* return the current default netstream driver key File */
+static uchar*
+GetDfltNetstrmDrvrKeyFile(void)
+{
+ return(pszDfltNetstrmDrvrKeyFile == NULL ? DFLT_NETSTRM_DRVR_KEYFILE : pszDfltNetstrmDrvrKeyFile);
+}
+
+
+/* return the current default netstream driver certificate File */
+static uchar*
+GetDfltNetstrmDrvrCertFile(void)
+{
+ return(pszDfltNetstrmDrvrCertFile == NULL ? DFLT_NETSTRM_DRVR_CERTFILE : pszDfltNetstrmDrvrCertFile);
+}
+
+
+/* queryInterface function
+ * rgerhards, 2008-02-21
+ */
+BEGINobjQueryInterface(glbl)
+CODESTARTobjQueryInterface(glbl)
+ if(pIf->ifVersion != glblCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->GetWorkDir = GetWorkDir;
+#define SIMP_PROP(name) \
+ pIf->Get##name = Get##name; \
+ pIf->Set##name = Set##name;
+ SIMP_PROP(DefPFFamily);
+ SIMP_PROP(DropMalPTRMsgs);
+ SIMP_PROP(Option_DisallowWarning);
+ SIMP_PROP(DisableDNS);
+ SIMP_PROP(LocalHostName)
+ SIMP_PROP(LocalDomain)
+ SIMP_PROP(StripDomains)
+ SIMP_PROP(LocalHosts)
+ SIMP_PROP(DfltNetstrmDrvr)
+ SIMP_PROP(DfltNetstrmDrvrCAF)
+ SIMP_PROP(DfltNetstrmDrvrKeyFile)
+ SIMP_PROP(DfltNetstrmDrvrCertFile)
+#undef SIMP_PROP
+finalize_it:
+ENDobjQueryInterface(glbl)
+
+
+/* Reset config variables to default values.
+ * rgerhards, 2008-04-17
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ if(pszDfltNetstrmDrvr != NULL) {
+ free(pszDfltNetstrmDrvr);
+ pszDfltNetstrmDrvr = NULL;
+ }
+ if(pszDfltNetstrmDrvrCAF != NULL) {
+ free(pszDfltNetstrmDrvrCAF);
+ pszDfltNetstrmDrvrCAF = NULL;
+ }
+ if(pszDfltNetstrmDrvrKeyFile != NULL) {
+ free(pszDfltNetstrmDrvrKeyFile);
+ pszDfltNetstrmDrvrKeyFile = NULL;
+ }
+ if(pszDfltNetstrmDrvrCertFile != NULL) {
+ free(pszDfltNetstrmDrvrCertFile);
+ pszDfltNetstrmDrvrCertFile = NULL;
+ }
+ if(pszWorkDir != NULL) {
+ free(pszWorkDir);
+ pszWorkDir = NULL;
+ }
+ bDropMalPTRMsgs = 0;
+ return RS_RET_OK;
+}
+
+
+
+/* Initialize the glbl class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+
+ /* register config handlers (TODO: we need to implement a way to unregister them) */
+ CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, NULL, &pszWorkDir, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, NULL, &bDropMalPTRMsgs, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriver", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvr, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercafile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrCAF, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriverkeyfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrKeyFile, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercertfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrCertFile, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL));
+ENDObjClassInit(glbl)
+
+
+/* Exit the glbl class.
+ * rgerhards, 2008-04-17
+ */
+BEGINObjClassExit(glbl, OBJ_IS_CORE_MODULE) /* class, version */
+ if(pszDfltNetstrmDrvr != NULL)
+ free(pszDfltNetstrmDrvr);
+ if(pszDfltNetstrmDrvrCAF != NULL)
+ free(pszDfltNetstrmDrvrCAF);
+ if(pszDfltNetstrmDrvrKeyFile != NULL)
+ free(pszDfltNetstrmDrvrKeyFile);
+ if(pszDfltNetstrmDrvrCertFile != NULL)
+ free(pszDfltNetstrmDrvrCertFile);
+ if(pszWorkDir != NULL)
+ free(pszWorkDir);
+ if(LocalHostName != NULL)
+ free(LocalHostName);
+ENDObjClassExit(glbl)
+
+/* vi:set ai:
+ */
diff --git a/runtime/glbl.h b/runtime/glbl.h
new file mode 100644
index 00000000..adfae27e
--- /dev/null
+++ b/runtime/glbl.h
@@ -0,0 +1,62 @@
+/* Definition of globally-accessible data items.
+ *
+ * This module provides access methods to items of global scope. Most often,
+ * these globals serve as defaults to initialize local settings. Currently,
+ * many of them are either constants or global variable references. However,
+ * this module provides the necessary hooks to change that at any time.
+ *
+ * Please note that there currently is no glbl.c file as we do not yet
+ * have any implementations.
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef GLBL_H_INCLUDED
+#define GLBL_H_INCLUDED
+
+#define glblGetIOBufSize() 4096 /* size of the IO buffer, e.g. for strm class */
+
+/* interfaces */
+BEGINinterface(glbl) /* name must also be changed in ENDinterface macro! */
+ uchar* (*GetWorkDir)(void);
+#define SIMP_PROP(name, dataType) \
+ dataType (*Get##name)(void); \
+ rsRetVal (*Set##name)(dataType);
+ SIMP_PROP(DefPFFamily, int);
+ SIMP_PROP(DropMalPTRMsgs, int);
+ SIMP_PROP(Option_DisallowWarning, int);
+ SIMP_PROP(DisableDNS, int);
+ SIMP_PROP(LocalHostName, uchar*)
+ SIMP_PROP(LocalDomain, uchar*)
+ SIMP_PROP(StripDomains, char**)
+ SIMP_PROP(LocalHosts, char**)
+ SIMP_PROP(DfltNetstrmDrvr, uchar*)
+ SIMP_PROP(DfltNetstrmDrvrCAF, uchar*)
+ SIMP_PROP(DfltNetstrmDrvrKeyFile, uchar*)
+ SIMP_PROP(DfltNetstrmDrvrCertFile, uchar*)
+#undef SIMP_PROP
+ENDinterface(glbl)
+#define glblCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+/* the remaining prototypes */
+PROTOTYPEObj(glbl);
+
+#endif /* #ifndef GLBL_H_INCLUDED */
diff --git a/linkedlist.c b/runtime/linkedlist.c
index 383cf488..8f842e43 100644
--- a/linkedlist.c
+++ b/runtime/linkedlist.c
@@ -13,22 +13,23 @@
*
* Copyright (C) 2007, 2008 by Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h"
@@ -409,7 +410,5 @@ finalize_it:
RETiRet;
}
-
-/*
- * vi:set ai:
+/* vim:set ai:
*/
diff --git a/linkedlist.h b/runtime/linkedlist.h
index 98fb76a5..aeacd6d7 100644
--- a/linkedlist.h
+++ b/runtime/linkedlist.h
@@ -1,23 +1,24 @@
/* Definition of the linkedlist object.
*
- * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef LINKEDLIST_H_INCLUDED
diff --git a/module-template.h b/runtime/module-template.h
index d5e142b4..5db73d33 100644
--- a/module-template.h
+++ b/runtime/module-template.h
@@ -6,22 +6,23 @@
*
* Copyright 2007 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef MODULE_TEMPLATE_H_INCLUDED
#define MODULE_TEMPLATE_H_INCLUDED 1
diff --git a/modules.c b/runtime/modules.c
index 32a71c0c..1e59a5fc 100644
--- a/modules.c
+++ b/runtime/modules.c
@@ -13,22 +13,23 @@
*
* Copyright 2007 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h"
#include "rsyslog.h"
@@ -48,7 +49,6 @@
#include <unistd.h>
#include <sys/file.h>
-#include "syslogd.h"
#include "cfsysline.h"
#include "modules.h"
#include "errmsg.h"
@@ -522,11 +522,16 @@ modUnloadAndDestructAll(eModLinkType_t modLinkTypesToUnload)
if(modLinkTypesToUnload == eMOD_LINK_ALL || pModCurr->eLinkType == modLinkTypesToUnload) {
if(modUnlinkAndDestroy(&pModCurr) == RS_RET_MODULE_STILL_REFERENCED) {
pModCurr = GetNxt(pModCurr);
+ } else {
+ /* Note: if the module was successfully unloaded, it has updated the
+ * pModCurr pointer to the next module. However, the unload process may
+ * still have indirectly referenced the pointer list in a way that the
+ * unloaded module is not aware of. So we restart the unload process
+ * to make sure we do not fall into a trap (what we did ;)). The
+ * performance toll is minimal. -- rgerhards, 2008-04-28
+ */
+ pModCurr = GetNxt(NULL);
}
- /* Note: if the module was successfully unloaded, it has updated the
- * pModCurr pointer to the next module. So we do NOT need to advance
- * to the next module on successful unload.
- */
} else {
pModCurr = GetNxt(pModCurr);
}
diff --git a/modules.h b/runtime/modules.h
index a8371d05..7d34bcf7 100644
--- a/modules.h
+++ b/runtime/modules.h
@@ -12,30 +12,30 @@
*
* File begun on 2007-07-22 by RGerhards
*
- * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef MODULES_H_INCLUDED
#define MODULES_H_INCLUDED 1
#include "objomsr.h"
-#include "threads.h"
/* the following define defines the current version of the module interface.
diff --git a/msg.c b/runtime/msg.c
index 9a12d572..b421c88f 100644
--- a/msg.c
+++ b/runtime/msg.c
@@ -7,24 +7,25 @@
* of the "old" message code without any modifications. However, it
* helps to have things at the right place one we go to the meat of it.
*
- * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h"
#include <stdio.h>
@@ -35,7 +36,6 @@
#include <assert.h>
#include <ctype.h>
#include "rsyslog.h"
-#include "syslogd.h"
#include "srUtils.h"
#include "stringbuf.h"
#include "template.h"
@@ -263,6 +263,8 @@ CODESTARTobjDestruct(msg)
free(pThis->pszHOSTNAME);
if(pThis->pszRcvFrom != NULL)
free(pThis->pszRcvFrom);
+ if(pThis->pszRcvFromIP != NULL)
+ free(pThis->pszRcvFromIP);
if(pThis->pszMSG != NULL)
free(pThis->pszMSG);
if(pThis->pszFacility != NULL)
@@ -422,6 +424,7 @@ static rsRetVal MsgSerialize(msg_t *pThis, strm_t *pStrm)
objSerializePTR(pStrm, pszTAG, PSZ);
objSerializePTR(pStrm, pszHOSTNAME, PSZ);
objSerializePTR(pStrm, pszRcvFrom, PSZ);
+ objSerializePTR(pStrm, pszRcvFromIP, PSZ);
objSerializePTR(pStrm, pCSStrucData, CSTR);
objSerializePTR(pStrm, pCSAPPNAME, CSTR);
@@ -684,7 +687,6 @@ char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt)
MsgLock(pM);
if(pM->pszTIMESTAMP3164 == NULL) {
if((pM->pszTIMESTAMP3164 = malloc(16)) == NULL) {
- glblHadMemShortage = 1;
MsgUnlock(pM);
return "";
}
@@ -696,7 +698,6 @@ char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt)
MsgLock(pM);
if(pM->pszTIMESTAMP_MySQL == NULL) {
if((pM->pszTIMESTAMP_MySQL = malloc(15)) == NULL) {
- glblHadMemShortage = 1;
MsgUnlock(pM);
return "";
}
@@ -708,7 +709,6 @@ char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt)
MsgLock(pM);
if(pM->pszTIMESTAMP_PgSQL == NULL) {
if((pM->pszTIMESTAMP_PgSQL = malloc(21)) == NULL) {
- glblHadMemShortage = 1;
MsgUnlock(pM);
return "";
}
@@ -720,7 +720,6 @@ char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt)
MsgLock(pM);
if(pM->pszTIMESTAMP3164 == NULL) {
if((pM->pszTIMESTAMP3164 = malloc(16)) == NULL) {
- glblHadMemShortage = 1;
MsgUnlock(pM);
return "";
}
@@ -732,7 +731,6 @@ char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt)
MsgLock(pM);
if(pM->pszTIMESTAMP3339 == NULL) {
if((pM->pszTIMESTAMP3339 = malloc(33)) == NULL) {
- glblHadMemShortage = 1;
MsgUnlock(pM);
return ""; /* TODO: check this: can it cause a free() of constant memory?) */
}
@@ -754,7 +752,6 @@ char *getTimeGenerated(msg_t *pM, enum tplFormatTypes eFmt)
MsgLock(pM);
if(pM->pszRcvdAt3164 == NULL) {
if((pM->pszRcvdAt3164 = malloc(16)) == NULL) {
- glblHadMemShortage = 1;
MsgUnlock(pM);
return "";
}
@@ -766,7 +763,6 @@ char *getTimeGenerated(msg_t *pM, enum tplFormatTypes eFmt)
MsgLock(pM);
if(pM->pszRcvdAt_MySQL == NULL) {
if((pM->pszRcvdAt_MySQL = malloc(15)) == NULL) {
- glblHadMemShortage = 1;
MsgUnlock(pM);
return "";
}
@@ -778,7 +774,6 @@ char *getTimeGenerated(msg_t *pM, enum tplFormatTypes eFmt)
MsgLock(pM);
if(pM->pszRcvdAt_PgSQL == NULL) {
if((pM->pszRcvdAt_PgSQL = malloc(21)) == NULL) {
- glblHadMemShortage = 1;
MsgUnlock(pM);
return "";
}
@@ -790,7 +785,6 @@ char *getTimeGenerated(msg_t *pM, enum tplFormatTypes eFmt)
MsgLock(pM);
if(pM->pszRcvdAt3164 == NULL) {
if((pM->pszRcvdAt3164 = malloc(16)) == NULL) {
- glblHadMemShortage = 1;
MsgUnlock(pM);
return "";
}
@@ -802,7 +796,6 @@ char *getTimeGenerated(msg_t *pM, enum tplFormatTypes eFmt)
MsgLock(pM);
if(pM->pszRcvdAt3339 == NULL) {
if((pM->pszRcvdAt3339 = malloc(33)) == NULL) {
- glblHadMemShortage = 1;
MsgUnlock(pM);
return "";
}
@@ -1181,6 +1174,18 @@ char *getRcvFrom(msg_t *pM)
return (char*) pM->pszRcvFrom;
}
+
+uchar *getRcvFromIP(msg_t *pM)
+{
+ if(pM == NULL)
+ return (uchar*) "";
+ else
+ if(pM->pszRcvFromIP == NULL)
+ return (uchar*) "";
+ else
+ return pM->pszRcvFromIP;
+}
+
/* rgerhards 2004-11-24: set STRUCTURED DATA in msg object
*/
rsRetVal MsgSetStructuredData(msg_t *pMsg, char* pszStrucData)
@@ -1354,6 +1359,24 @@ void MsgSetRcvFrom(msg_t *pMsg, char* pszRcvFrom)
}
+/* rgerhards 2005-05-16: set pszRcvFromIP in msg object */
+rsRetVal
+MsgSetRcvFromIP(msg_t *pMsg, uchar* pszRcvFromIP)
+{
+ DEFiRet;
+ assert(pMsg != NULL);
+ if(pMsg->pszRcvFromIP != NULL) {
+ free(pMsg->pszRcvFromIP);
+ pMsg->iLenRcvFromIP = 0;
+ }
+
+ CHKmalloc(pMsg->pszRcvFromIP = (uchar*)strdup((char*)pszRcvFromIP));
+ pMsg->iLenRcvFromIP = strlen((char*)pszRcvFromIP);
+finalize_it:
+ RETiRet;
+}
+
+
/* Set the HOSTNAME to a caller-provided string. This is thought
* to be a heap buffer that the caller will no longer use. This
* function is a performance optimization over MsgSetHOSTNAME().
@@ -1498,7 +1521,6 @@ static uchar *getNOW(eNOWType eNow)
struct syslogTime t;
if((pBuf = (uchar*) malloc(sizeof(uchar) * tmpBUFSIZE)) == NULL) {
- glblHadMemShortage = 1;
return NULL;
}
@@ -1608,6 +1630,8 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
pRes = getUxTradMsg(pMsg);
} else if(!strcmp((char*) pName, "fromhost")) {
pRes = getRcvFrom(pMsg);
+ } else if(!strcmp((char*) pName, "fromhost-ip")) {
+ pRes = (char*) getRcvFromIP(pMsg);
} else if(!strcmp((char*) pName, "source") || !strcmp((char*) pName, "hostname")) {
pRes = getHOSTNAME(pMsg);
} else if(!strcmp((char*) pName, "syslogtag")) {
@@ -2215,10 +2239,12 @@ rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp)
MsgSetUxTradMsg(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.pStr));
} else if(isProp("pszTAG")) {
MsgSetTAG(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.pStr));
+ } else if(isProp("pszRcvFromIP")) {
+ MsgSetRcvFromIP(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr));
} else if(isProp("pszRcvFrom")) {
- MsgSetHOSTNAME(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.pStr));
- } else if(isProp("pszHOSTNAME")) {
MsgSetRcvFrom(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.pStr));
+ } else if(isProp("pszHOSTNAME")) {
+ MsgSetHOSTNAME(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.pStr));
} else if(isProp("pCSStrucData")) {
MsgSetStructuredData(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.pStr));
} else if(isProp("pCSAPPNAME")) {
diff --git a/msg.h b/runtime/msg.h
index 61feaddb..084123b7 100644
--- a/msg.h
+++ b/runtime/msg.h
@@ -5,22 +5,23 @@
*
* Copyright 2007 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "template.h" /* this is a quirk, but these two are too interdependant... */
@@ -88,6 +89,8 @@ struct msg {
int iLenHOSTNAME; /* Length of HOSTNAME */
uchar *pszRcvFrom; /* System message was received from */
int iLenRcvFrom; /* Length of pszRcvFrom */
+ uchar *pszRcvFromIP; /* IP of system message was received from */
+ int iLenRcvFromIP; /* Length of pszRcvFromIP */
short iProtocolVersion;/* protocol version of message received 0 - legacy, 1 syslog-protocol) */
cstr_t *pCSProgName; /* the (BSD) program name */
cstr_t *pCSStrucData;/* STRUCTURED-DATA */
@@ -106,7 +109,6 @@ struct msg {
char *pszTIMESTAMP_PgSQL;/* TIMESTAMP as PgSQL formatted string (always 21 characters) */
int msgFlags; /* flags associated with this message */
};
-typedef struct msg msg_t; /* new name */
/* function prototypes
*/
@@ -149,6 +151,7 @@ char *getStructuredData(msg_t *pM);
int getProgramNameLen(msg_t *pM);
char *getProgramName(msg_t *pM);
void MsgSetRcvFrom(msg_t *pMsg, char* pszRcvFrom);
+rsRetVal MsgSetRcvFromIP(msg_t *pMsg, uchar* pszRcvFromIP);
void MsgAssignHOSTNAME(msg_t *pMsg, char *pBuf);
void MsgSetHOSTNAME(msg_t *pMsg, char* pszHOSTNAME);
int MsgSetUxTradMsg(msg_t *pMsg, char* pszUxTradMsg);
diff --git a/net.c b/runtime/net.c
index bbd6bec7..7663b1b3 100644
--- a/net.c
+++ b/runtime/net.c
@@ -4,7 +4,7 @@
* File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
* This file is under development and has not yet arrived at being fully
* self-contained and a real object. So far, it is mostly an excerpt
- * of the "old" message code without any modifications. However, it
+ * of the "old" networking code without any modifications. However, it
* helps to have things at the right place one we go to the meat of it.
*
* Starting 2007-12-24, I have begun to shuffle more network-related code
@@ -12,24 +12,32 @@
* long term, but it is good to have it out of syslogd.c. Maybe this here is
* an interim location ;)
*
- * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * rgerhards, 2008-04-16: I changed this code to LGPL today. I carefully analyzed
+ * that it does not borrow code from the original sysklogd and that I have
+ * permission to do so from all other contributors. My analysis found that all
+ * code from sysklogd has been superseeded by our own functionality, so it
+ * is OK to move this file to LGPL. Some variable sysklogd variable names
+ * remain, but even this will change as the net object evolves.
*
- * Rsyslog is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h"
@@ -47,7 +55,6 @@
#include <fcntl.h>
#include <unistd.h>
-#include "syslogd.h"
#include "syslogd-types.h"
#include "module-template.h"
#include "parse.h"
@@ -61,6 +68,7 @@ MODULE_TYPE_LIB
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
/* support for defining allowed TCP and UDP senders. We use the same
* structure to implement this (a linked list), but we define two different
@@ -123,7 +131,6 @@ static rsRetVal AddAllowedSenderEntry(struct AllowedSenders **ppRoot, struct All
assert(iAllow != NULL);
if((pEntry = (struct AllowedSenders*) calloc(1, sizeof(struct AllowedSenders))) == NULL) {
- glblHadMemShortage = 1;
return RS_RET_OUT_OF_MEMORY; /* no options left :( */
}
@@ -227,7 +234,7 @@ static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedS
iRet = AddAllowedSenderEntry(ppRoot, ppLast, iAllow, iSignificantBits);
} else {
/* we need to process a hostname ACL */
- if (DisableDNS) {
+ if(glbl.GetDisableDNS()) {
errmsg.LogError(NO_ERRCODE, "Ignoring hostname based ACLs because DNS is disabled.");
ABORT_FINALIZE(RS_RET_OK);
}
@@ -267,7 +274,6 @@ static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedS
iSignificantBits = 32;
allowIP.flags = 0;
if((allowIP.addr.NetAddr = malloc(res->ai_addrlen)) == NULL) {
- glblHadMemShortage = 1;
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
memcpy(allowIP.addr.NetAddr, res->ai_addr, res->ai_addrlen);
@@ -284,7 +290,6 @@ static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedS
allowIP.flags = 0;
if((allowIP.addr.NetAddr = malloc(sizeof(struct sockaddr_in)))
== NULL) {
- glblHadMemShortage = 1;
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
SIN(allowIP.addr.NetAddr)->sin_family = AF_INET;
@@ -306,7 +311,6 @@ static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedS
iSignificantBits = 128;
allowIP.flags = 0;
if((allowIP.addr.NetAddr = malloc(res->ai_addrlen)) == NULL) {
- glblHadMemShortage = 1;
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
memcpy(allowIP.addr.NetAddr, res->ai_addr, res->ai_addrlen);
@@ -622,6 +626,8 @@ should_use_so_bsdcompat(void)
* but has been moved out of it because of clarity and fuctional separation.
* It must be provided by the socket we received the message on as well as
* a NI_MAXHOST size large character buffer for the FQDN.
+ * 2008-05-16 rgerhards: added field for IP address representation. Must also
+ * be NI_MAXHOST size large.
*
* Please see http://www.hmug.org/man/3/getnameinfo.php (under Caveats)
* for some explanation of the code found below. We do by default not
@@ -631,27 +637,27 @@ should_use_so_bsdcompat(void)
* message should be processed (1) or discarded (0).
*/
static rsRetVal
-gethname(struct sockaddr_storage *f, uchar *pszHostFQDN)
+gethname(struct sockaddr_storage *f, uchar *pszHostFQDN, uchar *ip)
{
DEFiRet;
int error;
sigset_t omask, nmask;
- char ip[NI_MAXHOST];
struct addrinfo hints, *res;
assert(f != NULL);
assert(pszHostFQDN != NULL);
error = getnameinfo((struct sockaddr *)f, SALEN((struct sockaddr *)f),
- ip, sizeof ip, NULL, 0, NI_NUMERICHOST);
+ (char*) ip, sizeof ip, NULL, 0, NI_NUMERICHOST);
if (error) {
dbgprintf("Malformed from address %s\n", gai_strerror(error));
strcpy((char*) pszHostFQDN, "???");
+ strcpy((char*) ip, "???");
ABORT_FINALIZE(RS_RET_INVALID_SOURCE);
}
- if (!DisableDNS) {
+ if(!glbl.GetDisableDNS()) {
sigemptyset(&nmask);
sigaddset(&nmask, SIGHUP);
pthread_sigmask(SIG_BLOCK, &nmask, &omask);
@@ -662,7 +668,6 @@ gethname(struct sockaddr_storage *f, uchar *pszHostFQDN)
if (error == 0) {
memset (&hints, 0, sizeof (struct addrinfo));
hints.ai_flags = AI_NUMERICHOST;
- hints.ai_socktype = SOCK_DGRAM;
/* we now do a lookup once again. This one should fail,
* because we should not have obtained a non-numeric address. If
@@ -680,7 +685,7 @@ gethname(struct sockaddr_storage *f, uchar *pszHostFQDN)
* time being, we simply drop the name we obtained and use the IP - that one
* is OK in any way. We do also log the error message. rgerhards, 2007-07-16
*/
- if(bDropMalPTRMsgs == 1) {
+ if(glbl.GetDropMalPTRMsgs() == 1) {
snprintf((char*)szErrMsg, sizeof(szErrMsg) / sizeof(uchar),
"Malicious PTR record, message dropped "
"IP = \"%s\" HOST = \"%s\"",
@@ -708,9 +713,9 @@ gethname(struct sockaddr_storage *f, uchar *pszHostFQDN)
pthread_sigmask(SIG_SETMASK, &omask, NULL);
}
- if (error || DisableDNS) {
+ if(error || glbl.GetDisableDNS()) {
dbgprintf("Host name for your address (%s) unknown\n", ip);
- strcpy((char*) pszHostFQDN, ip);
+ strcpy((char*) pszHostFQDN, (char*)ip);
ABORT_FINALIZE(RS_RET_ADDRESS_UNKNOWN);
}
@@ -770,8 +775,9 @@ void debugListenInfo(int fd, char *type)
* there is no way to check it. We use this way of doing things because it
* frees us from using dynamic memory allocation where it really does not
* pay.
+ * 2005-05-16 rgerhards: added IP representation. Must also be NI_MAXHOST
*/
-rsRetVal cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN)
+rsRetVal cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN, uchar *pszIP)
{
DEFiRet;
register uchar *p;
@@ -781,7 +787,7 @@ rsRetVal cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN
assert(pszHost != NULL);
assert(pszHostFQDN != NULL);
- iRet = gethname(f, pszHostFQDN);
+ iRet = gethname(f, pszHostFQDN, pszIP);
if(iRet == RS_RET_INVALID_SOURCE || iRet == RS_RET_ADDRESS_UNKNOWN) {
strcpy((char*) pszHost, (char*) pszHostFQDN); /* we use whatever was provided as replacement */
@@ -792,9 +798,8 @@ rsRetVal cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN
/* if we reach this point, we obtained a non-numeric hostname and can now process it */
- /* Convert to lower case, just like LocalDomain above
- */
- for (p = pszHostFQDN ; *p ; p++)
+ /* Convert to lower case */
+ for(p = pszHostFQDN ; *p ; p++)
if (isupper((int) *p))
*p = tolower(*p);
@@ -810,16 +815,19 @@ rsRetVal cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN
*/
strcpy((char*)pszHost, (char*)pszHostFQDN);
if ((p = (uchar*) strchr((char*)pszHost, '.'))) { /* find start of domain name "machine.example.com" */
- if(strcmp((char*) (p + 1), LocalDomain) == 0) {
+ if(strcmp((char*)(p + 1), (char*)glbl.GetLocalDomain()) == 0) {
*p = '\0'; /* simply terminate the string */
} else {
/* now check if we belong to any of the domain names that were specified
* in the -s command line option. If so, remove and we are done.
+ * TODO: this must go away! -- rgerhards, 2008-04-16
+ * For proper modularization, this must be done different, e.g. via a
+ * "to be stripped" property of *this* object itself.
*/
- if (StripDomains) {
+ if(glbl.GetStripDomains() != NULL) {
count=0;
- while (StripDomains[count]) {
- if (strcmp((char*)(p + 1), StripDomains[count]) == 0) {
+ while(glbl.GetStripDomains()[count]) {
+ if (strcmp((char*)(p + 1), glbl.GetStripDomains()[count]) == 0) {
*p = '\0';
FINALIZE; /* we are done */
}
@@ -833,11 +841,12 @@ rsRetVal cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN
* door would be wide-open for all kinds of mixing up of hosts. Because of this,
* you'll see comparison against the full string (pszHost) below. The termination
* still occurs at *p, which points at the first dot after the hostname.
+ * TODO: this must also go away - see comment above -- rgerhards, 2008-04-16
*/
- if (LocalHosts) {
+ if(glbl.GetLocalHosts() != NULL) {
count=0;
- while (LocalHosts[count]) {
- if (!strcmp((char*)pszHost, LocalHosts[count])) {
+ while (glbl.GetLocalHosts()[count]) {
+ if (!strcmp((char*)pszHost, (char*)glbl.GetLocalHosts()[count])) {
*p = '\0';
break; /* we are done */
}
@@ -923,7 +932,7 @@ int *create_udp_socket(uchar *hostname, uchar *pszPort, int bIsServer)
hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
else
hints.ai_flags = AI_NUMERICSERV;
- hints.ai_family = family;
+ hints.ai_family = glbl.GetDefPFFamily();
hints.ai_socktype = SOCK_DGRAM;
error = getaddrinfo((char*) hostname, (char*) pszPort, &hints, &res);
if(error) {
@@ -1096,6 +1105,7 @@ ENDobjQueryInterface(net)
BEGINObjClassExit(net, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
CODESTARTObjClassExit(net)
/* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
ENDObjClassExit(net)
@@ -1107,6 +1117,7 @@ ENDObjClassExit(net)
BEGINAbstractObjClassInit(net, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
/* set our own handlers */
ENDObjClassInit(net)
diff --git a/net.h b/runtime/net.h
index 0f5b0bc1..9e471bf9 100644
--- a/net.h
+++ b/runtime/net.h
@@ -1,32 +1,37 @@
/* Definitions for network-related stuff.
*
- * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef INCLUDED_NET_H
#define INCLUDED_NET_H
-#ifdef SYSLOG_INET
#include <netinet/in.h>
#include <sys/socket.h> /* this is needed on HP UX -- rgerhards, 2008-03-04 */
+typedef enum _TCPFRAMINGMODE {
+ TCP_FRAMING_OCTET_STUFFING = 0, /* traditional LF-delimited */
+ TCP_FRAMING_OCTET_COUNTING = 1 /* -transport-tls like octet count */
+ } TCPFRAMINGMODE;
+
#define F_SET(where, flag) (where)|=(flag)
#define F_ISSET(where, flag) ((where)&(flag))==(flag)
#define F_UNSET(where, flag) (where)&=~(flag)
@@ -49,7 +54,7 @@ struct NetAddr {
};
#ifndef SO_BSDCOMPAT
- /* this shall prevent compiler errors due to undfined name */
+ /* this shall prevent compiler errors due to undefined name */
# define SO_BSDCOMPAT 0
#endif
@@ -88,7 +93,7 @@ struct AllowedSenders {
/* interfaces */
BEGINinterface(net) /* name must also be changed in ENDinterface macro! */
- rsRetVal (*cvthname)(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN);
+ rsRetVal (*cvthname)(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN, uchar *pszIP);
/* things to go away after proper modularization */
rsRetVal (*addAllowedSenderLine)(char* pName, uchar** ppRestOfConfLine);
void (*PrintAllowedSenders)(int iListToPrint);
@@ -106,7 +111,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 2 /* increment whenever you change the interface structure! */
+#define netCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */
/* prototypes */
PROTOTYPEObj(net);
@@ -114,5 +119,4 @@ PROTOTYPEObj(net);
/* the name of our library binary */
#define LM_NET_FILENAME "lmnet"
-#endif /* #ifdef SYSLOG_INET */
#endif /* #ifndef INCLUDED_NET_H */
diff --git a/runtime/netstrm.c b/runtime/netstrm.c
new file mode 100644
index 00000000..a1384a28
--- /dev/null
+++ b/runtime/netstrm.c
@@ -0,0 +1,309 @@
+/* netstrm.c
+ *
+ * This class implements a generic netstrmwork stream class. It supports
+ * sending and receiving data streams over a netstrmwork. The class abstracts
+ * the transport, though it is a safe assumption that TCP is being used.
+ * The class has a number of properties, among which are also ones to
+ * select privacy settings, eg by enabling TLS and/or GSSAPI. In the
+ * long run, this class shall provide all stream-oriented netstrmwork
+ * functionality inside rsyslog.
+ *
+ * It is a high-level class, which uses a number of helper objects
+ * to carry out its work (including, and most importantly, transport
+ * drivers).
+ *
+ * Work on this module begun 2008-04-17 by Rainer Gerhards. This code
+ * borrows from librelp's tcp.c/.h code. librelp is dual licensed and
+ * Rainer Gerhards and Adiscon GmbH have agreed to permit using the code
+ * under the terms of the GNU Lesser General Public License.
+ *
+ * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "rsyslog.h"
+#include "module-template.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "netstrms.h"
+#include "netstrm.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(errmsg)
+DEFobjCurrIf(netstrms)
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(netstrm) /* be sure to specify the object type also in END macro! */
+ENDobjConstruct(netstrm)
+
+
+/* destructor for the netstrm object */
+BEGINobjDestruct(netstrm) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(netstrm)
+ if(pThis->pDrvrData != NULL)
+ iRet = pThis->Drvr.Destruct(&pThis->pDrvrData);
+ENDobjDestruct(netstrm)
+
+
+/* ConstructionFinalizer */
+static rsRetVal
+netstrmConstructFinalize(netstrm_t *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ CHKiRet(pThis->Drvr.Construct(&pThis->pDrvrData));
+finalize_it:
+ RETiRet;
+}
+
+/* abort a connection. This is much like Destruct(), but tries
+ * to discard any unsent data. -- rgerhards, 2008-03-24
+ */
+static rsRetVal
+AbortDestruct(netstrm_t **ppThis)
+{
+ DEFiRet;
+ assert(ppThis != NULL);
+ ISOBJ_TYPE_assert((*ppThis), netstrm);
+
+ /* we do NOT exit on error, because that would make things worse */
+ (*ppThis)->Drvr.Abort((*ppThis)->pDrvrData);
+ iRet = netstrmDestruct(ppThis);
+
+ RETiRet;
+}
+
+
+/* accept an incoming connection request
+ * The netstrm instance that had the incoming request must be provided. If
+ * the connection request succeeds, a new netstrm object is created and
+ * passed back to the caller. The caller is responsible for destructing it.
+ * pReq is the nsd_t obj that has the accept request.
+ * rgerhards, 2008-04-21
+ */
+static rsRetVal
+AcceptConnReq(netstrm_t *pThis, netstrm_t **ppNew)
+{
+ nsd_t *pNewNsd = NULL;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ assert(ppNew != NULL);
+
+ /* accept the new connection */
+ CHKiRet(pThis->Drvr.AcceptConnReq(pThis->pDrvrData, &pNewNsd));
+ /* construct our object so that we can use it... */
+ CHKiRet(objUse(netstrms, DONT_LOAD_LIB)); /* use netstrms obj if not already done so */
+ CHKiRet(netstrms.CreateStrm(pThis->pNS, ppNew));
+ (*ppNew)->pDrvrData = pNewNsd;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ /* the close may be redundant, but that doesn't hurt... */
+ if(pNewNsd != NULL)
+ pThis->Drvr.Destruct(&pNewNsd);
+ }
+
+ RETiRet;
+}
+
+
+/* make the netstrm listen to specified port and IP.
+ * pLstnIP points to the port to listen to (NULL means "all"),
+ * iMaxSess has the maximum number of sessions permitted (this ist just a hint).
+ * pLstnPort must point to a port name or number. NULL is NOT permitted.
+ * rgerhards, 2008-04-22
+ */
+static rsRetVal
+LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+ uchar *pLstnPort, uchar *pLstnIP, int iSessMax)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pNS, netstrms);
+ assert(fAddLstn != NULL);
+ assert(pLstnPort != NULL);
+
+ CHKiRet(pNS->Drvr.LstnInit(pNS, pUsr, fAddLstn, pLstnPort, pLstnIP, iSessMax));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* receive data from a tcp socket
+ * The lenBuf parameter must contain the max buffer size on entry and contains
+ * the number of octets read (or -1 in case of error) on exit. This function
+ * never blocks, not even when called on a blocking socket. That is important
+ * for client sockets, which are set to block during send, but should not
+ * block when trying to read data. If *pLenBuf is -1, an error occured and
+ * errno holds the exact error cause.
+ * rgerhards, 2008-03-17
+ */
+static rsRetVal
+Rcv(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.Rcv(pThis->pDrvrData, pBuf, pLenBuf);
+ RETiRet;
+}
+
+
+/* set the driver mode
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+SetDrvrMode(netstrm_t *pThis, int iMode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetMode(pThis->pDrvrData, iMode);
+ RETiRet;
+}
+
+
+/* send a buffer. On entry, pLenBuf contains the number of octets to
+ * write. On exit, it contains the number of octets actually written.
+ * If this number is lower than on entry, only a partial buffer has
+ * been written.
+ * rgerhards, 2008-03-19
+ */
+static rsRetVal
+Send(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.Send(pThis->pDrvrData, pBuf, pLenBuf);
+ RETiRet;
+}
+
+
+/* get remote hname - slim wrapper for NSD driver function */
+static rsRetVal
+GetRemoteHName(netstrm_t *pThis, uchar **ppsz)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.GetRemoteHName(pThis->pDrvrData, ppsz);
+ RETiRet;
+}
+
+
+/* get remote IP - slim wrapper for NSD driver function */
+static rsRetVal
+GetRemoteIP(netstrm_t *pThis, uchar **ppsz)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.GetRemoteIP(pThis->pDrvrData, ppsz);
+ RETiRet;
+}
+
+
+/* open a connection to a remote host (server).
+ * rgerhards, 2008-03-19
+ */
+static rsRetVal
+Connect(netstrm_t *pThis, int family, uchar *port, uchar *host)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ assert(port != NULL);
+ assert(host != NULL);
+ iRet = pThis->Drvr.Connect(pThis->pDrvrData, family, port, host);
+ RETiRet;
+}
+
+
+/* Provide access to the underlying OS socket. This is dirty
+ * and scheduled to be removed. Does not work with all nsd drivers.
+ * See comment in netstrm interface for details.
+ * rgerhards, 2008-05-05
+ */
+static rsRetVal
+GetSock(netstrm_t *pThis, int *pSock)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ assert(pSock != NULL);
+ iRet = pThis->Drvr.GetSock(pThis->pDrvrData, pSock);
+ RETiRet;
+}
+
+
+/* queryInterface function
+ */
+BEGINobjQueryInterface(netstrm)
+CODESTARTobjQueryInterface(netstrm)
+ if(pIf->ifVersion != netstrmCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = netstrmConstruct;
+ pIf->ConstructFinalize = netstrmConstructFinalize;
+ pIf->Destruct = netstrmDestruct;
+ pIf->AbortDestruct = AbortDestruct;
+ pIf->Rcv = Rcv;
+ pIf->Send = Send;
+ pIf->Connect = Connect;
+ pIf->LstnInit = LstnInit;
+ pIf->AcceptConnReq = AcceptConnReq;
+ pIf->GetRemoteHName = GetRemoteHName;
+ pIf->GetRemoteIP = GetRemoteIP;
+ pIf->SetDrvrMode = SetDrvrMode;
+ pIf->GetSock = GetSock;
+finalize_it:
+ENDobjQueryInterface(netstrm)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(netstrm, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(netstrm)
+ /* release objects we no longer need */
+ objRelease(errmsg, CORE_COMPONENT);
+ objRelease(netstrms, DONT_LOAD_LIB);
+ENDObjClassExit(netstrm)
+
+
+/* Initialize the netstrm class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINAbstractObjClassInit(netstrm, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+
+ /* set our own handlers */
+ENDObjClassInit(netstrm)
+/* vi:set ai:
+ */
diff --git a/runtime/netstrm.h b/runtime/netstrm.h
new file mode 100644
index 00000000..a15c1d9b
--- /dev/null
+++ b/runtime/netstrm.h
@@ -0,0 +1,70 @@
+/* Definitions for the stream-based netstrmworking class.
+ *
+ * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NETSTRM_H
+#define INCLUDED_NETSTRM_H
+
+#include "netstrms.h"
+
+/* the netstrm object */
+struct netstrm_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ nsd_t *pDrvrData; /**< the driver's data elements (at most other places, this is called pNsd) */
+ nsd_if_t Drvr; /**< our stream driver */
+ netstrms_t *pNS; /**< pointer to our netstream subsystem object */
+};
+
+
+/* interface */
+BEGINinterface(netstrm) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(netstrm_t **ppThis);
+ rsRetVal (*ConstructFinalize)(netstrm_t *pThis);
+ rsRetVal (*Destruct)(netstrm_t **ppThis);
+ rsRetVal (*AbortDestruct)(netstrm_t **ppThis);
+ rsRetVal (*LstnInit)(netstrms_t *pNS, void *pUsr, rsRetVal(*)(void*,netstrm_t*),
+ uchar *pLstnPort, uchar *pLstnIP, int iSessMax);
+ rsRetVal (*AcceptConnReq)(netstrm_t *pThis, netstrm_t **ppNew);
+ rsRetVal (*Rcv)(netstrm_t *pThis, uchar *pRcvBuf, ssize_t *pLenBuf);
+ rsRetVal (*Send)(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf);
+ rsRetVal (*Connect)(netstrm_t *pThis, int family, unsigned char *port, unsigned char *host);
+ rsRetVal (*GetRemoteHName)(netstrm_t *pThis, uchar **pszName);
+ rsRetVal (*GetRemoteIP)(netstrm_t *pThis, uchar **pszIP);
+ rsRetVal (*SetDrvrMode)(netstrm_t *pThis, int iMode);
+ /* the GetSock() below is a hack to make imgssapi work. In the long term,
+ * we should migrate imgssapi to a stream driver, which will relieve us of
+ * this problem. Please note that nobody else should use GetSock(). Using it
+ * will also tie the caller to nsd_ptcp, because other drivers may not support
+ * it at all. Once the imgssapi problem is solved, GetSock should be removed from
+ * this interface. -- rgerhards, 2008-05-05
+ */
+ rsRetVal (*GetSock)(netstrm_t *pThis, int *pSock);
+ENDinterface(netstrm)
+#define netstrmCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+/* prototypes */
+PROTOTYPEObj(netstrm);
+
+/* the name of our library binary */
+#define LM_NETSTRM_FILENAME LM_NETSTRMS_FILENAME
+
+#endif /* #ifndef INCLUDED_NETSTRM_H */
diff --git a/runtime/netstrms.c b/runtime/netstrms.c
new file mode 100644
index 00000000..03a46329
--- /dev/null
+++ b/runtime/netstrms.c
@@ -0,0 +1,276 @@
+/* netstrms.c
+ *
+ * Work on this module begung 2008-04-23 by Rainer Gerhards.
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "rsyslog.h"
+#include "module-template.h"
+#include "obj.h"
+//#include "errmsg.h"
+#include "nsd.h"
+#include "netstrm.h"
+#include "nssel.h"
+#include "netstrms.h"
+
+MODULE_TYPE_LIB
+
+/* static data */
+DEFobjStaticHelpers
+//DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(netstrm)
+
+
+/* load our low-level driver. This must be done before any
+ * driver-specific functions (allmost all...) can be carried
+ * out. Note that the driver's .ifIsLoaded is correctly
+ * initialized by calloc() and we depend on that.
+ * WARNING: this code is mostly identical to similar code in
+ * nssel.c - TODO: abstract it and move it to some common place.
+ * rgerhards, 2008-04-18
+ */
+static rsRetVal
+loadDrvr(netstrms_t *pThis)
+{
+ DEFiRet;
+ uchar *pBaseDrvrName;
+ uchar szDrvrName[48]; /* 48 shall be large enough */
+
+ pBaseDrvrName = pThis->pBaseDrvrName;
+ if(pBaseDrvrName == NULL) /* if no drvr name is set, use system default */
+ pBaseDrvrName = glbl.GetDfltNetstrmDrvr();
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmnsd_%s", pBaseDrvrName) == sizeof(szDrvrName))
+ ABORT_FINALIZE(RS_RET_DRVRNAME_TOO_LONG);
+ CHKmalloc(pThis->pDrvrName = (uchar*) strdup((char*)szDrvrName));
+
+ pThis->Drvr.ifVersion = nsdCURR_IF_VERSION;
+ /* The pDrvrName+2 below is a hack to obtain the object name. It
+ * safes us to have yet another variable with the name without "lm" in
+ * front of it. If we change the module load interface, we may re-think
+ * about this hack, but for the time being it is efficient and clean
+ * enough. -- rgerhards, 2008-04-18
+ */
+ CHKiRet(obj.UseObj(__FILE__, szDrvrName+2, szDrvrName, (void*) &pThis->Drvr));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->pDrvrName != NULL)
+ free(pThis->pDrvrName);
+ pThis->pDrvrName = NULL;
+ }
+ RETiRet;
+}
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(netstrms) /* be sure to specify the object type also in END macro! */
+ENDobjConstruct(netstrms)
+
+
+/* destructor for the netstrms object */
+BEGINobjDestruct(netstrms) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(netstrms)
+ /* and now we must release our driver, if we got one. We use the presence of
+ * a driver name string as load indicator (because we also need that string
+ * to release the driver
+ */
+ if(pThis->pDrvrName != NULL) {
+ obj.ReleaseObj(__FILE__, pThis->pDrvrName+2, pThis->pDrvrName, (void*) &pThis->Drvr);
+ free(pThis->pDrvrName);
+ }
+ if(pThis->pBaseDrvrName != NULL) {
+ free(pThis->pBaseDrvrName);
+ pThis->pBaseDrvrName = NULL;
+ }
+ENDobjDestruct(netstrms)
+
+
+/* ConstructionFinalizer */
+static rsRetVal
+netstrmsConstructFinalize(netstrms_t *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ CHKiRet(loadDrvr(pThis));
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the base driver name. If the driver name
+ * is set to NULL, the previously set name is deleted but
+ * no name set again (which results in the system default being
+ * used)-- rgerhards, 2008-05-05
+ */
+static rsRetVal
+SetDrvrName(netstrms_t *pThis, uchar *pszName)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ if(pThis->pBaseDrvrName != NULL) {
+ free(pThis->pBaseDrvrName);
+ pThis->pBaseDrvrName = NULL;
+ }
+
+ if(pszName != NULL) {
+ CHKmalloc(pThis->pBaseDrvrName = (uchar*) strdup((char*) pszName));
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the driver mode -- rgerhards, 2008-04-30
+ */
+static rsRetVal
+SetDrvrMode(netstrms_t *pThis, int iMode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ pThis->iDrvrMode = iMode;
+ RETiRet;
+}
+
+
+/* return the driver mode
+ * We use non-standard calling conventions because it makes an awful lot
+ * of sense here.
+ * rgerhards, 2008-04-30
+ */
+static int
+GetDrvrMode(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->iDrvrMode;
+}
+
+
+/* create an instance of a netstrm object. It is initialized with default
+ * values. The current driver is used. The caller may set netstrm properties
+ * and must call ConstructFinalize().
+ */
+static rsRetVal
+CreateStrm(netstrms_t *pThis, netstrm_t **ppStrm)
+{
+ netstrm_t *pStrm = NULL;
+ DEFiRet;
+
+ CHKiRet(objUse(netstrm, DONT_LOAD_LIB));
+ CHKiRet(netstrm.Construct(&pStrm));
+ /* we copy over our driver structure. We could provide a pointer to
+ * ourselves, but that costs some performance on each driver invocation.
+ * As we already have hefty indirection (and thus performance toll), I
+ * prefer to copy over the function pointers here. -- rgerhards, 2008-04-23
+ */
+ memcpy(&pStrm->Drvr, &pThis->Drvr, sizeof(pThis->Drvr));
+ pStrm->pNS = pThis;
+
+ *ppStrm = pStrm;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pStrm != NULL)
+ netstrm.Destruct(&pStrm);
+ }
+ RETiRet;
+}
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(netstrms)
+CODESTARTobjQueryInterface(netstrms)
+ if(pIf->ifVersion != netstrmsCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = netstrmsConstruct;
+ pIf->ConstructFinalize = netstrmsConstructFinalize;
+ pIf->Destruct = netstrmsDestruct;
+ pIf->CreateStrm = CreateStrm;
+ pIf->SetDrvrName = SetDrvrName;
+ pIf->SetDrvrMode = SetDrvrMode;
+ pIf->GetDrvrMode = GetDrvrMode;
+finalize_it:
+ENDobjQueryInterface(netstrms)
+
+
+/* exit our class */
+BEGINObjClassExit(netstrms, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(netstrms)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(netstrm, DONT_LOAD_LIB);
+ENDObjClassExit(netstrms)
+
+
+/* Initialize the netstrms class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINAbstractObjClassInit(netstrms, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+
+ /* set our own handlers */
+ENDObjClassInit(netstrms)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ nsselClassExit();
+ netstrmsClassExit();
+ netstrmClassExit(); /* we use this object, so we must exit it after we are finished */
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(netstrmClassInit(pModInfo));
+ CHKiRet(nsselClassInit(pModInfo));
+ CHKiRet(netstrmsClassInit(pModInfo));
+ENDmodInit
+/* vi:set ai:
+ */
diff --git a/runtime/netstrms.h b/runtime/netstrms.h
new file mode 100644
index 00000000..1d1cc892
--- /dev/null
+++ b/runtime/netstrms.h
@@ -0,0 +1,57 @@
+/* Definitions for the stream-based netstrmsworking class.
+ *
+ * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NETSTRMS_H
+#define INCLUDED_NETSTRMS_H
+
+#include "nsd.h" /* we need our driver interface to be defined */
+
+/* the netstrms object */
+struct netstrms_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ uchar *pBaseDrvrName; /**< nsd base driver name to use, or NULL if system default */
+ uchar *pDrvrName; /**< full base driver name (set when driver is loaded) */
+ int iDrvrMode; /**< current default driver mode */
+ nsd_if_t Drvr; /**< our stream driver */
+};
+
+
+/* interface */
+BEGINinterface(netstrms) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(netstrms_t **ppThis);
+ rsRetVal (*ConstructFinalize)(netstrms_t *pThis);
+ rsRetVal (*Destruct)(netstrms_t **ppThis);
+ rsRetVal (*CreateStrm)(netstrms_t *pThis, netstrm_t **ppStrm);
+ rsRetVal (*SetDrvrName)(netstrms_t *pThis, uchar *pszName);
+ rsRetVal (*SetDrvrMode)(netstrms_t *pThis, int iMode);
+ int (*GetDrvrMode)(netstrms_t *pThis);
+ENDinterface(netstrms)
+#define netstrmsCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+/* prototypes */
+PROTOTYPEObj(netstrms);
+
+/* the name of our library binary */
+#define LM_NETSTRMS_FILENAME "lmnetstrms"
+
+#endif /* #ifndef INCLUDED_NETSTRMS_H */
diff --git a/runtime/nsd.h b/runtime/nsd.h
new file mode 100644
index 00000000..cc06c877
--- /dev/null
+++ b/runtime/nsd.h
@@ -0,0 +1,73 @@
+/* The interface definition for "NetStream Drivers" (nsd).
+ *
+ * This is just an abstract driver interface, which needs to be
+ * implemented by concrete classes. As such, no nsd data type itself
+ * is defined.
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#ifndef INCLUDED_NSD_H
+#define INCLUDED_NSD_H
+
+enum nsdsel_waitOp_e {
+ NSDSEL_RD = 1,
+ NSDSEL_WR = 2,
+ NSDSEL_RDWR = 3
+}; /**< the operation we wait for */
+
+/* nsd_t is actually obj_t (which is somewhat better than void* but in essence
+ * much the same).
+ */
+
+/* interface */
+BEGINinterface(nsd) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(nsd_t **ppThis);
+ rsRetVal (*Destruct)(nsd_t **ppThis);
+ rsRetVal (*Abort)(nsd_t *pThis);
+ rsRetVal (*Rcv)(nsd_t *pThis, uchar *pRcvBuf, ssize_t *pLenBuf);
+ rsRetVal (*Send)(nsd_t *pThis, uchar *pBuf, ssize_t *pLenBuf);
+ rsRetVal (*Connect)(nsd_t *pThis, int family, unsigned char *port, unsigned char *host);
+ rsRetVal (*LstnInit)(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+ uchar *pLstnPort, uchar *pLstnIP, int iSessMax);
+ rsRetVal (*AcceptConnReq)(nsd_t *pThis, nsd_t **ppThis);
+ rsRetVal (*GetRemoteHName)(nsd_t *pThis, uchar **pszName);
+ rsRetVal (*GetRemoteIP)(nsd_t *pThis, uchar **pszIP);
+ rsRetVal (*SetMode)(nsd_t *pThis, int mode); /* sets a driver specific mode - see driver doc for details */
+ rsRetVal (*GetSock)(nsd_t *pThis, int *pSock);
+ rsRetVal (*SetSock)(nsd_t *pThis, int sock);
+ /* GetSock() and SetSock() return an error if the driver does not use plain
+ * OS sockets. This interface is primarily meant as an internal aid for
+ * those drivers that utilize the nsd_ptcp to do some of their work.
+ */
+ENDinterface(nsd)
+#define nsdCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+/* interface for the select call */
+BEGINinterface(nsdsel) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(nsdsel_t **ppThis);
+ rsRetVal (*Destruct)(nsdsel_t **ppThis);
+ rsRetVal (*Add)(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp);
+ rsRetVal (*Select)(nsdsel_t *pNsdsel, int *piNumReady);
+ rsRetVal (*IsReady)(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady);
+ENDinterface(nsdsel)
+#define nsdselCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+#endif /* #ifndef INCLUDED_NSD_H */
diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c
new file mode 100644
index 00000000..5ea7ceb9
--- /dev/null
+++ b/runtime/nsd_gtls.c
@@ -0,0 +1,727 @@
+/* nsd_gtls.c
+ *
+ * An implementation of the nsd interface for GnuTLS.
+ *
+ * Copyright (C) 2007, 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gcrypt.h>
+#include <errno.h>
+
+#include "rsyslog.h"
+#include "syslogd-types.h"
+#include "module-template.h"
+#include "cfsysline.h"
+#include "obj.h"
+#include "stringbuf.h"
+#include "errmsg.h"
+#include "nsd_ptcp.h"
+#include "nsdsel_gtls.h"
+#include "nsd_gtls.h"
+
+/* things to move to some better place/functionality - TODO */
+#define DH_BITS 1024
+#define CRLFILE "crl.pem"
+
+
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+MODULE_TYPE_LIB
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(nsd_ptcp)
+
+static int bGlblSrvrInitDone = 0; /**< 0 - server global init not yet done, 1 - already done */
+
+/* a macro to check GnuTLS calls against unexpected errors */
+#define CHKgnutls(x) \
+ if((gnuRet = (x)) != 0) { \
+ uchar *pErr = gtlsStrerror(gnuRet); \
+ dbgprintf("unexpected GnuTLS error %d in %s:%d: %s\n", gnuRet, __FILE__, __LINE__, pErr); \
+ free(pErr); \
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR); \
+ }
+
+
+/* ------------------------------ GnuTLS specifics ------------------------------ */
+static gnutls_certificate_credentials xcred;
+static gnutls_dh_params dh_params;
+
+/* Convert a fingerprint to printable data. The conversion is carried out
+ * according IETF I-D syslog-transport-tls-12. The fingerprint string is
+ * returned in a new cstr object. It is the caller's responsibility to
+ * destruct that object.
+ * rgerhards, 2008-05-08
+ */
+static rsRetVal
+GenFingerprintStr(uchar *pFingerprint, size_t sizeFingerprint, cstr_t **ppStr)
+{
+ cstr_t *pStr = NULL;
+ uchar buf[4];
+ size_t i;
+ DEFiRet;
+
+ CHKiRet(rsCStrConstruct(&pStr));
+ for(i = 0 ; i < sizeFingerprint ; ++i) {
+ snprintf((char*)buf, sizeof(buf), "%2.2X:", pFingerprint[i]);
+ CHKiRet(rsCStrAppendStrWithLen(pStr, buf, 3));
+ }
+ CHKiRet(rsCStrFinish(pStr));
+
+ *ppStr = pStr;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pStr != NULL)
+ rsCStrDestruct(&pStr);
+ }
+ RETiRet;
+}
+
+
+/* a thread-safe variant of gnutls_strerror - TODO: implement it!
+ * The caller must free the returned string.
+ * rgerhards, 2008-04-30
+ */
+uchar *gtlsStrerror(int error)
+{
+ uchar *pErr;
+
+ // TODO: guard by mutex!
+ pErr = (uchar*) strdup(gnutls_strerror(error));
+
+ return pErr;
+}
+
+
+/* globally initialize GnuTLS */
+static rsRetVal
+gtlsGlblInit(void)
+{
+ int gnuRet;
+ uchar *cafile;
+ DEFiRet;
+
+ /* gcry_control must be called first, so that the thread system is correctly set up */
+ gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+ CHKgnutls(gnutls_global_init());
+
+ /* X509 stuff */
+ CHKgnutls(gnutls_certificate_allocate_credentials(&xcred));
+
+ /* sets the trusted cas file */
+ cafile = glbl.GetDfltNetstrmDrvrCAF();
+ dbgprintf("GTLS CA file: '%s'\n", cafile);
+ gnuRet = gnutls_certificate_set_x509_trust_file(xcred, (char*)cafile, GNUTLS_X509_FMT_PEM);
+ if(gnuRet < 0) {
+ /* TODO; a more generic error-tracking function (this one based on CHKgnutls()) */
+ uchar *pErr = gtlsStrerror(gnuRet);
+ dbgprintf("unexpected GnuTLS error %d in %s:%d: %s\n", gnuRet, __FILE__, __LINE__, pErr);
+ free(pErr);
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+gtlsInitSession(nsd_gtls_t *pThis)
+{
+ DEFiRet;
+ int gnuRet;
+ gnutls_session session;
+
+ gnutls_init(&session, GNUTLS_SERVER);
+ pThis->bHaveSess = 1;
+ pThis->bIsInitiator = 0;
+
+ /* avoid calling all the priority functions, since the defaults are adequate. */
+ CHKgnutls(gnutls_set_default_priority(session));
+ CHKgnutls(gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred));
+
+ /* request client certificate if any. */
+ gnutls_certificate_server_set_request( session, GNUTLS_CERT_REQUEST);
+ gnutls_dh_set_prime_bits(session, DH_BITS);
+
+ pThis->sess = session;
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+generate_dh_params(void)
+{
+ int gnuRet;
+ DEFiRet;
+ /* Generate Diffie Hellman parameters - for use with DHE
+ * kx algorithms. These should be discarded and regenerated
+ * once a day, once a week or once a month. Depending on the
+ * security requirements.
+ */
+ CHKgnutls(gnutls_dh_params_init( &dh_params));
+ CHKgnutls(gnutls_dh_params_generate2( dh_params, DH_BITS));
+finalize_it:
+ RETiRet;
+}
+
+
+/* set up all global things that are needed for server operations
+ * rgerhards, 2008-04-30
+ */
+static rsRetVal
+gtlsGlblInitLstn(void)
+{
+ int gnuRet;
+ uchar *keyFile;
+ uchar *certFile;
+ DEFiRet;
+
+ if(bGlblSrvrInitDone == 0) {
+ /* we do not use CRLs right now, and I doubt we'll ever do. This functionality is
+ * considered legacy. -- rgerhards, 2008-05-05
+ */
+ /*CHKgnutls(gnutls_certificate_set_x509_crl_file(xcred, CRLFILE, GNUTLS_X509_FMT_PEM));*/
+ certFile = glbl.GetDfltNetstrmDrvrCertFile();
+ keyFile = glbl.GetDfltNetstrmDrvrKeyFile();
+ dbgprintf("GTLS certificate file: '%s'\n", certFile);
+ dbgprintf("GTLS key file: '%s'\n", keyFile);
+ CHKgnutls(gnutls_certificate_set_x509_key_file(xcred, (char*)certFile, (char*)keyFile, GNUTLS_X509_FMT_PEM));
+ CHKiRet(generate_dh_params());
+ gnutls_certificate_set_dh_params(xcred, dh_params); /* this is void */
+ bGlblSrvrInitDone = 1; /* we are all set now */
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* check the fingerprint of the remote peer's certificate.
+ * rgerhards, 2008-05-08
+ */
+static rsRetVal
+gtlsChkFingerprint(nsd_gtls_t *pThis)
+{
+ cstr_t *pstrFingerprint = NULL;
+ uchar fingerprint[20];
+ size_t size;
+ const gnutls_datum *cert_list;
+ unsigned int list_size = 0;
+ gnutls_x509_crt cert;
+ int bMustDeinitCert = 0;
+ int gnuRet;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ /* This function only works for X.509 certificates. */
+ if(gnutls_certificate_type_get(pThis->sess) != GNUTLS_CRT_X509)
+ return RS_RET_TLS_CERT_ERR;
+
+ cert_list = gnutls_certificate_get_peers(pThis->sess, &list_size);
+
+ if(list_size < 1)
+ ABORT_FINALIZE(RS_RET_TLS_NO_CERT);
+
+ /* If we reach this point, we have at least one valid certificate.
+ * We always use only the first certificate. As of GnuTLS documentation, the
+ * first certificate always contains the remote peer's own certificate. All other
+ * certificates are issuer's certificates (up the chain). However, we do not match
+ * against some issuer fingerprint but only ourselfs. -- rgerhards, 2008-05-08
+ */
+ CHKgnutls(gnutls_x509_crt_init(&cert));
+ bMustDeinitCert = 1; /* indicate cert is initialized and must be freed on exit */
+ CHKgnutls(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER));
+
+ /* obtain the SHA1 fingerprint */
+ size = sizeof(fingerprint);
+ CHKgnutls(gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, fingerprint, &size));
+ CHKiRet(GenFingerprintStr(fingerprint, size, &pstrFingerprint));
+ dbgprintf("peer's certificate SHA1 fingerprint: %s\n", rsCStrGetSzStr(pstrFingerprint));
+
+
+finalize_it:
+ if(pstrFingerprint != NULL)
+ rsCStrDestruct(&pstrFingerprint);
+ if(bMustDeinitCert)
+ gnutls_x509_crt_deinit(cert);
+
+ RETiRet;
+}
+
+
+/* globally de-initialize GnuTLS */
+static rsRetVal
+gtlsGlblExit(void)
+{
+ DEFiRet;
+ /* X509 stuff */
+ gnutls_certificate_free_credentials(xcred);
+ gnutls_global_deinit(); /* we are done... */
+ RETiRet;
+}
+
+
+/* end a GnuTLS session
+ * The function checks if we have a session and ends it only if so. So it can
+ * always be called, even if there currently is no session.
+ */
+static rsRetVal
+gtlsEndSess(nsd_gtls_t *pThis)
+{
+ int gnuRet;
+ DEFiRet;
+
+ if(pThis->bHaveSess) {
+ if(pThis->bIsInitiator) {
+ gnuRet = gnutls_bye(pThis->sess, GNUTLS_SHUT_RDWR);
+ while(gnuRet == GNUTLS_E_INTERRUPTED || gnuRet == GNUTLS_E_AGAIN) {
+ gnuRet = gnutls_bye(pThis->sess, GNUTLS_SHUT_RDWR);
+ }
+ }
+ gnutls_deinit(pThis->sess);
+ }
+ RETiRet;
+}
+
+
+/* a small wrapper for gnutls_transport_set_ptr(). The main intension for
+ * creating this wrapper is to get the annoying "cast to pointer from different
+ * size" compiler warning just once. There seems to be no way around it, see:
+ * http://lists.gnu.org/archive/html/help-gnutls/2008-05/msg00000.html
+ * rgerhards, 2008.05-07
+ */
+static inline void
+gtlsSetTransportPtr(nsd_gtls_t *pThis, int sock)
+{
+ /* Note: the compiler warning for the next line is OK - see header comment! */
+ gnutls_transport_set_ptr(pThis->sess, (gnutls_transport_ptr_t) sock);
+}
+
+/* ---------------------------- end GnuTLS specifics ---------------------------- */
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(nsd_gtls) /* be sure to specify the object type also in END macro! */
+ iRet = nsd_ptcp.Construct(&pThis->pTcp);
+ENDobjConstruct(nsd_gtls)
+
+
+/* destructor for the nsd_gtls object */
+BEGINobjDestruct(nsd_gtls) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nsd_gtls)
+ if(pThis->iMode == 1) {
+ gtlsEndSess(pThis);
+ }
+
+ if(pThis->pTcp != NULL) {
+ nsd_ptcp.Destruct(&pThis->pTcp);
+ }
+ENDobjDestruct(nsd_gtls)
+
+
+/* Set the driver mode. For us, this has the following meaning:
+ * 0 - work in plain tcp mode, without tls (e.g. before a STARTTLS)
+ * 1 - work in TLS mode
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+SetMode(nsd_t *pNsd, int mode)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+dbgprintf("SetMode tries to set mode %d\n", mode);
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ if(mode != 0 && mode != 1)
+ ABORT_FINALIZE(RS_RET_INVAID_DRVR_MODE);
+
+ pThis->iMode = mode;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Provide access to the underlying OS socket. This is primarily
+ * useful for other drivers (like nsd_gtls) who utilize ourselfs
+ * for some of their functionality. -- rgerhards, 2008-04-18
+ */
+static rsRetVal
+SetSock(nsd_t *pNsd, int sock)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ assert(sock >= 0);
+
+ nsd_ptcp.SetSock(pThis->pTcp, sock);
+
+ RETiRet;
+}
+
+
+/* abort a connection. This is meant to be called immediately
+ * before the Destruct call. -- rgerhards, 2008-03-24
+ */
+static rsRetVal
+Abort(nsd_t *pNsd)
+{
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+
+ if(pThis->iMode == 0) {
+ nsd_ptcp.Abort(pThis->pTcp);
+ }
+
+ RETiRet;
+}
+
+
+
+/* initialize the tcp socket for a listner
+ * Here, we use the ptcp driver - because there is nothing special
+ * at this point with GnuTLS. Things become special once we accept
+ * a session, but not during listener setup.
+ * gerhards, 2008-04-25
+ */
+static rsRetVal
+LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+ uchar *pLstnPort, uchar *pLstnIP, int iSessMax)
+{
+ DEFiRet;
+ CHKiRet(gtlsGlblInitLstn());
+ iRet = nsd_ptcp.LstnInit(pNS, pUsr, fAddLstn, pLstnPort, pLstnIP, iSessMax);
+finalize_it:
+ RETiRet;
+}
+
+
+/* get the remote hostname. The returned hostname must be freed by the caller.
+ * rgerhards, 2008-04-25
+ */
+static rsRetVal
+GetRemoteHName(nsd_t *pNsd, uchar **ppszHName)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+ iRet = nsd_ptcp.GetRemoteHName(pThis->pTcp, ppszHName);
+ RETiRet;
+}
+
+
+/* get the remote host's IP address. The returned string must be freed by the
+ * caller. -- rgerhards, 2008-04-25
+ */
+static rsRetVal
+GetRemoteIP(nsd_t *pNsd, uchar **ppszIP)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+ iRet = nsd_ptcp.GetRemoteIP(pThis->pTcp, ppszIP);
+ RETiRet;
+}
+
+
+/* accept an incoming connection request - here, we do the usual accept
+ * handling. TLS specific handling is done thereafter (and if we run in TLS
+ * mode at this time).
+ * rgerhards, 2008-04-25
+ */
+static rsRetVal
+AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
+{
+ DEFiRet;
+ int gnuRet;
+ nsd_gtls_t *pNew = NULL;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ CHKiRet(nsd_gtlsConstruct(&pNew)); // TODO: prevent construct/destruct!
+ CHKiRet(nsd_ptcp.Destruct(&pNew->pTcp));
+ CHKiRet(nsd_ptcp.AcceptConnReq(pThis->pTcp, &pNew->pTcp));
+
+ if(pThis->iMode == 0) {
+ /* we are in non-TLS mode, so we are done */
+ *ppNew = (nsd_t*) pNew;
+ FINALIZE;
+ }
+
+ /* if we reach this point, we are in TLS mode */
+ CHKiRet(gtlsInitSession(pNew));
+ gtlsSetTransportPtr(pNew, ((nsd_ptcp_t*) (pNew->pTcp))->sock);
+
+ /* we now do the handshake. This is a bit complicated, because we are
+ * on non-blocking sockets. Usually, the handshake will not complete
+ * immediately, so that we need to retry it some time later.
+ */
+ gnuRet = gnutls_handshake(pNew->sess);
+ if(gnuRet == GNUTLS_E_AGAIN || gnuRet == GNUTLS_E_INTERRUPTED) {
+ pNew->rtryCall = gtlsRtry_handshake;
+ dbgprintf("GnuTLS handshake does not complete immediately - setting to retry (this is OK and normal)\n");
+ } else if(gnuRet != 0) {
+ ABORT_FINALIZE(RS_RET_TLS_HANDSHAKE_ERR);
+ }
+
+ pNew->iMode = 1; /* this session is now in TLS mode! */
+
+ *ppNew = (nsd_t*) pNew;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pNew != NULL)
+ nsd_gtlsDestruct(&pNew);
+ }
+ RETiRet;
+}
+
+
+/* receive data from a tcp socket
+ * The lenBuf parameter must contain the max buffer size on entry and contains
+ * the number of octets read (or -1 in case of error) on exit. This function
+ * never blocks, not even when called on a blocking socket. That is important
+ * for client sockets, which are set to block during send, but should not
+ * block when trying to read data. If *pLenBuf is -1, an error occured and
+ * errno holds the exact error cause.
+ * rgerhards, 2008-03-17
+ */
+static rsRetVal
+Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
+{
+ DEFiRet;
+ ssize_t lenRcvd;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ if(pThis->iMode == 0) {
+ CHKiRet(nsd_ptcp.Rcv(pThis->pTcp, pBuf, pLenBuf));
+ FINALIZE;
+ }
+
+ /* in TLS mode now */
+ lenRcvd = gnutls_record_recv(pThis->sess, pBuf, *pLenBuf);
+ if(lenRcvd < 0) {
+ int gnuRet; /* TODO: build a specific function for GnuTLS error reporting */
+ *pLenBuf = -1;
+ CHKgnutls(lenRcvd); /* this will abort the function */
+ }
+
+ *pLenBuf = lenRcvd;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* send a buffer. On entry, pLenBuf contains the number of octets to
+ * write. On exit, it contains the number of octets actually written.
+ * If this number is lower than on entry, only a partial buffer has
+ * been written.
+ * rgerhards, 2008-03-19
+ */
+static rsRetVal
+Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
+{
+ int iSent;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ if(pThis->iMode == 0) {
+ CHKiRet(nsd_ptcp.Send(pThis->pTcp, pBuf, pLenBuf));
+ FINALIZE;
+ }
+
+ /* in TLS mode now */
+ while(1) { /* loop broken inside */
+ iSent = gnutls_record_send(pThis->sess, pBuf, *pLenBuf);
+ if(iSent >= 0) {
+ *pLenBuf = iSent;
+ break;
+ }
+ if(iSent != GNUTLS_E_INTERRUPTED && iSent != GNUTLS_E_AGAIN) {
+ dbgprintf("unexpected GnuTLS error %d in %s:%d\n", iSent, __FILE__, __LINE__);
+ gnutls_perror(iSent); /* TODO: can we do better? */
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* open a connection to a remote host (server). With GnuTLS, we always
+ * open a plain tcp socket and then, if in TLS mode, do a handshake on it.
+ * rgerhards, 2008-03-19
+ */
+static rsRetVal
+Connect(nsd_t *pNsd, int family, uchar *port, uchar *host)
+{
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ int sock;
+ int gnuRet;
+ static const int cert_type_priority[3] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 };
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+ assert(port != NULL);
+ assert(host != NULL);
+
+ CHKiRet(nsd_ptcp.Connect(pThis->pTcp, family, port, host));
+
+ if(pThis->iMode == 0)
+ FINALIZE;
+
+ /* we reach this point if in TLS mode */
+ CHKgnutls(gnutls_init(&pThis->sess, GNUTLS_CLIENT));
+ pThis->bHaveSess = 1;
+ pThis->bIsInitiator = 1;
+
+ /* Use default priorities */
+ CHKgnutls(gnutls_set_default_priority(pThis->sess));
+ CHKgnutls(gnutls_certificate_type_set_priority(pThis->sess, cert_type_priority));
+
+ /* put the x509 credentials to the current session */
+ CHKgnutls(gnutls_credentials_set(pThis->sess, GNUTLS_CRD_CERTIFICATE, xcred));
+
+ /* assign the socket to GnuTls */
+ CHKiRet(nsd_ptcp.GetSock(pThis->pTcp, &sock));
+ gtlsSetTransportPtr(pThis, sock);
+
+ /* and perform the handshake */
+ CHKgnutls(gnutls_handshake(pThis->sess));
+ dbgprintf("GnuTLS handshake succeeded\n");
+
+ /* now check if the remote peer is permitted to talk to us */
+ CHKiRet(gtlsChkFingerprint(pThis));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->bHaveSess) {
+ gnutls_deinit(pThis->sess);
+ pThis->bHaveSess = 0;
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nsd_gtls)
+CODESTARTobjQueryInterface(nsd_gtls)
+ if(pIf->ifVersion != nsdCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = (rsRetVal(*)(nsd_t**)) nsd_gtlsConstruct;
+ pIf->Destruct = (rsRetVal(*)(nsd_t**)) nsd_gtlsDestruct;
+ pIf->Abort = Abort;
+ pIf->LstnInit = LstnInit;
+ pIf->AcceptConnReq = AcceptConnReq;
+ pIf->Rcv = Rcv;
+ pIf->Send = Send;
+ pIf->Connect = Connect;
+ pIf->SetSock = SetSock;
+ pIf->SetMode = SetMode;
+ pIf->GetRemoteHName = GetRemoteHName;
+ pIf->GetRemoteIP = GetRemoteIP;
+finalize_it:
+ENDobjQueryInterface(nsd_gtls)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nsd_gtls, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsd_gtls)
+ gtlsGlblExit(); /* shut down GnuTLS */
+
+ /* release objects we no longer need */
+ objRelease(nsd_ptcp, LM_NSD_PTCP_FILENAME);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(errmsg, CORE_COMPONENT);
+ENDObjClassExit(nsd_gtls)
+
+
+/* Initialize the nsd_gtls class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nsd_gtls, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(nsd_ptcp, LM_NSD_PTCP_FILENAME));
+
+ /* now do global TLS init stuff */
+ CHKiRet(gtlsGlblInit());
+ENDObjClassInit(nsd_gtls)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ nsdsel_gtlsClassExit();
+ nsd_gtlsClassExit();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(nsd_gtlsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ CHKiRet(nsdsel_gtlsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+
+ENDmodInit
+/* vi:set ai:
+ */
diff --git a/runtime/nsd_gtls.h b/runtime/nsd_gtls.h
new file mode 100644
index 00000000..bbb0eb9e
--- /dev/null
+++ b/runtime/nsd_gtls.h
@@ -0,0 +1,59 @@
+/* An implementation of the nsd interface for GnuTLS.
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NSD_GTLS_H
+#define INCLUDED_NSD_GTLS_H
+
+#include "nsd.h"
+
+typedef enum {
+ gtlsRtry_None = 0, /**< no call needs to be retried */
+ gtlsRtry_handshake = 1
+} gtlsRtryCall_t; /**< IDs of calls that needs to be retried */
+
+typedef nsd_if_t nsd_gtls_if_t; /* we just *implement* this interface */
+
+/* the nsd_gtls object */
+struct nsd_gtls_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ nsd_t *pTcp; /**< our aggregated nsd_ptcp data */
+ int iMode; /* 0 - plain tcp, 1 - TLS */
+ gtlsRtryCall_t rtryCall;/**< what must we retry? */
+ int bIsInitiator; /**< 0 if socket is the server end (listener), 1 if it is the initiator */
+ gnutls_session sess;
+ int bHaveSess; /* as we don't know exactly which gnutls_session values are invalid, we use this one
+ to flag whether or not we are in a session (same as -1 for a socket meaning no sess) */
+};
+
+/* interface is defined in nsd.h, we just implement it! */
+#define nsd_gtlsCURR_IF_VERSION nsdCURR_IF_VERSION
+
+/* prototypes */
+PROTOTYPEObj(nsd_gtls);
+/* some prototypes for things used by our nsdsel_gtls helper class */
+uchar *gtlsStrerror(int error);
+
+/* the name of our library binary */
+#define LM_NSD_GTLS_FILENAME "lmnsd_gtls"
+
+#endif /* #ifndef INCLUDED_NSD_GTLS_H */
diff --git a/runtime/nsd_ptcp.c b/runtime/nsd_ptcp.c
new file mode 100644
index 00000000..c5480a05
--- /dev/null
+++ b/runtime/nsd_ptcp.c
@@ -0,0 +1,693 @@
+/* nsd_ptcp.c
+ *
+ * An implementation of the nsd interface for plain tcp sockets.
+ *
+ * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <fnmatch.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "syslogd-types.h"
+#include "module-template.h"
+#include "parse.h"
+#include "srUtils.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "net.h"
+#include "netstrms.h"
+#include "netstrm.h"
+#include "nsdsel_ptcp.h"
+#include "nsd_ptcp.h"
+
+MODULE_TYPE_LIB
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(net)
+DEFobjCurrIf(netstrms)
+DEFobjCurrIf(netstrm)
+
+
+/* a few deinit helpers */
+
+/* close socket if open (may always be called) */
+static void
+sockClose(int *pSock)
+{
+ if(*pSock >= 0) {
+ close(*pSock);
+ *pSock = -1;
+ }
+}
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(nsd_ptcp) /* be sure to specify the object type also in END macro! */
+ pThis->sock = -1;
+ENDobjConstruct(nsd_ptcp)
+
+
+/* destructor for the nsd_ptcp object */
+BEGINobjDestruct(nsd_ptcp) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nsd_ptcp)
+ sockClose(&pThis->sock);
+ if(pThis->pRemHostIP != NULL)
+ free(pThis->pRemHostIP);
+ if(pThis->pRemHostName != NULL)
+ free(pThis->pRemHostName);
+ENDobjDestruct(nsd_ptcp)
+
+
+/* Provide access to the underlying OS socket. This is primarily
+ * useful for other drivers (like nsd_gtls) who utilize ourselfs
+ * for some of their functionality. -- rgerhards, 2008-04-18
+ */
+static rsRetVal
+GetSock(nsd_t *pNsd, int *pSock)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ptcp);
+ assert(pSock != NULL);
+
+ *pSock = pThis->sock;
+
+ RETiRet;
+}
+
+
+/* Set the driver mode. We support no different modes, but allow mode
+ * 0 to be set to be compatible with config file defaults and the other
+ * drivers.
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+SetMode(nsd_t __attribute__((unused)) *pNsd, int mode)
+{
+ DEFiRet;
+ if(mode != 0)
+ ABORT_FINALIZE(RS_RET_INVAID_DRVR_MODE);
+finalize_it:
+ RETiRet;
+}
+
+
+/* Provide access to the underlying OS socket. This is primarily
+ * useful for other drivers (like nsd_gtls) who utilize ourselfs
+ * for some of their functionality.
+ * This function sets the socket -- rgerhards, 2008-04-25
+ */
+static rsRetVal
+SetSock(nsd_t *pNsd, int sock)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ptcp);
+ assert(sock >= 0);
+
+ pThis->sock = sock;
+
+ RETiRet;
+}
+
+
+/* abort a connection. This is meant to be called immediately
+ * before the Destruct call. -- rgerhards, 2008-03-24
+ */
+static rsRetVal
+Abort(nsd_t *pNsd)
+{
+ struct linger ling;
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+
+ DEFiRet;
+ ISOBJ_TYPE_assert((pThis), nsd_ptcp);
+
+ if((pThis)->sock != -1) {
+ ling.l_onoff = 1;
+ ling.l_linger = 0;
+ if(setsockopt((pThis)->sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)) < 0 ) {
+ dbgprintf("could not set SO_LINGER, errno %d\n", errno);
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* Set pRemHost based on the address provided. This is to be called upon accept()ing
+ * a connection request. It must be provided by the socket we received the
+ * message on as well as a NI_MAXHOST size large character buffer for the FQDN.
+ * Please see http://www.hmug.org/man/3/getnameinfo.php (under Caveats)
+ * for some explanation of the code found below. If we detect a malicious
+ * hostname, we return RS_RET_MALICIOUS_HNAME and let the caller decide
+ * on how to deal with that.
+ * rgerhards, 2008-03-31
+ */
+static rsRetVal
+FillRemHost(nsd_ptcp_t *pThis, struct sockaddr *pAddr)
+{
+ int error;
+ uchar szIP[NI_MAXHOST] = "";
+ uchar szHname[NI_MAXHOST] = "";
+ struct addrinfo hints, *res;
+ size_t len;
+
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+ assert(pAddr != NULL);
+
+ error = getnameinfo(pAddr, SALEN(pAddr), (char*)szIP, sizeof(szIP), NULL, 0, NI_NUMERICHOST);
+
+ if(error) {
+ dbgprintf("Malformed from address %s\n", gai_strerror(error));
+ strcpy((char*)szHname, "???");
+ strcpy((char*)szIP, "???");
+ ABORT_FINALIZE(RS_RET_INVALID_HNAME);
+ }
+
+ if(!glbl.GetDisableDNS()) {
+ error = getnameinfo(pAddr, SALEN(pAddr), (char*)szHname, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
+ if(error == 0) {
+ memset (&hints, 0, sizeof (struct addrinfo));
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_socktype = SOCK_STREAM;
+ /* we now do a lookup once again. This one should fail,
+ * because we should not have obtained a non-numeric address. If
+ * we got a numeric one, someone messed with DNS!
+ */
+ if(getaddrinfo((char*)szHname, NULL, &hints, &res) == 0) {
+ freeaddrinfo (res);
+ /* OK, we know we have evil, so let's indicate this to our caller */
+ snprintf((char*)szHname, NI_MAXHOST, "[MALICIOUS:IP=%s]", szIP);
+ dbgprintf("Malicious PTR record, IP = \"%s\" HOST = \"%s\"", szIP, szHname);
+ iRet = RS_RET_MALICIOUS_HNAME;
+ }
+ } else {
+ strcpy((char*)szHname, (char*)szIP);
+ }
+ } else {
+ strcpy((char*)szHname, (char*)szIP);
+ }
+
+ /* We now have the names, so now let's allocate memory and store them permanently.
+ * (side note: we may hold on to these values for quite a while, thus we trim their
+ * memory consumption)
+ */
+ len = strlen((char*)szIP) + 1; /* +1 for \0 byte */
+ if((pThis->pRemHostIP = malloc(len)) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ memcpy(pThis->pRemHostIP, szIP, len);
+
+ len = strlen((char*)szHname) + 1; /* +1 for \0 byte */
+ if((pThis->pRemHostName = malloc(len)) == NULL) {
+ free(pThis->pRemHostIP); /* prevent leak */
+ pThis->pRemHostIP = NULL;
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ memcpy(pThis->pRemHostName, szHname, len);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* accept an incoming connection request
+ * rgerhards, 2008-04-22
+ */
+static rsRetVal
+AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
+{
+ int sockflags;
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof(addr);
+ nsd_ptcp_t *pNew = NULL;
+ int iNewSock = -1;
+
+ DEFiRet;
+ assert(ppNew != NULL);
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+
+ iNewSock = accept(pThis->sock, (struct sockaddr*) &addr, &addrlen);
+ if(iNewSock < 0) {
+ ABORT_FINALIZE(RS_RET_ACCEPT_ERR);
+ }
+
+ /* construct our object so that we can use it... */
+ CHKiRet(nsd_ptcpConstruct(&pNew));
+
+ CHKiRet(FillRemHost(pNew, (struct sockaddr*) &addr));
+
+ /* set the new socket to non-blocking IO -TODO:do we really need to do this here? Do we always want it? */
+ if((sockflags = fcntl(iNewSock, F_GETFL)) != -1) {
+ sockflags |= O_NONBLOCK;
+ /* SETFL could fail too, so get it caught by the subsequent
+ * error check.
+ */
+ sockflags = fcntl(iNewSock, F_SETFL, sockflags);
+ }
+ if(sockflags == -1) {
+ dbgprintf("error %d setting fcntl(O_NONBLOCK) on tcp socket %d", errno, iNewSock);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ pNew->sock = iNewSock;
+ *ppNew = (nsd_t*) pNew;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pNew != NULL)
+ nsd_ptcpDestruct(&pNew);
+ /* the close may be redundant, but that doesn't hurt... */
+ sockClose(&iNewSock);
+ }
+
+ RETiRet;
+}
+
+
+/* initialize tcp sockets for a listner. The initialized sockets are passed to the
+ * app-level caller via a callback.
+ * pLstnPort must point to a port name or number. NULL is NOT permitted. pLstnIP
+ * points to the port to listen to (NULL means "all"), iMaxSess has the maximum
+ * number of sessions permitted.
+ * rgerhards, 2008-04-22
+ */
+static rsRetVal
+LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+ uchar *pLstnPort, uchar *pLstnIP, int iSessMax)
+{
+ DEFiRet;
+ netstrm_t *pNewStrm = NULL;
+ nsd_t *pNewNsd = NULL;
+ int error, maxs, on = 1;
+ int sock;
+ int numSocks;
+ int sockflags;
+ struct addrinfo hints, *res = NULL, *r;
+
+ ISOBJ_TYPE_assert(pNS, netstrms);
+ assert(fAddLstn != NULL);
+ assert(pLstnPort != NULL);
+ assert(iSessMax >= 0);
+
+ dbgprintf("creating tcp listen socket on port %s\n", pLstnPort);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = glbl.GetDefPFFamily();
+ hints.ai_socktype = SOCK_STREAM;
+
+ error = getaddrinfo((char*)pLstnIP, (char*) pLstnPort, &hints, &res);
+ if(error) {
+ dbgprintf("error %d querying port '%s'\n", error, pLstnPort);
+ ABORT_FINALIZE(RS_RET_INVALID_PORT);
+ }
+
+ /* Count max number of sockets we may open */
+ for(maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++)
+ /* EMPTY */;
+
+ numSocks = 0; /* num of sockets counter at start of array */
+ for(r = res; r != NULL ; r = r->ai_next) {
+ sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+ if(sock < 0) {
+ if(!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT))
+ dbgprintf("error %d creating tcp listen socket", errno);
+ /* it is debatable if PF_INET with EAFNOSUPPORT should
+ * also be ignored...
+ */
+ continue;
+ }
+
+#ifdef IPV6_V6ONLY
+ if(r->ai_family == AF_INET6) {
+ int iOn = 1;
+ if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&iOn, sizeof (iOn)) < 0) {
+ close(sock);
+ continue;
+ }
+ }
+#endif
+ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0 ) {
+ dbgprintf("error %d setting tcp socket option\n", errno);
+ close(sock);
+ continue;
+ }
+
+ /* We use non-blocking IO! */
+ if((sockflags = fcntl(sock, F_GETFL)) != -1) {
+ sockflags |= O_NONBLOCK;
+ /* SETFL could fail too, so get it caught by the subsequent
+ * error check.
+ */
+ sockflags = fcntl(sock, F_SETFL, sockflags);
+ }
+ if(sockflags == -1) {
+ dbgprintf("error %d setting fcntl(O_NONBLOCK) on tcp socket", errno);
+ close(sock);
+ continue;
+ }
+
+
+
+ /* We need to enable BSD compatibility. Otherwise an attacker
+ * could flood our log files by sending us tons of ICMP errors.
+ */
+#ifndef BSD
+ if(net.should_use_so_bsdcompat()) {
+ if (setsockopt(sock, SOL_SOCKET, SO_BSDCOMPAT,
+ (char *) &on, sizeof(on)) < 0) {
+ errmsg.LogError(NO_ERRCODE, "TCP setsockopt(BSDCOMPAT)");
+ close(sock);
+ continue;
+ }
+ }
+#endif
+
+ if( (bind(sock, r->ai_addr, r->ai_addrlen) < 0)
+#ifndef IPV6_V6ONLY
+ && (errno != EADDRINUSE)
+#endif
+ ) {
+ /* TODO: check if *we* bound the socket - else we *have* an error! */
+ dbgprintf("error %d while binding tcp socket", errno);
+ close(sock);
+ continue;
+ }
+
+ if(listen(sock, iSessMax / 10 + 5) < 0) {
+ /* If the listen fails, it most probably fails because we ask
+ * for a too-large backlog. So in this case we first set back
+ * to a fixed, reasonable, limit that should work. Only if
+ * that fails, too, we give up.
+ */
+ dbgprintf("listen with a backlog of %d failed - retrying with default of 32.",
+ iSessMax / 10 + 5);
+ if(listen(sock, 32) < 0) {
+ dbgprintf("tcp listen error %d, suspending\n", errno);
+ close(sock);
+ continue;
+ }
+ }
+
+ /* if we reach this point, we were able to obtain a valid socket, so we can
+ * construct a new netstrm obj and hand it over to the upper layers for inclusion
+ * into their socket array. -- rgerhards, 2008-04-23
+ */
+ CHKiRet(pNS->Drvr.Construct(&pNewNsd));
+ CHKiRet(pNS->Drvr.SetSock(pNewNsd, sock));
+ CHKiRet(pNS->Drvr.SetMode(pNewNsd, netstrms.GetDrvrMode(pNS)));
+ CHKiRet(netstrms.CreateStrm(pNS, &pNewStrm));
+ pNewStrm->pDrvrData = (nsd_t*) pNewNsd;
+ CHKiRet(fAddLstn(pUsr, pNewStrm));
+ pNewNsd = NULL;
+ pNewStrm = NULL;
+ ++numSocks;
+ }
+
+ if(numSocks != maxs)
+ dbgprintf("We could initialize %d TCP listen sockets out of %d we received "
+ "- this may or may not be an error indication.\n", numSocks, maxs);
+
+ if(numSocks == 0) {
+ dbgprintf("No TCP listen sockets could successfully be initialized");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_BIND);
+ }
+
+finalize_it:
+ if(res != NULL)
+ freeaddrinfo(res);
+
+ if(iRet != RS_RET_OK) {
+ if(pNewStrm != NULL)
+ netstrm.Destruct(&pNewStrm);
+ if(pNewNsd != NULL)
+ pNS->Drvr.Destruct(&pNewNsd);
+ }
+
+ RETiRet;
+}
+
+
+/* receive data from a tcp socket
+ * The lenBuf parameter must contain the max buffer size on entry and contains
+ * the number of octets read (or -1 in case of error) on exit. This function
+ * never blocks, not even when called on a blocking socket. That is important
+ * for client sockets, which are set to block during send, but should not
+ * block when trying to read data. If *pLenBuf is -1, an error occured and
+ * errno holds the exact error cause.
+ * rgerhards, 2008-03-17
+ */
+static rsRetVal
+Rcv(nsd_t *pNsd, uchar *pRcvBuf, ssize_t *pLenBuf)
+{
+ DEFiRet;
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+
+ *pLenBuf = recv(pThis->sock, pRcvBuf, *pLenBuf, MSG_DONTWAIT);
+
+ RETiRet;
+}
+
+
+/* send a buffer. On entry, pLenBuf contains the number of octets to
+ * write. On exit, it contains the number of octets actually written.
+ * If this number is lower than on entry, only a partial buffer has
+ * been written.
+ * rgerhards, 2008-03-19
+ */
+static rsRetVal
+Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ ssize_t written;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+
+ written = send(pThis->sock, pBuf, *pLenBuf, 0);
+
+ if(written == -1) {
+ switch(errno) {
+ case EAGAIN:
+ case EINTR:
+ /* this is fine, just retry... */
+ written = 0;
+ break;
+ default:
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ break;
+ }
+ }
+
+ *pLenBuf = written;
+finalize_it:
+ RETiRet;
+}
+
+
+/* open a connection to a remote host (server).
+ * rgerhards, 2008-03-19
+ */
+static rsRetVal
+Connect(nsd_t *pNsd, int family, uchar *port, uchar *host)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ struct addrinfo *res = NULL;
+ struct addrinfo hints;
+
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+ assert(port != NULL);
+ assert(host != NULL);
+ assert(pThis->sock == -1);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_STREAM;
+ if(getaddrinfo((char*)host, (char*)port, &hints, &res) != 0) {
+ dbgprintf("error %d in getaddrinfo\n", errno);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ if((pThis->sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ if(connect(pThis->sock, res->ai_addr, res->ai_addrlen) != 0) {
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+finalize_it:
+ if(res != NULL)
+ freeaddrinfo(res);
+
+ if(iRet != RS_RET_OK) {
+ sockClose(&pThis->sock);
+ }
+
+ RETiRet;
+}
+
+
+/* get the remote hostname. The returned hostname must be freed by the
+ * caller.
+ * rgerhards, 2008-04-24
+ */
+static rsRetVal
+GetRemoteHName(nsd_t *pNsd, uchar **ppszHName)
+{
+ DEFiRet;
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+ assert(ppszHName != NULL);
+
+ // TODO: how can the RemHost be empty?
+ CHKmalloc(*ppszHName = (uchar*)strdup(pThis->pRemHostName == NULL ? "" : (char*) pThis->pRemHostName));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* get the remote host's IP address. The returned string must be freed by the
+ * caller.
+ * rgerhards, 2008-04-24
+ */
+static rsRetVal
+GetRemoteIP(nsd_t *pNsd, uchar **ppszIP)
+{
+ DEFiRet;
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+ assert(ppszIP != NULL);
+
+ CHKmalloc(*ppszIP = (uchar*)strdup(pThis->pRemHostIP == NULL ? "" : (char*) pThis->pRemHostIP));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nsd_ptcp)
+CODESTARTobjQueryInterface(nsd_ptcp)
+ if(pIf->ifVersion != nsdCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = (rsRetVal(*)(nsd_t**)) nsd_ptcpConstruct;
+ pIf->Destruct = (rsRetVal(*)(nsd_t**)) nsd_ptcpDestruct;
+ pIf->Abort = Abort;
+ pIf->GetSock = GetSock;
+ pIf->SetSock = SetSock;
+ pIf->SetMode = SetMode;
+ pIf->Rcv = Rcv;
+ pIf->Send = Send;
+ pIf->LstnInit = LstnInit;
+ pIf->AcceptConnReq = AcceptConnReq;
+ pIf->Connect = Connect;
+ pIf->GetRemoteHName = GetRemoteHName;
+ pIf->GetRemoteIP = GetRemoteIP;
+finalize_it:
+ENDobjQueryInterface(nsd_ptcp)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nsd_ptcp, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsd_ptcp)
+ /* release objects we no longer need */
+ objRelease(net, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(errmsg, CORE_COMPONENT);
+ objRelease(netstrm, DONT_LOAD_LIB);
+ objRelease(netstrms, LM_NETSTRMS_FILENAME);
+ENDObjClassExit(nsd_ptcp)
+
+
+/* Initialize the nsd_ptcp class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nsd_ptcp, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(net, CORE_COMPONENT));
+ CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(netstrm, DONT_LOAD_LIB));
+
+ /* set our own handlers */
+ENDObjClassInit(nsd_ptcp)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ nsdsel_ptcpClassExit();
+ nsd_ptcpClassExit();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(nsd_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ CHKiRet(nsdsel_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ENDmodInit
+/* vi:set ai:
+ */
diff --git a/runtime/nsd_ptcp.h b/runtime/nsd_ptcp.h
new file mode 100644
index 00000000..efd3ed05
--- /dev/null
+++ b/runtime/nsd_ptcp.h
@@ -0,0 +1,47 @@
+/* An implementation of the nsd interface for plain tcp sockets.
+ *
+ * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NSD_PTCP_H
+#define INCLUDED_NSD_PTCP_H
+
+#include "nsd.h"
+typedef nsd_if_t nsd_ptcp_if_t; /* we just *implement* this interface */
+
+/* the nsd_ptcp object */
+struct nsd_ptcp_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ uchar *pRemHostIP; /**< IP address of remote peer (currently used in server mode, only) */
+ uchar *pRemHostName; /**< host name of remote peer (currently used in server mode, only) */
+ int sock; /**< the socket we use for regular, single-socket, operations */
+};
+
+/* interface is defined in nsd.h, we just implement it! */
+#define nsd_ptcpCURR_IF_VERSION nsdCURR_IF_VERSION
+
+/* prototypes */
+PROTOTYPEObj(nsd_ptcp);
+
+/* the name of our library binary */
+#define LM_NSD_PTCP_FILENAME "lmnsd_ptcp"
+
+#endif /* #ifndef INCLUDED_NSD_PTCP_H */
diff --git a/runtime/nsdsel_gtls.c b/runtime/nsdsel_gtls.c
new file mode 100644
index 00000000..24c074f6
--- /dev/null
+++ b/runtime/nsdsel_gtls.c
@@ -0,0 +1,235 @@
+/* nsdsel_gtls.c
+ *
+ * An implementation of the nsd select() interface for GnuTLS.
+ *
+ * Copyright (C) 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/select.h>
+#include <gnutls/gnutls.h>
+
+#include "rsyslog.h"
+#include "module-template.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "nsd.h"
+#include "nsd_gtls.h"
+#include "nsd_ptcp.h"
+#include "nsdsel_ptcp.h"
+#include "nsdsel_gtls.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(nsdsel_ptcp)
+
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(nsdsel_gtls) /* be sure to specify the object type also in END macro! */
+ iRet = nsdsel_ptcp.Construct(&pThis->pTcp);
+ENDobjConstruct(nsdsel_gtls)
+
+
+/* destructor for the nsdsel_gtls object */
+BEGINobjDestruct(nsdsel_gtls) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nsdsel_gtls)
+ if(pThis->pTcp != NULL)
+ nsdsel_ptcp.Destruct(&pThis->pTcp);
+ENDobjDestruct(nsdsel_gtls)
+
+
+/* Add a socket to the select set */
+static rsRetVal
+Add(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp)
+{
+ DEFiRet;
+ nsdsel_gtls_t *pThis = (nsdsel_gtls_t*) pNsdsel;
+ nsd_gtls_t *pNsdGTLS = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert(pThis, nsdsel_gtls);
+ ISOBJ_TYPE_assert(pNsdGTLS, nsd_gtls);
+ if(pNsdGTLS->iMode == 1) {
+ if(pNsdGTLS->rtryCall != gtlsRtry_None) {
+ if(gnutls_record_get_direction(pNsdGTLS->sess) == 0) {
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, NSDSEL_RD));
+ } else {
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, NSDSEL_WR));
+ }
+ FINALIZE;
+ }
+ }
+
+ /* if we reach this point, we need no special handling */
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, waitOp));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* perform the select() piNumReady returns how many descriptors are ready for IO
+ * TODO: add timeout!
+ */
+static rsRetVal
+Select(nsdsel_t *pNsdsel, int *piNumReady)
+{
+ DEFiRet;
+ nsdsel_gtls_t *pThis = (nsdsel_gtls_t*) pNsdsel;
+
+ ISOBJ_TYPE_assert(pThis, nsdsel_gtls);
+ iRet = nsdsel_ptcp.Select(pThis->pTcp, piNumReady);
+ RETiRet;
+}
+
+
+/* retry an interrupted GTLS operation
+ * rgerhards, 2008-04-30
+ */
+static rsRetVal
+doRetry(nsd_gtls_t *pNsd)
+{
+ DEFiRet;
+ int gnuRet;
+
+ dbgprintf("GnuTLS requested retry of %d operation - executing\n", pNsd->rtryCall);
+
+ /* We follow a common scheme here: first, we do the systen call and
+ * then we check the result. So far, the result is checked after the
+ * switch, because the result check is the same for all calls. Note that
+ * this may change once we deal with the read and write calls (but
+ * probably this becomes an issue only when we begin to work on TLS
+ * for relp). -- rgerhards, 2008-04-30
+ */
+ switch(pNsd->rtryCall) {
+ case gtlsRtry_handshake:
+ gnuRet = gnutls_handshake(pNsd->sess);
+ if(gnuRet == 0) {
+ /* we got a handshake, now check authorization */
+ // TODO: do it!
+ }
+ break;
+ default:
+ assert(0); /* this shall not happen! */
+ break;
+ }
+
+ if(gnuRet == 0) {
+ pNsd->rtryCall = gtlsRtry_None; /* we are done */
+ } else if(gnuRet != GNUTLS_E_AGAIN && gnuRet != GNUTLS_E_INTERRUPTED) {
+ uchar *pErr = gtlsStrerror(gnuRet);
+ dbgprintf("unexpected GnuTLS error %d in %s:%d: %s\n", gnuRet, __FILE__, __LINE__, pErr);
+ free(pErr);
+ pNsd->rtryCall = gtlsRtry_None; /* we are also done... ;) */
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ }
+ /* if we are interrupted once again (else case), we do not need to
+ * change our status because we are already setup for retries.
+ */
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* check if a socket is ready for IO */
+static rsRetVal
+IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady)
+{
+ DEFiRet;
+ nsdsel_gtls_t *pThis = (nsdsel_gtls_t*) pNsdsel;
+ nsd_gtls_t *pNsdGTLS = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert(pThis, nsdsel_gtls);
+ ISOBJ_TYPE_assert(pNsdGTLS, nsd_gtls);
+ if(pNsdGTLS->iMode == 1) {
+ if(pNsdGTLS->rtryCall != gtlsRtry_None) {
+ CHKiRet(doRetry(pNsdGTLS));
+ /* we used this up for our own internal processing, so the socket
+ * is not ready from the upper layer point of view.
+ */
+ *pbIsReady = 0;
+ FINALIZE;
+ }
+ }
+
+ CHKiRet(nsdsel_ptcp.IsReady(pThis->pTcp, pNsdGTLS->pTcp, waitOp, pbIsReady));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* ------------------------------ end support for the select() interface ------------------------------ */
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nsdsel_gtls)
+CODESTARTobjQueryInterface(nsdsel_gtls)
+ if(pIf->ifVersion != nsdCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = (rsRetVal(*)(nsdsel_t**)) nsdsel_gtlsConstruct;
+ pIf->Destruct = (rsRetVal(*)(nsdsel_t**)) nsdsel_gtlsDestruct;
+ pIf->Add = Add;
+ pIf->Select = Select;
+ pIf->IsReady = IsReady;
+finalize_it:
+ENDobjQueryInterface(nsdsel_gtls)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nsdsel_gtls, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsdsel_gtls)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(errmsg, CORE_COMPONENT);
+ objRelease(nsdsel_ptcp, LM_NSD_PTCP_FILENAME);
+ENDObjClassExit(nsdsel_gtls)
+
+
+/* Initialize the nsdsel_gtls class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nsdsel_gtls, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(nsdsel_ptcp, LM_NSD_PTCP_FILENAME));
+
+ /* set our own handlers */
+ENDObjClassInit(nsdsel_gtls)
+/* vi:set ai:
+ */
diff --git a/runtime/nsdsel_gtls.h b/runtime/nsdsel_gtls.h
new file mode 100644
index 00000000..7c2df684
--- /dev/null
+++ b/runtime/nsdsel_gtls.h
@@ -0,0 +1,42 @@
+/* An implementation of the nsd select interface for GnuTLS.
+ *
+ * Copyright (C) 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NSDSEL_GTLS_H
+#define INCLUDED_NSDSEL_GTLS_H
+
+#include "nsd.h"
+typedef nsdsel_if_t nsdsel_gtls_if_t; /* we just *implement* this interface */
+
+/* the nsdsel_gtls object */
+struct nsdsel_gtls_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ nsdsel_t *pTcp; /* our aggregated ptcp sel handler (which does almost everything) */
+};
+
+/* interface is defined in nsd.h, we just implement it! */
+#define nsdsel_gtlsCURR_IF_VERSION nsdCURR_IF_VERSION
+
+/* prototypes */
+PROTOTYPEObj(nsdsel_gtls);
+
+#endif /* #ifndef INCLUDED_NSDSEL_GTLS_H */
diff --git a/runtime/nsdsel_ptcp.c b/runtime/nsdsel_ptcp.c
new file mode 100644
index 00000000..41b85e0c
--- /dev/null
+++ b/runtime/nsdsel_ptcp.c
@@ -0,0 +1,196 @@
+/* nsdsel_ptcp.c
+ *
+ * An implementation of the nsd select() interface for plain tcp sockets.
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/select.h>
+
+#include "rsyslog.h"
+#include "module-template.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "nsd_ptcp.h"
+#include "nsdsel_ptcp.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
+
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(nsdsel_ptcp) /* be sure to specify the object type also in END macro! */
+ pThis->maxfds = 0;
+ FD_ZERO(&pThis->readfds);
+ FD_ZERO(&pThis->writefds);
+ENDobjConstruct(nsdsel_ptcp)
+
+
+/* destructor for the nsdsel_ptcp object */
+BEGINobjDestruct(nsdsel_ptcp) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nsdsel_ptcp)
+ENDobjDestruct(nsdsel_ptcp)
+
+
+/* Add a socket to the select set */
+static rsRetVal
+Add(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp)
+{
+ DEFiRet;
+ nsdsel_ptcp_t *pThis = (nsdsel_ptcp_t*) pNsdsel;
+ nsd_ptcp_t *pSock = (nsd_ptcp_t*) pNsd;
+
+ ISOBJ_TYPE_assert(pSock, nsd_ptcp);
+ ISOBJ_TYPE_assert(pThis, nsdsel_ptcp);
+
+ switch(waitOp) {
+ case NSDSEL_RD:
+ FD_SET(pSock->sock, &pThis->readfds);
+ break;
+ case NSDSEL_WR:
+ FD_SET(pSock->sock, &pThis->writefds);
+ break;
+ case NSDSEL_RDWR:
+ FD_SET(pSock->sock, &pThis->readfds);
+ FD_SET(pSock->sock, &pThis->writefds);
+ break;
+ }
+
+ if(pSock->sock > pThis->maxfds)
+ pThis->maxfds = pSock->sock;
+
+ RETiRet;
+}
+
+
+/* perform the select() piNumReady returns how many descriptors are ready for IO
+ * TODO: add timeout!
+ */
+static rsRetVal
+Select(nsdsel_t *pNsdsel, int *piNumReady)
+{
+ DEFiRet;
+ int i;
+ nsdsel_ptcp_t *pThis = (nsdsel_ptcp_t*) pNsdsel;
+
+ ISOBJ_TYPE_assert(pThis, nsdsel_ptcp);
+ assert(piNumReady != NULL);
+
+ if(Debug) { // TODO: debug setting!
+ // TODO: name in dbgprintf!
+ dbgprintf("--------<NSDSEL_PTCP> calling select, active fds (max %d): ", pThis->maxfds);
+ for(i = 0; i <= pThis->maxfds; ++i)
+ if(FD_ISSET(i, &pThis->readfds) || FD_ISSET(i, &pThis->writefds))
+ dbgprintf("%d ", i);
+ dbgprintf("\n");
+ }
+
+ /* now do the select */
+ *piNumReady = select(pThis->maxfds+1, &pThis->readfds, &pThis->writefds, NULL, NULL);
+
+ RETiRet;
+}
+
+
+/* check if a socket is ready for IO */
+static rsRetVal
+IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady)
+{
+ DEFiRet;
+ nsdsel_ptcp_t *pThis = (nsdsel_ptcp_t*) pNsdsel;
+ nsd_ptcp_t *pSock = (nsd_ptcp_t*) pNsd;
+
+ ISOBJ_TYPE_assert(pThis, nsdsel_ptcp);
+ ISOBJ_TYPE_assert(pSock, nsd_ptcp);
+ assert(pbIsReady != NULL);
+
+ switch(waitOp) {
+ case NSDSEL_RD:
+ *pbIsReady = FD_ISSET(pSock->sock, &pThis->readfds);
+ break;
+ case NSDSEL_WR:
+ *pbIsReady = FD_ISSET(pSock->sock, &pThis->writefds);
+ break;
+ case NSDSEL_RDWR:
+ *pbIsReady = FD_ISSET(pSock->sock, &pThis->readfds)
+ | FD_ISSET(pSock->sock, &pThis->writefds);
+ break;
+ }
+
+ RETiRet;
+}
+
+
+/* ------------------------------ end support for the select() interface ------------------------------ */
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nsdsel_ptcp)
+CODESTARTobjQueryInterface(nsdsel_ptcp)
+ if(pIf->ifVersion != nsdCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = (rsRetVal(*)(nsdsel_t**)) nsdsel_ptcpConstruct;
+ pIf->Destruct = (rsRetVal(*)(nsdsel_t**)) nsdsel_ptcpDestruct;
+ pIf->Add = Add;
+ pIf->Select = Select;
+ pIf->IsReady = IsReady;
+finalize_it:
+ENDobjQueryInterface(nsdsel_ptcp)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nsdsel_ptcp, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsdsel_ptcp)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(errmsg, CORE_COMPONENT);
+ENDObjClassExit(nsdsel_ptcp)
+
+
+/* Initialize the nsdsel_ptcp class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nsdsel_ptcp, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+
+ /* set our own handlers */
+ENDObjClassInit(nsdsel_ptcp)
+/* vi:set ai:
+ */
diff --git a/runtime/nsdsel_ptcp.h b/runtime/nsdsel_ptcp.h
new file mode 100644
index 00000000..6c0c7fa7
--- /dev/null
+++ b/runtime/nsdsel_ptcp.h
@@ -0,0 +1,44 @@
+/* An implementation of the nsd select interface for plain tcp sockets.
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NSDSEL_PTCP_H
+#define INCLUDED_NSDSEL_PTCP_H
+
+#include "nsd.h"
+typedef nsdsel_if_t nsdsel_ptcp_if_t; /* we just *implement* this interface */
+
+/* the nsdsel_ptcp object */
+struct nsdsel_ptcp_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ int maxfds;
+ fd_set readfds;
+ fd_set writefds;
+};
+
+/* interface is defined in nsd.h, we just implement it! */
+#define nsdsel_ptcpCURR_IF_VERSION nsdCURR_IF_VERSION
+
+/* prototypes */
+PROTOTYPEObj(nsdsel_ptcp);
+
+#endif /* #ifndef INCLUDED_NSDSEL_PTCP_H */
diff --git a/runtime/nssel.c b/runtime/nssel.c
new file mode 100644
index 00000000..d11d5fe1
--- /dev/null
+++ b/runtime/nssel.c
@@ -0,0 +1,227 @@
+/* nssel.c
+ *
+ * The io waiter is a helper object enabling us to wait on a set of streams to become
+ * ready for IO - this is modelled after select(). We need this, because
+ * stream drivers may have different concepts. Consequently,
+ * the structure must contain nsd_t's from the same stream driver type
+ * only. This is implemented as a singly-linked list where every
+ * new element is added at the top of the list.
+ *
+ * Work on this module begun 2008-04-22 by Rainer Gerhards.
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "module-template.h"
+#include "netstrm.h"
+#include "nssel.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+
+
+/* load our low-level driver. This must be done before any
+ * driver-specific functions (allmost all...) can be carried
+ * out. Note that the driver's .ifIsLoaded is correctly
+ * initialized by calloc() and we depend on that. Please note that
+ * we do some name-mangeling. We know that each nsd driver also needs
+ * a nssel driver. So we simply append "sel" to the nsd driver name: This,
+ * of course, means that the driver name must match these rules, but that
+ * shouldn't be a real problem.
+ * WARNING: this code is mostly identical to similar code in
+ * netstrms.c - TODO: abstract it and move it to some common place.
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+loadDrvr(nssel_t *pThis)
+{
+ DEFiRet;
+ uchar *pBaseDrvrName;
+ uchar szDrvrName[48]; /* 48 shall be large enough */
+
+ pBaseDrvrName = pThis->pBaseDrvrName;
+ if(pBaseDrvrName == NULL) /* if no drvr name is set, use system default */
+ pBaseDrvrName = glbl.GetDfltNetstrmDrvr();
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmnsdsel_%s", pBaseDrvrName) == sizeof(szDrvrName))
+ ABORT_FINALIZE(RS_RET_DRVRNAME_TOO_LONG);
+ CHKmalloc(pThis->pDrvrName = (uchar*) strdup((char*)szDrvrName));
+
+ pThis->Drvr.ifVersion = nsdCURR_IF_VERSION;
+ /* The pDrvrName+2 below is a hack to obtain the object name. It
+ * safes us to have yet another variable with the name without "lm" in
+ * front of it. If we change the module load interface, we may re-think
+ * about this hack, but for the time being it is efficient and clean
+ * enough. -- rgerhards, 2008-04-18
+ */
+ CHKiRet(obj.UseObj(__FILE__, szDrvrName+2, DONT_LOAD_LIB, (void*) &pThis->Drvr));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->pDrvrName != NULL)
+ free(pThis->pDrvrName);
+ pThis->pDrvrName = NULL;
+ }
+ RETiRet;
+}
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(nssel) /* be sure to specify the object type also in END macro! */
+ENDobjConstruct(nssel)
+
+
+/* destructor for the nssel object */
+BEGINobjDestruct(nssel) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nssel)
+ if(pThis->pDrvrData != NULL)
+ pThis->Drvr.Destruct(&pThis->pDrvrData);
+
+ /* and now we must release our driver, if we got one. We use the presence of
+ * a driver name string as load indicator (because we also need that string
+ * to release the driver
+ */
+ if(pThis->pDrvrName != NULL) {
+ obj.ReleaseObj(__FILE__, pThis->pDrvrName+2, DONT_LOAD_LIB, (void*) &pThis->Drvr);
+ free(pThis->pDrvrName);
+ }
+ENDobjDestruct(nssel)
+
+
+/* ConstructionFinalizer */
+static rsRetVal
+ConstructFinalize(nssel_t *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nssel);
+ CHKiRet(loadDrvr(pThis));
+ CHKiRet(pThis->Drvr.Construct(&pThis->pDrvrData));
+finalize_it:
+ RETiRet;
+}
+
+
+/* Add a stream object to the current select() set.
+ * Note that a single stream may have multiple "sockets" if
+ * it is a listener. If so, all of them are begin added.
+ */
+static rsRetVal
+Add(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, nssel);
+ ISOBJ_TYPE_assert(pStrm, netstrm);
+
+ CHKiRet(pThis->Drvr.Add(pThis->pDrvrData, pStrm->pDrvrData, waitOp));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* wait for IO to happen on one of our netstreams. iNumReady has
+ * the number of ready "sockets" after the call. This function blocks
+ * until some are ready. EAGAIN is retried.
+ */
+static rsRetVal
+Wait(nssel_t *pThis, int *piNumReady)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nssel);
+ assert(piNumReady != NULL);
+ iRet = pThis->Drvr.Select(pThis->pDrvrData, piNumReady);
+ RETiRet;
+}
+
+
+/* Check if a stream is ready for IO. *piNumReady contains the remaining number
+ * of ready streams. Note that this function may say the stream is not ready
+ * but still decrement *piNumReady. This can happen when (e.g. with TLS) the low
+ * level driver requires some IO which is hidden from the upper layer point of view.
+ * rgerhards, 2008-04-23
+ */
+static rsRetVal
+IsReady(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp, int *pbIsReady, int *piNumReady)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nssel);
+ ISOBJ_TYPE_assert(pStrm, netstrm);
+ assert(pbIsReady != NULL);
+ assert(piNumReady != NULL);
+ iRet = pThis->Drvr.IsReady(pThis->pDrvrData, pStrm->pDrvrData, waitOp, pbIsReady);
+ RETiRet;
+}
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nssel)
+CODESTARTobjQueryInterface(nssel)
+ if(pIf->ifVersion != nsselCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = nsselConstruct;
+ pIf->ConstructFinalize = ConstructFinalize;
+ pIf->Destruct = nsselDestruct;
+ pIf->Add = Add;
+ pIf->Wait = Wait;
+ pIf->IsReady = IsReady;
+finalize_it:
+ENDobjQueryInterface(nssel)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nssel, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nssel)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ENDObjClassExit(nssel)
+
+
+/* Initialize the nssel class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nssel, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+
+ /* set our own handlers */
+ENDObjClassInit(nssel)
+/* vi:set ai:
+ */
diff --git a/runtime/nssel.h b/runtime/nssel.h
new file mode 100644
index 00000000..8cb34f5a
--- /dev/null
+++ b/runtime/nssel.h
@@ -0,0 +1,56 @@
+/* Definitions for the nssel IO waiter.
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NSSEL_H
+#define INCLUDED_NSSEL_H
+
+#include "netstrms.h"
+
+/* the nssel object */
+struct nssel_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ nsd_t *pDrvrData; /**< the driver's data elements */
+ uchar *pBaseDrvrName; /**< nsd base driver name to use, or NULL if system default */
+ uchar *pDrvrName; /**< full base driver name (set when driver is loaded) */
+ nsdsel_if_t Drvr; /**< our stream driver */
+};
+
+
+/* interface */
+BEGINinterface(nssel) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(nssel_t **ppThis);
+ rsRetVal (*ConstructFinalize)(nssel_t *pThis);
+ rsRetVal (*Destruct)(nssel_t **ppThis);
+ rsRetVal (*Add)(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp);
+ rsRetVal (*Wait)(nssel_t *pThis, int *pNumReady);
+ rsRetVal (*IsReady)(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp, int *pbIsReady, int *piNumReady);
+ENDinterface(nssel)
+#define nsselCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+/* prototypes */
+PROTOTYPEObj(nssel);
+
+/* the name of our library binary */
+#define LM_NSSEL_FILENAME LM_NETSTRMS_FILENAME
+
+#endif /* #ifndef INCLUDED_NSSEL_H */
diff --git a/obj-types.h b/runtime/obj-types.h
index 4cd45153..5f531eb1 100644
--- a/obj-types.h
+++ b/runtime/obj-types.h
@@ -7,22 +7,23 @@
*
* Copyright 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef OBJ_TYPES_H_INCLUDED
@@ -63,13 +64,13 @@ typedef enum { /* IDs of base methods supported by all objects - used for jump t
/* the base data type for interfaces
* This MUST be in sync with the ifBEGIN macro
*/
-typedef struct interface_s {
+struct interface_s {
int ifVersion; /* must be set to version requested */
int ifIsLoaded; /* is the interface loaded? (0-no, 1-yes, 2-load failed; if not 1, functions can NOT be called! */
-} interface_t;
+};
-typedef struct objInfo_s {
+struct objInfo_s {
uchar *pszID; /* the object ID as a string */
size_t lenID; /* length of the ID string */
int iObjVers;
@@ -77,16 +78,16 @@ typedef struct objInfo_s {
rsRetVal (*objMethods[OBJ_NUM_METHODS])();
rsRetVal (*QueryIF)(interface_t*);
struct modInfo_s *pModInfo;
-} objInfo_t;
+};
-typedef struct obj { /* the dummy struct that each derived class can be casted to */
+struct obj_s { /* the dummy struct that each derived class can be casted to */
objInfo_t *pObjInfo;
#ifndef NDEBUG /* this means if debug... */
unsigned int iObjCooCKiE; /* must always be 0xBADEFEE for a valid object */
#endif
uchar *pszName; /* the name of *this* specific object instance */
-} obj_t;
+};
/* macros which must be gloablly-visible (because they are used during definition of
@@ -105,14 +106,28 @@ typedef struct obj { /* the dummy struct that each derived class can be casted t
do { \
ASSERT(pObj != NULL); \
ASSERT((unsigned) ((obj_t*) (pObj))->iObjCooCKiE == (unsigned) 0xBADEFEE); \
- ASSERT(!strcmp((char*)(((obj_t*)pObj)->pObjInfo->pszID), #objType)); \
- } while(0);
+ if(strcmp((char*)(((obj_t*)pObj)->pObjInfo->pszID), #objType)) { \
+ dbgprintf("%s:%d ISOBJ assert failure: invalid object type, expected '%s' " \
+ "actual '%s'\n", __FILE__, __LINE__, #objType, (((obj_t*)pObj)->pObjInfo->pszID)); \
+ assert(0); /* trigger assertion, messge we already have */ \
+ } \
+ } while(0)
#else /* non-debug mode, no checks but much faster */
# define BEGINobjInstance obj_t objData
# define ISOBJ_TYPE_assert(pObj, objType)
# define ISOBJ_assert(pObj)
#endif
+/* a set method for *very simple* object accesses. Note that this does
+ * NOT conform to the standard calling conventions and should be
+ * used only if actually nothing can go wrong! -- rgerhards, 2008-04-17
+ */
+#define DEFpropGetMeth(obj, prop, dataType)\
+ dataType obj##Get##prop(void)\
+ { \
+ return pThis->prop = pVal; \
+ }
+
#define DEFpropSetMethPTR(obj, prop, dataType)\
rsRetVal obj##Set##prop(obj##_t *pThis, dataType *pVal)\
{ \
@@ -312,8 +327,8 @@ rsRetVal objName##ClassExit(void) \
}
/* ------------------------------ object loader system ------------------------------ *
- * The following code is the early beginning of a dynamic object loader system. The
- * root idea is that all objects will become dynamically loadable libraries over time,
+ * The following code builds a dynamic object loader system. The
+ * root idea is that all objects are dynamically loadable,
* which is necessary to get a clean plug-in interface where every plugin can access
* rsyslog's rich object model via simple and quite portable methods.
*
@@ -326,17 +341,12 @@ rsRetVal objName##ClassExit(void) \
* macros create a static variable named like the object in each calling objects
* static data block.
*
- * To facilitate moving to this system, I begin to implement some hooks, which
- * allows to use interfaces today (when the rest of the infrastructure is not yet
- * there). This is in the hope that it will ease migration to the full-fledged system
- * once we are ready to work on that.
- * rgerhards, 2008-02-21
+ * rgerhards, 2008-02-21 (initial implementation), 2008-04-17 (update of this note)
*/
/* this defines the QueryInterface print entry point. Over time, it should be
* present in all objects.
*/
-//#define PROTOTYPEObjQueryInterface(obj) rsRetVal obj##QueryInterface(obj##_if_t *pThis)
#define BEGINobjQueryInterface(obj) \
rsRetVal obj##QueryInterface(obj##_if_t *pIf) \
{ \
@@ -371,9 +381,6 @@ rsRetVal objName##ClassExit(void) \
*/
#define CORE_COMPONENT NULL /* use this to indicate this is a core component */
#define DONT_LOAD_LIB NULL /* do not load a library to obtain object interface (currently same as CORE_COMPONENT) */
-/*#define objUse(objName, MYLIB, FILENAME) \
- obj.UseObj(__FILE__, (uchar*)#objName, MYLIB, (uchar*)FILENAME, (void*) &objName)
-*/
#define objUse(objName, FILENAME) \
obj.UseObj(__FILE__, (uchar*)#objName, (uchar*)FILENAME, (void*) &objName)
#define objRelease(objName, FILENAME) \
diff --git a/obj.c b/runtime/obj.c
index 7a4435ea..312ed223 100644
--- a/obj.c
+++ b/runtime/obj.c
@@ -50,22 +50,23 @@
*
* Copyright 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h"
@@ -1011,13 +1012,6 @@ FindObjInfo(cstr_t *pstrOID, objInfo_t **ppInfo)
bFound = 0;
i = 0;
while(!bFound && i < OBJ_NUM_IDS) {
-#if 0
-RUNLOG_VAR("%d", i);
-if(arrObjInfo[i] != NULL) {
-RUNLOG_VAR("%p", arrObjInfo[i]->pszID);
-RUNLOG_VAR("%s", arrObjInfo[i]->pszID);
-}
-#endif
if(arrObjInfo[i] != NULL && !rsCStrSzStrCmp(pstrOID, arrObjInfo[i]->pszID, arrObjInfo[i]->lenID)) {
bFound = 1;
break;
@@ -1198,15 +1192,14 @@ ReleaseObj(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);
+ dbgprintf("source file %s releasing object '%s', ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded);
if(pObjFile == NULL)
FINALIZE; /* if it is not a lodable module, we do not need to do anything... */
if(pIf->ifIsLoaded == 0) {
- ABORT_FINALIZE(RS_RET_OK); /* we are already set */ /* TODO: flag an error? */
- }
- if(pIf->ifIsLoaded == 2) {
+ ABORT_FINALIZE(RS_RET_OK); /* we are not loaded - this is perfectly OK... */
+ } else if(pIf->ifIsLoaded == 2) {
pIf->ifIsLoaded = 0; /* clean up */
ABORT_FINALIZE(RS_RET_OK); /* we had a load error and can not continue */
}
@@ -1215,7 +1208,6 @@ ReleaseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf)
CHKiRet(FindObjInfo(pStr, &pObjInfo));
/* if we reach this point, we have a valid pObjInfo */
- //if(pObjInfo->pModInfo != NULL) { /* NULL means core module */
module.Release(srcFile, &pObjInfo->pModInfo); /* decrease refcount */
pIf->ifIsLoaded = 0; /* indicated "no longer valid" */
@@ -1292,10 +1284,10 @@ objClassExit(void)
/* TODO: implement the class exits! */
#if 0
- errmsgClassInit(pModInfo);
cfsyslineInit(pModInfo);
varClassInit(pModInfo);
#endif
+ errmsgClassExit();
moduleClassExit();
RETiRet;
}
diff --git a/obj.h b/runtime/obj.h
index 29ad2ae4..dc04203b 100644
--- a/obj.h
+++ b/runtime/obj.h
@@ -23,22 +23,23 @@
*
* Copyright 2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef OBJ_H_INCLUDED
diff --git a/objomsr.c b/runtime/objomsr.c
index 6a617ad1..21d284f3 100644
--- a/objomsr.c
+++ b/runtime/objomsr.c
@@ -5,22 +5,23 @@
*
* Copyright 2007 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h"
@@ -140,6 +141,5 @@ int OMSRgetEntry(omodStringRequest_t *pThis, int iEntry, uchar **ppTplName, int
return RS_RET_OK;
}
-/*
- * vi:set ai:
+/* vim:set ai:
*/
diff --git a/objomsr.h b/runtime/objomsr.h
index 9fdddf69..2255e4f3 100644
--- a/objomsr.h
+++ b/runtime/objomsr.h
@@ -2,22 +2,23 @@
*
* Copyright 2007 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef OBJOMSR_H_INCLUDED
diff --git a/queue.c b/runtime/queue.c
index 0f58c545..56711416 100644
--- a/queue.c
+++ b/runtime/queue.c
@@ -43,7 +43,6 @@
#include <errno.h>
#include "rsyslog.h"
-#include "syslogd.h"
#include "queue.h"
#include "stringbuf.h"
#include "srUtils.h"
@@ -53,6 +52,7 @@
/* static data */
DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
/* forward-definitions */
rsRetVal queueChkPersist(queue_t *pThis);
@@ -642,7 +642,7 @@ queueLoadPersStrmInfoFixup(strm_t *pStrm, queue_t __attribute__((unused)) *pThis
DEFiRet;
ISOBJ_TYPE_assert(pStrm, strm);
ISOBJ_TYPE_assert(pThis, queue);
- CHKiRet(strmSetDir(pStrm, glblGetWorkDir(), strlen((char*)glblGetWorkDir())));
+ CHKiRet(strmSetDir(pStrm, glbl.GetWorkDir(), strlen((char*)glbl.GetWorkDir())));
finalize_it:
RETiRet;
}
@@ -667,7 +667,7 @@ queueHaveQIF(queue_t *pThis)
/* Construct file name */
lenQIFNam = snprintf((char*)pszQIFNam, sizeof(pszQIFNam) / sizeof(uchar), "%s/%s.qi",
- (char*) glblGetWorkDir(), (char*)pThis->pszFilePrefix);
+ (char*) glbl.GetWorkDir(), (char*)pThis->pszFilePrefix);
/* check if the file exists */
if(stat((char*) pszQIFNam, &stat_buf) == -1) {
@@ -704,7 +704,7 @@ queueTryLoadPersistedInfo(queue_t *pThis)
/* Construct file name */
lenQIFNam = snprintf((char*)pszQIFNam, sizeof(pszQIFNam) / sizeof(uchar), "%s/%s.qi",
- (char*) glblGetWorkDir(), (char*)pThis->pszFilePrefix);
+ (char*) glbl.GetWorkDir(), (char*)pThis->pszFilePrefix);
/* check if the file exists */
if(stat((char*) pszQIFNam, &stat_buf) == -1) {
@@ -791,7 +791,7 @@ static rsRetVal qConstructDisk(queue_t *pThis)
;
} else {
CHKiRet(strmConstruct(&pThis->tVars.disk.pWrite));
- CHKiRet(strmSetDir(pThis->tVars.disk.pWrite, glblGetWorkDir(), strlen((char*)glblGetWorkDir())));
+ CHKiRet(strmSetDir(pThis->tVars.disk.pWrite, glbl.GetWorkDir(), strlen((char*)glbl.GetWorkDir())));
CHKiRet(strmSetiMaxFiles(pThis->tVars.disk.pWrite, 10000000));
CHKiRet(strmSettOperationsMode(pThis->tVars.disk.pWrite, STREAMMODE_WRITE));
CHKiRet(strmSetsType(pThis->tVars.disk.pWrite, STREAMTYPE_FILE_CIRCULAR));
@@ -799,7 +799,7 @@ static rsRetVal qConstructDisk(queue_t *pThis)
CHKiRet(strmConstruct(&pThis->tVars.disk.pRead));
CHKiRet(strmSetbDeleteOnClose(pThis->tVars.disk.pRead, 1));
- CHKiRet(strmSetDir(pThis->tVars.disk.pRead, glblGetWorkDir(), strlen((char*)glblGetWorkDir())));
+ CHKiRet(strmSetDir(pThis->tVars.disk.pRead, glbl.GetWorkDir(), strlen((char*)glbl.GetWorkDir())));
CHKiRet(strmSetiMaxFiles(pThis->tVars.disk.pRead, 10000000));
CHKiRet(strmSettOperationsMode(pThis->tVars.disk.pRead, STREAMMODE_READ));
CHKiRet(strmSetsType(pThis->tVars.disk.pRead, STREAMTYPE_FILE_CIRCULAR));
@@ -1259,7 +1259,7 @@ rsRetVal queueConstruct(queue_t **ppThis, queueType_t qType, int iWorkerThreads,
/* we have an object, so let's fill the properties */
objConstructSetObjInfo(pThis);
- if((pThis->pszSpoolDir = (uchar*) strdup((char*)glblGetWorkDir())) == NULL)
+ if((pThis->pszSpoolDir = (uchar*) strdup((char*)glbl.GetWorkDir())) == NULL)
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
/* set some water marks so that we have useful defaults if none are set specifically */
@@ -1872,7 +1872,7 @@ static rsRetVal queuePersist(queue_t *pThis, int bIsCheckpoint)
/* Construct file name */
lenQIFNam = snprintf((char*)pszQIFNam, sizeof(pszQIFNam) / sizeof(uchar), "%s/%s.qi",
- (char*) glblGetWorkDir(), (char*)pThis->pszFilePrefix);
+ (char*) glbl.GetWorkDir(), (char*)pThis->pszFilePrefix);
if((bIsCheckpoint != QUEUE_CHECKPOINT) && (queueGetOverallQueueSize(pThis) == 0)) {
if(pThis->bNeedDelQIF) {
@@ -2313,6 +2313,7 @@ rsRetVal queueQueryInterface(void) { return RS_RET_NOT_IMPLEMENTED; }
*/
BEGINObjClassInit(queue, 1, OBJ_IS_CORE_MODULE)
/* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
/* now set our own handlers */
OBJSetMethodHandler(objMethod_SETPROPERTY, queueSetProperty);
diff --git a/queue.h b/runtime/queue.h
index 9e75b31b..9e75b31b 100644
--- a/queue.h
+++ b/runtime/queue.h
diff --git a/regexp.c b/runtime/regexp.c
index 86b3e6c4..86b3e6c4 100644
--- a/regexp.c
+++ b/runtime/regexp.c
diff --git a/regexp.h b/runtime/regexp.h
index 8f6ac891..8f6ac891 100644
--- a/regexp.h
+++ b/runtime/regexp.h
diff --git a/runtime/rsyslog.c b/runtime/rsyslog.c
new file mode 100644
index 00000000..c05119d8
--- /dev/null
+++ b/runtime/rsyslog.c
@@ -0,0 +1,237 @@
+/* rsyslog.c - the main entry point into rsyslog's runtime library (RTL)
+ *
+ * This module contains all function which work on a RTL global level. It's
+ * name is abbreviated to "rsrt" (rsyslog runtime).
+ *
+ * Please note that the runtime library tends to be plugin-safe. That is, it must be
+ * initialized by calling a global initialization function. However, that
+ * function checks if the library is already initialized and, if so, does
+ * nothing except incrementing a refeence count. Similarly, the deinit
+ * function does nothing as long as there are still other users (which
+ * is tracked via the refcount). As such, it is safe to call init and
+ * exit multiple times, as long as this are always matching calls. This
+ * capability is needed for a plugin system, where one plugin never
+ * knows what the other did. HOWEVER, as of this writing, not all runtime
+ * library objects may work cleanly without static global data (the
+ * debug system is a very good example of this). So while we aim at the
+ * ability to work well in a plugin environment, things may not really work
+ * out. If you intend to use the rsyslog runtime library inside plugins,
+ * you should investigate the situation in detail. Please note that the
+ * rsyslog project itself does not yet need this functionality - thus you
+ * can safely assume it is totally untested ;).
+ *
+ * rgerhards, 2008-04-17: I have now once again checked on the plugin-safety.
+ * Unfortunately, there is currently no hook at all with which we could
+ * abstract a global data instance class. As such, we can NOT make the
+ * runtime plugin-safe in the above-described sense. As the rsyslog
+ * project itself does not need this functionality (and it is quesationable
+ * if someone else ever will), we do currently do not make an effort to
+ * support it. So if you intend to use rsyslog runtime inside a non-rsyslog
+ * plugin system, be careful!
+ *
+ * The rsyslog runtime library is in general reentrant and thread-safe. There
+ * are some intentional exceptions (e.g. inside the msg object). These are
+ * documented. Any other threading and reentrency issue can be considered a bug.
+ *
+ * Module begun 2008-04-16 by Rainer Gerhards
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "vm.h"
+#include "sysvar.h"
+#include "stringbuf.h"
+#include "wti.h"
+#include "wtp.h"
+#include "expr.h"
+#include "ctok.h"
+#include "vmop.h"
+#include "vmstk.h"
+#include "vmprg.h"
+#include "datetime.h"
+#include "queue.h"
+#include "conf.h"
+#include "glbl.h"
+#include "errmsg.h"
+
+/* forward definitions */
+static rsRetVal dfltErrLogger(uchar *errMsg);
+
+/* globally visible static data - see comment in rsyslog.h for details */
+uchar *glblModPath; /* module load path */
+rsRetVal (*glblErrLogger)(uchar*) = dfltErrLogger; /* the error logger to use by the errmsg module */
+
+/* static data */
+static int iRefCount = 0; /* our refcount - it MUST exist only once inside a process (not thread)
+ thus it is perfectly OK to use a static. MUST be initialized to 0! */
+
+/* This is the default instance of the error logger. It simply writes the message
+ * to stderr. It is expected that this is replaced by the runtime user very early
+ * during startup (at least if the default is unsuitable). However, we provide a
+ * default so that we can log errors during the intial phase, most importantly
+ * during initialization. -- rgerhards. 2008-04-17
+ */
+static rsRetVal dfltErrLogger(uchar *errMsg)
+{
+ DEFiRet;
+ fprintf(stderr, "rsyslog runtime error: %s\n", errMsg);
+ RETiRet;
+}
+
+
+/* set the error log function
+ * rgerhards, 2008-04-18
+ */
+rsRetVal
+rsrtSetErrLogger(rsRetVal (*errLogger)(uchar*))
+{
+ DEFiRet;
+ assert(errLogger != NULL);
+ glblErrLogger = errLogger;
+ RETiRet;
+}
+
+
+/* globally initialze the runtime system
+ * NOTE: this is NOT thread safe and must not be called concurrently. If that
+ * ever poses a problem, we may use proper mutex calls - not considered needed yet.
+ * If ppErrObj is provided, it receives a char pointer to the name of the object that
+ * caused the problem (if one occured). The caller must never free this pointer. If
+ * ppErrObj is NULL, no such information will be provided. pObjIF is the pointer to
+ * the "obj" object interface, which may be used to query any other rsyslog objects.
+ * rgerhards, 2008-04-16
+ */
+rsRetVal
+rsrtInit(char **ppErrObj, obj_if_t *pObjIF)
+{
+ DEFiRet;
+
+ if(iRefCount == 0) {
+ /* init runtime only if not yet done */
+ if(ppErrObj != NULL) *ppErrObj = "obj";
+ CHKiRet(objClassInit(NULL)); /* *THIS* *MUST* always be the first class initilizer being called! */
+ CHKiRet(objGetObjInterface(pObjIF)); /* this provides the root pointer for all other queries */
+
+ /* initialize core 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
+ * up with an invalid call. The most important thing that can happen is that an error
+ * is detected and needs to be logged, wich in turn requires a broader number of classes
+ * to be available. The solution is that we take care in the order of calls AND use a
+ * class immediately after it is initialized. And, of course, we load those classes
+ * first that we use ourselfs... -- rgerhards, 2008-03-07
+ */
+ if(ppErrObj != NULL) *ppErrObj = "glbl";
+ CHKiRet(glblClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "datetime";
+ CHKiRet(datetimeClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "msg";
+ CHKiRet(msgClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "str,";
+ CHKiRet(strmClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "wti";
+ CHKiRet(wtiClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "wtp";
+ CHKiRet(wtpClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "queue";
+ CHKiRet(queueClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "vmstk";
+ CHKiRet(vmstkClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "sysvar";
+ CHKiRet(sysvarClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "vm";
+ CHKiRet(vmClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "vmop";
+ CHKiRet(vmopClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "vmprg";
+ CHKiRet(vmprgClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "ctok_token";
+ CHKiRet(ctok_tokenClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "ctok";
+ CHKiRet(ctokClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "expr";
+ CHKiRet(exprClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "conf";
+ CHKiRet(confClassInit(NULL));
+
+ /* dummy "classes" */
+ if(ppErrObj != NULL) *ppErrObj = "str";
+ CHKiRet(strInit());
+ }
+
+ ++iRefCount;
+ dbgprintf("rsyslog runtime initialized, version %s, current users %d\n", VERSION, iRefCount);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* globally de-initialze the runtime system
+ * NOTE: this is NOT thread safe and must not be called concurrently. If that
+ * ever poses a problem, we may use proper mutex calls - not considered needed yet.
+ * This function must be provided with the caller's obj object pointer. This is
+ * automatically deinitialized by the runtime system.
+ * rgerhards, 2008-04-16
+ */
+rsRetVal
+rsrtExit(void)
+{
+ DEFiRet;
+
+ if(iRefCount == 1) {
+ /* do actual de-init only if we are the last runtime user */
+ confClassExit();
+ glblClassExit();
+ objClassExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */
+ }
+
+ --iRefCount;
+ /* TODO we must deinit this pointer! pObjIF = NULL; / * no longer exists for this caller */
+
+ dbgprintf("rsyslog runtime de-initialized, current users %d\n", iRefCount);
+
+ RETiRet;
+}
+
+
+/* returns 0 if the rsyslog runtime is not initialized and another value
+ * if it is. This function is primarily meant to be used by runtime functions
+ * itself. However, it is safe to call it before initializing the runtime.
+ * Plugins should NOT rely on this function. The reason is that another caller
+ * may have already initialized it but deinits it before this plugin is done.
+ * So for plugins and like architectures, the right course of action is to
+ * call rsrtInit() and rsrtExit(), which can be called by multiple callers.
+ * rgerhards, 2008-04-16
+ */
+int rsrtIsInit(void)
+{
+ return iRefCount;
+}
+
+
+/* vim:set ai:
+ */
diff --git a/rsyslog.h b/runtime/rsyslog.h
index c73c659c..367a239f 100644
--- a/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -1,27 +1,28 @@
-/* Header file with global definitions for the whole
- * rsyslog project (including all subprojects like
- * rfc3195d).
+/* This is the header file for the rsyslog runtime. It must be included
+ * if someone intends to use the runtime.
+ *
* Begun 2005-09-15 RGerhards
*
- * Copyright (C) 2005 by Rainer Gerhards and Adiscon GmbH
+ * Copyright (C) 2005-2008 by Rainer Gerhards and Adiscon GmbH
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
-*/
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
#ifndef INCLUDED_RSYSLOG_H
#define INCLUDED_RSYSLOG_H
@@ -43,6 +44,44 @@
# define _FILE_OFFSET_BITS 64
#endif
+/* portability: not all platforms have these defines, so we
+ * define them here if they are missing. -- rgerhards, 2008-03-04
+ */
+#ifndef LOG_MAKEPRI
+# define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
+#endif
+#ifndef LOG_PRI
+# define LOG_PRI(p) ((p) & LOG_PRIMASK)
+#endif
+#ifndef LOG_FAC
+# define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)
+#endif
+
+
+/* define some base data types */
+typedef unsigned char uchar;/* get rid of the unhandy "unsigned char" */
+typedef struct thrdInfo thrdInfo_t;
+typedef struct obj_s obj_t;
+typedef struct filed selector_t;/* TODO: this so far resides in syslogd.c, think about modularization */
+typedef struct NetAddr netAddr_t;
+typedef struct netstrms_s netstrms_t;
+typedef struct netstrm_s netstrm_t;
+typedef struct nssel_s nssel_t;
+typedef enum nsdsel_waitOp_e nsdsel_waitOp_t;
+typedef struct nsd_ptcp_s nsd_ptcp_t;
+typedef struct nsd_gtls_s nsd_gtls_t;
+typedef struct nsd_gsspi_s nsd_gsspi_t;
+typedef struct nsd_nss_s nsd_nss_t;
+typedef struct nsdsel_ptcp_s nsdsel_ptcp_t;
+typedef struct nsdsel_gtls_s nsdsel_gtls_t;
+typedef obj_t nsd_t;
+typedef obj_t nsdsel_t;
+typedef struct msg msg_t;
+typedef struct interface_s interface_t;
+typedef struct objInfo_s objInfo_t;
+typedef enum rsRetVal_ rsRetVal; /**< friendly type for global return value */
+typedef rsRetVal (*errLogFunc_t)(uchar*); /* this is a trick to store a function ptr to a function returning a function ptr... */
+typedef struct tcpsrv_s tcpsrv_t;
/* some universal 64 bit define... */
typedef long long int64;
@@ -172,6 +211,19 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
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 */
+ RS_RET_MALICIOUS_HNAME = -2074, /**< remote peer is trying malicious things with its hostname */
+ RS_RET_ACCEPT_ERR = -2074, /**< error during accept() system call */
+ RS_RET_INVALID_HNAME = -2075, /**< remote peer's hostname invalid or unobtainable */
+ RS_RET_INVALID_PORT = -2076, /**< invalid port value */
+ RS_RET_COULD_NOT_BIND = -2077, /**< could not bind socket, defunct */
+ RS_RET_GNUTLS_ERR = -2078, /**< (unexpected) error in GnuTLS call */
+ RS_RET_MAX_SESS_REACHED = -2079, /**< max nbr of sessions reached, can not create more */
+ RS_RET_MAX_LSTN_REACHED = -2080, /**< max nbr of listeners reached, can not create more */
+ RS_RET_INVAID_DRVR_MODE = -2081, /**< tried to set mode not supported by driver */
+ RS_RET_DRVRNAME_TOO_LONG = -2082, /**< driver name too long - should never happen */
+ RS_RET_TLS_HANDSHAKE_ERR = -2083, /**< TLS handshake failed */
+ RS_RET_TLS_CERT_ERR = -2084, /**< generic TLS certificate error */
+ RS_RET_TLS_NO_CERT = -2085, /**< no TLS certificate available where one was expected */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
@@ -182,7 +234,6 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_NO_RUN = 3, /**< operation successful, but function does not like to be executed */
RS_RET_OK = 0 /**< operation successful */
};
-typedef enum rsRetVal_ rsRetVal; /**< friendly type for global return value */
/* some helpful macros to work with srRetVals.
* Be sure to call the to-be-returned variable always "iRet" and
@@ -247,9 +298,6 @@ typedef enum rsObjectID rsObjID;
#define RSFREEOBJ(x) {(x)->OID = OIDrsFreed; free(x);}
#endif
-/* get rid of the unhandy "unsigned char"
- */
-typedef unsigned char uchar;
/* for the time being, we do our own portability handling here. It
* looks like autotools either does not yet support checks for it, or
@@ -263,8 +311,26 @@ typedef unsigned char uchar;
void dbgprintf(char *, ...) __attribute__((format(printf, 1, 2)));
#include "debug.h"
+#include "obj.h"
+
+/* the variable below is a trick: before we can init the runtime, the caller
+ * may want to set a module load path. We can not do this via the glbl class
+ * because it needs an initialized runtime system (and may at some point in time
+ * even be loaded itself). So this is a no-go. What we do is use a single global
+ * variable which may be provided with a pointer by the caller. This variable
+ * resides in rsyslog.c, the main runtime file. We have not seen any realy valule
+ * in providing object access functions. If you don't like that, feel free to
+ * add them. -- rgerhards, 2008-04-17
+ */
+extern uchar *glblModPath; /* module load path */
+extern rsRetVal (*glblErrLogger)(uchar*);
+
+/* some runtime prototypes */
+rsRetVal rsrtInit(char **ppErrObj, obj_if_t *pObjIF);
+rsRetVal rsrtExit(void);
+int rsrtIsInit(void);
+rsRetVal rsrtSetErrLogger(rsRetVal (*errLogger)(uchar*));
#endif /* multi-include protection */
-/*
- * vi:set ai:
+/* vim:set ai:
*/
diff --git a/srUtils.h b/runtime/srUtils.h
index ebd6518f..bfce4cbb 100644
--- a/srUtils.h
+++ b/runtime/srUtils.h
@@ -7,22 +7,23 @@
*
* Copyright 2003-2007 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef __SRUTILS_H_INCLUDED__
#define __SRUTILS_H_INCLUDED__ 1
@@ -90,6 +91,7 @@ void mutexCancelCleanup(void *arg);
void srSleep(int iSeconds, int iuSeconds);
char *rs_strerror_r(int errnum, char *buf, size_t buflen);
int decodeSyslogName(uchar *name, syslogName_t *codetab);
+int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep);
/* mutex operations */
/* some macros to cancel-safe lock a mutex (it will automatically be released
diff --git a/srUtils.c b/runtime/srutils.c
index fa451b7e..97cc3252 100644
--- a/srUtils.c
+++ b/runtime/srutils.c
@@ -9,26 +9,28 @@
*
* Copyright 2003-2008 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h"
#include "rsyslog.h"
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -39,16 +41,16 @@
#include <assert.h>
#include <sys/wait.h>
#include <ctype.h>
-#include "liblogging-stub.h"
#define TRUE 1
#define FALSE 0
#include "srUtils.h"
-#include "syslogd.h"
#include "obj.h"
/* here we host some syslog specific names. There currently is no better place
* to do it, but over here is also not ideal... -- rgerhards, 2008-02-14
+ * rgerhards, 2008-04-16: note in LGPL move: the code tables below exist in
+ * the same way in BSD, so it is not a problem to move them from GPLv3 to LGPL.
*/
syslogName_t syslogPriNames[] = {
{"alert", LOG_ALERT},
@@ -502,5 +504,51 @@ int decodeSyslogName(uchar *name, syslogName_t *codetab)
}
+/**
+ * getSubString
+ *
+ * Copy a string byte by byte until the occurrence
+ * of a given separator.
+ *
+ * \param ppSrc Pointer to a pointer of the source array of characters. If a
+ separator detected the Pointer points to the next char after the
+ separator. Except if the end of the string is dedected ('\n').
+ Then it points to the terminator char.
+ * \param pDst Pointer to the destination array of characters. Here the substing
+ will be stored.
+ * \param DstSize Maximum numbers of characters to store.
+ * \param cSep Separator char.
+ * \ret int Returns 0 if no error occured.
+ *
+ * rgerhards, 2008-02-12: some notes are due... I will once again fix this function, this time
+ * so that it treats ' ' as a request for whitespace. But in general, the function and its callers
+ * should be changed over time, this is not really very good code...
+ */
+int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep)
+{
+ uchar *pSrc = *ppSrc;
+ int iErr = 0; /* 0 = no error, >0 = error */
+ while((cSep == ' ' ? !isspace(*pSrc) : *pSrc != cSep) && *pSrc != '\n' && *pSrc != '\0' && DstSize>1) {
+ *pDst++ = *(pSrc)++;
+ DstSize--;
+ }
+ /* check if the Dst buffer was to small */
+ if ((cSep == ' ' ? !isspace(*pSrc) : *pSrc != cSep) && *pSrc != '\n' && *pSrc != '\0') {
+ dbgprintf("in getSubString, error Src buffer > Dst buffer\n");
+ iErr = 1;
+ }
+ if (*pSrc == '\0' || *pSrc == '\n')
+ /* this line was missing, causing ppSrc to be invalid when it
+ * was returned in case of end-of-string. rgerhards 2005-07-29
+ */
+ *ppSrc = pSrc;
+ else
+ *ppSrc = pSrc+1;
+ *pDst = '\0';
+ return iErr;
+}
+
+
+
/* vim:set ai:
*/
diff --git a/stream.c b/runtime/stream.c
index 1be4571a..3afa9fcd 100644
--- a/stream.c
+++ b/runtime/stream.c
@@ -41,7 +41,6 @@
#include <errno.h>
#include "rsyslog.h"
-#include "syslogd.h"
#include "stringbuf.h"
#include "srUtils.h"
#include "obj.h"
diff --git a/stream.h b/runtime/stream.h
index 371358ab..371358ab 100644
--- a/stream.h
+++ b/runtime/stream.h
diff --git a/stringbuf.c b/runtime/stringbuf.c
index 4254d5bd..93d1e1ef 100644
--- a/stringbuf.c
+++ b/runtime/stringbuf.c
@@ -7,24 +7,25 @@
* All functions in this "class" start with rsCStr (rsyslog Counted String).
* begun 2005-09-07 rgerhards
*
- * Copyright (C) 2007 by Rainer Gerhards and Adiscon GmbH
+ * Copyright (C) 2007-2008 by Rainer Gerhards and Adiscon GmbH
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h"
diff --git a/stringbuf.h b/runtime/stringbuf.h
index e44e86e1..c1966449 100644
--- a/stringbuf.h
+++ b/runtime/stringbuf.h
@@ -15,22 +15,23 @@
* Copyright 2005
* Rainer Gerhards and Adiscon GmbH. All Rights Reserved.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef _STRINGBUF_H_INCLUDED__
#define _STRINGBUF_H_INCLUDED__ 1
diff --git a/sync.c b/runtime/sync.c
index a3053e28..a3053e28 100644
--- a/sync.c
+++ b/runtime/sync.c
diff --git a/sync.h b/runtime/sync.h
index 57144fee..57144fee 100644
--- a/sync.h
+++ b/runtime/sync.h
diff --git a/syslogd-types.h b/runtime/syslogd-types.h
index 9aea3778..be0dfdd8 100644
--- a/syslogd-types.h
+++ b/runtime/syslogd-types.h
@@ -6,28 +6,28 @@
*
* Copyright 2007 Rainer Gerhards and Adiscon GmbH.
*
- * This file is part of rsyslog.
+ * This file is part of the rsyslog runtime library.
*
- * 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 rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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,
+ * The rsyslog runtime library 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.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#ifndef SYSLOGD_TYPES_INCLUDED
#define SYSLOGD_TYPES_INCLUDED 1
#include "stringbuf.h"
-//#include "net.h"
#include <sys/param.h>
#if HAVE_SYSLOG_H
#include <syslog.h>
@@ -99,6 +99,5 @@ struct syslogTime {
typedef struct syslogTime syslogTime_t;
#endif /* #ifndef SYSLOGD_TYPES_INCLUDED */
-/*
- * vi:set ai:
+/* vi:set ai:
*/
diff --git a/sysvar.c b/runtime/sysvar.c
index 5eec8f67..5eec8f67 100644
--- a/sysvar.c
+++ b/runtime/sysvar.c
diff --git a/sysvar.h b/runtime/sysvar.h
index 35051b64..35051b64 100644
--- a/sysvar.h
+++ b/runtime/sysvar.h
diff --git a/var.c b/runtime/var.c
index 7e51fc6d..7e51fc6d 100644
--- a/var.c
+++ b/runtime/var.c
diff --git a/var.h b/runtime/var.h
index bbe7ba33..bbe7ba33 100644
--- a/var.h
+++ b/runtime/var.h
diff --git a/vm.c b/runtime/vm.c
index bcd331ec..bcd331ec 100644
--- a/vm.c
+++ b/runtime/vm.c
diff --git a/vm.h b/runtime/vm.h
index d2458220..d2458220 100644
--- a/vm.h
+++ b/runtime/vm.h
diff --git a/vmop.c b/runtime/vmop.c
index 219315c4..219315c4 100644
--- a/vmop.c
+++ b/runtime/vmop.c
diff --git a/vmop.h b/runtime/vmop.h
index 97f924d7..97f924d7 100644
--- a/vmop.h
+++ b/runtime/vmop.h
diff --git a/vmprg.c b/runtime/vmprg.c
index a2b744d7..a2b744d7 100644
--- a/vmprg.c
+++ b/runtime/vmprg.c
diff --git a/vmprg.h b/runtime/vmprg.h
index db1f62f0..db1f62f0 100644
--- a/vmprg.h
+++ b/runtime/vmprg.h
diff --git a/vmstk.c b/runtime/vmstk.c
index 1ee3d485..1ee3d485 100644
--- a/vmstk.c
+++ b/runtime/vmstk.c
diff --git a/vmstk.h b/runtime/vmstk.h
index 2d45ee4d..2d45ee4d 100644
--- a/vmstk.h
+++ b/runtime/vmstk.h
diff --git a/wti.c b/runtime/wti.c
index 82cd2165..0e04200c 100644
--- a/wti.c
+++ b/runtime/wti.c
@@ -40,7 +40,6 @@
#include <errno.h>
#include "rsyslog.h"
-#include "syslogd.h"
#include "stringbuf.h"
#include "srUtils.h"
#include "wtp.h"
diff --git a/wti.h b/runtime/wti.h
index b3d92473..b3d92473 100644
--- a/wti.h
+++ b/runtime/wti.h
diff --git a/wtp.c b/runtime/wtp.c
index fcc7589c..0658232b 100644
--- a/wtp.c
+++ b/runtime/wtp.c
@@ -41,7 +41,6 @@
#include <errno.h>
#include "rsyslog.h"
-#include "syslogd.h"
#include "stringbuf.h"
#include "srUtils.h"
#include "wtp.h"
diff --git a/wtp.h b/runtime/wtp.h
index 13ebe536..13ebe536 100644
--- a/wtp.h
+++ b/runtime/wtp.h
diff --git a/tcpclt.c b/tcpclt.c
index 3a76e47d..2bc2ea56 100644
--- a/tcpclt.c
+++ b/tcpclt.c
@@ -38,10 +38,9 @@
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#include "syslogd.h"
+#include "dirty.h"
#include "syslogd-types.h"
#include "net.h"
-#include "tcpsyslog.h"
#include "tcpclt.h"
#include "module-template.h"
#include "srUtils.h"
@@ -52,7 +51,6 @@ MODULE_TYPE_LIB
DEFobjStaticHelpers
/* Initialize TCP sockets (for sender)
- * This is done once per selector line, if not yet initialized.
*/
static int
CreateSocket(struct addrinfo *addrDest)
diff --git a/tcpclt.h b/tcpclt.h
index d2f1fe02..b7aada65 100644
--- a/tcpclt.h
+++ b/tcpclt.h
@@ -26,7 +26,6 @@
#ifndef TCPCLT_H_INCLUDED
#define TCPCLT_H_INCLUDED 1
-#include "tcpsyslog.h"
#include "obj.h"
/* the tcpclt object */
diff --git a/tcps_sess.c b/tcps_sess.c
index 001f32f0..6243d91f 100644
--- a/tcps_sess.c
+++ b/tcps_sess.c
@@ -27,35 +27,27 @@
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
*/
-
#include "config.h"
#include <stdlib.h>
#include <assert.h>
-#include <string.h>
#include <errno.h>
-#include <unistd.h>
-#include <stdarg.h>
#include <ctype.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
+
#include "rsyslog.h"
-#include "syslogd.h"
+#include "dirty.h"
#include "module-template.h"
#include "net.h"
#include "tcpsrv.h"
#include "tcps_sess.h"
#include "obj.h"
#include "errmsg.h"
+#include "netstrm.h"
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
+DEFobjCurrIf(netstrm)
/* forward definitions */
static rsRetVal Close(tcps_sess_t *pThis);
@@ -64,7 +56,6 @@ static rsRetVal Close(tcps_sess_t *pThis);
/* Standard-Constructor
*/
BEGINobjConstruct(tcps_sess) /* be sure to specify the object type also in END macro! */
- pThis->sock = -1; /* no sock */
pThis->iMsg = 0; /* just make sure... */
pThis->bAtStrtOfFram = 1; /* indicate frame header expected */
pThis->eFraming = TCP_FRAMING_OCTET_STUFFING; /* just make sure... */
@@ -90,8 +81,8 @@ finalize_it:
/* destructor for the tcps_sess object */
BEGINobjDestruct(tcps_sess) /* be sure to specify the object type also in END and CODESTART macros! */
CODESTARTobjDestruct(tcps_sess)
- if(pThis->sock != -1)
- Close(pThis);
+ if(pThis->pStrm != NULL)
+ netstrm.Destruct(&pThis->pStrm);
if(pThis->pSrv->pOnSessDestruct != NULL) {
pThis->pSrv->pOnSessDestruct(&pThis->pUsr);
@@ -99,7 +90,8 @@ CODESTARTobjDestruct(tcps_sess)
/* now destruct our own properties */
if(pThis->fromHost != NULL)
free(pThis->fromHost);
- close(pThis->sock);
+ if(pThis->fromHostIP != NULL)
+ free(pThis->fromHostIP);
ENDobjDestruct(tcps_sess)
@@ -110,6 +102,10 @@ ENDobjDebugPrint(tcps_sess)
/* set property functions */
+/* set the hostname. Note that the caller *hands over* the string. That is,
+ * the caller no longer controls it once SetHost() has received it. Most importantly,
+ * the caller must not free it. -- rgerhards, 2008-04-24
+ */
static rsRetVal
SetHost(tcps_sess_t *pThis, uchar *pszHost)
{
@@ -119,25 +115,43 @@ SetHost(tcps_sess_t *pThis, uchar *pszHost)
if(pThis->fromHost != NULL) {
free(pThis->fromHost);
- pThis->fromHost = NULL;
}
- if((pThis->fromHost = strdup((char*)pszHost)) == NULL)
- ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ pThis->fromHost = pszHost;
+
+ RETiRet;
+}
+
+/* set the remote host's IP. Note that the caller *hands over* the string. That is,
+ * the caller no longer controls it once SetHostIP() has received it. Most importantly,
+ * the caller must not free it. -- rgerhards, 2008-05-16
+ */
+static rsRetVal
+SetHostIP(tcps_sess_t *pThis, uchar *pszHostIP)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+
+ if(pThis->fromHostIP != NULL) {
+ free(pThis->fromHostIP);
+ }
+
+ pThis->fromHostIP = pszHostIP;
-finalize_it:
RETiRet;
}
static rsRetVal
-SetSock(tcps_sess_t *pThis, int sock)
+SetStrm(tcps_sess_t *pThis, netstrm_t *pStrm)
{
DEFiRet;
ISOBJ_TYPE_assert(pThis, tcps_sess);
- pThis->sock = sock;
+ pThis->pStrm = pStrm;
RETiRet;
}
+
static rsRetVal
SetMsgIdx(tcps_sess_t *pThis, int idx)
{
@@ -148,7 +162,7 @@ SetMsgIdx(tcps_sess_t *pThis, int idx)
}
-/* set out parent, the tcpsrv object */
+/* set our parent, the tcpsrv object */
static rsRetVal
SetTcpsrv(tcps_sess_t *pThis, tcpsrv_t *pSrv)
{
@@ -200,16 +214,15 @@ PrepareClose(tcps_sess_t *pThis)
/* In this case, we have an invalid frame count and thus
* generate an error message and discard the frame.
*/
- errmsg.LogError(NO_ERRCODE, "Incomplete frame at end of stream in session %d - "
- "ignoring extra data (a message may be lost).\n",
- pThis->sock);
+ errmsg.LogError(NO_ERRCODE, "Incomplete frame at end of stream in session %p - "
+ "ignoring extra data (a message may be lost).\n", pThis->pStrm);
/* nothing more to do */
} else { /* here, we have traditional framing. Missing LF at the end
* of message may occur. As such, we process the message in
* this case.
*/
dbgprintf("Extra data at end of stream in legacy syslog/tcp message - processing\n");
- parseAndSubmitMessage(pThis->fromHost, pThis->msg, pThis->iMsg, MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY);
+ parseAndSubmitMessage(pThis->fromHost, pThis->fromHostIP, pThis->msg, pThis->iMsg, MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY);
pThis->bAtStrtOfFram = 1;
}
@@ -228,10 +241,11 @@ Close(tcps_sess_t *pThis)
DEFiRet;
ISOBJ_TYPE_assert(pThis, tcps_sess);
- close(pThis->sock);
- pThis->sock = -1;
+ netstrm.Destruct(&pThis->pStrm);
free(pThis->fromHost);
pThis->fromHost = NULL; /* not really needed, but... */
+ free(pThis->fromHostIP);
+ pThis->fromHostIP = NULL; /* not really needed, but... */
RETiRet;
}
@@ -290,7 +304,7 @@ processDataRcvd(tcps_sess_t *pThis, char c)
if(pThis->iMsg >= MAXLINE) {
/* emergency, we now need to flush, no matter if we are at end of message or not... */
dbgprintf("error: message received is larger than MAXLINE, we split it\n");
- parseAndSubmitMessage(pThis->fromHost, pThis->msg, pThis->iMsg, MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY);
+ parseAndSubmitMessage(pThis->fromHost, pThis->fromHostIP, pThis->msg, pThis->iMsg, MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY);
pThis->iMsg = 0;
/* we might think if it is better to ignore the rest of the
* message than to treat it as a new one. Maybe this is a good
@@ -300,7 +314,7 @@ processDataRcvd(tcps_sess_t *pThis, char c)
}
if(c == '\n' && pThis->eFraming == TCP_FRAMING_OCTET_STUFFING) { /* record delemiter? */
- parseAndSubmitMessage(pThis->fromHost, pThis->msg, pThis->iMsg, MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY);
+ parseAndSubmitMessage(pThis->fromHost, pThis->fromHostIP, pThis->msg, pThis->iMsg, MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY);
pThis->iMsg = 0;
pThis->inputState = eAtStrtFram;
} else {
@@ -318,7 +332,7 @@ processDataRcvd(tcps_sess_t *pThis, char c)
pThis->iOctetsRemain--;
if(pThis->iOctetsRemain < 1) {
/* we have end of frame! */
- parseAndSubmitMessage(pThis->fromHost, pThis->msg, pThis->iMsg, MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY);
+ parseAndSubmitMessage(pThis->fromHost, pThis->fromHostIP, pThis->msg, pThis->iMsg, MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY);
pThis->iMsg = 0;
pThis->inputState = eAtStrtFram;
}
@@ -345,27 +359,13 @@ static rsRetVal
DataRcvd(tcps_sess_t *pThis, char *pData, size_t iLen)
{
DEFiRet;
- char *pMsg;
char *pEnd;
ISOBJ_TYPE_assert(pThis, tcps_sess);
assert(pData != NULL);
assert(iLen > 0);
- /* We now copy the message to the session buffer. As
- * it looks, we need to do this in any case because
- * we might run into multiple messages inside a single
- * buffer. Of course, we could think about optimizations,
- * but as this code is to be replaced by liblogging, it
- * probably doesn't make so much sense...
- * rgerhards 2005-07-04
- *
- * Algo:
- * - copy message to buffer until the first LF is found
- * - printline() the buffer
- * - continue with copying
- */
- pMsg = pThis->msg; /* just a shortcut */
+ /* We now copy the message to the session buffer. */
pEnd = pData + iLen; /* this is one off, which is intensional */
while(pData < pEnd) {
@@ -403,7 +403,8 @@ CODESTARTobjQueryInterface(tcps_sess)
pIf->SetUsrP = SetUsrP;
pIf->SetTcpsrv = SetTcpsrv;
pIf->SetHost = SetHost;
- pIf->SetSock = SetSock;
+ pIf->SetHostIP = SetHostIP;
+ pIf->SetStrm = SetStrm;
pIf->SetMsgIdx = SetMsgIdx;
finalize_it:
ENDobjQueryInterface(tcps_sess)
@@ -416,6 +417,7 @@ BEGINObjClassExit(tcps_sess, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END
CODESTARTObjClassExit(tcps_sess)
/* release objects we no longer need */
objRelease(errmsg, CORE_COMPONENT);
+ objRelease(netstrm, LM_NETSTRMS_FILENAME);
ENDObjClassExit(tcps_sess)
@@ -426,6 +428,7 @@ ENDObjClassExit(tcps_sess)
BEGINObjClassInit(tcps_sess, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE class also in END MACRO! */
/* request objects we use */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME));
/* set our own handlers */
OBJSetMethodHandler(objMethod_DEBUGPRINT, tcps_sessDebugPrint);
diff --git a/tcps_sess.h b/tcps_sess.h
index 0433fdfb..ff7c167a 100644
--- a/tcps_sess.h
+++ b/tcps_sess.h
@@ -28,18 +28,12 @@
/* a forward-definition, we are somewhat cyclic */
struct tcpsrv_s;
-/* framing modes for TCP */
-typedef enum _TCPFRAMINGMODE {
- TCP_FRAMING_OCTET_STUFFING = 0, /* traditional LF-delimited */
- TCP_FRAMING_OCTET_COUNTING = 1 /* -transport-tls like octet count */
- } TCPFRAMINGMODE;
-
/* the tcps_sess object */
typedef struct tcps_sess_s {
BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
struct tcpsrv_s *pSrv; /* pointer back to my server (e.g. for callbacks) */
- int sock;
- int iMsg; /* index of next char to store in msg */
+ netstrm_t *pStrm;
+ int iMsg; /* index of next char to store in msg */
int bAtStrtOfFram; /* are we at the very beginning of a new frame? */
enum {
eAtStrtFram,
@@ -48,8 +42,9 @@ typedef struct tcps_sess_s {
} inputState; /* our current state */
int iOctetsRemain; /* Number of Octets remaining in message */
TCPFRAMINGMODE eFraming;
- char msg[MAXLINE+1];
- char *fromHost;
+ uchar msg[MAXLINE+1];
+ uchar *fromHost;
+ uchar *fromHostIP;
void *pUsr; /* a user-pointer */
} tcps_sess_t;
@@ -67,7 +62,8 @@ BEGINinterface(tcps_sess) /* name must also be changed in ENDinterface macro! */
rsRetVal (*SetTcpsrv)(tcps_sess_t *pThis, struct tcpsrv_s *pSrv);
rsRetVal (*SetUsrP)(tcps_sess_t*, void*);
rsRetVal (*SetHost)(tcps_sess_t *pThis, uchar*);
- rsRetVal (*SetSock)(tcps_sess_t *pThis, int);
+ rsRetVal (*SetHostIP)(tcps_sess_t *pThis, uchar*);
+ rsRetVal (*SetStrm)(tcps_sess_t *pThis, netstrm_t*);
rsRetVal (*SetMsgIdx)(tcps_sess_t *pThis, int);
ENDinterface(tcps_sess)
#define tcps_sessCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
diff --git a/tcpsrv.c b/tcpsrv.c
index 955fb9b5..6db2fee7 100644
--- a/tcpsrv.c
+++ b/tcpsrv.c
@@ -54,7 +54,7 @@
#include <fcntl.h>
#endif
#include "rsyslog.h"
-#include "syslogd.h"
+#include "dirty.h"
#include "cfsysline.h"
#include "module-template.h"
#include "net.h"
@@ -62,43 +62,28 @@
#include "conf.h"
#include "tcpsrv.h"
#include "obj.h"
+#include "glbl.h"
+#include "netstrms.h"
+#include "netstrm.h"
+#include "nssel.h"
#include "errmsg.h"
MODULE_TYPE_LIB
/* defines */
#define TCPSESS_MAX_DEFAULT 200 /* default for nbr of tcp sessions if no number is given */
+#define TCPLSTN_MAX_DEFAULT 20 /* default for nbr of listeners */
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(conf)
+DEFobjCurrIf(glbl)
DEFobjCurrIf(tcps_sess)
DEFobjCurrIf(errmsg)
DEFobjCurrIf(net)
-
-
-
-/* code to free all sockets within a socket table.
- * A socket table is a descriptor table where the zero
- * element has the count of elements. This is used for
- * listening sockets. The socket table itself is also
- * freed.
- * A POINTER to this structure must be provided, thus
- * double indirection!
- * rgerhards, 2007-06-28
- */
-static void freeAllSockets(int **socks)
-{
- assert(socks != NULL);
- assert(*socks != NULL);
- while(**socks) {
- dbgprintf("Closing socket %d.\n", (*socks)[**socks]);
- close((*socks)[**socks]);
- (**socks)--;
- }
- free(*socks);
- *socks = NULL;
-}
+DEFobjCurrIf(netstrms)
+DEFobjCurrIf(netstrm)
+DEFobjCurrIf(nssel)
/* configure TCP listener settings. This is called during command
@@ -196,11 +181,15 @@ TCPSessGetNxtSess(tcpsrv_t *pThis, int iCurr)
{
register int i;
+ BEGINfunc
ISOBJ_TYPE_assert(pThis, tcpsrv);
- for(i = iCurr + 1 ; i < pThis->iSessMax ; ++i)
+ assert(pThis->pSessions != NULL);
+ for(i = iCurr + 1 ; i < pThis->iSessMax ; ++i) {
if(pThis->pSessions[i] != NULL)
break;
+ }
+ ENDfunc
return((i < pThis->iSessMax) ? i : -1);
}
@@ -213,54 +202,70 @@ TCPSessGetNxtSess(tcpsrv_t *pThis, int iCurr)
*/
static void deinit_tcp_listener(tcpsrv_t *pThis)
{
- int iTCPSess;
+ int i;
ISOBJ_TYPE_assert(pThis, tcpsrv);
- assert(pThis->pSessions != NULL);
- /* close all TCP connections! */
- iTCPSess = TCPSessGetNxtSess(pThis, -1);
- while(iTCPSess != -1) {
- tcps_sess.Destruct(&pThis->pSessions[iTCPSess]);
- /* now get next... */
- iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess);
+ if(pThis->pSessions != NULL) {
+ /* close all TCP connections! */
+ i = TCPSessGetNxtSess(pThis, -1);
+ while(i != -1) {
+ tcps_sess.Destruct(&pThis->pSessions[i]);
+ /* now get next... */
+ i = TCPSessGetNxtSess(pThis, i);
+ }
+
+ /* we are done with the session table - so get rid of it... */
+ free(pThis->pSessions);
+ pThis->pSessions = NULL; /* just to make sure... */
}
-
- /* we are done with the session table - so get rid of it...
- */
- free(pThis->pSessions);
- pThis->pSessions = NULL; /* just to make sure... */
if(pThis->TCPLstnPort != NULL)
free(pThis->TCPLstnPort);
- /* finally close the listen sockets themselfs */
- freeAllSockets(&pThis->pSocksLstn);
+ /* finally close our listen streams */
+ for(i = 0 ; i < pThis->iLstnMax ; ++i) {
+ netstrm.Destruct(pThis->ppLstn + i);
+ }
}
-/* Initialize TCP sockets (for listener)
- * This function returns either NULL (which means it failed) or
- * a pointer to an array of file descriptiors. If the pointer is
- * returned, the zeroest element [0] contains the count of valid
- * descriptors. The descriptors themself follow in range
- * [1] ... [num-descriptors]. It is guaranteed that each of these
- * descriptors is valid, at least when this function returns.
- * Please note that technically the array may be larger than the number
- * of valid pointers stored in it. The memory overhead is minimal, so
- * we do not bother to re-allocate an array of the exact size. Logically,
- * the array still contains the exactly correct number of descriptors.
+/* add a listen socket to our listen socket array. This is a callback
+ * invoked from the netstrm class. -- rgerhards, 2008-04-23
*/
-static int *create_tcp_socket(tcpsrv_t *pThis)
+static rsRetVal
+addTcpLstn(void *pUsr, netstrm_t *pLstn)
{
- struct addrinfo hints, *res, *r;
- int error, maxs, *s, *socks, on = 1;
- char *TCPLstnPort;
+ tcpsrv_t *pThis = (tcpsrv_t*) pUsr;
+ DEFiRet;
ISOBJ_TYPE_assert(pThis, tcpsrv);
+ ISOBJ_TYPE_assert(pLstn, netstrm);
+
+ if(pThis->iLstnMax >= TCPLSTN_MAX_DEFAULT)
+ ABORT_FINALIZE(RS_RET_MAX_LSTN_REACHED);
+
+ pThis->ppLstn[pThis->iLstnMax] = pLstn;
+ ++pThis->iLstnMax;
- if(!strcmp(pThis->TCPLstnPort, "0"))
- TCPLstnPort = "514";
+finalize_it:
+ RETiRet;
+}
+
+
+/* Initialize TCP sockets (for listener) and listens on them */
+static rsRetVal
+create_tcp_socket(tcpsrv_t *pThis)
+{
+ DEFiRet;
+ uchar *TCPLstnPort;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+
+ if(!strcmp((char*)pThis->TCPLstnPort, "0"))
+ TCPLstnPort = (uchar*)"514";
+ // TODO: we need to enable the caller to set a port (based on who is
+ // using this, 514 may be totally unsuitable... --- rgerhards, 2008-04-22
/* use default - we can not do service db update, because there is
* no IANA-assignment for syslog/tcp. In the long term, we might
* re-use RFC 3195 port of 601, but that would probably break to
@@ -268,121 +273,10 @@ static int *create_tcp_socket(tcpsrv_t *pThis)
* rgerhards, 2007-06-28
*/
else
- TCPLstnPort = pThis->TCPLstnPort;
- dbgprintf("creating tcp socket on port %s\n", TCPLstnPort);
- memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
- hints.ai_family = family;
- hints.ai_socktype = SOCK_STREAM;
-
- error = getaddrinfo(NULL, TCPLstnPort, &hints, &res);
- if(error) {
- errmsg.LogError(NO_ERRCODE, "%s", gai_strerror(error));
- return NULL;
- }
-
- /* Count max number of sockets we may open */
- for (maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++)
- /* EMPTY */;
- socks = malloc((maxs+1) * sizeof(int));
- if (socks == NULL) {
- errmsg.LogError(NO_ERRCODE, "couldn't allocate memory for TCP listen sockets, suspending TCP message reception.");
- freeaddrinfo(res);
- return NULL;
- }
-
- *socks = 0; /* num of sockets counter at start of array */
- s = socks + 1;
- for (r = res; r != NULL ; r = r->ai_next) {
- *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
- if (*s < 0) {
- if(!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT))
- errmsg.LogError(NO_ERRCODE, "create_tcp_socket(), socket");
- /* it is debatable if PF_INET with EAFNOSUPPORT should
- * also be ignored...
- */
- continue;
- }
-
-#ifdef IPV6_V6ONLY
- if (r->ai_family == AF_INET6) {
- int iOn = 1;
- if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
- (char *)&iOn, sizeof (iOn)) < 0) {
- errmsg.LogError(NO_ERRCODE, "TCP setsockopt");
- close(*s);
- *s = -1;
- continue;
- }
- }
-#endif
- if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR,
- (char *) &on, sizeof(on)) < 0 ) {
- errmsg.LogError(NO_ERRCODE, "TCP setsockopt(REUSEADDR)");
- close(*s);
- *s = -1;
- continue;
- }
-
- /* We need to enable BSD compatibility. Otherwise an attacker
- * could flood our log files by sending us tons of ICMP errors.
- */
-#ifndef OS_BSD
- if(net.should_use_so_bsdcompat()) {
- if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT,
- (char *) &on, sizeof(on)) < 0) {
- errmsg.LogError(NO_ERRCODE, "TCP setsockopt(BSDCOMPAT)");
- close(*s);
- *s = -1;
- continue;
- }
- }
-#endif
-
- if( (bind(*s, r->ai_addr, r->ai_addrlen) < 0)
-#ifndef IPV6_V6ONLY
- && (errno != EADDRINUSE)
-#endif
- ) {
- errmsg.LogError(NO_ERRCODE, "TCP bind");
- close(*s);
- *s = -1;
- continue;
- }
-
- if( listen(*s,pThis->iSessMax / 10 + 5) < 0) {
- /* If the listen fails, it most probably fails because we ask
- * for a too-large backlog. So in this case we first set back
- * to a fixed, reasonable, limit that should work. Only if
- * that fails, too, we give up.
- */
- errmsg.LogError(NO_ERRCODE, "listen with a backlog of %d failed - retrying with default of 32.",
- pThis->iSessMax / 10 + 5);
- if(listen(*s, 32) < 0) {
- errmsg.LogError(NO_ERRCODE, "TCP listen, suspending tcp inet");
- close(*s);
- *s = -1;
- continue;
- }
- }
-
- (*socks)++;
- s++;
- }
-
- if(res != NULL)
- freeaddrinfo(res);
+ TCPLstnPort = (uchar*)pThis->TCPLstnPort;
- if(Debug && *socks != maxs)
- dbgprintf("We could initialize %d TCP listen sockets out of %d we received "
- "- this may or may not be an error indication.\n", *socks, maxs);
-
- if(*socks == 0) {
- errmsg.LogError(NO_ERRCODE, "No TCP listen socket could successfully be initialized, "
- "message reception via TCP disabled.\n");
- free(socks);
- return(NULL);
- }
+ /* TODO: add capability to specify local listen address! */
+ CHKiRet(netstrm.LstnInit(pThis->pNS, (void*)pThis, addTcpLstn, TCPLstnPort, NULL, pThis->iSessMax));
/* OK, we had success. Now it is also time to
* initialize our connections
@@ -393,11 +287,11 @@ static int *create_tcp_socket(tcpsrv_t *pThis)
* we have assigned so far, because we can not really use it...
*/
errmsg.LogError(NO_ERRCODE, "Could not initialize TCP session table, suspending TCP message reception.");
- freeAllSockets(&socks); /* prevent a socket leak */
- return(NULL);
+ ABORT_FINALIZE(RS_RET_ERR);
}
- return(socks);
+finalize_it:
+ RETiRet;
}
@@ -412,34 +306,26 @@ static int *create_tcp_socket(tcpsrv_t *pThis)
* rgerhards, 2008-03-02
*/
static rsRetVal
-SessAccept(tcpsrv_t *pThis, tcps_sess_t **ppSess, int fd)
+SessAccept(tcpsrv_t *pThis, tcps_sess_t **ppSess, netstrm_t *pStrm)
{
DEFiRet;
tcps_sess_t *pSess;
- int newConn;
+ netstrm_t *pNewStrm = NULL;
int iSess = -1;
struct sockaddr_storage addr;
- socklen_t addrlen = sizeof(struct sockaddr_storage);
- uchar fromHost[NI_MAXHOST];
- uchar fromHostFQDN[NI_MAXHOST];
+ uchar *fromHostFQDN = NULL;
+ uchar *fromHostIP = NULL;
ISOBJ_TYPE_assert(pThis, tcpsrv);
- newConn = accept(fd, (struct sockaddr*) &addr, &addrlen);
- if (newConn < 0) {
- errmsg.LogError(NO_ERRCODE, "tcp accept, ignoring error and connection request");
- ABORT_FINALIZE(RS_RET_ERR); // TODO: better error code
- //was: return -1;
- }
+ CHKiRet(netstrm.AcceptConnReq(pStrm, &pNewStrm));
/* Add to session list */
iSess = TCPSessTblFindFreeSpot(pThis);
if(iSess == -1) {
errno = 0;
errmsg.LogError(NO_ERRCODE, "too many tcp sessions - dropping incoming request");
- close(newConn);
- ABORT_FINALIZE(RS_RET_ERR); // TODO: better error code
- //was: return -1;
+ ABORT_FINALIZE(RS_RET_MAX_SESS_REACHED);
} else {
/* we found a free spot and can construct our session object */
CHKiRet(tcps_sess.Construct(&pSess));
@@ -448,40 +334,30 @@ SessAccept(tcpsrv_t *pThis, tcps_sess_t **ppSess, int fd)
/* OK, we have a "good" index... */
/* get the host name */
- if(net.cvthname(&addr, fromHost, fromHostFQDN) != RS_RET_OK) {
- /* we seem to have something malicous - at least we
- * are now told to discard the connection request.
- * Error message has been generated by cvthname.
- */
- close (newConn);
- ABORT_FINALIZE(RS_RET_ERR); // TODO: better error code
- //was: return -1;
- }
+ CHKiRet(netstrm.GetRemoteHName(pNewStrm, &fromHostFQDN));
+ CHKiRet(netstrm.GetRemoteIP(pNewStrm, &fromHostIP));
+ /* TODO: check if we need to strip the domain name here -- rgerhards, 2008-04-24 */
- /* Here we check if a host is permitted to send us
- * syslog messages. If it isn't, we do not further
- * process the message but log a warning (if we are
- * configured to do this).
+ /* Here we check if a host is permitted to send us messages. If it isn't, we do not further
+ * process the message but log a warning (if we are configured to do this).
* rgerhards, 2005-09-26
*/
-RUNLOG_VAR("%p", ppSess);
-RUNLOG_VAR("%p", pSess);
if(!pThis->pIsPermittedHost((struct sockaddr*) &addr, (char*) fromHostFQDN, pThis->pUsr, pSess->pUsr)) {
- dbgprintf("%s is not an allowed sender\n", (char *) fromHostFQDN);
- if(option_DisallowWarning) {
+ dbgprintf("%s is not an allowed sender\n", fromHostFQDN);
+ if(glbl.GetOption_DisallowWarning()) {
errno = 0;
- errmsg.LogError(NO_ERRCODE, "TCP message from disallowed sender %s discarded",
- (char*)fromHost);
+ errmsg.LogError(NO_ERRCODE, "TCP message from disallowed sender %s discarded", fromHostFQDN);
}
- close(newConn);
ABORT_FINALIZE(RS_RET_HOST_NOT_PERMITTED);
}
/* OK, we have an allowed sender, so let's continue, what
* means we can finally fill in the session object.
*/
- CHKiRet(tcps_sess.SetHost(pSess, fromHost));
- CHKiRet(tcps_sess.SetSock(pSess, newConn));
+ CHKiRet(tcps_sess.SetHost(pSess, fromHostFQDN));
+ CHKiRet(tcps_sess.SetHostIP(pSess, fromHostIP));
+ CHKiRet(tcps_sess.SetStrm(pSess, pNewStrm));
+ pNewStrm = NULL; /* prevent it from being freed in error handler, now done in tcps_sess! */
CHKiRet(tcps_sess.SetMsgIdx(pSess, 0));
CHKiRet(tcps_sess.ConstructFinalize(pSess));
@@ -500,80 +376,69 @@ finalize_it:
tcps_sess.Destruct(&pThis->pSessions[iSess]);
}
iSess = -1; // TODO: change this to be fully iRet compliant ;)
+ if(pNewStrm != NULL)
+ netstrm.Destruct(&pNewStrm);
}
RETiRet;
}
-/* This function is called to gather input.
- */
+static void
+RunCancelCleanup(void *arg)
+{
+ nssel_t **ppSel = (nssel_t**) arg;
+
+ if(*ppSel != NULL)
+ nssel.Destruct(ppSel);
+}
+/* This function is called to gather input. */
static rsRetVal
Run(tcpsrv_t *pThis)
{
DEFiRet;
- int maxfds;
int nfds;
int i;
int iTCPSess;
- fd_set readfds;
+ int bIsReady;
tcps_sess_t *pNewSess;
+ nssel_t *pSel;
+ int state;
ISOBJ_TYPE_assert(pThis, tcpsrv);
- /* this is an endless loop - it is terminated when the thread is
- * signalled to do so. This, however, is handled by the framework,
- * right into the sleep below.
+ /* this is an endless loop - it is terminated by the framework canelling
+ * this thread. Thus, we also need to instantiate a cancel cleanup handler
+ * to prevent us from leaking anything. -- rgerharsd, 20080-04-24
*/
+ pthread_cleanup_push(RunCancelCleanup, (void*) &pSel);
while(1) {
- maxfds = 0;
- FD_ZERO (&readfds);
-
- /* Add the TCP listen sockets to the list of read descriptors.
- */
- if(pThis->pSocksLstn != NULL && *pThis->pSocksLstn) {
- for (i = 0; i < *pThis->pSocksLstn; i++) {
- /* The if() below is theoretically not needed, but I leave it in
- * so that a socket may become unsuable during execution. That
- * feature is not yet supported by the current code base.
- */
- if (pThis->pSocksLstn[i+1] != -1) {
- if(Debug)
- net.debugListenInfo(pThis->pSocksLstn[i+1], "TCP");
- FD_SET(pThis->pSocksLstn[i+1], &readfds);
- if(pThis->pSocksLstn[i+1]>maxfds) maxfds=pThis->pSocksLstn[i+1];
- }
- }
- /* do the sessions */
- iTCPSess = TCPSessGetNxtSess(pThis, -1);
- while(iTCPSess != -1) {
- int fdSess;
- fdSess = pThis->pSessions[iTCPSess]->sock; // TODO: NOT CLEAN!, use method
- dbgprintf("Adding TCP Session %d\n", fdSess);
- FD_SET(fdSess, &readfds);
- if (fdSess>maxfds) maxfds=fdSess;
- /* now get next... */
- iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess);
- }
+ CHKiRet(nssel.Construct(&pSel));
+ // TODO: set driver
+ CHKiRet(nssel.ConstructFinalize(pSel));
+
+ /* Add the TCP listen sockets to the list of read descriptors. */
+ for(i = 0 ; i < pThis->iLstnMax ; ++i) {
+ CHKiRet(nssel.Add(pSel, pThis->ppLstn[i], NSDSEL_RD));
}
- if(Debug) {
- // TODO: name in dbgprintf!
- dbgprintf("--------<TCPSRV> calling select, active file descriptors (max %d): ", maxfds);
- for (nfds = 0; nfds <= maxfds; ++nfds)
- if ( FD_ISSET(nfds, &readfds) )
- dbgprintf("%d ", nfds);
- dbgprintf("\n");
+ /* do the sessions */
+ iTCPSess = TCPSessGetNxtSess(pThis, -1);
+ while(iTCPSess != -1) {
+ /* TODO: access to pNsd is NOT really CLEAN, use method... */
+ CHKiRet(nssel.Add(pSel, pThis->pSessions[iTCPSess]->pStrm, NSDSEL_RD));
+ /* now get next... */
+ iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess);
}
/* wait for io to become ready */
- nfds = select(maxfds+1, (fd_set *) &readfds, NULL, NULL, NULL);
+ CHKiRet(nssel.Wait(pSel, &nfds));
- for (i = 0; i < *pThis->pSocksLstn; i++) {
- if (FD_ISSET(pThis->pSocksLstn[i+1], &readfds)) {
- dbgprintf("New connect on TCP inetd socket: #%d\n", pThis->pSocksLstn[i+1]);
-RUNLOG_VAR("%p", &pNewSess);
- SessAccept(pThis, &pNewSess, pThis->pSocksLstn[i+1]);
+ for(i = 0 ; i < pThis->iLstnMax ; ++i) {
+ CHKiRet(nssel.IsReady(pSel, pThis->ppLstn[i], NSDSEL_RD, &bIsReady, &nfds));
+ if(bIsReady) {
+ dbgprintf("New connect on NSD %p.\n", pThis->ppLstn[i]);
+ SessAccept(pThis, &pNewSess, pThis->ppLstn[i]);
--nfds; /* indicate we have processed one */
}
}
@@ -581,12 +446,10 @@ RUNLOG_VAR("%p", &pNewSess);
/* now check the sessions */
iTCPSess = TCPSessGetNxtSess(pThis, -1);
while(nfds && iTCPSess != -1) {
- int fdSess;
- int state;
- fdSess = pThis->pSessions[iTCPSess]->sock; // TODO: not clean, use method
- if(FD_ISSET(fdSess, &readfds)) {
+ CHKiRet(nssel.IsReady(pSel, pThis->pSessions[iTCPSess]->pStrm, NSDSEL_RD, &bIsReady, &nfds));
+ if(bIsReady) {
char buf[MAXLINE];
- dbgprintf("tcp session socket with new data: #%d\n", fdSess);
+ dbgprintf("netstream %p with new data\n", pThis->pSessions[iTCPSess]->pStrm);
/* Receive message */
state = pThis->pRcvData(pThis->pSessions[iTCPSess], buf, sizeof(buf));
@@ -594,7 +457,8 @@ RUNLOG_VAR("%p", &pNewSess);
pThis->pOnRegularClose(pThis->pSessions[iTCPSess]);
tcps_sess.Destruct(&pThis->pSessions[iTCPSess]);
} else if(state == -1) {
- errmsg.LogError(NO_ERRCODE, "TCP session %d will be closed, error ignored\n", fdSess);
+ errmsg.LogError(NO_ERRCODE, "netstream session %p will be closed, error ignored\n",
+ pThis->pSessions[iTCPSess]->pStrm);
pThis->pOnErrClose(pThis->pSessions[iTCPSess]);
tcps_sess.Destruct(&pThis->pSessions[iTCPSess]);
} else {
@@ -613,29 +477,45 @@ RUNLOG_VAR("%p", &pNewSess);
}
iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess);
}
+ CHKiRet(nssel.Destruct(&pSel));
}
+ /* note that this point is usually not reached */
+ pthread_cleanup_pop(0); /* remove cleanup handler */
+
+finalize_it: // TODO: think: is it really good to exit the loop?
RETiRet;
}
-/* Standard-Constructor
- */
+/* Standard-Constructor */
BEGINobjConstruct(tcpsrv) /* be sure to specify the object type also in END macro! */
- pThis->pSocksLstn = NULL;
- pThis->iSessMax = 200; /* TODO: useful default ;) */
+ pThis->iSessMax = TCPSESS_MAX_DEFAULT; /* TODO: useful default ;) */
ENDobjConstruct(tcpsrv)
-/* ConstructionFinalizer
- */
+/* ConstructionFinalizer */
static rsRetVal
-tcpsrvConstructFinalize(tcpsrv_t __attribute__((unused)) *pThis)
+tcpsrvConstructFinalize(tcpsrv_t *pThis)
{
DEFiRet;
ISOBJ_TYPE_assert(pThis, tcpsrv);
- pThis->pSocksLstn = pThis->OpenLstnSocks(pThis);
+ /* prepare network stream subsystem */
+ CHKiRet(netstrms.Construct(&pThis->pNS));
+ CHKiRet(netstrms.SetDrvrMode(pThis->pNS, pThis->iDrvrMode));
+ // TODO: set driver!
+ CHKiRet(netstrms.ConstructFinalize(pThis->pNS));
+
+ /* set up listeners */
+ CHKmalloc(pThis->ppLstn = calloc(TCPLSTN_MAX_DEFAULT, sizeof(netstrm_t*)));
+ iRet = pThis->OpenLstnSocks(pThis);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->pNS != NULL)
+ netstrms.Destruct(&pThis->pNS);
+ }
RETiRet;
}
@@ -647,6 +527,11 @@ CODESTARTobjDestruct(tcpsrv)
pThis->OnDestruct(pThis->pUsr);
deinit_tcp_listener(pThis);
+
+ if(pThis->pNS != NULL)
+ netstrms.Destruct(&pThis->pNS);
+ if(pThis->ppLstn != NULL)
+ free(pThis->ppLstn);
ENDobjDestruct(tcpsrv)
@@ -729,7 +614,7 @@ SetCBOnErrClose(tcpsrv_t *pThis, rsRetVal (*pCB)(tcps_sess_t*))
}
static rsRetVal
-SetCBOpenLstnSocks(tcpsrv_t *pThis, int* (*pCB)(tcpsrv_t*))
+SetCBOpenLstnSocks(tcpsrv_t *pThis, rsRetVal (*pCB)(tcpsrv_t*))
{
DEFiRet;
pThis->OpenLstnSocks = pCB;
@@ -743,6 +628,18 @@ SetUsrP(tcpsrv_t *pThis, void *pUsr)
pThis->pUsr = pUsr;
RETiRet;
}
+/* set the driver mode -- rgerhards, 2008-04-30
+ */
+static rsRetVal
+SetDrvrMode(tcpsrv_t *pThis, int iMode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->iDrvrMode = iMode;
+ RETiRet;
+}
+
+
/* queryInterface function
@@ -770,6 +667,7 @@ CODESTARTobjQueryInterface(tcpsrv)
pIf->Run = Run;
pIf->SetUsrP = SetUsrP;
+ pIf->SetDrvrMode = SetDrvrMode;
pIf->SetCBIsPermittedHost = SetCBIsPermittedHost;
pIf->SetCBOpenLstnSocks = SetCBOpenLstnSocks;
pIf->SetCBRcvData = SetCBRcvData;
@@ -793,7 +691,11 @@ CODESTARTObjClassExit(tcpsrv)
/* release objects we no longer need */
objRelease(tcps_sess, DONT_LOAD_LIB);
objRelease(conf, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
+ objRelease(netstrms, DONT_LOAD_LIB);
+ objRelease(nssel, DONT_LOAD_LIB);
+ objRelease(netstrm, LM_NETSTRMS_FILENAME);
objRelease(net, LM_NET_FILENAME);
ENDObjClassExit(tcpsrv)
@@ -806,8 +708,12 @@ BEGINObjClassInit(tcpsrv, 1, OBJ_IS_LOADABLE_MODULE) /* class, version - CHANGE
/* request objects we use */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(netstrm, DONT_LOAD_LIB));
+ CHKiRet(objUse(nssel, DONT_LOAD_LIB));
CHKiRet(objUse(tcps_sess, DONT_LOAD_LIB));
CHKiRet(objUse(conf, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
/* set our own handlers */
OBJSetMethodHandler(objMethod_DEBUGPRINT, tcpsrvDebugPrint);
diff --git a/tcpsrv.h b/tcpsrv.h
index 20a7ea25..07826125 100644
--- a/tcpsrv.h
+++ b/tcpsrv.h
@@ -26,9 +26,12 @@
#include "tcps_sess.h"
/* the tcpsrv object */
-typedef struct tcpsrv_s {
+struct tcpsrv_s {
BEGINobjInstance; /**< Data to implement generic object - MUST be the first data element! */
- int *pSocksLstn; /**< listen socket array for server [0] holds count */
+ netstrms_t *pNS; /**< pointer to network stream subsystem */
+ int iDrvrMode; /**< mode of the stream driver to use */
+ int iLstnMax; /**< max nbr of listeners currently supported */
+ netstrm_t **ppLstn; /**< our netstream listners */
int iSessMax; /**< max number of sessions supported */
char *TCPLstnPort; /**< the port the listener shall listen on */
tcps_sess_t **pSessions;/**< array of all of our sessions */
@@ -36,16 +39,16 @@ typedef struct tcpsrv_s {
/* callbacks */
int (*pIsPermittedHost)(struct sockaddr *addr, char *fromHostFQDN, void*pUsrSrv, void*pUsrSess);
int (*pRcvData)(tcps_sess_t*, char*, size_t);
- int* (*OpenLstnSocks)(struct tcpsrv_s*);
+ rsRetVal (*OpenLstnSocks)(struct tcpsrv_s*);
rsRetVal (*pOnListenDeinit)(void*);
rsRetVal (*OnDestruct)(void*);
rsRetVal (*pOnRegularClose)(tcps_sess_t *pSess);
rsRetVal (*pOnErrClose)(tcps_sess_t *pSess);
/* session specific callbacks */
- rsRetVal (*pOnSessAccept)(struct tcpsrv_s *, tcps_sess_t*);
+ rsRetVal (*pOnSessAccept)(tcpsrv_t *, tcps_sess_t*);
rsRetVal (*OnSessConstructFinalize)(void*);
rsRetVal (*pOnSessDestruct)(void*);
-} tcpsrv_t;
+};
/* interfaces */
@@ -55,24 +58,25 @@ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */
rsRetVal (*ConstructFinalize)(tcpsrv_t __attribute__((unused)) *pThis);
rsRetVal (*Destruct)(tcpsrv_t **ppThis);
void (*configureTCPListen)(tcpsrv_t*, char *cOptarg);
- int (*SessAccept)(tcpsrv_t *pThis, tcps_sess_t**ppSess, int fd);
- int* (*create_tcp_socket)(tcpsrv_t *pThis);
+ rsRetVal (*SessAccept)(tcpsrv_t *pThis, tcps_sess_t **ppSess, netstrm_t *pStrm);
+ rsRetVal (*create_tcp_socket)(tcpsrv_t *pThis);
rsRetVal (*Run)(tcpsrv_t *pThis);
/* set methods */
rsRetVal (*SetUsrP)(tcpsrv_t*, void*);
rsRetVal (*SetCBIsPermittedHost)(tcpsrv_t*, int (*) (struct sockaddr *addr, char*, void*, void*));
- rsRetVal (*SetCBOpenLstnSocks)(tcpsrv_t *, int* (*)(tcpsrv_t*));
+ rsRetVal (*SetCBOpenLstnSocks)(tcpsrv_t *, rsRetVal (*)(tcpsrv_t*));
rsRetVal (*SetCBRcvData)(tcpsrv_t *, int (*)(tcps_sess_t*, char*, size_t));
rsRetVal (*SetCBOnListenDeinit)(tcpsrv_t*, rsRetVal (*)(void*));
rsRetVal (*SetCBOnDestruct)(tcpsrv_t*, rsRetVal (*) (void*));
rsRetVal (*SetCBOnRegularClose)(tcpsrv_t*, rsRetVal (*) (tcps_sess_t*));
rsRetVal (*SetCBOnErrClose)(tcpsrv_t*, rsRetVal (*) (tcps_sess_t*));
+ rsRetVal (*SetDrvrMode)(tcpsrv_t *pThis, int iMode);
/* session specifics */
rsRetVal (*SetCBOnSessAccept)(tcpsrv_t*, rsRetVal (*) (tcpsrv_t*, tcps_sess_t*));
rsRetVal (*SetCBOnSessDestruct)(tcpsrv_t*, rsRetVal (*) (void*));
rsRetVal (*SetCBOnSessConstructFinalize)(tcpsrv_t*, rsRetVal (*) (void*));
ENDinterface(tcpsrv)
-#define tcpsrvCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+#define tcpsrvCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */
/* prototypes */
diff --git a/tcpsyslog.c b/tcpsyslog.c
deleted file mode 100644
index d00731d3..00000000
--- a/tcpsyslog.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* tcpsyslog.c
- * This is the implementation of TCP-based syslog. It includes those
- * (few) things that both clients and servers need.
- *
- * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
- * This file is under development and has not yet arrived at being fully
- * self-contained and a real object. So far, it is mostly an excerpt
- * of the "old" message code without any modifications. However, it
- * helps to have things at the right place one we go to the meat of it.
- *
- * Copyright 2007 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 <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- */
-#include "config.h"
-#include "rsyslog.h"
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <errno.h>
-#include <assert.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#include "syslogd.h"
-#include "syslogd-types.h"
-#include "net.h"
-#include "tcpsyslog.h"
-#include "srUtils.h"
-
-
-/* vi:set ai:
- */
diff --git a/tcpsyslog.h b/tcpsyslog.h
deleted file mode 100644
index 13c40a92..00000000
--- a/tcpsyslog.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* tcpsyslog.h
- * These are the definitions for TCP-based syslog.
- *
- * File begun on 2007-07-21 by RGerhards (extracted from syslogd.c)
- *
- * Copyright 2007 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 <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- */
-#ifndef TCPSYSLOG_H_INCLUDED
-#define TCPSYSLOG_H_INCLUDED 1
-
-#include <netdb.h>
-
-typedef enum _TCPFRAMINGMODE {
- TCP_FRAMING_OCTET_STUFFING = 0, /* traditional LF-delimited */
- TCP_FRAMING_OCTET_COUNTING = 1 /* -transport-tls like octet count */
- } TCPFRAMINGMODE;
-
-#endif /* #ifndef TCPSYSLOG_H_INCLUDED */
-/*
- * vi:set ai:
- */
diff --git a/template.c b/template.c
index 844c5aec..e5021f35 100644
--- a/template.c
+++ b/template.c
@@ -33,7 +33,7 @@
#include "syslogd-types.h"
#include "template.h"
#include "msg.h"
-#include "syslogd.h"
+#include "dirty.h"
#include "obj.h"
#include "errmsg.h"
diff --git a/threads.c b/threads.c
index e32ff0d9..f4f604fc 100644
--- a/threads.c
+++ b/threads.c
@@ -33,7 +33,7 @@
#include <assert.h>
#include "rsyslog.h"
-#include "syslogd.h"
+#include "dirty.h"
#include "linkedlist.h"
#include "threads.h"
diff --git a/threads.h b/threads.h
index aa6a5c28..78924d95 100644
--- a/threads.h
+++ b/threads.h
@@ -23,16 +23,15 @@
#ifndef THREADS_H_INCLUDED
#define THREADS_H_INCLUDED
-
/* the thread object */
-typedef struct thrdInfo {
+struct thrdInfo {
pthread_mutex_t *mutTermOK; /* Is it ok to terminate that thread now? */
int bIsActive; /* Is thread running? */
int bShallStop; /* set to 1 if the thread should be stopped ? */
rsRetVal (*pUsrThrdMain)(struct thrdInfo*); /* user thread main to be called in new thread */
rsRetVal (*pAfterRun)(struct thrdInfo*); /* cleanup function */
pthread_t thrdID;
-} thrdInfo_t;
+};
/* prototypes */
rsRetVal thrdExit(void);
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 00000000..7fe420b0
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,44 @@
+sbin_PROGRAMS =
+man_MANS = rsyslogd.8 rsyslog.conf.5
+
+sbin_PROGRAMS += rsyslogd
+rsyslogd_SOURCES = \
+ syslogd.c \
+ syslogd.h \
+ omshell.c \
+ omshell.h \
+ omusrmsg.c \
+ omusrmsg.h \
+ omfwd.c \
+ omfwd.h \
+ omfile.c \
+ omfile.h \
+ omdiscard.c \
+ omdiscard.h \
+ iminternal.c \
+ iminternal.h \
+ pidfile.c \
+ pidfile.h \
+ \
+ ../dirty.h \
+ \
+ ../action.h \
+ ../action.c \
+ ../threads.c \
+ ../threads.h \
+ \
+ ../parse.c \
+ ../parse.h \
+ \
+ ../outchannel.c \
+ ../outchannel.h \
+ ../template.c \
+ ../template.h \
+ ../conf.c \
+ ../conf.h
+
+rsyslogd_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
+rsyslogd_LDADD = $(zlib_libs) $(pthreads_libs) $(dl_libs) $(rt_libs) $(rsrt_libs)
+rsyslogd_LDFLAGS = -export-dynamic
+
+EXTRA_DIST = $(man_MANS)
diff --git a/tools/gnutls/cert-gen-selfsigned b/tools/gnutls/cert-gen-selfsigned
new file mode 100755
index 00000000..e1c25386
--- /dev/null
+++ b/tools/gnutls/cert-gen-selfsigned
@@ -0,0 +1,6 @@
+#/bin/sh
+# generates a self-signed certificate and key suitable for use with rsyslog
+# 2008-05-08, rgerhards
+# TODO: make this a robust shell script
+certtool --generate-privkey --outfile $1-key.pem
+certtool --generate-self-signed --load-privkey $1-key.pem --outfile $1-cert.pem
diff --git a/tools/gnutls/cert-show-fingerprint b/tools/gnutls/cert-show-fingerprint
new file mode 100755
index 00000000..f61c6840
--- /dev/null
+++ b/tools/gnutls/cert-show-fingerprint
@@ -0,0 +1,6 @@
+#/bin/sh
+# must be called with the certificate file as first parameter. Displays all
+# fingerprints for the first certificate.
+# 2008-05-08, rgerhards
+# TODO: make this a robust shell script
+certtool -i < $1|grep Fingerprint
diff --git a/iminternal.c b/tools/iminternal.c
index 60460a99..60460a99 100644
--- a/iminternal.c
+++ b/tools/iminternal.c
diff --git a/iminternal.h b/tools/iminternal.h
index 8dc0f171..8dc0f171 100644
--- a/iminternal.h
+++ b/tools/iminternal.h
diff --git a/omdiscard.c b/tools/omdiscard.c
index f13144e8..f13144e8 100644
--- a/omdiscard.c
+++ b/tools/omdiscard.c
diff --git a/omdiscard.h b/tools/omdiscard.h
index 116308a4..116308a4 100644
--- a/omdiscard.h
+++ b/tools/omdiscard.h
diff --git a/omfile.c b/tools/omfile.c
index 6a53a723..285e798d 100644
--- a/omfile.c
+++ b/tools/omfile.c
@@ -85,6 +85,7 @@ static int bEnableSync = 0;/* enable syncing of files (no dash in front of pathn
static uchar *pszTplName = NULL; /* name of the default template to use */
/* end globals for default values */
+
typedef struct _instanceData {
uchar f_fname[MAXFNAME];/* file or template name (display only) */
short fd; /* file descriptor for (current) file */
@@ -280,7 +281,6 @@ int resolveFileSizeLimit(instanceData *pData)
*/
if((pCmd = (uchar*)strdup((char*)pData->f_sizeLimitCmd)) == NULL) {
/* there is not much we can do - we make syslogd close the file in this case */
- glblHadMemShortage = 1;
return 1;
}
@@ -480,7 +480,6 @@ static int prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsg
/* we need to allocate memory for the cache structure */
pCache[iFirstFree] = (dynaFileCacheEntry*) calloc(1, sizeof(dynaFileCacheEntry));
if(pCache[iFirstFree] == NULL) {
- glblHadMemShortage = TRUE;
dbgprintf("prepareDynfile(): could not alloc mem, discarding this request\n");
return -1;
}
@@ -775,7 +774,7 @@ CODESTARTparseSelectorAct
pData->fileType = eTypeTTY;
untty();
}
- if (strcmp((char*) p, ctty) == 0)
+ if (strcmp((char*) p, _PATH_CONSOLE) == 0)
pData->fileType = eTypeCONSOLE;
break;
default:
@@ -841,6 +840,5 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(regCfSysLineHdlr((uchar *)"actionfiledefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszTplName, NULL));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
-/*
- * vi:set ai:
+/* vi:set ai:
*/
diff --git a/omfile.h b/tools/omfile.h
index 03e081f3..03e081f3 100644
--- a/omfile.h
+++ b/tools/omfile.h
diff --git a/tools/omfwd.c b/tools/omfwd.c
new file mode 100644
index 00000000..59245536
--- /dev/null
+++ b/tools/omfwd.c
@@ -0,0 +1,639 @@
+/* omfwd.c
+ * This is the implementation of the build-in forwarding output module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" message code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Copyright 2007 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 <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fnmatch.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <unistd.h>
+#ifdef USE_NETZIP
+#include <zlib.h>
+#endif
+#include <pthread.h>
+#include "syslogd.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "net.h"
+#include "netstrms.h"
+#include "netstrm.h"
+#include "omfwd.h"
+#include "template.h"
+#include "msg.h"
+#include "tcpclt.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+
+MODULE_TYPE_OUTPUT
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(net)
+DEFobjCurrIf(netstrms)
+DEFobjCurrIf(netstrm)
+DEFobjCurrIf(tcpclt)
+
+typedef struct _instanceData {
+ netstrms_t *pNS; /* netstream subsystem */
+ netstrm_t *pNetstrm; /* our output netstream */
+ uchar *pszStrmDrvr;
+ int iStrmDrvrMode;
+ char *f_hname;
+ int *pSockArray; /* sockets to use for UDP */
+ int bIsConnected; /* are we connected to remote host? 0 - no, 1 - yes, UDP means addr resolved */
+ struct addrinfo *f_addr;
+ int compressionLevel; /* 0 - no compression, else level for zlib */
+ char *port;
+ int protocol;
+# define FORW_UDP 0
+# define FORW_TCP 1
+ /* following fields for TCP-based delivery */
+ tcpclt_t *pTCPClt; /* our tcpclt object */
+} instanceData;
+
+/* config data */
+static uchar *pszTplName = NULL; /* name of the default template to use */
+static uchar *pszStrmDrvr = NULL; /* name of the stream driver to use */
+static int iStrmDrvrMode = 0; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
+
+
+/* get the syslog forward port from selector_t. The passed in
+ * struct must be one that is setup for forwarding.
+ * rgerhards, 2007-06-28
+ * We may change the implementation to try to lookup the port
+ * if it is unspecified. So far, we use the IANA default auf 514.
+ */
+static char *getFwdPt(instanceData *pData)
+{
+ assert(pData != NULL);
+ if(pData->port == NULL)
+ return("514");
+ else
+ return(pData->port);
+}
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ if(pData->f_addr != NULL) { /* TODO: is the check ok? */
+ freeaddrinfo(pData->f_addr);
+ pData->f_addr = NULL;
+ }
+ if(pData->port != NULL)
+ free(pData->port);
+
+ /* final cleanup */
+ if(pData->pNetstrm != NULL)
+ netstrm.Destruct(&pData->pNetstrm);
+ if(pData->pSockArray != NULL)
+ net.closeUDPListenSockets(pData->pSockArray);
+
+ if(pData->protocol == FORW_TCP) {
+ tcpclt.Destruct(&pData->pTCPClt);
+ }
+
+ if(pData->f_hname != NULL)
+ free(pData->f_hname);
+
+ENDfreeInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ printf("%s", pData->f_hname);
+ENDdbgPrintInstInfo
+
+
+/* Send a message via UDP
+ * rgehards, 2007-12-20
+ */
+static rsRetVal UDPSend(instanceData *pData, char *msg, size_t len)
+{
+ DEFiRet;
+ struct addrinfo *r;
+ int i;
+ unsigned lsent = 0;
+ int bSendSuccess;
+
+ if(pData->pSockArray != NULL) {
+ /* we need to track if we have success sending to the remote
+ * peer. Success is indicated by at least one sendto() call
+ * succeeding. We track this be bSendSuccess. We can not simply
+ * rely on lsent, as a call might initially work, but a later
+ * call fails. Then, lsent has the error status, even though
+ * the sendto() succeeded. -- rgerhards, 2007-06-22
+ */
+ bSendSuccess = FALSE;
+ for (r = pData->f_addr; r; r = r->ai_next) {
+ for (i = 0; i < *pData->pSockArray; i++) {
+ lsent = sendto(pData->pSockArray[i+1], msg, len, 0, r->ai_addr, r->ai_addrlen);
+ if (lsent == len) {
+ bSendSuccess = TRUE;
+ break;
+ } else {
+ int eno = errno;
+ char errStr[1024];
+ dbgprintf("sendto() error: %d = %s.\n",
+ eno, rs_strerror_r(eno, errStr, sizeof(errStr)));
+ }
+ }
+ if (lsent == len && !send_to_all)
+ break;
+ }
+ /* finished looping */
+ if (bSendSuccess == FALSE) {
+ dbgprintf("error forwarding via udp, suspending\n");
+ iRet = RS_RET_SUSPENDED;
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* CODE FOR SENDING TCP MESSAGES */
+
+
+/* Send a frame via plain TCP protocol
+ * rgerhards, 2007-12-28
+ */
+static rsRetVal TCPSendFrame(void *pvData, char *msg, size_t len)
+{
+ DEFiRet;
+ ssize_t lenSend;
+ instanceData *pData = (instanceData *) pvData;
+
+ lenSend = len;
+ CHKiRet(netstrm.Send(pData->pNetstrm, (uchar*)msg, &lenSend));
+ dbgprintf("TCP sent %ld bytes, requested %ld\n", (long) lenSend, (long) len);
+
+ if(lenSend != (ssize_t) len) {
+ /* no real error, could "just" not send everything...
+ * For the time being, we ignore this...
+ * rgerhards, 2005-10-25
+ */
+ dbgprintf("message not completely (tcp)send, ignoring %ld\n", (long) lenSend);
+ usleep(1000); /* experimental - might be benefitial in this situation */
+ /* TODO: we need to revisit this code -- rgerhards, 2007-12-28 */
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function is called immediately before a send retry is attempted.
+ * It shall clean up whatever makes sense.
+ * rgerhards, 2007-12-28
+ */
+static rsRetVal TCPSendPrepRetry(void *pvData)
+{
+ DEFiRet;
+ instanceData *pData = (instanceData *) pvData;
+
+ assert(pData != NULL);
+ netstrm.Destruct(&pData->pNetstrm);
+ RETiRet;
+}
+
+
+/* initializes everything so that TCPSend can work.
+ * rgerhards, 2007-12-28
+ */
+static rsRetVal TCPSendInit(void *pvData)
+{
+ DEFiRet;
+ instanceData *pData = (instanceData *) pvData;
+
+ assert(pData != NULL);
+ if(pData->pNetstrm == NULL) {
+ CHKiRet(netstrms.Construct(&pData->pNS));
+ /* the stream driver must be set before the object is finalized! */
+ CHKiRet(netstrms.SetDrvrName(pData->pNS, pszStrmDrvr));
+ CHKiRet(netstrms.ConstructFinalize(pData->pNS));
+
+ /* now create the actual stream and connect to the server */
+ CHKiRet(netstrms.CreateStrm(pData->pNS, &pData->pNetstrm));
+ CHKiRet(netstrm.ConstructFinalize(pData->pNetstrm));
+ CHKiRet(netstrm.SetDrvrMode(pData->pNetstrm, pData->iStrmDrvrMode));
+ CHKiRet(netstrm.Connect(pData->pNetstrm, glbl.GetDefPFFamily(),
+ (uchar*)pData->port, (uchar*)pData->f_hname));
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pData->pNetstrm != NULL)
+ netstrm.Destruct(&pData->pNetstrm);
+ if(pData->pNS != NULL)
+ netstrms.Destruct(&pData->pNS);
+ }
+
+ RETiRet;
+}
+
+
+/* try to resume connection if it is not ready
+ * rgerhards, 2007-08-02
+ */
+static rsRetVal doTryResume(instanceData *pData)
+{
+ DEFiRet;
+ struct addrinfo *res;
+ struct addrinfo hints;
+
+ if(pData->bIsConnected)
+ FINALIZE;
+
+ /* The remote address is not yet known and needs to be obtained */
+ dbgprintf(" %s\n", pData->f_hname);
+ if(pData->protocol == FORW_UDP) {
+ memset(&hints, 0, sizeof(hints));
+ /* port must be numeric, because config file syntax requires this */
+ hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_family = glbl.GetDefPFFamily();
+ hints.ai_socktype = pData->protocol == SOCK_DGRAM;
+ if((getaddrinfo(pData->f_hname, getFwdPt(pData), &hints, &res)) != 0) {
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ dbgprintf("%s found, resuming.\n", pData->f_hname);
+ pData->f_addr = res;
+ pData->bIsConnected = 1;
+ if(pData->pSockArray == NULL) {
+ pData->pSockArray = net.create_udp_socket((uchar*)pData->f_hname, NULL, 0);
+ }
+ } else {
+ CHKiRet(TCPSendInit((void*)pData));
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pData->f_addr != NULL) {
+ freeaddrinfo(pData->f_addr);
+ pData->f_addr = NULL;
+ }
+ iRet = RS_RET_SUSPENDED;
+ }
+
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ iRet = doTryResume(pData);
+ENDtryResume
+
+BEGINdoAction
+ char *psz; /* temporary buffering */
+ register unsigned l;
+CODESTARTdoAction
+ CHKiRet(doTryResume(pData));
+
+ dbgprintf(" %s:%s/%s\n", pData->f_hname, getFwdPt(pData),
+ pData->protocol == FORW_UDP ? "udp" : "tcp");
+
+ psz = (char*) ppString[0];
+ l = strlen((char*) psz);
+ if (l > MAXLINE)
+ l = MAXLINE;
+
+# ifdef USE_NETZIP
+ /* Check if we should compress and, if so, do it. We also
+ * check if the message is large enough to justify compression.
+ * The smaller the message, the less likely is a gain in compression.
+ * To save CPU cycles, we do not try to compress very small messages.
+ * What "very small" means needs to be configured. Currently, it is
+ * hard-coded but this may be changed to a config parameter.
+ * rgerhards, 2006-11-30
+ */
+ if(pData->compressionLevel && (l > MIN_SIZE_FOR_COMPRESS)) {
+ Bytef out[MAXLINE+MAXLINE/100+12] = "z";
+ uLongf destLen = sizeof(out) / sizeof(Bytef);
+ uLong srcLen = l;
+ int ret;
+ ret = compress2((Bytef*) out+1, &destLen, (Bytef*) psz,
+ srcLen, pData->compressionLevel);
+ dbgprintf("Compressing message, length was %d now %d, return state %d.\n",
+ l, (int) destLen, ret);
+ if(ret != Z_OK) {
+ /* if we fail, we complain, but only in debug mode
+ * Otherwise, we are silent. In any case, we ignore the
+ * failed compression and just sent the uncompressed
+ * data, which is still valid. So this is probably the
+ * best course of action.
+ * rgerhards, 2006-11-30
+ */
+ dbgprintf("Compression failed, sending uncompressed message\n");
+ } else if(destLen+1 < l) {
+ /* only use compression if there is a gain in using it! */
+ dbgprintf("there is gain in compression, so we do it\n");
+ psz = (char*) out;
+ l = destLen + 1; /* take care for the "z" at message start! */
+ }
+ ++destLen;
+ }
+# endif
+
+ if(pData->protocol == FORW_UDP) {
+ /* forward via UDP */
+ CHKiRet(UDPSend(pData, psz, l));
+ } else {
+ /* forward via TCP */
+ rsRetVal ret;
+ ret = tcpclt.Send(pData->pTCPClt, pData, psz, l);
+ if(ret != RS_RET_OK) {
+ /* error! */
+ dbgprintf("error forwarding via tcp, suspending\n");
+ iRet = RS_RET_SUSPENDED;
+ }
+ }
+finalize_it:
+ENDdoAction
+
+
+/* This function loads TCP support, if not already loaded. It will be called
+ * during config processing. To server ressources, TCP support will only
+ * be loaded if it actually is used. -- rgerhard, 2008-04-17
+ */
+static rsRetVal
+loadTCPSupport(void)
+{
+ DEFiRet;
+ CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(tcpclt, LM_TCPCLT_FILENAME));
+
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINparseSelectorAct
+ uchar *q;
+ int i;
+ int bErr;
+ rsRetVal localRet;
+ struct addrinfo;
+ TCPFRAMINGMODE tcp_framing = TCP_FRAMING_OCTET_STUFFING;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ if(*p != '@')
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+
+ CHKiRet(createInstance(&pData));
+
+ ++p; /* eat '@' */
+ if(*p == '@') { /* indicator for TCP! */
+ localRet = loadTCPSupport();
+ if(localRet != RS_RET_OK) {
+ errmsg.LogError(NO_ERRCODE, "could not activate network stream modules for TCP "
+ "(internal error %d) - are modules missing?", localRet);
+ ABORT_FINALIZE(localRet);
+ }
+ pData->protocol = FORW_TCP;
+ ++p; /* eat this '@', too */
+ } else {
+ pData->protocol = FORW_UDP;
+ }
+ /* we are now after the protocol indicator. Now check if we should
+ * use compression. We begin to use a new option format for this:
+ * @(option,option)host:port
+ * The first option defined is "z[0..9]" where the digit indicates
+ * the compression level. If it is not given, 9 (best compression) is
+ * assumed. An example action statement might be:
+ * @@(z5,o)127.0.0.1:1400
+ * Which means send via TCP with medium (5) compresion (z) to the local
+ * host on port 1400. The '0' option means that octet-couting (as in
+ * IETF I-D syslog-transport-tls) is to be used for framing (this option
+ * applies to TCP-based syslog only and is ignored when specified with UDP).
+ * That is not yet implemented.
+ * rgerhards, 2006-12-07
+ */
+ if(*p == '(') {
+ /* at this position, it *must* be an option indicator */
+ do {
+ ++p; /* eat '(' or ',' (depending on when called) */
+ /* check options */
+ if(*p == 'z') { /* compression */
+# ifdef USE_NETZIP
+ ++p; /* eat */
+ if(isdigit((int) *p)) {
+ int iLevel;
+ iLevel = *p - '0';
+ ++p; /* eat */
+ pData->compressionLevel = iLevel;
+ } else {
+ errmsg.LogError(NO_ERRCODE, "Invalid compression level '%c' specified in "
+ "forwardig action - NOT turning on compression.",
+ *p);
+ }
+# else
+ errmsg.LogError(NO_ERRCODE, "Compression requested, but rsyslogd is not compiled "
+ "with compression support - request ignored.");
+# endif /* #ifdef USE_NETZIP */
+ } else if(*p == 'o') { /* octet-couting based TCP framing? */
+ ++p; /* eat */
+ /* no further options settable */
+ tcp_framing = TCP_FRAMING_OCTET_COUNTING;
+ } else { /* invalid option! Just skip it... */
+ errmsg.LogError(NO_ERRCODE, "Invalid option %c in forwarding action - ignoring.", *p);
+ ++p; /* eat invalid option */
+ }
+ /* the option processing is done. We now do a generic skip
+ * to either the next option or the end of the option
+ * block.
+ */
+ while(*p && *p != ')' && *p != ',')
+ ++p; /* just skip it */
+ } while(*p && *p == ','); /* Attention: do.. while() */
+ if(*p == ')')
+ ++p; /* eat terminator, on to next */
+ else
+ /* we probably have end of string - leave it for the rest
+ * of the code to handle it (but warn the user)
+ */
+ errmsg.LogError(NO_ERRCODE, "Option block not terminated in forwarding action.");
+ }
+ /* extract the host first (we do a trick - we replace the ';' or ':' with a '\0')
+ * now skip to port and then template name. rgerhards 2005-07-06
+ */
+ for(q = p ; *p && *p != ';' && *p != ':' ; ++p)
+ /* JUST SKIP */;
+
+ pData->port = NULL;
+ if(*p == ':') { /* process port */
+ uchar * tmp;
+
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ tmp = ++p;
+ for(i=0 ; *p && isdigit((int) *p) ; ++p, ++i)
+ /* SKIP AND COUNT */;
+ pData->port = malloc(i + 1);
+ if(pData->port == NULL) {
+ errmsg.LogError(NO_ERRCODE, "Could not get memory to store syslog forwarding port, "
+ "using default port, results may not be what you intend\n");
+ /* we leave f_forw.port set to NULL, this is then handled by getFwdPt(). */
+ } else {
+ memcpy(pData->port, tmp, i);
+ *(pData->port + i) = '\0';
+ }
+ }
+
+ /* now skip to template */
+ bErr = 0;
+ while(*p && *p != ';') {
+ if(*p && *p != ';' && !isspace((int) *p)) {
+ if(bErr == 0) { /* only 1 error msg! */
+ bErr = 1;
+ errno = 0;
+ errmsg.LogError(NO_ERRCODE, "invalid selector line (port), probably not doing "
+ "what was intended");
+ }
+ }
+ ++p;
+ }
+
+ /* TODO: make this if go away! */
+ if(*p == ';') {
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ CHKmalloc(pData->f_hname = strdup((char*) q));
+ *p = ';';
+ } else {
+ CHKmalloc(pData->f_hname = strdup((char*) q));
+ }
+
+ /* process template */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
+ (pszTplName == NULL) ? (uchar*)"RSYSLOG_TraditionalForwardFormat" : pszTplName));
+
+ if(pData->protocol == FORW_TCP) {
+ /* create our tcpclt */
+ CHKiRet(tcpclt.Construct(&pData->pTCPClt));
+ /* and set callbacks */
+ CHKiRet(tcpclt.SetSendInit(pData->pTCPClt, TCPSendInit));
+ CHKiRet(tcpclt.SetSendFrame(pData->pTCPClt, TCPSendFrame));
+ CHKiRet(tcpclt.SetSendPrepRetry(pData->pTCPClt, TCPSendPrepRetry));
+ CHKiRet(tcpclt.SetFraming(pData->pTCPClt, tcp_framing));
+ pData->iStrmDrvrMode = iStrmDrvrMode;
+ if(pData->pszStrmDrvr != NULL)
+ CHKmalloc(pData->pszStrmDrvr = (uchar*)strdup((char*)pszStrmDrvr));
+ }
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(errmsg, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(netstrm, LM_NETSTRMS_FILENAME);
+ objRelease(netstrms, LM_NETSTRMS_FILENAME);
+ objRelease(tcpclt, LM_TCPCLT_FILENAME);
+
+ if(pszTplName != NULL) {
+ free(pszTplName);
+ pszTplName = NULL;
+ }
+ if(pszStrmDrvr != NULL) {
+ free(pszStrmDrvr);
+ pszStrmDrvr = NULL;
+ }
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+/* Reset config variables for this module to default values.
+ * rgerhards, 2008-03-28
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ if(pszTplName != NULL) {
+ free(pszTplName);
+ pszTplName = NULL;
+ }
+ if(pszStrmDrvr != NULL) {
+ free(pszStrmDrvr);
+ pszStrmDrvr = NULL;
+ }
+ iStrmDrvrMode = 0;
+
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit(Fwd)
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(net,LM_NET_FILENAME));
+
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionforwarddefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszTplName, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriver", 0, eCmdHdlrGetWord, NULL, &pszStrmDrvr, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdrivermode", 0, eCmdHdlrInt, NULL, &iStrmDrvrMode, NULL));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/omfwd.h b/tools/omfwd.h
index dea432e5..dea432e5 100644
--- a/omfwd.h
+++ b/tools/omfwd.h
diff --git a/omshell.c b/tools/omshell.c
index 2176c101..2176c101 100644
--- a/omshell.c
+++ b/tools/omshell.c
diff --git a/omshell.h b/tools/omshell.h
index 3061ad07..3061ad07 100644
--- a/omshell.h
+++ b/tools/omshell.h
diff --git a/omusrmsg.c b/tools/omusrmsg.c
index 42d3291d..42d3291d 100644
--- a/omusrmsg.c
+++ b/tools/omusrmsg.c
diff --git a/omusrmsg.h b/tools/omusrmsg.h
index 52e780f7..52e780f7 100644
--- a/omusrmsg.h
+++ b/tools/omusrmsg.h
diff --git a/pidfile.c b/tools/pidfile.c
index 2be13da6..2be13da6 100644
--- a/pidfile.c
+++ b/tools/pidfile.c
diff --git a/pidfile.h b/tools/pidfile.h
index 40be9069..40be9069 100644
--- a/pidfile.h
+++ b/tools/pidfile.h
diff --git a/rsyslog.conf.5 b/tools/rsyslog.conf.5
index 1c47f535..1c47f535 100644
--- a/rsyslog.conf.5
+++ b/tools/rsyslog.conf.5
diff --git a/rsyslogd.8 b/tools/rsyslogd.8
index 2aa911d9..2aa911d9 100644
--- a/rsyslogd.8
+++ b/tools/rsyslogd.8
diff --git a/syslogd.c b/tools/syslogd.c
index f4ac2080..8b829771 100644
--- a/syslogd.c
+++ b/tools/syslogd.c
@@ -129,6 +129,8 @@
#include <zlib.h>
#endif
+#include <netdb.h>
+
#include "pidfile.h"
#include "srUtils.h"
#include "stringbuf.h"
@@ -140,7 +142,6 @@
#include "msg.h"
#include "modules.h"
#include "action.h"
-#include "tcpsyslog.h"
#include "iminternal.h"
#include "cfsysline.h"
#include "omshell.h"
@@ -151,21 +152,15 @@
#include "threads.h"
#include "queue.h"
#include "stream.h"
-#include "wti.h"
-#include "wtp.h"
-#include "expr.h"
-#include "ctok.h"
#include "conf.h"
-#include "vmop.h"
-#include "vmstk.h"
#include "vm.h"
-#include "vmprg.h"
#include "errmsg.h"
#include "datetime.h"
#include "sysvar.h"
/* definitions for objects we access */
DEFobjCurrIf(obj)
+DEFobjCurrIf(glbl)
DEFobjCurrIf(datetime)
DEFobjCurrIf(conf)
DEFobjCurrIf(expr)
@@ -243,25 +238,17 @@ static rsRetVal GlobalClassExit(void);
# define _PATH_DEV "/dev/"
#endif
-#ifndef _PATH_CONSOLE
-#define _PATH_CONSOLE "/dev/console"
-#endif
-
#ifndef _PATH_TTY
#define _PATH_TTY "/dev/tty"
#endif
static uchar *ConfFile = (uchar*) _PATH_LOGCONF; /* read-only after startup */
static char *PidFile = _PATH_LOGPID; /* read-only after startup */
-char ctty[] = _PATH_CONSOLE; /* this is read-only; used by omfile -- TODO: remove that dependency */
static pid_t myPid; /* our pid for use in self-generated messages, e.g. on startup */
/* mypid is read-only after the initial fork() */
static int restart = 0; /* do restart (config read) - multithread safe */
-int glblHadMemShortage = 0; /* indicates if we had memory shortage some time during the run */
-
-
static int bParseHOSTNAMEandTAG = 1; /* global config var: should the hostname and tag be
* parsed inside message - rgerhards, 2006-03-13 */
static int bFinished = 0; /* used by termination signal handler, read-only except there
@@ -296,25 +283,16 @@ int iCompatibilityMode = 0; /* version we should be compatible with; 0 means sy
static int bDebugPrintTemplateList = 1;/* output template list in debug mode? */
static int bDebugPrintCfSysLineHandlerList = 1;/* output cfsyslinehandler list in debug mode? */
static int bDebugPrintModuleList = 1;/* output module list in debug mode? */
-int bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records during DNS lookup */
static uchar cCCEscapeChar = '\\';/* character to be used to start an escape sequence for control chars */
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 */
-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 */
int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */
static int NoFork = 0; /* don't fork - don't run in daemon mode - read-only after startup */
-int DisableDNS = 0; /* don't look up IP addresses of remote messages */
-char **StripDomains = NULL;/* these domains may be stripped before writing logs - r/o after s.u., never touched by init */
-char **LocalHosts = NULL;/* these hosts are logged with their hostname - read-only after startup, never touched by init */
static int bHaveMainQueue = 0;/* set to 1 if the main queue - in queueing mode - is available
* If the main queue is either not yet ready or not running in
* queueing mode (mode DIRECT!), then this is set to 0.
@@ -386,11 +364,6 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
bDebugPrintModuleList = 1;
bEscapeCCOnRcv = 1; /* default is to escape control characters */
bReduceRepeatMsgs = 0;
- bDropMalPTRMsgs = 0;
- if(pszWorkDir != NULL) {
- free(pszWorkDir);
- pszWorkDir = NULL;
- }
if(pszMainMsgQFName != NULL) {
free(pszMainMsgQFName);
pszMainMsgQFName = NULL;
@@ -418,11 +391,8 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
}
-
-int option_DisallowWarning = 1; /* complain if message from disallowed sender is received */
-
-
/* hardcoded standard templates (used for defaults) */
+static uchar template_DebugFormat[] = "\"Debug line with all properties:\nFROMHOST: '%FROMHOST%', fromhost-ip: '%fromhost-ip%', HOSTNAME: '%HOSTNAME%', PRI: %PRI%,\nsyslogtag '%syslogtag%', programname: '%programname%', APP-NAME: '%APP-NAME%', PROCID: '%PROCID%', MSGID: '%MSGID%',\nTIMESTAMP: '%TIMESTAMP%', STRUCTURED-DATA: '%STRUCTURED-DATA%',\nmsg: '%msg%'\nescaped msg: '%msg:::drop-cc%'\nrawmsg: '%rawmsg%'\n\n\"";
static uchar template_SyslogProtocol23Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n\"";
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\"";
@@ -499,7 +469,6 @@ selectorConstruct(selector_t **ppThis)
assert(ppThis != NULL);
if((pThis = (selector_t*) calloc(1, sizeof(selector_t))) == NULL) {
- glblHadMemShortage = 1;
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
CHKiRet(llInit(&pThis->llActList, actionDestruct, NULL, NULL));
@@ -629,19 +598,22 @@ void untty(void)
* rgerhards, 2008-03-19:
* I added an additional calling parameter to permit specifying the flow
* control capability of the source.
+ *
+ * rgerhards, 2008-05-16:
+ * I added an additional calling parameter (hnameIP) to enable specifying the IP
+ * of a remote host.
*/
-rsRetVal printline(char *hname, char *msg, int bParseHost, int flags, flowControl_t flowCtlType)
+rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int bParseHost, int flags, flowControl_t flowCtlType)
{
DEFiRet;
- register char *p;
+ register uchar *p;
int pri;
msg_t *pMsg;
- /* Now it is time to create the message object (rgerhards)
- */
+ /* Now it is time to create the message object (rgerhards) */
CHKiRet(msgConstruct(&pMsg));
MsgSetFlowControlType(pMsg, flowCtlType);
- MsgSetRawMsg(pMsg, msg);
+ MsgSetRawMsg(pMsg, (char*)msg);
pMsg->bParseHOSTNAME = bParseHost;
/* test for special codes */
@@ -669,18 +641,19 @@ rsRetVal printline(char *hname, char *msg, int bParseHost, int flags, flowContro
* being the local host). rgerhards 2004-11-16
*/
if(bParseHost == 0)
- MsgSetHOSTNAME(pMsg, hname);
- MsgSetRcvFrom(pMsg, hname);
+ MsgSetHOSTNAME(pMsg, (char*)hname);
+ MsgSetRcvFrom(pMsg, (char*)hname);
+ CHKiRet(MsgSetRcvFromIP(pMsg, hnameIP));
/* rgerhards 2004-11-19: well, well... we've now seen that we
* have the "hostname problem" also with the traditional Unix
* message. As we like to emulate it, we need to add the hostname
* to it.
*/
- if(MsgSetUxTradMsg(pMsg, p) != 0)
+ if(MsgSetUxTradMsg(pMsg, (char*)p) != 0)
ABORT_FINALIZE(RS_RET_ERR);
- logmsg(pMsg, flags | SYNC_FILE);
+ logmsg(pMsg, flags);
finalize_it:
RETiRet;
@@ -720,22 +693,27 @@ finalize_it:
* rgerhards, 2008-03-19:
* I added an additional calling parameter to permit specifying the flow
* control capability of the source.
+ *
+ * rgerhards, 2008-05-16:
+ * I added an additional calling parameter (hnameIP) to enable specifying the IP
+ * of a remote host.
*/
rsRetVal
-parseAndSubmitMessage(char *hname, char *msg, int len, int bParseHost, int flags, flowControl_t flowCtlType)
+parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int bParseHost, int flags, flowControl_t flowCtlType)
{
DEFiRet;
register int iMsg;
- char *pMsg;
- char *pData;
- char *pEnd;
- char tmpline[MAXLINE + 1];
+ uchar *pMsg;
+ uchar *pData;
+ uchar *pEnd;
+ uchar tmpline[MAXLINE + 1];
# ifdef USE_NETZIP
- char deflateBuf[MAXLINE + 1];
+ uchar deflateBuf[MAXLINE + 1];
uLongf iLenDefBuf;
# endif
assert(hname != NULL);
+ assert(hnameIP != NULL);
assert(msg != NULL);
assert(len >= 0);
@@ -821,7 +799,7 @@ parseAndSubmitMessage(char *hname, char *msg, int len, int bParseHost, int flags
*/
if(iMsg == MAXLINE) {
*(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
- printline(hname, tmpline, bParseHost, flags, flowCtlType);
+ printline(hname, hnameIP, tmpline, bParseHost, flags, flowCtlType);
} else {
/* This case in theory never can happen. If it happens, we have
* a logic error. I am checking for it, because if I would not,
@@ -873,12 +851,25 @@ parseAndSubmitMessage(char *hname, char *msg, int len, int bParseHost, int flags
*(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
/* typically, we should end up here! */
- printline(hname, tmpline, bParseHost, flags, flowCtlType);
+ printline(hname, hnameIP, tmpline, bParseHost, flags, flowCtlType);
finalize_it:
RETiRet;
}
+
+/* this is a special function used to submit an error message. This
+ * function is also passed to the runtime library as the generic error
+ * message handler. -- rgerhards, 2008-04-17
+ */
+rsRetVal
+submitErrMsg(uchar *msg)
+{
+ DEFiRet;
+ iRet = logmsgInternal(LOG_SYSLOG|LOG_ERR, msg, ADDDATE);
+ RETiRet;
+}
+
/* rgerhards 2004-11-09: the following is a function that can be used
* to log a message orginating from the syslogd itself. In sysklogd code,
* this is done by simply calling logmsg(). However, logmsg() is changed in
@@ -889,16 +880,17 @@ finalize_it:
* think on the best way to do this.
*/
rsRetVal
-logmsgInternal(int pri, char *msg, int flags)
+logmsgInternal(int pri, uchar *msg, int flags)
{
DEFiRet;
msg_t *pMsg;
CHKiRet(msgConstruct(&pMsg));
- MsgSetUxTradMsg(pMsg, msg);
- MsgSetRawMsg(pMsg, msg);
- MsgSetHOSTNAME(pMsg, (char*)LocalHostName);
- MsgSetRcvFrom(pMsg, (char*)LocalHostName);
+ MsgSetUxTradMsg(pMsg, (char*)msg);
+ MsgSetRawMsg(pMsg, (char*)msg);
+ MsgSetHOSTNAME(pMsg, (char*)glbl.GetLocalHostName());
+ MsgSetRcvFrom(pMsg, (char*)glbl.GetLocalHostName());
+ MsgSetRcvFromIP(pMsg, (uchar*)"127.0.0.1");
MsgSetTAG(pMsg, "rsyslogd:");
pMsg->iFacility = LOG_FAC(pri);
pMsg->iSeverity = LOG_PRI(pri);
@@ -1863,14 +1855,10 @@ static void doDie(int sig)
static void
freeAllDynMemForTermination(void)
{
- if(pszWorkDir != NULL)
- free(pszWorkDir);
if(pszMainMsgQFName != NULL)
free(pszMainMsgQFName);
if(pModDir != NULL)
free(pModDir);
- if(LocalHostName != NULL)
- free(LocalHostName);
}
@@ -1912,7 +1900,7 @@ die(int sig)
"\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"]" " exiting on signal %d.",
(int) myPid, sig);
errno = 0;
- logmsgInternal(LOG_SYSLOG|LOG_INFO, buf, ADDDATE);
+ logmsgInternal(LOG_SYSLOG|LOG_INFO, (uchar*)buf, ADDDATE);
}
/* drain queue (if configured so) and stop main queue worker thread pool */
@@ -1936,8 +1924,6 @@ die(int sig)
tplDeleteAll();
remove_pid(PidFile);
- if(glblHadMemShortage)
- dbgprintf("Had memory shortage at least once during the run.\n");
/* de-init some modules */
modExitIminternal();
@@ -2130,10 +2116,10 @@ static void dbgPrintInitInfo(void)
dbgPrintCfSysLineHandlers();
dbgprintf("Messages with malicious PTR DNS Records are %sdropped.\n",
- bDropMalPTRMsgs ? "" : "not ");
+ glbl.GetDropMalPTRMsgs() ? "" : "not ");
dbgprintf("Control characters are %sreplaced upon reception.\n",
- bEscapeCCOnRcv? "" : "not ");
+ bEscapeCCOnRcv? "" : "not ");
if(bEscapeCCOnRcv)
dbgprintf("Control character escape sequence prefix is '%c'.\n",
@@ -2159,7 +2145,7 @@ static void dbgPrintInitInfo(void)
setQPROP(queueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", 100);
setQPROP(queueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", 1);
*/
- dbgprintf("Work Directory: '%s'.\n", pszWorkDir);
+ dbgprintf("Work Directory: '%s'.\n", glbl.GetWorkDir());
}
@@ -2282,7 +2268,7 @@ init(void)
if(MainMsgQueType == QUEUETYPE_DISK) {
errno = 0; /* for logerror! */
- if(pszWorkDir == NULL) {
+ if(glbl.GetWorkDir() == NULL) {
errmsg.LogError(NO_ERRCODE, "No $WorkDirectory specified - can not run main message queue in 'disk' mode. "
"Using 'FixedArray' instead.\n");
MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
@@ -2367,7 +2353,7 @@ init(void)
" [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
"\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] restart",
(int) myPid);
- logmsgInternal(LOG_SYSLOG|LOG_INFO, bufStartUpMsg, ADDDATE);
+ logmsgInternal(LOG_SYSLOG|LOG_INFO, (uchar*)bufStartUpMsg, ADDDATE);
memset(&sigAct, 0, sizeof (sigAct));
sigemptyset(&sigAct.sa_mask);
@@ -2476,51 +2462,6 @@ void sighup_handler()
}
-/**
- * getSubString
- *
- * Copy a string byte by byte until the occurrence
- * of a given separator.
- *
- * \param ppSrc Pointer to a pointer of the source array of characters. If a
- separator detected the Pointer points to the next char after the
- separator. Except if the end of the string is dedected ('\n').
- Then it points to the terminator char.
- * \param pDst Pointer to the destination array of characters. Here the substing
- will be stored.
- * \param DstSize Maximum numbers of characters to store.
- * \param cSep Separator char.
- * \ret int Returns 0 if no error occured.
- *
- * rgerhards, 2008-02-12: some notes are due... I will once again fix this function, this time
- * so that it treats ' ' as a request for whitespace. But in general, the function and its callers
- * should be changed over time, this is not really very good code...
- */
-int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep)
-{
- uchar *pSrc = *ppSrc;
- int iErr = 0; /* 0 = no error, >0 = error */
- while((cSep == ' ' ? !isspace(*pSrc) : *pSrc != cSep) && *pSrc != '\n' && *pSrc != '\0' && DstSize>1) {
- *pDst++ = *(pSrc)++;
- DstSize--;
- }
- /* check if the Dst buffer was to small */
- if ((cSep == ' ' ? !isspace(*pSrc) : *pSrc != cSep) && *pSrc != '\n' && *pSrc != '\0') {
- dbgprintf("in getSubString, error Src buffer > Dst buffer\n");
- iErr = 1;
- }
- if (*pSrc == '\0' || *pSrc == '\n')
- /* this line was missing, causing ppSrc to be invalid when it
- * was returned in case of end-of-string. rgerhards 2005-07-29
- */
- *ppSrc = pSrc;
- else
- *ppSrc = pSrc+1;
- *pDst = '\0';
- return iErr;
-}
-
-
/* this function pulls all internal messages from the buffer
* and puts them into the processing engine.
* We can only do limited error handling, as this would not
@@ -2679,7 +2620,7 @@ static rsRetVal loadBuildInModules(void)
* is that rsyslog will terminate if we can not register our built-in config commands.
* This, I think, is the right thing to do. -- rgerhards, 2007-07-31
*/
- CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, NULL, &pszWorkDir, NULL));
+// CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, NULL, &pszWorkDir, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeretrycount", 0, eCmdHdlrInt, NULL, &glbliActionResumeRetryCount, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuefilename", 0, eCmdHdlrGetWord, NULL, &pszMainMsgQFName, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesize", 0, eCmdHdlrInt, NULL, &iMainMsgQueueSize, NULL));
@@ -2707,7 +2648,6 @@ static rsRetVal loadBuildInModules(void)
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));
- CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, NULL, &bDropMalPTRMsgs, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary, NULL, &bDropTrailingLF, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"template", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_TEMPLATE, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"outchannel", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_OUTCHANNEL, NULL));
@@ -2786,6 +2726,8 @@ static void mainThread()
*/
/* initialize the build-in templates */
+ pTmp = template_DebugFormat;
+ tplAddLine("RSYSLOG_DebugFormat", &pTmp);
pTmp = template_SyslogProtocol23Format;
tplAddLine("RSYSLOG_SyslogProtocol23Format", &pTmp);
pTmp = template_FileFormat; /* new format for files with high-precision stamp */
@@ -2828,8 +2770,9 @@ static void mainThread()
}
-/* Method to initialize all global classes.
+/* Method to initialize all global classes and use the objects that we need.
* rgerhards, 2008-01-04
+ * rgerhards, 2008-04-16: the actual initialization is now carried out by the runtime
*/
static rsRetVal
InitGlobalClasses(void)
@@ -2837,67 +2780,34 @@ 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() */
+ /* Intialize the runtime system */
+ pErrObj = "rsyslog runtime"; /* set in case the runtime errors before setting an object */
+ CHKiRet(rsrtInit(&pErrObj, &obj));
+ CHKiRet(rsrtSetErrLogger(submitErrMsg)); /* set out error handler */
+
+ /* Now tell the system which classes we need ourselfs */
+ pErrObj = "glbl";
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
pErrObj = "errmsg";
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
- * up with an invalid call. The most important thing that can happen is that an error
- * is detected and needs to be logged, wich in turn requires a broader number of classes
- * to be available. The solution is that we take care in the order of calls AND use a
- * 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" */
+ /* intialize some dummy classes that are not part of the runtime */
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";
@@ -2937,7 +2847,6 @@ GlobalClassExit(void)
objRelease(datetime, CORE_COMPONENT);
/* TODO: implement the rest of the deinit */
- confClassExit();
#if 0
CHKiRet(datetimeClassInit(NULL));
CHKiRet(msgClassInit(NULL));
@@ -2967,7 +2876,7 @@ GlobalClassExit(void)
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(module, CORE_COMPONENT));
#endif
- objClassExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */
+ rsrtExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */
RETiRet;
}
@@ -3048,18 +2957,19 @@ int realMain(int argc, char **argv)
DEFiRet;
register int i;
- register char *p;
+ register uchar *p;
int num_fds;
int ch;
struct hostent *hent;
extern int optind;
extern char *optarg;
struct sigaction sigAct;
- int bIsFirstOption = 1;
int bEOptionWasGiven = 0;
int bImUxSockLoaded = 0; /* already generated a $ModLoad imuxsock? */
char *arg; /* for command line option processing */
uchar legacyConfLine[80];
+ uchar *LocalHostName;
+ uchar *LocalDomain;
/* 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
@@ -3098,11 +3008,6 @@ int realMain(int argc, char **argv)
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! */
@@ -3143,7 +3048,6 @@ int realMain(int argc, char **argv)
default:
usage();
}
- bIsFirstOption = 0; /* we already saw an option character */
}
if ((argc -= optind))
@@ -3173,11 +3077,11 @@ int realMain(int argc, char **argv)
* error log messages, which need the correct hostname. -- rgerhards, 2008-04-04
*/
net.getLocalHostname(&LocalHostName);
- if((p = strchr((char*)LocalHostName, '.'))) {
+ if((p = (uchar*)strchr((char*)LocalHostName, '.'))) {
*p++ = '\0';
LocalDomain = p;
} else {
- LocalDomain = "";
+ LocalDomain = (uchar*)"";
/* It's not clearly defined whether gethostname()
* should return the simple hostname or the fqdn. A
@@ -3197,7 +3101,7 @@ int realMain(int argc, char **argv)
free(LocalHostName);
CHKmalloc(LocalHostName = (uchar*)strdup(hent->h_name));
- if((p = strchr((char*)LocalHostName, '.')))
+ if((p = (uchar*)strchr((char*)LocalHostName, '.')))
{
*p++ = '\0';
LocalDomain = p;
@@ -3206,8 +3110,15 @@ int realMain(int argc, char **argv)
}
/* Convert to lower case to recognize the correct domain laterly */
- for (p = (char *)LocalDomain ; *p ; p++)
+ for(p = LocalDomain ; *p ; p++)
*p = (char)tolower((int)*p);
+
+ /* we now have our hostname and can set it inside the global vars.
+ * TODO: think if all of this would better be a runtime function
+ * rgerhards, 2008-04-17
+ */
+ glbl.SetLocalHostName(LocalHostName);
+ glbl.SetLocalDomain(LocalDomain);
/* initialize the objects */
if((iRet = modInitIminternal()) != RS_RET_OK) {
@@ -3228,10 +3139,10 @@ int realMain(int argc, char **argv)
dbgprintf("deque option %c, optarg '%s'\n", ch, arg);
switch((char)ch) {
case '4':
- family = PF_INET;
+ glbl.SetDefPFFamily(PF_INET);
break;
case '6':
- family = PF_INET6;
+ glbl.SetDefPFFamily(PF_INET6);
break;
case 'A':
send_to_all++;
@@ -3268,10 +3179,10 @@ int realMain(int argc, char **argv)
PidFile = arg;
break;
case 'l':
- if (LocalHosts) {
+ if(glbl.GetLocalHosts() != NULL) {
fprintf (stderr, "rsyslogd: Only one -l argument allowed, the first one is taken.\n");
} else {
- LocalHosts = crunch_list(arg);
+ glbl.SetLocalHosts(crunch_list(arg));
}
break;
case 'm': /* mark interval */
@@ -3321,10 +3232,10 @@ int realMain(int argc, char **argv)
fprintf(stderr, "-r option only supported in compatibility modes 0 to 2 - ignored\n");
break;
case 's':
- if (StripDomains) {
+ if(glbl.GetStripDomains() != NULL) {
fprintf (stderr, "rsyslogd: Only one -s argument allowed, the first one is taken.\n");
} else {
- StripDomains = crunch_list(arg);
+ glbl.SetStripDomains(crunch_list(arg));
}
break;
case 't': /* enable tcp logging */
@@ -3338,10 +3249,10 @@ int realMain(int argc, char **argv)
bParseHOSTNAMEandTAG = 0;
break;
case 'w': /* disable disallowed host warnigs */
- option_DisallowWarning = 0;
+ glbl.SetOption_DisallowWarning(0);
break;
case 'x': /* disable dns for remote messages */
- DisableDNS = 1;
+ glbl.SetDisableDNS(1);
break;
case '?':
default:
diff --git a/syslogd.h b/tools/syslogd.h
index 46de8d28..e866a16b 100644
--- a/syslogd.h
+++ b/tools/syslogd.h
@@ -29,44 +29,11 @@
#include "linkedlist.h"
#include "expr.h"
-/* portability: not all platforms have these defines, so we
- * define them here if they are missing. -- rgerhards, 2008-03-04
- */
-#ifndef LOG_MAKEPRI
-# define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
-#endif
-#ifndef LOG_PRI
-# define LOG_PRI(p) ((p) & LOG_PRIMASK)
-#endif
-#ifndef LOG_FAC
-# define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)
-#endif
-
-#ifdef USE_NETZIP
-/* config param: minimum message size to try compression. The smaller
- * the message, the less likely is any compression gain. We check for
- * gain before we submit the message. But to do so we still need to
- * do the (costly) compress() call. The following setting sets a size
- * for which no call to compress() is done at all. This may result in
- * a few more bytes being transmited but better overall performance.
- * Note: I have not yet checked the minimum UDP packet size. It might be
- * that we do not save anything by compressing very small messages, because
- * UDP might need to pad ;)
- * rgerhards, 2006-11-30
- */
-#define MIN_SIZE_FOR_COMPRESS 60
+#ifndef _PATH_CONSOLE
+#define _PATH_CONSOLE "/dev/console"
#endif
-#define MAXLINE 2048 /* maximum line length */
-
-/* Flags to logmsg().
- */
-#define NOFLAG 0x000 /* no flag is set (to be used when a flag must be specified and none is required) */
-#define INTERNAL_MSG 0x001 /* msg generated by logmsgInternal() --> special handling */
-#define SYNC_FILE 0x002 /* do fsync on file after printing */
-#define ADDDATE 0x004 /* add a date to the message */
-#define MARK 0x008 /* this message is a mark */
/* This structure represents the files that will have log
* copies printed.
@@ -113,54 +80,20 @@ struct filed {
linkedList_t llActList; /* list of configured actions */
};
-typedef struct filed selector_t; /* new type name */
-#define MSG_PARSE_HOSTNAME 1
-#define MSG_DONT_PARSE_HOSTNAME 0
-rsRetVal parseAndSubmitMessage(char *hname, char *msg, int len, int bParseHost, int flags, flowControl_t flowCtlType);
#include "net.h" /* TODO: remove when you remoe isAllowedSender from here! */
void untty(void);
rsRetVal selectorConstruct(selector_t **ppThis);
-rsRetVal cflineParseTemplateName(uchar** pp, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *dfltTplName);
-rsRetVal cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *pszTpl);
-int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep);
rsRetVal selectorDestruct(void *pVal);
rsRetVal selectorAddList(selector_t *f);
/* the following prototypes should go away once we have an input
* module interface -- rgerhards, 2007-12-12
*/
-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 uchar *LocalHostName;
-extern int family;
extern int NoHops;
extern int send_to_all;
-extern int option_DisallowWarning;
extern int Debug;
-extern char**LocalHosts;
-extern int DisableDNS;
-extern char **StripDomains;
-extern char *LocalDomain;
-extern int bDropMalPTRMsgs;
-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,
- * we move to the next interval until we reach the largest.
- * TODO: move this to action object!
- */
-extern int repeatinterval[2];
-#define MAXREPEAT ((int)((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1))
-#define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
-#define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \
- (f)->f_repeatcount = MAXREPEAT; \
- }
+#include "dirty.h"
#endif /* #ifndef SYSLOGD_H_INCLUDED */