diff options
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | Makefile.am | 150 | ||||
-rw-r--r-- | action.c | 2 | ||||
-rw-r--r-- | ca.pem | 14 | ||||
-rw-r--r-- | conf.c | 9 | ||||
-rw-r--r-- | configure.ac | 124 | ||||
-rw-r--r-- | dirty.h | 81 | ||||
-rw-r--r-- | doc/features.html | 6 | ||||
-rw-r--r-- | doc/im3195.html | 46 | ||||
-rw-r--r-- | doc/rsyslog_conf.html | 4 | ||||
-rw-r--r-- | doc/rsyslog_ng_comparison.html | 4 | ||||
-rw-r--r-- | doc/src/queueWorkerLogic.dia (renamed from doc/queueWorkerLogic.dia) | bin | 3334 -> 3334 bytes | |||
-rw-r--r-- | doc/src/tls.dia | bin | 0 -> 4656 bytes | |||
-rw-r--r-- | doc/status.html | 13 | ||||
-rw-r--r-- | glbl.h | 40 | ||||
-rw-r--r-- | gss-misc.c | 4 | ||||
-rw-r--r-- | liblogging-stub.h | 26 | ||||
-rw-r--r-- | omfwd.c | 644 | ||||
-rw-r--r-- | outchannel.c | 2 | ||||
-rw-r--r-- | parse.c | 2 | ||||
-rw-r--r-- | parse.h | 19 | ||||
-rw-r--r-- | plugins/im3195/Makefile.am | 8 | ||||
-rw-r--r-- | plugins/im3195/im3195.c | 166 | ||||
-rw-r--r-- | plugins/imfile/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/imfile/imfile.c | 12 | ||||
-rw-r--r-- | plugins/imgssapi/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/imgssapi/imgssapi.c | 2 | ||||
-rw-r--r-- | plugins/imklog/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/imklog/imklog.c | 10 | ||||
-rw-r--r-- | plugins/imklog/imklog.h | 2 | ||||
-rw-r--r-- | plugins/imklog/linux.c | 11 | ||||
-rw-r--r-- | plugins/immark/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/immark/immark.c | 4 | ||||
-rw-r--r-- | plugins/imrelp/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/imrelp/imrelp.c | 2 | ||||
-rw-r--r-- | plugins/imtcp/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/imtcp/imtcp.c | 14 | ||||
-rw-r--r-- | plugins/imudp/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/imudp/imudp.c | 8 | ||||
-rw-r--r-- | plugins/imuxsock/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/imuxsock/imuxsock.c | 18 | ||||
-rw-r--r-- | plugins/omgssapi/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/omgssapi/omgssapi.c | 35 | ||||
-rw-r--r-- | plugins/omlibdbi/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/omlibdbi/omlibdbi.c | 2 | ||||
-rw-r--r-- | plugins/ommail/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/ommail/ommail.c | 8 | ||||
-rw-r--r-- | plugins/ommysql/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/ommysql/ommysql.c | 2 | ||||
-rw-r--r-- | plugins/ompgsql/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/ompgsql/ompgsql.c | 2 | ||||
-rw-r--r-- | plugins/omrelp/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/omrelp/omrelp.c | 8 | ||||
-rw-r--r-- | plugins/omsnmp/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/omsnmp/omsnmp.c | 2 | ||||
-rw-r--r-- | plugins/omtesting/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/omtesting/omtesting.c | 2 | ||||
-rw-r--r-- | rfc3195d.8 | 84 | ||||
-rw-r--r-- | rfc3195d.c | 289 | ||||
-rw-r--r-- | runtime/Makefile.am | 145 | ||||
-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) | 15 | ||||
-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.c | 205 | ||||
-rw-r--r-- | runtime/glbl.h | 59 | ||||
-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) | 16 | ||||
-rw-r--r-- | runtime/modules.h (renamed from modules.h) | 18 | ||||
-rw-r--r-- | runtime/msg.c (renamed from msg.c) | 29 | ||||
-rw-r--r-- | runtime/msg.h (renamed from msg.h) | 16 | ||||
-rw-r--r-- | runtime/net.c (renamed from net.c) | 68 | ||||
-rw-r--r-- | runtime/net.h (renamed from net.h) | 26 | ||||
-rw-r--r-- | runtime/netstrm.c | 305 | ||||
-rw-r--r-- | runtime/netstrm.h | 61 | ||||
-rw-r--r-- | runtime/netstrms.c | 200 | ||||
-rw-r--r-- | runtime/netstrms.h | 52 | ||||
-rw-r--r-- | runtime/nsd.h | 72 | ||||
-rw-r--r-- | runtime/nsd_gtls.c | 444 | ||||
-rw-r--r-- | runtime/nsd_gtls.h | 49 | ||||
-rw-r--r-- | runtime/nsd_ptcp.c | 675 | ||||
-rw-r--r-- | runtime/nsd_ptcp.h | 47 | ||||
-rw-r--r-- | runtime/nsdsel_gtls.c | 184 | ||||
-rw-r--r-- | runtime/nsdsel_gtls.h | 45 | ||||
-rw-r--r-- | runtime/nsdsel_ptcp.c | 222 | ||||
-rw-r--r-- | runtime/nsdsel_ptcp.h | 47 | ||||
-rw-r--r-- | runtime/nssel.c | 229 | ||||
-rw-r--r-- | runtime/nssel.h | 55 | ||||
-rw-r--r-- | runtime/obj-types.h (renamed from obj-types.h) | 59 | ||||
-rw-r--r-- | runtime/obj.c (renamed from obj.c) | 26 | ||||
-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.c | 237 | ||||
-rw-r--r-- | runtime/rsyslog.h (renamed from rsyslog.h) | 97 | ||||
-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.c | 4 | ||||
-rw-r--r-- | tcpclt.h | 1 | ||||
-rw-r--r-- | tcps_sess.c | 47 | ||||
-rw-r--r-- | tcps_sess.h | 14 | ||||
-rw-r--r-- | tcpsrv.c | 421 | ||||
-rw-r--r-- | tcpsrv.h | 20 | ||||
-rw-r--r-- | tcpsyslog.c | 55 | ||||
-rw-r--r-- | tcpsyslog.h | 38 | ||||
-rw-r--r-- | template.c | 2 | ||||
-rw-r--r-- | threads.c | 2 | ||||
-rw-r--r-- | threads.h | 5 | ||||
-rw-r--r-- | tools/Makefile.am | 42 | ||||
-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) | 5 | ||||
-rw-r--r-- | tools/omfile.h (renamed from omfile.h) | 0 | ||||
-rw-r--r-- | tools/omfwd.c | 625 | ||||
-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) | 228 | ||||
-rw-r--r-- | tools/syslogd.h (renamed from syslogd.h) | 73 |
167 files changed, 5237 insertions, 2363 deletions
@@ -1,3 +1,18 @@ +--------------------------------------------------------------------------- +Version 3.19.0 (rgerhards), 2008-04-?? +- begins new devel branch version +- partly rewritten and improved omfwd among others, now loads TCP + code only if this is actually necessary +- implemented im3195, the RFC3195 input as a plugin +- 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 +- 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-04-?? - this version is the new beta - merged in imklog bug fix from v3-stable (3.16.1) diff --git a/Makefile.am b/Makefile.am index 0e75710c..a3e67bc8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,125 +1,10 @@ -#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,8 +14,8 @@ lmtcpsrv_la_SOURCES = \ tcps_sess.h \ tcpsrv.c \ tcpsrv.h -lmtcpsrv_la_CPPFLAGS = $(pthreads_cflags) -lmtcpsrv_la_LDFLAGS = -module -avoid-version +lmtcpsrv_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) +lmtcpsrv_la_LDFLAGS = -module -avoid-version $(rsrt_libs) lmtcpsrv_la_LIBADD = # @@ -139,31 +24,20 @@ lmtcpsrv_la_LIBADD = lmtcpclt_la_SOURCES = \ tcpclt.c \ tcpclt.h -lmtcpclt_la_CPPFLAGS = $(pthreads_cflags) -lmtcpclt_la_LDFLAGS = -module -avoid-version +lmtcpclt_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) +lmtcpclt_la_LDFLAGS = -module -avoid-version $(rsrt_libs) 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_LDFLAGS = -module -avoid-version +lmgssutil_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) +lmgssutil_la_LDFLAGS = -module -avoid-version $(rsrt_libs) lmgssutil_la_LIBADD = $(gss_libs) endif @@ -179,10 +53,14 @@ EXTRA_DIST = \ COPYING.LESSER \ $(man_MANS) -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 +100,7 @@ endif if ENABLE_MAIL SUBDIRS += plugins/ommail endif + +if ENABLE_RFC3195 +SUBDIRS += plugins/im3195 +endif @@ -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" @@ -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----- @@ -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 */ @@ -500,7 +505,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; } @@ -563,6 +567,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..d436cec8 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.0],[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=yes@:>@])], + [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/dirty.h b/dirty.h new file mode 100644 index 00000000..fe188acd --- /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(char *hname, char *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/features.html b/doc/features.html index 13fc34c6..f9d17818 100644 --- a/doc/features.html +++ b/doc/features.html @@ -101,10 +101,8 @@ 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 @@ -124,4 +122,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: im3195</b></p> +<p><b>Author: </b>Rainer Gerhards +<rgerhards@adiscon.com></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 <port></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 © 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/rsyslog_conf.html b/doc/rsyslog_conf.html index 9325f73c..4dcef903 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 @@ -1190,4 +1192,4 @@ additional and database support). For obvious reasons, the syntax for defining such features is available in rsyslogd, only.<br> </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..0d57a374 100644 --- a/doc/rsyslog_ng_comparison.html +++ b/doc/rsyslog_ng_comparison.html @@ -57,7 +57,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> @@ -580,4 +580,4 @@ the mean time, you may want to read it in parallel. It is available at 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 +</body></html> diff --git a/doc/queueWorkerLogic.dia b/doc/src/queueWorkerLogic.dia Binary files differindex 068ea50c..068ea50c 100644 --- a/doc/queueWorkerLogic.dia +++ b/doc/src/queueWorkerLogic.dia diff --git a/doc/src/tls.dia b/doc/src/tls.dia Binary files differnew file mode 100644 index 00000000..77e5d185 --- /dev/null +++ b/doc/src/tls.dia diff --git a/doc/status.html b/doc/status.html index 63a3f588..3ff8a625 100644 --- a/doc/status.html +++ b/doc/status.html @@ -2,19 +2,20 @@ <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-04-24.</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> -<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/Article213.phtml">change log</a> - +<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-98.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.0 - <a href="http://www.rsyslog.com/Article215.phtml">change log</a> - +<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-99.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 */ @@ -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 */ @@ -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. @@ -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..57c8ab8b --- /dev/null +++ b/plugins/im3195/Makefile.am @@ -0,0 +1,8 @@ +pkglib_LTLIBRARIES = im3195.la + +im3195_la_SOURCES = im3195.c im3195.h +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..76d54e40 --- /dev/null +++ b/plugins/im3195/im3195.c @@ -0,0 +1,166 @@ +/** + * 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 */ + + srSLMGGetRawMSG(pSLMG, &pszRawMsg); + + parseAndSubmitMessage((char*)fromHost, (char*) 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..c9ac45d1 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" 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..e5888620 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,7 @@ 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); + MsgSetHOSTNAME(pMsg, (char*)glbl.GetLocalHostName()); MsgSetTAG(pMsg, (char*)pszTag); pMsg->iFacility = LOG_FAC(iFacility); pMsg->iSeverity = LOG_PRI(iSeverity); @@ -225,6 +227,7 @@ ENDafterRun BEGINmodExit CODESTARTmodExit /* release objects we used */ + objRelease(glbl, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDmodExit @@ -251,6 +254,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..6c969261 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" 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..1e599d14 100644 --- a/plugins/imtcp/imtcp.c +++ b/plugins/imtcp/imtcp.c @@ -39,10 +39,11 @@ #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 "tcpsrv.h" MODULE_TYPE_INPUT @@ -52,6 +53,7 @@ DEF_IMOD_STATIC_DATA DEFobjCurrIf(tcpsrv) DEFobjCurrIf(tcps_sess) DEFobjCurrIf(net) +DEFobjCurrIf(netstrm) /* Module static data */ static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change for multiple instances */ @@ -70,7 +72,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 +83,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; } @@ -172,6 +176,7 @@ CODESTARTmodExit /* release objects we used */ objRelease(net, LM_NET_FILENAME); + objRelease(netstrm, LM_NETSTRM_FILENAME); objRelease(tcps_sess, LM_TCPSRV_FILENAME); objRelease(tcpsrv, LM_TCPSRV_FILENAME); ENDmodExit @@ -199,6 +204,7 @@ CODEmodInit_QueryRegCFSLineHdlr pOurTcpsrv = NULL; /* request objects we use */ CHKiRet(objUse(net, LM_NET_FILENAME)); + CHKiRet(objUse(netstrm, LM_NETSTRM_FILENAME)); CHKiRet(objUse(tcps_sess, LM_TCPSRV_FILENAME)); CHKiRet(objUse(tcpsrv, LM_TCPSRV_FILENAME)); 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..e0f9f1d3 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 @@ -195,7 +197,7 @@ CODESTARTrunInput 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 +255,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 +284,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..94f97eb5 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; @@ -181,7 +181,7 @@ static rsRetVal readSocket(int fd, int bParseHost, int flags) iRcvd = recv(fd, line, MAXLINE - 1, 0); dbgprintf("Message from UNIX socket: #%d\n", fd); if (iRcvd > 0) { - parseAndSubmitMessage((char*)LocalHostName, line, iRcvd, bParseHost, flags, eFLOWCTL_LIGHT_DELAY); + parseAndSubmitMessage((char*)glbl.GetLocalHostName(), 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 +289,8 @@ ENDafterRun BEGINmodExit CODESTARTmodExit + objRelease(glbl, CORE_COMPONENT); + objRelease(errmsg, CORE_COMPONENT); ENDmodExit @@ -319,6 +321,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 +349,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 8c6a2006..6d419de0 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 161ec073..21165f9b 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/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 f79ec949..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.h" -#include "srAPI.h" -#include "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..dcb475d8 --- /dev/null +++ b/runtime/Makefile.am @@ -0,0 +1,145 @@ +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 lmnetstrm.la lmnssel.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 +lmnetstrms_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) +lmnetstrms_la_LDFLAGS = -module -avoid-version +lmnetstrms_la_LIBADD = + +# individual network streams +lmnetstrm_la_SOURCES = netstrm.c netstrm.h +lmnetstrm_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) +lmnetstrm_la_LDFLAGS = -module -avoid-version +lmnetstrm_la_LIBADD = + +# network stream select support (a helper class) +lmnssel_la_SOURCES = nssel.c nssel.h +lmnssel_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) +lmnssel_la_LDFLAGS = -module -avoid-version +lmnssel_la_LIBADD = + +# netstream drivers + +# plain tcp driver - main driver +pkglib_LTLIBRARIES += lmnsd_ptcp.la +lmnsd_ptcp_la_SOURCES = nsd_ptcp.c nsd_ptcp.h +lmnsd_ptcp_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) +lmnsd_ptcp_la_LDFLAGS = -module -avoid-version +lmnsd_ptcp_la_LIBADD = + +# select interface for ptcp driver +pkglib_LTLIBRARIES += lmnsdsel_ptcp.la +lmnsdsel_ptcp_la_SOURCES = nsdsel_ptcp.c nsdsel_ptcp.h +lmnsdsel_ptcp_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) +lmnsdsel_ptcp_la_LDFLAGS = -module -avoid-version +lmnsdsel_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 +lmnsd_gtls_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) $(gnutls_cflags) +lmnsd_gtls_la_LDFLAGS = -module -avoid-version +lmnsd_gtls_la_LIBADD = $(gnutls_libs) +# +# select interface for gtls driver +pkglib_LTLIBRARIES += lmnsdsel_gtls.la +lmnsdsel_gtls_la_SOURCES = nsdsel_gtls.c nsdsel_gtls.h +lmnsdsel_gtls_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) +lmnsdsel_gtls_la_LDFLAGS = -module -avoid-version +lmnsdsel_gtls_la_LIBADD = +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 1aebc354..0043ce5c 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_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..53624e38 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> 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/runtime/glbl.c b/runtime/glbl.c new file mode 100644 index 00000000..787b6ab7 --- /dev/null +++ b/runtime/glbl.c @@ -0,0 +1,205 @@ +/* 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 +// TESTING ONLY# define DFLT_NETSTRM_DRVR ((uchar*)"lmnsd_ptcp") +#warning "define must be restored for non-testing!" +# define DFLT_NETSTRM_DRVR ((uchar*)"lmnsd_gtls") +#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 */ + + +/* 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 + +#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 : pszWorkDir); +} + + +/* 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) +#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(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 *)"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(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..b6864f3d --- /dev/null +++ b/runtime/glbl.h @@ -0,0 +1,59 @@ +/* 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*) +#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..c156fef2 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" 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. @@ -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" @@ -684,7 +684,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 +695,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 +706,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 +717,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 +728,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 +749,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 +760,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 +771,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 +782,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 +793,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 ""; } @@ -1498,7 +1488,6 @@ static uchar *getNOW(eNOWType eNow) struct syslogTime t; if((pBuf = (uchar*) malloc(sizeof(uchar) * tmpBUFSIZE)) == NULL) { - glblHadMemShortage = 1; return NULL; } @@ -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... */ @@ -106,7 +107,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 */ @@ -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); @@ -651,7 +655,7 @@ gethname(struct sockaddr_storage *f, uchar *pszHostFQDN) ABORT_FINALIZE(RS_RET_INVALID_SOURCE); } - if (!DisableDNS) { + if(!glbl.GetDisableDNS()) { sigemptyset(&nmask); sigaddset(&nmask, SIGHUP); pthread_sigmask(SIG_BLOCK, &nmask, &omask); @@ -662,7 +666,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 +683,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,7 +711,7 @@ 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); ABORT_FINALIZE(RS_RET_ADDRESS_UNKNOWN); @@ -792,9 +795,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 +812,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 +838,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 +929,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 +1102,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 +1114,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) @@ -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 @@ -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..be754aae --- /dev/null +++ b/runtime/netstrm.c @@ -0,0 +1,305 @@ +/* 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 "nsd.h" +#include "netstrms.h" +#include "netstrm.h" + +MODULE_TYPE_LIB + +/* 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(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; +} + + +/* 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; +} + + +/* 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; +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, LM_NETSTRMS_FILENAME); +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)); + CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME)); + + /* set our own handlers */ +ENDObjClassInit(netstrm) + + +/* --------------- here now comes the plumbing that makes as a library module --------------- */ + + +BEGINmodExit +CODESTARTmodExit + netstrmClassExit(); +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)); /* must be done after tcps_sess, as we use it */ +ENDmodInit +/* vi:set ai: + */ diff --git a/runtime/netstrm.h b/runtime/netstrm.h new file mode 100644 index 00000000..160bbb0b --- /dev/null +++ b/runtime/netstrm.h @@ -0,0 +1,61 @@ +/* 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 "nsd.h" /* we need our driver interface to be defined */ + +/* 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); +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 "lmnetstrm" + +#endif /* #ifndef INCLUDED_NETSTRM_H */ diff --git a/runtime/netstrms.c b/runtime/netstrms.c new file mode 100644 index 00000000..661234e4 --- /dev/null +++ b/runtime/netstrms.c @@ -0,0 +1,200 @@ +/* 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 <stdlib.h> +#include <assert.h> +#include <errno.h> + +#include "rsyslog.h" +#include "module-template.h" +#include "obj.h" +//#include "errmsg.h" +//#include "net.h" +#include "nsd.h" +#include "netstrm.h" +#include "netstrms.h" + +MODULE_TYPE_LIB + +/* static data */ +DEFobjStaticHelpers +//DEFobjCurrIf(errmsg) +DEFobjCurrIf(glbl) +DEFobjCurrIf(netstrm) +//DEFobjCurrIf(net) + + +/* 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. + * rgerhards, 2008-04-18 + */ +static rsRetVal +loadDrvr(netstrms_t *pThis) +{ + uchar *pDrvrName; + DEFiRet; + + pDrvrName = pThis->pDrvrName; + if(pDrvrName == NULL) /* if no drvr name is set, use system default */ + pDrvrName = glbl.GetDfltNetstrmDrvr(); + + 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__, pDrvrName+2, pDrvrName, (void*) &pThis->Drvr)); +finalize_it: + 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) + if(pThis->pDrvrName != NULL) + free(pThis->pDrvrName); +ENDobjDestruct(netstrms) + + +/* ConstructionFinalizer */ +static rsRetVal +netstrmsConstructFinalize(netstrms_t *pThis) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrms); + CHKiRet(loadDrvr(pThis)); +finalize_it: + RETiRet; +} + + +/* 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, LM_NETSTRM_FILENAME)); + 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; +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(net, CORE_COMPONENT); + objRelease(glbl, CORE_COMPONENT); + objRelease(netstrm, LM_NETSTRM_FILENAME); +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)); + //CHKiRet(objUse(net, CORE_COMPONENT)); + + /* set our own handlers */ +ENDObjClassInit(netstrms) + + +/* --------------- here now comes the plumbing that makes as a library module --------------- */ + + +BEGINmodExit +CODESTARTmodExit + netstrmsClassExit(); +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(netstrmsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ +ENDmodInit +/* vi:set ai: + */ diff --git a/runtime/netstrms.h b/runtime/netstrms.h new file mode 100644 index 00000000..1e920304 --- /dev/null +++ b/runtime/netstrms.h @@ -0,0 +1,52 @@ +/* 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 *pDrvrName; /**< nsd driver name to use, or NULL if system default */ + 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); +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..1b3702a0 --- /dev/null +++ b/runtime/nsd.h @@ -0,0 +1,72 @@ +/* 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 (*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..d59043f2 --- /dev/null +++ b/runtime/nsd_gtls.c @@ -0,0 +1,444 @@ +/* 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 <stdlib.h> +#include <assert.h> +#include <gnutls/gnutls.h> + +#include "rsyslog.h" +#include "syslogd-types.h" +#include "module-template.h" +#include "obj.h" +#include "errmsg.h" +#include "nsd_ptcp.h" +#include "nsd_gtls.h" + +MODULE_TYPE_LIB + +/* static data */ +DEFobjStaticHelpers +DEFobjCurrIf(errmsg) +DEFobjCurrIf(glbl) +DEFobjCurrIf(nsd_ptcp) + + +/* a macro to check GnuTLS calls against unexpected errors */ +#define CHKgnutls(x) \ + if((gnuRet = (x)) != 0) { \ + dbgprintf("unexpected GnuTLS error %d in %s:%d\n", gnuRet, __FILE__, __LINE__); \ + gnutls_perror(gnuRet); /* TODO: can we do better? */ \ + ABORT_FINALIZE(RS_RET_GNUTLS_ERR); \ + } + +#define CAFILE "ca.pem" // TODO: allow to specify + +/* ------------------------------ GnuTLS specifics ------------------------------ */ +static gnutls_certificate_credentials xcred; + +/* globally initialize GnuTLS */ +static rsRetVal +gtlsGlblInit(void) +{ + int gnuRet; + DEFiRet; + + CHKgnutls(gnutls_global_init()); + + /* X509 stuff */ + CHKgnutls(gnutls_certificate_allocate_credentials(&xcred)); + + /* sets the trusted cas file */ + gnutls_certificate_set_x509_trust_file(xcred, CAFILE, GNUTLS_X509_FMT_PEM); + +finalize_it: + 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) { + 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; +} + + +/* ---------------------------- 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); + pThis->iMode = 1; /* TODO: must be made configurable */ + pThis->iMode = 0; /* TODO: must be made configurable */ +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) + + +/* 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; + iRet = nsd_ptcp.LstnInit(pNS, pUsr, fAddLstn, pLstnPort, pLstnIP, iSessMax); + 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; + nsd_gtls_t *pNew = NULL; + nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd; + + ISOBJ_TYPE_assert((pThis), nsd_gtls); + // TODO: method to construct without pTcp + CHKiRet(nsd_gtlsConstruct(&pNew)); + CHKiRet(nsd_ptcp.Destruct(&pNew->pTcp)); + CHKiRet(nsd_ptcp.AcceptConnReq(pThis->pTcp, &pNew->pTcp)); + + *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; + 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 */ + +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) + 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; + + /* 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)); + gnutls_transport_set_ptr(pThis->sess, (gnutls_transport_ptr)sock); + + /* and perform the handshake */ + CHKgnutls(gnutls_handshake(pThis->sess)); + dbgprintf("GnuTLS handshake succeeded\n"); + +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->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 + 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 */ +ENDmodInit +/* vi:set ai: + */ diff --git a/runtime/nsd_gtls.h b/runtime/nsd_gtls.h new file mode 100644 index 00000000..c193f57c --- /dev/null +++ b/runtime/nsd_gtls.h @@ -0,0 +1,49 @@ +/* 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 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 */ + gnutls_session sess; + int bHaveSess; +}; + +/* interface is defined in nsd.h, we just implement it! */ +#define nsd_gtlsCURR_IF_VERSION nsdCURR_IF_VERSION + +/* prototypes */ +PROTOTYPEObj(nsd_gtls); + +/* 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..2a74e061 --- /dev/null +++ b/runtime/nsd_ptcp.c @@ -0,0 +1,675 @@ +/* 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 "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; +} + + +/* 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 + */ +RUNLOG_VAR("%d", sock); + CHKiRet(pNS->Drvr.Construct(&pNewNsd)); + CHKiRet(pNS->Drvr.SetSock(pNewNsd, sock)); +RUNLOG; + CHKiRet(netstrms.CreateStrm(pNS, &pNewStrm)); + pNewStrm->pDrvrData = (nsd_t*) pNewNsd; +RUNLOG; + 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->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, LM_NETSTRM_FILENAME); + 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(netstrm, LM_NETSTRM_FILENAME)); + CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME)); + + /* set our own handlers */ +ENDObjClassInit(nsd_ptcp) + + +/* --------------- here now comes the plumbing that makes as a library module --------------- */ + + +BEGINmodExit +CODESTARTmodExit + 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 */ +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..7cafec49 --- /dev/null +++ b/runtime/nsdsel_gtls.c @@ -0,0 +1,184 @@ +/* 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 "nsdsel_ptcp.h" +#include "nsdsel_gtls.h" + +MODULE_TYPE_LIB + +/* 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); + iRet = nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, waitOp); + 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; +} + + +/* 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); + iRet = nsdsel_ptcp.IsReady(pThis->pTcp, pNsdGTLS->pTcp, waitOp, pbIsReady); + 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_LOADABLE_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_NSDSEL_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_LOADABLE_MODULE) /* class, version */ + /* request objects we use */ + CHKiRet(objUse(errmsg, CORE_COMPONENT)); + CHKiRet(objUse(glbl, CORE_COMPONENT)); + CHKiRet(objUse(nsdsel_ptcp, LM_NSDSEL_PTCP_FILENAME)); + + /* set our own handlers */ +ENDObjClassInit(nsdsel_gtls) + + +/* --------------- here now comes the plumbing that makes as a library module --------------- */ + + +BEGINmodExit +CODESTARTmodExit + nsdsel_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(nsdsel_gtlsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ +ENDmodInit +/* vi:set ai: + */ diff --git a/runtime/nsdsel_gtls.h b/runtime/nsdsel_gtls.h new file mode 100644 index 00000000..a309d302 --- /dev/null +++ b/runtime/nsdsel_gtls.h @@ -0,0 +1,45 @@ +/* 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); + +/* the name of our library binary */ +#define LM_NSDSEL_GTLS_FILENAME "lmnsdsel_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..b439063a --- /dev/null +++ b/runtime/nsdsel_ptcp.c @@ -0,0 +1,222 @@ +/* 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" + +MODULE_TYPE_LIB + +/* 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_LOADABLE_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_LOADABLE_MODULE) /* class, version */ + /* request objects we use */ + CHKiRet(objUse(errmsg, CORE_COMPONENT)); + CHKiRet(objUse(glbl, CORE_COMPONENT)); + + /* set our own handlers */ +ENDObjClassInit(nsdsel_ptcp) + + +/* --------------- here now comes the plumbing that makes as a library module --------------- */ + + +BEGINmodExit +CODESTARTmodExit + nsdsel_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(nsdsel_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ +ENDmodInit +/* vi:set ai: + */ diff --git a/runtime/nsdsel_ptcp.h b/runtime/nsdsel_ptcp.h new file mode 100644 index 00000000..93874e55 --- /dev/null +++ b/runtime/nsdsel_ptcp.h @@ -0,0 +1,47 @@ +/* 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); + +/* the name of our library binary */ +#define LM_NSDSEL_PTCP_FILENAME "lmnsdsel_ptcp" + +#endif /* #ifndef INCLUDED_NSDSEL_PTCP_H */ diff --git a/runtime/nssel.c b/runtime/nssel.c new file mode 100644 index 00000000..5333fc75 --- /dev/null +++ b/runtime/nssel.c @@ -0,0 +1,229 @@ +/* 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" + +MODULE_TYPE_LIB + +/* 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. + * rgerhards, 2008-04-18 + */ +static rsRetVal +loadDrvr(nssel_t *pThis) +{ + uchar *pDrvrName; + DEFiRet; + + pDrvrName = pThis->pDrvrName; + if(pDrvrName == NULL) /* if no drvr name is set, use system default */ + pDrvrName = glbl.GetDfltNetstrmDrvr(); + + 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__, pDrvrName+2, pDrvrName, (void*) &pThis->Drvr)); + CHKiRet(obj.UseObj(__FILE__, "nsdsel_gtls", "lmnsdsel_gtls", (void*) &pThis->Drvr)); +finalize_it: + 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); +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) + + +/* --------------- here now comes the plumbing that makes us a library module --------------- */ + + +BEGINmodExit +CODESTARTmodExit + nsselClassExit(); +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(nsselClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ +ENDmodInit +/* vi:set ai: + */ diff --git a/runtime/nssel.h b/runtime/nssel.h new file mode 100644 index 00000000..2f907caa --- /dev/null +++ b/runtime/nssel.h @@ -0,0 +1,55 @@ +/* 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 "nsd.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 *pDrvrName; /**< nsd driver name to use, or NULL if system default */ + 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 "lmnssel" + +#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) \ @@ -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; @@ -1204,7 +1198,7 @@ ReleaseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf) 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? */ + ABORT_FINALIZE(RS_RET_OK); /* we are not loaded - this is perfectly OK... */ } if(pIf->ifIsLoaded == 2) { pIf->ifIsLoaded = 0; /* clean up */ @@ -1292,10 +1286,10 @@ objClassExit(void) /* TODO: implement the class exits! */ #if 0 - errmsgClassInit(pModInfo); cfsyslineInit(pModInfo); varClassInit(pModInfo); #endif + errmsgClassExit(); moduleClassExit(); RETiRet; } @@ -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..19fda468 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,14 @@ 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 */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ @@ -182,7 +229,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 +293,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 +306,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/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/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 @@ -40,7 +40,6 @@ #include <errno.h> #include "rsyslog.h" -#include "syslogd.h" #include "stringbuf.h" #include "srUtils.h" #include "wtp.h" @@ -41,7 +41,6 @@ #include <errno.h> #include "rsyslog.h" -#include "syslogd.h" #include "stringbuf.h" #include "srUtils.h" #include "wtp.h" @@ -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) @@ -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..33c13aa0 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,6 @@ CODESTARTobjDestruct(tcps_sess) /* now destruct our own properties */ if(pThis->fromHost != NULL) free(pThis->fromHost); - close(pThis->sock); ENDobjDestruct(tcps_sess) @@ -110,6 +100,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. -- gerhards, 2008-04-24 + */ static rsRetVal SetHost(tcps_sess_t *pThis, uchar *pszHost) { @@ -119,25 +113,24 @@ 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; 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) { @@ -200,9 +193,8 @@ 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 @@ -228,8 +220,7 @@ 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... */ @@ -403,7 +394,7 @@ CODESTARTobjQueryInterface(tcps_sess) pIf->SetUsrP = SetUsrP; pIf->SetTcpsrv = SetTcpsrv; pIf->SetHost = SetHost; - pIf->SetSock = SetSock; + pIf->SetStrm = SetStrm; pIf->SetMsgIdx = SetMsgIdx; finalize_it: ENDobjQueryInterface(tcps_sess) @@ -416,6 +407,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_NETSTRM_FILENAME); ENDObjClassExit(tcps_sess) @@ -426,6 +418,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_NETSTRM_FILENAME)); /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, tcps_sessDebugPrint); diff --git a/tcps_sess.h b/tcps_sess.h index 0433fdfb..9f3d10d6 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, @@ -49,7 +43,7 @@ typedef struct tcps_sess_s { int iOctetsRemain; /* Number of Octets remaining in message */ TCPFRAMINGMODE eFraming; char msg[MAXLINE+1]; - char *fromHost; + uchar *fromHost; void *pUsr; /* a user-pointer */ } tcps_sess_t; @@ -67,7 +61,7 @@ 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 (*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! */ @@ -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 @@ -197,9 +182,10 @@ TCPSessGetNxtSess(tcpsrv_t *pThis, int iCurr) register int i; ISOBJ_TYPE_assert(pThis, tcpsrv); - for(i = iCurr + 1 ; i < pThis->iSessMax ; ++i) + for(i = iCurr + 1 ; i < pThis->iSessMax ; ++i) { if(pThis->pSessions[i] != NULL) break; + } return((i < pThis->iSessMax) ? i : -1); } @@ -213,17 +199,17 @@ 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]); + i = TCPSessGetNxtSess(pThis, -1); + while(i != -1) { + tcps_sess.Destruct(&pThis->pSessions[i]); /* now get next... */ - iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess); + i = TCPSessGetNxtSess(pThis, i); } /* we are done with the session table - so get rid of it... @@ -234,33 +220,49 @@ static void deinit_tcp_listener(tcpsrv_t *pThis) 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) +{ + 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; + +finalize_it: + RETiRet; +} + + +/* Initialize TCP sockets (for listener) and listens on them */ +static rsRetVal +create_tcp_socket(tcpsrv_t *pThis) { - struct addrinfo hints, *res, *r; - int error, maxs, *s, *socks, on = 1; - char *TCPLstnPort; + DEFiRet; + uchar *TCPLstnPort; ISOBJ_TYPE_assert(pThis, tcpsrv); - if(!strcmp(pThis->TCPLstnPort, "0")) - TCPLstnPort = "514"; + 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 +270,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 + TCPLstnPort = (uchar*)pThis->TCPLstnPort; - 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); - - 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 +284,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 +303,25 @@ 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; 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 +330,28 @@ 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(pStrm, &fromHostFQDN)); + /* 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.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 +370,70 @@ 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) { +RUNLOG_VAR("%d", 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 +441,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 +452,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 +472,44 @@ 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)); + // 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 +521,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 +608,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; @@ -793,7 +672,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(nssel, LM_NSSEL_FILENAME); + objRelease(netstrm, LM_NETSTRM_FILENAME); + objRelease(netstrms, LM_NETSTRMS_FILENAME); objRelease(net, LM_NET_FILENAME); ENDObjClassExit(tcpsrv) @@ -806,8 +689,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, LM_NETSTRM_FILENAME)); + CHKiRet(objUse(nssel, LM_NSSEL_FILENAME)); 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); @@ -26,9 +26,11 @@ #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 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 +38,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,13 +57,13 @@ 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*)); @@ -72,7 +74,7 @@ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */ 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: - */ @@ -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" @@ -33,7 +33,7 @@ #include <assert.h> #include "rsyslog.h" -#include "syslogd.h" +#include "dirty.h" #include "linkedlist.h" #include "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..f00abf0b --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1,42 @@ +sbin_PROGRAMS = +man_MANS = + +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 \ + \ + ../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 + +man_MANS += rsyslogd.8 rsyslog.conf.5 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..4b5eb280 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: 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..719075c7 --- /dev/null +++ b/tools/omfwd.c @@ -0,0 +1,625 @@ +/* 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 */ + 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 */ + + +/* 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)); + /* here we may set another netstream driver (e.g. to do TLS) */ + 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.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; + if(!netstrms.ifIsLoaded) + CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME)); + if(!netstrm.ifIsLoaded) + CHKiRet(objUse(netstrm, LM_NETSTRM_FILENAME)); + if(!tcpclt.ifIsLoaded) + 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)); + } + +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); + if(netstrm.ifIsLoaded) + objRelease(netstrm, LM_NETSTRM_FILENAME); + if(netstrms.ifIsLoaded) + objRelease(netstrms, LM_NETSTRMS_FILENAME); + if(!tcpclt.ifIsLoaded) + 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(glbl, CORE_COMPONENT)); + CHKiRet(objUse(errmsg, CORE_COMPONENT)); + CHKiRet(objUse(net,LM_NET_FILENAME)); + + CHKiRet(regCfSysLineHdlr((uchar *)"actionforwarddefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszTplName, NULL)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); +ENDmodInit + +/* vim:set ai: + */ 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..835a020d 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,10 +391,6 @@ 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_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\""; @@ -499,7 +468,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)); @@ -680,7 +648,7 @@ rsRetVal printline(char *hname, char *msg, int bParseHost, int flags, flowContro if(MsgSetUxTradMsg(pMsg, p) != 0) ABORT_FINALIZE(RS_RET_ERR); - logmsg(pMsg, flags | SYNC_FILE); + logmsg(pMsg, flags); finalize_it: RETiRet; @@ -879,6 +847,19 @@ 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 +870,16 @@ 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()); MsgSetTAG(pMsg, "rsyslogd:"); pMsg->iFacility = LOG_FAC(pri); pMsg->iSeverity = LOG_PRI(pri); @@ -1863,14 +1844,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 +1889,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 +1913,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 +2105,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 +2134,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 +2257,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 +2342,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 +2451,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 +2609,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 +2637,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)); @@ -2828,8 +2757,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 +2767,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 +2834,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 +2863,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 +2944,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 +2995,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 +3035,6 @@ int realMain(int argc, char **argv) default: usage(); } - bIsFirstOption = 0; /* we already saw an option character */ } if ((argc -= optind)) @@ -3173,11 +3064,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 +3088,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 +3097,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 +3126,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 +3166,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 +3219,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 +3236,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 */ |