pre-merged upstream for a clean merge-back

This commit is contained in:
Janmejay Singh 2016-02-04 16:14:21 +05:30
commit 25cc42c2ff
211 changed files with 8153 additions and 1851 deletions

View File

@ -1,22 +1,73 @@
language: c
compiler:
- gcc
- clang
# you can comment this in if a large number of known-good
# merges is to happen and only buildbot testing is desired
#branches:
# except:
# - master-candidate
matrix:
exclude:
- compiler: "gcc"
- compiler: "clang"
include:
# note: -Werror makes ./configure.sh not properly detect functions
# like strndup() on Ubuntu 12.04. So we enable it on trusty builds
# only. The first build with gcc actually only has the purpose of
# checking for warnings (the testbench currently has some issues
# on travis Ubuntu 14.04, but not in the regular environments, we
# need to find out some time why this is).
- compiler: "gcc"
env: CFLAGS="-g -std=c99 -Werror -W -Wall -Wextra -Wformat-security -Wshadow -Wcast-align -Wpointer-arith -Wmissing-format-attribute"
dist: trusty
- compiler: "clang"
env: STAT_AN="YES", GROK="YES", CFLAGS="-g -O1 -std=c99 -Werror"
dist: trusty
- compiler: "gcc"
env: BUILD_FROM_TARBALL="YES", GROK="YES", CHECK="YES", CFLAGS="-g -O2 -W -Wall -Wformat-security -Wshadow -Wcast-align -Wpointer-arith -Wmissing-format-attribute", RS_TESTBENCH_VALGRIND_EXTRA_OPTS="--suppressions=travis/trusty.supp --gen-suppressions=all"
dist: trusty
- compiler: "clang"
env: CHECK="YES", CFLAGS="-g -O1 -fsanitize=address -fno-color-diagnostics"
before_install:
- travis_retry sudo apt-get install -qq python-software-properties
- travis_retry sudo add-apt-repository ppa:adiscon/v8-devel -y
#- travis_retry sudo apt-get install -qq python-software-properties
- travis_retry sudo add-apt-repository ppa:adiscon/v8-stable -y
- travis_retry sudo apt-get update -qq
install:
- travis_retry sudo apt-get install -qq build-essential automake pkg-config libtool autoconf autotools-dev gdb valgrind libdbi-dev libsnmp-dev
- travis_retry sudo apt-get install -qq libestr-dev librelp-dev libjson0-dev zlib1g-dev uuid-dev libgcrypt11-dev liblogging-stdlog-dev bison flex
- travis_retry sudo apt-get install -qq build-essential automake pkg-config libtool autoconf autotools-dev gdb valgrind libdbi-dev libsnmp-dev libmysqlclient-dev postgresql-client faketime
- travis_retry sudo apt-get install -qq libestr-dev librelp-dev libfastjson-dev zlib1g-dev uuid-dev libgcrypt11-dev liblogging-stdlog-dev bison flex libksi1 libksi1-dev libcurl4-gnutls-dev
- travis_retry sudo apt-get install -qq python-docutils liblognorm1-dev
- if [ "$CC" == "clang" ]; then travis_retry sudo apt-get install -qq clang; fi
- if [ "x$GROK" == "xYES" ]; then travis_retry sudo apt-get install -qq libglib2.0-dev libgrok1 libgrok-dev libtokyocabinet-dev ; fi
script:
- if [ "x$BUILD_FROM_TARBALL" == "xYES" ]; then autoreconf -fvi && ./configure && make dist && mv *.tar.gz rsyslog.tar.gz && mkdir unpack && cd unpack && tar xzf ../rsyslog.tar.gz && ls -ld rsyslog* && cd rsyslog* ; fi
- pwd
- autoreconf --force --verbose --install
# add "CC=clang" to configure if clang is desired
- ./configure --prefix=/opt/rsyslog --build=x86_64-pc-linux-gnu --host=x86_64-pc-linux-gnu --mandir=/usr/share/man --infodir=/usr/share/info --datadir=/usr/share --sysconfdir=/etc --localstatedir=/var/lib --disable-dependency-tracking --disable-silent-rules --libdir=/usr/lib64 --docdir=/usr/share/doc/rsyslog --disable-generate-man-pages --enable-testbench --enable-imdiag --enable-imfile --enable-impstats --enable-imptcp --enable-mmanon --enable-mmaudit --enable-mmfields --enable-mmjsonparse --enable-mmpstrucdata --enable-mmsequence --enable-mmutf8fix --enable-mail --enable-omprog --enable-omruleset --enable-omstdout --enable-omuxsock --enable-pmaixforwardedfrom --enable-pmciscoios --enable-pmcisconames --enable-pmlastmsg --enable-pmsnare --enable-libgcrypt --enable-mmnormalize --disable-omudpspoof --enable-relp --disable-snmp --disable-mmsnmptrapd --enable-gnutls --enable-valgrind
# I don't know how to pass two env vars in the include matrix, so
# I set the second one here via an "if"
- if [ "x$GROK" == "xYES" ]; then export GROK="--enable-mmgrok"; fi
- if [ "$CC" == "clang" ]; then export NO_VALGRIND="--without-valgrind-testbench"; fi
- ./configure --prefix=/opt/rsyslog --build=x86_64-pc-linux-gnu --host=x86_64-pc-linux-gnu --mandir=/usr/share/man --infodir=/usr/share/info --datadir=/usr/share --sysconfdir=/etc --localstatedir=/var/lib --disable-dependency-tracking --enable-silent-rules --libdir=/usr/lib64 --docdir=/usr/share/doc/rsyslog --disable-generate-man-pages --enable-testbench --enable-imdiag --enable-imfile --enable-impstats --enable-imptcp --enable-mmanon --enable-mmaudit --enable-mmfields --enable-mmjsonparse --enable-mmpstrucdata --enable-mmsequence --enable-mmutf8fix --enable-mail --enable-omprog --enable-omruleset --enable-omstdout --enable-omuxsock --enable-pmaixforwardedfrom --enable-pmciscoios --enable-pmcisconames --enable-pmlastmsg --enable-pmsnare --enable-libgcrypt --enable-mmnormalize --disable-omudpspoof --enable-relp --disable-snmp --disable-mmsnmptrapd --enable-gnutls --enable-mysql --enable-gt-ksi --enable-libdbi --enable-pgsql --enable-omhttpfs --enable-elasticsearch --enable-valgrind $NO_VALGRIND $GROK
- export USE_AUTO_DEBUG="off" # set to "on" to enable this for travis
- make && make check #make dist && make check && sudo make install
- make distcheck
- make
- if [ "x$CHECK" == "xYES" ] ; then make check ; fi
- if [ -f tests/test-suite.log ] ; then cat tests/test-suite.log; fi
- if [ "x$CHECK" == "xYES" ] ; then make distcheck ; fi
- if [ "x$STAT_AN" == "xYES" ] ; then make clean ; fi
- if [ "x$STAT_AN" == "xYES" ] ; then cd compat; scan-build --status-bugs make && cd .. ; fi
# we now build those components that we know to need some more work
# they will not be included in the later static analyzer run. But by
# explicitely listing the modules which do not work, we automatically
# get new modules/files covered.
- if [ "x$STAT_AN" == "xYES" ] ; then cd runtime; make lmnet_la-net.lo libgcry_la-libgcry.lo ; cd .. ; fi
- if [ "x$STAT_AN" == "xYES" ] ; then scan-build --status-bugs make ; fi
# if that all worked, we go the traditional gcc & valgrind way
#- env TESTS="json_array_looping.sh" make -e check
# only for newer autoconf tools you need to add:
# - cat tests/test-suite.log

View File

@ -21,9 +21,49 @@ These are many ways to contribute to the project:
This list is not conclusive. There for sure are many more ways to contribute and if you find one, just let us know. We are very open to new suggestions and like to try out new things.
Requirements for patches
------------------------
In order to ensure good code quality, after applying the path the code must
- compile cleanly without WARNING messages under both gcc and clang
- pass clang static analyzer without any report
Note that both warning messages and static analyzer warnings may be false
positives. We have decided to accept that fate and work around it (e.g. by
re-arranging the code, etc). Otherwise, we cannot use these useful features.
As a last resort, compiler warnings can be turned off via
#pragma diagnostic
directives. This should really only be done if there is no other known
way around it. If so, it should be applied to a single function, only and
not to full source file. Be sure to re-enable the warning after the function
in question. We have done this in some few cases ourselfs, and if someone
can fix the root cause, we would appreciate help. But, again, this is a
last resort which should normally not be used.
For pull requests submitted via github, these two conditions are
verified automatically. See the PR for potential failueres. For patches
submitted otherwise, they will be verified semi-manually.
Also, patches are requested to not break the testbench. Unfortunately, the
current testbench has some racy tests, which are still useful enough so that
we do not want to disable them until the root cause has been found. If your
PR runs into something that you think is not related to your code, just sit
back and relax. The rsyslog core developer team reviews PRs regularly and
restarts tests which we know to look racy. If the problem persists, we will
contact you.
Once all this has passed, a final integration test will be done via buildbot
on a larger number of platforms. This is a semi-manual process. You will be
contacted if a problem shows up during it (very unlikely, but occasionally
happens).
Note to developers
------------------
Please adress pull requests against the master branch. The changes will at first be merged into another branch (master-candidate). There, the changes will be tested and merged into the master branch, should the test succeed.
Please adress pull requests against the master branch. The changes will at
first be merged into another branch (master-candidate). There, the
changes will be tested and merged into the master branch, should the test succeed.
More information is available at:
http://www.rsyslog.com/how-to-contribute-to-rsyslog/

233
ChangeLog
View File

@ -1,8 +1,234 @@
------------------------------------------------------------------------------
Version 8.14.0 [v8-stable] 2015-11-03
Version 8.17.0 [v8-stable] 2016-03-08
- NEW REQUIREMENT: libfastjson
see also:
- new feature: dynamic statistics counters
which may be changed during rule processing
Thanks to Janmejay Singh for suggesting and implementing this feature
- simplified locking in when accessing message and local variables
this simlifies the code and slightly increases performance if such
variables are heavily accessed.
- imuxsock: add "ruleset" input parameter
- imptcp: performance improvements
Thanks to Janmejay Singh for implementing this improvement
- made build compile (almost) without warnings
still some warnings are suppressed where this is currently required
- improve interface definition in some modules, e.g. mmanon, mmsequence
This is more an internal cleanup and should have no actual affect to
the end user.
- bugfix: potential loss of single message at queue shutdown
see also: https://github.com/rsyslog/rsyslog/issues/262
- bugfix: potential deadlock with heavy variable access
When making havy use of global, local and message variables, a deadlock
could occur. While it is extremly unlikely to happen, we have at least
seen one incarnation of this problem in practice.
- bugfix ommysql: on some platforms, serverport parameter had no effect
This was caused by an invalid code sequence which's outcome depends on
compiler settings.
- bugfix omelasticsearch: invalid pointer dereference
The actual practical impact is not clear. This came up when working
on compiler warnings.
Thanks to David Lang for the patch.
- bugfix rsgtutil: -h command line option did not work
Thanks to Henri Lakk for the patch.
- bugfix lexer: hex numbers were not properly represented
see: https://github.com/rsyslog/rsyslog/pull/771
Thanks to Sam Hanes for the patch.
------------------------------------------------------------------------------
Version 8.16.0 [v8-stable] 2016-01-26
- rsgtutil: Added extraction support including loglines and hash chains.
More details on how to extract loglines can be found in the rsgtutil
manpage. See also: https://github.com/rsyslog/rsyslog/issues/561
- clean up doAction output module interface
We started with char * pointers, but used different types of pointers
over time. This lead to alignment warnings. In practice, I think this
should never cause any problems (at least there have been no reports
in the 7 or so years we do this), but it is not clean. The interface is
now cleaned up. We do this in a way that does not require modifications
to modules that just use string parameters. For those with message
parameters, have a look at e.g. mmutf8fix to see how easy the
required change is.
- new system properties for $NOW properties based on UTC
This permits to express current system time in UTC.
See also https://github.com/rsyslog/rsyslog/issues/729
- impstats: support broken ElasticSearch JSON implementation
ES 2.0 no longer supports valid JSON and disallows dots inside names.
This adds a new "json-elasticsearch" format option which replaces
those dots by the bang ("!") character. So "discarded.full" becomes
"discarded!full".
This is a workaroud. A method that will provide more control over
replacements will be implemented some time in the future. For
details, see below-quoted issue tracker.
closes https://github.com/rsyslog/rsyslog/issues/713
- omelasticsearch: craft better URLs
Elasticsearch is confused by url's ending in a bare '?' or '&'. While
this is valid, those are no longer produced.
Thanks to Benno Evers for the patch.
- imfile: add experimental "reopenOnTruncate" parameter
Thanks to Matthew Wang for the patch.
- bugfix imfile: proper handling of inotify initialization failure
Thanks to Zachary Zhao for the patch.
- bugfix imfile: potential segfault due to improper handling of ev var
This occurs in inotify mode, only.
Thanks to Zachary Zhao and Peter Portante for the patch.
closes https://github.com/rsyslog/rsyslog/issues/718
- bugfix imfile: potential segfault under heavey load.
This occurs in inotify mode when using wildcards, only.
The root cause is dropped IN_IGNOPRED inotify events which be dropped
in circumstance of high input pressure and frequent rotation, and
according to wikipeida, they can also be dropped in other conditions.
Thanks to Zachary Zhao for the patch.
closes https://github.com/rsyslog/rsyslog/issues/723
- bugfix ommail: invalid handling of server response
if that response was split into different read calls. Could lead to
error-termination of send operation. Problem is pretty unlikely to
occur in standard setups (requires slow connection to SMTP server).
Thank to github user haixingood for the patch.
- bugfix omelasticsearch: custom serverport was ignored on some platforms
Thanks to Benno Evers for the patch.
- bugfix: tarball did not include some testbench files
Thanks to Thomas D. (whissi) for the patch.
- bugfix: memory misadressing during config parsing string template
This occurred if an (invalid) template option larger than 63 characters
was given.
Thanks to git hub user c6226 for the patch.
- bugfix imzmq: memory leak
Thanks to Jeremy Liang for the patch.
- bugfix imzmq: memory leak
Thanks to github user xushengping for the patch.
- bugfix omzmq: memory leak
Thanks to Jack Lin for the patch.
- some code improvement and cleanup
------------------------------------------------------------------------------
Version 8.15.0 [v8-stable] 2015-12-15
- KSI Lib: Updated code to run with libksi 3.4.0.5
Also libksi 3.4.0.x is required to build rsyslog if ksi support
is enabled. New libpackages have been build as well.
- KSI utilities: Added option to ser publication url.
Since libksi 3.4.0.x, there is no default publication url anymore.
The publication url has to be set using the --publications-server
Parameter, otherwise the ksi signature cannot be verified. UserID
and UserKey can also be set by parameter now.
Closes https://github.com/rsyslog/rsyslog/issues/581
- KSI Lib: Fixed wrong TLV container for KSI signatures from 0905 to 0906.
closes https://github.com/rsyslog/rsyslog/issues/587
- KSI/GT Lib: Fixed multiple issues found using static analyzer
- performance improvement for configs with heavy use of JSON variables
Depending on the config, this can be a very big gain in performance.
- added pmpanngfw: contributed module for translating Palo Alto Networks logs.
see also: https://github.com/rsyslog/rsyslog/pull/573
Thanks to Luigi Mori for the contribution.
- testbench: Changed valgrind option for imtcp-tls-basic-vg.sh
For details see: https://github.com/rsyslog/rsyslog/pull/569
- pmciscoios: support for asterisk before timestamp added
thanks to github user c0by for the patch
see also: https://github.com/rsyslog/rsyslog/pull/583
- solr external output plugin much enhanced
see also: https://github.com/rsyslog/rsyslog/pull/529
Thanks to Radu Gheorghe for the patch.
- omrabbitmq: improvements
thanks to Luigi Mori for the patch
see also: https://github.com/rsyslog/rsyslog/pull/580
- add support for libfastjson (as a replacement for json-c)
- KSI utilities: somewhat improved error messages
Thanks to Henri Lakk for the patch.
see also: https://github.com/rsyslog/rsyslog/pull/588
- pmciscoios: support for some format variations
Thanks to github user c0by for the patch
- support grok via new contributed module mmgrok
Thanks to 饶琛琳 (github user chenryn) for the contribution.
- omkafka: new statistics counter "maxoutqsize"
Thanks to 饶琛琳 (github user chenryn) for the contribution.
- improvments for 0mq modules:
* omczmq - suspend / Retry handling - the output plugin can now recover
from some error states due to issues with plugin startup or message sending
* omczmq - refactored topic handling code for ZMQ_PUB output to be a little
more efficient
* omczmq - added ability to set a timeout for sends
* omczmq - set topics can be in separate frame (default) or part of message
frame (configurable)
* omcmzq - code cleanup
* imczmq - code cleanup
* imczmq - fixed a couple of cases where vars could be used uninitialized
* imczmq - ZMQ_ROUTER support
* imczmq - Fix small memory leak from not freeing sockets when done with them
* allow creation of on demand ephemeral CurveZMQ certs for encryption.
Clients may specify clientcertpath="*" to indicate they want an on
demand generated cert.
Thanks to Brian Knox for the contributions.
- cleanup on code to unset a variable
under extreme cases (very, very unlikely), the old code could also lead
to errornous processing
- omelasticsearch: build on FreeBSD
Thanks to github user c0by for the patch
- pmciscoios: fix some small issues clang static analyzer detected
- testbench: many improvements and some new tests
note that there still is a number of tests which are somewhat racy
- overall code improvements thanks to clang static analyzer
- gnutls fix: Added possible fix for gnutls issue #575
see also: https://github.com/rsyslog/rsyslog/issues/575
Thanks to Charles Southerland for the patch
- bugfix omkafka: restore ability to build on all platforms
Undo commit aea09800643343ab8b6aa205b0f10a4be676643b
because that lead to build failures on various important platforms.
This means it currently is not possible to configure the location
of librdkafka, but that will affect far fewer people.
closes: https://github.com/rsyslog/rsyslog/issues/596
- bugfix omkafka: fix potentially negative partition number
Thanks to Tait Clarridge for providing a patch.
- bugfix: solve potential race in creation of additional action workers
Under extreme circumstances, this could lead to segfault. Note that we
detected this problem thanks to ASAN address sanitzier in combination
with a very exterme testbench test. We do not think that this issue
was ever reported in practice.
- bugfix: potential memory leak in config parsing
Thanks to github user linmujia for the patch
- bugfix: small memory leak in loading template config
This happened when a plugin was used inside the template. Then, the
memory for the template name was never freed.
Thanks to github user xushengping for the fix.
- bugfix: fix extra whitespace in property expansions
Address off-by-one issues introduced in f3bd7a2 resulting in extra
whitespace in property expansions
Thanks to Matthew Gabeler-Lee for the patch.
- bugfix: mmfields leaked memory if very large messages were processed
detected by clang static analyzer
- bugfix: mmfields could add garbagge data to field
this happened when very large fields were to be processed.
Thanks to Peter Portante for reporting this.
- bugfix: omhttpfs now also compiles with older json-c lib
- bugfix: memory leak in (contributed) module omhttpfs
Thanks to git hub user c6226 for the patch.
- bugfix: parameter mismatch in error message for wrap() function
- bugfix: parameter mismatch in error message for random() function
- bugfix: divide by zero if max() function was provided zero
- bugfix: invalid mutex handling in omfile async write mode
could lead to segfault, even though highly unlikely (caught by
testbench on a single platform)
- bugfix: fix inconsistent number processing
Unfortunately, previous versions of the rule engine tried to
support oct and hex, but that wasn't really the case.
Everything based on JSON was just dec-converted. As this was/is
the norm, we fix that inconsistency by always using dec.
Luckly, oct and hex support was never documented and could
probably only have been activated by constant numbers.
- bugfix: timezone() object: fix NULL pointer dereference
This happened during startup when the offset or id parameter was not
given. Could lead to a segfault at startup.
Detected by clang static analyzer.
- bugfix omfile: memory addressing error if very long outchannel name used
Thanks to github user c6226 for the patch.
------------------------------------------------------------------------------
Version 8.14.0 [v8-stable] 2015-11-03
- Added possibility to customize librdkafka location
see also: https://github.com/rsyslog/rsyslog/pull/502
Thanks to Matthew Wang for the patch.
- add property "rawmsg-after-pri"
- bugfix: potential misadresseing in imfile
Could happen when wildcards were used.
see also https://github.com/rsyslog/rsyslog/issues/532
see also https://github.com/rsyslog/rsyslog/issues/534
Thanks to zhangdaoling for the bugfix.
- bugfix: re_extract RainerScript function did not work
Thanks to Janmejay Singh for the patch
------------------------------------------------------------------------------
@ -188,6 +414,11 @@ Version 8.10.0 [v8-stable] 2015-05-19
source builds per default but enforced when building from git source.
- mmpstrucdata: some code cleanup
removed lots of early development debug outputs
- bugfix imuxsock: fix a memory leak that happened with large messages
... when annotation was enabled.
Thanks to github user c6226 for the patch
- bugfix omhttpfs: memory leak
Thanks to github user c6226 for the patch
- bugfix imuxsock: fix a crash when setting a hostname
Setting a hostname via the legacy directive would lead to a crash
during shutdown caused by a double-free.

View File

@ -103,6 +103,10 @@ if ENABLE_PMSNARE
SUBDIRS += contrib/pmsnare
endif
if ENABLE_PMPANNGFW
SUBDIRS += contrib/pmpanngfw
endif
if ENABLE_PMLASTMSG
SUBDIRS += plugins/pmlastmsg
endif
@ -203,6 +207,10 @@ if ENABLE_MMJSONPARSE
SUBDIRS += plugins/mmjsonparse
endif
if ENABLE_MMGROK
SUBDIRS += contrib/mmgrok
endif
if ENABLE_MMAUDIT
SUBDIRS += plugins/mmaudit
endif
@ -254,7 +262,8 @@ SUBDIRS += tests
# when some global update happened.
DISTCHECK_CONFIGURE_FLAGS= \
--disable-silent-rules \
--disable-testbench
--disable-testbench \
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
THIS_IS_TEMPORARILY_DISABLED = \
--enable-distcheck-workaround \
@ -270,6 +279,7 @@ THIS_IS_TEMPORARILY_DISABLED = \
--enable-mail \
--enable-klog \
--enable-diagtools \
--enable-mmgrok \
--enable-gnutls \
--enable-omstdout \
--enable-pmlastmsg \

View File

@ -63,7 +63,10 @@ Ubuntu
Note: this list is (obviously) incomplete. We intend to complete it as we
have more information and install additional systems.
sudo apt-get install libdbi-dev
sudo apt-get install libdbi-dev libmysqlclient-dev postgresql-client libpq-dev libnet-dev librdkafka-dev libgrok-dev libgrok1 libgrok-dev libpcre3-dev libtokyocabinet-dev libglib2.0-dev
for KSI, from the Adiscon PPA:
sudo apt-get install libksi0 libksi-devel
openSUSE 13
@ -102,7 +105,7 @@ Contributions to rsyslog are very welcome. Fork and send us your Pull Requests.
For more information about contributing, see the
[CONTRIBUTING](CONTRIBUTING.md) file.
Note that it is esay to add output plugins using languages like Python or
Note that it is easy to add output plugins using languages like Python or
Perl. So if you need to connect to a system which is not yet supported, you
can easily do so via an external plugin. For more information see the
[README](plugins/external/README.md) file in the external plugin directory.
@ -118,7 +121,7 @@ Project Philosophy
==================
We are an open source project in all aspects and very open to outside feedback
and contribution. We base our work on standards and try to solve all real-world
needs (of course, we occasionally fail tackeling actually all needs ;)). While
needs (of course, we occasionally fail tackling actually all needs ;)). While
the project is primarily sponsored by Adiscon, technical development is
independent from company goals and most decisions are solely based on mailing
list discussion results. There is an active community around rsyslog.

View File

@ -63,7 +63,7 @@
* beast.
* rgerhards, 2011-06-15
*
* Copyright 2007-2015 Rainer Gerhards and Adiscon GmbH.
* Copyright 2007-2016 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
@ -306,6 +306,7 @@ rsRetVal actionDestruct(action_t * const pThis)
pThis->pMod->freeInstance(pThis->pModData);
pthread_mutex_destroy(&pThis->mutAction);
pthread_mutex_destroy(&pThis->mutWrkrDataTable);
d_free(pThis->pszName);
d_free(pThis->ppTpl);
d_free(pThis->peParamPassing);
@ -360,6 +361,7 @@ rsRetVal actionConstruct(action_t **ppThis)
pThis->tLastOccur = datetime.GetTime(NULL); /* done once per action on startup only */
pThis->iActionNbr = iActionNbr;
pthread_mutex_init(&pThis->mutAction, NULL);
pthread_mutex_init(&pThis->mutWrkrDataTable, NULL);
INIT_ATOMIC_HELPER_MUT(pThis->mutCAS);
/* indicate we have a new action */
@ -385,7 +387,7 @@ actionConstructFinalize(action_t *__restrict__ const pThis, struct nvlst *lst)
}
/* generate a friendly name for us action stats */
if(pThis->pszName == NULL) {
snprintf((char*) pszAName, sizeof(pszAName)/sizeof(uchar), "action %d", pThis->iActionNbr);
snprintf((char*) pszAName, sizeof(pszAName), "action %d", pThis->iActionNbr);
pThis->pszName = ustrdup(pszAName);
}
@ -438,7 +440,7 @@ actionConstructFinalize(action_t *__restrict__ const pThis, struct nvlst *lst)
/* create our queue */
/* generate a friendly name for the queue */
snprintf((char*) pszAName, sizeof(pszAName)/sizeof(uchar), "%s queue",
snprintf((char*) pszAName, sizeof(pszAName), "%s queue",
pThis->pszName);
/* now check if we can run the action in "firehose mode" during stage one of
@ -778,6 +780,7 @@ actionCheckAndCreateWrkrInstance(action_t * const pThis, wti_t * const pWti)
/* maintain worker data table -- only needed if wrkrHUP is requested! */
pthread_mutex_lock(&pThis->mutWrkrDataTable);
int freeSpot;
for(freeSpot = 0 ; freeSpot < pThis->wrkrDataTableSize ; ++freeSpot)
if(pThis->wrkrDataTable[freeSpot] == NULL)
@ -788,9 +791,9 @@ actionCheckAndCreateWrkrInstance(action_t * const pThis, wti_t * const pWti)
(pThis->wrkrDataTableSize + 1) * sizeof(void*));
pThis->wrkrDataTableSize++;
}
dbgprintf("DDDD: writing data to table spot %d\n", freeSpot);
pThis->wrkrDataTable[freeSpot] = pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData;
pThis->nWrkr++;
pthread_mutex_unlock(&pThis->mutWrkrDataTable);
DBGPRINTF("wti %p: created action worker instance %d for "
"action %d\n", pWti, pThis->nWrkr, pThis->iActionNbr);
}
@ -978,15 +981,20 @@ releaseDoActionParams(action_t *__restrict__ const pAction, wti_t *__restrict__
switch(pAction->peParamPassing[j]) {
case ACT_ARRAY_PASSING:
ppMsgs = (uchar***) pWrkrInfo->p.nontx.actParams[0].param;
if(((uchar**)ppMsgs)[j] != NULL) {
jArr = 0;
while(ppMsgs[j][jArr] != NULL) {
free(ppMsgs[j][jArr]);
ppMsgs[j][jArr] = NULL;
++jArr;
/* if we every use array passing mode again, we need to check
* this code. It hasn't been used since refactoring for v7.
*/
if(ppMsgs != NULL) {
if(((uchar**)ppMsgs)[j] != NULL) {
jArr = 0;
while(ppMsgs[j][jArr] != NULL) {
free(ppMsgs[j][jArr]);
ppMsgs[j][jArr] = NULL;
++jArr;
}
free(((uchar**)ppMsgs)[j]);
((uchar**)ppMsgs)[j] = NULL;
}
free(((uchar**)ppMsgs)[j]);
((uchar**)ppMsgs)[j] = NULL;
}
break;
case ACT_JSON_PASSING:
@ -1291,7 +1299,7 @@ processMsgMain(action_t *__restrict__ const pAction,
{
DEFiRet;
iRet = prepareDoActionParams(pAction, pWti, pMsg, ttNow);
CHKiRet(prepareDoActionParams(pAction, pWti, pMsg, ttNow));
if(pAction->isTransactional) {
pWti->actWrkrInfo[pAction->iActionNbr].pAction = pAction;
@ -1332,7 +1340,10 @@ processBatchMain(void *__restrict__ const pVoid,
for(i = 0 ; i < batchNumMsgs(pBatch) && !*pWti->pbShutdownImmediate ; ++i) {
if(batchIsValidElem(pBatch, i)) {
iRet = processMsgMain(pAction, pWti, pBatch->pElem[i].pMsg, &ttNow);
/* we do not check error state below, because aborting would be
* more harmful than continuing.
*/
processMsgMain(pAction, pWti, pBatch->pElem[i].pMsg, &ttNow);
batchSetElemState(pBatch, i, BATCH_STATE_COMM);
}
}
@ -1349,6 +1360,7 @@ void
actionRemoveWorker(action_t *const __restrict__ pAction,
void *const __restrict__ actWrkrData)
{
pthread_mutex_lock(&pAction->mutWrkrDataTable);
pAction->nWrkr--;
for(int w = 0 ; w < pAction->wrkrDataTableSize ; ++w) {
if(pAction->wrkrDataTable[w] == actWrkrData) {
@ -1356,6 +1368,7 @@ actionRemoveWorker(action_t *const __restrict__ pAction,
break; /* done */
}
}
pthread_mutex_unlock(&pAction->mutWrkrDataTable);
}
@ -1377,14 +1390,21 @@ actionCallHUPHdlr(action_t * const pAction)
}
if(pAction->pMod->doHUPWrkr != NULL) {
pthread_mutex_lock(&pAction->mutWrkrDataTable);
for(int i = 0 ; i < pAction->wrkrDataTableSize ; ++i) {
dbgprintf("HUP: table entry %d: %p %s\n", i,
pAction->wrkrDataTable[i],
pAction->wrkrDataTable[i] == NULL ? "[unused]" : "");
if(pAction->wrkrDataTable[i] != NULL) {
CHKiRet(pAction->pMod->doHUPWrkr(pAction->wrkrDataTable[i]));
const rsRetVal localRet
= pAction->pMod->doHUPWrkr(pAction->wrkrDataTable[i]);
if(localRet != RS_RET_OK) {
DBGPRINTF("HUP handler returned error state %d - "
"ignored\n", localRet);
}
}
}
pthread_mutex_unlock(&pAction->mutWrkrDataTable);
}
finalize_it:
@ -1770,7 +1790,7 @@ addAction(action_t **ppAction, modInfo_t *pMod, void *pModData,
if(!(iTplOpts & OMSR_TPL_AS_MSG)) {
if((pAction->ppTpl[i] =
tplFind(ourConf, (char*)pTplName, strlen((char*)pTplName))) == NULL) {
snprintf(errMsg, sizeof(errMsg) / sizeof(char),
snprintf(errMsg, sizeof(errMsg),
" Could not find template %d '%s' - action disabled",
i, pTplName);
errno = 0;

View File

@ -74,6 +74,7 @@ struct action_s {
uchar *pszName; /* action name */
DEF_ATOMIC_HELPER_MUT(mutCAS)
/* for per-worker HUP processing */
pthread_mutex_t mutWrkrDataTable; /* protects table structures */
void **wrkrDataTable;
int wrkrDataTableSize;
int nWrkr;

View File

@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
AC_INIT([rsyslog],[8.14.0.master],[rsyslog@lists.adiscon.com])
AC_INIT([rsyslog],[8.17.0.master],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE([subdir-objects])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
@ -26,9 +26,7 @@ PKG_PROG_PKG_CONFIG
# modules we require
PKG_CHECK_MODULES(LIBESTR, libestr >= 0.1.9)
PKG_CHECK_MODULES([JSON_C], [json],, [
PKG_CHECK_MODULES([JSON_C], [json-c],,)
])
PKG_CHECK_MODULES([JSON_C], [libfastjson],,)
save_CFLAGS="$CFLAGS"
save_LIBS="$LIBS"
@ -294,6 +292,14 @@ AC_CHECK_HEADERS(
[AC_MSG_FAILURE([pthread is missing])]
)
AC_CHECK_LIB(
[pthread],
[pthread_rwlockattr_setkind_np],
[AC_DEFINE(
[HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP],
[1],
[Set-kind available for rwlock attr.])])
AC_CHECK_FUNCS(
[pthread_setschedparam],
[
@ -955,6 +961,24 @@ AC_ARG_ENABLE(mmjsonparse,
)
AM_CONDITIONAL(ENABLE_MMJSONPARSE, test x$enable_mmjsonparse = xyes)
# mmgrok
AC_ARG_ENABLE(mmgrok,
[AS_HELP_STRING([--enable-mmgrok],[Enable building mmgrok support @<:@default=no@:>@])],
[case "${enableval}" in
yes) enable_mmgrok="yes" ;;
no) enable_mmgrok="no" ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-mmgrok) ;;
esac],
[enable_mmgrok=no]
)
if test "x$enable_mmgrok" = "xyes"; then
GLIB_CFLAGS="$(pkg-config --cflags glib-2.0)"
GLIB_LIBS="$(pkg-config --libs glib-2.0)"
fi
AM_CONDITIONAL(ENABLE_MMGROK, test x$enable_mmgrok = xyes)
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
# mmaudit
AC_ARG_ENABLE(mmaudit,
[AS_HELP_STRING([--enable-mmaudit],[Enable building mmaudit support @<:@default=no@:>@])],
@ -1107,8 +1131,8 @@ AC_ARG_ENABLE(gt-ksi,
[enable_gt_ksi=no]
)
if test "x$enable_gt_ksi" = "xyes"; then
PKG_CHECK_MODULES(GT_KSI, libksi >= 3.2.2.0)
PKG_CHECK_MODULES(GT_KSI, libksi < 3.3.0.0)
PKG_CHECK_MODULES(GT_KSI, libksi >= 3.4.0.2)
PKG_CHECK_MODULES(GT_KSI, libksi < 3.5.0.0)
fi
AM_CONDITIONAL(ENABLE_GT_KSI, test x$enable_gt_ksi = xyes)
@ -1378,6 +1402,19 @@ AC_ARG_ENABLE(pmsnare,
AM_CONDITIONAL(ENABLE_PMSNARE, test x$enable_pmsnare = xyes)
# settings for pmpanngfw
AC_ARG_ENABLE(pmpanngfw,
[AS_HELP_STRING([--enable-pmpanngfw],[Compiles Palo Alto Networks parser module @<:@default=no@:>@])],
[case "${enableval}" in
yes) enable_pmpanngfw="yes" ;;
no) enable_pmpanngfw="no" ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-pmpanngfw) ;;
esac],
[enable_pmpanngfw=no]
)
AM_CONDITIONAL(ENABLE_PMPANNGFW, test x$enable_pmpanngfw = xyes)
# settings for omruleset
AC_ARG_ENABLE(omruleset,
[AS_HELP_STRING([--enable-omruleset],[Compiles ruleset forwarding module @<:@default=no@:>@])],
@ -1443,8 +1480,15 @@ AC_ARG_ENABLE(omkafka,
esac],
[enable_omkafka=no]
)
if test "x$enable_omkafka"; then
#PKG_CHECK_MODULES(LIBRDKAFKA, librdkafka)
if test "x$enable_omkafka" = "xyes"; then
PKG_CHECK_MODULES([LIBRDKAFKA], [librdkafka],, [
AC_CHECK_LIB([rdkafka], [rd_kafka_produce], [
AC_MSG_WARN([librdkafka is missing but library present, using -lrdkafka])
LIBRDKAFKA_LIBS=-lrdkafka
], [
AC_MSG_ERROR([could not find rdkafka library])
])
])
AC_CHECK_HEADERS([librdkafka/rdkafka.h])
fi
AM_CONDITIONAL(ENABLE_OMKAFKA, test x$enable_omkafka = xyes)
@ -1708,10 +1752,12 @@ AC_CONFIG_FILES([Makefile \
plugins/mmsnmptrapd/Makefile \
plugins/pmlastmsg/Makefile \
contrib/pmsnare/Makefile \
contrib/pmpanngfw/Makefile \
contrib/pmaixforwardedfrom/Makefile \
contrib/omhiredis/Makefile \
contrib/omrabbitmq/Makefile \
contrib/imkmsg/Makefile \
contrib/mmgrok/Makefile \
contrib/mmcount/Makefile \
contrib/omzmq3/Makefile \
contrib/omczmq/Makefile \
@ -1777,10 +1823,12 @@ echo " pmcisconames module will be compiled: $enable_pmcisconames"
echo " pmciscoios module will be compiled: $enable_pmciscoios"
echo " pmaixforwardedfrom module w.be compiled: $enable_pmaixforwardedfrom"
echo " pmsnare module will be compiled: $enable_pmsnare"
echo " pmpanngfw module will be compiled: $enable_pmpanngfw"
echo
echo "---{ message modification modules }---"
echo " mmnormalize module will be compiled: $enable_mmnormalize"
echo " mmjsonparse module will be compiled: $enable_mmjsonparse"
echo " mmgrok module will be compiled: $enable_mmgrok"
echo " mmjaduit module will be compiled: $enable_mmaudit"
echo " mmsnmptrapd module will be compiled: $enable_mmsnmptrapd"
echo " mmutf8fix enabled: $enable_mmutf8fix"

View File

@ -48,26 +48,29 @@ DEFobjCurrIf(glbl)
DEFobjCurrIf(prop)
DEFobjCurrIf(ruleset)
/* Arguments to pass to poll handler */
/* --------------------------------- */
typedef struct _pollerData_t {
ruleset_t *ruleset;
thrdInfo_t *thread;
thrdInfo_t *thread;
int sockType;
} pollerData_t;
struct instanceConf_s {
bool is_server;
char *beacon;
int beaconPort;
int sockType;
char *sockEndpoints;
char *topicList;
char *authType;
char *clientCertPath;
char *serverCertPath;
uchar *pszBindRuleset;
ruleset_t *pBindRuleset;
struct instanceConf_s *next;
bool serverish; /* whether socket will be a server or client */
char *beacon; /* (optional) content of beacon */
int beaconPort; /* (optional) port if beacon is set */
int sockType; /* (required) type of zeromq socket */
char *sockEndpoints; /* (required) comma delimited list of endpoints */
char *topicList; /* (optional) topics to subscribe to if SUB */
char *authType; /* (optional) type of authentication */
char *clientCertPath; /* (optional) path to curve client cert(s) */
char *serverCertPath; /* (optional) path to curve server cert */
uchar *pszBindRuleset; /* (optional) ruleset to bind to */
ruleset_t *pBindRuleset; /* holds the ruleset reference */
struct instanceConf_s *next; /* pointer to next conf */
};
struct modConfData_s {
@ -78,12 +81,12 @@ struct modConfData_s {
};
struct lstn_s {
zactor_t *beaconActor;
zsock_t *sock;
zcert_t *clientCert;
zcert_t *serverCert;
ruleset_t *pRuleset;
struct lstn_s *next;
zactor_t *beaconActor; /* CZMQ beacon actor */
zsock_t *sock; /* zeromq socket */
zcert_t *clientCert; /* client curve certificate */
zcert_t *serverCert; /* server curve certificate */
ruleset_t *pRuleset; /* ruleset */
struct lstn_s *next; /* pointer to next input */
};
static modConfData_t *runModConf = NULL;
@ -103,6 +106,34 @@ static struct cnfparamblk modpblk = {
modpdescr
};
/* -------------------------------------------------------------
* Explanation of Options
* ----------------------
* endpoints
* A comma delimited list of endpoints to connect to. Whether the
* endpoint connects or binds is determined by defaults for
* each socket type.
* socktype
* The type of zeromq socket to use; supports SUB and PULL.
* beacon
* The beacon is lit! If beacon is set to a value, that value
* will be used to advertise the existence of this endpoint
* over udp multicast beacons.
* beaconport
* The port to use for the beacon
* authtype
* The authentication type to use - currently only supports
* CURVESERVER and CURVECLIENT.
* clientcertpath
* The path to client certificate(s). Must be set if authtype is
* set to CURVE.
* servercertpath
* The path to server certificate. Must be set if authtype is
* set to CURVE
* topics
* A comma delimited list of topics to subscribe to.
* ------------------------------------------------------------- */
static struct cnfparamdescr inppdescr[] = {
{ "beacon", eCmdHdlrGetWord, 0 },
{ "beaconport", eCmdHdlrGetWord, 0 },
@ -124,7 +155,7 @@ static struct cnfparamblk inppblk = {
};
static void setDefaults(instanceConf_t* iconf) {
iconf->is_server = false;
iconf->serverish = true;
iconf->beacon = NULL;
iconf->beaconPort = -1;
iconf->sockType = -1;
@ -169,46 +200,43 @@ static rsRetVal createListener(struct cnfparamvals* pvals) {
continue;
}
/* get the ruleset to bind to */
if(!strcmp(inppblk.descr[i].name, "ruleset")) {
inst->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL);
}
/* get the socket endpoints to use */
else if(!strcmp(inppblk.descr[i].name, "endpoints")) {
inst->sockEndpoints = es_str2cstr(pvals[i].val.d.estr, NULL);
}
/* get beacon argument */
else if (!strcmp(inppblk.descr[i].name, "beacon")) {
inst->beacon = es_str2cstr(pvals[i].val.d.estr, NULL);
}
/* get beacon port */
else if (!strcmp(inppblk.descr[i].name, "beaconport")) {
inst->beaconPort = atoi(es_str2cstr(pvals[i].val.d.estr, NULL));
}
/* get the socket type */
else if(!strcmp(inppblk.descr[i].name, "socktype")){
char *stringType = es_str2cstr(pvals[i].val.d.estr, NULL);
if ( NULL == stringType ){
errmsg.LogError(0, RS_RET_OUT_OF_MEMORY,
"imczmq: '%s' is invalid sockType", stringType);
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
if (!strcmp("SUB", stringType)) {
inst->sockType = ZMQ_SUB;
}
else if (!strcmp("PULL", stringType)) {
inst->sockType = ZMQ_PULL;
}
else {
errmsg.LogError(0, RS_RET_CONFIG_ERROR,
"imczmq: invalid sockType");
ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
else if (!strcmp("ROUTER", stringType)) {
inst->sockType = ZMQ_ROUTER;
}
else {
errmsg.LogError(0, RS_RET_CONFIG_ERROR,
"imczmq: '%s' is invalid sockType", stringType);
free(stringType);
ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
}
free(stringType);
}
/* get the subscription topics */
else if(!strcmp(inppblk.descr[i].name, "topics")) {
if (inst->sockType != ZMQ_SUB) {
errmsg.LogError(0, RS_RET_CONFIG_ERROR,
@ -218,8 +246,6 @@ static rsRetVal createListener(struct cnfparamvals* pvals) {
inst->topicList = es_str2cstr(pvals[i].val.d.estr, NULL);
}
/* get the authentication type to use */
else if(!strcmp(inppblk.descr[i].name, "authtype")) {
inst->authType = es_str2cstr(pvals[i].val.d.estr, NULL);
@ -234,18 +260,12 @@ static rsRetVal createListener(struct cnfparamvals* pvals) {
ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
}
}
/* get client cert argument */
else if(!strcmp(inppblk.descr[i].name, "clientcertpath")) {
inst->clientCertPath = es_str2cstr(pvals[i].val.d.estr, NULL);
}
/* get server cert argument */
else if(!strcmp(inppblk.descr[i].name, "servercertpath")) {
inst->serverCertPath = es_str2cstr(pvals[i].val.d.estr, NULL);
}
/* the config has a bad option */
else {
errmsg.LogError(0, NO_ERRCODE,
"imczmq: program error, non-handled "
@ -265,20 +285,25 @@ static rsRetVal addListener(instanceConf_t* iconf){
pData->next = NULL;
pData->pRuleset = iconf->pBindRuleset;
/* create our zeromq socket */
/* Create the zeromq socket */
/* ------------------------ */
pData->sock = zsock_new(iconf->sockType);
if (!pData->sock) {
if (!pData->sock) {
errmsg.LogError(0, RS_RET_NO_ERRCODE,
"imczmq: new socket failed for endpoints: %s",
iconf->sockEndpoints);
ABORT_FINALIZE(RS_RET_NO_ERRCODE);
}
/* if a beacon is set start it */
DBGPRINTF ("imczmq: created socket...\n");
/* Create the beacon actor if configured */
/* ------------------------------------- */
if((iconf->beacon != NULL) && (iconf->beaconPort > 0)) {
DBGPRINTF ("imczmq: starting beacon actor...\n");
/* create the beacon actor, if it fails abort */
pData->beaconActor = zactor_new(zbeacon, NULL);
if (!pData->beaconActor) {
errmsg.LogError(0, RS_RET_NO_ERRCODE,
@ -286,7 +311,6 @@ static rsRetVal addListener(instanceConf_t* iconf){
ABORT_FINALIZE (RS_RET_NO_ERRCODE);
}
/* configure the beacon and abort if UDP broadcasting ont available */
zsock_send(pData->beaconActor, "si", "CONFIGURE", iconf->beaconPort);
char *hostname = zstr_recv(pData->beaconActor);
if (!*hostname) {
@ -295,73 +319,84 @@ static rsRetVal addListener(instanceConf_t* iconf){
ABORT_FINALIZE (RS_RET_NO_ERRCODE);
}
/* start publishing the beacon */
zsock_send(pData->beaconActor, "sbi", "PUBLISH", pData->beaconActor, strlen(iconf->beacon));
zsock_send(pData->beaconActor,
"sbi", "PUBLISH", pData->beaconActor, strlen(iconf->beacon));
DBGPRINTF ("omczmq: beacon is lit: hostname: '%s', port: '%d'...\n",
hostname, iconf->beaconPort);
}
DBGPRINTF("imczmq: authtype is: %s\n", iconf->authType);
/* if we are a CURVE server */
if ((iconf->authType != NULL) && (!strcmp(iconf->authType, "CURVESERVER"))) {
if (iconf->authType != NULL) {
iconf->is_server = true;
/* CURVESERVER */
/* ----------- */
/* set global auth domain */
zsock_set_zap_domain(pData->sock, "global");
if (!strcmp(iconf->authType, "CURVESERVER")) {
/* set that we are a curve server */
zsock_set_curve_server(pData->sock, 1);
zsock_set_zap_domain(pData->sock, "global");
zsock_set_curve_server(pData->sock, 1);
/* get and set our server cert */
DBGPRINTF("imczmq: server cert is %s...\n", iconf->serverCertPath);
pData->serverCert = zcert_load(iconf->serverCertPath);
if (!pData->serverCert) {
errmsg.LogError(0, NO_ERRCODE, "could not load server cert");
ABORT_FINALIZE(RS_RET_ERR);
pData->serverCert = zcert_load(iconf->serverCertPath);
if (!pData->serverCert) {
errmsg.LogError(0, NO_ERRCODE, "could not load server cert");
ABORT_FINALIZE(RS_RET_ERR);
}
zcert_apply(pData->serverCert, pData->sock);
zstr_sendx(authActor, "CURVE", iconf->clientCertPath, NULL);
zsock_wait(authActor);
DBGPRINTF("imczmq: CURVESERVER: serverCertPath: '%s'\n", iconf->serverCertPath);
DBGPRINTF("mczmq: CURVESERVER: clientCertPath: '%s'\n", iconf->clientCertPath);
}
zcert_apply(pData->serverCert, pData->sock);
/* CURVECLIENT */
/* ----------- */
/* set allowed clients */
DBGPRINTF("imczmq: allowed clients are %s...\n", iconf->clientCertPath);
zstr_sendx(authActor, "CURVE", iconf->clientCertPath, NULL);
zsock_wait(authActor);
else if (!strcmp(iconf->authType, "CURVECLIENT")) {
if (!strcmp(iconf->clientCertPath, "*")) {
pData->clientCert = zcert_new();
}
else {
pData->clientCert = zcert_load(iconf->clientCertPath);
}
if (!pData->clientCert) {
errmsg.LogError(0, NO_ERRCODE, "could not load client cert");
ABORT_FINALIZE(RS_RET_ERR);
}
zcert_apply(pData->clientCert, pData->sock);
pData->serverCert = zcert_load(iconf->serverCertPath);
if (!pData->serverCert) {
errmsg.LogError(0, NO_ERRCODE, "could not load server cert");
ABORT_FINALIZE(RS_RET_ERR);
}
char *server_key = zcert_public_txt(pData->serverCert);
zsock_set_curve_serverkey (pData->sock, server_key);
DBGPRINTF("imczmq: CURVECLIENT: serverCertPath: '%s'\n", iconf->serverCertPath);
DBGPRINTF("imczmq: CURVECLIENT: clientCertPath: '%s'\n", iconf->clientCertPath);
DBGPRINTF("imczmq: CURVECLIENT: server_key: '%s'\n", server_key);
}
else {
errmsg.LogError(0, NO_ERRCODE, "unrecognized auth type: '%s'", iconf->authType);
ABORT_FINALIZE(RS_RET_ERR);
}
}
/* if we are a CURVE client */
if ((iconf->authType != NULL) && (!strcmp(iconf->authType, "CURVECLIENT"))) {
DBGPRINTF("imczmq: we are a curve client...\n");
/* subscribe to topics */
/* ------------------- */
iconf->is_server = false;
/* get our client cert */
pData->clientCert = zcert_load(iconf->clientCertPath);
if (!pData->clientCert) {
errmsg.LogError(0, NO_ERRCODE, "could not load client cert");
ABORT_FINALIZE(RS_RET_ERR);
}
/* apply the client cert to the socket */
zcert_apply(pData->clientCert, pData->sock);
/* get the server cert */
DBGPRINTF("omczmq: server cert is %s...\n", iconf->serverCertPath);
pData->serverCert = zcert_load(iconf->serverCertPath);
if (!pData->serverCert) {
errmsg.LogError(0, NO_ERRCODE, "could not load server cert");
ABORT_FINALIZE(RS_RET_ERR);
}
/* get the server public key and set it for the socket */
char *server_key = zcert_public_txt(pData->serverCert);
DBGPRINTF("omczmq: server public key is %s...\n", server_key);
zsock_set_curve_serverkey (pData->sock, server_key);
}
/* if we have a ZMQ_SUB sock, subscribe to topics */
if (iconf->sockType == ZMQ_SUB) {
iconf->is_server = false;
char topic[256], *list = iconf->topicList;
while (list) {
char *delimiter = strchr(list, ',');
@ -388,8 +423,19 @@ static rsRetVal addListener(instanceConf_t* iconf){
}
}
switch (iconf->sockType) {
case ZMQ_SUB:
iconf->serverish = false;
break;
case ZMQ_PULL:
case ZMQ_ROUTER:
iconf->serverish = true;
break;
}
int rc = zsock_attach(pData->sock, (const char*)iconf->sockEndpoints,
iconf->is_server);
iconf->serverish);
if (rc == -1) {
errmsg.LogError(0, NO_ERRCODE, "zsock_attach to %s",
iconf->sockEndpoints);
@ -397,6 +443,8 @@ static rsRetVal addListener(instanceConf_t* iconf){
}
/* add this struct to the global */
/* ----------------------------- */
if(lcnfRoot == NULL) {
lcnfRoot = pData;
}
@ -415,9 +463,11 @@ static int handlePoll(zloop_t __attribute__((unused)) *loop, zmq_pollitem_t *pol
msg_t* pMsg;
pollerData_t *pollerData = (pollerData_t *)args;
zmsg_t *msg = zmsg_recv(poller->socket);
zframe_t *payload = zmsg_last(msg);
char* buf = zframe_strdup(payload);
if (pollerData->sockType == ZMQ_ROUTER ) {
zframe_t *idFrame = zframe_recv (poller->socket);
zframe_destroy (&idFrame);
}
char *buf = zstr_recv(poller->socket);
if (msgConstruct(&pMsg) == RS_RET_OK) {
MsgSetRawMsg(pMsg, buf, strlen(buf));
@ -432,8 +482,7 @@ static int handlePoll(zloop_t __attribute__((unused)) *loop, zmq_pollitem_t *pol
submitMsg2(pMsg);
}
free(buf);
zmsg_destroy(&msg);
zstr_free(&buf);
if( pollerData->thread->bShallStop == TRUE) {
return -1;
@ -445,14 +494,22 @@ static int handlePoll(zloop_t __attribute__((unused)) *loop, zmq_pollitem_t *pol
static rsRetVal rcvData(thrdInfo_t* pThrd){
DEFiRet;
DBGPRINTF("imczmq: starting auth actor...\n");
zmq_pollitem_t *items = NULL;
pollerData_t *pollerData = NULL;
/* Create the authentication actor */
/* ------------------------------ */
authActor = zactor_new(zauth, NULL);
if (!authActor) {
errmsg.LogError(0, RS_RET_NO_ERRCODE,
"imczmq: could not create auth service");
ABORT_FINALIZE(RS_RET_NO_ERRCODE);
}
DBGPRINTF ("imczmq: auth actor started\n");
instanceConf_t *inst;
for (inst = runModConf->root; inst != NULL; inst=inst->next) {
addListener(inst);
@ -470,12 +527,13 @@ static rsRetVal rcvData(thrdInfo_t* pThrd){
n_items++;
}
zmq_pollitem_t *items = NULL;
CHKmalloc(items = (zmq_pollitem_t*)MALLOC(sizeof(zmq_pollitem_t)*n_items));
/* create poller and set up zloop handler */
/* TODO: replace zloop with zpoller */
/* ------------------------------------- */
pollerData_t *pollerData = NULL;
CHKmalloc(pollerData = (pollerData_t *)MALLOC(sizeof(pollerData_t)*n_items));
CHKmalloc(items = (zmq_pollitem_t*)MALLOC(sizeof(zmq_pollitem_t)*n_items));
size_t i;
for(i=0, current = lcnfRoot; current != NULL; current = current->next, i++) {
items[i].socket=zsock_resolve(current->sock);
@ -483,12 +541,12 @@ static rsRetVal rcvData(thrdInfo_t* pThrd){
pollerData[i].thread = pThrd;
pollerData[i].ruleset = current->pRuleset;
pollerData[i].sockType = zsock_type(current->sock);
}
zloopHandle = zloop_new();
int rc;
zloopHandle = zloop_new();
for(i=0; i<n_items; ++i) {
rc = zloop_poller(zloopHandle, &items[i], handlePoll, &pollerData[i]);
if (rc) {
errmsg.LogError(0, NO_ERRCODE,
@ -496,9 +554,19 @@ static rsRetVal rcvData(thrdInfo_t* pThrd){
i, zmq_strerror(errno));
}
}
DBGPRINTF("imczmq: zloop_poller starting...");
/* start loop */
/* ---------- */
zloop_start(zloopHandle);
/* loop has exited */
/* --------------- */
zloop_destroy(&zloopHandle);
DBGPRINTF("imczmq: zloop_poller stopped.");
finalize_it:
free(items);
@ -607,9 +675,10 @@ ENDendCnfLoad
static inline void
std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
{
errmsg.LogError(0, NO_ERRCODE, "imczmq: ruleset '%s' for socket %s not found - "
"using default ruleset instead", inst->pszBindRuleset,
inst->sockEndpoints);
errmsg.LogError(0, NO_ERRCODE,
"imczmq: ruleset '%s' for socket %s not found - "
"using default ruleset instead", inst->pszBindRuleset,
inst->sockEndpoints);
}
@ -645,6 +714,7 @@ CODESTARTfreeCnf
lstn_r = lstn;
zcert_destroy(&lstn->clientCert);
zcert_destroy(&lstn->serverCert);
zsock_destroy(&lstn->sock);
lstn = lstn_r->next;
free(lstn_r);
}

View File

@ -99,7 +99,7 @@ enqMsg(uchar *msg, uchar* pszTag, syslog_pri_t pri, struct timeval *tp, struct j
if(tp == NULL) {
CHKiRet(msgConstruct(&pMsg));
} else {
datetime.timeval2syslogTime(tp, &st);
datetime.timeval2syslogTime(tp, &st, TIME_IN_LOCALTIME);
CHKiRet(msgConstructWithTime(&pMsg, &st, tp->tv_sec));
}
MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
@ -129,7 +129,7 @@ rsRetVal imkmsgLogIntMsg(syslog_pri_t priority, char *fmt, ...)
uchar msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */
va_start(ap, fmt);
vsnprintf((char*)msgBuf, sizeof(msgBuf) / sizeof(char), fmt, ap);
vsnprintf((char*)msgBuf, sizeof(msgBuf), fmt, ap);
va_end(ap);
logmsgInternal(NO_ERRCODE, priority, msgBuf, 0);

View File

@ -305,6 +305,7 @@ static rsRetVal parseSubscriptions(char* subscribes, sublist** subList){
DBGPRINTF("'%s'", currentSub->subscribe);
}
DBGPRINTF("\n");
finalize_it:
RETiRet;
}
@ -474,8 +475,10 @@ static rsRetVal createListener(struct cnfparamvals* pvals) {
} else if(!strcmp(inppblk.descr[i].name, "rcvHWM")) {
inst->rcvHWM = (int) pvals[i].val.d.n;
} else if(!strcmp(inppblk.descr[i].name, "subscribe")) {
CHKiRet(parseSubscriptions(es_str2cstr(pvals[i].val.d.estr, NULL),
&inst->subscriptions));
char *subscribes = es_str2cstr(pvals[i].val.d.estr, NULL);
rsRetVal ret = parseSubscriptions(subscribes, &inst->subscriptions);
free(subscribes);
CHKiRet(ret);
} else if(!strcmp(inppblk.descr[i].name, "identity")){
inst->identity = es_str2cstr(pvals[i].val.d.estr, NULL);
} else if(!strcmp(inppblk.descr[i].name, "sndBuf")) {

View File

@ -0,0 +1,8 @@
pkglib_LTLIBRARIES = mmgrok.la
mmgrok_la_SOURCES = mmgrok.c
mmgrok_la_CPPFLAGS = $(GLIB_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
mmgrok_la_LDFLAGS = -module -avoid-version
mmgrok_la_LIBADD = $(GLIB_LIBS) -lgrok $(JSON_C_LIBS)
EXTRA_DIST =

32
contrib/mmgrok/README Normal file
View File

@ -0,0 +1,32 @@
Grok Message Modify Plugin
Using hundreds of grok patterns from logstash-patterns-core.
Build
This plugin requires json-c, glib2, and grok packages.
If you use RH/CentOS/Fedora, you'll have to build grok rpms by yourself as follow:
sudo yum install -y yum-utils rpmdevtools
git clone git@github.com:jordansissel/grok.git
mkdir -p ~/rpmbuild/SPECS/; cp grok/grok.spec.template ~/rpmbuild/SPECS/grok.spec
(mkdir -p ~/rpmbuld/SOURCES/; cd ~/rpmbuild/SOURCES/; spectool -g ../SPECS/grok.spec)
sudo yum-builddep ~/rpmbuild/SPECS/grok.spec
rpmbuild -bb ~/rpmbuild/SPECS/grok.spec
# use yum command instead of rpm, because grok depends on libevent, pcre, tokyocabinet
sudo yum install -y libjson-c-devel glib2-devel ~/rpbuild/RPMS/x86_64/grok*.rpm
Example
module(load="mmgrok")
template(name="tmlp" type="string" string="%$!msg!test%\n")
action(type="mmgrok" patterndir="path/to/yourpatternsDir" match="%{WORD:test}" soure="msg" target="!msg")
action(type="omfile" file="path/to/file" template="tmlp")
Descrption
patterndir: path to grok patterns dir, default: /usr/share/grok/patterns/base
matchthe pattern used to match message
source: the source message/variable to be matched
target: the root path to write the captured json tree

423
contrib/mmgrok/mmgrok.c Normal file
View File

@ -0,0 +1,423 @@
/* mmgrok.c
* Grok the message is parsed into a structured json data inside JSON.
*/
#include "config.h"
#include "rsyslog.h"
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include <json.h>
#include <grok.h>
#include <glib.h>
#include "conf.h"
#include "syslogd-types.h"
#include "template.h"
#include "module-template.h"
#include "errmsg.h"
#include "cfsysline.h"
#include "dirty.h"
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
MODULE_CNFNAME("mmgrok");
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
DEFobjCurrIf(errmsg);
DEF_OMOD_STATIC_DATA
typedef struct result_s{
char *key;
int key_len;
const char *value;
int value_len;
char *type;
}result_t;
/* config variables */
typedef struct _instanceData
{
char *pszPatternDir;
char *pszMatch;
char *pszSource;
char *pszTarget;/* as a json root for store parse json data */
msg_t *pmsg; /* store origin messages*/
}instanceData;
typedef struct wrkrInstanceData{
instanceData *pData;
}wrkrInstanceData_t;
struct modConfData_s{
rsconf_t *pConf;/* our overall config object */
};
static modConfData_t *loadModConf = NULL;
static modConfData_t *runModConf = NULL;
/* action (instance) paramters */
static struct cnfparamdescr actpdescr[]={
{"patterndir",eCmdHdlrString,0},
{"match",eCmdHdlrString,0},
{"source",eCmdHdlrString,0},
{"target",eCmdHdlrString,0},
};
static struct cnfparamblk actpblk =
{
CNFPARAMBLK_VERSION,
sizeof(actpdescr)/sizeof(struct cnfparamdescr),
actpdescr
};
BEGINbeginCnfLoad
CODESTARTbeginCnfLoad
loadModConf = pModConf;
pModConf->pConf = pConf;
ENDbeginCnfLoad
BEGINendCnfLoad
CODESTARTendCnfLoad
ENDendCnfLoad
BEGINcheckCnf
CODESTARTcheckCnf
ENDcheckCnf
BEGINactivateCnf
CODESTARTactivateCnf
runModConf = pModConf;
ENDactivateCnf
BEGINfreeCnf
CODESTARTfreeCnf
ENDfreeCnf
BEGINcreateInstance
CODESTARTcreateInstance
ENDcreateInstance
BEGINcreateWrkrInstance
CODESTARTcreateWrkrInstance
ENDcreateWrkrInstance
BEGINisCompatibleWithFeature
CODESTARTisCompatibleWithFeature
ENDisCompatibleWithFeature
BEGINfreeInstance
CODESTARTfreeInstance
free(pData->pszPatternDir);
free(pData->pszMatch);
free(pData->pszSource);
free(pData->pszTarget);
ENDfreeInstance
BEGINfreeWrkrInstance
CODESTARTfreeWrkrInstance
ENDfreeWrkrInstance
static inline void setInstParamDefaults(instanceData *pData)
{
pData->pszPatternDir= NULL;
pData->pszMatch = NULL;
pData->pszSource = NULL;
pData->pszTarget = NULL;
pData->pmsg = NULL;
}
BEGINnewActInst
struct cnfparamvals *pvals;
int i;
CODESTARTnewActInst
DBGPRINTF("newActInst (mmgrok)\n");
if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
}
CODE_STD_STRING_REQUESTnewActInst(1)
CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
CHKiRet(createInstance(&pData));
setInstParamDefaults(pData);
for(i = 0 ; i < actpblk.nParams ; ++i) {
if(!pvals[i].bUsed)
continue;
if(!strcmp(actpblk.descr[i].name, "patterndir")) {
pData->pszPatternDir= es_str2cstr(pvals[i].val.d.estr, NULL);
continue;
}
else if(!strcmp(actpblk.descr[i].name, "match")) {
pData->pszMatch = es_str2cstr(pvals[i].val.d.estr, NULL);
continue;
}
else if(!strcmp(actpblk.descr[i].name, "source")) {
pData->pszSource= es_str2cstr(pvals[i].val.d.estr, NULL);
continue;
}
else if(!strcmp(actpblk.descr[i].name,"target"))
{
pData->pszTarget=es_str2cstr(pvals[i].val.d.estr,NULL);
continue;
}
else{
DBGPRINTF("mmgrok: program error, non-handled "
"param '%s'\n", actpblk.descr[i].name);
}
}
if(pData->pszTarget == NULL) {
CHKmalloc(pData->pszTarget = strdup("!"));
}
CODE_STD_FINALIZERnewActInst
cnfparamvalsDestruct(pvals, &actpblk);
ENDnewActInst
BEGINdbgPrintInstInfo
CODESTARTdbgPrintInstInfo
DBGPRINTF("mmgrok\n");
ENDdbgPrintInstInfo
BEGINtryResume
CODESTARTtryResume
ENDtryResume
static inline grok_t *CreateGrok()
{
grok_t *grok = grok_new();
if(grok == NULL){
DBGPRINTF("mmgrok: create a grok faile!");
exit(1);
}
grok_init(grok);
return grok;
}
/* the parseing is complate message into json */
static rsRetVal
msg_to_json(GList *list,instanceData *pData)
{
GList *it= list;
struct json_object *json;
struct json_object *jval;
DEFiRet;
json = json_object_new_object();
if(json == NULL)
{
ABORT_FINALIZE(RS_RET_ERR);
}
for(;it;it= it->next)
{
int key_len = ((result_t *)it->data)->key_len;
char *key = (char *)malloc(key_len+1);
snprintf(key,key_len+1,"%.*s",key_len,((result_t *)it->data)->key);
int value_len = ((result_t *)it->data)->value_len;
char *value = (char *)malloc(value_len+1);
snprintf(value,value_len+1,"%.*s",value_len,((result_t*)it->data)->value);
jval = json_object_new_string(value);
json_object_object_add(json,key,jval);
free(key);
free(value);
}
msgAddJSON(pData->pmsg,(uchar*)pData->pszTarget,json,0,0);
finalize_it:
RETiRet;
}
/* store parse result ,use list in glib*/
static rsRetVal
parse_result_store(const grok_match_t gm,instanceData *pData)
{
GList *re_list = NULL;
char *pname;
const char *pdata;
int pname_len,pdata_len;
char *key;
char *type;
DEFiRet;
grok_match_walk_init(&gm); //grok API
while(grok_match_walk_next(&gm,&pname,&pname_len,&pdata,&pdata_len) == 0)
{
/* parse key and value type from patterns */
key = strchr(pname,':');
if(key!=NULL)
{
int key_len;
result_t *result = g_new0(result_t,1);
key_len = pname_len - ((key+1) - pname);
key = key+1;
pname_len = key_len;
type = strchr(key,':');
int type_len;
if(type!=NULL)
{
key_len = (type - key);
type = type+1;
type_len = pname_len - key_len -1;
sprintf(type,"%.*s",type_len,type);
}
else{type = "null";}
/* store parse result into list */
result->key = key;
result->key_len = key_len;
result->value = pdata;
result->value_len = pdata_len;
result->type = type;
/* the value of merger the same key*/
re_list = g_list_append(re_list,result);
}
}
msg_to_json(re_list,pData);
g_list_free(re_list);
grok_match_walk_end(&gm);
RETiRet;
}
/* motify message for per line */
static rsRetVal
MotifyLine(char *line,grok_t *grok,instanceData *pData)
{
grok_match_t gm;
DEFiRet;
grok_patterns_import_from_file(grok,pData->pszPatternDir);
int compile = grok_compile(grok,pData->pszMatch);
if(compile!=GROK_OK)
{
DBGPRINTF("mmgrok: grok_compile faile!exit code: %d\n",compile);
ABORT_FINALIZE(RS_RET_ERR);
}
int exe = grok_exec(grok,line,&gm);
if(exe!=GROK_OK)
{
DBGPRINTF("mmgrok: grok_exec faile!exit code: %d\n",exe);
ABORT_FINALIZE(RS_RET_ERR);
}
parse_result_store(gm,pData);
finalize_it:
RETiRet;
}
/* motify rsyslog messages */
static rsRetVal
MotifyMessage(instanceData *pData)
{
DEFiRet;
grok_t *grok = CreateGrok();
char *msg = strdup(pData->pszSource);
char *line = NULL;
line = strtok(msg,"\n");
while(line!=NULL)
{
MotifyLine(line,grok,pData);
line = strtok(NULL,"\n");
}
free(msg);msg=NULL;
RETiRet;
}
BEGINdoAction_NoStrings
msg_t **ppMsg = (msg_t **) pMsgData;
msg_t *pMsg = ppMsg[0];
uchar *buf;
instanceData *pData;
CODESTARTdoAction
pData = pWrkrData->pData;
buf = getMSG(pMsg);
pData->pmsg = pMsg;
while(*buf && isspace(*buf)) {
++buf;
}
if(*buf == '\0' ) {
DBGPRINTF("mmgrok: not msg for mmgrok!");
ABORT_FINALIZE(RS_RET_NO_CEE_MSG);
}
pData->pszSource = (char *)buf;
CHKiRet(MotifyMessage(pData));
finalize_it:
ENDdoAction
BEGINparseSelectorAct
CODESTARTparseSelectorAct
CODE_STD_STRING_REQUESTparseSelectorAct(1)
if(strncmp((char*) p, ":mmgrok:", sizeof(":mmgrok:") - 1)) {
ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
}
p += sizeof(":mmgrok:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
CHKiRet(createInstance(&pData));
if(*(p-1) == ';')
--p;
CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_TPL_AS_MSG, (uchar*) "RSYSLOG_FileFormat"));
CODE_STD_FINALIZERparseSelectorAct
ENDparseSelectorAct
BEGINmodExit
CODESTARTmodExit
objRelease(errmsg, CORE_COMPONENT);
ENDmodExit
BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_OMOD_QUERIES
CODEqueryEtryPt_STD_OMOD8_QUERIES
CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
CODEqueryEtryPt_STD_CONF2_QUERIES
ENDqueryEtryPt
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
DEFiRet;
RETiRet;
}
BEGINmodInit()
rsRetVal localRet;
rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
unsigned long opts;
int bMsgPassingSupported;
CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION;
CODEmodInit_QueryRegCFSLineHdlr
DBGPRINTF("mmgrok: module compiled with rsyslog version %s.\n", VERSION);
bMsgPassingSupported = 0;
localRet = pHostQueryEtryPt((uchar*)"OMSRgetSupportedTplOpts",
&pomsrGetSupportedTplOpts);
if(localRet == RS_RET_OK) {
CHKiRet((*pomsrGetSupportedTplOpts)(&opts));
if(opts & OMSR_TPL_AS_MSG)
bMsgPassingSupported = 1;
} else if(localRet != RS_RET_ENTRY_POINT_NOT_FOUND) {
ABORT_FINALIZE(localRet); /* Something else went wrong, not acceptable */
}
if(!bMsgPassingSupported) {
DBGPRINTF("mmgrok: msg-passing is not supported by rsyslog core, "
"can not continue.\n");
ABORT_FINALIZE(RS_RET_NO_MSG_PASSING);
}
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit

View File

@ -312,15 +312,15 @@ getCounter(struct hashtable *ht, char *str, int initial) {
}
BEGINdoAction
msg_t *pMsg;
BEGINdoAction_NoStrings
msg_t **ppMsg = (msg_t **) pMsgData;
msg_t *pMsg = ppMsg[0];
struct json_object *json;
int val = 0;
int *pCounter;
instanceData *pData;
CODESTARTdoAction
pData = pWrkrData->pData;
pMsg = (msg_t*) ppString[0];
switch(pData->mode) {
case mmSequenceRandom:

View File

@ -47,36 +47,81 @@ DEFobjCurrIf(errmsg)
static pthread_mutex_t mutDoAct = PTHREAD_MUTEX_INITIALIZER;
typedef struct _instanceData {
zactor_t *authActor;
zactor_t *beaconActor;
zsock_t *sock;
zcert_t *clientCert;
zcert_t *serverCert;
char *sockEndpoints;
int sockType;
char *authType;
char *clientCertPath;
char *serverCertPath;
uchar *tplName;
char *beacon;
int beaconport;
char *topicList;
zactor_t *authActor; /* reference to a CZMQ auth actor */
zactor_t *beaconActor; /* reference to a CZMQ beacon actor */
zsock_t *sock; /* zeromq socket */
bool serverish; /* whether socket will be a server (bind) or client */
int sendTimeout; /* send timeout for socket (defaults to -1) */
zcert_t *clientCert; /* client curve certificate */
zcert_t *serverCert; /* server curve certificate */
zlist_t *topics; /* publish topics if set */
bool sendError; /* set to true of a socket send timed out */
char *sockEndpoints; /* (required) comma delimited list of endpoints */
int sockType; /* (required) the type of our zeromq socket */
char *authType; /* (optional) type of authentication */
char *clientCertPath; /* (optional) path to curve client cert(s) */
char *serverCertPath; /* (optional) path to curve server cert */
uchar *tplName; /* (optional) name of template to use */
char *beacon; /* (optional) content of beacon if beaconing */
int beaconport; /* (optional) port of beacon if beaconing */
char *topicList; /* (optional) topic list */
bool topicFrame; /* (optional) whether to set topic as separate frame */
} instanceData;
typedef struct wrkrInstanceData {
instanceData *pData;
} wrkrInstanceData_t;
/* -------------------------------------------------------------
* Explanation of Options
* ----------------------
* endpoints
* A comma delimited list of endpoints to connect to. Whether the
* endpoint connects or binds is determined by defaults for
* each socket type.
* socktype
* The type of zeromq socket to use; supports PUB, PUSH and DEALER.
* sndTimeout
* Send timeout. Defaults to -1, which is "block forever" and the
* standard ZeroMQ default. 0 = immediate, otherwise is value
* in milliseconds.
* beacon
* The beacon is lit! If beacon is set to a value, that value
* will be used to advertise the existence of this endpoint
* over udp multicast beacons.
* beaconport
* The port to use for the beacon
* authtype
* The authentication type to use - currently only supports
* CURVESERVER and CURVECLIENT.
* clientcertpath
* The path to client certificate(s). Must be set if authtype is
* set to CURVE.
* servercertpath
* The path to server certificate. Must be set if authtype is
* set to CURVE
* template
* The template to use to format outgoing logs. If not set,
* defaults to RSYSLOG_ForwardFormat.
* topics
* A comma delimited list of topics to publish messages on.
* If this is set, each message will be sent once per topic
* in the list. Note that ZeroMQ "topics" are simply matches
* against the first bytes in a message, so dynamic topics
* per message can be constructed using templates as well.
* ------------------------------------------------------------- */
static struct cnfparamdescr actpdescr[] = {
{ "endpoints", eCmdHdlrGetWord, 1 },
{ "socktype", eCmdHdlrGetWord, 1 },
{ "sendtimeout", eCmdHdlrGetWord, 0 },
{ "beacon", eCmdHdlrGetWord, 0 },
{ "beaconport", eCmdHdlrGetWord, 0 },
{ "authtype", eCmdHdlrGetWord, 0 },
{ "clientcertpath", eCmdHdlrGetWord, 0 },
{ "servercertpath", eCmdHdlrGetWord, 0 },
{ "template", eCmdHdlrGetWord, 0 },
{ "topics", eCmdHdlrGetWord, 0 }
{ "topics", eCmdHdlrGetWord, 0 },
{ "topicframe", eCmdHdlrGetWord, 0}
};
static struct cnfparamblk actpblk = {
@ -88,125 +133,151 @@ static struct cnfparamblk actpblk = {
static rsRetVal initCZMQ(instanceData* pData) {
DEFiRet;
/* tell czmq to not use it's own signal handler */
putenv ("ZSYS_SIGHANDLER=false");
/* Turn off CZMQ signal handling */
/* ----------------------------- */
putenv ("ZSYS_SIGHANDLER=false");
/* Create the authentication actor */
/* ------------------------------ */
/* create new auth actor */
DBGPRINTF ("omczmq: starting auth actor...\n");
pData->authActor = zactor_new(zauth, NULL);
if (!pData->authActor) {
errmsg.LogError(0, RS_RET_NO_ERRCODE,
"omczmq: could not create auth service");
ABORT_FINALIZE (RS_RET_NO_ERRCODE);
"omczmq: could not create auth actor");
ABORT_FINALIZE (RS_RET_SUSPENDED);
}
/* create our zeromq socket */
DBGPRINTF ("omczmq: creating zeromq socket...\n");
DBGPRINTF ("omczmq: auth actor started\n");
/* Create the zeromq socket */
/* ------------------------ */
pData->sock = zsock_new(pData->sockType);
if (!pData->sock) {
errmsg.LogError(0, RS_RET_NO_ERRCODE,
"omczmq: new socket failed for endpoints: %s",
pData->sockEndpoints);
ABORT_FINALIZE(RS_RET_NO_ERRCODE);
ABORT_FINALIZE(RS_RET_SUSPENDED);
}
bool is_server = false;
zsock_set_sndtimeo (pData->sock, pData->sendTimeout);
DBGPRINTF ("omczmq: created socket with timeout %d...\n", pData->sendTimeout);
/* Create the beacon actor if configured */
/* ------------------------------------- */
/* if a beacon is set start it */
if((pData->beacon != NULL) && (pData->beaconport > 0)) {
DBGPRINTF ("omczmq: starting beacon actor...\n");
/* create the beacon actor, if it fails abort */
pData->beaconActor = zactor_new(zbeacon, NULL);
if (!pData->beaconActor) {
errmsg.LogError(0, RS_RET_NO_ERRCODE,
"omczmq: could not create beacon service");
ABORT_FINALIZE (RS_RET_NO_ERRCODE);
ABORT_FINALIZE (RS_RET_SUSPENDED);
}
/* configure the beacon and abort if UDP broadcasting ont available */
zsock_send(pData->beaconActor, "si", "CONFIGURE", pData->beaconport);
char *hostname = zstr_recv(pData->beaconActor);
if (!*hostname) {
errmsg.LogError(0, RS_RET_NO_ERRCODE,
"omczmq: no UDP broadcasting available");
ABORT_FINALIZE (RS_RET_NO_ERRCODE);
ABORT_FINALIZE (RS_RET_SUSPENDED);
}
/* start publishing the beacon */
zsock_send(pData->beaconActor, "sbi", "PUBLISH", pData->beacon, strlen(pData->beacon));
DBGPRINTF ("omczmq: beacon is lit: hostname: '%s', port: '%d'...\n",
hostname, pData->beaconport);
zstr_free (&hostname);
}
/* if we are a CURVE server */
if ((pData->authType != NULL) && (!strcmp(pData->authType, "CURVESERVER"))) {
DBGPRINTF("omczmq: we are a curve server...\n");
/* Load certs for auth if auth is used */
/* ----------------------------------- */
if (pData->authType != NULL) {
/* CURVESERVER */
/* ---------- */
if (!strcmp(pData->authType, "CURVESERVER")) {
is_server = true;
zsock_set_zap_domain(pData->sock, "global");
zsock_set_curve_server(pData->sock, 1);
/* set global auth domain */
zsock_set_zap_domain(pData->sock, "global");
pData->serverCert = zcert_load(pData->serverCertPath);
/* set that we are a curve server */
zsock_set_curve_server(pData->sock, 1);
if (!pData->serverCert) {
errmsg.LogError(0, NO_ERRCODE, "could not load server cert");
ABORT_FINALIZE(RS_RET_ERR);
}
/* get and set our server cert */
DBGPRINTF("omczmq: server cert is %s...\n", pData->serverCertPath);
pData->serverCert = zcert_load(pData->serverCertPath);
if (!pData->serverCert) {
errmsg.LogError(0, NO_ERRCODE, "could not load server cert");
ABORT_FINALIZE(RS_RET_ERR);
zcert_apply(pData->serverCert, pData->sock);
zstr_sendx(pData->authActor, "CURVE", pData->clientCertPath, NULL);
zsock_wait(pData->authActor);
DBGPRINTF("omczmq: CURVESERVER: serverCertPath: '%s'\n", pData->serverCertPath);
DBGPRINTF("omczmq: CURVESERVER: clientCertPath: '%s'\n", pData->clientCertPath);
}
zcert_apply(pData->serverCert, pData->sock);
/* CURVECLIENT */
/* ----------- */
/* set allowed clients */
DBGPRINTF("omczmq: allowed clients are %s...\n", pData->clientCertPath);
zstr_sendx(pData->authActor, "CURVE", pData->clientCertPath, NULL);
zsock_wait(pData->authActor);
}
else if (!strcmp(pData->authType, "CURVECLIENT")) {
if (!strcmp(pData->clientCertPath, "*")) {
pData->clientCert = zcert_new();
}
else {
pData->clientCert = zcert_load(pData->clientCertPath);
}
if (!pData->clientCert) {
errmsg.LogError(0, NO_ERRCODE, "could not load client cert");
ABORT_FINALIZE(RS_RET_ERR);
}
/* if we are a CURVE client */
if ((pData->authType != NULL) && (!strcmp(pData->authType, "CURVECLIENT"))) {
DBGPRINTF("omczmq: we are a curve client...\n");
zcert_apply(pData->clientCert, pData->sock);
is_server = false;
pData->serverCert = zcert_load(pData->serverCertPath);
/* get our client cert */
pData->clientCert = zcert_load(pData->clientCertPath);
if (!pData->clientCert) {
errmsg.LogError(0, NO_ERRCODE, "could not load client cert");
ABORT_FINALIZE(RS_RET_ERR);
if (!pData->serverCert) {
errmsg.LogError(0, NO_ERRCODE, "could not load server cert");
ABORT_FINALIZE(RS_RET_ERR);
}
char *server_key = zcert_public_txt(pData->serverCert);
zsock_set_curve_serverkey (pData->sock, server_key);
DBGPRINTF("omczmq: CURVECLIENT: serverCertPath: '%s'\n", pData->serverCertPath);
DBGPRINTF("omczmq: CURVECLIENT: clientCertPath: '%s'\n", pData->clientCertPath);
DBGPRINTF("omczmq: CURVECLIENT: server_key: '%s'\n", server_key);
}
/* apply the client cert to the socket */
zcert_apply(pData->clientCert, pData->sock);
/* get the server cert */
DBGPRINTF("omczmq: server cert is %s...\n", pData->serverCertPath);
pData->serverCert = zcert_load(pData->serverCertPath);
if (!pData->serverCert) {
errmsg.LogError(0, NO_ERRCODE, "could not load server cert");
ABORT_FINALIZE(RS_RET_ERR);
else {
errmsg.LogError(0, NO_ERRCODE, "unrecognized auth type: '%s'", pData->authType);
ABORT_FINALIZE(RS_RET_ERR);
}
/* get the server public key and set it for the socket */
char *server_key = zcert_public_txt(pData->serverCert);
DBGPRINTF("omczmq: server public key is %s...\n", server_key);
zsock_set_curve_serverkey (pData->sock, server_key);
}
switch (pData->sockType) {
case ZMQ_PUB:
pData->serverish = true;
break;
case ZMQ_PUSH:
case ZMQ_DEALER:
pData->serverish = false;
break;
}
/* if we are a PUB server */
if (pData->sockType == ZMQ_PUB) {
DBGPRINTF("omczmq: we are a pub server...\n");
is_server = true;
}
/* we default to CONNECT unless told otherwise */
int rc = zsock_attach(pData->sock, (const char*)pData->sockEndpoints, is_server);
int rc = zsock_attach(pData->sock, (const char*)pData->sockEndpoints, pData->serverish);
if (rc == -1) {
errmsg.LogError(0, NO_ERRCODE, "zsock_attach to %s failed",
pData->sockEndpoints);
ABORT_FINALIZE(RS_RET_ERR);
ABORT_FINALIZE(RS_RET_SUSPENDED);
}
finalize_it:
@ -221,61 +292,35 @@ rsRetVal outputCZMQ(uchar* msg, instanceData* pData) {
CHKiRet(initCZMQ(pData));
}
/* if we have a ZMQ_PUB sock and topics, send with topics */
if (pData->sockType == ZMQ_PUB && pData->topicList) {
char topic[256], *list = pData->topicList;
int rc;
/* if we have a ZMQ_PUB sock and topics, send once per topic */
if (pData->sockType == ZMQ_PUB && pData->topics) {
char *topic = zlist_first(pData->topics);
while (topic) {
if (pData->topicFrame) {
int rc = zstr_sendx(pData->sock, topic, (char*)msg, NULL);
if (rc != 0) {
pData->sendError = true;
ABORT_FINALIZE(RS_RET_SUSPENDED);
}
}
else {
int rc = zstr_sendf(pData->sock, "%s%s", topic, (char*)msg);
if (rc != 0) {
pData->sendError = true;
ABORT_FINALIZE(RS_RET_SUSPENDED);
}
while (list) {
char *delimiter = strchr(list, ',');
if (!delimiter) {
delimiter = list + strlen (list);
}
if (delimiter - list > 255) {
errmsg.LogError(0, NO_ERRCODE,
"pData->topicList must be under 256 characters");
ABORT_FINALIZE(RS_RET_ERR);
}
memcpy(topic, list, delimiter - list);
topic[delimiter - list] = 0;
/* send the topic */
rc = zstr_sendm(pData->sock, topic);
/* something is very wrong */
if (rc == -1) {
errmsg.LogError(0, NO_ERRCODE, "omczmq: send of topic %s failed"
": %s", topic, zmq_strerror(errno));
ABORT_FINALIZE(RS_RET_ERR);
}
/* send the log line */
rc = zstr_send(pData->sock, (char*)msg);
/* something is very wrong */
if (rc == -1) {
errmsg.LogError(0, NO_ERRCODE, "omczmq: send of %s failed: %s",
msg, zmq_strerror(errno));
ABORT_FINALIZE(RS_RET_ERR);
}
if (*delimiter == 0) {
break;
}
list = delimiter + 1;
topic = zlist_next(pData->topics);
}
} else {
/* send the log line */
}
/* otherwise do a normal send */
else {
int rc = zstr_send(pData->sock, (char*)msg);
/* something is very wrong */
if (rc == -1) {
errmsg.LogError(0, NO_ERRCODE, "omczmq: send of %s failed: %s",
msg, zmq_strerror(errno));
ABORT_FINALIZE(RS_RET_ERR);
if (rc != 0) {
pData->sendError = true;
ABORT_FINALIZE(RS_RET_SUSPENDED);
}
}
finalize_it:
@ -286,16 +331,22 @@ static inline void
setInstParamDefaults(instanceData* pData) {
pData->sockEndpoints = NULL;
pData->sock = NULL;
pData->sendError = false;
pData->serverish = false;
pData->clientCert = NULL;
pData->serverCert = NULL;
pData->tplName = NULL;
pData->sockType = -1;
pData->sendTimeout = -1;
pData->topics = NULL;
pData->authActor = NULL;
pData->beaconActor = NULL;
pData->beaconport = 0;
pData->authType = NULL;
pData->clientCertPath = NULL;
pData->serverCertPath = NULL;
pData->topicList = NULL;
pData->topicFrame = true;
}
@ -324,6 +375,8 @@ ENDdbgPrintInstInfo
BEGINfreeInstance
CODESTARTfreeInstance
if (pData->topics != NULL)
zlist_destroy(&pData->topics);
zsock_destroy(&pData->sock);
zactor_destroy(&pData->authActor);
zactor_destroy(&pData->beaconActor);
@ -345,19 +398,24 @@ ENDfreeWrkrInstance
BEGINtryResume
instanceData *pData;
CODESTARTtryResume
pthread_mutex_lock(&mutDoAct);
if(NULL == pWrkrData->pData->sock) {
iRet = initCZMQ(pWrkrData->pData);
}
pData = pWrkrData->pData;
DBGPRINTF("omczmq: trying to resume...\n");
zsock_destroy(&pData->sock);
zactor_destroy(&pData->beaconActor);
zactor_destroy(&pData->authActor);
iRet = initCZMQ(pData);
pthread_mutex_unlock(&mutDoAct);
ENDtryResume
BEGINdoAction
instanceData *pData = pWrkrData->pData;
instanceData *pData;
CODESTARTdoAction
pthread_mutex_lock(&mutDoAct);
pData = pWrkrData->pData;
iRet = outputCZMQ(ppString[0], pData);
pthread_mutex_unlock(&mutDoAct);
ENDdoAction
@ -375,45 +433,66 @@ CODESTARTnewActInst
setInstParamDefaults(pData);
CODE_STD_STRING_REQUESTnewActInst(1)
/* handle our configuration arguments
* - endpoints - required
* - socktype - required
* - beacon - optional
* - beaconport - required if beacon is set
* - authtype - optional and NULL == no auth
* - clientcertpath - required if authtype is CURVESERVER or CURVECLIENT
* - servercertpath - required if authtype is CURVESERVER or CURVECLIENT
* - template - optional defaults to RSYSLOG_ForwardFormat
* - topics - optional
*/
/* Handle options from the configuration */
/* ------------------------------------- */
for (i = 0; i < actpblk.nParams; ++i) {
if (!pvals[i].bUsed) {
continue;
}
/* get the socket endpoints to use */
if (!strcmp(actpblk.descr[i].name, "endpoints")) {
pData->sockEndpoints = es_str2cstr(pvals[i].val.d.estr, NULL);
}
/* get the output template to use */
else if (!strcmp(actpblk.descr[i].name, "template")) {
pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
}
/* get the socket type */
}
else if (!strcmp(actpblk.descr[i].name, "sendtimeout")) {
pData->sendTimeout = atoi(es_str2cstr(pvals[i].val.d.estr, NULL));
}
else if (!strcmp(actpblk.descr[i].name, "socktype")){
char *stringType = es_str2cstr(pvals[i].val.d.estr, NULL);
if (!strcmp("PUB", stringType)) {
pData->sockType = ZMQ_PUB;
if(stringType != NULL){
if (!strcmp("PUB", stringType)) {
pData->sockType = ZMQ_PUB;
}
else if (!strcmp("PUSH", stringType)) {
pData->sockType = ZMQ_PUSH;
}
else if (!strcmp("DEALER", stringType)) {
pData->sockType = ZMQ_DEALER;
}
else {
free(stringType);
errmsg.LogError(0, RS_RET_CONFIG_ERROR,
"omczmq: invalid socktype");
ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
}
free(stringType);
}
else if (!strcmp("PUSH", stringType)) {
pData->sockType = ZMQ_PUSH;
}
else {
errmsg.LogError(0, RS_RET_CONFIG_ERROR,
"omczmq: invalid socktype");
ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
else{
errmsg.LogError(0, RS_RET_OUT_OF_MEMORY,
"omczmq: out of memory");
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
}
/* get the authentication type to use */
else if (!strcmp(actpblk.descr[i].name, "authtype")) {
pData->authType = es_str2cstr(pvals[i].val.d.estr, NULL);
/* make sure defined type is supported */
/* auth must be NULL, CURVESERVER or CURVECLIENT */
if ((pData->authType != NULL) &&
strcmp("CURVESERVER", pData->authType) &&
strcmp("CURVECLIENT", pData->authType))
@ -425,28 +504,27 @@ CODESTARTnewActInst
ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
}
}
/* get client cert argument */
else if (!strcmp(actpblk.descr[i].name, "clientcertpath")) {
pData->clientCertPath = es_str2cstr(pvals[i].val.d.estr, NULL);
}
/* get server cert argument */
else if (!strcmp(actpblk.descr[i].name, "servercertpath")) {
pData->serverCertPath = es_str2cstr(pvals[i].val.d.estr, NULL);
}
/* get beacon argument */
else if (!strcmp(actpblk.descr[i].name, "beacon")) {
pData->beacon = es_str2cstr(pvals[i].val.d.estr, NULL);
}
/* get beacon port */
else if (!strcmp(actpblk.descr[i].name, "beaconport")) {
pData->beaconport = atoi(es_str2cstr(pvals[i].val.d.estr, NULL));
}
/* get the subscription topics */
else if (!strcmp(actpblk.descr[i].name, "topicframe")) {
int tframe = atoi(es_str2cstr(pvals[i].val.d.estr, NULL));
if (tframe == 1) {
pData->topicFrame = true;
}
else {
pData->topicFrame = false;
}
}
else if(!strcmp(actpblk.descr[i].name, "topics")) {
if (pData->sockType != ZMQ_PUB) {
errmsg.LogError(0, RS_RET_CONFIG_ERROR,
@ -454,38 +532,62 @@ CODESTARTnewActInst
ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
}
pData->topicList = es_str2cstr(pvals[i].val.d.estr, NULL);
}
// create a list of topics
pData->topics = zlist_new();
char *topics = es_str2cstr(pvals[i].val.d.estr, NULL);
char *topics_org = topics;
char topic[256];
if(topics == NULL){
errmsg.LogError(0, RS_RET_OUT_OF_MEMORY,
"out of memory");
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
while (*topics) {
char *delimiter = strchr(topics, ',');
if (!delimiter) {
delimiter = topics + strlen(topics);
}
if (delimiter - topics > 255) {
errmsg.LogError(0, RS_RET_CONFIG_ERROR,
"topics must be under 256 characters");
free(topics_org);
ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
}
memcpy (topic, topics, delimiter - topics);
topic[delimiter-topics] = 0;
char *current_topic = strdup(topic);
zlist_append (pData->topics, current_topic);
if (*delimiter == 0) {
break;
}
topics = delimiter + 1;
}
free(topics_org);
/* the config has a bad option */
}
else {
errmsg.LogError(0, NO_ERRCODE, "omczmq: %s is not a valid option",
errmsg.LogError(0, NO_ERRCODE,
"omczmq: config error - '%s' is not a valid option",
actpblk.descr[i].name);
ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
}
}
/* if we don't have a template name,
* use the default RSYSLOG_ForwardFormat template */
/* Defaults and sanity checking */
/* ----------------------------- */
if (pData->tplName == NULL) {
CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup("RSYSLOG_ForwardFormat"),
OMSR_NO_RQD_TPL_OPTS));
}
/* use the requested template */
else {
CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)pData->tplName, OMSR_NO_RQD_TPL_OPTS));
}
/* error if no socket endpoints are defined */
if (NULL == pData->sockEndpoints) {
errmsg.LogError(0, RS_RET_CONFIG_ERROR, "omczmq: sockEndpoint required");
ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
}
/* error if no socket type is defined */
if (pData->sockType == -1) {
errmsg.LogError(0, RS_RET_CONFIG_ERROR, "omczmq: socktype required");
if ((pData->beacon != NULL) && (pData->beaconport == 0)) {
errmsg.LogError(0, NO_ERRCODE,
"omczmq: config error - beaconport is required if beacon is set");
ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
}

View File

@ -43,11 +43,8 @@
#include "statsobj.h"
#include "unicode-helper.h"
// output module
MODULE_TYPE_OUTPUT
// do not need to be kept dynamically linked
MODULE_TYPE_NOKEEP
// module name
MODULE_CNFNAME("omhttpfs")
/* internal structures
@ -133,9 +130,7 @@ static struct cnfparamdescr actpdescr[] = {
{ "host", eCmdHdlrGetWord, 0 },
{ "port", eCmdHdlrInt, 0 },
{ "user", eCmdHdlrGetWord, 0 },
//{ "ip", eCmdHdlrGetWord, 0 },
{ "https", eCmdHdlrBinary, 0 },
//{ "timeout", eCmdHdlrInt, 0 },
{ "file", eCmdHdlrGetWord, CNFPARAM_REQUIRED },
{ "isdynfile", eCmdHdlrBinary, 0 },
{ "template", eCmdHdlrGetWord, 0 },
@ -167,12 +162,12 @@ httpfs_init_curl(wrkrInstanceData_t *pWrkrData, instanceData *pData)
if (pData->https) {
DBGPRINTF("%s(): Enable HTTPS\n", __FUNCTION__);
// for ssl
/* for ssl */
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
}
} else {
// LOG
/* LOG */
errmsg.LogError(0, RS_RET_OBJ_CREATION_FAILED, "omhttpfs: failed to init cURL\n");
return RS_RET_OBJ_CREATION_FAILED;
@ -195,10 +190,8 @@ httpfs_init_curl(wrkrInstanceData_t *pWrkrData, instanceData *pData)
static rsRetVal
httpfs_build_url(wrkrInstanceData_t *pWrkrData, char* op, es_str_t** url_buf)
{
//
*url_buf = es_newStr(HTTPFS_URL_BUFFER_LENGTH);
// scheme
if (pWrkrData->pData->https) {
es_addBuf(url_buf, "https://", sizeof("https://")-1);
} else {
@ -349,15 +342,24 @@ static size_t
httpfs_curl_result_callback(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
char *newreply = NULL;
wrkrInstanceData_t *mem = (wrkrInstanceData_t *)userp;
mem->reply = realloc(mem->reply, mem->replyLen + realsize + 1);
if(mem->reply == NULL) {
newreply = realloc(mem->reply, mem->replyLen + realsize + 1);
if (newreply == NULL) {
/* out of memory! */
printf("not enough memory (realloc returned NULL)\n");
dbgprintf("not enough memory (realloc returned NULL)\n");
if (mem->reply != NULL)
free(mem->reply);
mem->reply = NULL;
mem->replyLen = 0;
return 0;
}
mem->reply = newreply;
memcpy(&(mem->reply[mem->replyLen]), contents, realsize);
mem->replyLen += realsize;
mem->reply[mem->replyLen] = 0;
@ -427,7 +429,9 @@ int httpfs_permission_to_string(int permission, char* perm_string)
*/
static rsRetVal
httpfs_parse_exception(char* buf, int length, httpfs_json_remote_exception* jre)
{
{
DEFiRet;
if (!length) {
return RS_RET_JSON_PARSE_ERR;
}
@ -438,29 +442,43 @@ httpfs_parse_exception(char* buf, int length, httpfs_json_remote_exception* jre)
struct json_object *json;
json = json_tokener_parse_ex(jt, buf, length);
if (!json_object_is_type(json, json_type_object)) {
// not an object ?
return RS_RET_JSON_PARSE_ERR;
ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR);
}
if (!json_object_object_get_ex(json, "RemoteException", &json)) {
return RS_RET_JSON_PARSE_ERR;
if (!RS_json_object_object_get_ex(json, "RemoteException", &json)) {
ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR);
}
struct json_object *jobj;
memset(jre, 0, sizeof(*jre));
json_object_object_get_ex(json, "javaClassName", &jobj);
strncpy(jre->class, (char*) json_object_get_string(jobj), json_object_get_string_len(jobj));
const char *str;
size_t len;
json_object_object_get_ex(json, "exception", &jobj);
strncpy(jre->exception, (char*) json_object_get_string(jobj), json_object_get_string_len(jobj));
RS_json_object_object_get_ex(json, "javaClassName", &jobj);
str = json_object_get_string(jobj);
len = strlen(str);
strncpy(jre->class, str, len);
json_object_object_get_ex(json, "message", &jobj);
strncpy(jre->message, (char*) json_object_get_string(jobj), json_object_get_string_len(jobj));
RS_json_object_object_get_ex(json, "exception", &jobj);
str = json_object_get_string(jobj);
len = strlen(str);
strncpy(jre->exception, str, len);
RS_json_object_object_get_ex(json, "message", &jobj);
str = json_object_get_string(jobj);
len = strlen(str);
strncpy(jre->message, str, len);
finalize_it:
if(jt != NULL)
json_tokener_free(jt);
if(json != NULL)
json_object_put(json);
RETiRet;
}
return RS_RET_OK;
}
#if 0
/**
@ -514,7 +532,7 @@ HTTPFS_CURL_VARS_RELEASE
static rsRetVal
httpfs_create_file(wrkrInstanceData_t *pWrkrData, uchar* buf)
{
// httpfs.create automatically create folders, no mkdirs needed.
/* httpfs.create automatically create folders, no mkdirs needed. */
/*
curl -b /tmp/c.tmp -c /tmp/c.tmp -d 'aaaaabbbbb' -i -H 'Content-Type: application/octet-stream' -X PUT \
@ -544,7 +562,6 @@ HTTPFS_CURL_EXEC
int success = 0;
if (response_code == 201) {
//&& !strncmp(result->buf, HTTPFS_JSON_BOOLEAN_TRUE, strlen(HTTPFS_JSON_BOOLEAN_TRUE))) {
success = 1;
}
@ -590,7 +607,7 @@ HTTPFS_CURL_EXEC
if (response_code == 200) {
success = 1;
} else if (response_code == 404) {
// TODO: 404 ?
/* TODO: 404 ? */
}
HTTPFS_CURL_VARS_RELEASE
@ -627,11 +644,11 @@ HTTPFS_CURL_EXEC
if (response_code == 200) {
success = 1;
} else if (response_code == 404) {
// TODO: 404 ?
/* TODO: 404 ? */
}
// TODO: not success?
/* TODO: not success? */
HTTPFS_CURL_VARS_RELEASE
if (success) {
@ -672,7 +689,7 @@ httpfs_log(wrkrInstanceData_t *pWrkrData, uchar* buf)
curl_easy_getinfo(pWrkrData->curl, CURLINFO_RESPONSE_CODE, &response_code);
if (response_code != 404) {
// todo: log error
/* TODO: log error */
DBGPRINTF("omhttpfs: Append fail HTTP %ld: %s\n", response_code, pWrkrData->file);
return RS_RET_FALSE;
}
@ -691,21 +708,19 @@ httpfs_log(wrkrInstanceData_t *pWrkrData, uchar* buf)
if (response_code == 500) {
DBGPRINTF("omhttpfs: Create file failed HTTP %ld: %s\n", response_code, pWrkrData->file);
// retry
httpfs_parse_exception(pWrkrData->reply, pWrkrData->replyLen, &jre);
if (!strncmp(jre.exception, HTTPFS_FILEALREADYEXISTSEXCEPTION, strlen(HTTPFS_FILEALREADYEXISTSEXCEPTION))) {
// file exists, go to append
/* file exists, go to append */
DBGPRINTF("omhttpfs: File already exists, append again: %s\n", pWrkrData->file);
iRet = httpfs_append_file(pWrkrData, buf);
if (iRet == RS_RET_OK) {
DBGPRINTF("omhttpfs: Re-Append success: %s\n", pWrkrData->file);
//free(&jre);
return RS_RET_OK;
} else {
DBGPRINTF("omhttpfs: Re-Append failed: %s\n", pWrkrData->file);
// error
// exit
/* error
exit */
}
} else {
@ -715,7 +730,6 @@ httpfs_log(wrkrInstanceData_t *pWrkrData, uchar* buf)
DBGPRINTF("omhttpfs: Create file failed: %s %s\n", pWrkrData->file, pWrkrData->reply);
}
// TODO: ...
return RS_RET_FALSE;
}
@ -734,7 +748,6 @@ ENDcreateInstance
BEGINcreateWrkrInstance
CODESTARTcreateWrkrInstance
DBGPRINTF("omhttpfs: createWrkrInstance\n");
// init worker resource
pWrkrData->curl = NULL;
CHKiRet(httpfs_init_curl(pWrkrData, pWrkrData->pData));
finalize_it:
@ -783,7 +796,7 @@ ENDdbgPrintInstInfo
BEGINtryResume
CODESTARTtryResume
DBGPRINTF("omhttpfs: tryResume called\n");
// TODO: test networking
/* TODO: test networking */
iRet = RS_RET_OK;
ENDtryResume
@ -793,14 +806,14 @@ ENDtryResume
BEGINdoAction
CODESTARTdoAction
DBGPRINTF("omhttpfs: doAction\n");
// dynamic file name
/* dynamic file name */
if (pWrkrData->pData->isDynFile) {
pWrkrData->file = ustrdup(ppString[1]);
} else {
pWrkrData->file = ustrdup(pWrkrData->pData->file);
}
// ppString[0] -> log content
/* ppString[0] -> log content */
iRet = httpfs_log(pWrkrData, ppString[0]);
if(iRet != RS_RET_OK) {
@ -849,7 +862,7 @@ CODESTARTnewActInst
if(!strcmp(actpblk.descr[i].name, "host")) {
pData->host = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if(!strcmp(actpblk.descr[i].name, "port")) {
pData->port = (int) pvals[i].val.d.n, NULL;
pData->port = (int) pvals[i].val.d.n;
} else if(!strcmp(actpblk.descr[i].name, "user")) {
pData->user = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
@ -868,16 +881,13 @@ CODESTARTnewActInst
DBGPRINTF("omhttpfs: program error, non-handled param '%s'\n", actpblk.descr[i].name);
}
}
// empty user
if(pData->user == NULL || pData->user[0] == '\0') {
pData->user = ustrdup((uchar*) OMHTTPFS_DEFAULT_USER);
}
// empty host
if(pData->host == NULL || pData->host[0] == '\0') {
pData->host = ustrdup((uchar*) OMHTTPFS_DEFAULT_HOST);
}
// register template for file name
if (pData->isDynFile) {
CODE_STD_STRING_REQUESTparseSelectorAct(2)
@ -886,7 +896,6 @@ CODESTARTnewActInst
CODE_STD_STRING_REQUESTparseSelectorAct(1)
}
// register template for log content
tplToUse = ustrdup((pData->tplName == NULL) ? (uchar* ) "RSYSLOG_FileFormat" : pData->tplName);
CHKiRet(OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_NO_RQD_TPL_OPTS));
@ -897,8 +906,6 @@ ENDnewActInst
BEGINparseSelectorAct
CODESTARTparseSelectorAct
// this is for the legacy configuration format
// forget it
ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
CODE_STD_FINALIZERparseSelectorAct
ENDparseSelectorAct

View File

@ -41,6 +41,9 @@
#include "cfsysline.h"
#include <amqp.h>
#include <amqp_tcp_socket.h>
#define RABBITMQ_CHANNEL 1
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
@ -69,9 +72,13 @@ typedef struct _instanceData {
uchar *vhost;
uchar *user;
uchar *password;
uchar *exchange;
char *exchange;
uchar *routing_key;
uchar *tplName;
char *exchange_type;
int durable;
int auto_delete;
int delivery_mode;
} instanceData;
typedef struct wrkrInstanceData {
@ -89,7 +96,11 @@ static struct cnfparamdescr actpdescr[] = {
{ "password", eCmdHdlrGetWord, 0 },
{ "exchange", eCmdHdlrGetWord, 0 },
{ "routing_key", eCmdHdlrGetWord, 0 },
{ "template", eCmdHdlrGetWord, 0 }
{ "template", eCmdHdlrGetWord, 0 },
{ "exchange_type", eCmdHdlrGetWord, 0},
{ "durable", eCmdHdlrNonNegInt, 0},
{ "auto_delete", eCmdHdlrNonNegInt, 0},
{ "delivery_mode", eCmdHdlrNonNegInt, 0}
};
static struct cnfparamblk actpblk =
{
@ -108,9 +119,9 @@ die_on_error(int x, char const *context)
int retVal = 0; // false
if (x < 0) {
char *errstr = amqp_error_string(-x);
const char *errstr = amqp_error_string2(-x);
errmsg.LogError(0, RS_RET_ERR, "omrabbitmq: %s: %s", context, errstr);
free(errstr);
retVal = 1; // true
}
@ -136,7 +147,7 @@ die_on_amqp_error(amqp_rpc_reply_t x, char const *context)
break;
case AMQP_RESPONSE_LIBRARY_EXCEPTION:
errmsg.LogError(0, RS_RET_ERR, "omrabbitmq: %s: %s", context, amqp_error_string(x.library_error));
errmsg.LogError(0, RS_RET_ERR, "omrabbitmq: %s: %s", context, amqp_error_string2(x.library_error));
break;
case AMQP_RESPONSE_SERVER_EXCEPTION:
@ -195,19 +206,26 @@ closeAMQPConnection(instanceData *pData)
static rsRetVal
initRabbitMQ(instanceData *pData)
{
int sockfd;
amqp_socket_t *asocket;
amqp_exchange_declare_t edReq;
DEFiRet;
DBGPRINTF("omrabbitmq: trying connect to '%s' at port %d\n", pData->host, pData->port);
pData->conn = amqp_new_connection();
if (die_on_error(sockfd = amqp_open_socket((char*) pData->host, pData->port), "Opening socket")) {
asocket = amqp_tcp_socket_new(pData->conn);
if (!asocket) {
errmsg.LogError(0, RS_RET_ERR, "omrabbitmq: Error allocating tcp socket");
pData->conn = NULL;
ABORT_FINALIZE(RS_RET_SUSPENDED);
}
amqp_set_sockfd(pData->conn, sockfd);
if (die_on_error(amqp_socket_open(asocket, (char*) pData->host, pData->port), "Opening socket")) {
pData->conn = NULL;
ABORT_FINALIZE(RS_RET_SUSPENDED);
}
if (die_on_amqp_error(amqp_login(pData->conn, (char*) pData->vhost, 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, pData->user, pData->password),
"Logging in")) {
@ -215,13 +233,30 @@ initRabbitMQ(instanceData *pData)
ABORT_FINALIZE(RS_RET_SUSPENDED);
}
amqp_channel_open(pData->conn, 1);
amqp_channel_open(pData->conn, RABBITMQ_CHANNEL);
if (die_on_amqp_error(amqp_get_rpc_reply(pData->conn), "Opening channel")) {
pData->conn = NULL;
ABORT_FINALIZE(RS_RET_SUSPENDED);
}
if(pData->exchange_type != NULL) {
edReq.ticket = 0;
edReq.exchange = amqp_cstring_bytes(pData->exchange);
edReq.type = amqp_cstring_bytes(pData->exchange_type);
edReq.passive = 0;
edReq.durable = pData->durable;
edReq.auto_delete = pData->auto_delete;
edReq.internal = 0;
edReq.nowait = 0;
edReq.arguments = amqp_empty_table;
amqp_simple_rpc_decoded(pData->conn, RABBITMQ_CHANNEL, AMQP_EXCHANGE_DECLARE_METHOD, AMQP_EXCHANGE_DECLARE_OK_METHOD, &edReq);
if(die_on_amqp_error(amqp_get_rpc_reply(pData->conn), "Declaring exchange")) {
pData->conn = NULL;
ABORT_FINALIZE(RS_RET_SUSPENDED);
}
}
finalize_it:
RETiRet;
}
@ -262,6 +297,7 @@ CODESTARTfreeInstance
free(pData->exchange);
free(pData->routing_key);
free(pData->tplName);
free(pData->exchange_type);
ENDfreeInstance
@ -281,6 +317,10 @@ CODESTARTdbgPrintInstInfo
dbgprintf("\texchange='%s'\n", pData->exchange);
dbgprintf("\trouting_key='%s'\n", pData->routing_key);
dbgprintf("\ttemplate='%s'\n", pData->tplName);
dbgprintf("\texchange_type='%s'\n", pData->exchange_type);
dbgprintf("\tauto_delete=%d\n", pData->auto_delete);
dbgprintf("\tdurable=%d\n", pData->durable);
dbgprintf("\tdelivery_mode=%d\n", pData->delivery_mode);
ENDdbgPrintInstInfo
@ -341,7 +381,7 @@ CODESTARTdoAction
body_bytes = amqp_cstring_bytes((char *)ppString[0]);
if (die_on_error(amqp_basic_publish(pData->conn, 1,
if (die_on_error(amqp_basic_publish(pData->conn, RABBITMQ_CHANNEL,
cstring_bytes((char *) pData->exchange),
cstring_bytes((char *) pData->routing_key),
0, 0, &pData->props, body_bytes), "amqp_basic_publish")) {
@ -365,6 +405,10 @@ setInstParamDefaults(instanceData *pData)
pData->exchange = NULL;
pData->routing_key = NULL;
pData->tplName = NULL;
pData->exchange_type = NULL;
pData->auto_delete = 0;
pData->durable = 0;
pData->delivery_mode = 2;
}
@ -396,11 +440,19 @@ CODESTARTnewActInst
} else if (!strcmp(actpblk.descr[i].name, "password")) {
pData->password = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if (!strcmp(actpblk.descr[i].name, "exchange")) {
pData->exchange = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
pData->exchange = es_str2cstr(pvals[i].val.d.estr, NULL);
} else if (!strcmp(actpblk.descr[i].name, "routing_key")) {
pData->routing_key = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if (!strcmp(actpblk.descr[i].name, "template")) {
pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if (!strcmp(actpblk.descr[i].name, "exchange_type")) {
pData->exchange_type = es_str2cstr(pvals[i].val.d.estr, NULL);
} else if (!strcmp(actpblk.descr[i].name, "auto_delete")) {
pData->auto_delete = (int) pvals[i].val.d.n;
} else if (!strcmp(actpblk.descr[i].name, "durable")) {
pData->durable = (int) pvals[i].val.d.n;
} else if (!strcmp(actpblk.descr[i].name, "delivery_mode")) {
pData->delivery_mode = (int) pvals[i].val.d.n;
} else {
dbgprintf("omrabbitmq: program error, non-handled param '%s'\n", actpblk.descr[i].name);
}
@ -439,7 +491,7 @@ CODESTARTnewActInst
// RabbitMQ properties initialization
memset(&pData->props, 0, sizeof pData->props);
pData->props._flags = AMQP_BASIC_DELIVERY_MODE_FLAG;
pData->props.delivery_mode = 2; /* persistent delivery mode */
pData->props.delivery_mode = pData->delivery_mode;
pData->props._flags |= AMQP_BASIC_CONTENT_TYPE_FLAG;
pData->props.content_type = amqp_cstring_bytes("application/json");

View File

@ -41,7 +41,6 @@
MODULE_TYPE_PARSER
MODULE_TYPE_NOKEEP
MODULE_CNFNAME("pmaixforwardedfrom")
PARSER_NAME("rsyslog.aixforwardedfrom")
/* internal structures
@ -83,11 +82,9 @@ CODESTARTparse
--lenMsg;
++p2parse;
}
dbgprintf("pmaixforwardedfrom: msg to look at: [%d]'%s'\n", lenMsg, p2parse);
if((unsigned) lenMsg < 42) {
/* too short, can not be "our" message */
/* minimum message, 16 character timestamp, 'Message forwarded from ", 1 character name, ': '*/
dbgprintf("msg too short!\n");
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
@ -97,7 +94,7 @@ dbgprintf("msg too short!\n");
/* if there is the string "Message forwarded from " were the hostname should be */
if(strncasecmp((char*) p2parse, OpeningText, sizeof(OpeningText)-1) != 0) {
/* wrong opening text */
dbgprintf("not a AIX message forwarded from mangled log!\n");
DBGPRINTF("not a AIX message forwarded from mangled log!\n");
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
/* bump the message portion up by 23 characters to overwrite the "Message forwarded from " with the hostname */
@ -113,7 +110,7 @@ dbgprintf("not a AIX message forwarded from mangled log!\n");
++p2parse;
}
if (lenMsg && *p2parse != ':') {
dbgprintf("not a AIX message forwarded from mangled log but similar enough that the preamble has been removed\n");
DBGPRINTF("not a AIX message forwarded from mangled log but similar enough that the preamble has been removed\n");
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
/* bump the message portion up by one character to overwrite the extra : */

View File

@ -82,11 +82,9 @@ CODESTARTparse
--lenMsg;
++p2parse;
}
dbgprintf("pmcisconames: msg to look at: [%d]'%s'\n", lenMsg, p2parse);
if((unsigned) lenMsg < 34) {
/* too short, can not be "our" message */
/* minimum message, 16 character timestamp, 1 character name, ' : %ASA-1-000000: '*/
dbgprintf("msg too short!\n");
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
/* check if the timestamp is a 16 character or 21 character timestamp
@ -123,7 +121,7 @@ dbgprintf("msg too short!\n");
/* if the syslog tag is : and the next thing starts with a % assume that this is a mangled cisco log and fix it */
if(strncasecmp((char*) p2parse, OpeningText, sizeof(OpeningText)-1) != 0) {
/* wrong opening text */
dbgprintf("not a cisco name mangled log!\n");
DBGPRINTF("not a cisco name mangled log!\n");
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
/* bump the message portion up by two characters to overwrite the extra : */

View File

@ -0,0 +1,8 @@
pkglib_LTLIBRARIES = pmpanngfw.la
pmpanngfw_la_SOURCES = pmpanngfw.c
pmpanngfw_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
pmpanngfw_la_LDFLAGS = -module -avoid-version
pmpanngfw_la_LIBADD =
EXTRA_DIST =

View File

@ -0,0 +1,87 @@
# pmpanngfw
Module to detect and transform PAN-OS NGFW logs into a format compatible with mmnormalize
## How it works
Original log:
Apr 10 02:48:29 1,2012/04/10 02:48:29,001606001116,THREAT,url,1,2012/04/10 02:48:28,##IP##,##IP##,##IP##,##IP##,rule1,counselor,,facebook- base,vsys1,trust,untrust,ethernet1/2,ethernet1/1,forwardAll,2012/04/10 02:48:28,27555,1,8450,80,0,0,0x208000,tcp,alert,"www.facebook. com/ajax/pagelet/generic.php/ProfileTimelineSectionPagelet?__a=1&ajaxpipe=1&ajaxpipe_token=AXgw4BUd5yCuD2rQ&data={""profile_id"":603261604,""start"":1333263600,""end"":1335855599,""query_type"":5,""page_index"":1,""section_container_id"":""ucp7d6_26"",""section_pagelet_id"":""pagelet_timeline_recent"",""unit_container_id"":""ucp7d6_25"",""current_scrubber_key"":""recent"",""time_cutoff"":null,""buffer"":1300,""require_click"":false,""num_visible_units"":5,""remove_dupes"":true}&__user=857280013&__adt=3&__att=iframe",(9999),social-networking,informational,client-to-server,0,0x0,192.168.0.0-192.168.255.255,United States,0,text/html
Transformed:
Apr 10 02:48:29 1<tab>2012/04/10 02:48:29<tab>001606001116<tab>THREAT<tab>url<tab>1<tab>2012/04/10 02:48:28<tab>##IP##<tab>##IP##<tab>##IP##<tab>##IP##<tab>rule1<tab>counselor<tab><tab>facebook-base<tab>vsys1<tab>trust<tab>untrust<tab>ethernet1/2<tab>ethernet1/1<tab>forwardAll 2012/04/10 02:48:28 27555<tab>1<tab>8450<tab>80<tab>0<tab>0x208000<tab>tcp alert<tab>www.facebook.com/ajax/pagelet/generic.php/ProfileTimelineSectionPagelet?__a=1&ajaxpipe=1&ajaxpipe_token=AXgw4BUd5yCuD2rQ&data={"profile_id":603261604,"start":1333263600,"end":1335855599,"query_type":5,"page_index":1,"section_container_id":"ucp7d6_26","section_pagelet_id":"pagelet_timeline_recent","unit_container_id":"ucp7d6_25","current_scrubber_key":"recent","time_cutoff":null,"buffer":1300,"require_click":false,"num_visible_units":5,"remove_dupes":true}&__user=857280013&__adt=3&__att=iframe<tab>(9999)<tab>social-networking<tab>informational<tab>client-to-server<tab>0<tab>0x0<tab>192.168.0.0-192.168.255.255<tab>United States<tab>0<tab>text/html
## How to compile
$ autoreconf -fvi
$ ./configure --enable-pmpanngfw
$ cd contrib/pmpanngfw/
$ make
The resulting plugin should be found in contrib/pmpanngfw/.libs/
## Example config
module(load="imtcp")
module(load="pmpanngfw")
module(load="mmnormalize")
module(load="omrabbitmq")
template(name="csv" type="list") {
property(name="$!src_ip" format="csv")
constant(value=",")
property(name="$!dest_ip" format="csv")
constant(value=",")
property(name="$!url")
constant(value="\n")
}
$template alljson,"%$!all-json%\n"
template(name="mmeld_json" type="list") {
constant(value="{")
property(outname="@timestamp" name="timestamp" format="jsonf" dateFormat="rfc3339")
constant(value=",")
property(outname="@source_host" name="source" format="jsonf")
constant(value=",")
property(outname="@message" name="msg" format="jsonf")
constant(value=",")
property(outname="@timegenerated" name="timegenerated" format="jsonf" dateFormat="rfc3339")
constant(value=",")
property(outname="@timereported" name="timereported" format="jsonf" dateFormat="rfc3339")
constant(value=",")
property(outname="src_ip" name="$!src_ip" format="jsonf")
constant(value=",")
property(outname="dest_ip" name="$!dest_ip" format="jsonf")
constant(value=",")
property(outname="url" name="$!url" format="jsonf")
constant(value=",")
property(outname="tags" name="$!event.tags" format="jsonf")
constant(value="}")
constant(value="\n")
}
ruleset(name="pan-ngfw" parser=["rsyslog.panngfw", "rsyslog.rfc5424", "rsyslog.rfc3164"]) {
action(type="mmnormalize" rulebase="palo_alto_networks.rb" userawmsg="on")
if strlen($!unparsed-data) == 0 then {
if $!log_subtype == "url" then set $!url = $!misc;
*.* action(type="omrabbitmq"
host="localhost"
virtual_host="/"
user="guest"
password="guest"
exchange="mmeld-syslog"
routing_key=""
exchange_type="fanout"
template="alljson")
}
*.* stop
}
input(type="imtcp" port="13514" ruleset="pan-ngfw")
## mmnormalize rulebase
See https://gist.github.com/jtschichold/87f59b99d98c8eac1da5

View File

@ -0,0 +1,297 @@
/* pmpanngfw.c
*
* this detects logs sent by Palo Alto Networks NGFW and transforms CSV into tab-separated fields
* for handling inside the mmnormalize
*
* Example: foo,"bar,""baz""",qux becomes foo<TAB>bar,"baz"<TAB>qux
*
* created 2010-12-13 by Luigi Mori (lmori@paloaltonetworks.com) based on pmsnare
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* -or-
* see COPYING.ASL20 in the source distribution
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "config.h"
#include "rsyslog.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "conf.h"
#include "syslogd-types.h"
#include "template.h"
#include "msg.h"
#include "module-template.h"
#include "glbl.h"
#include "errmsg.h"
#include "parser.h"
#include "datetime.h"
#include "unicode-helper.h"
#include "typedefs.h"
MODULE_TYPE_PARSER
MODULE_TYPE_NOKEEP
PARSER_NAME("rsyslog.panngfw")
/* internal structures
*/
DEF_PMOD_STATIC_DATA
DEFobjCurrIf(errmsg)
DEFobjCurrIf(glbl)
DEFobjCurrIf(parser)
DEFobjCurrIf(datetime)
/* static data */
static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */
typedef struct {
uint64 value;
uint64 mask;
} log_type_t;
const log_type_t log_types[] = {
{ 0x002c544145524854ULL, 0x00FFFFFFFFFFFFFFULL }, /* THREAT, */
{ 0x2c43494646415254ULL, 0xFFFFFFFFFFFFFFFFULL }, /* TRAFFIC, */
{ 0x002c4d4554535953ULL, 0x00FFFFFFFFFFFFFFULL }, /* CONFIG */
{ 0x002c4749464e4f43ULL, 0x00FFFFFFFFFFFFFFULL } /* SYSTEM */
};
#define NUM_LOG_TYPES (sizeof(log_types)/sizeof(log_type_t))
BEGINisCompatibleWithFeature
CODESTARTisCompatibleWithFeature
if(eFeat == sFEATUREAutomaticSanitazion)
iRet = RS_RET_OK;
if(eFeat == sFEATUREAutomaticPRIParsing)
iRet = RS_RET_OK;
ENDisCompatibleWithFeature
BEGINparse
uchar *p2parse;
uchar *p2target;
uchar *msgend;
int lenMsg, lenDelta;
int state;
int num_fields = 4;
uchar *f3_commas[3];
int cur_comma = 0;
uint64 log_type;
int j;
CODESTARTparse
#define CSV_DELIMITER '\t'
#define STATE_FIELD_START 0
#define STATE_IN_FIELD 1
#define STATE_IN_QUOTE 2
#define STATE_IN_QUOTE_QUOTE 3
state = STATE_FIELD_START;
dbgprintf("Message will now be parsed by fix Palo Alto Networks NGFW parser.\n");
assert(pMsg != NULL);
assert(pMsg->pszRawMsg != NULL);
lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI; /* note: offAfterPRI is already the number of PRI chars (do not add one!) */
p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */
msgend = p2parse+lenMsg;
dbgprintf("pmpanngfw: msg to look at: [%d]'%s'\n", lenMsg, p2parse);
/* pass the first 3 fields */
while(p2parse < msgend) {
if (*p2parse == ',') {
f3_commas[cur_comma] = p2parse;
if (cur_comma == 2) {
break;
}
cur_comma++;
}
p2parse++;
}
/* check number of fields detected so far */
if (cur_comma != 2) {
dbgprintf("not a PAN-OS syslog message: first 3 fields not found\n");
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
/* check msg length */
p2parse++;
if ((p2parse > msgend) || ((msgend - p2parse) < sizeof(uint64))) {
dbgprintf("not a PAN-OS syslog message: too short\n");
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
/* check log type */
log_type = *((uint64 *)p2parse);
for(j = 0; j < NUM_LOG_TYPES; j++) {
if ((log_type & log_types[j].mask) == log_types[j].value)
break;
}
if (j == NUM_LOG_TYPES) {
dbgprintf("not a PAN-OS syslog message, log type: %llx\n", log_type);
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
/* set the delimiter */
*f3_commas[0] = CSV_DELIMITER;
*f3_commas[1] = CSV_DELIMITER;
*f3_commas[2] = CSV_DELIMITER;
p2target = p2parse;
while(p2parse < msgend) {
/* dbgprintf("state: %d char: %c p2parse: %16x p2target: %16x\n", state, *p2parse, p2parse, p2target); */
switch(state) {
case STATE_FIELD_START:
switch(*p2parse) {
case '"':
state = STATE_IN_QUOTE;
p2parse++;
break;
case ',':
state = STATE_FIELD_START;
*p2target = CSV_DELIMITER;
num_fields++;
p2parse++;
p2target++;
break;
default:
state = STATE_IN_FIELD;
*p2target = *p2parse;
p2parse++;
p2target++;
}
break;
case STATE_IN_FIELD:
switch(*p2parse) {
case ',':
state = STATE_FIELD_START;
*p2target = CSV_DELIMITER;
num_fields++;
p2parse++;
p2target++;
break;
default:
*p2target = *p2parse;
p2parse++;
p2target++;
}
break;
case STATE_IN_QUOTE:
switch(*p2parse) {
case '"':
state = STATE_IN_QUOTE_QUOTE;
p2parse++;
break;
default:
*p2target = *p2parse;
p2parse++;
p2target++;
}
break;
case STATE_IN_QUOTE_QUOTE:
switch(*p2parse) {
case '"':
state = STATE_IN_QUOTE;
*p2target = *p2parse;
p2parse++;
p2target++;
break;
case ',':
state = STATE_FIELD_START;
*p2target = CSV_DELIMITER;
num_fields++;
p2parse++;
p2target++;
break;
default:
dbgprintf("pmpanngfw: martian char (%d) after quote in quote\n", *p2parse);
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
break;
default:
dbgprintf("how could I have reached this state ?!?\n");
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
}
if(p2parse != p2target) {
lenDelta = p2parse - p2target;
assert(lenDelta >= 2);
*p2target = 0;
pMsg->iLenRawMsg -= lenDelta;
pMsg->iLenMSG -= lenDelta;
}
lenMsg = p2target - (pMsg->pszRawMsg + pMsg->offAfterPRI);
DBGPRINTF("pmpanngfw: new message: [%d]'%s'\n", lenMsg, pMsg->pszRawMsg + pMsg->offAfterPRI);
DBGPRINTF("pmpanngfw: # fields: %d\n", num_fields);
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
finalize_it:
ENDparse
BEGINmodExit
CODESTARTmodExit
/* release what we no longer need */
objRelease(errmsg, CORE_COMPONENT);
objRelease(glbl, CORE_COMPONENT);
objRelease(parser, CORE_COMPONENT);
objRelease(datetime, CORE_COMPONENT);
ENDmodExit
BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_PMOD_QUERIES
CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
ENDqueryEtryPt
BEGINmodInit()
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(parser, CORE_COMPONENT));
CHKiRet(objUse(datetime, CORE_COMPONENT));
DBGPRINTF("panngfw parser init called, compiled with version %s\n", VERSION);
bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(); /* cache value, is set only during rsyslogd option processing */
ENDmodInit
/* vim:set ai:
*/

View File

@ -160,7 +160,7 @@ int fileno(FILE *stream);
<EXPR>"startswith" { return CMP_STARTSWITH; }
<EXPR>"startswith_i" { return CMP_STARTSWITHI; }
<EXPR>0[0-7]+ | /* octal number */
<EXPR>0x[0-7a-f] | /* hex number, following rule is dec; strtoll handles all! */
<EXPR>0x[0-9a-f]+ | /* hex number, following rule is dec; strtoll handles all! */
<EXPR>([1-9][0-9]*|0) { yylval.n = strtoll(yytext, NULL, 0); return NUMBER; }
<EXPR>\$[$!./]{0,1}[@a-z][!@a-z0-9\-_\.\[\]]* { yylval.s = strdup(yytext+1); return VAR; }
<EXPR>\'([^'\\]|\\['"\\$bntr]|\\x[0-9a-f][0-9a-f]|\\[0-7][0-7][0-7])*\' {
@ -232,6 +232,8 @@ int fileno(FILE *stream);
BEGIN INOBJ; return BEGINOBJ; }
"lookup_table"[ \n\t]*"(" { yylval.objType = CNFOBJ_LOOKUP_TABLE;
BEGIN INOBJ; return BEGINOBJ; }
"dyn_stats"[ \n\t]*"(" { yylval.objType = CNFOBJ_DYN_STATS;
BEGIN INOBJ; return BEGINOBJ; }
"action"[ \n\t]*"(" { BEGIN INOBJ; return BEGIN_ACTION; }
^[ \t]*:\$?[a-z\-]+[ ]*,[ ]*!?[a-z]+[ ]*,[ ]*\"(\\\"|[^\"])*\" {
yylval.s = strdup(rmLeadingSpace(yytext));

View File

@ -112,7 +112,19 @@ tokenToString(const int token)
case CMP_STARTSWITH: tokstr ="CMP_STARTSWITH"; break;
case CMP_STARTSWITHI: tokstr ="CMP_STARTSWITHI"; break;
case UMINUS: tokstr ="UMINUS"; break;
default: snprintf(tokbuf, sizeof(tokbuf), "%c[%d]", token, token);
case '&': tokstr ="&"; break;
case '+': tokstr ="+"; break;
case '-': tokstr ="-"; break;
case '*': tokstr ="*"; break;
case '/': tokstr ="/"; break;
case '%': tokstr ="%"; break;
case 'M': tokstr ="M"; break;
case 'N': tokstr ="N"; break;
case 'S': tokstr ="S"; break;
case 'V': tokstr ="V"; break;
case 'F': tokstr ="F"; break;
case 'A': tokstr ="A"; break;
default: snprintf(tokbuf, sizeof(tokbuf), "%c[%d]", token, token);
tokstr = tokbuf; break;
}
return tokstr;
@ -768,7 +780,7 @@ doGetGID(struct nvlst *valnode, struct cnfparamdescr *param,
} else {
val->val.datatype = 'N';
val->val.d.n = resultBuf->gr_gid;
dbgprintf("param '%s': uid %d obtained for group '%s'\n",
DBGPRINTF("param '%s': uid %d obtained for group '%s'\n",
param->name, (int) resultBuf->gr_gid, cstr);
r = 1;
}
@ -795,7 +807,7 @@ doGetUID(struct nvlst *valnode, struct cnfparamdescr *param,
} else {
val->val.datatype = 'N';
val->val.d.n = resultBuf->pw_uid;
dbgprintf("param '%s': uid %d obtained for user '%s'\n",
DBGPRINTF("param '%s': uid %d obtained for user '%s'\n",
param->name, (int) resultBuf->pw_uid, cstr);
r = 1;
}
@ -1001,7 +1013,7 @@ nvlstGetParam(struct nvlst *valnode, struct cnfparamdescr *param,
r = 1; /* this *is* valid! */
break;
default:
dbgprintf("error: invalid param type\n");
DBGPRINTF("error: invalid param type\n");
r = 0;
break;
}
@ -1026,7 +1038,7 @@ nvlstGetParams(struct nvlst *lst, struct cnfparamblk *params,
struct cnfparamdescr *param;
if(params->version != CNFPARAMBLK_VERSION) {
dbgprintf("nvlstGetParams: invalid param block version "
DBGPRINTF("nvlstGetParams: invalid param block version "
"%d, expected %d\n",
params->version, CNFPARAMBLK_VERSION);
return NULL;
@ -1086,7 +1098,7 @@ cnfparamvalsIsSet(struct cnfparamblk *params, struct cnfparamvals *vals)
if(vals == NULL)
return 0;
if(params->version != CNFPARAMBLK_VERSION) {
dbgprintf("nvlstGetParams: invalid param block version "
DBGPRINTF("nvlstGetParams: invalid param block version "
"%d, expected %d\n",
params->version, CNFPARAMBLK_VERSION);
return 0;
@ -1105,6 +1117,9 @@ cnfparamsPrint(const struct cnfparamblk *params, const struct cnfparamvals *vals
int i;
char *cstr;
if(!Debug)
return;
for(i = 0 ; i < params->nParams ; ++i) {
dbgprintf("%s: ", params->descr[i].name);
if(vals[i].bUsed) {
@ -1188,16 +1203,44 @@ done:
}
/* ensure that retval is a number; if string is no number,
* try to convert it to one. The semantics from es_str2num()
* are used (bSuccess tells if the conversion went well or not).
static inline int64_t
str2num(es_str_t *s, int *bSuccess)
{
size_t i;
int neg;
int64_t num = 0;
const uchar *const c = es_getBufAddr(s);
if(c[0] == '-') {
neg = -1;
i = -1;
} else {
neg = 1;
i = 0;
}
while(i < s->lenStr && isdigit(c[i])) {
num = num * 10 + c[i] - '0';
++i;
}
num *= neg;
if(bSuccess != NULL)
*bSuccess = (i == s->lenStr) ? 1 : 0;
return num;
}
/* We support decimal integers. Unfortunately, previous versions
* said they support oct and hex, but that wasn't really the case.
* Everything based on JSON was just dec-converted. As this was/is
* the norm, we fix that inconsistency. Luckly, oct and hex support
* was never documented.
* rgerhards, 2015-11-12
*/
static long long
var2Number(struct var *r, int *bSuccess)
{
long long n = 0;
if(r->datatype == 'S') {
n = es_str2num(r->d.estr, bSuccess);
n = str2num(r->d.estr, bSuccess);
} else {
if(r->datatype == 'J') {
#ifdef HAVE_JSON_OBJECT_NEW_INT64
@ -1262,15 +1305,15 @@ var2CString(struct var *__restrict__ const r, int *__restrict__ const bMustFree)
int SKIP_NOTHING = 0x0;
int SKIP_STRING = 0x1;
int SKIP_JSON = 0x2;
static void
varFreeMembersSelectively(const struct var *r, const int skipMask)
{
int kill_string = ! (skipMask & SKIP_STRING);
if(kill_string && (r->datatype == 'S')) es_deleteStr(r->d.estr);
int kill_json = ! (skipMask & SKIP_JSON);
if(kill_json && (r->datatype == 'J')) json_object_put(r->d.json);
if(r->datatype == 'J') {
json_object_put(r->d.json);
} else if( !(skipMask & SKIP_STRING) && (r->datatype == 'S')) {
es_deleteStr(r->d.estr);
}
}
static void
@ -1303,7 +1346,7 @@ doExtractFieldByChar(uchar *str, uchar delim, const int matchnbr, uchar **resstr
++iCurrFld;
}
}
dbgprintf("field() field requested %d, field found %d\n", matchnbr, iCurrFld);
DBGPRINTF("field() field requested %d, field found %d\n", matchnbr, iCurrFld);
if(iCurrFld == matchnbr) {
/* field found, now extract it */
@ -1315,12 +1358,12 @@ doExtractFieldByChar(uchar *str, uchar delim, const int matchnbr, uchar **resstr
* step back a little not to copy it as part of the field. */
/* we got our end pointer, now do the copy */
iLen = pFldEnd - pFld + 1; /* the +1 is for an actual char, NOT \0! */
allocLen = iLen + 1;
# ifdef VALGRIND
allocLen = iLen + 1;
# ifdef VALGRIND
allocLen += (3 - (iLen % 4));
/*older versions of valgrind have a problem with strlen inspecting 4-bytes at a time*/
# endif
CHKmalloc(pBuf = MALLOC(allocLen * sizeof(uchar)));
/*older versions of valgrind have a problem with strlen inspecting 4-bytes at a time*/
# endif
CHKmalloc(pBuf = MALLOC(allocLen));
/* now copy */
memcpy(pBuf, pFld, iLen);
pBuf[iLen] = '\0'; /* terminate it */
@ -1355,7 +1398,7 @@ doExtractFieldByStr(uchar *str, char *delim, const rs_size_t lenDelim, const int
++iCurrFld;
}
}
dbgprintf("field() field requested %d, field found %d\n", matchnbr, iCurrFld);
DBGPRINTF("field() field requested %d, field found %d\n", matchnbr, iCurrFld);
if(iCurrFld == matchnbr) {
/* field found, now extract it */
@ -1368,7 +1411,7 @@ doExtractFieldByStr(uchar *str, char *delim, const rs_size_t lenDelim, const int
iLen = pFldEnd - pFld;
}
/* we got our end pointer, now do the copy */
CHKmalloc(pBuf = MALLOC((iLen + 1) * sizeof(uchar)));
CHKmalloc(pBuf = MALLOC(iLen + 1));
/* now copy */
memcpy(pBuf, pFld, iLen);
pBuf[iLen] = '\0'; /* terminate it */
@ -1419,16 +1462,16 @@ doFunc_re_extract(struct cnffunc *func, struct var *ret, void* usrptr)
int iREstat;
iREstat = regexp.regexec(func->funcdata, (char*)(str + iOffs),
submatchnbr+1, pmatch, 0);
dbgprintf("re_extract: regexec return is %d\n", iREstat);
DBGPRINTF("re_extract: regexec return is %d\n", iREstat);
if(iREstat == 0) {
if(pmatch[0].rm_so == -1) {
dbgprintf("oops ... start offset of successful regexec is -1\n");
DBGPRINTF("oops ... start offset of successful regexec is -1\n");
break;
}
if(iTry == matchnbr) {
bFound = 1;
} else {
dbgprintf("re_extract: regex found at offset %d, new offset %d, tries %d\n",
DBGPRINTF("re_extract: regex found at offset %d, new offset %d, tries %d\n",
iOffs, (int) (iOffs + pmatch[0].rm_eo), iTry);
iOffs += pmatch[0].rm_eo;
++iTry;
@ -1437,7 +1480,7 @@ doFunc_re_extract(struct cnffunc *func, struct var *ret, void* usrptr)
break;
}
}
dbgprintf("re_extract: regex: end search, found %d\n", bFound);
DBGPRINTF("re_extract: regex: end search, found %d\n", bFound);
if(!bFound) {
bHadNoMatch = 1;
goto finalize_it;
@ -1590,12 +1633,18 @@ doRandomGen(struct var *__restrict__ const sourceVal) {
int success = 0;
long long max = var2Number(sourceVal, &success);
if (! success) {
dbgprintf("rainerscript: random(max) didn't get a valid 'max' limit, defaulting random-number value to 0");
DBGPRINTF("rainerscript: random(max) didn't get a valid 'max' limit, defaulting random-number value to 0");
return 0;
}
if(max == 0) {
DBGPRINTF("rainerscript: random(max) invalid, 'max' is zero, , defaulting random-number value to 0");
return 0;
}
long int x = randomNumber();
if (max > MAX_RANDOM_NUMBER) {
dbgprintf("rainerscript: desired random-number range [0 - %lld) is wider than supported limit of [0 - %d)", max, MAX_RANDOM_NUMBER);
DBGPRINTF("rainerscript: desired random-number range [0 - %lld] "
"is wider than supported limit of [0 - %d)",
max, MAX_RANDOM_NUMBER);
}
return x % max;
}
@ -1607,7 +1656,6 @@ static inline void
doFuncCall(struct cnffunc *__restrict__ const func, struct var *__restrict__ const ret,
void *__restrict__ const usrptr)
{
char *fname;
char *envvar;
int bMustFree;
es_str_t *estr;
@ -1623,7 +1671,7 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct var *__restrict__ con
uint8_t lookup_key_type;
lookup_t *lookup_table;
dbgprintf("rainerscript: executing function id %d\n", func->fID);
DBGPRINTF("rainerscript: executing function id %d\n", func->fID);
switch(func->fID) {
case CNFFUNC_STRLEN:
if(func->expr[0]->nodetype == 'S') {
@ -1717,6 +1765,7 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct var *__restrict__ con
varFreeMembers(&r[0]);
}
ret->datatype = 'N';
DBGPRINTF("JSONorString: cnum node type %c result %d\n", func->expr[0]->nodetype, (int) ret->d.n);
break;
case CNFFUNC_RE_MATCH:
cnfexprEval(func->expr[0], &r[0], usrptr);
@ -1783,7 +1832,6 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct var *__restrict__ con
ret->datatype = 'N';
break;
case CNFFUNC_LOOKUP:
dbgprintf("DDDD: executing lookup\n");
ret->datatype = 'S';
if(func->funcdata == NULL) {
ret->d.estr = es_newStrFromCStr("TABLE-NOT-FOUND", sizeof("TABLE-NOT-FOUND")-1);
@ -1806,9 +1854,21 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct var *__restrict__ con
}
varFreeMembers(&r[1]);
break;
case CNFFUNC_DYN_INC:
ret->datatype = 'N';
if(func->funcdata == NULL) {
ret->d.n = -1;
break;
}
cnfexprEval(func->expr[1], &r[1], usrptr);
str = (char*) var2CString(&r[1], &bMustFree);
ret->d.n = dynstats_inc(func->funcdata, (uchar*)str);
if(bMustFree) free(str);
varFreeMembers(&r[1]);
break;
default:
if(Debug) {
fname = es_str2cstr(func->fname, NULL);
char *fname = es_str2cstr(func->fname, NULL);
dbgprintf("rainerscript: invalid function id %u (name '%s')\n",
(unsigned) func->fID, fname);
free(fname);
@ -1827,21 +1887,31 @@ evalVar(struct cnfvar *__restrict__ const var, void *__restrict__ const usrptr,
unsigned short bMustBeFreed = 0;
rsRetVal localRet;
struct json_object *json;
uchar *cstr;
if(var->prop.id == PROP_CEE ||
var->prop.id == PROP_LOCAL_VAR ||
var->prop.id == PROP_GLOBAL_VAR ) {
localRet = msgGetJSONPropJSON((msg_t*)usrptr, &var->prop, &json);
ret->datatype = 'J';
ret->d.json = (localRet == RS_RET_OK) ? json : NULL;
DBGPRINTF("rainerscript: var %d:%s: '%s'\n", var->prop.id, var->prop.name,
localRet = msgGetJSONPropJSONorString((msg_t*)usrptr, &var->prop, &json, &cstr);
if(json != NULL) {
ret->datatype = 'J';
ret->d.json = (localRet == RS_RET_OK) ? json : NULL;
DBGPRINTF("rainerscript: (json) var %d:%s: '%s'\n",
var->prop.id, var->prop.name,
(ret->d.json == NULL) ? "" : json_object_get_string(ret->d.json));
} else { /* we have a string */
ret->datatype = 'S';
ret->d.estr = (localRet == RS_RET_OK) ?
es_newStrFromCStr((char*) cstr, strlen((char*) cstr))
: es_newStr(1);
DBGPRINTF("rainerscript: (json/string) var %d: '%s'\n", var->prop.id, cstr);
free(cstr);
}
} else {
ret->datatype = 'S';
pszProp = (uchar*) MsgGetProp((msg_t*)usrptr, NULL, &var->prop, &propLen, &bMustBeFreed, NULL);
ret->d.estr = es_newStrFromCStr((char*)pszProp, propLen);
DBGPRINTF("rainerscript: var %d: '%s'\n", var->prop.id, pszProp);
DBGPRINTF("rainerscript: (string) var %d: '%s'\n", var->prop.id, pszProp);
if(bMustBeFreed)
free(pszProp);
}
@ -2410,11 +2480,12 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct var *__restric
default:
ret->datatype = 'N';
ret->d.n = 0ll;
dbgprintf("eval error: unknown nodetype %u['%c']\n",
DBGPRINTF("eval error: unknown nodetype %u['%c']\n",
(unsigned) expr->nodetype, (char) expr->nodetype);
break;
}
DBGPRINTF("eval expr %p, return datatype '%c'\n", expr, ret->datatype);
DBGPRINTF("eval expr %p, return datatype '%c':%d\n", expr, ret->datatype,
(ret->datatype == 'N') ? (int)ret->d.n: 0);
}
//---------------------------------------------------------
@ -2533,8 +2604,15 @@ struct json_object*
cnfexprEvalCollection(struct cnfexpr *__restrict__ const expr, void *__restrict__ const usrptr)
{
struct var ret;
void *retptr;
cnfexprEval(expr, &ret, usrptr);
return ret.d.json;/*caller is supposed to free the returned json-object*/
if(ret.datatype == 'J') {
retptr = ret.d.json; /*caller is supposed to free the returned json-object*/
} else {
retptr = NULL;
varFreeMembers(&ret); /* we must free the element */
}
return retptr;
}
inline static void
@ -2969,7 +3047,7 @@ cnfstmtDestruct(struct cnfstmt *stmt)
free(stmt->d.s_reload_lookup_table.stub_value);
}
default:
dbgprintf("error: unknown stmt type during destruct %u\n",
DBGPRINTF("error: unknown stmt type during destruct %u\n",
(unsigned) stmt->nodetype);
break;
}
@ -3003,10 +3081,10 @@ cnfNewIterator(char *var, struct cnfexpr *collection)
static void
cnfIteratorDestruct(struct cnfitr *itr)
{
if (itr->var != NULL) free(itr->var);
itr->var = NULL;
if (itr->collection != NULL) cnfexprDestruct(itr->collection);
itr->collection = NULL;
free(itr->var);
if(itr->collection != NULL)
cnfexprDestruct(itr->collection);
free(itr);
}
struct cnfstmt *
@ -3434,7 +3512,7 @@ cnfexprOptimize(struct cnfexpr *expr)
long long ln, rn;
struct cnfexpr *exprswap;
dbgprintf("optimize expr %p, type '%s'\n", expr, tokenToString(expr->nodetype));
DBGPRINTF("optimize expr %p, type '%s'\n", expr, tokenToString(expr->nodetype));
switch(expr->nodetype) {
case '&':
constFoldConcat(expr);
@ -3748,7 +3826,7 @@ cnfstmtOptimize(struct cnfstmt *root)
DBGPRINTF("optimizer error: we see a NOP, how come?\n");
break;
default:
dbgprintf("error: unknown stmt type %u during optimizer run\n",
DBGPRINTF("error: unknown stmt type %u during optimizer run\n",
(unsigned) stmt->nodetype);
break;
}
@ -3772,10 +3850,10 @@ cnffparamlstNew(struct cnfexpr *expr, struct cnffparamlst *next)
static const char* const numInWords[] = {"zero", "one", "two", "three", "four", "five", "six"};
#define GENERATE_FUNC_WITH_NARG_RANGE(name, minArg, maxArg, funcId, errMsg) \
if(nParams < minArg || nParams > maxArg) { \
parser_errmsg(errMsg, name, nParams); \
return CNFFUNC_INVALID; \
} \
if(nParams < minArg || nParams > maxArg) { \
parser_errmsg(errMsg, name, nParams); \
return CNFFUNC_INVALID; \
} \
return funcId
@ -3824,6 +3902,8 @@ funcName2ID(es_str_t *fname, unsigned short nParams)
GENERATE_FUNC("prifilt", 1, CNFFUNC_PRIFILT);
} else if(FUNC_NAME("lookup")) {
GENERATE_FUNC("lookup", 2, CNFFUNC_LOOKUP);
} else if(FUNC_NAME("dyn_inc")) {
GENERATE_FUNC("dyn_inc", 2, CNFFUNC_DYN_INC);
} else if(FUNC_NAME("replace")) {
GENERATE_FUNC_WITH_ERR_MSG(
"replace", 3, CNFFUNC_REPLACE,
@ -3832,10 +3912,10 @@ funcName2ID(es_str_t *fname, unsigned short nParams)
"but is %d.");
} else if(FUNC_NAME("wrap")) {
GENERATE_FUNC_WITH_NARG_RANGE("wrap", 2, 3, CNFFUNC_WRAP,
"number of parameters for %s() must either be "
"two (operand_string, wrapper) or"
"three (operand_string, wrapper, wrapper_escape_str)"
"but is %d.");
"number of parameters for %s() must either be "
"two (operand_string, wrapper) or"
"three (operand_string, wrapper, wrapper_escape_str)"
"but is %d.");
} else if(FUNC_NAME("random")) {
GENERATE_FUNC("random", 1, CNFFUNC_RANDOM);
} else {
@ -3982,6 +4062,36 @@ finalize_it:
RETiRet;
}
static inline rsRetVal
initFunc_dyn_stats(struct cnffunc *func)
{
uchar *cstr = NULL;
DEFiRet;
func->destructable_funcdata = 0;
if(func->nParams != 2) {
parser_errmsg("rsyslog logic error in line %d of file %s\n",
__LINE__, __FILE__);
FINALIZE;
}
func->funcdata = NULL;
if(func->expr[0]->nodetype != 'S') {
parser_errmsg("dyn-stats bucket-name (param 1) of dyn-stats manipulating functions like dyn_inc must be a constant string");
FINALIZE;
}
cstr = (uchar*)es_str2cstr(((struct cnfstringval*) func->expr[0])->estr, NULL);
if((func->funcdata = dynstats_findBucket(cstr)) == NULL) {
parser_errmsg("dyn-stats bucket '%s' not found", cstr);
FINALIZE;
}
finalize_it:
free(cstr);
RETiRet;
}
struct cnffunc *
cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst)
@ -4027,6 +4137,9 @@ cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst)
case CNFFUNC_EXEC_TEMPLATE:
initFunc_exec_template(func);
break;
case CNFFUNC_DYN_INC:
initFunc_dyn_stats(func);
break;
default:break;
}
}
@ -4127,13 +4240,13 @@ cnfDoInclude(char *name)
}
if(S_ISREG(fileInfo.st_mode)) { /* config file */
dbgprintf("requested to include config file '%s'\n", cfgFile);
DBGPRINTF("requested to include config file '%s'\n", cfgFile);
cnfSetLexFile(cfgFile);
} else if(S_ISDIR(fileInfo.st_mode)) { /* config directory */
dbgprintf("requested to include directory '%s'\n", cfgFile);
DBGPRINTF("requested to include directory '%s'\n", cfgFile);
cnfDoInclude(cfgFile);
} else {
dbgprintf("warning: unable to process IncludeConfig directive '%s'\n", cfgFile);
DBGPRINTF("warning: unable to process IncludeConfig directive '%s'\n", cfgFile);
}
}

View File

@ -46,6 +46,7 @@ enum cnfobjType {
CNFOBJ_LOOKUP_TABLE,
CNFOBJ_PARSER,
CNFOBJ_TIMEZONE,
CNFOBJ_DYN_STATS,
CNFOBJ_INVALID = 0
};
@ -81,6 +82,8 @@ cnfobjType2str(enum cnfobjType ot)
return "main_queue";
case CNFOBJ_LOOKUP_TABLE:
return "lookup_table";
case CNFOBJ_DYN_STATS:
return "dyn_stats";
break;
default:return "error: invalid cnfobjType";
}
@ -278,7 +281,8 @@ enum cnffuncid {
CNFFUNC_EXEC_TEMPLATE,
CNFFUNC_REPLACE,
CNFFUNC_WRAP,
CNFFUNC_RANDOM
CNFFUNC_RANDOM,
CNFFUNC_DYN_INC
};
struct cnffunc {

View File

@ -208,7 +208,7 @@ struct outchannel *ochAddLine(char* pName, uchar** ppRestOfConfLine)
return NULL;
pOch->iLenName = strlen(pName);
pOch->pszName = (char*) MALLOC(sizeof(char) * (pOch->iLenName + 1));
pOch->pszName = (char*) MALLOC(pOch->iLenName + 1);
if(pOch->pszName == NULL) {
dbgprintf("ochAddLine could not alloc memory for outchannel name!");
pOch->iLenName = 0;

View File

@ -453,6 +453,8 @@ rsRetVal parsAddrWithBits(rsParsObj *pThis, struct NetAddr **pIP, int *pBits)
/* mask bits follow, let's parse them! */
++pThis->iCurrPos; /* eat slash */
if((iRet = parsInt(pThis, pBits)) != RS_RET_OK) {
free((*pIP)->addr.NetAddr);
free((*pIP)->addr.HostWildcard);
free (pszIP);
free (*pIP);
FINALIZE;
@ -489,6 +491,8 @@ rsRetVal parsAddrWithBits(rsParsObj *pThis, struct NetAddr **pIP, int *pBits)
/* mask bits follow, let's parse them! */
++pThis->iCurrPos; /* eat slash */
if((iRet = parsInt(pThis, pBits)) != RS_RET_OK) {
free((*pIP)->addr.NetAddr);
free((*pIP)->addr.HostWildcard);
free (pszIP);
free (*pIP);
FINALIZE;

View File

@ -196,22 +196,17 @@ finalize_it:
RETiRet;
}
/* actually submit a message to the rsyslog core
/* submit a generated numeric-suffix message to the rsyslog core
*/
static rsRetVal
doInjectMsg(int iNum, ratelimit_t *ratelimiter)
doInjectMsg(uchar *szMsg, ratelimit_t *ratelimiter)
{
uchar szMsg[1024];
msg_t *pMsg;
struct syslogTime stTime;
time_t ttGenTime;
DEFiRet;
snprintf((char*)szMsg, sizeof(szMsg)/sizeof(uchar),
"<167>Mar 1 01:00:00 172.20.245.8 tag msgnum:%8.8d:", iNum);
datetime.getCurrTime(&stTime, &ttGenTime);
datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME);
/* we now create our own message object and submit it to the queue */
CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime));
MsgSetRawMsg(pMsg, (char*) szMsg, ustrlen(szMsg));
@ -226,6 +221,19 @@ finalize_it:
RETiRet;
}
/* submit a generated numeric-suffix message to the rsyslog core
*/
static rsRetVal
doInjectNumericSuffixMsg(int iNum, ratelimit_t *ratelimiter)
{
uchar szMsg[1024];
DEFiRet;
snprintf((char*)szMsg, sizeof(szMsg)/sizeof(uchar),
"<167>Mar 1 01:00:00 172.20.245.8 tag msgnum:%8.8d:", iNum);
CHKiRet(doInjectMsg(szMsg, ratelimiter));
finalize_it:
RETiRet;
}
/* This function injects messages. Command format:
* injectmsg <fromnbr> <number-of-messages>
@ -235,29 +243,38 @@ static rsRetVal
injectMsg(uchar *pszCmd, tcps_sess_t *pSess)
{
uchar wordBuf[1024];
int iFrom;
int nMsgs;
int iFrom, nMsgs;
uchar *litteralMsg;
int i;
ratelimit_t *ratelimit = NULL;
DEFiRet;
/* we do not check errors here! */
getFirstWord(&pszCmd, wordBuf, sizeof(wordBuf)/sizeof(uchar), TO_LOWERCASE);
iFrom = atoi((char*)wordBuf);
getFirstWord(&pszCmd, wordBuf, sizeof(wordBuf)/sizeof(uchar), TO_LOWERCASE);
nMsgs = atoi((char*)wordBuf);
litteralMsg = NULL;
CHKiRet(ratelimitNew(&ratelimit, "imdiag", "injectmsg"));
for(i = 0 ; i < nMsgs ; ++i) {
doInjectMsg(i + iFrom, ratelimit);
/* we do not check errors here! */
getFirstWord(&pszCmd, wordBuf, sizeof(wordBuf), TO_LOWERCASE);
if (ustrcmp(UCHAR_CONSTANT("litteral"), wordBuf) == 0) {
/* user has provided content for a message */
++pszCmd; /* ignore following space */
CHKiRet(doInjectMsg(pszCmd, ratelimit));
nMsgs = 1;
} else { /* assume 2 args, (from_idx, to_idx) */
iFrom = atoi((char*)wordBuf);
getFirstWord(&pszCmd, wordBuf, sizeof(wordBuf), TO_LOWERCASE);
nMsgs = atoi((char*)wordBuf);
for(i = 0 ; i < nMsgs ; ++i) {
CHKiRet(doInjectNumericSuffixMsg(i + iFrom, ratelimit));
}
}
CHKiRet(sendResponse(pSess, "%d messages injected\n", nMsgs));
DBGPRINTF("imdiag: %d messages injected\n", nMsgs);
finalize_it:
if(ratelimit != NULL)
ratelimitDestruct(ratelimit);
free(litteralMsg);
RETiRet;
}
@ -335,12 +352,12 @@ OnMsgReceived(tcps_sess_t *pSess, uchar *pRcv, int iLenMsg)
* WITHOUT a termination \0 char. So we need to convert it to one
* before proceeding.
*/
CHKmalloc(pszMsg = MALLOC(sizeof(uchar) * (iLenMsg + 1)));
CHKmalloc(pszMsg = MALLOC(iLenMsg + 1));
pToFree = pszMsg;
memcpy(pszMsg, pRcv, iLenMsg);
pszMsg[iLenMsg] = '\0';
getFirstWord(&pszMsg, cmdBuf, sizeof(cmdBuf)/sizeof(uchar), TO_LOWERCASE);
getFirstWord(&pszMsg, cmdBuf, sizeof(cmdBuf), TO_LOWERCASE);
dbgprintf("imdiag received command '%s'\n", cmdBuf);
if(!ustrcmp(cmdBuf, UCHAR_CONSTANT("getmainmsgqueuesize"))) {

View File

@ -12,11 +12,11 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
* -or-
* see COPYING.ASL20 in the source distribution
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -112,6 +112,7 @@ typedef struct lstn_s {
regex_t end_preg; /* compiled version of startRegex */
uchar *prevLineSegment; /* previous line segment (in regex mode) */
sbool escapeLF; /* escape LF inside the MSG content? */
sbool reopenOnTruncate;
sbool addMetadata;
ruleset_t *pRuleset; /* ruleset to bind listener to (use system default if unspecified) */
ratelimit_t *ratelimiter;
@ -146,6 +147,7 @@ struct instanceConf_s {
uint8_t readMode;
uchar *startRegex;
sbool escapeLF;
sbool reopenOnTruncate;
sbool addMetadata;
int maxLinesAtOnce;
ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
@ -174,7 +176,7 @@ struct modConfData_s {
static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
#if HAVE_INOTIFY_INIT
#if HAVE_INOTIFY_INIT
/* support for inotify mode */
/* we need to track directories */
@ -259,6 +261,7 @@ static struct cnfparamdescr inppdescr[] = {
{ "readmode", eCmdHdlrInt, 0 },
{ "startmsg.regex", eCmdHdlrString, 0 },
{ "escapelf", eCmdHdlrBinary, 0 },
{ "reopenontruncate", eCmdHdlrBinary, 0 },
{ "maxlinesatonce", eCmdHdlrInt, 0 },
{ "maxsubmitatonce", eCmdHdlrInt, 0 },
{ "removestateondelete", eCmdHdlrBinary, 0 },
@ -284,9 +287,9 @@ static void
dbg_wdmapPrint(char *msg)
{
int i;
dbgprintf("%s\n", msg);
DBGPRINTF("%s\n", msg);
for(i = 0 ; i < nWdmap ; ++i)
dbgprintf("wdmap[%d]: wd: %d, file %d, dir %d\n", i,
DBGPRINTF("wdmap[%d]: wd: %d, file %d, dir %d\n", i,
wdmap[i].wd, wdmap[i].fIdx, wdmap[i].dirIdx);
}
#endif
@ -306,18 +309,18 @@ finalize_it:
/* looks up a wdmap entry by dirIdx and returns it's index if found
* or -1 if not found.
*/
static int
static int
wdmapLookupListner(lstn_t* pLstn)
{
int i = 0;
int wd = -1;
int i = 0;
int wd = -1;
/* Loop through */
for(i = 0 ; i < nWdmap; ++i) {
if (wdmap[i].pLstn == pLstn)
wd = wdmap[i].wd;
wd = wdmap[i].wd;
}
return wd;
return wd;
}
/* compare function for bsearch() */
@ -368,14 +371,13 @@ wdmapAdd(int wd, const int dirIdx, lstn_t *const pLstn)
}
if(i < nWdmap) {
/* we need to shift to make room for new entry */
dbgprintf("DDDD: imfile doing wdmap mmemmov(%d, %d, %d) for ADD\n", i,i+1,nWdmap-i);
memmove(wdmap + i, wdmap + i + 1, nWdmap - i);
memmove(wdmap + i + 1, wdmap + i, sizeof(wd_map_t) * (nWdmap - i));
}
wdmap[i].wd = wd;
wdmap[i].dirIdx = dirIdx;
wdmap[i].pLstn = pLstn;
++nWdmap;
dbgprintf("DDDD: imfile: enter into wdmap[%d]: wd %d, dir %d, lstn %s:%s\n",i,wd,dirIdx,
DBGPRINTF("imfile: enter into wdmap[%d]: wd %d, dir %d, lstn %s:%s\n",i,wd,dirIdx,
(pLstn == NULL) ? "DIRECTORY" : "FILE",
(pLstn == NULL) ? dirs[dirIdx].dirName : pLstn->pszFileName);
@ -398,11 +400,10 @@ wdmapDel(const int wd)
if(i < nWdmap-1) {
/* we need to shift to delete it (see comment at wdmap definition) */
dbgprintf("DDDD: imfile doing wdmap mmemmov(%d, %d, %d) for DEL\n", i,i+1,nWdmap-i-1);
memmove(wdmap + i, wdmap + i+1, nWdmap - i-1);
memmove(wdmap + i, wdmap + i + 1, sizeof(wd_map_t) * (nWdmap - i - 1));
}
--nWdmap;
dbgprintf("DDDD: imfile: wd %d deleted, was idx %d\n", wd, i);
DBGPRINTF("imfile: wd %d deleted, was idx %d\n", wd, i);
finalize_it:
RETiRet;
@ -455,7 +456,7 @@ static rsRetVal enqLine(lstn_t *const __restrict__ pLstn,
CHKiRet(msgConstruct(&pMsg));
MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY);
MsgSetInputName(pMsg, pInputName);
MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine), cstrLen(cstrLine));
MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStrNoNULL(cstrLine), cstrLen(cstrLine));
MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
MsgSetTAG(pMsg, pLstn->pszTag, pLstn->lenTag);
@ -486,18 +487,18 @@ openFile(lstn_t *pLstn)
DBGPRINTF("imfile: trying to open state for '%s', state file '%s'\n",
pLstn->pszFileName, statefn);
/* Construct file name */
lenSFNam = snprintf((char*)pszSFNam, sizeof(pszSFNam) / sizeof(uchar), "%s/%s",
lenSFNam = snprintf((char*)pszSFNam, sizeof(pszSFNam), "%s/%s",
(char*) glbl.GetWorkDir(), (char*)statefn);
/* check if the file exists */
if(stat((char*) pszSFNam, &stat_buf) == -1) {
if(errno == ENOENT) {
dbgprintf("imfile: clean startup, state file for '%s'\n", pLstn->pszFileName);
DBGPRINTF("imfile: clean startup, state file for '%s'\n", pLstn->pszFileName);
ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
} else {
char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
dbgprintf("imfile: error trying to access state file for '%s':%s\n",
DBGPRINTF("imfile: error trying to access state file for '%s':%s\n",
pLstn->pszFileName, errStr);
ABORT_FINALIZE(RS_RET_IO_ERROR);
}
@ -513,6 +514,7 @@ openFile(lstn_t *pLstn)
/* read back in the object */
CHKiRet(obj.Deserialize(&pLstn->pStrm, (uchar*) "strm", psSF, NULL, pLstn));
CHKiRet(strm.SetbReopenOnTruncate(pLstn->pStrm, pLstn->reopenOnTruncate));
DBGPRINTF("imfile: deserialized state file, state file base name '%s', "
"configured base name '%s'\n", pLstn->pStrm->pszFName,
pLstn->pszFileName);
@ -639,6 +641,7 @@ createInstance(instanceConf_t **pinst)
inst->startRegex = NULL;
inst->bRMStateOnDel = 1;
inst->escapeLF = 1;
inst->reopenOnTruncate = 0;
inst->addMetadata = ADD_METADATA_UNSPECIFIED;
/* node created, let's add to config */
@ -693,6 +696,12 @@ checkInstance(instanceConf_t *inst)
char errStr[512];
DEFiRet;
/* this is primarily for the clang static analyzer, but also
* guards against logic errors in the config handler.
*/
if(inst->pszFileName == NULL)
ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
i = getBasename(basen, inst->pszFileName);
memcpy(dirn, inst->pszFileName, i); /* do not copy slash */
dirn[i] = '\0';
@ -761,6 +770,7 @@ addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal)
inst->iPersistStateInterval = cs.iPersistStateInterval;
inst->readMode = cs.readMode;
inst->escapeLF = 0;
inst->reopenOnTruncate = 0;
inst->addMetadata = 0;
inst->bRMStateOnDel = 0;
@ -785,7 +795,7 @@ lstnAdd(lstn_t **newLstn)
{
lstn_t *pLstn;
DEFiRet;
CHKmalloc(pLstn = (lstn_t*) MALLOC(sizeof(lstn_t)));
if(runModConf->pRootLstn == NULL) {
runModConf->pRootLstn = pLstn;
@ -797,7 +807,7 @@ lstnAdd(lstn_t **newLstn)
runModConf->pTailLstn = pLstn;
pLstn->next = NULL;
*newLstn = pLstn;
finalize_it:
RETiRet;
}
@ -806,7 +816,7 @@ finalize_it:
static void
lstnDel(lstn_t *pLstn)
{
dbgprintf("imfile: lstnDel called for %s\n", pLstn->pszFileName);
DBGPRINTF("imfile: lstnDel called for %s\n", pLstn->pszFileName);
if(pLstn->pStrm != NULL) { /* stream open? */
persistStrmState(pLstn);
strm.Destruct(&(pLstn->pStrm));
@ -836,7 +846,7 @@ lstnDel(lstn_t *pLstn)
* the ppExisting parameter.
*/
static rsRetVal
lstnDup(lstn_t ** ppExisting, uchar *const __restrict__ newname)
lstnDup(lstn_t **ppExisting, uchar *const __restrict__ newname)
{
DEFiRet;
lstn_t *const existing = *ppExisting;
@ -845,7 +855,10 @@ lstnDup(lstn_t ** ppExisting, uchar *const __restrict__ newname)
CHKiRet(lstnAdd(&pThis));
pThis->pszDirName = existing->pszDirName; /* read-only */
pThis->pszBaseName = (uchar*)strdup((char*)newname);
asprintf((char**)&pThis->pszFileName, "%s/%s", (char*)pThis->pszDirName, (char*)newname);
if(asprintf((char**)&pThis->pszFileName, "%s/%s", (char*)pThis->pszDirName, (char*)newname) == -1) {
DBGPRINTF("imfile/lstnDup: asprintf failed, malfunction can happen\n");
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
pThis->pszTag = (uchar*) strdup((char*) existing->pszTag);
pThis->lenTag = ustrlen(pThis->pszTag);
pThis->pszStateFile = existing->pszStateFile == NULL ? NULL : (uchar*) strdup((char*) existing->pszStateFile);
@ -862,12 +875,13 @@ lstnDup(lstn_t ** ppExisting, uchar *const __restrict__ newname)
pThis->startRegex = existing->startRegex; /* no strdup, as it is read-only */
if(pThis->startRegex != NULL) // TODO: make this a single function with better error handling
if(regcomp(&pThis->end_preg, (char*)pThis->startRegex, REG_EXTENDED)) {
dbgprintf("imfile: error regex compile\n");
DBGPRINTF("imfile: error regex compile\n");
ABORT_FINALIZE(RS_RET_ERR);
}
pThis->bRMStateOnDel = existing->bRMStateOnDel;
pThis->hasWildcard = existing->hasWildcard;
pThis->escapeLF = existing->escapeLF;
pThis->reopenOnTruncate = existing->reopenOnTruncate;
pThis->addMetadata = existing->addMetadata;
pThis->pRuleset = existing->pRuleset;
pThis->nRecords = 0;
@ -928,11 +942,12 @@ addListner(instanceConf_t *inst)
pThis->startRegex = inst->startRegex; /* no strdup, as it is read-only */
if(pThis->startRegex != NULL)
if(regcomp(&pThis->end_preg, (char*)pThis->startRegex, REG_EXTENDED)) {
dbgprintf("imfile: error regex compile\n");
DBGPRINTF("imfile: error regex compile\n");
ABORT_FINALIZE(RS_RET_ERR);
}
pThis->bRMStateOnDel = inst->bRMStateOnDel;
pThis->escapeLF = inst->escapeLF;
pThis->reopenOnTruncate = inst->reopenOnTruncate;
pThis->addMetadata = (inst->addMetadata == ADD_METADATA_UNSPECIFIED) ?
hasWildcard : inst->addMetadata;
pThis->pRuleset = inst->pBindRuleset;
@ -958,7 +973,7 @@ CODESTARTnewInpInst
}
if(Debug) {
dbgprintf("input param blk in imfile:\n");
DBGPRINTF("input param blk in imfile:\n");
cnfparamsPrint(&inppblk, pvals);
}
@ -991,6 +1006,8 @@ CODESTARTnewInpInst
inst->addMetadata = (sbool) pvals[i].val.d.n;
} else if(!strcmp(inppblk.descr[i].name, "escapelf")) {
inst->escapeLF = (sbool) pvals[i].val.d.n;
} else if(!strcmp(inppblk.descr[i].name, "reopenontruncate")) {
inst->reopenOnTruncate = (sbool) pvals[i].val.d.n;
} else if(!strcmp(inppblk.descr[i].name, "maxlinesatonce")) {
if( loadModConf->opMode == OPMODE_INOTIFY
&& pvals[i].val.d.n > 0) {
@ -1005,7 +1022,7 @@ CODESTARTnewInpInst
} else if(!strcmp(inppblk.descr[i].name, "maxsubmitatonce")) {
inst->nMultiSub = pvals[i].val.d.n;
} else {
dbgprintf("imfile: program error, non-handled "
DBGPRINTF("imfile: program error, non-handled "
"param '%s'\n", inppblk.descr[i].name);
}
}
@ -1056,7 +1073,7 @@ CODESTARTsetModCnf
}
if(Debug) {
dbgprintf("module (global) param blk for imfile:\n");
DBGPRINTF("module (global) param blk for imfile:\n");
cnfparamsPrint(&modpblk, pvals);
}
@ -1077,7 +1094,7 @@ CODESTARTsetModCnf
free(cstr);
}
} else {
dbgprintf("imfile: program error, non-handled "
DBGPRINTF("imfile: program error, non-handled "
"param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
}
}
@ -1100,7 +1117,7 @@ CODESTARTendCnfLoad
/* persist module-specific settings from legacy config system */
loadModConf->iPollInterval = cs.iPollInterval;
}
dbgprintf("imfile: opmode is %d, polling interval is %d\n",
DBGPRINTF("imfile: opmode is %d, polling interval is %d\n",
loadModConf->opMode,
loadModConf->iPollInterval);
@ -1182,7 +1199,7 @@ ENDfreeCnf
* So even if we found some lines, it is highly unlikely to find a new one
* just now. Trying it would result in a performance-costly additional try
* which in the very, very vast majority of cases will never find any new
* lines.
* lines.
* On spamming the main queue: keep in mind that it will automatically rate-limit
* ourselfes if we begin to overrun it. So we really do not need to care here.
*/
@ -1211,7 +1228,7 @@ doPolling(void)
if(glbl.GetGlobalInputTermState() == 0)
srSleep(runModConf->iPollInterval, 10);
}
RETiRet;
}
@ -1233,10 +1250,10 @@ fileTableDisplay(fileTable_t *tab)
{
int f;
uchar *baseName;
dbgprintf("DDDD: imfile: dirs.currMaxfiles %d\n", tab->currMax);
DBGPRINTF("imfile: dirs.currMaxfiles %d\n", tab->currMax);
for(f = 0 ; f < tab->currMax ; ++f) {
baseName = tab->listeners[f].pLstn->pszBaseName;
dbgprintf("DDDD: imfile: TABLE %p CONTENTS, %d->%p:'%s'\n", tab, f, tab->listeners[f].pLstn, (char*)baseName);
DBGPRINTF("imfile: TABLE %p CONTENTS, %d->%p:'%s'\n", tab, f, tab->listeners[f].pLstn, (char*)baseName);
}
}
*/
@ -1246,7 +1263,7 @@ fileTableSearch(fileTable_t *const __restrict__ tab, uchar *const __restrict__ f
{
int f;
uchar *baseName = NULL;
/* UNCOMMENT FOR DEBUG fileTableDisplay(tab); */
/* UNCOMMENT FOR DEBUG fileTableDisplay(tab); */
for(f = 0 ; f < tab->currMax ; ++f) {
baseName = tab->listeners[f].pLstn->pszBaseName;
if(!fnmatch((char*)baseName, (char*)fn, FNM_PATHNAME | FNM_PERIOD))
@ -1254,7 +1271,7 @@ fileTableSearch(fileTable_t *const __restrict__ tab, uchar *const __restrict__ f
}
if(f == tab->currMax)
f = -1;
dbgprintf("DDDD: imfile: fileTableSearch file '%s' - '%s', found:%d\n", fn, baseName, f);
DBGPRINTF("imfile: fileTableSearch file '%s' - '%s', found:%d\n", fn, baseName, f);
return f;
}
@ -1263,7 +1280,7 @@ fileTableSearchNoWildcard(fileTable_t *const __restrict__ tab, uchar *const __re
{
int f;
uchar *baseName = NULL;
/* UNCOMMENT FOR DEBUG fileTableDisplay(tab); */
/* UNCOMMENT FOR DEBUG fileTableDisplay(tab); */
for(f = 0 ; f < tab->currMax ; ++f) {
baseName = tab->listeners[f].pLstn->pszBaseName;
if (strcmp((const char*)baseName, (const char*)fn) == 0)
@ -1271,18 +1288,17 @@ fileTableSearchNoWildcard(fileTable_t *const __restrict__ tab, uchar *const __re
}
if(f == tab->currMax)
f = -1;
dbgprintf("DDDD: imfile: fileTableSearchNoWildcard file '%s' - '%s', found:%d\n", fn, baseName, f);
DBGPRINTF("imfile: fileTableSearchNoWildcard file '%s' - '%s', found:%d\n", fn, baseName, f);
return f;
}
/* add file to file table */
/* add file to file table */
static rsRetVal
fileTableAddFile(fileTable_t *const __restrict__ tab, lstn_t *const __restrict__ pLstn)
{
int j;
DEFiRet;
dbgprintf("DDDDD: imfile: fileTableAddFile\n");
/* UNCOMMENT FOR DEBUG fileTableDisplay(tab); */
/* UNCOMMENT FOR DEBUG fileTableDisplay(tab); */
for(j = 0 ; j < tab->currMax && tab->listeners[j].pLstn != pLstn ; ++j)
; /* just scan */
if(j < tab->currMax) {
@ -1354,6 +1370,7 @@ dirsAdd(uchar *dirName)
errmsg.LogError(0, RS_RET_OUT_OF_MEMORY,
"cannot alloc memory to monitor directory '%s' - ignoring",
dirName);
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
dirs = newDirTab;
allocMaxDirs = newMax;
@ -1366,7 +1383,7 @@ dirsAdd(uchar *dirName)
CHKiRet(fileTableInit(&dirs[currMaxDirs].configured, INIT_FILE_IN_DIR_TAB_SIZE));
++currMaxDirs;
dbgprintf("DDDD: imfile: added to dirs table: '%s'\n", dirName);
DBGPRINTF("imfile: added to dirs table: '%s'\n", dirName);
finalize_it:
RETiRet;
}
@ -1384,7 +1401,6 @@ dirsFindDir(uchar *dir)
; /* just scan, all done in for() */
if(i == currMaxDirs)
i = -1;
//dbgprintf("DDDD: dir '%s', found:%d\n", dir, i);
return i;
}
@ -1429,9 +1445,9 @@ dirsAddFile(lstn_t *__restrict__ pLstn, const int bActive)
dir = dirs + dirIdx;
CHKiRet(fileTableAddFile((bActive ? &dir->active : &dir->configured), pLstn));
dbgprintf("DDDD: imfile: associated file [%s] to directory %d[%s], Active = %d\n",
DBGPRINTF("imfile: associated file [%s] to directory %d[%s], Active = %d\n",
pLstn->pszFileName, dirIdx, dir->dirName, bActive);
/* UNCOMMENT FOR DEBUG fileTableDisplay(bActive ? &dir->active : &dir->configured); */
/* UNCOMMENT FOR DEBUG fileTableDisplay(bActive ? &dir->active : &dir->configured); */
finalize_it:
RETiRet;
}
@ -1448,7 +1464,7 @@ in_setupDirWatch(const int dirIdx)
goto done;
}
wdmapAdd(wd, dirIdx, NULL);
dbgprintf("DDDD: imfile: watch %d added for dir %s\n", wd, dirs[dirIdx].dirName);
DBGPRINTF("imfile: watch %d added for dir %s\n", wd, dirs[dirIdx].dirName);
done: return;
}
@ -1473,7 +1489,7 @@ startLstnFile(lstn_t *const __restrict__ pLstn)
goto done;
}
wdmapAdd(wd, -1, pLstn);
dbgprintf("DDDD: imfile: watch %d added for file %s\n", wd, pLstn->pszFileName);
DBGPRINTF("imfile: watch %d added for file %s\n", wd, pLstn->pszFileName);
dirsAddFile(pLstn, ACTIVE_FILE);
pollFile(pLstn, NULL);
done: return;
@ -1493,7 +1509,7 @@ in_setupFileWatchDynamic(lstn_t *pLstn, uchar *const __restrict__ newBaseName)
if(stat(fullfn, &fileInfo) != 0) {
char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
dbgprintf("imfile: ignoring file '%s' cannot stat(): %s\n",
DBGPRINTF("imfile: ignoring file '%s' cannot stat(): %s\n",
fullfn, errStr);
goto done;
}
@ -1516,7 +1532,7 @@ done: return;
* happen only for things after the watch has been activated.
*/
static void
in_setupFileWatchStatic(lstn_t *const __restrict__ pLstn)
in_setupFileWatchStatic(lstn_t *pLstn)
{
DBGPRINTF("imfile: adding file '%s' to configured table\n",
pLstn->pszFileName);
@ -1570,72 +1586,64 @@ static void
in_dbg_showEv(struct inotify_event *ev)
{
if(ev->mask & IN_IGNORED) {
dbgprintf("watch was REMOVED\n");
DBGPRINTF("watch was REMOVED\n");
} else if(ev->mask & IN_MODIFY) {
dbgprintf("watch was MODIFID\n");
DBGPRINTF("watch was MODIFID\n");
} else if(ev->mask & IN_ACCESS) {
dbgprintf("watch IN_ACCESS\n");
DBGPRINTF("watch IN_ACCESS\n");
} else if(ev->mask & IN_ATTRIB) {
dbgprintf("watch IN_ATTRIB\n");
DBGPRINTF("watch IN_ATTRIB\n");
} else if(ev->mask & IN_CLOSE_WRITE) {
dbgprintf("watch IN_CLOSE_WRITE\n");
DBGPRINTF("watch IN_CLOSE_WRITE\n");
} else if(ev->mask & IN_CLOSE_NOWRITE) {
dbgprintf("watch IN_CLOSE_NOWRITE\n");
DBGPRINTF("watch IN_CLOSE_NOWRITE\n");
} else if(ev->mask & IN_CREATE) {
dbgprintf("file was CREATED: %s\n", ev->name);
DBGPRINTF("file was CREATED: %s\n", ev->name);
} else if(ev->mask & IN_DELETE) {
dbgprintf("watch IN_DELETE\n");
DBGPRINTF("watch IN_DELETE\n");
} else if(ev->mask & IN_DELETE_SELF) {
dbgprintf("watch IN_DELETE_SELF\n");
DBGPRINTF("watch IN_DELETE_SELF\n");
} else if(ev->mask & IN_MOVE_SELF) {
dbgprintf("watch IN_MOVE_SELF\n");
DBGPRINTF("watch IN_MOVE_SELF\n");
} else if(ev->mask & IN_MOVED_FROM) {
dbgprintf("watch IN_MOVED_FROM\n");
DBGPRINTF("watch IN_MOVED_FROM\n");
} else if(ev->mask & IN_MOVED_TO) {
dbgprintf("watch IN_MOVED_TO\n");
DBGPRINTF("watch IN_MOVED_TO\n");
} else if(ev->mask & IN_OPEN) {
dbgprintf("watch IN_OPEN\n");
DBGPRINTF("watch IN_OPEN\n");
} else if(ev->mask & IN_ISDIR) {
dbgprintf("watch IN_ISDIR\n");
DBGPRINTF("watch IN_ISDIR\n");
} else {
dbgprintf("unknown mask code %8.8x\n", ev->mask);
DBGPRINTF("unknown mask code %8.8x\n", ev->mask);
}
}
static void
filesDisplay(void)
{
lstn_t *pLstn;
for(pLstn = runModConf->pRootLstn ; pLstn != NULL ; pLstn = pLstn->next)
dbgprintf("DDDD: imfile: files: [%p]: '%s'\n", pLstn, pLstn->pszFileName);
}
/* inotify told us that a file's wd was closed. We now need to remove
* the file from our internal structures. Remember that a different inode
* with the same name may already be in processing.
*/
static void
in_removeFile(const struct inotify_event *const ev,
const int dirIdx,
in_removeFile(const int dirIdx,
lstn_t *const __restrict__ pLstn)
{
filesDisplay(); // TODO: remove after initial unstable release(s)
uchar statefile[MAXFNAME];
uchar toDel[MAXFNAME];
int bDoRMState;
int wd;
uchar *statefn;
DBGPRINTF("imfile: remove listener '%s', wd %d\n",
pLstn->pszFileName, ev->wd);
DBGPRINTF("imfile: remove listener '%s', dirIdx %d\n",
pLstn->pszFileName, dirIdx);
if(pLstn->bRMStateOnDel) {
statefn = getStateFileName(pLstn, statefile, sizeof(statefile));
snprintf((char*)toDel, sizeof(toDel) / sizeof(uchar), "%s/%s",
snprintf((char*)toDel, sizeof(toDel), "%s/%s",
glbl.GetWorkDir(), (char*)statefn);
bDoRMState = 1;
} else {
bDoRMState = 0;
}
pollFile(pLstn, NULL); /* one final try to gather data */
/* delete listener data */
/* delete listener data */
DBGPRINTF("imfile: DELETING listener data for '%s' - '%s'\n", pLstn->pszBaseName, pLstn->pszFileName);
lstnDel(pLstn);
fileTableDelFile(&dirs[dirIdx].active, pLstn);
@ -1648,6 +1656,8 @@ filesDisplay(); // TODO: remove after initial unstable release(s)
"file \"%s\": %s", toDel, errStr);
}
}
wd = wdmapLookupListner(pLstn);
wdmapDel(wd);
}
static void
@ -1659,17 +1669,17 @@ in_handleDirEventCREATE(struct inotify_event *ev, const int dirIdx)
if(ftIdx >= 0) {
pLstn = dirs[dirIdx].active.listeners[ftIdx].pLstn;
} else {
dbgprintf("imfile: file '%s' not active in dir '%s'\n",
DBGPRINTF("imfile: file '%s' not active in dir '%s'\n",
ev->name, dirs[dirIdx].dirName);
ftIdx = fileTableSearch(&dirs[dirIdx].configured, (uchar*)ev->name);
if(ftIdx == -1) {
dbgprintf("imfile: file '%s' not associated with dir '%s'\n",
DBGPRINTF("imfile: file '%s' not associated with dir '%s'\n",
ev->name, dirs[dirIdx].dirName);
goto done;
}
pLstn = dirs[dirIdx].configured.listeners[ftIdx].pLstn;
}
dbgprintf("DDDD: imfile: file '%s' associated with dir '%s'\n", ev->name, dirs[dirIdx].dirName);
DBGPRINTF("imfile: file '%s' associated with dir '%s'\n", ev->name, dirs[dirIdx].dirName);
in_setupFileWatchDynamic(pLstn, (uchar*)ev->name);
done: return;
}
@ -1685,20 +1695,20 @@ in_handleDirEventDELETE(struct inotify_event *const ev, const int dirIdx)
{
const int ftIdx = fileTableSearch(&dirs[dirIdx].active, (uchar*)ev->name);
if(ftIdx == -1) {
dbgprintf("imfile: deleted file '%s' not active in dir '%s'\n",
DBGPRINTF("imfile: deleted file '%s' not active in dir '%s'\n",
ev->name, dirs[dirIdx].dirName);
goto done;
}
dbgprintf("DDDD: imfile: imfile delete processing for '%s'\n",
DBGPRINTF("imfile: imfile delete processing for '%s'\n",
dirs[dirIdx].active.listeners[ftIdx].pLstn->pszFileName);
in_removeFile(ev, dirIdx, dirs[dirIdx].active.listeners[ftIdx].pLstn);
in_removeFile(dirIdx, dirs[dirIdx].active.listeners[ftIdx].pLstn);
done: return;
}
static void
in_handleDirEvent(struct inotify_event *const ev, const int dirIdx)
{
dbgprintf("DDDD: imfile: handle dir event for %s\n", dirs[dirIdx].dirName);
DBGPRINTF("imfile: handle dir event for %s\n", dirs[dirIdx].dirName);
if((ev->mask & IN_CREATE)) {
in_handleDirEventCREATE(ev, dirIdx);
} else if((ev->mask & IN_DELETE)) {
@ -1727,40 +1737,30 @@ in_processEvent(struct inotify_event *ev)
wd_map_t *etry;
lstn_t *pLstn;
int iRet;
struct inotify_event evFileHelper;
int ftIdx;
int wd;
int wd;
DBGPRINTF("DDDD: imfile: in_processEvent (wd=%d) event Mask='0x%.8X'\n", ev->wd, ev->mask);
if (ev->mask & IN_IGNORED) {
wdmapDel(ev->wd);
if(ev->mask & IN_IGNORED) {
goto done;
} else if (ev->mask & IN_MOVED_FROM) {
} else if(ev->mask & IN_MOVED_FROM) {
/* Find wd entry and remove it */
etry = wdmapLookup(ev->wd);
if(etry != NULL) {
ftIdx = fileTableSearchNoWildcard(&dirs[etry->dirIdx].active, (uchar*)ev->name);
DBGPRINTF("DDDD: imfile: IN_MOVED_FROM Event (ftIdx=%d, name=%s)\n", ftIdx, ev->name);
DBGPRINTF("imfile: IN_MOVED_FROM Event (ftIdx=%d, name=%s)\n", ftIdx, ev->name);
if(ftIdx >= 0) {
/* Find listener and wd table index*/
pLstn = dirs[etry->dirIdx].active.listeners[ftIdx].pLstn;
wd = wdmapLookupListner(pLstn);
pLstn = dirs[etry->dirIdx].active.listeners[ftIdx].pLstn;
wd = wdmapLookupListner(pLstn);
/* Remove file from inotify watch */
iRet = inotify_rm_watch(ino_fd, wd); /* Note this will TRIGGER IN_IGNORED Event! */
if (iRet != 0) {
DBGPRINTF("imfile: inotify_rm_watch error %d (ftIdx=%d, wd=%d, name=%s)\n", errno, ftIdx, wd, ev->name);
} else {
DBGPRINTF("DDDD: imfile: inotify_rm_watch successfully removed file from watch (ftIdx=%d, wd=%d, name=%s)\n", ftIdx, wd, ev->name);
DBGPRINTF("imfile: inotify_rm_watch successfully removed file from watch (ftIdx=%d, wd=%d, name=%s)\n", ftIdx, wd, ev->name);
}
/* Create Event to remove file*/
evFileHelper.wd = wd;
evFileHelper.mask = IN_DELETE;
evFileHelper.cookie = 0;
evFileHelper.len = ev->len;
evFileHelper.name[0] = ev->name[0];
in_removeFile(&evFileHelper, etry->dirIdx, pLstn);
in_removeFile(etry->dirIdx, pLstn);
DBGPRINTF("imfile: IN_MOVED_FROM Event file removed file (wd=%d, name=%s)\n", wd, ev->name);
}
}
@ -1771,7 +1771,6 @@ in_processEvent(struct inotify_event *ev)
DBGPRINTF("imfile: could not lookup wd %d\n", ev->wd);
goto done;
}
dbgprintf("DDDD: imfile: wd %d got file %p, dir %d\n", ev->wd, etry->pLstn, etry->dirIdx);
if(etry->pLstn == NULL) { /* directory? */
in_handleDirEvent(ev, etry->dirIdx);
} else {
@ -1781,6 +1780,9 @@ done: return;
}
/* Monitor files in inotify mode */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align" /* TODO: how can we fix these warnings? */
/* Problem with the warnings: they seem to stem back from the way the API is structured */
static rsRetVal
do_inotify()
{
@ -1793,6 +1795,10 @@ do_inotify()
CHKiRet(wdmapInit());
CHKiRet(dirsInit());
ino_fd = inotify_init();
if(ino_fd < 0) {
errmsg.LogError(1, RS_RET_INOTIFY_INIT_FAILED, "imfile: Init inotify instance failed ");
return RS_RET_INOTIFY_INIT_FAILED;
}
DBGPRINTF("imfile: inotify fd %d\n", ino_fd);
in_setupInitialWatches();
@ -1801,14 +1807,11 @@ do_inotify()
if(rd < 0 && Debug) {
char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
dbgprintf("imfile: error during inotify: %s\n", errStr);
DBGPRINTF("imfile: error during inotify: %s\n", errStr);
}
currev = 0;
while(currev < rd) {
ev = (struct inotify_event*) (iobuf+currev);
dbgprintf("DDDD: imfile event notification: rd %d[%d], wd (%d, mask "
"%8.8x, cookie %4.4x, len %d)\n",
(int) rd, currev, ev->wd, ev->mask, ev->cookie, ev->len);
in_dbg_showEv(ev);
in_processEvent(ev);
currev += sizeof(struct inotify_event) + ev->len;
@ -1819,6 +1822,7 @@ finalize_it:
close(ino_fd);
RETiRet;
}
#pragma GCC diagnostic pop
#else /* #if HAVE_INOTIFY_INIT */
static rsRetVal
@ -1837,7 +1841,7 @@ do_inotify()
*/
BEGINrunInput
CODESTARTrunInput
DBGPRINTF("imfile: working in %s mode\n",
DBGPRINTF("imfile: working in %s mode\n",
(runModConf->opMode == OPMODE_POLLING) ? "polling" : "inotify");
if(runModConf->opMode == OPMODE_POLLING)
iRet = doPolling();
@ -1898,7 +1902,7 @@ persistStrmState(lstn_t *pLstn)
finalize_it:
if(psSF != NULL)
strm.Destruct(&psSF);
if(iRet != RS_RET_OK) {
errmsg.LogError(0, iRet, "imfile: could not persist state "
"file %s - data may be repeated on next "

View File

@ -435,7 +435,7 @@ OnSessAcceptGSS(tcpsrv_t *pThis, tcps_sess_t *pSess)
*/
char *buf;
int ret = 0;
CHKmalloc(buf = (char*) MALLOC(sizeof(char) * (glbl.GetMaxLine() + 1)));
CHKmalloc(buf = (char*) MALLOC(glbl.GetMaxLine() + 1));
prop.GetString(pSess->fromHostIP, &pszPeer, &lenPeer);

View File

@ -64,6 +64,7 @@ DEFobjCurrIf(net)
DEFobjCurrIf(errmsg)
struct modConfData_s {
int bIgnPrevMsg;
};
static struct configSettings_s {
@ -185,7 +186,7 @@ enqMsg(uchar *msg, uchar *pszTag, int iFacility, int iSeverity, struct timeval *
if(tp == NULL) {
CHKiRet(msgConstruct(&pMsg));
} else {
datetime.timeval2syslogTime(tp, &st);
datetime.timeval2syslogTime(tp, &st, TIME_IN_LOCALTIME);
CHKiRet(msgConstructWithTime(&pMsg, &st, tp->tv_sec));
}
MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
@ -233,7 +234,6 @@ readjournal() {
const void *get;
const void *pidget;
char *parse;
size_t length;
size_t pidlength;
@ -334,64 +334,7 @@ readjournal() {
/* get length of journal data prefix */
prefixlen = ((char *)equal_sign - (char *)get);
/* translate name fields to lumberjack names */
parse = (char *)get;
switch (*parse)
{
case '_':
++parse;
if (*parse == 'P') {
if (!strncmp(parse+1, "ID=", 4)) {
name = strdup("pid");
} else {
name = strndup(get, prefixlen);
}
} else if (*parse == 'G') {
if (!strncmp(parse+1, "ID=", 4)) {
name = strdup("gid");
} else {
name = strndup(get, prefixlen);
}
} else if (*parse == 'U') {
if (!strncmp(parse+1, "ID=", 4)) {
name = strdup("uid");
} else {
name = strndup(get, prefixlen);
}
} else if (*parse == 'E') {
if (!strncmp(parse+1, "XE=", 4)) {
name = strdup("exe");
} else {
name = strndup(get, prefixlen);
}
} else if (*parse == 'C') {
parse++;
if (*parse == 'O') {
if (!strncmp(parse+1, "MM=", 4)) {
name = strdup("appname");
} else {
name = strndup(get, prefixlen);
}
} else if (*parse == 'M') {
if (!strncmp(parse+1, "DLINE=", 7)) {
name = strdup("cmd");
} else {
name = strndup(get, prefixlen);
}
} else {
name = strndup(get, prefixlen);
}
} else {
name = strndup(get, prefixlen);
}
break;
default:
name = strndup(get, prefixlen);
break;
}
name = strndup(get, prefixlen);
CHKmalloc(name);
prefixlen++; /* remove '=' */
@ -588,6 +531,7 @@ finalize_it:
}
BEGINrunInput
int count = 0;
CODESTARTrunInput
CHKiRet(ratelimitNew(&ratelimiter, "imjournal", NULL));
dbgprintf("imjournal: ratelimiting burst %d, interval %d\n", cs.ratelimitBurst,
@ -616,7 +560,7 @@ CODESTARTrunInput
* signalled to do so. This, however, is handled by the framework.
*/
while (glbl.GetGlobalInputTermState() == 0) {
int count = 0, r;
int r;
r = sd_journal_next(j);
if (r < 0) {

View File

@ -241,7 +241,7 @@ readklog(modConfData_t *pModConf)
if((size_t) iMaxLine < sizeof(bufRcv) - 1) {
pRcv = bufRcv;
} else {
if((pRcv = (uchar*) MALLOC(sizeof(uchar) * (iMaxLine + 1))) == NULL) {
if((pRcv = (uchar*) MALLOC(iMaxLine + 1)) == NULL) {
iMaxLine = sizeof(bufRcv) - 1; /* better this than noting */
pRcv = bufRcv;
}

View File

@ -137,7 +137,7 @@ enqMsg(uchar *const __restrict__ msg, uchar* pszTag, const syslog_pri_t pri, str
if(tp == NULL) {
CHKiRet(msgConstruct(&pMsg));
} else {
datetime.timeval2syslogTime(tp, &st);
datetime.timeval2syslogTime(tp, &st, TIME_IN_LOCALTIME);
CHKiRet(msgConstructWithTime(&pMsg, &st, tp->tv_sec));
}
MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
@ -206,7 +206,7 @@ rsRetVal imklogLogIntMsg(syslog_pri_t priority, char *fmt, ...)
uchar msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */
va_start(ap, fmt);
vsnprintf((char*)msgBuf, sizeof(msgBuf) / sizeof(char), fmt, ap);
vsnprintf((char*)msgBuf, sizeof(msgBuf), fmt, ap);
va_end(ap);
logmsgInternal(NO_ERRCODE, priority, msgBuf, 0);

View File

@ -341,6 +341,8 @@ CODESTARTsetModCnf
mode = es_str2cstr(pvals[i].val.d.estr, NULL);
if(!strcasecmp(mode, "json")) {
loadModConf->statsFmt = statsFmt_JSON;
} else if(!strcasecmp(mode, "json-elasticsearch")) {
loadModConf->statsFmt = statsFmt_JSON_ES;
} else if(!strcasecmp(mode, "cee")) {
loadModConf->statsFmt = statsFmt_CEE;
} else if(!strcasecmp(mode, "legacy")) {
@ -468,6 +470,7 @@ CODESTARTfreeCnf
if(runModConf->logfd != -1)
close(runModConf->logfd);
free(runModConf->logfile);
free(runModConf->pszBindRuleset);
ENDfreeCnf

View File

@ -10,18 +10,18 @@
*
* File begun on 2010-08-10 by RGerhards
*
* Copyright 2007-2015 Rainer Gerhards and Adiscon GmbH.
* Copyright 2007-2016 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
* -or-
* see COPYING.ASL20 in the source distribution
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -49,6 +49,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/queue.h>
#include <netinet/tcp.h>
#include <stdint.h>
#include <zlib.h>
@ -94,6 +95,7 @@ DEFobjCurrIf(statsobj)
static void * wrkr(void *myself);
#define DFLT_wrkrMax 2
#define DFLT_inlineDispatchThreshold 1
#define COMPRESS_NEVER 0
#define COMPRESS_SINGLE_MSG 1 /* old, single-message compression */
@ -142,6 +144,7 @@ struct modConfData_s {
rsconf_t *pConf; /* our overall config object */
instanceConf_t *root, *tail;
int wrkrMax;
int bProcessOnPoller;
sbool configSetViaV2Method;
};
@ -150,7 +153,8 @@ static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current lo
/* module-global parameters */
static struct cnfparamdescr modpdescr[] = {
{ "threads", eCmdHdlrPositiveInt, 0 }
{ "threads", eCmdHdlrPositiveInt, 0 },
{ "processOnPoller", eCmdHdlrBinary, 0 }
};
static struct cnfparamblk modpblk =
{ CNFPARAMBLK_VERSION,
@ -270,12 +274,8 @@ struct ptcplstn_s {
*/
static struct wrkrInfo_s {
pthread_t tid; /* the worker's thread ID */
pthread_cond_t run;
struct epoll_event *event; /* event == NULL -> idle */
long long unsigned numCalled; /* how often was this called */
} wrkrInfo[16];
static pthread_mutex_t wrkrMut;
static pthread_cond_t wrkrIdle;
} *wrkrInfo;
static int wrkrRunning;
@ -291,15 +291,31 @@ typedef enum {
struct epolld_s {
epolld_type_t typ;
void *ptr;
int sock;
struct epoll_event ev;
};
typedef struct io_req_s {
STAILQ_ENTRY(io_req_s) link;
epolld_t *epd;
} io_req_t;
typedef struct io_q_s {
STAILQ_HEAD(ioq_s, io_req_s) q;
STATSCOUNTER_DEF(ctrEnq, mutCtrEnq);
int ctrMaxSz; //TODO: discuss potential problems around concurrent reads and writes
int sz; //current q size
statsobj_t *stats;
pthread_mutex_t mut;
pthread_cond_t wakeup_worker;
} io_q_t;
/* global data */
pthread_attr_t wrkrThrdAttr; /* Attribute for session threads; read only after startup */
static ptcpsrv_t *pSrvRoot = NULL;
static int epollfd = -1; /* (sole) descriptor for epoll */
static int iMaxLine; /* maximum size of a single message */
static io_q_t io_q;
/* forward definitions */
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
@ -747,10 +763,18 @@ finalize_it:
* rgerhards, 2008-03-14
* EXTRACT from tcps_sess.c
*/
static inline rsRetVal
processDataRcvd(ptcpsess_t *pThis, char c, struct syslogTime *stTime, time_t ttGenTime, multi_submit_t *pMultiSub)
static rsRetVal
processDataRcvd(ptcpsess_t *const __restrict__ pThis,
char **buff,
const int buffLen,
struct syslogTime *stTime,
const time_t ttGenTime,
multi_submit_t *pMultiSub,
unsigned *const __restrict__ pnMsgs)
{
DEFiRet;
char c = **buff;
int octatesToCopy, octatesToDiscard;
if(pThis->inputState == eAtStrtFram) {
if(pThis->bSuppOctetFram && isdigit((int) c)) {
@ -797,42 +821,60 @@ processDataRcvd(ptcpsess_t *pThis, char c, struct syslogTime *stTime, time_t ttG
}
} else {
assert(pThis->inputState == eInMsg);
if(pThis->iMsg >= iMaxLine) {
/* emergency, we now need to flush, no matter if we are at end of message or not... */
DBGPRINTF("error: message received is larger than max msg size, we split it\n");
doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
/* we might think if it is better to ignore the rest of the
* message than to treat it as a new one. Maybe this is a good
* candidate for a configuration parameter...
* rgerhards, 2006-12-04
*/
}
if(( (c == '\n')
|| ((pThis->pLstn->pSrv->iAddtlFrameDelim != TCPSRV_NO_ADDTL_DELIMITER)
&& (c == pThis->pLstn->pSrv->iAddtlFrameDelim))
) && pThis->eFraming == TCP_FRAMING_OCTET_STUFFING) { /* record delimiter? */
doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
pThis->inputState = eAtStrtFram;
} else {
/* IMPORTANT: here we copy the actual frame content to the message - for BOTH framing modes!
* If we have a message that is larger than the max msg size, we truncate it. This is the best
* we can do in light of what the engine supports. -- rgerhards, 2008-03-14
*/
if(pThis->iMsg < iMaxLine) {
*(pThis->pMsg + pThis->iMsg++) = c;
if (pThis->eFraming == TCP_FRAMING_OCTET_STUFFING) {
if(pThis->iMsg >= iMaxLine) {
/* emergency, we now need to flush, no matter if we are at end of message or not... */
DBGPRINTF("error: message received is larger than max msg size, we split it\n");
doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
++(*pnMsgs);
/* we might think if it is better to ignore the rest of the
* message than to treat it as a new one. Maybe this is a good
* candidate for a configuration parameter...
* rgerhards, 2006-12-04
*/
}
}
if(pThis->eFraming == TCP_FRAMING_OCTET_COUNTING) {
/* do we need to find end-of-frame via octet counting? */
pThis->iOctetsRemain--;
if(pThis->iOctetsRemain < 1) {
if ((c == '\n')
|| ((pThis->pLstn->pSrv->iAddtlFrameDelim != TCPSRV_NO_ADDTL_DELIMITER)
&& (c == pThis->pLstn->pSrv->iAddtlFrameDelim))
) { /* record delimiter? */
doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
++(*pnMsgs);
pThis->inputState = eAtStrtFram;
} else {
/* IMPORTANT: here we copy the actual frame content to the message - for BOTH framing modes!
* If we have a message that is larger than the max msg size, we truncate it. This is the best
* we can do in light of what the engine supports. -- rgerhards, 2008-03-14
*/
if(pThis->iMsg < iMaxLine) {
*(pThis->pMsg + pThis->iMsg++) = c;
}
}
} else {
assert(pThis->eFraming == TCP_FRAMING_OCTET_COUNTING);
octatesToCopy = pThis->iOctetsRemain;
octatesToDiscard = 0;
if (buffLen < octatesToCopy) {
octatesToCopy = buffLen;
}
if (octatesToCopy + pThis->iMsg > iMaxLine) {
octatesToDiscard = octatesToCopy - (iMaxLine - pThis->iMsg);
octatesToCopy = iMaxLine - pThis->iMsg;
}
memcpy(pThis->pMsg + pThis->iMsg, *buff, octatesToCopy);
pThis->iMsg += octatesToCopy;
pThis->iOctetsRemain -= (octatesToCopy + octatesToDiscard);
*buff += (octatesToCopy + octatesToDiscard - 1);
if (pThis->iOctetsRemain == 0) {
/* we have end of frame! */
doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
++(*pnMsgs);
pThis->inputState = eAtStrtFram;
}
}
}
finalize_it:
@ -862,13 +904,14 @@ DataRcvdUncompressed(ptcpsess_t *pThis, char *pData, size_t iLen, struct syslogT
multi_submit_t multiSub;
msg_t *pMsgs[CONF_NUM_MULTISUB];
char *pEnd;
unsigned nMsgs = 0;
DEFiRet;
assert(pData != NULL);
assert(iLen > 0);
if(ttGenTime == 0)
datetime.getCurrTime(stTime, &ttGenTime);
datetime.getCurrTime(stTime, &ttGenTime, TIME_IN_LOCALTIME);
multiSub.ppMsgs = pMsgs;
multiSub.maxElem = CONF_NUM_MULTISUB;
multiSub.nElem = 0;
@ -877,11 +920,15 @@ DataRcvdUncompressed(ptcpsess_t *pThis, char *pData, size_t iLen, struct syslogT
pEnd = pData + iLen; /* this is one off, which is intensional */
while(pData < pEnd) {
CHKiRet(processDataRcvd(pThis, *pData++, stTime, ttGenTime, &multiSub));
CHKiRet(processDataRcvd(pThis, &pData, pEnd - pData, stTime, ttGenTime, &multiSub, &nMsgs));
pData++;
}
iRet = multiSubmitFlush(&multiSub);
if(glblSenderKeepTrack)
statsRecordSender(propGetSzStr(pThis->peerName), nMsgs, ttGenTime);
finalize_it:
RETiRet;
}
@ -899,7 +946,7 @@ DataRcvdCompressed(ptcpsess_t *pThis, char *buf, size_t len)
// by simply updating the input and output sizes?
uint64_t outtotal;
datetime.getCurrTime(&stTime, &ttGenTime);
datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME);
outtotal = 0;
if(!pThis->bzInitDone) {
@ -977,11 +1024,12 @@ addEPollSock(epolld_type_t typ, void *ptr, int sock, epolld_t **pEpd)
DEFiRet;
epolld_t *epd = NULL;
CHKmalloc(epd = calloc(sizeof(epolld_t), 1));
CHKmalloc(epd = calloc(1, sizeof(epolld_t)));
epd->typ = typ;
epd->ptr = ptr;
epd->sock = sock;
*pEpd = epd;
epd->ev.events = EPOLLIN|EPOLLET;
epd->ev.events = EPOLLIN|EPOLLET|EPOLLONESHOT;
epd->ev.data.ptr = (void*) epd;
if(epoll_ctl(epollfd, EPOLL_CTL_ADD, sock, &(epd->ev)) != 0) {
@ -996,6 +1044,9 @@ addEPollSock(epolld_type_t typ, void *ptr, int sock, epolld_t **pEpd)
finalize_it:
if(iRet != RS_RET_OK) {
if (epd != NULL) {
errmsg.LogError(0, RS_RET_INTERNAL_ERROR, "error: could not initialize mutex for ptcp connection for socket: %d", sock);
}
free(epd);
}
RETiRet;
@ -1101,7 +1152,7 @@ addSess(ptcplstn_t *pLstn, int sock, prop_t *peerName, prop_t *peerIP)
ptcpsrv_t *pSrv = pLstn->pSrv;
CHKmalloc(pSess = malloc(sizeof(ptcpsess_t)));
CHKmalloc(pSess->pMsg = malloc(iMaxLine * sizeof(uchar)));
CHKmalloc(pSess->pMsg = malloc(iMaxLine));
pSess->pLstn = pLstn;
pSess->sock = sock;
pSess->bSuppOctetFram = pLstn->bSuppOctetFram;
@ -1114,8 +1165,6 @@ addSess(ptcplstn_t *pLstn, int sock, prop_t *peerName, prop_t *peerIP)
pSess->peerIP = peerIP;
pSess->compressionMode = pLstn->pSrv->compressionMode;
CHKiRet(addEPollSock(epolld_sess, pSess, sock, &pSess->epd));
/* add to start of server's listener list */
pSess->prev = NULL;
pthread_mutex_lock(&pSrv->mutSessLst);
@ -1125,6 +1174,8 @@ addSess(ptcplstn_t *pLstn, int sock, prop_t *peerName, prop_t *peerIP)
pSrv->pSess = pSess;
pthread_mutex_unlock(&pSrv->mutSessLst);
CHKiRet(addEPollSock(epolld_sess, pSess, sock, &pSess->epd));
finalize_it:
if(iRet != RS_RET_OK) {
if(pSess != NULL) {
@ -1368,15 +1419,14 @@ startWorkerPool(void)
{
int i;
wrkrRunning = 0;
if(runModConf->wrkrMax > 16)
runModConf->wrkrMax = 16; /* TODO: make dynamic? */
DBGPRINTF("imptcp: starting worker pool, %d workers\n", runModConf->wrkrMax);
pthread_mutex_init(&wrkrMut, NULL);
pthread_cond_init(&wrkrIdle, NULL);
wrkrInfo = calloc(runModConf->wrkrMax, sizeof(struct wrkrInfo_s));
if (wrkrInfo == NULL) {
DBGPRINTF("imptcp: worker-info array allocation failed.\n");
return;
}
for(i = 0 ; i < runModConf->wrkrMax ; ++i) {
/* init worker info structure! */
pthread_cond_init(&wrkrInfo[i].run, NULL);
wrkrInfo[i].event = NULL;
wrkrInfo[i].numCalled = 0;
pthread_create(&wrkrInfo[i].tid, &wrkrThrdAttr, wrkr, &(wrkrInfo[i]));
}
@ -1390,14 +1440,14 @@ stopWorkerPool(void)
{
int i;
DBGPRINTF("imptcp: stoping worker pool\n");
pthread_mutex_lock(&io_q.mut);
pthread_cond_broadcast(&io_q.wakeup_worker); /* awake wrkr if not running */
pthread_mutex_unlock(&io_q.mut);
for(i = 0 ; i < runModConf->wrkrMax ; ++i) {
pthread_cond_signal(&wrkrInfo[i].run); /* awake wrkr if not running */
pthread_join(wrkrInfo[i].tid, NULL);
DBGPRINTF("imptcp: info: worker %d was called %llu times\n", i, wrkrInfo[i].numCalled);
pthread_cond_destroy(&wrkrInfo[i].run);
}
pthread_cond_destroy(&wrkrIdle);
pthread_mutex_destroy(&wrkrMut);
free(wrkrInfo);
}
@ -1435,7 +1485,6 @@ startupServers()
RETiRet;
}
/* process new activity on listener. This means we need to accept a new
* connection.
*/
@ -1451,8 +1500,9 @@ lstnActivity(ptcplstn_t *pLstn)
DBGPRINTF("imptcp: new connection on listen socket %d\n", pLstn->sock);
while(glbl.GetGlobalInputTermState() == 0) {
localRet = AcceptConnReq(pLstn, &newSock, &peerName, &peerIP);
if(localRet == RS_RET_NO_MORE_DATA || glbl.GetGlobalInputTermState() == 1)
if(localRet == RS_RET_NO_MORE_DATA || glbl.GetGlobalInputTermState() == 1) {
break;
}
CHKiRet(localRet);
localRet = addSess(pLstn, newSock, peerName, peerIP);
if(localRet != RS_RET_OK) {
@ -1467,12 +1517,11 @@ finalize_it:
RETiRet;
}
/* process new activity on session. This means we need to accept data
* or close the session.
*/
static inline rsRetVal
sessActivity(ptcpsess_t *pSess)
sessActivity(ptcpsess_t *pSess, int *continue_polling)
{
int lenRcv;
int lenBuf;
@ -1500,6 +1549,7 @@ sessActivity(ptcpsess_t *pSess)
remsock = pSess->sock;
bEmitOnClose = 1;
}
*continue_polling = 0;
CHKiRet(closeSess(pSess)); /* close may emit more messages in strmzip mode! */
if(bEmitOnClose) {
errmsg.LogError(0, RS_RET_PEER_CLOSED_CONN, "imptcp session %d closed by "
@ -1510,6 +1560,7 @@ sessActivity(ptcpsess_t *pSess)
if(errno == EAGAIN || errno == EWOULDBLOCK)
break;
DBGPRINTF("imptcp: error on session socket %d - closed.\n", pSess->sock);
*continue_polling = 0;
closeSess(pSess); /* try clean-up by dropping session */
break;
}
@ -1525,26 +1576,106 @@ finalize_it:
* concurrently.
*/
static inline void
processWorkItem(struct epoll_event *event)
processWorkItem(epolld_t *epd)
{
epolld_t *epd;
int continue_polling = 1;
epd = (epolld_t*) event->data.ptr;
switch(epd->typ) {
case epolld_lstn:
/* listener never stops polling (except server shutdown) */
lstnActivity((ptcplstn_t *) epd->ptr);
break;
case epolld_sess:
sessActivity((ptcpsess_t *) epd->ptr);
sessActivity((ptcpsess_t *) epd->ptr, &continue_polling);
break;
default:
errmsg.LogError(0, RS_RET_INTERNAL_ERROR,
"error: invalid epolld_type_t %d after epoll", epd->typ);
"error: invalid epolld_type_t %d after epoll", epd->typ);
break;
}
if (continue_polling == 1) {
epoll_ctl(epollfd, EPOLL_CTL_MOD, epd->sock, &(epd->ev));
}
}
static rsRetVal
initIoQ() {
DEFiRet;
CHKiConcCtrl(pthread_mutex_init(&io_q.mut, NULL));
CHKiConcCtrl(pthread_cond_init(&io_q.wakeup_worker, NULL));
STAILQ_INIT(&io_q.q);
io_q.sz = 0;
io_q.ctrMaxSz = 0; /* TODO: discuss this and fix potential concurrent read/write issues */
CHKiRet(statsobj.Construct(&io_q.stats));
CHKiRet(statsobj.SetName(io_q.stats, (uchar*) "io-work-q"));
CHKiRet(statsobj.SetOrigin(io_q.stats, (uchar*) "imptcp"));
STATSCOUNTER_INIT(io_q.ctrEnq, io_q.mutCtrEnq);
CHKiRet(statsobj.AddCounter(io_q.stats, UCHAR_CONSTANT("enqueued"),
ctrType_IntCtr, CTR_FLAG_RESETTABLE, &io_q.ctrEnq));
CHKiRet(statsobj.AddCounter(io_q.stats, UCHAR_CONSTANT("maxqsize"),
ctrType_Int, CTR_FLAG_NONE, &io_q.ctrMaxSz));
CHKiRet(statsobj.ConstructFinalize(io_q.stats));
finalize_it:
RETiRet;
}
static void
destroyIoQ() {
io_req_t *n;
if (io_q.stats != NULL) {
statsobj.Destruct(&io_q.stats);
}
pthread_mutex_lock(&io_q.mut);
while (!STAILQ_EMPTY(&io_q.q)) {
n = STAILQ_FIRST(&io_q.q);
STAILQ_REMOVE_HEAD(&io_q.q, link);
errmsg.LogError(0, RS_RET_INTERNAL_ERROR, "imptcp: discarded enqueued io-work to allow shutdown - ignored");
free(n);
}
io_q.sz = 0;
pthread_mutex_unlock(&io_q.mut);
pthread_cond_destroy(&io_q.wakeup_worker);
pthread_mutex_destroy(&io_q.mut);
}
static inline rsRetVal
enqueueIoWork(epolld_t *epd, int dispatchInlineIfQueueFull) {
io_req_t *n;
int dispatchInline;
DEFiRet;
CHKmalloc(n = malloc(sizeof(io_req_t)));
n->epd = epd;
int inlineDispatchThreshold = DFLT_inlineDispatchThreshold * runModConf->wrkrMax;
dispatchInline = 0;
pthread_mutex_lock(&io_q.mut);
if (dispatchInlineIfQueueFull && io_q.sz > inlineDispatchThreshold) {
dispatchInline = 1;
} else {
STAILQ_INSERT_TAIL(&io_q.q, n, link);
io_q.sz++;
STATSCOUNTER_INC(io_q.ctrEnq, io_q.mutCtrEnq);
STATSCOUNTER_SETMAX_NOMUT(io_q.ctrMaxSz, io_q.sz);
pthread_cond_signal(&io_q.wakeup_worker);
}
pthread_mutex_unlock(&io_q.mut);
if (dispatchInline == 1) {
free(n);
processWorkItem(epd);
}
finalize_it:
if (iRet != RS_RET_OK) {
if (n == NULL) {
errmsg.LogError(0, iRet, "imptcp: couldn't allocate memory to enqueue io-request - ignored");
}
}
RETiRet;
}
/* This function is called to process a complete workset, that
* is a set of events returned from epoll.
*/
@ -1552,46 +1683,20 @@ static inline void
processWorkSet(int nEvents, struct epoll_event events[])
{
int iEvt;
int i;
int remainEvents;
remainEvents = nEvents;
epolld_t *epd;
for(iEvt = 0 ; (iEvt < nEvents) && (glbl.GetGlobalInputTermState() == 0) ; ++iEvt) {
if(remainEvents == 1) {
epd = (epolld_t*)events[iEvt].data.ptr;
if(runModConf->bProcessOnPoller && remainEvents == 1) {
/* process self, save context switch */
processWorkItem(events+iEvt);
processWorkItem(epd);
} else {
pthread_mutex_lock(&wrkrMut);
/* check if there is a free worker */
for(i = 0 ; (i < runModConf->wrkrMax) && (wrkrInfo[i].event != NULL) ; ++i)
/*do search*/;
if(i < runModConf->wrkrMax) {
/* worker free -> use it! */
wrkrInfo[i].event = events+iEvt;
++wrkrRunning;
pthread_cond_signal(&wrkrInfo[i].run);
pthread_mutex_unlock(&wrkrMut);
} else {
pthread_mutex_unlock(&wrkrMut);
/* no free worker, so we process this one ourselfs */
processWorkItem(events+iEvt);
}
enqueueIoWork(epd, runModConf->bProcessOnPoller);
}
--remainEvents;
}
if(nEvents > 1) {
/* we now need to wait until all workers finish. This is because the
* rest of this module can not handle the concurrency introduced
* by workers running during the epoll call.
*/
pthread_mutex_lock(&wrkrMut);
while(wrkrRunning > 0) {
pthread_cond_wait(&wrkrIdle, &wrkrMut);
}
pthread_mutex_unlock(&wrkrMut);
}
}
@ -1601,26 +1706,37 @@ static void *
wrkr(void *myself)
{
struct wrkrInfo_s *me = (struct wrkrInfo_s*) myself;
pthread_mutex_lock(&wrkrMut);
pthread_mutex_lock(&io_q.mut);
++wrkrRunning;
pthread_mutex_unlock(&io_q.mut);
io_req_t *n;
while(1) {
while(me->event == NULL && glbl.GetGlobalInputTermState() == 0) {
pthread_cond_wait(&me->run, &wrkrMut);
n = NULL;
pthread_mutex_lock(&io_q.mut);
if (io_q.sz == 0) {
--wrkrRunning;
if (glbl.GetGlobalInputTermState() != 0) {
pthread_mutex_unlock(&io_q.mut);
break;
} else {
pthread_cond_wait(&io_q.wakeup_worker, &io_q.mut);
}
++wrkrRunning;
}
if(glbl.GetGlobalInputTermState() == 1)
break;
pthread_mutex_unlock(&wrkrMut);
if (io_q.sz > 0) {
n = STAILQ_FIRST(&io_q.q);
STAILQ_REMOVE_HEAD(&io_q.q, link);
io_q.sz--;
}
pthread_mutex_unlock(&io_q.mut);
++me->numCalled;
processWorkItem(me->event);
pthread_mutex_lock(&wrkrMut);
me->event = NULL; /* indicate we are free again */
--wrkrRunning;
pthread_cond_signal(&wrkrIdle);
if (n != NULL) {
++me->numCalled;
processWorkItem(n->epd);
free(n);
}
}
pthread_mutex_unlock(&wrkrMut);
return NULL;
}
@ -1707,6 +1823,7 @@ CODESTARTbeginCnfLoad
pModConf->pConf = pConf;
/* init our settings */
loadModConf->wrkrMax = DFLT_wrkrMax;
loadModConf->bProcessOnPoller = 1;
loadModConf->configSetViaV2Method = 0;
bLegacyCnfModGlobalsPermitted = 1;
/* init legacy config vars */
@ -1735,6 +1852,8 @@ CODESTARTsetModCnf
continue;
if(!strcmp(modpblk.descr[i].name, "threads")) {
loadModConf->wrkrMax = (int) pvals[i].val.d.n;
} else if(!strcmp(modpblk.descr[i].name, "processOnPoller")) {
loadModConf->bProcessOnPoller = (int) pvals[i].val.d.n;
} else {
dbgprintf("imptcp: program error, non-handled "
"param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
@ -1855,6 +1974,7 @@ BEGINrunInput
int nEvents;
struct epoll_event events[128];
CODESTARTrunInput
initIoQ();
startWorkerPool();
DBGPRINTF("imptcp: now beginning to process input data\n");
while(glbl.GetGlobalInputTermState() == 0) {
@ -1893,7 +2013,7 @@ shutdownSrv(ptcpsrv_t *pSrv)
pLstn = pLstn->next;
DBGPRINTF("imptcp shutdown listen socket %d (rcvd %lld bytes, "
"decompressed %lld)\n", lstnDel->sock, lstnDel->rcvdBytes,
lstnDel->rcvdDecompressed);
lstnDel->rcvdDecompressed);
free(lstnDel->epd);
free(lstnDel);
}
@ -1914,6 +2034,7 @@ BEGINafterRun
ptcpsrv_t *pSrv, *srvDel;
CODESTARTafterRun
stopWorkerPool();
destroyIoQ();
/* we need to close everything that is still open */
pSrv = pSrvRoot;

View File

@ -248,7 +248,7 @@ getMsgs(thrdInfo_t *pThrd, int timeout)
if((size_t) iMaxLine < sizeof(bufRcv) - 1) {
pRcv = bufRcv;
} else {
CHKmalloc(pRcv = (uchar*) malloc(sizeof(uchar) * (iMaxLine + 1)));
CHKmalloc(pRcv = (uchar*) malloc(iMaxLine + 1));
}
while(pThrd->bShallStop != RSTRUE) {

View File

@ -417,7 +417,7 @@ processPacket(struct lstn_s *lstn, struct sockaddr_storage *frominetPrev, int *p
*pbIsPermitted = 1; /* no check -> everything permitted */
}
DBGPRINTF("recv(%d,%d),acl:%d,msg:%.128s\n", lstn->sock, (int) lenRcvBuf, *pbIsPermitted, rcvBuf);
DBGPRINTF("recv(%d,%d),acl:%d,msg:%.*s\n", lstn->sock, (int) lenRcvBuf, *pbIsPermitted, (int)lenRcvBuf, rcvBuf);
if(*pbIsPermitted != 0) {
/* we now create our own message object and submit it to the queue */
@ -459,7 +459,9 @@ processSocket(struct wrkrInfo_s *pWrkr, struct lstn_s *lstn, struct sockaddr_sto
{
DEFiRet;
int iNbrTimeUsed;
time_t ttGenTime;
time_t ttGenTime = 0; /* to avoid clang static analyzer false positive */
/* note: we do never use this time, because we always get a
* requery below on first loop iteration */
struct syslogTime stTime;
char errStr[1024];
msg_t *pMsgs[CONF_NUM_MULTISUB];
@ -507,7 +509,7 @@ processSocket(struct wrkrInfo_s *pWrkr, struct lstn_s *lstn, struct sockaddr_sto
}
if((runModConf->iTimeRequery == 0) || (iNbrTimeUsed++ % runModConf->iTimeRequery) == 0) {
datetime.getCurrTime(&stTime, &ttGenTime);
datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME);
}
pWrkr->ctrMsgsRcvd += nelem;
@ -580,7 +582,7 @@ processSocket(struct wrkrInfo_s *pWrkr, struct lstn_s *lstn, struct sockaddr_sto
++pWrkr->ctrMsgsRcvd;
if((runModConf->iTimeRequery == 0) || (iNbrTimeUsed++ % runModConf->iTimeRequery) == 0) {
datetime.getCurrTime(&stTime, &ttGenTime);
datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME);
}
CHKiRet(processPacket(lstn, frominetPrev, pbIsPermitted, pWrkr->pRcvBuf, lenRcvBuf, &stTime,
@ -1103,7 +1105,7 @@ BEGINactivateCnf
CODESTARTactivateCnf
/* caching various settings */
iMaxLine = glbl.GetMaxLine();
lenRcvBuf = (iMaxLine + 1) * sizeof(char);
lenRcvBuf = iMaxLine + 1;
# ifdef HAVE_RECVMMSG
lenRcvBuf *= runModConf->batchSize;
# endif

View File

@ -6,7 +6,7 @@
*
* File begun on 2007-12-20 by RGerhards (extracted from syslogd.c)
*
* Copyright 2007-2015 Rainer Gerhards and Adiscon GmbH.
* Copyright 2007-2016 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
@ -50,6 +50,7 @@
#include "parser.h"
#include "prop.h"
#include "debug.h"
#include "ruleset.h"
#include "unlimited_select.h"
#include "sd-daemon.h"
#include "statsobj.h"
@ -99,6 +100,7 @@ DEFobjCurrIf(net)
DEFobjCurrIf(parser)
DEFobjCurrIf(datetime)
DEFobjCurrIf(statsobj)
DEFobjCurrIf(ruleset)
statsobj_t *modStats;
@ -148,6 +150,7 @@ typedef struct lstn_s {
sbool bUseSysTimeStamp; /* use timestamp from system (instead of from message) */
sbool bUnlink; /* unlink&re-create socket at start and end of processing */
sbool bUseSpecialParser;/* use "canned" log socket parser instead of parser chain? */
ruleset_t *pRuleset;
} lstn_t;
static lstn_t *listeners;
@ -208,6 +211,8 @@ struct instanceConf_s {
sbool bUnlink;
sbool bUseSpecialParser;
sbool bParseHost;
uchar *pszBindRuleset; /* name of ruleset to bind to */
ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
struct instanceConf_s *next;
};
@ -273,6 +278,7 @@ static struct cnfparamdescr inppdescr[] = {
{ "usespecialparser", eCmdHdlrBinary, 0 },
{ "parsehostname", eCmdHdlrBinary, 0 },
{ "usepidfromsystem", eCmdHdlrBinary, 0 },
{ "ruleset", eCmdHdlrString, 0 },
{ "ratelimit.interval", eCmdHdlrInt, 0 },
{ "ratelimit.burst", eCmdHdlrInt, 0 },
{ "ratelimit.severity", eCmdHdlrInt, 0 }
@ -283,8 +289,7 @@ static struct cnfparamblk inppblk =
inppdescr
};
/* we do not use this, because we do not bind to a ruleset so far
* enable when this is changed: #include "im-helper.h" */ /* must be included AFTER the type definitions! */
#include "im-helper.h" /* must be included AFTER the type definitions! */
static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
@ -300,6 +305,8 @@ createInstance(instanceConf_t **pinst)
CHKmalloc(inst = MALLOC(sizeof(instanceConf_t)));
inst->sockName = NULL;
inst->pLogHostName = NULL;
inst->pszBindRuleset = NULL;
inst->pBindRuleset = NULL;
inst->ratelimitInterval = DFLT_ratelimitInterval;
inst->ratelimitBurst = DFLT_ratelimitBurst;
inst->ratelimitSeverity = DFLT_ratelimitSeverity;
@ -422,6 +429,7 @@ addListner(instanceConf_t *inst)
listeners[nfd].bWritePid = inst->bWritePid;
listeners[nfd].bUseSysTimeStamp = inst->bUseSysTimeStamp;
listeners[nfd].bUseSpecialParser = inst->bUseSpecialParser;
listeners[nfd].pRuleset = inst->pBindRuleset;
CHKiRet(ratelimitNew(&listeners[nfd].dflt_ratelimiter, "imuxsock", NULL));
ratelimitSetLinuxLike(listeners[nfd].dflt_ratelimiter,
listeners[nfd].ratelimitInterval,
@ -791,9 +799,9 @@ SubmitMsg(uchar *pRcv, int lenRcv, lstn_t *pLstn, struct ucred *cred, struct tim
findRatelimiter(pLstn, cred, &ratelimiter); /* ignore error, better so than others... */
if(ts == NULL) {
datetime.getCurrTime(&st, &tt);
datetime.getCurrTime(&st, &tt, TIME_IN_LOCALTIME);
} else {
datetime.timeval2syslogTime(ts, &st);
datetime.timeval2syslogTime(ts, &st, TIME_IN_LOCALTIME);
tt = ts->tv_sec;
}
@ -888,6 +896,9 @@ SubmitMsg(uchar *pRcv, int lenRcv, lstn_t *pLstn, struct ucred *cred, struct tim
pmsgbuf[toffs+1] = '\0';
MsgSetRawMsg(pMsg, (char*)pmsgbuf, toffs + 1);
if (pmsgbuf != msgbuf) {
free(pmsgbuf);
}
}
} else {
/* just add the unmodified message */
@ -959,6 +970,7 @@ SubmitMsg(uchar *pRcv, int lenRcv, lstn_t *pLstn, struct ucred *cred, struct tim
MsgSetRcvFrom(pMsg, pLstn->hostName == NULL ? glbl.GetLocalHostNameProp() : pLstn->hostName);
CHKiRet(MsgSetRcvFromIP(pMsg, pLocalHostIP));
MsgSetRuleset(pMsg, pLstn->pRuleset);
ratelimitAddMsg(ratelimiter, NULL, pMsg);
STATSCOUNTER_INC(ctrSubmit, mutCtrSubmit);
finalize_it:
@ -977,6 +989,9 @@ finalize_it:
* of the socket which is to be processed. This eases access to the
* growing number of properties. -- rgerhards, 2008-08-01
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align" /* TODO: how can we fix these warnings? */
/* Problem with the warnings: they seem to stem back from the way the API is structured */
static rsRetVal readSocket(lstn_t *pLstn)
{
DEFiRet;
@ -1005,7 +1020,7 @@ static rsRetVal readSocket(lstn_t *pLstn)
if((size_t) iMaxLine < sizeof(bufRcv) - 1) {
pRcv = bufRcv;
} else {
CHKmalloc(pRcv = (uchar*) MALLOC(sizeof(uchar) * (iMaxLine + 1)));
CHKmalloc(pRcv = (uchar*) MALLOC(iMaxLine + 1));
}
memset(&msgh, 0, sizeof(msgh));
@ -1060,6 +1075,7 @@ finalize_it:
RETiRet;
}
#pragma GCC diagnostic pop
/* activate current listeners */
@ -1285,6 +1301,8 @@ CODESTARTnewInpInst
inst->bParseHost = (int) pvals[i].val.d.n;
} else if(!strcmp(inppblk.descr[i].name, "usespecialparser")) {
inst->bUseSpecialParser = (int) pvals[i].val.d.n;
} else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if(!strcmp(inppblk.descr[i].name, "ratelimit.interval")) {
inst->ratelimitInterval = (int) pvals[i].val.d.n;
} else if(!strcmp(inppblk.descr[i].name, "ratelimit.burst")) {
@ -1328,8 +1346,20 @@ CODESTARTendCnfLoad
ENDendCnfLoad
/* function to generate error message if framework does not find requested ruleset */
static void
std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
{
errmsg.LogError(0, NO_ERRCODE, "imuxsock: ruleset '%s' for socket %s not found - "
"using default ruleset instead", inst->pszBindRuleset,
inst->sockName);
}
BEGINcheckCnf
instanceConf_t *inst;
CODESTARTcheckCnf
for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
std_checkRuleset(pModConf, inst);
}
ENDcheckCnf
@ -1384,6 +1414,7 @@ CODESTARTfreeCnf
free(pModConf->pLogSockName);
for(inst = pModConf->root ; inst != NULL ; ) {
free(inst->sockName);
free(inst->pszBindRuleset);
free(inst->pLogHostName);
del = inst;
inst = inst->next;
@ -1512,6 +1543,7 @@ CODESTARTmodExit
objRelease(prop, CORE_COMPONENT);
objRelease(statsobj, CORE_COMPONENT);
objRelease(datetime, CORE_COMPONENT);
objRelease(ruleset, CORE_COMPONENT);
ENDmodExit
@ -1573,6 +1605,7 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(statsobj, CORE_COMPONENT));
CHKiRet(objUse(datetime, CORE_COMPONENT));
CHKiRet(objUse(parser, CORE_COMPONENT));
CHKiRet(objUse(ruleset, CORE_COMPONENT));
DBGPRINTF("imuxsock version %s initializing\n", PACKAGE_VERSION);

View File

@ -361,13 +361,13 @@ done: *idx = i;
}
BEGINdoAction
msg_t *pMsg;
BEGINdoAction_NoStrings
msg_t **ppMsg = (msg_t **) pMsgData;
msg_t *pMsg = ppMsg[0];
uchar *msg;
int lenMsg;
int i;
CODESTARTdoAction
pMsg = (msg_t*) ppString[0];
lenMsg = getMSGLen(pMsg);
msg = getMSG(pMsg);
for(i = 0 ; i < lenMsg ; ++i) {

View File

@ -14,7 +14,7 @@
*
* File begun on 2012-02-23 by RGerhards
*
* Copyright 2013 Adiscon GmbH.
* Copyright 2013-2016 Adiscon GmbH.
*
* This file is part of rsyslog.
*
@ -54,7 +54,6 @@
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
MODULE_CNFNAME("mmaudit")
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
@ -191,7 +190,6 @@ audit_parse(uchar *buf, struct json_object **jsonRoot)
json_object_object_add(*jsonRoot, "data", json);
while(*buf) {
//dbgprintf("audit_parse, buf: '%s'\n", buf);
CHKiRet(parseName(&buf, name, sizeof(name)));
if(*buf != '=') {
ABORT_FINALIZE(RS_RET_ERR);
@ -200,7 +198,6 @@ audit_parse(uchar *buf, struct json_object **jsonRoot)
CHKiRet(parseValue(&buf, val, sizeof(val)));
jval = json_object_new_string(val);
json_object_object_add(json, name, jval);
dbgprintf("mmaudit: parsed %s=%s\n", name, val);
}
@ -209,8 +206,9 @@ finalize_it:
}
BEGINdoAction
msg_t *pMsg;
BEGINdoAction_NoStrings
msg_t **ppMsg = (msg_t **) pMsgData;
msg_t *pMsg = ppMsg[0];
uchar *buf;
int typeID;
struct json_object *jsonRoot;
@ -220,14 +218,12 @@ BEGINdoAction
char auditID[1024];
int bSuccess = 0;
CODESTARTdoAction
pMsg = (msg_t*) ppString[0];
/* note that we can performance-optimize the interface, but this also
* requires changes to the libraries. For now, we accept message
* duplication. -- rgerhards, 2010-12-01
*/
buf = getMSG(pMsg);
dbgprintf("mmaudit: msg is '%s'\n", buf);
while(*buf && isspace(*buf)) {
++buf;
}

View File

@ -143,7 +143,7 @@ CODESTARTfreeInstance
for (i = 0; i < pData->iParams; i++) {
free(pData->aParams[i]);
}
free(pData->aParams);
free(pData->aParams);
}
ENDfreeInstance
@ -217,7 +217,6 @@ processProgramReply(wrkrInstanceData_t *__restrict__ const pWrkrData, msg_t *con
int numCharsRead;
char *newptr;
dbgprintf("mmexternal: checking prog output, fd %d\n", pWrkrData->fdPipeIn);
numCharsRead = 0;
do {
if(pWrkrData->maxLenRespBuf < numCharsRead + 256) { /* 256 to permit at least a decent read */
@ -242,7 +241,6 @@ dbgprintf("mmexternal: checking prog output, fd %d\n", pWrkrData->fdPipeIn);
strcpy(pWrkrData->respBuf, "{}\n");
numCharsRead = 3;
}
dbgprintf("mmexternal: read state %lld, data '%s'\n", (long long) r, pWrkrData->respBuf);
if(Debug && r == -1) {
DBGPRINTF("mmexternal: error reading from external program: %s\n",
rs_strerror_r(errno, errStr, sizeof(errStr)));
@ -322,7 +320,7 @@ execBinary(wrkrInstanceData_t *pWrkrData, int fdStdin, int fdStdOutErr)
*/
rs_strerror_r(errno, errStr, sizeof(errStr));
DBGPRINTF("mmexternal: failed to execute binary '%s': %s\n",
pWrkrData->pData->szBinary, errStr);
pWrkrData->pData->szBinary, errStr);
}
/* we should never reach this point, but if we do, we terminate */
@ -510,10 +508,11 @@ finalize_it:
}
BEGINdoAction
BEGINdoAction_NoStrings
msg_t **ppMsg = (msg_t **) pMsgData;
msg_t *pMsg = ppMsg[0];
instanceData *pData;
CODESTARTdoAction
dbgprintf("DDDD:mmexternal processing message\n");
pData = pWrkrData->pData;
if(pData->bForceSingleInst)
pthread_mutex_lock(&pData->mut);
@ -521,13 +520,12 @@ dbgprintf("DDDD:mmexternal processing message\n");
openPipe(pWrkrData);
}
iRet = callExtProg(pWrkrData, (msg_t*)ppString[0]);
iRet = callExtProg(pWrkrData, pMsg);
if(iRet != RS_RET_OK)
iRet = RS_RET_SUSPENDED;
if(pData->bForceSingleInst)
pthread_mutex_unlock(&pData->mut);
dbgprintf("DDDD:mmexternal DONE processing message\n");
ENDdoAction
@ -566,8 +564,8 @@ CODESTARTnewActInst
if(!pvals[i].bUsed)
continue;
if(!strcmp(actpblk.descr[i].name, "binary")) {
estrBinary = pvals[i].val.d.estr;
estrParams = NULL;
estrBinary = pvals[i].val.d.estr;
estrParams = NULL;
/* Search for space */
c = es_getBufAddr(pvals[i].val.d.estr);
@ -575,18 +573,22 @@ CODESTARTnewActInst
while(iCnt < es_strlen(pvals[i].val.d.estr) ) {
if (c[iCnt] == ' ') {
/* Split binary name from parameters */
estrBinary = es_newStrFromSubStr ( pvals[i].val.d.estr, 0, iCnt );
estrParams = es_newStrFromSubStr ( pvals[i].val.d.estr, iCnt+1, es_strlen(pvals[i].val.d.estr));
estrBinary = es_newStrFromSubStr ( pvals[i].val.d.estr, 0, iCnt );
estrParams = es_newStrFromSubStr ( pvals[i].val.d.estr, iCnt+1, es_strlen(pvals[i].val.d.estr));
break;
}
iCnt++;
}
/* Assign binary and params */
pData->szBinary = (uchar*)es_str2cstr(estrBinary, NULL);
dbgprintf("mmexternal: szBinary = '%s'\n", pData->szBinary);
DBGPRINTF("mmexternal: szBinary = '%s'\n", pData->szBinary);
/* Check for Params! */
if (estrParams != NULL) {
dbgprintf("mmexternal: szParams = '%s'\n", es_str2cstr(estrParams, NULL) );
if(Debug) {
char *params = es_str2cstr(estrParams, NULL);
DBGPRINTF("mmexternal: szParams = '%s'\n", params);
free(params);
}
/* Count parameters if set */
c = es_getBufAddr(estrParams); /* Reset to beginning */
@ -594,10 +596,10 @@ CODESTARTnewActInst
iCnt = 0;
while(iCnt < es_strlen(estrParams) ) {
if (c[iCnt] == ' ' && c[iCnt-1] != '\\')
pData->iParams++;
pData->iParams++;
iCnt++;
}
dbgprintf("mmexternal: iParams = '%d'\n", pData->iParams);
DBGPRINTF("mmexternal: iParams = '%d'\n", pData->iParams);
/* Create argv Array */
CHKmalloc(pData->aParams = malloc( (pData->iParams+1) * sizeof(char*))); /* One more for first param */
@ -605,32 +607,32 @@ CODESTARTnewActInst
/* Second Loop, create parameter array*/
c = es_getBufAddr(estrParams); /* Reset to beginning */
iCnt = iStr = iPrm = 0;
estrTmp = NULL;
bInQuotes = FALSE;
estrTmp = NULL;
bInQuotes = FALSE;
/* Set first parameter to binary */
pData->aParams[iPrm] = strdup((char*)pData->szBinary);
dbgprintf("mmexternal: Param (%d): '%s'\n", iPrm, pData->aParams[iPrm]);
iPrm++;
pData->aParams[iPrm] = strdup((char*)pData->szBinary);
DBGPRINTF("mmexternal: Param (%d): '%s'\n", iPrm, pData->aParams[iPrm]);
iPrm++;
while(iCnt < es_strlen(estrParams) ) {
if ( c[iCnt] == ' ' && !bInQuotes ) {
/* Copy into Param Array! */
estrTmp = es_newStrFromSubStr( estrParams, iStr, iCnt-iStr);
estrTmp = es_newStrFromSubStr( estrParams, iStr, iCnt-iStr);
}
else if ( iCnt+1 >= es_strlen(estrParams) ) {
/* Copy rest of string into Param Array! */
estrTmp = es_newStrFromSubStr( estrParams, iStr, iCnt-iStr+1);
estrTmp = es_newStrFromSubStr( estrParams, iStr, iCnt-iStr+1);
}
else if (c[iCnt] == '"') {
/* switch inQuotes Mode */
bInQuotes = !bInQuotes;
bInQuotes = !bInQuotes;
}
if ( estrTmp != NULL ) {
pData->aParams[iPrm] = es_str2cstr(estrTmp, NULL);
pData->aParams[iPrm] = es_str2cstr(estrTmp, NULL);
iStr = iCnt+1; /* Set new start */
dbgprintf("mmexternal: Param (%d): '%s'\n", iPrm, pData->aParams[iPrm]);
DBGPRINTF("mmexternal: Param (%d): '%s'\n", iPrm, pData->aParams[iPrm]);
es_deleteStr( estrTmp );
estrTmp = NULL;
estrTmp = NULL;
iPrm++;
}
@ -638,7 +640,7 @@ CODESTARTnewActInst
iCnt++;
}
/* NULL last parameter! */
pData->aParams[iPrm] = NULL;
pData->aParams[iPrm] = NULL;
}
} else if(!strcmp(actpblk.descr[i].name, "output")) {
@ -660,7 +662,7 @@ CODESTARTnewActInst
ABORT_FINALIZE(RS_RET_INVLD_INTERFACE_INPUT);
}
} else {
dbgprintf("mmexternal: program error, non-handled param '%s'\n", actpblk.descr[i].name);
DBGPRINTF("mmexternal: program error, non-handled param '%s'\n", actpblk.descr[i].name);
}
}

View File

@ -226,22 +226,24 @@ parse_fields(instanceData *pData, msg_t *pMsg, uchar *msgtext, int lenMsg)
DBGPRINTF("mmfields: field %d: '%s'\n", field, buf);
snprintf((char*)fieldname, sizeof(fieldname), "f%d", field);
fieldname[sizeof(fieldname)-1] = '\0';
jval = json_object_new_string((char*)fieldbuf);
jval = json_object_new_string((char*)buf);
json_object_object_add(json, (char*)fieldname, jval);
field++;
}
msgAddJSON(pMsg, pData->jsonRoot, json, 0, 0);
finalize_it:
if(buf != fieldbuf)
free(buf);
RETiRet;
}
BEGINdoAction
msg_t *pMsg;
BEGINdoAction_NoStrings
msg_t **ppMsg = (msg_t **) pMsgData;
msg_t *pMsg = ppMsg[0];
uchar *msg;
int lenMsg;
CODESTARTdoAction
pMsg = (msg_t*) ppString[0];
lenMsg = getMSGLen(pMsg);
msg = getMSG(pMsg);
CHKiRet(parse_fields(pWrkrData->pData, pMsg, msg, lenMsg));

View File

@ -214,8 +214,9 @@ finalize_it:
RETiRet;
}
BEGINdoAction
msg_t *pMsg;
BEGINdoAction_NoStrings
msg_t **ppMsg = (msg_t **) pMsgData;
msg_t *pMsg = ppMsg[0];
uchar *buf;
rs_size_t len;
int bSuccess = 0;
@ -224,7 +225,6 @@ BEGINdoAction
instanceData *pData;
CODESTARTdoAction
pData = pWrkrData->pData;
pMsg = (msg_t*) ppString[0];
/* note that we can performance-optimize the interface, but this also
* requires changes to the libraries. For now, we accept message
* duplication. -- rgerhards, 2010-12-01
@ -260,7 +260,6 @@ ENDdoAction
static inline void
setInstParamDefaults(instanceData *pData)
{
pData->cookie = NULL;
pData->bUseRawMsg = 0;
}
@ -297,8 +296,6 @@ CODESTARTnewActInst
if(pData->container == NULL)
CHKmalloc(pData->container = (uchar*) strdup("!"));
if(pData->cookie == NULL)
CHKmalloc(pData->cookie = strdup("@cee:"));
pData->lenCookie = strlen(pData->cookie);
CODE_STD_FINALIZERnewActInst
cnfparamvalsDestruct(pvals, &actpblk);

View File

@ -222,15 +222,15 @@ BEGINtryResume
CODESTARTtryResume
ENDtryResume
BEGINdoAction
msg_t *pMsg;
BEGINdoAction_NoStrings
msg_t **ppMsg = (msg_t **) pMsgData;
msg_t *pMsg = ppMsg[0];
uchar *buf;
rs_size_t len;
int r;
struct json_object *json = NULL;
unsigned short freeBuf = 0;
CODESTARTdoAction
pMsg = (msg_t*) ppString[0];
if(pWrkrData->pData->bUseRawMsg) {
getRawMsg(pMsg, &buf, &len);
} else if (pWrkrData->pData->varDescr) {

View File

@ -333,11 +333,11 @@ finalize_it:
}
BEGINdoAction
msg_t *pMsg;
BEGINdoAction_NoStrings
msg_t **ppMsg = (msg_t **) pMsgData;
msg_t *pMsg = ppMsg[0];
CODESTARTdoAction
DBGPRINTF("mmpstrucdata: enter\n");
pMsg = (msg_t*) ppString[0];
if(!MsgHasStructuredData(pMsg)) {
DBGPRINTF("mmpstrucdata: message does not have structured data\n");
FINALIZE;

View File

@ -211,6 +211,8 @@ fixInvldMBSeq(instanceData *pData, uchar *msg, int lenMsg, int strtIdx, int *end
{
int i;
/* startIdx and seqLen always set if bytesLeft is set,
which is required before this function is called */
*endIdx = strtIdx + seqLen;
if(*endIdx > lenMsg)
*endIdx = lenMsg;
@ -222,16 +224,17 @@ static inline void
doUTF8(instanceData *pData, uchar *msg, int lenMsg)
{
uchar c;
int8_t seqLen, bytesLeft = 0;
int8_t seqLen = 0, bytesLeft = 0;
uint32_t codepoint;
int strtIdx, endIdx;
int strtIdx = 0, endIdx = 0;
int i;
for(i = 0 ; i < lenMsg ; ++i) {
c = msg[i];
if(bytesLeft) {
if((c & 0xc0) != 0x80) {
/* sequence invalid, invalidate all bytes */
/* sequence invalid, invalidate all bytes
startIdx is always set if bytesLeft is set */
fixInvldMBSeq(pData, msg, lenMsg, strtIdx, &endIdx,
seqLen);
i = endIdx - 1;
@ -242,6 +245,8 @@ doUTF8(instanceData *pData, uchar *msg, int lenMsg)
if(bytesLeft == 0) {
/* too-large codepoint? */
if(codepoint > 0x10FFFF) {
/* sequence invalid, invalidate all bytes
startIdx is always set if bytesLeft is set */
fixInvldMBSeq(pData, msg, lenMsg,
strtIdx, &endIdx,
seqLen);
@ -285,12 +290,12 @@ doUTF8(instanceData *pData, uchar *msg, int lenMsg)
}
}
BEGINdoAction
msg_t *pMsg;
BEGINdoAction_NoStrings
msg_t **ppMsg = (msg_t **) pMsgData;
msg_t *pMsg = ppMsg[0];
uchar *msg;
int lenMsg;
CODESTARTdoAction
pMsg = (msg_t*) ppString[0];
lenMsg = getMSGLen(pMsg);
msg = getMSG(pMsg);
if(pWrkrData->pData->mode == MODE_CC) {

View File

@ -4,7 +4,7 @@
* NOTE: read comments in module-template.h for more specifics!
*
* Copyright 2011 Nathan Scott.
* Copyright 2009-2014 Rainer Gerhards and Adiscon GmbH.
* Copyright 2009-2016 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
@ -38,6 +38,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if defined(__FreeBSD__)
#include <unistd.h>
#endif
#include "cJSON/cjson.h"
#include "conf.h"
#include "syslogd-types.h"
@ -49,6 +52,10 @@
#include "cfsysline.h"
#include "unicode-helper.h"
#ifndef O_LARGEFILE
# define O_LARGEFILE 0
#endif
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
MODULE_CNFNAME("omelasticsearch")
@ -148,7 +155,6 @@ ENDcreateInstance
BEGINcreateWrkrInstance
CODESTARTcreateWrkrInstance
dbgprintf("omelasticsearch: createWrkrInstance\n");
pWrkrData->restURL = NULL;
if(pData->bulkmode) {
pWrkrData->batch.currTpl1 = NULL;
@ -161,7 +167,6 @@ dbgprintf("omelasticsearch: createWrkrInstance\n");
}
CHKiRet(curlSetup(pWrkrData, pWrkrData->pData));
finalize_it:
dbgprintf("DDDD: createWrkrInstance,pData %p/%p, pWrkrData %p\n", pData, pWrkrData->pData, pWrkrData);
ENDcreateWrkrInstance
BEGINisCompatibleWithFeature
@ -314,6 +319,8 @@ getIndexTypeAndParent(instanceData *pData, uchar **tpls,
uchar **srchIndex, uchar **srchType, uchar **parent,
uchar **bulkId)
{
if(tpls == NULL)
return;
if(pData->dynSrchIdx) {
*srchIndex = tpls[1];
if(pData->dynSrchType) {
@ -380,7 +387,7 @@ static rsRetVal
setCurlURL(wrkrInstanceData_t *pWrkrData, instanceData *pData, uchar **tpls)
{
char authBuf[1024];
uchar *searchIndex;
uchar *searchIndex = 0;
uchar *searchType;
uchar *parent;
uchar *bulkId;
@ -388,10 +395,12 @@ setCurlURL(wrkrInstanceData_t *pWrkrData, instanceData *pData, uchar **tpls)
int rLocal;
int r;
DEFiRet;
char separator;
const int bulkmode = pData->bulkmode;
setBaseURL(pData, &url);
if(pData->bulkmode) {
if(bulkmode) {
r = es_addBuf(&url, "_bulk", sizeof("_bulk")-1);
parent = NULL;
} else {
@ -400,17 +409,23 @@ setCurlURL(wrkrInstanceData_t *pWrkrData, instanceData *pData, uchar **tpls)
if(r == 0) r = es_addChar(&url, '/');
if(r == 0) r = es_addBuf(&url, (char*)searchType, ustrlen(searchType));
}
if(r == 0) r = es_addChar(&url, '?');
separator = '?';
if(pData->asyncRepl) {
if(r == 0) r = es_addBuf(&url, "replication=async&",
sizeof("replication=async&")-1);
if(r == 0) r = es_addChar(&url, separator);
if(r == 0) r = es_addBuf(&url, "replication=async", sizeof("replication=async")-1);
separator = '&';
}
if(pData->timeout != NULL) {
if(r == 0) r = es_addChar(&url, separator);
if(r == 0) r = es_addBuf(&url, "timeout=", sizeof("timeout=")-1);
if(r == 0) r = es_addBuf(&url, (char*)pData->timeout, ustrlen(pData->timeout));
if(r == 0) r = es_addChar(&url, '&');
separator = '&';
}
if(parent != NULL) {
if(r == 0) r = es_addChar(&url, separator);
if(r == 0) r = es_addBuf(&url, "parent=", sizeof("parent=")-1);
if(r == 0) es_addBuf(&url, (char*)parent, ustrlen(parent));
}
@ -447,9 +462,9 @@ buildBatch(wrkrInstanceData_t *pWrkrData, uchar *message, uchar **tpls)
{
int length = strlen((char *)message);
int r;
uchar *searchIndex;
uchar *searchIndex = 0;
uchar *searchType;
uchar *parent;
uchar *parent = NULL;
uchar *bulkId = NULL;
DEFiRet;
# define META_STRT "{\"index\":{\"_index\": \""
@ -522,7 +537,7 @@ getDataErrorDefault(wrkrInstanceData_t *pWrkrData,cJSON **pReplyRoot,uchar *reqm
* Sections are marked by { and }
*/
static inline rsRetVal
getSection(const char* bulkRequest,char **bulkRequestNextSectionStart )
getSection(const char* bulkRequest, const char **bulkRequestNextSectionStart )
{
DEFiRet;
char* index =0;
@ -545,24 +560,24 @@ getSection(const char* bulkRequest,char **bulkRequestNextSectionStart )
* and sets lastLocation pointer to the location till which bulkrequest has been parsed.(used as input to make function thread safe.)
*/
static inline rsRetVal
getSingleRequest(const char* bulkRequest, char** singleRequest ,char **lastLocation)
getSingleRequest(const char* bulkRequest, char** singleRequest, const char **lastLocation)
{
DEFiRet;
char *req = bulkRequest;
char *start = bulkRequest;
const char *req = bulkRequest;
const char *start = bulkRequest;
if (getSection(req,&req)!=RS_RET_OK)
ABORT_FINALIZE(RS_RET_ERR);
if (getSection(req,&req)!=RS_RET_OK)
ABORT_FINALIZE(RS_RET_ERR);
*singleRequest = (char*) calloc (req - start+ 1 + 1,sizeof(char));/* (req - start+ 1 == length of data + 1 for terminal char)*/
if (*singleRequest==NULL) ABORT_FINALIZE(RS_RET_ERR);
memcpy(*singleRequest,start,req - start);
*lastLocation=req;
CHKmalloc(*singleRequest = (char*) calloc (req - start+ 1 + 1,1));
/* (req - start+ 1 == length of data + 1 for terminal char)*/
memcpy(*singleRequest,start,req - start);
*lastLocation=req;
finalize_it:
RETiRet;
finalize_it:
RETiRet;
}
/*
@ -608,7 +623,7 @@ parseRequestAndResponseForContext(wrkrInstanceData_t *pWrkrData,cJSON **pReplyRo
numitems = cJSON_GetArraySize(items);
DBGPRINTF("omelasticsearch: Entire request %s\n",reqmsg);
char *lastReqRead= (char*)reqmsg;
const char *lastReqRead= (char*)reqmsg;
DBGPRINTF("omelasticsearch: %d items in reply\n", numitems);
for(i = 0 ; i < numitems ; ++i) {
@ -654,7 +669,7 @@ parseRequestAndResponseForContext(wrkrInstanceData_t *pWrkrData,cJSON **pReplyRo
response = cJSON_PrintUnformatted(create);
if(*response==NULL)
if(response==NULL)
{
free(request);/*as its has been assigned.*/
DBGPRINTF("omelasticsearch: Error getting cJSON_PrintUnformatted. Cannot continue\n");
@ -719,8 +734,11 @@ getDataErrorOnly(context *ctx,int itemStatus,char *request,char *response)
* Dumps all requests of bulk insert interleaved with request and response
*/
static inline rsRetVal
getDataInterleaved(context *ctx,int itemStatus,char *request,char *response)
static rsRetVal
getDataInterleaved(context *ctx,
int __attribute__((unused)) itemStatus,
char *request,
char *response)
{
DEFiRet;
cJSON *interleaved =0;
@ -1060,7 +1078,6 @@ finalize_it:
BEGINbeginTransaction
CODESTARTbeginTransaction
dbgprintf("omelasticsearch: beginTransaction, pWrkrData %p, pData %p\n", pWrkrData, pWrkrData->pData);
if(!pWrkrData->pData->bulkmode) {
FINALIZE;
}
@ -1081,14 +1098,12 @@ CODESTARTdoAction
ppString, 1));
}
finalize_it:
dbgprintf("omelasticsearch: result doAction: %d (bulkmode %d)\n", iRet, pWrkrData->pData->bulkmode);
ENDdoAction
BEGINendTransaction
char *cstr = NULL;
CODESTARTendTransaction
dbgprintf("omelasticsearch: endTransaction init\n");
/* End Transaction only if batch data is not empty */
if (pWrkrData->batch.data != NULL ) {
cstr = es_str2cstr(pWrkrData->batch.data, NULL);
@ -1099,7 +1114,6 @@ dbgprintf("omelasticsearch: endTransaction init\n");
dbgprintf("omelasticsearch: endTransaction, pWrkrData->batch.data is NULL, nothing to send. \n");
finalize_it:
free(cstr);
dbgprintf("omelasticsearch: endTransaction done with %d\n", iRet);
ENDendTransaction
/* elasticsearch POST result string ... useful for debugging */
@ -1209,7 +1223,7 @@ CODESTARTnewActInst
}else if(!strcmp(actpblk.descr[i].name, "interleaved")) {
pData->interleaved = pvals[i].val.d.n;
} else if(!strcmp(actpblk.descr[i].name, "serverport")) {
pData->port = (int) pvals[i].val.d.n, NULL;
pData->port = (int) pvals[i].val.d.n;
} else if(!strcmp(actpblk.descr[i].name, "uid")) {
pData->uid = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if(!strcmp(actpblk.descr[i].name, "pwd")) {

View File

@ -213,7 +213,7 @@ filePrepare(file_t *pFile)
/* file does not exist, create it (and eventually parent directories */
if(1) { // check if bCreateDirs
len = ustrlen(pFile->name) + 1;
CHKmalloc(pszWork = MALLOC(sizeof(uchar) * len));
CHKmalloc(pszWork = MALLOC(len));
memcpy(pszWork, pFile->name, len);
for(p = pszWork+1 ; *p ; p++)
if(*p == '/') {
@ -312,7 +312,6 @@ fileWrite(file_t *pFile, uchar *buf, size_t *lenWrite)
}
}
dbgprintf("XXXXX: omhdfs writing %u bytes\n", *lenWrite);
tSize num_written_bytes = hdfsWrite(pFile->fs, pFile->fh, buf, *lenWrite);
if((unsigned) num_written_bytes != *lenWrite) {
errmsg.LogError(errno, RS_RET_ERR_HDFS_WRITE,
@ -371,7 +370,6 @@ addData(instanceData *pData, uchar *buf)
memcpy((char*) pData->ioBuf + pData->offsBuf, buf, len);
pData->offsBuf += len;
} else {
dbgprintf("XXXXX: not enough room, need to flush\n");
CHKiRet(fileWrite(pData->pFile, pData->ioBuf, &pData->offsBuf));
if(len >= sizeof(pData->ioBuf)) {
CHKiRet(fileWrite(pData->pFile, buf, &len));
@ -426,7 +424,7 @@ ENDtryResume
BEGINbeginTransaction
CODESTARTbeginTransaction
dbgprintf("omhdfs: beginTransaction\n");
DBGPRINTF("omhdfs: beginTransaction\n");
ENDbeginTransaction
@ -444,7 +442,7 @@ ENDdoAction
BEGINendTransaction
instanceData *pData = pWrkrData->pData;
CODESTARTendTransaction
dbgprintf("omhdfs: endTransaction\n");
DBGPRINTF("omhdfs: endTransaction\n");
pthread_mutex_lock(&mutDoAct);
if(pData->offsBuf != 0) {
DBGPRINTF("omhdfs: data unwritten at end of transaction, persisting...\n");

View File

@ -2,7 +2,7 @@ pkglib_LTLIBRARIES = omkafka.la
omkafka_la_SOURCES = omkafka.c
omkafka_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
omkafka_la_LDFLAGS = -module -avoid-version -lrdkafka
omkafka_la_LDFLAGS = -module -avoid-version $(LIBRDKAFKA_LIBS)
omkafka_la_LIBADD =
EXTRA_DIST =

View File

@ -52,6 +52,7 @@ DEFobjCurrIf(errmsg)
DEFobjCurrIf(statsobj)
statsobj_t *kafkaStats;
int ctrQueueSize;
STATSCOUNTER_DEF(ctrTopicSubmit, mutCtrTopicSubmit);
STATSCOUNTER_DEF(ctrKafkaFail, mutCtrKafkaFail);
STATSCOUNTER_DEF(ctrCacheMiss, mutCtrCacheMiss);
@ -113,7 +114,7 @@ typedef struct _instanceData {
sbool autoPartition;
int fixedPartition;
int nPartitions;
int32_t currPartition;
uint32_t currPartition;
int nConfParams;
struct kafka_params *confParams;
int nTopicConfParams;
@ -160,16 +161,16 @@ BEGINinitConfVars /* (re)set config variables to default values */
CODESTARTinitConfVars
ENDinitConfVars
static inline int
static inline uint32_t
getPartition(instanceData *const __restrict__ pData)
{
if (pData->autoPartition) {
return RD_KAFKA_PARTITION_UA;
} else {
return (pData->fixedPartition == NO_FIXED_PARTITION) ?
ATOMIC_INC_AND_FETCH_int(&pData->currPartition,
ATOMIC_INC_AND_FETCH_unsigned(&pData->currPartition,
&pData->mutCurrPartition) % pData->nPartitions
: pData->fixedPartition;
: (unsigned) pData->fixedPartition;
}
}
@ -830,6 +831,7 @@ finalize_it:
if(iRet != RS_RET_OK) {
iRet = RS_RET_SUSPENDED;
}
STATSCOUNTER_SETMAX_NOMUT(ctrQueueSize, rd_kafka_outq_len(pData->rk));
STATSCOUNTER_INC(ctrTopicSubmit, mutCtrTopicSubmit);
RETiRet;
}
@ -938,18 +940,22 @@ CODESTARTnewActInst
CHKmalloc(pData->confParams = malloc(sizeof(struct kafka_params) *
pvals[i].val.d.ar->nmemb ));
for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
CHKiRet(processKafkaParam(es_str2cstr(pvals[i].val.d.ar->arr[j], NULL),
char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
CHKiRet(processKafkaParam(cstr,
&pData->confParams[j].name,
&pData->confParams[j].val));
free(cstr);
}
} else if(!strcmp(actpblk.descr[i].name, "topicconfparam")) {
pData->nTopicConfParams = pvals[i].val.d.ar->nmemb;
CHKmalloc(pData->topicConfParams = malloc(sizeof(struct kafka_params) *
pvals[i].val.d.ar->nmemb ));
for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
CHKiRet(processKafkaParam(es_str2cstr(pvals[i].val.d.ar->arr[j], NULL),
char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
CHKiRet(processKafkaParam(cstr,
&pData->topicConfParams[j].name,
&pData->topicConfParams[j].val));
free(cstr);
}
} else if(!strcmp(actpblk.descr[i].name, "errorfile")) {
pData->errorFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
@ -1055,6 +1061,9 @@ CODEmodInit_QueryRegCFSLineHdlr
STATSCOUNTER_INIT(ctrTopicSubmit, mutCtrTopicSubmit);
CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"submitted",
ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrTopicSubmit));
ctrQueueSize = 0;
CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"maxoutqsize",
ctrType_Int, CTR_FLAG_NONE, &ctrQueueSize));
STATSCOUNTER_INIT(ctrKafkaFail, mutCtrKafkaFail);
CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"failures",
ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaFail));

View File

@ -51,7 +51,7 @@
#include "conf.h"
#undef HAVE_DBI_TXSUPP
#warning transaction support disabled in v8 -- TODO: reenable
/* transaction support disabled in v8 -- TODO: reenable */
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
@ -229,7 +229,7 @@ reportDBError(instanceData *pData, int bSilent)
errmsg.LogError(0, NO_ERRCODE, "unknown DB error occured - could not obtain connection handle");
} else { /* we can ask dbi for the error description... */
uDBErrno = dbi_conn_error(pData->conn, &pszDbiErr);
snprintf(errMsg, sizeof(errMsg)/sizeof(char), "db error (%d): %s\n", uDBErrno, pszDbiErr);
snprintf(errMsg, sizeof(errMsg), "db error (%d): %s\n", uDBErrno, pszDbiErr);
if(bSilent || uDBErrno == pData->uLastDBErrno)
dbgprintf("libdbi, DBError(silent): %s\n", errMsg);
else {
@ -617,7 +617,6 @@ INITLegCnfVars
CODEmodInit_QueryRegCFSLineHdlr
# ifndef HAVE_DBI_TXSUPP
DBGPRINTF("omlibdbi: no transaction support in libdbi\n");
# warning libdbi too old - transactions are not enabled (use 0.9 or later)
# endif
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(regCfSysLineHdlr2((uchar *)"actionlibdbidriverdirectory", 0, eCmdHdlrGetWord, NULL, &cs.dbiDrvrDir, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));

View File

@ -436,8 +436,8 @@ Send(int sock, char *msg, size_t len)
DBGPRINTF("message not (smtp/tcp)send, errno %d", errno);
ABORT_FINALIZE(RS_RET_TCP_SEND_ERROR);
}
} else if(lenSend != (ssize_t) len) {
offsBuf += len; /* on to next round... */
} else if(lenSend != (ssize_t) (len - offsBuf)) {
offsBuf += lenSend; /* on to next round... */
} else {
FINALIZE;
}
@ -502,7 +502,7 @@ finalize_it:
/* read response line from server
*/
static rsRetVal
readResponseLn(wrkrInstanceData_t *pWrkrData, char *pLn, size_t lenLn)
readResponseLn(wrkrInstanceData_t *pWrkrData, char *pLn, size_t lenLn, size_t *const __restrict__ respLen)
{
DEFiRet;
size_t i = 0;
@ -518,10 +518,11 @@ readResponseLn(wrkrInstanceData_t *pWrkrData, char *pLn, size_t lenLn)
if(i < (lenLn - 1)) /* if line is too long, we simply discard the rest */
pLn[i++] = c;
} while(1);
pLn[i] = '\0';
DBGPRINTF("smtp server response: %s\n", pLn); /* do not remove, this is helpful in troubleshooting SMTP probs! */
finalize_it:
pLn[i] = '\0';
*respLen = i;
RETiRet;
}
@ -536,17 +537,16 @@ readResponse(wrkrInstanceData_t *pWrkrData, int *piState, int iExpected)
DEFiRet;
int bCont;
char buf[128];
size_t respLen;
assert(pWrkrData != NULL);
assert(piState != NULL);
bCont = 1;
do {
CHKiRet(readResponseLn(pWrkrData, buf, sizeof(buf)));
/* note: the code below is not 100% clean as we may have received less than 4 characters.
* However, as we have a fixed size this will not create a vulnerability. An error will
* also most likely be generated, so it is quite acceptable IMHO -- rgerhards, 2008-04-08
*/
CHKiRet(readResponseLn(pWrkrData, buf, sizeof(buf), &respLen));
if(respLen < 4) /* we treat too-short responses as error */
ABORT_FINALIZE(RS_RET_SMTP_ERROR);
if(buf[3] != '-') { /* last or only response line? */
bCont = 0;
*piState = buf[0] - '0';

View File

@ -287,8 +287,8 @@ getDefaultBSON(msg_t *pMsg)
/* TODO: move to datetime? Refactor in any case! rgerhards, 2012-03-30 */
ts_gen = (gint64) datetime.syslogTime2time_t(&pMsg->tTIMESTAMP) * 1000; /* ms! */
dbgprintf("ommongodb: ts_gen is %lld\n", (long long) ts_gen);
dbgprintf("ommongodb: secfrac is %d, precision %d\n", pMsg->tTIMESTAMP.secfrac, pMsg->tTIMESTAMP.secfracPrecision);
DBGPRINTF("ommongodb: ts_gen is %lld\n", (long long) ts_gen);
DBGPRINTF("ommongodb: secfrac is %d, precision %d\n", pMsg->tTIMESTAMP.secfrac, pMsg->tTIMESTAMP.secfracPrecision);
if(pMsg->tTIMESTAMP.secfracPrecision > 3) {
secfrac = pMsg->tTIMESTAMP.secfrac / i10pow(pMsg->tTIMESTAMP.secfracPrecision - 3);
} else if(pMsg->tTIMESTAMP.secfracPrecision < 3) {

View File

@ -168,7 +168,7 @@ static void reportDBError(wrkrInstanceData_t *pWrkrData, int bSilent)
errmsg.LogError(0, NO_ERRCODE, "unknown DB error occured - could not obtain MySQL handle");
} else { /* we can ask mysql for the error description... */
uMySQLErrno = mysql_errno(pWrkrData->hmysql);
snprintf(errMsg, sizeof(errMsg)/sizeof(char), "db error (%d): %s\n", uMySQLErrno,
snprintf(errMsg, sizeof(errMsg), "db error (%d): %s\n", uMySQLErrno,
mysql_error(pWrkrData->hmysql));
if(bSilent || uMySQLErrno == pWrkrData->uLastMySQLErrno)
dbgprintf("mysql, DBError(silent): %s\n", errMsg);
@ -205,7 +205,7 @@ static rsRetVal initMySQL(wrkrInstanceData_t *pWrkrData, int bSilent)
int err=errno;
if(fp==NULL){
char msg[512];
snprintf(msg,sizeof(msg)/sizeof(char),"Could not open '%s' for reading",pData->configfile);
snprintf(msg,sizeof(msg),"Could not open '%s' for reading",pData->configfile);
if(bSilent) {
char errStr[512];
rs_strerror_r(err, errStr, sizeof(errStr));
@ -332,7 +332,7 @@ CODESTARTnewActInst
strncpy(pData->dbsrv, cstr, sizeof(pData->dbsrv));
free(cstr);
} else if(!strcmp(actpblk.descr[i].name, "serverport")) {
pData->dbsrvPort = (int) pvals[i].val.d.n, NULL;
pData->dbsrvPort = (int) pvals[i].val.d.n;
} else if(!strcmp(actpblk.descr[i].name, "db")) {
cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
strncpy(pData->dbname, cstr, sizeof(pData->dbname));
@ -366,7 +366,6 @@ CODESTARTnewActInst
OMSR_RQD_TPL_OPT_SQL));
}
CODE_STD_FINALIZERnewActInst
dbgprintf("XXXX: added param, iRet %d\n", iRet);
cnfparamvalsDestruct(pvals, &actpblk);
ENDnewActInst

View File

@ -49,7 +49,6 @@
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
MODULE_CNFNAME("ompgsql")
/* internal structures
*/
@ -145,7 +144,7 @@ static void reportDBError(instanceData *pData, int bSilent)
errmsg.LogError(0, NO_ERRCODE, "unknown DB error occured - could not obtain PgSQL handle");
} else { /* we can ask pgsql for the error description... */
ePgSQLStatus = PQstatus(pData->f_hpgsql);
snprintf(errMsg, sizeof(errMsg)/sizeof(char), "db error (%d): %s\n", ePgSQLStatus,
snprintf(errMsg, sizeof(errMsg), "db error (%d): %s\n", ePgSQLStatus,
PQerrorMessage(pData->f_hpgsql));
if(bSilent || ePgSQLStatus == pData->eLastPgSQLStatus)
dbgprintf("pgsql, DBError(silent): %s\n", errMsg);
@ -311,7 +310,6 @@ ENDdoAction
BEGINendTransaction
CODESTARTendTransaction
iRet = writePgSQL((uchar*) "commit;", pWrkrData->pData); /* TODO: make user-configurable */
dbgprintf("ompgsql: endTransaction\n");
ENDendTransaction
#endif
@ -404,7 +402,7 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
# warning: transaction support missing for v8
/* TODO: transaction support missing for v8 */
bCoreSupportsBatching= 0;
DBGPRINTF("ompgsql: transactions are not yet supported on v8\n");

View File

@ -139,7 +139,7 @@ CODESTARTfreeInstance
for (i = 0; i < pData->iParams; i++) {
free(pData->aParams[i]);
}
free(pData->aParams);
free(pData->aParams);
}
ENDfreeInstance
@ -170,7 +170,6 @@ writeProgramOutput(wrkrInstanceData_t *__restrict__ const pWrkrData,
char errStr[1024];
ssize_t r;
dbgprintf("omprog: writeProgramOutput, fd %d\n", pWrkrData->fdOutput);
if(pWrkrData->fdOutput == -1) {
pWrkrData->fdOutput = open((char*)pWrkrData->pData->outputFileName,
O_WRONLY | O_APPEND | O_CREAT, 0600);
@ -282,10 +281,10 @@ execBinary(wrkrInstanceData_t *pWrkrData, int fdStdin, int fdStdOutErr)
*/
rs_strerror_r(errno, errStr, sizeof(errStr));
DBGPRINTF("omprog: failed to execute binary '%s': %s\n",
pWrkrData->pData->szBinary, errStr);
pWrkrData->pData->szBinary, errStr);
openlog("rsyslogd", 0, LOG_SYSLOG);
syslog(LOG_ERR, "omprog: failed to execute binary '%s': %s\n",
pWrkrData->pData->szBinary, errStr);
pWrkrData->pData->szBinary, errStr);
}
/* we should never reach this point, but if we do, we terminate */
@ -512,8 +511,8 @@ CODESTARTnewActInst
if(!pvals[i].bUsed)
continue;
if(!strcmp(actpblk.descr[i].name, "binary")) {
estrBinary = pvals[i].val.d.estr;
estrParams = NULL;
estrBinary = pvals[i].val.d.estr;
estrParams = NULL;
/* Search for space */
c = es_getBufAddr(pvals[i].val.d.estr);
@ -521,18 +520,22 @@ CODESTARTnewActInst
while(iCnt < es_strlen(pvals[i].val.d.estr) ) {
if (c[iCnt] == ' ') {
/* Split binary name from parameters */
estrBinary = es_newStrFromSubStr ( pvals[i].val.d.estr, 0, iCnt );
estrParams = es_newStrFromSubStr ( pvals[i].val.d.estr, iCnt+1, es_strlen(pvals[i].val.d.estr));
estrBinary = es_newStrFromSubStr ( pvals[i].val.d.estr, 0, iCnt );
estrParams = es_newStrFromSubStr ( pvals[i].val.d.estr, iCnt+1, es_strlen(pvals[i].val.d.estr));
break;
}
iCnt++;
}
/* Assign binary and params */
pData->szBinary = (uchar*)es_str2cstr(estrBinary, NULL);
dbgprintf("omprog: szBinary = '%s'\n", pData->szBinary);
DBGPRINTF("omprog: szBinary = '%s'\n", pData->szBinary);
/* Check for Params! */
if (estrParams != NULL) {
dbgprintf("omprog: szParams = '%s'\n", es_str2cstr(estrParams, NULL) );
if(Debug) {
char *params = es_str2cstr(estrParams, NULL);
dbgprintf("omprog: szParams = '%s'\n", params);
free(params);
}
/* Count parameters if set */
c = es_getBufAddr(estrParams); /* Reset to beginning */
@ -540,10 +543,10 @@ CODESTARTnewActInst
iCnt = 0;
while(iCnt < es_strlen(estrParams) ) {
if (c[iCnt] == ' ' && c[iCnt-1] != '\\')
pData->iParams++;
pData->iParams++;
iCnt++;
}
dbgprintf("omprog: iParams = '%d'\n", pData->iParams);
DBGPRINTF("omprog: iParams = '%d'\n", pData->iParams);
/* Create argv Array */
CHKmalloc(pData->aParams = malloc( (pData->iParams+1) * sizeof(char*))); /* One more for first param */
@ -551,32 +554,32 @@ CODESTARTnewActInst
/* Second Loop, create parameter array*/
c = es_getBufAddr(estrParams); /* Reset to beginning */
iCnt = iStr = iPrm = 0;
estrTmp = NULL;
bInQuotes = FALSE;
estrTmp = NULL;
bInQuotes = FALSE;
/* Set first parameter to binary */
pData->aParams[iPrm] = strdup((char*)pData->szBinary);
dbgprintf("omprog: Param (%d): '%s'\n", iPrm, pData->aParams[iPrm]);
iPrm++;
pData->aParams[iPrm] = strdup((char*)pData->szBinary);
DBGPRINTF("omprog: Param (%d): '%s'\n", iPrm, pData->aParams[iPrm]);
iPrm++;
while(iCnt < es_strlen(estrParams) ) {
if ( c[iCnt] == ' ' && !bInQuotes ) {
/* Copy into Param Array! */
estrTmp = es_newStrFromSubStr( estrParams, iStr, iCnt-iStr);
estrTmp = es_newStrFromSubStr( estrParams, iStr, iCnt-iStr);
}
else if ( iCnt+1 >= es_strlen(estrParams) ) {
/* Copy rest of string into Param Array! */
estrTmp = es_newStrFromSubStr( estrParams, iStr, iCnt-iStr+1);
estrTmp = es_newStrFromSubStr( estrParams, iStr, iCnt-iStr+1);
}
else if (c[iCnt] == '"') {
/* switch inQuotes Mode */
bInQuotes = !bInQuotes;
bInQuotes = !bInQuotes;
}
if ( estrTmp != NULL ) {
pData->aParams[iPrm] = es_str2cstr(estrTmp, NULL);
pData->aParams[iPrm] = es_str2cstr(estrTmp, NULL);
iStr = iCnt+1; /* Set new start */
dbgprintf("omprog: Param (%d): '%s'\n", iPrm, pData->aParams[iPrm]);
DBGPRINTF("omprog: Param (%d): '%s'\n", iPrm, pData->aParams[iPrm]);
es_deleteStr( estrTmp );
estrTmp = NULL;
estrTmp = NULL;
iPrm++;
}
@ -584,7 +587,7 @@ CODESTARTnewActInst
iCnt++;
}
/* NULL last parameter! */
pData->aParams[iPrm] = NULL;
pData->aParams[iPrm] = NULL;
}
} else if(!strcmp(actpblk.descr[i].name, "output")) {
@ -592,28 +595,27 @@ CODESTARTnewActInst
} else if(!strcmp(actpblk.descr[i].name, "forcesingleinstance")) {
pData->bForceSingleInst = (int) pvals[i].val.d.n;
} else if(!strcmp(actpblk.descr[i].name, "hup.signal")) {
const char *const signal = es_str2cstr(pvals[i].val.d.estr, NULL);
if(!strcmp(signal, "HUP"))
const char *const sig = es_str2cstr(pvals[i].val.d.estr, NULL);
if(!strcmp(sig, "HUP"))
pData->iHUPForward = SIGHUP;
else if(!strcmp(signal, "USR1"))
else if(!strcmp(sig, "USR1"))
pData->iHUPForward = SIGUSR1;
else if(!strcmp(signal, "USR2"))
else if(!strcmp(sig, "USR2"))
pData->iHUPForward = SIGUSR2;
else if(!strcmp(signal, "INT"))
else if(!strcmp(sig, "INT"))
pData->iHUPForward = SIGINT;
else if(!strcmp(signal, "TERM"))
else if(!strcmp(sig, "TERM"))
pData->iHUPForward = SIGTERM;
else {
errmsg.LogError(0, RS_RET_CONF_PARAM_INVLD,
"omprog: hup.signal '%s' in hup.signal parameter",
signal);
"omprog: hup.signal '%s' in hup.signal parameter", sig);
ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD);
}
free((void*)signal);
free((void*)sig);
} else if(!strcmp(actpblk.descr[i].name, "template")) {
pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else {
dbgprintf("omprog: program error, non-handled param '%s'\n", actpblk.descr[i].name);
DBGPRINTF("omprog: program error, non-handled param '%s'\n", actpblk.descr[i].name);
}
}

View File

@ -16,7 +16,7 @@
*
* File begun on 2008-03-13 by RGerhards
*
* Copyright 2008-2014 Adiscon GmbH.
* Copyright 2008-2016 Adiscon GmbH.
*
* This file is part of rsyslog.
*
@ -259,8 +259,10 @@ CODESTARTfreeInstance
free(pData->caCertFile);
free(pData->myCertFile);
free(pData->myPrivKeyFile);
for(i = 0 ; i < pData->permittedPeers.nmemb ; ++i) {
free(pData->permittedPeers.name[i]);
if(pData->permittedPeers.name != NULL) {
for(i = 0 ; i < pData->permittedPeers.nmemb ; ++i) {
free(pData->permittedPeers.name[i]);
}
}
ENDfreeInstance
@ -290,6 +292,7 @@ setInstParamDefaults(instanceData *pData)
pData->caCertFile = NULL;
pData->myCertFile = NULL;
pData->myPrivKeyFile = NULL;
pData->permittedPeers.name = NULL;
pData->permittedPeers.nmemb = 0;
}
@ -340,7 +343,7 @@ CODESTARTnewActInst
pData->permittedPeers.nmemb = pvals[i].val.d.ar->nmemb;
CHKmalloc(pData->permittedPeers.name =
malloc(sizeof(uchar*) * pData->permittedPeers.nmemb));
for(j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
for(j = 0 ; j < pData->permittedPeers.nmemb ; ++j) {
pData->permittedPeers.name[j] = (uchar*)es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
}
} else {
@ -442,7 +445,7 @@ finalize_it:
BEGINbeginTransaction
CODESTARTbeginTransaction
dbgprintf("omrelp: beginTransaction\n");
DBGPRINTF("omrelp: beginTransaction\n");
if(!pWrkrData->bIsConnected) {
CHKiRet(doConnect(pWrkrData));
}

View File

@ -10,7 +10,7 @@
*
* File begun on 2009-11-02 by RGerhards
*
* Copyright 2009-2013 Rainer Gerhards and Adiscon GmbH.
* Copyright 2009-2016 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
@ -125,10 +125,11 @@ ENDtryResume
* rsyslog procesing we can not really slow down the producer any longer, as we already
* work off a queue. So a delay would just block out execution for longer than needed.
*/
BEGINdoAction
BEGINdoAction_NoStrings
msg_t **ppMsg = (msg_t **) pMsgData;
msg_t *pMsg;
CODESTARTdoAction
CHKmalloc(pMsg = MsgDup((msg_t*) ppString[0]));
CHKmalloc(pMsg = MsgDup(ppMsg[0]));
DBGPRINTF(":omruleset: forwarding message %p to ruleset %s[%p]\n", pMsg,
(char*) pWrkrData->pData->pszRulesetName, pWrkrData->pData->pRuleset);
MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);

View File

@ -3,7 +3,7 @@
*
* File begun on 2014-07-07 by RGerhards
*
* Copyright 2014 Rainer Gerhards and Adiscon GmbH.
* Copyright 2014-2015 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
@ -55,7 +55,8 @@ DEFobjCurrIf(datetime)
/* parser instance parameters */
static struct cnfparamdescr parserpdescr[] = {
{ "present.origin", eCmdHdlrBinary, 0 }
{ "present.origin", eCmdHdlrBinary, 0 },
{ "present.xr", eCmdHdlrBinary, 0 }
};
static struct cnfparamblk parserpblk =
{ CNFPARAMBLK_VERSION,
@ -65,6 +66,7 @@ static struct cnfparamblk parserpblk =
struct instanceConf_s {
int bOriginPresent; /* is ORIGIN field present? */
int bXrPresent; /* is XR? */
};
BEGINisCompatibleWithFeature
@ -86,17 +88,26 @@ createInstance(instanceConf_t **pinst)
DEFiRet;
CHKmalloc(inst = MALLOC(sizeof(instanceConf_t)));
inst->bOriginPresent = 0;
inst->bXrPresent = 0;
*pinst = inst;
finalize_it:
RETiRet;
}
BEGINfreeParserInst
CODESTARTfreeParserInst
dbgprintf("pmciscoios: free parser instance %p\n", pInst);
ENDfreeParserInst
BEGINnewParserInst
struct cnfparamvals *pvals;
struct cnfparamvals *pvals = NULL;
int i;
CODESTARTnewParserInst
DBGPRINTF("newParserInst (pmciscoios)\n");
inst = NULL;
CHKiRet(createInstance(&inst));
if(lst == NULL)
@ -120,26 +131,28 @@ CODESTARTnewParserInst
dbgprintf("pmciscoios: program error, non-handled "
"param '%s'\n", parserpblk.descr[i].name);
}
if(!strcmp(parserpblk.descr[i].name, "present.xr")) {
inst->bXrPresent = (int) pvals[i].val.d.n;
} else {
dbgprintf("pmciscoios: program error, non-handled "
"param '%s'\n", parserpblk.descr[i].name);
}
}
finalize_it:
CODE_STD_FINALIZERnewParserInst
if(lst != NULL)
cnfparamvalsDestruct(pvals, &parserpblk);
if(iRet != RS_RET_OK)
freeParserInst(inst);
ENDnewParserInst
BEGINfreeParserInst
CODESTARTfreeParserInst
dbgprintf("pmciscoios: free parser instance %p\n", pInst);
ENDfreeParserInst
BEGINparse2
uchar *p2parse;
long long msgcounter;
int lenMsg;
int i;
int iHostname;
int iHostname = 0;
uchar bufParseTAG[512];
uchar bufParseHOSTNAME[CONF_HOSTNAME_MAXSIZE]; /* used by origin */
CODESTARTparse2
@ -184,7 +197,23 @@ CODESTARTparse2
p2parse += 2;
}
/* XR RSP (optional) */
if(pInst->bXrPresent) {
while( lenMsg > 1
&& !(*p2parse == ':')) {
--lenMsg;
++p2parse;
}
/* delimiter check */
if(lenMsg < 2) {
DBGPRINTF("pmciscoios: fail after XR: '%s'\n", p2parse);
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
p2parse += 1;
}
/* TIMESTAMP */
if(p2parse[0] == '*' || p2parse[0] == '.') p2parse++;
if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg, PARSE3164_TZSTRING, NO_PERMIT_YEAR_AFTER_TIME) == RS_RET_OK) {
if(pMsg->dfltTZ[0] != '\0')
applyDfltTZ(&pMsg->tTIMESTAMP, pMsg->dfltTZ);
@ -194,6 +223,20 @@ CODESTARTparse2
}
/* Note: date parser strips ": ", so we cannot do the delimiter check here */
/* XR RSP (optional) */
if(pInst->bXrPresent) {
while( lenMsg > 1
&& !(*p2parse == '%')) {
--lenMsg;
p2parse++;
}
/* delimiter check */
if(lenMsg < 2) {
DBGPRINTF("pmciscoios: fail after XR tag search: '%s'\n", p2parse);
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
}
/* parse SYSLOG TAG. must always start with '%', else we have a field mismatch */
if(lenMsg < 1 || *p2parse != '%') {
DBGPRINTF("pmciscoios: fail at tag begin (no '%%'): '%s'\n", p2parse);
@ -206,6 +249,7 @@ CODESTARTparse2
--lenMsg;
}
/* delimiter check */
if(pInst->bXrPresent) p2parse++;
if(lenMsg < 2 || *p2parse != ':' || *(p2parse+1) != ' ') {
DBGPRINTF("pmciscoios: fail after tag: '%s'\n", p2parse);
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
@ -217,6 +261,7 @@ CODESTARTparse2
/* if we reach this point, we have a wellformed message and can persist the values */
MsgSetTAG(pMsg, bufParseTAG, i);
/* if bOriginPresent !=0 iHostname gets initialized */
if(pInst->bOriginPresent)
MsgSetHOSTNAME(pMsg, bufParseHOSTNAME, iHostname);
MsgSetMSGoffs(pMsg, p2parse - pMsg->pszRawMsg);

View File

@ -10,7 +10,7 @@
*
* File begun on 2010-07-13 by RGerhards
*
* Copyright 2014-2014 Rainer Gerhards and Adiscon GmbH.
* Copyright 2014-2016 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
@ -91,16 +91,13 @@ CODESTARTparse
--lenMsg;
++p2parse;
}
dbgprintf("pmlastmsg: msg to look at: [%d]'%s'\n", lenMsg, p2parse);
if((unsigned) lenMsg < sizeof(OpeningText)-1 + sizeof(ClosingText)-1 + 1) {
/* too short, can not be "our" message */
dbgprintf("msg too short!\n");
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
if(strncasecmp((char*) p2parse, OpeningText, sizeof(OpeningText)-1) != 0) {
/* wrong opening text */
dbgprintf("wrong opening text!\n");
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}
lenMsg -= sizeof(OpeningText) - 1;
@ -119,9 +116,6 @@ dbgprintf("wrong opening text!\n");
if(strncasecmp((char*) p2parse, ClosingText, lenMsg) != 0) {
/* wrong closing text */
dbgprintf("strcasecmp: %d\n", strncasecmp((char*) p2parse, ClosingText, lenMsg));
dbgprintf("pmlastmsg: closing msg to look at: [%d]'%s', (%s)\n", lenMsg, p2parse, ClosingText);
dbgprintf("wrong closing text!\n");
ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
}

View File

@ -55,6 +55,9 @@ librsyslog_la_SOURCES = \
modules.h \
statsobj.c \
statsobj.h \
dynstats.c \
dynstats.h \
statsobj.h \
stream.c \
stream.h \
var.c \

View File

@ -194,6 +194,7 @@
*/
#ifdef HAVE_ATOMIC_BUILTINS64
# define ATOMIC_INC_uint64(data, phlpmut) ((void) __sync_fetch_and_add(data, 1))
# define ATOMIC_ADD_uint64(data, phlpmut, value) ((void) __sync_fetch_and_add(data, value))
# define ATOMIC_DEC_unit64(data, phlpmut) ((void) __sync_sub_and_fetch(data, 1))
# define ATOMIC_INC_AND_FETCH_uint64(data, phlpmut) __sync_fetch_and_add(data, 1)
@ -206,6 +207,11 @@
++(*(data)); \
pthread_mutex_unlock(phlpmut); \
}
# define ATOMIC_ADD_uint64(data, phlpmut, value) { \
pthread_mutex_lock(phlpmut); \
*data += value; \
pthread_mutex_unlock(phlpmut); \
}
# define ATOMIC_DEC_uint64(data, phlpmut) { \
pthread_mutex_lock(phlpmut); \
--(*(data)); \

View File

@ -319,7 +319,7 @@ static int doParseOnOffOption(uchar **pp)
pOptStart = *pp;
skipWhiteSpace(pp); /* skip over any whitespace */
if(getSubString(pp, (char*) szOpt, sizeof(szOpt) / sizeof(uchar), ' ') != 0) {
if(getSubString(pp, (char*) szOpt, sizeof(szOpt), ' ') != 0) {
errmsg.LogError(0, NO_ERRCODE, "Invalid $-configline - could not extract on/off option");
return -1;
}
@ -351,7 +351,7 @@ static rsRetVal doGetGID(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *p
assert(pp != NULL);
assert(*pp != NULL);
if(getSubString(pp, (char*) szName, sizeof(szName) / sizeof(uchar), ' ') != 0) {
if(getSubString(pp, (char*) szName, sizeof(szName), ' ') != 0) {
errmsg.LogError(0, RS_RET_NOT_FOUND, "could not extract group name");
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
@ -407,7 +407,7 @@ static rsRetVal doGetUID(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *p
assert(pp != NULL);
assert(*pp != NULL);
if(getSubString(pp, (char*) szName, sizeof(szName) / sizeof(uchar), ' ') != 0) {
if(getSubString(pp, (char*) szName, sizeof(szName), ' ') != 0) {
errmsg.LogError(0, RS_RET_NOT_FOUND, "could not extract user name");
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}

View File

@ -107,7 +107,7 @@ doModLoad(uchar **pp, __attribute__((unused)) void* pVal)
ASSERT(*pp != NULL);
skipWhiteSpace(pp); /* skip over any whitespace */
if(getSubString(pp, (char*) szName, sizeof(szName) / sizeof(uchar), ' ') != 0) {
if(getSubString(pp, (char*) szName, sizeof(szName), ' ') != 0) {
errmsg.LogError(0, RS_RET_NOT_FOUND, "could not extract module name");
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
@ -168,7 +168,7 @@ doNameLine(uchar **pp, void* pVal)
eDir = (enum eDirective) pVal; /* this time, it actually is NOT a pointer! */
if(getSubString(&p, szName, sizeof(szName) / sizeof(char), ',') != 0) {
if(getSubString(&p, szName, sizeof(szName), ',') != 0) {
errmsg.LogError(0, RS_RET_NOT_FOUND, "Invalid config line: could not extract name - line ignored");
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
@ -222,7 +222,7 @@ cfsysline(uchar *p)
ASSERT(p != NULL);
errno = 0;
if(getSubString(&p, (char*) szCmd, sizeof(szCmd) / sizeof(uchar), ' ') != 0) {
if(getSubString(&p, (char*) szCmd, sizeof(szCmd), ' ') != 0) {
errmsg.LogError(0, RS_RET_NOT_FOUND, "Invalid $-configline - could not extract command - line ignored\n");
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}

View File

@ -90,7 +90,7 @@ static const time_t yearInSecs[] = {
* Convert struct timeval to syslog_time
*/
void
timeval2syslogTime(struct timeval *tp, struct syslogTime *t)
timeval2syslogTime(struct timeval *tp, struct syslogTime *t, const int inUTC)
{
struct tm *tm;
struct tm tmBuf;
@ -98,7 +98,10 @@ timeval2syslogTime(struct timeval *tp, struct syslogTime *t)
time_t secs;
secs = tp->tv_sec;
tm = localtime_r(&secs, &tmBuf);
if(inUTC)
tm = gmtime_r(&secs, &tmBuf);
else
tm = localtime_r(&secs, &tmBuf);
t->year = tm->tm_year + 1900;
t->month = tm->tm_mon + 1;
@ -109,24 +112,30 @@ timeval2syslogTime(struct timeval *tp, struct syslogTime *t)
t->secfrac = tp->tv_usec;
t->secfracPrecision = 6;
# if __sun
/* Solaris uses a different method of exporting the time zone.
* It is UTC - localtime, which is the opposite sign of mins east of GMT.
*/
lBias = -(tm->tm_isdst ? altzone : timezone);
# elif defined(__hpux)
lBias = tz.tz_dsttime ? - tz.tz_minuteswest : 0;
# else
lBias = tm->tm_gmtoff;
# endif
if(lBias < 0) {
t->OffsetMode = '-';
lBias *= -1;
} else
if(inUTC) {
t->OffsetMode = '+';
lBias = 0;
} else {
# if __sun
/* Solaris uses a different method of exporting the time zone.
* It is UTC - localtime, which is the opposite sign of mins east of GMT.
*/
lBias = -(tm->tm_isdst ? altzone : timezone);
# elif defined(__hpux)
lBias = tz.tz_dsttime ? - tz.tz_minuteswest : 0;
# else
lBias = tm->tm_gmtoff;
# endif
if(lBias < 0) {
t->OffsetMode = '-';
lBias *= -1;
} else
t->OffsetMode = '+';
}
t->OffsetHour = lBias / 3600;
t->OffsetMinute = (lBias % 3600) / 60;
t->timeType = TIME_TYPE_RFC5424; /* we have a high precision timestamp */
t->inUTC = inUTC;
}
/**
@ -145,7 +154,7 @@ timeval2syslogTime(struct timeval *tp, struct syslogTime *t)
* in some situations to minimize time() calls (namely when doing
* output processing). This can be left NULL if not needed.
*/
static void getCurrTime(struct syslogTime *t, time_t *ttSeconds)
static void getCurrTime(struct syslogTime *t, time_t *ttSeconds, const int inUTC)
{
struct timeval tp;
# if defined(__hpux)
@ -164,7 +173,7 @@ static void getCurrTime(struct syslogTime *t, time_t *ttSeconds)
if(ttSeconds != NULL)
*ttSeconds = tp.tv_sec;
timeval2syslogTime(&tp, t);
timeval2syslogTime(&tp, t, inUTC);
}

View File

@ -32,7 +32,7 @@ typedef struct datetime_s {
/* interfaces */
BEGINinterface(datetime) /* name must also be changed in ENDinterface macro! */
void (*getCurrTime)(struct syslogTime *t, time_t *ttSeconds);
void (*getCurrTime)(struct syslogTime *t, time_t *ttSeconds, const int inUTC);
rsRetVal (*ParseTIMESTAMP3339)(struct syslogTime *pTime, uchar** ppszTS, int*);
rsRetVal (*ParseTIMESTAMP3164)(struct syslogTime *pTime, uchar** pszTS, int*, const int bParseTZ, const int bDetectYearAfterTime);
int (*formatTimestampToMySQL)(struct syslogTime *ts, char* pDst);
@ -42,13 +42,13 @@ BEGINinterface(datetime) /* name must also be changed in ENDinterface macro! */
int (*formatTimestampSecFrac)(struct syslogTime *ts, char* pBuf);
/* v3, 2009-11-12 */
time_t (*GetTime)(time_t *ttSeconds);
/* v6, 2011-06-20 */
void (*timeval2syslogTime)(struct timeval *tp, struct syslogTime *t);
/* v6, 2011-06-20 , v10, 2016-01-12*/
void (*timeval2syslogTime)(struct timeval *tp, struct syslogTime *t, const int inUTC);
/* v7, 2012-03-29 */
int (*formatTimestampUnix)(struct syslogTime *ts, char*pBuf);
time_t (*syslogTime2time_t)(struct syslogTime *ts);
ENDinterface(datetime)
#define datetimeCURR_IF_VERSION 9 /* increment whenever you change the interface structure! */
#define datetimeCURR_IF_VERSION 10 /* increment whenever you change the interface structure! */
/* interface changes:
* 1 - initial version
* 2 - not compatible to 1 - bugfix required ParseTIMESTAMP3164 to accept char ** as
@ -60,6 +60,8 @@ ENDinterface(datetime)
* 6 - see above
* 8 - ParseTIMESTAMP3164 has addtl parameter to permit TZ string parsing
* 9 - ParseTIMESTAMP3164 has addtl parameter to permit year parsing
* 10 - functions having addtl paramater inUTC to emit time in UTC:
* timeval2syslogTime, getCurrtime
*/
#define PARSE3164_TZSTRING 1
@ -68,6 +70,12 @@ ENDinterface(datetime)
#define PERMIT_YEAR_AFTER_TIME 1
#define NO_PERMIT_YEAR_AFTER_TIME 0
/* two defines for functions that create timestamps either in local
* time or UTC.
*/
#define TIME_IN_UTC 1
#define TIME_IN_LOCALTIME 0
/* prototypes */
PROTOTYPEObj(datetime);
void applyDfltTZ(struct syslogTime *pTime, char *tz);

View File

@ -367,7 +367,7 @@ static void dbgMutLogPrintOne(dbgMutLog_t *pLog)
strmutop = "owned";
break;
default:
snprintf(buf, sizeof(buf)/sizeof(char), "unknown state %d - should not happen!", pLog->mutexOp);
snprintf(buf, sizeof(buf), "unknown state %d - should not happen!", pLog->mutexOp);
strmutop = buf;
break;
}
@ -465,7 +465,7 @@ static inline void dbgMutexPreLockLog(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD
pszHolder = "[NONE]";
else {
dbgGetThrdName(pszHolderThrdName, sizeof(pszHolderThrdName), pHolder->thrd, 1);
snprintf(pszBuf, sizeof(pszBuf)/sizeof(char), "%s:%d [%s]", pHolder->pFuncDB->file, pHolder->lockLn, pszHolderThrdName);
snprintf(pszBuf, sizeof(pszBuf), "%s:%d [%s]", pHolder->pFuncDB->file, pHolder->lockLn, pszHolderThrdName);
pszHolder = pszBuf;
}
@ -512,7 +512,7 @@ static inline void dbgMutexPreTryLockLog(pthread_mutex_t *pmut, dbgFuncDB_t *pFu
pszHolder = "[NONE]";
else {
dbgGetThrdName(pszHolderThrdName, sizeof(pszHolderThrdName), pHolder->thrd, 1);
snprintf(pszBuf, sizeof(pszBuf)/sizeof(char), "%s:%d [%s]", pHolder->pFuncDB->file, pHolder->lockLn, pszHolderThrdName);
snprintf(pszBuf, sizeof(pszBuf), "%s:%d [%s]", pHolder->pFuncDB->file, pHolder->lockLn, pszHolderThrdName);
pszHolder = pszBuf;
}
@ -1226,7 +1226,7 @@ dbgGetRTOptNamVal(uchar **ppszOpt, uchar **ppOptName, uchar **ppOptVal)
/* name - up until '=' or whitespace */
i = 0;
while(i < (sizeof(optname)/sizeof(uchar) - 1) && *p && *p != '=' && !isspace(*p)) {
while(i < (sizeof(optname) - 1) && *p && *p != '=' && !isspace(*p)) {
optname[i++] = *p++;
}
@ -1237,7 +1237,7 @@ dbgGetRTOptNamVal(uchar **ppszOpt, uchar **ppOptName, uchar **ppOptVal)
/* we have a value, get it */
++p;
i = 0;
while(i < (sizeof(optval)/sizeof(uchar) - 1) && *p && !isspace(*p)) {
while(i < (sizeof(optval) - 1) && *p && !isspace(*p)) {
optval[i++] = *p++;
}
optval[i] = '\0';

View File

@ -305,7 +305,7 @@ resolveAddr(struct sockaddr_storage *addr, dnscache_entry_t *etry)
* is OK in any way. We do also log the error message. rgerhards, 2007-07-16
*/
if(glbl.GetDropMalPTRMsgs() == 1) {
snprintf((char*)szErrMsg, sizeof(szErrMsg) / sizeof(uchar),
snprintf((char*)szErrMsg, sizeof(szErrMsg),
"Malicious PTR record, message dropped "
"IP = \"%s\" HOST = \"%s\"",
szIP, fqdnBuf);
@ -320,7 +320,7 @@ resolveAddr(struct sockaddr_storage *addr, dnscache_entry_t *etry)
* (OK, I admit this is more or less impossible, but I am paranoid...)
* rgerhards, 2007-07-16
*/
snprintf((char*)szErrMsg, sizeof(szErrMsg) / sizeof(uchar),
snprintf((char*)szErrMsg, sizeof(szErrMsg),
"Malicious PTR record (message accepted, but used IP "
"instead of PTR name: IP = \"%s\" HOST = \"%s\"",
szIP, fqdnBuf);

541
runtime/dynstats.c Normal file
View File

@ -0,0 +1,541 @@
/*
* This file is part of the rsyslog runtime library.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* -or-
* see COPYING.ASL20 in the source distribution
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <assert.h>
#include "rsyslog.h"
#include "srUtils.h"
#include "errmsg.h"
#include "rsconf.h"
#include "unicode-helper.h"
/* definitions for objects we access */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
DEFobjCurrIf(statsobj)
#define DYNSTATS_PARAM_NAME "name"
#define DYNSTATS_PARAM_RESETTABLE "resettable"
#define DYNSTATS_PARAM_MAX_CARDINALITY "maxCardinality"
#define DYNSTATS_PARAM_UNUSED_METRIC_LIFE "unusedMetricLife" /* in seconds */
#define DYNSTATS_DEFAULT_RESETTABILITY 1
#define DYNSTATS_DEFAULT_MAX_CARDINALITY 2000
#define DYNSTATS_DEFAULT_UNUSED_METRIC_LIFE 3600 /* seconds */
#define DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH 100
#define DYNSTATS_METRIC_NAME_SEPARATOR '.'
#define DYNSTATS_HASHTABLE_SIZE_OVERPROVISIONING 1.25
static struct cnfparamdescr modpdescr[] = {
{ DYNSTATS_PARAM_NAME, eCmdHdlrString, CNFPARAM_REQUIRED },
{ DYNSTATS_PARAM_RESETTABLE, eCmdHdlrBinary, 0 },
{ DYNSTATS_PARAM_MAX_CARDINALITY, eCmdHdlrPositiveInt, 0},
{ DYNSTATS_PARAM_UNUSED_METRIC_LIFE, eCmdHdlrPositiveInt, 0} /* in minutes */
};
static struct cnfparamblk modpblk =
{ CNFPARAMBLK_VERSION,
sizeof(modpdescr)/sizeof(struct cnfparamdescr),
modpdescr
};
rsRetVal
dynstatsClassInit(void) {
DEFiRet;
CHKiRet(objGetObjInterface(&obj));
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(statsobj, CORE_COMPONENT));
finalize_it:
RETiRet;
}
static inline void
dynstats_destroyCtr(dynstats_bucket_t *b, dynstats_ctr_t *ctr, uint8_t destructStatsCtr) {
if (destructStatsCtr) {
statsobj.DestructCounter(b->stats, ctr->pCtr);
}
free(ctr->metric);
free(ctr);
}
static inline void /* assumes exclusive access to bucket */
dynstats_destroyCounters(dynstats_bucket_t *b) {
dynstats_ctr_t *ctr;
hashtable_destroy(b->table, 0);
statsobj.DestructAllCounters(b->stats);
while(1) {
ctr = b->ctrs;
if (ctr == NULL) {
break;
} else {
b->ctrs = ctr->next;
dynstats_destroyCtr(b, ctr, 0);
}
}
STATSCOUNTER_BUMP(b->ctrMetricsPurged, b->mutCtrMetricsPurged, b->metricCount);
}
void
dynstats_destroyBucket(dynstats_bucket_t* b) {
dynstats_buckets_t *bkts;
bkts = &loadConf->dynstats_buckets;
pthread_rwlock_wrlock(&b->lock);
dynstats_destroyCounters(b);
statsobj.Destruct(&b->stats);
free(b->name);
pthread_rwlock_unlock(&b->lock);
pthread_rwlock_destroy(&b->lock);
pthread_mutex_destroy(&b->mutMetricCount);
statsobj.DestructCounter(bkts->global_stats, b->pOpsOverflowCtr);
statsobj.DestructCounter(bkts->global_stats, b->pNewMetricAddCtr);
statsobj.DestructCounter(bkts->global_stats, b->pNoMetricCtr);
statsobj.DestructCounter(bkts->global_stats, b->pMetricsPurgedCtr);
statsobj.DestructCounter(bkts->global_stats, b->pOpsIgnoredCtr);
free(b);
}
static rsRetVal
dynstats_addBucketMetrics(dynstats_buckets_t *bkts, dynstats_bucket_t *b, const uchar* name) {
uchar *metric_name_buff, *metric_suffix;
const uchar *suffix_litteral;
int name_len;
DEFiRet;
name_len = ustrlen(name);
CHKmalloc(metric_name_buff = malloc((name_len + DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH + 1) * sizeof(uchar)));
ustrncpy(metric_name_buff, name, name_len);
metric_suffix = metric_name_buff + name_len;
*metric_suffix = DYNSTATS_METRIC_NAME_SEPARATOR;
metric_suffix++;
suffix_litteral = UCHAR_CONSTANT("ops_overflow");
ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
STATSCOUNTER_INIT(b->ctrOpsOverflow, b->mutCtrOpsOverflow);
CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
CTR_FLAG_RESETTABLE, &(b->ctrOpsOverflow), &b->pOpsOverflowCtr));
suffix_litteral = UCHAR_CONSTANT("new_metric_add");
ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
STATSCOUNTER_INIT(b->ctrNewMetricAdd, b->mutCtrNewMetricAdd);
CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
CTR_FLAG_RESETTABLE, &(b->ctrNewMetricAdd), &b->pNewMetricAddCtr));
suffix_litteral = UCHAR_CONSTANT("no_metric");
ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
STATSCOUNTER_INIT(b->ctrNoMetric, b->mutCtrNoMetric);
CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
CTR_FLAG_RESETTABLE, &(b->ctrNoMetric), &b->pNoMetricCtr));
suffix_litteral = UCHAR_CONSTANT("metrics_purged");
ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
STATSCOUNTER_INIT(b->ctrMetricsPurged, b->mutCtrMetricsPurged);
CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
CTR_FLAG_RESETTABLE, &(b->ctrMetricsPurged), &b->pMetricsPurgedCtr));
suffix_litteral = UCHAR_CONSTANT("ops_ignored");
ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
STATSCOUNTER_INIT(b->ctrOpsIgnored, b->mutCtrOpsIgnored);
CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
CTR_FLAG_RESETTABLE, &(b->ctrOpsIgnored), &b->pOpsIgnoredCtr));
finalize_it:
free(metric_name_buff);
if (iRet != RS_RET_OK) {
if (b->pOpsOverflowCtr != NULL) {
statsobj.DestructCounter(bkts->global_stats, b->pOpsOverflowCtr);
}
if (b->pNewMetricAddCtr != NULL) {
statsobj.DestructCounter(bkts->global_stats, b->pNewMetricAddCtr);
}
if (b->pNoMetricCtr != NULL) {
statsobj.DestructCounter(bkts->global_stats, b->pNoMetricCtr);
}
if (b->pMetricsPurgedCtr != NULL) {
statsobj.DestructCounter(bkts->global_stats, b->pMetricsPurgedCtr);
}
if (b->pOpsIgnoredCtr != NULL) {
statsobj.DestructCounter(bkts->global_stats, b->pOpsIgnoredCtr);
}
}
RETiRet;
}
static void
no_op_free(void __attribute__((unused)) *ignore) {}
static rsRetVal
dynstats_resetBucket(dynstats_bucket_t *b, uint8_t do_purge) {
size_t htab_sz;
DEFiRet;
htab_sz = (size_t) (DYNSTATS_HASHTABLE_SIZE_OVERPROVISIONING * b->maxCardinality + 1);
pthread_rwlock_wrlock(&b->lock);
if (do_purge) {
dynstats_destroyCounters(b);
}
ATOMIC_STORE_0_TO_INT(&b->metricCount, &b->mutMetricCount);
b->ctrs = NULL;
if ((b->table = create_hashtable(htab_sz, hash_from_string, key_equals_string, no_op_free)) == NULL) {
errmsg.LogError(errno, RS_RET_INTERNAL_ERROR, "error trying to initialize hash-table for dyn-stats bucket named: %s", b->name);
ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
}
timeoutComp(&b->metricCleanupTimeout, b->unusedMetricLife);
finalize_it:
pthread_rwlock_unlock(&b->lock);
if (iRet != RS_RET_OK) {
statsobj.Destruct(&b->stats);
}
RETiRet;
}
static inline void
dynstats_resetIfExpired(dynstats_bucket_t *b) {
long timeout;
pthread_rwlock_rdlock(&b->lock);
timeout = timeoutVal(&b->metricCleanupTimeout);
pthread_rwlock_unlock(&b->lock);
if (timeout == 0) {
errmsg.LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO, "dynstats: bucket '%s' is being reset", b->name);
dynstats_resetBucket(b, 1);
}
}
static void
dynstats_readCallback(statsobj_t __attribute__((unused)) *ignore, void *b) {
dynstats_buckets_t *bkts;
bkts = &loadConf->dynstats_buckets;
pthread_rwlock_rdlock(&bkts->lock);
dynstats_resetIfExpired((dynstats_bucket_t *) b);
pthread_rwlock_unlock(&bkts->lock);
}
static inline rsRetVal
dynstats_initNewBucketStats(dynstats_bucket_t *b) {
DEFiRet;
CHKiRet(statsobj.Construct(&b->stats));
CHKiRet(statsobj.SetOrigin(b->stats, UCHAR_CONSTANT("dynstats.bucket")));
CHKiRet(statsobj.SetName(b->stats, b->name));
statsobj.SetReadNotifier(b->stats, dynstats_readCallback, b);
CHKiRet(statsobj.ConstructFinalize(b->stats));
finalize_it:
RETiRet;
}
static rsRetVal
dynstats_newBucket(const uchar* name, uint8_t resettable, uint32_t maxCardinality, uint32_t unusedMetricLife) {
dynstats_bucket_t *b;
dynstats_buckets_t *bkts;
uint8_t lock_initialized, metric_count_mutex_initialized;
pthread_rwlockattr_t bucket_lock_attr;
DEFiRet;
lock_initialized = metric_count_mutex_initialized = 0;
b = NULL;
bkts = &loadConf->dynstats_buckets;
if (bkts->initialized) {
CHKmalloc(b = calloc(1, sizeof(dynstats_bucket_t)));
b->resettable = resettable;
b->maxCardinality = maxCardinality;
b->unusedMetricLife = 1000 * unusedMetricLife;
CHKmalloc(b->name = ustrdup(name));
pthread_rwlockattr_init(&bucket_lock_attr);
#ifdef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
pthread_rwlockattr_setkind_np(&bucket_lock_attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
#endif
pthread_rwlock_init(&b->lock, &bucket_lock_attr);
lock_initialized = 1;
pthread_mutex_init(&b->mutMetricCount, NULL);
metric_count_mutex_initialized = 1;
CHKiRet(dynstats_initNewBucketStats(b));
CHKiRet(dynstats_resetBucket(b, 0));
CHKiRet(dynstats_addBucketMetrics(bkts, b, name));
pthread_rwlock_wrlock(&bkts->lock);
if (bkts->list == NULL) {
bkts->list = b;
} else {
b->next = bkts->list;
bkts->list = b;
}
pthread_rwlock_unlock(&bkts->lock);
} else {
errmsg.LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: bucket creation failed, as global-initialization of buckets was unsuccessful");
ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
}
finalize_it:
if (iRet != RS_RET_OK) {
if (metric_count_mutex_initialized) {
pthread_mutex_destroy(&b->mutMetricCount);
}
if (lock_initialized) {
pthread_rwlock_destroy(&b->lock);
}
if (b != NULL) {
free(b->name);
free(b);
}
}
RETiRet;
}
rsRetVal
dynstats_processCnf(struct cnfobj *o) {
struct cnfparamvals *pvals;
short i;
uchar *name = NULL;
uint8_t resettable = DYNSTATS_DEFAULT_RESETTABILITY;
uint32_t maxCardinality = DYNSTATS_DEFAULT_MAX_CARDINALITY;
uint32_t unusedMetricLife = DYNSTATS_DEFAULT_UNUSED_METRIC_LIFE;
DEFiRet;
pvals = nvlstGetParams(o->nvlst, &modpblk, NULL);
if(pvals == NULL) {
ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
}
for(i = 0 ; i < modpblk.nParams ; ++i) {
if(!pvals[i].bUsed)
continue;
if(!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_NAME)) {
CHKmalloc(name = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL));
} else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_RESETTABLE)) {
resettable = (pvals[i].val.d.n != 0);
} else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_MAX_CARDINALITY)) {
maxCardinality = (uint32_t) pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_UNUSED_METRIC_LIFE)) {
unusedMetricLife = (uint32_t) pvals[i].val.d.n;
} else {
dbgprintf("dyn_stats: program error, non-handled "
"param '%s'\n", modpblk.descr[i].name);
}
}
if (name != NULL) {
CHKiRet(dynstats_newBucket(name, resettable, maxCardinality, unusedMetricLife));
}
finalize_it:
free(name);
cnfparamvalsDestruct(pvals, &modpblk);
RETiRet;
}
rsRetVal
dynstats_initCnf(dynstats_buckets_t *bkts) {
DEFiRet;
bkts->initialized = 0;
bkts->list = NULL;
CHKiRet(statsobj.Construct(&bkts->global_stats));
CHKiRet(statsobj.SetOrigin(bkts->global_stats, UCHAR_CONSTANT("dynstats")));
CHKiRet(statsobj.SetName(bkts->global_stats, UCHAR_CONSTANT("global")));
CHKiRet(statsobj.ConstructFinalize(bkts->global_stats));
pthread_rwlock_init(&bkts->lock, NULL);
bkts->initialized = 1;
finalize_it:
if (iRet != RS_RET_OK) {
statsobj.Destruct(&bkts->global_stats);
}
RETiRet;
}
void
dynstats_destroyAllBuckets() {
dynstats_buckets_t *bkts;
dynstats_bucket_t *b;
bkts = &loadConf->dynstats_buckets;
if (bkts->initialized) {
pthread_rwlock_wrlock(&bkts->lock);
while(1) {
b = bkts->list;
if (b == NULL) {
break;
} else {
bkts->list = b->next;
dynstats_destroyBucket(b);
}
}
pthread_rwlock_unlock(&bkts->lock);
pthread_rwlock_destroy(&bkts->lock);
}
}
dynstats_bucket_t *
dynstats_findBucket(const uchar* name) {
dynstats_buckets_t *bkts;
dynstats_bucket_t *b;
bkts = &loadConf->dynstats_buckets;
if (bkts->initialized) {
pthread_rwlock_rdlock(&bkts->lock);
b = bkts->list;
while(b != NULL) {
if (! ustrcmp(name, b->name)) {
break;
}
b = b->next;
}
pthread_rwlock_unlock(&bkts->lock);
} else {
b = NULL;
errmsg.LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: bucket lookup failed, as global-initialization of buckets was unsuccessful");
}
return b;
}
static rsRetVal
dynstats_createCtr(dynstats_bucket_t *b, const uchar* metric, dynstats_ctr_t **ctr) {
DEFiRet;
CHKmalloc(*ctr = calloc(1, sizeof(dynstats_ctr_t)));
CHKmalloc((*ctr)->metric = ustrdup(metric));
STATSCOUNTER_INIT((*ctr)->ctr, (*ctr)->mutCtr);
CHKiRet(statsobj.AddManagedCounter(b->stats, metric, ctrType_IntCtr,
b->resettable, &(*ctr)->ctr, &(*ctr)->pCtr));
finalize_it:
if (iRet != RS_RET_OK) {
if ((*ctr) != NULL) {
free((*ctr)->metric);
free(*ctr);
*ctr = NULL;
}
}
RETiRet;
}
static rsRetVal
dynstats_addNewCtr(dynstats_bucket_t *b, const uchar* metric, uint8_t doInitialIncrement) {
dynstats_ctr_t *ctr;
dynstats_ctr_t *found_ctr;
int created;
uchar *copy_of_key = NULL;
DEFiRet;
created = 0;
ctr = NULL;
if (ATOMIC_FETCH_32BIT(&b->metricCount, &b->mutMetricCount) >= b->maxCardinality) {
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
CHKiRet(dynstats_createCtr(b, metric, &ctr));
pthread_rwlock_wrlock(&b->lock);
found_ctr = (dynstats_ctr_t*) hashtable_search(b->table, ctr->metric);
if (found_ctr != NULL) {
if (doInitialIncrement) {
STATSCOUNTER_INC(found_ctr->ctr, found_ctr->mutCtr);
}
} else {
copy_of_key = ustrdup(ctr->metric);
if (copy_of_key != NULL) {
created = hashtable_insert(b->table, copy_of_key, ctr);
}
if (created) {
if (b->ctrs == NULL) {
b->ctrs = ctr;
} else {
ctr->next = b->ctrs;
b->ctrs = ctr;
}
if (doInitialIncrement) {
STATSCOUNTER_INC(ctr->ctr, ctr->mutCtr);
}
}
}
pthread_rwlock_unlock(&b->lock);
if (found_ctr != NULL) {
//ignore
} else if (created) {
ATOMIC_INC(&b->metricCount, &b->mutMetricCount);
STATSCOUNTER_INC(b->ctrNewMetricAdd, b->mutCtrNewMetricAdd);
} else {
if (copy_of_key != NULL) {
free(copy_of_key);
}
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
finalize_it:
if ((! created) && (ctr != NULL)) {
dynstats_destroyCtr(b, ctr, 1);
}
RETiRet;
}
rsRetVal
dynstats_inc(dynstats_bucket_t *b, uchar* metric) {
dynstats_ctr_t *ctr;
DEFiRet;
if (! GatherStats) {
FINALIZE;
}
if (ustrlen(metric) == 0) {
STATSCOUNTER_INC(b->ctrNoMetric, b->mutCtrNoMetric);
FINALIZE;
}
if (pthread_rwlock_tryrdlock(&b->lock) == 0) {
ctr = (dynstats_ctr_t *) hashtable_search(b->table, metric);
if (ctr != NULL) {
STATSCOUNTER_INC(ctr->ctr, ctr->mutCtr);
}
pthread_rwlock_unlock(&b->lock);
} else {
ABORT_FINALIZE(RS_RET_NOENTRY);
}
if (ctr == NULL) {
CHKiRet(dynstats_addNewCtr(b, metric, 1));
}
finalize_it:
if (iRet != RS_RET_OK) {
if (iRet == RS_RET_NOENTRY) {
/* NOTE: this is not tested (because it requires very strong orchestration to gurantee contended lock for testing) */
STATSCOUNTER_INC(b->ctrOpsIgnored, b->mutCtrOpsIgnored);
} else {
STATSCOUNTER_INC(b->ctrOpsOverflow, b->mutCtrOpsOverflow);
}
}
RETiRet;
}

73
runtime/dynstats.h Normal file
View File

@ -0,0 +1,73 @@
/*
* This file is part of the rsyslog runtime library.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* -or-
* see COPYING.ASL20 in the source distribution
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef INCLUDED_DYNSTATS_H
#define INCLUDED_DYNSTATS_H
#include "hashtable.h"
typedef struct hashtable htable;
struct dynstats_ctr_s {
STATSCOUNTER_DEF(ctr, mutCtr);
ctr_t *pCtr;
uchar *metric;
struct dynstats_ctr_s *next; /* linked list ptr */
};
struct dynstats_bucket_s {
htable *table;
uchar *name;
pthread_rwlock_t lock;
statsobj_t *stats;
STATSCOUNTER_DEF(ctrOpsOverflow, mutCtrOpsOverflow);
ctr_t *pOpsOverflowCtr;
STATSCOUNTER_DEF(ctrNewMetricAdd, mutCtrNewMetricAdd);
ctr_t *pNewMetricAddCtr;
STATSCOUNTER_DEF(ctrNoMetric, mutCtrNoMetric);
ctr_t *pNoMetricCtr;
STATSCOUNTER_DEF(ctrMetricsPurged, mutCtrMetricsPurged);
ctr_t *pMetricsPurgedCtr;
STATSCOUNTER_DEF(ctrOpsIgnored, mutCtrOpsIgnored);
ctr_t *pOpsIgnoredCtr;
struct dynstats_bucket_s *next; /* linked list ptr */
struct dynstats_ctr_s *ctrs;
uint32_t maxCardinality;
uint32_t metricCount;
pthread_mutex_t mutMetricCount;
uint32_t unusedMetricLife;
uint32_t lastResetTs;
struct timespec metricCleanupTimeout;
uint8_t resettable;
};
struct dynstats_buckets_s {
struct dynstats_bucket_s *list;
statsobj_t *global_stats;
pthread_rwlock_t lock;
uint8_t initialized;
};
rsRetVal dynstats_initCnf(dynstats_buckets_t *b);
rsRetVal dynstats_processCnf(struct cnfobj *o);
dynstats_bucket_t * dynstats_findBucket(const uchar* name);
rsRetVal dynstats_inc(dynstats_bucket_t *bucket, uchar* metric);
void dynstats_destroyAllBuckets();
void dynstats_resetExpired();
rsRetVal dynstatsClassInit(void);
#endif /* #ifndef INCLUDED_DYNSTATS_H */

View File

@ -96,7 +96,7 @@ doLogMsg(const int iErrno, const int iErrCode, const int severity, const char *
snprintf(buf, sizeof(buf), "%s [v%s try http://www.rsyslog.com/e/%d ]", msg, VERSION, iErrCode * -1);
}
}
buf[sizeof(buf)/sizeof(char) - 1] = '\0'; /* just to be on the safe side... */
buf[sizeof(buf) - 1] = '\0'; /* just to be on the safe side... */
errno = 0;
glblErrLogger(severity, iErrCode, (uchar*)buf);
@ -129,7 +129,7 @@ LogError(const int iErrno, const int iErrCode, const char *fmt, ... )
lenBuf--;
}
va_end(ap);
buf[sizeof(buf)/sizeof(char) - 1] = '\0'; /* just to be on the safe side... */
buf[sizeof(buf) - 1] = '\0'; /* just to be on the safe side... */
doLogMsg(iErrno, iErrCode, LOG_ERR, buf);
}
@ -158,7 +158,7 @@ LogMsg(const int iErrno, const int iErrCode, const int severity, const char *fmt
lenBuf--;
}
va_end(ap);
buf[sizeof(buf)/sizeof(char) - 1] = '\0'; /* just to be on the safe side... */
buf[sizeof(buf) - 1] = '\0'; /* just to be on the safe side... */
doLogMsg(iErrno, iErrCode, severity, buf);
}

View File

@ -7,18 +7,18 @@
*
* Module begun 2008-04-16 by Rainer Gerhards
*
* Copyright 2008-2015 Rainer Gerhards and Adiscon GmbH.
* Copyright 2008-2016 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
* -or-
* see COPYING.ASL20 in the source distribution
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -111,6 +111,10 @@ static int bEscape8BitChars = 0; /* escape characters > 127 on reception: 0 - no
static int bEscapeTab = 1; /* escape tab control character when doing CC escapes: 0 - no, 1 - yes */
static int bParserEscapeCCCStyle = 0; /* escape control characters in c style: 0 - no, 1 - yes */
short janitorInterval = 10; /* interval (in minutes) at which the janitor runs */
int glblReportNewSenders = 0;
int glblReportGoneAwaySenders = 0;
int glblSenderStatsTimeout = 12 * 60 * 60; /* 12 hr timeout for senders */
int glblSenderKeepTrack = 0; /* keep track of known senders? */
pid_t glbl_ourpid;
#ifndef HAVE_ATOMIC_BUILTINS
@ -150,6 +154,10 @@ static struct cnfparamdescr cnfparamdescr[] = {
{ "parser.parsehostnameandtag", eCmdHdlrBinary, 0 },
{ "stdlog.channelspec", eCmdHdlrString, 0 },
{ "janitor.interval", eCmdHdlrPositiveInt, 0 },
{ "senders.reportnew", eCmdHdlrBinary, 0 },
{ "senders.reportgoneaway", eCmdHdlrBinary, 0 },
{ "senders.timeoutafter", eCmdHdlrPositiveInt, 0 },
{ "senders.keeptrack", eCmdHdlrBinary, 0 },
{ "net.ipprotocol", eCmdHdlrGetWord, 0 },
{ "net.acladdhostnameonfail", eCmdHdlrBinary, 0 },
{ "net.aclresolvehostname", eCmdHdlrBinary, 0 },
@ -164,8 +172,8 @@ static struct cnfparamblk paramblk =
};
static struct cnfparamdescr timezonecnfparamdescr[] = {
{ "id", eCmdHdlrString, 0 },
{ "offset", eCmdHdlrGetWord, 0 }
{ "id", eCmdHdlrString, CNFPARAM_REQUIRED},
{ "offset", eCmdHdlrGetWord, CNFPARAM_REQUIRED }
};
static struct cnfparamblk timezonepblk =
{ CNFPARAMBLK_VERSION,
@ -826,7 +834,11 @@ addTimezoneInfo(uchar *tzid, char offsMode, int8_t offsHour, int8_t offsMin)
DEFiRet;
tzinfo_t *newti;
CHKmalloc(newti = realloc(tzinfos, (ntzinfos+1)*sizeof(tzinfo_t)));
CHKmalloc(newti[ntzinfos].id = strdup((char*)tzid));
if((newti[ntzinfos].id = strdup((char*)tzid)) == NULL) {
free(newti);
DBGPRINTF("addTimezoneInfo: strdup failed with OOM\n");
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
newti[ntzinfos].offsMode = offsMode;
newti[ntzinfos].offsHour = offsHour;
newti[ntzinfos].offsMin = offsMin;
@ -863,8 +875,10 @@ glblProcessTimezone(struct cnfobj *o)
int i;
pvals = nvlstGetParams(o->nvlst, &timezonepblk, NULL);
dbgprintf("timezone param blk after glblProcessTimezone:\n");
cnfparamsPrint(&timezonepblk, pvals);
if(Debug) {
dbgprintf("timezone param blk after glblProcessTimezone:\n");
cnfparamsPrint(&timezonepblk, pvals);
}
for(i = 0 ; i < timezonepblk.nParams ; ++i) {
if(!pvals[i].bUsed)
@ -879,6 +893,20 @@ glblProcessTimezone(struct cnfobj *o)
}
}
/* note: the following two checks for NULL are not strictly necessary
* as these are required parameters for the config block. But we keep
* them to make the clang static analyzer happy, which also helps
* guard against logic errors.
*/
if(offset == NULL) {
parser_errmsg("offset parameter missing (logic error?), timezone config ignored");
goto done;
}
if(id == NULL) {
parser_errmsg("id parameter missing (logic error?), timezone config ignored");
goto done;
}
if( strlen((char*)offset) != 6
|| !(offset[0] == '-' || offset[0] == '+')
|| !(isdigit(offset[1]) && isdigit(offset[2]))
@ -917,8 +945,10 @@ glblProcessCnf(struct cnfobj *o)
int i;
cnfparamvals = nvlstGetParams(o->nvlst, &paramblk, cnfparamvals);
dbgprintf("glbl param blk after glblProcessCnf:\n");
cnfparamsPrint(&paramblk, cnfparamvals);
if(Debug) {
dbgprintf("glbl param blk after glblProcessCnf:\n");
cnfparamsPrint(&paramblk, cnfparamvals);
}
/* The next thing is a bit hackish and should be changed in higher
* versions. There are a select few parameters which we need to
@ -1088,6 +1118,14 @@ glblDoneLoadCnf(void)
"parameter '%s' -- ignored", proto);
}
free(proto);
} else if(!strcmp(paramblk.descr[i].name, "senders.reportnew")) {
glblReportNewSenders = (int) cnfparamvals[i].val.d.n;
} else if(!strcmp(paramblk.descr[i].name, "senders.reportgoneaway")) {
glblReportGoneAwaySenders = (int) cnfparamvals[i].val.d.n;
} else if(!strcmp(paramblk.descr[i].name, "senders.timeoutafter")) {
glblSenderStatsTimeout = (int) cnfparamvals[i].val.d.n;
} else if(!strcmp(paramblk.descr[i].name, "senders.keeptrack")) {
glblSenderKeepTrack = (int) cnfparamvals[i].val.d.n;
} else if(!strcmp(paramblk.descr[i].name, "net.acladdhostnameonfail")) {
*(net.pACLAddHostnameOnFail) = (int) cnfparamvals[i].val.d.n;
} else if(!strcmp(paramblk.descr[i].name, "net.aclresolvehostname")) {

View File

@ -8,18 +8,18 @@
* Please note that there currently is no glbl.c file as we do not yet
* have any implementations.
*
* Copyright 2008-2015 Rainer Gerhards and Adiscon GmbH.
* Copyright 2008-2016 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
* -or-
* see COPYING.ASL20 in the source distribution
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -109,6 +109,10 @@ ENDinterface(glbl)
PROTOTYPEObj(glbl);
extern int glblDebugOnShutdown; /* start debug log when we are shut down */
extern int glblReportNewSenders;
extern int glblReportGoneAwaySenders;
extern int glblSenderStatsTimeout;
extern int glblSenderKeepTrack;
extern short janitorInterval;
static inline pid_t glblGetOurPid(void) { return glbl_ourpid; }

View File

@ -76,7 +76,7 @@ static void display_status_(char *m, OM_uint32 code, int type)
} else {
char buf[1024];
snprintf(buf, sizeof(buf), "GSS-API error %s: %s\n", m, (char *) msg.value);
buf[sizeof(buf)/sizeof(char) - 1] = '\0';
buf[sizeof(buf) - 1] = '\0';
errmsg.LogError(0, NO_ERRCODE, "%s", buf);
}
if (msg.length != 0)

View File

@ -7,7 +7,7 @@
*
* Module begun 2014-05-15 by Rainer Gerhards
*
* Copyright (C) 2014 by Rainer Gerhards and Adiscon GmbH.
* Copyright (C) 2014-2015 by Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@ -41,7 +41,7 @@ static pthread_mutex_t janitorMut = PTHREAD_MUTEX_INITIALIZER;
rsRetVal
janitorAddEtry(void (*cb)(void*), const char *id, void *pUsr)
{
struct janitorEtry *etry;
struct janitorEtry *etry = NULL;
DEFiRet;
CHKmalloc(etry = malloc(sizeof(struct janitorEtry)));
CHKmalloc(etry->id = strdup(id));
@ -53,6 +53,8 @@ janitorAddEtry(void (*cb)(void*), const char *id, void *pUsr)
pthread_mutex_unlock(&janitorMut);
DBGPRINTF("janitor: entry %p, id '%s' added\n", etry, id);
finalize_it:
if(iRet != RS_RET_OK && etry != NULL)
free(etry);
RETiRet;
}

View File

@ -1,6 +1,6 @@
/* gcry.c - rsyslog's libgcrypt based crypto provider
*
* Copyright 2013 Adiscon GmbH.
* Copyright 2013-2016 Adiscon GmbH.
*
* We need to store some additional information in support of encryption.
* For this, we create a side-file, which is named like the actual log
@ -25,11 +25,11 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
* -or-
* see COPYING.ASL20 in the source distribution
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -285,8 +285,8 @@ finalize_it:
RETiRet;
}
static rsRetVal
eiWriteIV(gcryfile gf, uchar *iv)
static rsRetVal __attribute__((nonnull(2)))
eiWriteIV(gcryfile gf, const uchar *const iv)
{
static const char hexchars[16] =
{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
@ -520,7 +520,17 @@ seedIV(gcryfile gf, uchar **iv)
{
int fd;
#ifdef __clang_analyzer__
*iv = calloc(1, gf->blkLength); /* do NOT use this code! */
/* this execution branch is only present to prevent a
* "garbagge value used" warning by the static analyzer.
* In fact, that is exactly what we want to and need to
* use. Using calloc here keeps that analyzer happy, but would
* cause a security issue if used in practice.
*/
#else
*iv = malloc(gf->blkLength); /* do NOT zero-out! */
#endif
/* if we cannot obtain data from /dev/urandom, we use whatever
* is present at the current memory location as random data. Of
* course, this is very weak and we should consider a different
@ -595,6 +605,7 @@ rsgcryBlkBegin(gcryfile gf)
gcry_error_t gcryError;
uchar *iv = NULL;
DEFiRet;
const char openMode = gf->openMode;
gcryError = gcry_cipher_open(&gf->chd, gf->ctx->algo, gf->ctx->mode, 0);
if (gcryError) {
@ -610,7 +621,7 @@ rsgcryBlkBegin(gcryfile gf)
ABORT_FINALIZE(RS_RET_ERR);
}
if(gf->openMode == 'r') {
if(openMode == 'r') {
readIV(gf, &iv);
readBlkEnd(gf);
} else {
@ -624,7 +635,7 @@ rsgcryBlkBegin(gcryfile gf)
ABORT_FINALIZE(RS_RET_ERR);
}
if(gf->openMode == 'w') {
if(openMode == 'w') {
CHKiRet(eiOpenAppend(gf));
CHKiRet(eiWriteIV(gf, iv));
}

View File

@ -17,7 +17,7 @@
* information (most importantly last block hash) and sigblkConstruct
* reads (or initilizes if not present) it.
*
* Copyright 2013 Adiscon GmbH.
* Copyright 2013-2016 Adiscon GmbH.
*
* This file is part of rsyslog.
*
@ -146,7 +146,7 @@ rsgtExit(void)
static inline gtfile
rsgtfileConstruct(gtctx ctx)
{
gtfile gf;
gtfile gf = NULL;
if((gf = calloc(1, sizeof(struct gtfile_s))) == NULL)
goto done;
gf->ctx = ctx;
@ -342,25 +342,18 @@ tlvWriteBlockHdr(gtfile gf) {
2 + hashOutputLengthOctets(gf->hashAlg) /* iv */ +
2 + 1 + gf->x_prev->len /* last hash */;
/* write top-level TLV object block-hdr */
r = tlv16Write(gf, 0x00, 0x0901, tlvlen);
CHKr(tlv16Write(gf, 0x00, 0x0901, tlvlen));
/* and now write the children */
/* hash-algo */
r = tlv8Write(gf, 0x00, 0x01, 1);
if(r != 0) goto done;
r = tlvbufAddOctet(gf, hashIdentifier(gf->hashAlg));
if(r != 0) goto done;
CHKr(tlv8Write(gf, 0x00, 0x01, 1));
CHKr(tlvbufAddOctet(gf, hashIdentifier(gf->hashAlg)));
/* block-iv */
r = tlv8Write(gf, 0x00, 0x02, hashOutputLengthOctets(gf->hashAlg));
if(r != 0) goto done;
r = tlvbufAddOctetString(gf, gf->IV, hashOutputLengthOctets(gf->hashAlg));
if(r != 0) goto done;
CHKr(tlv8Write(gf, 0x00, 0x02, hashOutputLengthOctets(gf->hashAlg)));
CHKr(tlvbufAddOctetString(gf, gf->IV, hashOutputLengthOctets(gf->hashAlg)));
/* last-hash */
r = tlv8Write(gf, 0x00, 0x03, gf->x_prev->len + 1);
if(r != 0) goto done;
r = tlvbufAddOctet(gf, gf->x_prev->hashID);
if(r != 0) goto done;
r = tlvbufAddOctetString(gf, gf->x_prev->data, gf->x_prev->len);
if(r != 0) goto done;
CHKr(tlv8Write(gf, 0x00, 0x03, gf->x_prev->len + 1));
CHKr(tlvbufAddOctet(gf, gf->x_prev->hashID));
CHKr(tlvbufAddOctetString(gf, gf->x_prev->data, gf->x_prev->len));
done: return r;
}
@ -420,6 +413,7 @@ readStateFile(gtfile gf)
if (gf->x_prev->data == NULL) {
free(gf->x_prev);
gf->x_prev = NULL;
goto err;
}
if(read(fd, gf->x_prev->data, gf->x_prev->len)
@ -432,7 +426,6 @@ readStateFile(gtfile gf)
return;
err:
gf->x_prev = malloc(sizeof(imprint_t));
gf->x_prev->hashID = hashIdentifier(gf->hashAlg);
gf->x_prev->len = hashOutputLengthOctets(gf->hashAlg);
@ -567,6 +560,8 @@ rsgtCtxOpenFile(gtctx ctx, unsigned char *logfn)
gf->statefilename = (uchar*) strdup(fn);
if(tlvOpen(gf, LOGSIGHDR, sizeof(LOGSIGHDR)-1) != 0) {
reportErr(ctx, "signature file open failed");
/* Free memory */
free(gf);
gf = NULL;
}
done: return gf;
@ -631,7 +626,7 @@ sigblkInit(gtfile gf)
{
if(gf == NULL) goto done;
seedIV(gf);
memset(gf->roots_valid, 0, sizeof(gf->roots_valid)/sizeof(char));
memset(gf->roots_valid, 0, sizeof(gf->roots_valid));
gf->nRoots = 0;
gf->nRecords = 0;
gf->bInBlk = 1;
@ -654,7 +649,7 @@ bufAddIV(gtfile gf, uchar *buf, size_t *len)
/* concat: add imprint to buffer */
static inline void
bufAddImprint(gtfile gf, uchar *buf, size_t *len, imprint_t *imp)
bufAddImprint(uchar *buf, size_t *len, imprint_t *imp)
{
buf[*len] = imp->hashID;
++(*len);
@ -688,7 +683,7 @@ hash_m(gtfile gf, GTDataHash **m)
size_t len = 0;
int r = 0;
bufAddImprint(gf, concatBuf, &len, gf->x_prev);
bufAddImprint(concatBuf, &len, gf->x_prev);
bufAddIV(gf, concatBuf, &len);
rgt = GTDataHash_create(gf->hashAlg, concatBuf, len, m);
if(rgt != GT_OK) {

View File

@ -332,7 +332,7 @@ int rsgt_getBlockParams(FILE *fp, uint8_t bRewind, block_sig_t **bs, block_hdr_t
int rsgt_chkFileHdr(FILE *fp, char *expect);
gtfile rsgt_vrfyConstruct_gf(void);
void rsgt_vrfyBlkInit(gtfile gf, block_hdr_t *bh, uint8_t bHasRecHashes, uint8_t bHasIntermedHashes);
int rsgt_vrfy_nextRec(block_sig_t *bs, gtfile gf, FILE *sigfp, FILE *nsigfp, unsigned char *rec, size_t len, gterrctx_t *ectx);
int rsgt_vrfy_nextRec(gtfile gf, FILE *sigfp, FILE *nsigfp, unsigned char *rec, size_t len, gterrctx_t *ectx);
int verifyBLOCK_HDR(FILE *sigfp, FILE *nsigfp);
int verifyBLOCK_SIG(block_sig_t *bs, gtfile gf, FILE *sigfp, FILE *nsigfp, uint8_t bExtend, gterrctx_t *ectx);
void rsgt_errctxInit(gterrctx_t *ectx);
@ -341,13 +341,16 @@ void rsgt_errctxSetErrRec(gterrctx_t *ectx, char *rec);
void rsgt_errctxFrstRecInBlk(gterrctx_t *ectx, char *rec);
void rsgt_objfree(uint16_t tlvtype, void *obj);
void rsgt_set_debug(int iDebug);
int rsgt_ConvertSigFile(char* name, FILE *oldsigfp, FILE *newsigfp, int verbose);
int rsgt_ConvertSigFile(FILE *oldsigfp, FILE *newsigfp, int verbose);
/* TODO: replace these? */
int hash_m(gtfile gf, GTDataHash **m);
int hash_r(gtfile gf, GTDataHash **r, const unsigned char *rec, const size_t len);
int hash_node(gtfile gf, GTDataHash **node, GTDataHash *m, GTDataHash *r, uint8_t level);
extern char *rsgt_read_puburl; /**< url of publication server */
extern char *rsgt_read_puburl; /**< url of publication server */
extern char *rsgt_extend_puburl; /**< url of extension server */
extern char *rsgt_userid; /**< userid for extension server */
extern char *rsgt_userkey; /**< userkey for extension server */
extern uint8_t rsgt_read_showVerified;
extern int RSGT_FLAG_TLV16_RUNTIME;
extern int RSGT_FLAG_NONCRIT_RUNTIME;

View File

@ -36,6 +36,8 @@ typedef struct imprint_s imprint_t;
typedef struct block_hdr_s block_hdr_t;
typedef struct block_sig_s block_sig_t;
typedef struct tlvrecord_s tlvrecord_t;
typedef struct block_hashchain_s block_hashchain_t;
typedef struct block_hashstep_s block_hashstep_t;
struct tlvrecord_s {
uint16_t tlvtype;
@ -47,7 +49,7 @@ struct tlvrecord_s {
struct imprint_s {
uint8_t hashID;
int len;
size_t len;
uint8_t *data;
};
@ -69,6 +71,23 @@ struct block_sig_s {
} sig;
};
struct block_hashstep_s {
uint8_t direction; /* left-link or right-link */
uint8_t level_corr;
imprint_t sib_hash;
};
struct block_hashchain_s {
imprint_t rec_hash;
uint64_t stepCount; /* Helper to count left & right links */
block_hashstep_t *hashsteps[MAX_ROOTS]; /* Using MAX_ROOTS here as well for the moment! */
uint8_t direction; /* left-link or right-link */
uint8_t level; /* default 0 */
// block_hashstep_t left_link;
// block_hashstep_t right_link;
};
static inline char *
sigTypeName(uint8_t sigID)
{
@ -85,4 +104,9 @@ sigTypeName(uint8_t sigID)
#define RSGT_TYPE_MASK 0x1f
#define RSGT_FLAG_TLV16 0x80
/* check return state of operation and abort, if non-OK */
#define CHKr(code) if((r = code) != 0) goto done
/* check return state of operation and jump to donedecode, if non-OK */
#define CHKrDecode(code) if((r = code) != 0) goto donedecode
#endif /* #ifndef INCLUDED_LIBRSGTCM_H */

View File

@ -53,6 +53,8 @@ typedef unsigned char uchar;
static int rsgt_read_debug = 0;
char *rsgt_read_puburl = "http://verify.guardtime.com/gt-controlpublications.bin";
char *rsgt_extend_puburl = "http://verifier.guardtime.net/gt-extendingservice";
char *rsgt_userid = "";
char *rsgt_userkey = "";
uint8_t rsgt_read_showVerified = 0;
/* macro to obtain next char from file including error tracking */
@ -61,16 +63,6 @@ uint8_t rsgt_read_showVerified = 0;
goto done; \
}
/* check return state of operation and abort, if non-OK */
#define CHKr(code) if((r = code) != 0) goto done
static void
errfunc(__attribute__((unused)) void *usrptr, uchar *emsg)
{
if (rsgt_read_debug)
printf("Internal Error: %s \n", emsg);
}
/* if verbose==0, only the first and last two octets are shown,
* otherwise everything.
*/
@ -233,7 +225,7 @@ static inline int rsgt_tlvfileAddOctet(FILE *newsigfp, int8_t octet)
int r = 0;
if ( fputc(octet, newsigfp) == EOF )
r = RSGTE_IO;
done: return r;
return r;
}
static inline int rsgt_tlvfileAddOctetString(FILE *newsigfp, uint8_t *octet, int size)
{
@ -389,7 +381,8 @@ rsgt_tlvRecRead(FILE *fp, tlvrecord_t *rec)
r = 0;
done:
if(rsgt_read_debug)
if(r == 0 && rsgt_read_debug)
/* Only show debug if no fail */
printf("debug: rsgt_tlvRecRead tlvtype %4.4x, len %u, r = %d\n", (unsigned) rec->tlvtype,
(unsigned) rec->tlvlen, r);
return r;
@ -450,7 +443,7 @@ static int
rsgt_tlvDecodeIMPRINT(tlvrecord_t *rec, imprint_t **imprint)
{
int r = 1;
imprint_t *imp;
imprint_t *imp = NULL;
if((imp = calloc(1, sizeof(imprint_t))) == NULL) {
r = RSGTE_OOM;
@ -468,8 +461,14 @@ rsgt_tlvDecodeIMPRINT(tlvrecord_t *rec, imprint_t **imprint)
*imprint = imp;
r = 0;
done:
if(rsgt_read_debug)
printf("debug: read tlvDecodeIMPRINT returned %d TLVLen=%d, HashID=%d\n", r, rec->tlvlen, imp->hashID);
if(r == 0) {
if(rsgt_read_debug)
printf("debug: read tlvDecodeIMPRINT returned %d TLVLen=%d, HashID=%d\n", r, rec->tlvlen, imp->hashID);
} else {
/* Free memory on FAIL!*/
if (imp != NULL)
rsgt_objfree(rec->tlvtype, imp);
}
return r;
}
@ -574,7 +573,7 @@ rsgt_tlvDecodeBLOCK_HDR(tlvrecord_t *rec, block_hdr_t **blockhdr)
{
int r = 1;
uint16_t strtidx = 0;
block_hdr_t *bh;
block_hdr_t *bh = NULL;
if((bh = calloc(1, sizeof(block_hdr_t))) == NULL) {
r = RSGTE_OOM;
goto done;
@ -589,8 +588,14 @@ rsgt_tlvDecodeBLOCK_HDR(tlvrecord_t *rec, block_hdr_t **blockhdr)
*blockhdr = bh;
r = 0;
done:
if(rsgt_read_debug)
printf("debug: rsgt_tlvDecodeBLOCK_HDR returned %d, tlvtype %4.4x\n", r, (unsigned) rec->tlvtype);
if (r == 0) {
if(rsgt_read_debug)
printf("debug: tlvDecodeBLOCK_HDR returned %d, tlvtype %4.4x\n", r, (unsigned) rec->tlvtype);
} else {
/* Free memory on FAIL!*/
if (bh != NULL)
rsgt_objfree(rec->tlvtype, bh);
}
return r;
}
@ -599,7 +604,7 @@ rsgt_tlvDecodeBLOCK_SIG(tlvrecord_t *rec, block_sig_t **blocksig)
{
int r = 1;
uint16_t strtidx = 0;
block_sig_t *bs;
block_sig_t *bs = NULL;
if((bs = calloc(1, sizeof(block_sig_t))) == NULL) {
r = RSGTE_OOM;
goto done;
@ -613,8 +618,14 @@ rsgt_tlvDecodeBLOCK_SIG(tlvrecord_t *rec, block_sig_t **blocksig)
*blocksig = bs;
r = 0;
done:
if(rsgt_read_debug)
printf("debug: rsgt_tlvDecodeBLOCK_SIG returned %d, tlvtype %4.4x\n", r, (unsigned) rec->tlvtype);
if(r == 0) {
if (rsgt_read_debug)
printf("debug: rsgt_tlvDecodeBLOCK_SIG returned %d, tlvtype %4.4x\n", r, (unsigned) rec->tlvtype);
} else {
/* Free memory on FAIL!*/
if (bs != NULL)
rsgt_objfree(rec->tlvtype, bs);
}
return r;
}
static int
@ -637,8 +648,8 @@ rsgt_tlvRecDecode(tlvrecord_t *rec, void *obj)
break;
}
done:
if(rsgt_read_debug)
printf("debug: rsgt_tlvRecDecode returned %d, tlvtype %4.4x\n", r, (unsigned) rec->tlvtype);
if(r == 0 && rsgt_read_debug)
printf("debug: tlvRecDecode returned %d, tlvtype %4.4x\n", r, (unsigned) rec->tlvtype);
return r;
}
@ -652,14 +663,15 @@ rsgt_tlvrdRecHash(FILE *fp, FILE *outfp, imprint_t **imp)
if(rec.tlvtype != 0x0902) {
r = RSGTE_MISS_REC_HASH;
rsgt_objfree(rec.tlvtype, *imp);
*imp = NULL;
goto done;
}
if(outfp != NULL)
if((r = rsgt_tlvwrite(outfp, &rec)) != 0) goto done;
r = 0;
done:
if(rsgt_read_debug)
printf("debug: rsgt_tlvrdRecHash returned %d, rec->tlvtype %4.4x\n", r, (unsigned) rec.tlvtype);
if(r == 0 && rsgt_read_debug)
printf("debug: tlvrdRecHash returned %d, rec->tlvtype %4.4x\n", r, (unsigned) rec.tlvtype);
return r;
}
@ -673,14 +685,15 @@ rsgt_tlvrdTreeHash(FILE *fp, FILE *outfp, imprint_t **imp)
if(rec.tlvtype != 0x0903) {
r = RSGTE_MISS_TREE_HASH;
rsgt_objfree(rec.tlvtype, *imp);
*imp = NULL;
goto done;
}
if(outfp != NULL)
if((r = rsgt_tlvwrite(outfp, &rec)) != 0) goto done;
r = 0;
done:
if(rsgt_read_debug)
printf("debug: rsgt_tlvrdTreeHash returned %d, rec->tlvtype %4.4x\n", r, (unsigned) rec.tlvtype);
if(r == 0 && rsgt_read_debug)
printf("debug: tlvrdTreeHash returned %d, rec->tlvtype %4.4x\n", r, (unsigned) rec.tlvtype);
return r;
}
@ -847,6 +860,10 @@ rsgt_tlvprint(FILE *fp, uint16_t tlvtype, void *obj, uint8_t verbose)
void
rsgt_objfree(uint16_t tlvtype, void *obj)
{
// check if obj is valid
if (obj == NULL )
return;
switch(tlvtype) {
case 0x0901:
free(((block_hdr_t*)obj)->iv);
@ -1061,15 +1078,17 @@ rsgt_vrfy_chkTreeHash(gtfile gf, FILE *sigfp, FILE *nsigfp,
}
r = 0;
done:
if(rsgt_read_debug)
printf("debug: rsgt_vrfy_chkTreeHash returned %d, hashID=%d, Length=%d\n", r, imp->hashID, hashOutputLengthOctets(imp->hashID));
if(imp != NULL)
if(imp != NULL) {
if(rsgt_read_debug)
printf("debug: rsgt_vrfy_chkTreeHash returned %d, hashID=%d, Length=%d\n", r, imp->hashID, hashOutputLengthOctets(imp->hashID));
/* Free memory */
rsgt_objfree(0x0903, imp);
}
return r;
}
int
rsgt_vrfy_nextRec(block_sig_t *bs, gtfile gf, FILE *sigfp, FILE *nsigfp,
rsgt_vrfy_nextRec(gtfile gf, FILE *sigfp, FILE *nsigfp,
unsigned char *rec, size_t len, gterrctx_t *ectx)
{
int r = 0;
@ -1176,6 +1195,7 @@ done:
iWr += subrec.lenHdr; \
memcpy(newrec.data+iWr, subrec.data, subrec.tlvlen); \
iWr += subrec.tlvlen;
static inline int
rsgt_extendSig(GTTimestamp *timestamp, tlvrecord_t *rec, gterrctx_t *ectx)
{
@ -1204,19 +1224,19 @@ rsgt_extendSig(GTTimestamp *timestamp, tlvrecord_t *rec, gterrctx_t *ectx)
*/
iRd = iWr = 0;
// TODO; check tlvtypes at comment places below!
if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done;
CHKr(rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec));
/* HASH_ALGO */
COPY_SUBREC_TO_NEWREC
if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done;
CHKr(rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec));
/* BLOCK_IV */
COPY_SUBREC_TO_NEWREC
if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done;
CHKr(rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec));
/* LAST_HASH */
COPY_SUBREC_TO_NEWREC
if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done;
CHKr(rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec));
/* REC_COUNT */
COPY_SUBREC_TO_NEWREC
if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done;
CHKr(rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec));
/* actual sig! */
newrec.data[iWr++] = 0x09 | RSGT_FLAG_TLV16_RUNTIME;
newrec.data[iWr++] = 0x06;
@ -1253,7 +1273,12 @@ verifyBLOCK_HDR(FILE *sigfp, FILE *nsigfp)
}
if (nsigfp != NULL)
if ((r = rsgt_tlvwrite(nsigfp, &rec)) != 0) goto done;
done: rsgt_objfree(rec.tlvtype, bh);
done:
/* if (r == 0 || r == RSGTE_IO)*/ {
/* Only free memory if return is OK or error was RSGTE_IO was (happened in rsksi_tlvwrite) */
if (bh != NULL)
rsgt_objfree(rec.tlvtype, bh);
}
if(rsgt_read_debug)
printf("debug: verifyBLOCK_HDR returned %d\n", r);
return r;
@ -1325,7 +1350,7 @@ void rsgt_set_debug(int iDebug)
}
/* Helper function to convert an old V10 signature file into V11 */
int rsgt_ConvertSigFile(char* name, FILE *oldsigfp, FILE *newsigfp, int verbose)
int rsgt_ConvertSigFile(FILE *oldsigfp, FILE *newsigfp, int verbose)
{
int r = 0, rRead = 0;
imprint_t *imp = NULL;
@ -1373,6 +1398,7 @@ int rsgt_ConvertSigFile(char* name, FILE *oldsigfp, FILE *newsigfp, int verbose)
/* Free mem*/
free(imp->data);
free(imp);
imp = NULL;
break;
case 0x0902:
/* Split Data into HEADER and BLOCK */
@ -1389,7 +1415,7 @@ int rsgt_ConvertSigFile(char* name, FILE *oldsigfp, FILE *newsigfp, int verbose)
}
/* Check OLD encoded HASH ALGO */
CHKr(rsgt_tlvDecodeSUBREC(&rec, &strtidx, &subrec));
CHKrDecode(rsgt_tlvDecodeSUBREC(&rec, &strtidx, &subrec));
if(!(subrec.tlvtype == 0x00 && subrec.tlvlen == 1)) {
r = RSGTE_FMT;
goto donedecode;
@ -1397,7 +1423,7 @@ int rsgt_ConvertSigFile(char* name, FILE *oldsigfp, FILE *newsigfp, int verbose)
bh->hashID = subrec.data[0];
/* Check OLD encoded BLOCK_IV */
CHKr(rsgt_tlvDecodeSUBREC(&rec, &strtidx, &subrec));
CHKrDecode(rsgt_tlvDecodeSUBREC(&rec, &strtidx, &subrec));
if(!(subrec.tlvtype == 0x01)) {
r = RSGTE_INVLTYP;
goto donedecode;
@ -1406,7 +1432,7 @@ int rsgt_ConvertSigFile(char* name, FILE *oldsigfp, FILE *newsigfp, int verbose)
memcpy(bh->iv, subrec.data, subrec.tlvlen);
/* Check OLD encoded LAST HASH */
CHKr(rsgt_tlvDecodeSUBREC(&rec, &strtidx, &subrec));
CHKrDecode(rsgt_tlvDecodeSUBREC(&rec, &strtidx, &subrec));
if(!(subrec.tlvtype == 0x02)) { r = RSGTE_INVLTYP; goto donedecode; }
bh->lastHash.hashID = subrec.data[0];
if(subrec.tlvlen != 1 + hashOutputLengthOctets(bh->lastHash.hashID)) {
@ -1421,7 +1447,7 @@ int rsgt_ConvertSigFile(char* name, FILE *oldsigfp, FILE *newsigfp, int verbose)
rsgt_printBLOCK_HDR(stdout, bh, verbose);
/* Check OLD encoded COUNT */
CHKr(rsgt_tlvDecodeSUBREC(&rec, &strtidx, &subrec));
CHKrDecode(rsgt_tlvDecodeSUBREC(&rec, &strtidx, &subrec));
if(!(subrec.tlvtype == 0x03 && subrec.tlvlen <= 8)) { r = RSGTE_INVLTYP; goto donedecode; }
bs->recCount = 0;
for(i = 0 ; i < subrec.tlvlen ; ++i) {
@ -1429,13 +1455,12 @@ int rsgt_ConvertSigFile(char* name, FILE *oldsigfp, FILE *newsigfp, int verbose)
}
/* Check OLD encoded SIG */
CHKr(rsgt_tlvDecodeSUBREC(&rec, &strtidx, &subrec));
CHKrDecode(rsgt_tlvDecodeSUBREC(&rec, &strtidx, &subrec));
if(!(subrec.tlvtype == 0x0906)) { r = RSGTE_INVLTYP; goto donedecode; }
bs->sig.der.len = subrec.tlvlen;
bs->sigID = SIGID_RFC3161;
if((bs->sig.der.data = (uint8_t*)malloc(bs->sig.der.len)) == NULL) {r=RSGTE_OOM;goto donedecode;}
memcpy(bs->sig.der.data, subrec.data, bs->sig.der.len);
r = 0;
/* Debug output */
rsgt_printBLOCK_SIG(stdout, bs, verbose);
@ -1453,48 +1478,37 @@ int rsgt_ConvertSigFile(char* name, FILE *oldsigfp, FILE *newsigfp, int verbose)
2 + hashOutputLengthOctets(bh->hashID) /* iv */ +
2 + 1 + bh->lastHash.len /* last hash */;
/* write top-level TLV object block-hdr */
r = rsgt_tlv16Write(newsigfp, 0x00, 0x0901, tlvlen);
CHKrDecode(rsgt_tlv16Write(newsigfp, 0x00, 0x0901, tlvlen));
/* and now write the children */
/* hash-algo */
r = rsgt_tlv8Write(newsigfp, 0x00, 0x01, 1);
if(r != 0) goto done;
r = rsgt_tlvfileAddOctet(newsigfp, hashIdentifier(bh->hashID));
if(r != 0) goto done;
CHKrDecode(rsgt_tlv8Write(newsigfp, 0x00, 0x01, 1));
CHKrDecode(rsgt_tlvfileAddOctet(newsigfp, hashIdentifier(bh->hashID)));
/* block-iv */
r = rsgt_tlv8Write(newsigfp, 0x00, 0x02, hashOutputLengthOctets(bh->hashID));
if(r != 0) goto done;
r = rsgt_tlvfileAddOctetString(newsigfp, bh->iv, hashOutputLengthOctets(bh->hashID));
if(r != 0) goto done;
CHKrDecode(rsgt_tlv8Write(newsigfp, 0x00, 0x02, hashOutputLengthOctets(bh->hashID)));
CHKrDecode(rsgt_tlvfileAddOctetString(newsigfp, bh->iv, hashOutputLengthOctets(bh->hashID)));
/* last-hash */
r = rsgt_tlv8Write(newsigfp, 0x00, 0x03, bh->lastHash.len + 1);
if(r != 0) goto done;
r = rsgt_tlvfileAddOctet(newsigfp, bh->lastHash.hashID);
if(r != 0) goto done;
r = rsgt_tlvfileAddOctetString(newsigfp, bh->lastHash.data, bh->lastHash.len);
if(r != 0) goto done;
CHKrDecode(rsgt_tlv8Write(newsigfp, 0x00, 0x03, bh->lastHash.len + 1));
CHKrDecode(rsgt_tlvfileAddOctet(newsigfp, bh->lastHash.hashID));
CHKrDecode(rsgt_tlvfileAddOctetString(newsigfp, bh->lastHash.data, bh->lastHash.len));
/* Create Block Signature */
tlvlenRecords = rsgt_tlvGetInt64OctetSize(bs->recCount);
tlvlen = 2 + tlvlenRecords /* rec-count */ +
4 + bs->sig.der.len /* rfc-3161 */;
/* write top-level TLV object (block-sig */
r = rsgt_tlv16Write(newsigfp, 0x00, 0x0904, tlvlen);
if(r != 0) goto done;
CHKrDecode(rsgt_tlv16Write(newsigfp, 0x00, 0x0904, tlvlen));
/* and now write the children */
/* rec-count */
r = rsgt_tlv8Write(newsigfp, 0x00, 0x01, tlvlenRecords);
if(r != 0) goto done;
r = rsgt_tlvfileAddInt64(newsigfp, bs->recCount);
if(r != 0) goto done;
CHKrDecode(rsgt_tlv8Write(newsigfp, 0x00, 0x01, tlvlenRecords));
CHKrDecode(rsgt_tlvfileAddInt64(newsigfp, bs->recCount));
/* rfc-3161 */
r = rsgt_tlv16Write(newsigfp, 0x00, 0x906, bs->sig.der.len);
if(r != 0) goto done;
r = rsgt_tlvfileAddOctetString(newsigfp, bs->sig.der.data, bs->sig.der.len);
CHKrDecode(rsgt_tlv16Write(newsigfp, 0x00, 0x906, bs->sig.der.len));
CHKrDecode(rsgt_tlvfileAddOctetString(newsigfp, bs->sig.der.data, bs->sig.der.len));
donedecode:
/* Set back to OLD default */
RSGT_FLAG_TLV16_RUNTIME = 0x20;
donedecode:
/* Free mem*/
if (bh != NULL) {
free(bh->iv);

View File

@ -71,7 +71,7 @@ reportErr(rsksictx ctx, char *errmsg)
done: return;
}
static void
void
reportKSIAPIErr(rsksictx ctx, ksifile ksi, char *apiname, int ecode)
{
char errbuf[4096];
@ -89,31 +89,51 @@ rsksisetErrFunc(rsksictx ctx, void (*func)(void*, uchar *), void *usrptr)
ctx->errFunc = func;
}
imprint_t *
rsksiImprintFromKSI_DataHash(ksifile ksi, KSI_DataHash *hash)
int
rsksiIntoImprintFromKSI_DataHash(imprint_t* imp, ksifile ksi, KSI_DataHash *hash)
{
int r;
imprint_t *imp;
int r = RSGTE_SUCCESS;
const unsigned char *digest;
unsigned digest_len;
size_t digest_len;
if((imp = calloc(1, sizeof(imprint_t))) == NULL) {
goto done;
}
int hashID;
KSI_HashAlgorithm hashID;
r = KSI_DataHash_extract(hash, &hashID, &digest, &digest_len);
if (r != KSI_OK){
reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHash_extract", r);
free(imp); imp = NULL; goto done;
r = RSGTE_IO;
goto done;
}
imp->hashID = hashID;
imp->len = digest_len;
if((imp->data = (uint8_t*)malloc(imp->len)) == NULL) {
free(imp); imp = NULL; goto done;
r = RSGTE_OOM;
goto done;
}
memcpy(imp->data, digest, digest_len);
done: return imp;
done:
return r;
}
imprint_t *
rsksiImprintFromKSI_DataHash(ksifile ksi, KSI_DataHash *hash)
{
int r;
imprint_t *imp;
if((imp = calloc(1, sizeof(imprint_t))) == NULL) {
goto done;
}
r = rsksiIntoImprintFromKSI_DataHash(imp, ksi, hash);
if (r != RSGTE_SUCCESS) {
free(imp);
imp = NULL;
goto done;
}
done:
return imp;
}
void
@ -126,25 +146,9 @@ rsksiimprintDel(imprint_t *imp)
}
int
rsksiInit(char *usragent)
rsksiInit(__attribute__((unused)) char *usragent)
{
int r = 0;
int ret = KSI_OK;
/*
ret = GT_init();
if(ret != KSI_OK) {
r = 1;
goto done;
}
ret = GTHTTP_init(usragent, 1);
if(ret != KSI_OK) {
r = 1;
goto done;
}
*/
done: return r;
return 0;
}
void
@ -156,7 +160,7 @@ rsksiExit(void)
static inline ksifile
rsksifileConstruct(rsksictx ctx)
{
ksifile ksi;
ksifile ksi = NULL;
if((ksi = calloc(1, sizeof(struct ksifile_s))) == NULL)
goto done;
ksi->ctx = ctx;
@ -169,14 +173,14 @@ rsksifileConstruct(rsksictx ctx)
done: return ksi;
}
static inline int
static inline size_t
tlvbufPhysWrite(ksifile ksi)
{
ssize_t lenBuf;
ssize_t iTotalWritten;
ssize_t iWritten;
char *pWriteBuf;
int r = 0;
size_t r = 0;
lenBuf = ksi->tlvIdx;
pWriteBuf = ksi->tlvBuf;
@ -204,7 +208,7 @@ finalize_it:
return r;
}
static inline int
static inline size_t
tlvbufChkWrite(ksifile ksi)
{
if(ksi->tlvIdx == sizeof(ksi->tlvBuf)) {
@ -217,19 +221,19 @@ tlvbufChkWrite(ksifile ksi)
/* write to TLV file buffer. If buffer is full, an actual call occurs. Else
* output is written only on flush or close.
*/
static inline int
static inline size_t
tlvbufAddOctet(ksifile ksi, int8_t octet)
{
int r;
size_t r;
r = tlvbufChkWrite(ksi);
if(r != 0) goto done;
ksi->tlvBuf[ksi->tlvIdx++] = octet;
done: return r;
}
static inline int
tlvbufAddOctetString(ksifile ksi, uint8_t *octet, int size)
static inline size_t
tlvbufAddOctetString(ksifile ksi, uint8_t *octet, size_t size)
{
int i, r = 0;
size_t i, r = 0;
for(i = 0 ; i < size ; ++i) {
r = tlvbufAddOctet(ksi, octet[i]);
if(r != 0) goto done;
@ -336,7 +340,7 @@ tlvWriteHashKSI(ksifile ksi, uint16_t tlvtype, KSI_DataHash *rec)
unsigned tlvlen;
int r;
const unsigned char *digest;
unsigned digest_len;
size_t digest_len;
r = KSI_DataHash_extract(rec, NULL, &digest, &digest_len);
if (r != KSI_OK){
reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHash_extract", r);
@ -359,25 +363,18 @@ tlvWriteBlockHdrKSI(ksifile ksi) {
2 + hashOutputLengthOctetsKSI(ksi->hashAlg) /* iv */ +
2 + 1 + ksi->x_prev->len /* last hash */;
/* write top-level TLV object block-hdr */
r = tlv16WriteKSI(ksi, 0x00, 0x0901, tlvlen);
CHKr(tlv16WriteKSI(ksi, 0x00, 0x0901, tlvlen));
/* and now write the children */
/* hash-algo */
r = tlv8WriteKSI(ksi, 0x00, 0x01, 1);
if(r != 0) goto done;
r = tlvbufAddOctet(ksi, hashIdentifierKSI(ksi->hashAlg));
if(r != 0) goto done;
CHKr(tlv8WriteKSI(ksi, 0x00, 0x01, 1));
CHKr(tlvbufAddOctet(ksi, hashIdentifierKSI(ksi->hashAlg)));
/* block-iv */
r = tlv8WriteKSI(ksi, 0x00, 0x02, hashOutputLengthOctetsKSI(ksi->hashAlg));
if(r != 0) goto done;
r = tlvbufAddOctetString(ksi, ksi->IV, hashOutputLengthOctetsKSI(ksi->hashAlg));
if(r != 0) goto done;
CHKr(tlv8WriteKSI(ksi, 0x00, 0x02, hashOutputLengthOctetsKSI(ksi->hashAlg)));
CHKr(tlvbufAddOctetString(ksi, ksi->IV, hashOutputLengthOctetsKSI(ksi->hashAlg)));
/* last-hash */
r = tlv8WriteKSI(ksi, 0x00, 0x03, ksi->x_prev->len + 1);
if(r != 0) goto done;
r = tlvbufAddOctet(ksi, ksi->x_prev->hashID);
if(r != 0) goto done;
r = tlvbufAddOctetString(ksi, ksi->x_prev->data, ksi->x_prev->len);
if(r != 0) goto done;
CHKr(tlv8WriteKSI(ksi, 0x00, 0x03, ksi->x_prev->len + 1));
CHKr(tlvbufAddOctet(ksi, ksi->x_prev->hashID));
CHKr(tlvbufAddOctetString(ksi, ksi->x_prev->data, ksi->x_prev->len));
done: return r;
}
@ -401,8 +398,8 @@ tlvWriteBlockSigKSI(ksifile ksi, uchar *der, uint16_t lenDer)
if(r != 0) goto done;
r = tlvbufAddInt64(ksi, ksi->nRecords);
if(r != 0) goto done;
/* rfc-3161 */
r = tlv16WriteKSI(ksi, 0x00, 0x906, lenDer);
/* Open-KSI signature */
r = tlv16WriteKSI(ksi, 0x00, 0x0905, lenDer);
if(r != 0) goto done;
r = tlvbufAddOctetString(ksi, der, lenDer);
done: return r;
@ -439,10 +436,11 @@ readStateFile(ksifile ksi)
if (ksi->x_prev->data == NULL) {
free(ksi->x_prev);
ksi->x_prev = NULL;
goto err;
}
if(read(fd, ksi->x_prev->data, ksi->x_prev->len)
!= ksi->x_prev->len) {
!= (ssize_t) ksi->x_prev->len) {
rsksiimprintDel(ksi->x_prev);
ksi->x_prev = NULL;
goto err;
@ -451,7 +449,6 @@ readStateFile(ksifile ksi)
return;
err:
ksi->x_prev = malloc(sizeof(imprint_t));
ksi->x_prev->hashID = hashIdentifierKSI(ksi->hashAlg);
ksi->x_prev->len = hashOutputLengthOctetsKSI(ksi->hashAlg);
@ -587,6 +584,8 @@ rsksiCtxOpenFile(rsksictx ctx, unsigned char *logfn)
ksi->statefilename = (uchar*) strdup(fn);
if(tlvOpenKSI(ksi, LOGSIGHDR, sizeof(LOGSIGHDR)-1) != 0) {
reportErr(ctx, "signature file open failed");
/* Free memory */
free(ksi);
ksi = NULL;
}
done: return ksi;
@ -610,8 +609,6 @@ rsksiSetHashFunction(rsksictx ctx, char *algName)
ctx->hashAlg = KSI_HASHALG_SHA2_384;
else if(!strcmp(algName, "SHA2-512"))
ctx->hashAlg = KSI_HASHALG_SHA2_512;
else if(!strcmp(algName, "RIPEMD-256"))
ctx->hashAlg = KSI_HASHALG_RIPEMD_256;
else if(!strcmp(algName, "SHA3-244"))
ctx->hashAlg = KSI_HASHALG_SHA3_244;
else if(!strcmp(algName, "SHA3-256"))
@ -664,7 +661,7 @@ sigblkInitKSI(ksifile ksi)
{
if(ksi == NULL) goto done;
seedIVKSI(ksi);
memset(ksi->roots_valid, 0, sizeof(ksi->roots_valid)/sizeof(char));
memset(ksi->roots_valid, 0, sizeof(ksi->roots_valid));
ksi->nRoots = 0;
ksi->nRecords = 0;
ksi->bInBlk = 1;
@ -687,7 +684,7 @@ bufAddIV(ksifile ksi, uchar *buf, size_t *len)
/* concat: add imprint to buffer */
static inline void
bufAddImprint(ksifile ksi, uchar *buf, size_t *len, imprint_t *imp)
bufAddImprint(uchar *buf, size_t *len, imprint_t *imp)
{
buf[*len] = imp->hashID;
++(*len);
@ -701,7 +698,7 @@ bufAddHash(ksifile ksi, uchar *buf, size_t *len, KSI_DataHash *hash)
{
int r;
const unsigned char *digest;
unsigned digest_len;
size_t digest_len;
r = KSI_DataHash_extract(hash, NULL, &digest, &digest_len); // TODO: error check
if (r != KSI_OK){
reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHash_extract", r);
@ -730,7 +727,7 @@ hash_m_ksi(ksifile ksi, KSI_DataHash **m)
size_t len = 0;
int r = 0;
bufAddImprint(ksi, concatBuf, &len, ksi->x_prev);
bufAddImprint(concatBuf, &len, ksi->x_prev);
bufAddIV(ksi, concatBuf, &len);
rgt = KSI_DataHash_create(ksi->ctx->ksi_ctx, concatBuf, len, ksi->hashAlg, m);
if(rgt != KSI_OK) {
@ -847,7 +844,7 @@ static int
signIt(ksifile ksi, KSI_DataHash *hash)
{
unsigned char *der = NULL;
unsigned lenDer;
size_t lenDer;
int r = KSI_OK;
int ret = 0;
KSI_Signature *sig = NULL;

View File

@ -61,7 +61,7 @@ struct ksifile_s {
uint8_t disabled; /* permits to disable this file --> set to 1 */
uint64_t blockSizeLimit;
uint8_t *IV; /* initial value for blinding masks */
imprint_t *x_prev; /* last leaf hash (maybe of previous block) --> preserve on term */
imprint_t *x_prev; /* last leaf hash (maybe of previous block) --> preserve on term */
unsigned char *sigfilename;
unsigned char *statefilename;
int fd;
@ -119,6 +119,7 @@ struct rsksistatefile {
};
/* error states */
#define RSGTE_SUCCESS 0 /* Success state */
#define RSGTE_IO 1 /* any kind of io error */
#define RSGTE_FMT 2 /* data fromat error */
#define RSGTE_INVLTYP 3 /* invalid TLV type record (unexcpected at this point) */
@ -142,6 +143,7 @@ struct rsksistatefile {
#define RSGTE_HASH_CREATE 20 /* error creating a hash */
#define RSGTE_END_OF_SIG 21 /* unexpected end of signature - more log line exist */
#define RSGTE_END_OF_LOG 22 /* unexpected end of log file - more signatures exist */
#define RSGTE_EXTRACT_HASH 23 /* error extracting hashes for record */
/* the following function maps RSGTE_* state to a string - must be updated
* whenever a new state is added.
@ -152,7 +154,7 @@ static inline char *
RSKSIE2String(int err)
{
switch(err) {
case 0:
case RSGTE_SUCCESS:
return "success";
case RSGTE_IO:
return "i/o error";
@ -198,6 +200,8 @@ RSKSIE2String(int err)
return "unexpected end of signature";
case RSGTE_END_OF_LOG:
return "unexpected end of log";
case RSGTE_EXTRACT_HASH:
return "either record-hash, left-hash or right-hash was empty";
default:
return "unknown error";
}
@ -220,8 +224,6 @@ hashOutputLengthOctetsKSI(uint8_t hashID)
return 48;
case KSI_HASHALG_SHA2_512: /** The SHA-512 algorithm. */
return 64;
case KSI_HASHALG_RIPEMD_256: /** The RIPEMD-256 algorithm. */
return 32;
case KSI_HASHALG_SHA3_244: /** The SHA3-244 algorithm. */
return 28;
case KSI_HASHALG_SHA3_256: /** The SHA3-256 algorithm. */
@ -252,8 +254,6 @@ hashIdentifierKSI(KSI_HashAlgorithm hashID)
return 0x04;
case KSI_HASHALG_SHA2_512: /** The SHA-512 algorithm. */
return 0x05;
case KSI_HASHALG_RIPEMD_256: /** The RIPEMD-256 algorithm. */
return 0x06;
case KSI_HASHALG_SHA3_244: /** The SHA3-244 algorithm. */
return 0x07;
case KSI_HASHALG_SHA3_256: /** The SHA3-256 algorithm. */
@ -283,8 +283,6 @@ hashAlgNameKSI(uint8_t hashID)
return "SHA2-384";
case KSI_HASHALG_SHA2_512:
return "SHA2-512";
case KSI_HASHALG_RIPEMD_256:
return "RIPEMD-256";
case KSI_HASHALG_SHA3_244:
return "SHA3-224";
case KSI_HASHALG_SHA3_256:
@ -314,8 +312,6 @@ hashID2AlgKSI(uint8_t hashID)
return KSI_HASHALG_SHA2_384;
case 0x05:
return KSI_HASHALG_SHA2_512;
case 0x06:
return KSI_HASHALG_RIPEMD_256;
case 0x07:
return KSI_HASHALG_SHA3_244;
case 0x08:
@ -357,13 +353,15 @@ int rsksiInit(char *usragent);
void rsksiExit(void);
rsksictx rsksiCtxNew(void);
void rsksisetErrFunc(rsksictx ctx, void (*func)(void*, unsigned char *), void *usrptr);
void reportKSIAPIErr(rsksictx ctx, ksifile ksi, char *apiname, int ecode);
ksifile rsksiCtxOpenFile(rsksictx ctx, unsigned char *logfn);
int rsksifileDestruct(ksifile ksi);
void rsksiCtxDel(rsksictx ctx);
void sigblkInitKSI(ksifile ksi);
int sigblkAddRecordKSI(ksifile ksi, const unsigned char *rec, const size_t len);
int sigblkFinishKSI(ksifile ksi);
imprint_t * rsksiImprintFromKSI_DataHash(ksifile ksi, KSI_DataHash *hash);
int rsksiIntoImprintFromKSI_DataHash(imprint_t* imp, ksifile ksi, KSI_DataHash *hash);
imprint_t* rsksiImprintFromKSI_DataHash(ksifile ksi, KSI_DataHash *hash);
void rsksiimprintDel(imprint_t *imp);
/* reader functions */
int rsksi_tlvrdHeader(FILE *fp, unsigned char *hdr);
@ -371,13 +369,16 @@ int rsksi_tlvrd(FILE *fp, tlvrecord_t *rec, void *obj);
void rsksi_tlvprint(FILE *fp, uint16_t tlvtype, void *obj, uint8_t verbose);
void rsksi_printBLOCK_HDR(FILE *fp, block_hdr_t *bh, uint8_t verbose);
void rsksi_printBLOCK_SIG(FILE *fp, block_sig_t *bs, uint8_t verbose);
int rsksi_getBlockParams(FILE *fp, uint8_t bRewind, block_sig_t **bs, block_hdr_t **bh, uint8_t *bHasRecHashes, uint8_t *bHasIntermedHashes);
int rsksi_chkFileHdr(FILE *fp, char *expect);
int rsksi_getBlockParams(ksifile ksi, FILE *fp, uint8_t bRewind, block_sig_t **bs, block_hdr_t **bh, uint8_t *bHasRecHashes, uint8_t *bHasIntermedHashes);
int rsksi_getExcerptBlockParams(ksifile ksi, FILE *fp, uint8_t bRewind, block_sig_t **bs, block_hdr_t **bh);
int rsksi_chkFileHdr(FILE *fp, char *expect, uint8_t verbose);
ksifile rsksi_vrfyConstruct_gf(void);
void rsksi_vrfyBlkInit(ksifile ksi, block_hdr_t *bh, uint8_t bHasRecHashes, uint8_t bHasIntermedHashes);
int rsksi_vrfy_nextRec(ksifile ksi, FILE *sigfp, FILE *nsigfp, unsigned char *rec, size_t len, ksierrctx_t *ectx);
int verifyBLOCK_HDRKSI(FILE *sigfp, FILE *nsigfp);
int verifyBLOCK_SIGKSI(block_sig_t *bs, ksifile ksi, FILE *sigfp, FILE *nsigfp, uint8_t bExtend, ksierrctx_t *ectx);
int rsksi_vrfy_nextRecExtract(ksifile ksi, FILE *sigfp, FILE *nsigfp, unsigned char *rec, size_t len, ksierrctx_t *ectx, block_hashchain_t *hashchain, int storehashchain);
int rsksi_vrfy_nextHashChain(ksifile ksi, block_sig_t *bs, FILE *sigfp, unsigned char *rec, size_t len, ksierrctx_t *ectx);
int verifyBLOCK_HDRKSI(ksifile ksi, FILE *sigfp, FILE *nsigfp, tlvrecord_t* tlvrec);
int verifyBLOCK_SIGKSI(block_sig_t *bs, ksifile ksi, FILE *sigfp, FILE *nsigfp, uint8_t bExtend, KSI_DataHash *ksiHash, ksierrctx_t *ectx);
void rsksi_errctxInit(ksierrctx_t *ectx);
void rsksi_errctxExit(ksierrctx_t *ectx);
void rsksi_errctxSetErrRec(ksierrctx_t *ectx, char *rec);
@ -385,12 +386,27 @@ void rsksi_errctxFrstRecInBlk(ksierrctx_t *ectx, char *rec);
void rsksi_objfree(uint16_t tlvtype, void *obj);
void rsksi_set_debug(int iDebug);
int rsksi_ConvertSigFile(char* name, FILE *oldsigfp, FILE *newsigfp, int verbose);
int rsksi_WriteHashChain(FILE *newsigfp, block_hashchain_t *hashchain, block_sig_t *bsIn, int verbose);
int rsksi_ExtractBlockSignature(FILE *newsigfp, ksifile ksi, block_sig_t *bsIn, ksierrctx_t *ectx, int verbose);
int rsksi_tlvwrite(FILE *fp, tlvrecord_t *rec);
int rsksi_tlvRecDecode(tlvrecord_t *rec, void *obj);
int rsksi_tlvDecodeIMPRINT(tlvrecord_t *rec, imprint_t **imprint);
int rsksi_tlvDecodeHASHCHAIN(tlvrecord_t *rec, block_hashchain_t **blhashchain);
int verifySigblkFinish(ksifile ksi, KSI_DataHash **pRoot);
int verifySigblkFinishChain(ksifile ksi, block_hashchain_t *hashchain, KSI_DataHash **pRoot, ksierrctx_t *ectx);
void outputHash(FILE *fp, const char *hdr, const uint8_t *data, const uint16_t len, const uint8_t verbose);
void outputKSIHash(FILE *fp, char *hdr, const KSI_DataHash *const __restrict__ hash, const uint8_t verbose);
/* TODO: replace these? */
int hash_m_ksi(ksifile ksi, KSI_DataHash **m);
int hash_r_ksi(ksifile ksi, KSI_DataHash **r, const unsigned char *rec, const size_t len);
int hash_node_ksi(ksifile ksi, KSI_DataHash **node, KSI_DataHash *m, KSI_DataHash *r, uint8_t level);
extern char *rsksi_read_puburl; /**< url of publication server */
extern char *rsksi_read_puburl; /**< url of publication server */
extern char *rsksi_extend_puburl; /**< url of extension server */
extern char *rsksi_userid; /**< userid for extension server */
extern char *rsksi_userkey; /**< userkey for extension server */
extern uint8_t rsksi_read_showVerified;
extern int RSKSI_FLAG_TLV16_RUNTIME;
extern int RSKSI_FLAG_NONCRIT_RUNTIME;

File diff suppressed because it is too large Load Diff

View File

@ -102,7 +102,7 @@ SetCnfParam(void *pT, struct nvlst *lst, int paramType)
{
lmcry_gcry_t *pThis = (lmcry_gcry_t*) pT;
int i, r;
unsigned keylen;
unsigned keylen = 0;
uchar *key = NULL;
uchar *keyfile = NULL;
uchar *keyprogram = NULL;
@ -198,14 +198,23 @@ SetCnfParam(void *pT, struct nvlst *lst, int paramType)
}
cnfparamvalsDestruct(pvals, pblk);
if(key != NULL) {
memset(key, 0, strlen((char*)key));
free(key);
}
free(keyfile);
free(algo);
free(mode);
finalize_it:
if (key != NULL)
free(key);
if (keyfile != NULL)
free(keyfile);
if (algo != NULL)
free(algo);
if (keyprogram != NULL)
free(keyprogram);
if (mode != NULL)
free(mode);
RETiRet;
}

View File

@ -1,18 +1,18 @@
/* lookup.c
* Support for lookup tables in RainerScript.
*
* Copyright 2013 Adiscon GmbH.
* Copyright 2013-2016 Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
* -or-
* see COPYING.ASL20 in the source distribution
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -38,6 +38,8 @@
#include "dirty.h"
#include "unicode-helper.h"
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
/* definitions for objects we access */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)

View File

@ -276,8 +276,9 @@ static rsRetVal endTransaction(wrkrInstanceData_t __attribute__((unused)) *pWrkr
/* doAction()
*/
#define BEGINdoAction \
static rsRetVal doAction(uchar __attribute__((unused)) **ppString, wrkrInstanceData_t __attribute__((unused)) *pWrkrData)\
static rsRetVal doAction(void * pMsgData, wrkrInstanceData_t __attribute__((unused)) *pWrkrData)\
{\
uchar **ppString = (uchar **) pMsgData; \
DEFiRet;
#define CODESTARTdoAction \
@ -287,6 +288,14 @@ static rsRetVal doAction(uchar __attribute__((unused)) **ppString, wrkrInstanceD
RETiRet;\
}
/* below is a variant of doAction where the passed-in data is not the common
* case of string.
*/
#define BEGINdoAction_NoStrings \
static rsRetVal doAction(void * pMsgData, wrkrInstanceData_t __attribute__((unused)) *pWrkrData)\
{\
DEFiRet;
/* dbgPrintInstInfo()
* Extra comments:

View File

@ -11,7 +11,7 @@
*
* File begun on 2007-07-22 by RGerhards
*
* Copyright 2007-2015 Rainer Gerhards and Adiscon GmbH.
* Copyright 2007-2016 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@ -247,7 +247,8 @@ static void moduleDestruct(modInfo_t *pThis)
free(pThis->cnfName);
if(pThis->pModHdlr != NULL) {
# ifdef VALGRIND
# warning "dlclose disabled for valgrind"
DBGPRINTF("moduleDestruct: compiled with valgrind, do "
"not unload module\n");
# else
if (pThis->eKeepType == eMOD_NOKEEP) {
dlclose(pThis->pModHdlr);
@ -414,33 +415,43 @@ finalize_it:
* module list. Needed to prevent mem leaks.
*/
static inline void
abortCnfUse(cfgmodules_etry_t *pNew)
abortCnfUse(cfgmodules_etry_t **pNew)
{
free(pNew);
if(pNew != NULL) {
free(*pNew);
*pNew = NULL;
}
}
/* Add a module to the config module list for current loadConf.
* Requires last pointer obtained by readyModForCnf().
* The module pointer is handed over to this function. It is no
* longer available to caller one we are called.
*/
rsRetVal
addModToCnfList(cfgmodules_etry_t *pNew, cfgmodules_etry_t *pLast)
addModToCnfList(cfgmodules_etry_t **pNew, cfgmodules_etry_t *pLast)
{
DEFiRet;
assert(pNew != NULL);
assert(*pNew != NULL);
if(pNew == NULL)
ABORT_FINALIZE(RS_RET_ERR);
if(loadConf == NULL) {
abortCnfUse(pNew);
FINALIZE; /* we are in an early init state */
}
if(pLast == NULL) {
loadConf->modules.root = pNew;
loadConf->modules.root = *pNew;
} else {
/* there already exist entries */
pLast->next = pNew;
pLast->next = *pNew;
}
finalize_it:
if(pNew != NULL)
*pNew = NULL;
RETiRet;
}
@ -1053,8 +1064,8 @@ Load(uchar *pModName, sbool bConfLoad, struct nvlst *lst)
int bHasExtension;
void *pModHdlr, *pModInit;
modInfo_t *pModInfo;
cfgmodules_etry_t *pNew;
cfgmodules_etry_t *pLast;
cfgmodules_etry_t *pNew = NULL;
cfgmodules_etry_t *pLast = NULL;
uchar *pModDirCurr, *pModDirNext;
int iLoadCnt;
struct dlhandle_s *pHandle = NULL;
@ -1110,7 +1121,7 @@ Load(uchar *pModName, sbool bConfLoad, struct nvlst *lst)
/* regular modules need to be added to conf list (for
* builtins, this happend during initial load).
*/
addModToCnfList(pNew, pLast);
addModToCnfList(&pNew, pLast);
}
}
}
@ -1129,7 +1140,7 @@ Load(uchar *pModName, sbool bConfLoad, struct nvlst *lst)
free(pPathBuf);
/* we always alloc enough memory for everything we potentiall need to add */
lenPathBuf = PATHBUF_OVERHEAD;
CHKmalloc(pPathBuf = malloc(sizeof(uchar)*lenPathBuf));
CHKmalloc(pPathBuf = malloc(lenPathBuf));
}
*pPathBuf = '\0'; /* we do not need to append the path - its already in the module name */
iPathLen = 0;
@ -1152,7 +1163,7 @@ Load(uchar *pModName, sbool bConfLoad, struct nvlst *lst)
free(pPathBuf);
/* we always alloc enough memory for everything we potentiall need to add */
lenPathBuf = iPathLen + PATHBUF_OVERHEAD;
CHKmalloc(pPathBuf = malloc(sizeof(uchar)*lenPathBuf));
CHKmalloc(pPathBuf = malloc(lenPathBuf));
}
memcpy((char *) pPathBuf, (char *)pModDirCurr, iPathLen);
@ -1230,18 +1241,19 @@ Load(uchar *pModName, sbool bConfLoad, struct nvlst *lst)
errmsg.LogError(0, localRet,
"module '%s', failed processing config parameters",
pPathBuf);
abortCnfUse(pNew);
ABORT_FINALIZE(localRet);
}
}
pModInfo->bSetModCnfCalled = 1;
}
addModToCnfList(pNew, pLast);
addModToCnfList(&pNew, pLast);
}
finalize_it:
if(pPathBuf != pathBuf) /* used malloc()ed memory? */
free(pPathBuf);
if(iRet != RS_RET_OK)
abortCnfUse(&pNew);
pthread_mutex_unlock(&mutObjGlobalOp);
RETiRet;
}

View File

@ -200,6 +200,6 @@ PROTOTYPEObj(module);
*/
rsRetVal modulesProcessCnf(struct cnfobj *o);
uchar *modGetName(modInfo_t *pThis);
rsRetVal addModToCnfList(cfgmodules_etry_t *pNew, cfgmodules_etry_t *pLast);
rsRetVal addModToCnfList(cfgmodules_etry_t **pNew, cfgmodules_etry_t *pLast);
rsRetVal readyModForCnf(modInfo_t *pThis, cfgmodules_etry_t **ppNew, cfgmodules_etry_t **ppLast);
#endif /* #ifndef MODULES_H_INCLUDED */

View File

@ -7,7 +7,7 @@
* 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-2015 Rainer Gerhards and Adiscon GmbH.
* Copyright 2007-2016 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@ -71,7 +71,7 @@
/* TODO: move the global variable root to the config object - had no time to to it
* right now before vacation -- rgerhards, 2013-07-22
*/
static pthread_rwlock_t glblVars_rwlock;
static pthread_mutex_t glblVars_lock;
struct json_object *global_var_root = NULL;
/* static data */
@ -405,6 +405,7 @@ static rsRetVal jsonPathFindParent(struct json_object *jroot, uchar *name, uchar
static uchar * jsonPathGetLeaf(uchar *name, int lenName);
static struct json_object *jsonDeepCopy(struct json_object *src);
static json_bool jsonVarExtract(struct json_object* root, const char *key, struct json_object **value);
void getRawMsgAfterPRI(msg_t * const pM, uchar **pBuf, int *piLen);
/* the locking and unlocking implementations: */
@ -549,6 +550,8 @@ propNameToID(uchar *pName, propid_t *pPropID)
*pPropID = PROP_SYSLOGTAG;
} else if(!strcmp((char*) pName, "rawmsg")) {
*pPropID = PROP_RAWMSG;
} else if(!strcmp((char*) pName, "rawmsg-after-pri")) {
*pPropID = PROP_RAWMSG_AFTER_PRI;
} else if(!strcmp((char*) pName, "inputname")) {
*pPropID = PROP_INPUTNAME;
} else if(!strcmp((char*) pName, "fromhost")) {
@ -608,6 +611,22 @@ propNameToID(uchar *pName, propid_t *pPropID)
*pPropID = PROP_SYS_QHOUR;
} else if(!strcmp((char*) pName, "$minute")) {
*pPropID = PROP_SYS_MINUTE;
} else if(!strcmp((char*) pName, "$now-utc")) {
*pPropID = PROP_SYS_NOW;
} else if(!strcmp((char*) pName, "$year-utc")) {
*pPropID = PROP_SYS_YEAR_UTC;
} else if(!strcmp((char*) pName, "$month-utc")) {
*pPropID = PROP_SYS_MONTH_UTC;
} else if(!strcmp((char*) pName, "$day-utc")) {
*pPropID = PROP_SYS_DAY_UTC;
} else if(!strcmp((char*) pName, "$hour-utc")) {
*pPropID = PROP_SYS_HOUR_UTC;
} else if(!strcmp((char*) pName, "$hhour-utc")) {
*pPropID = PROP_SYS_HHOUR_UTC;
} else if(!strcmp((char*) pName, "$qhour-utc")) {
*pPropID = PROP_SYS_QHOUR_UTC;
} else if(!strcmp((char*) pName, "$minute-utc")) {
*pPropID = PROP_SYS_MINUTE_UTC;
} else if(!strcmp((char*) pName, "$myhostname")) {
*pPropID = PROP_SYS_MYHOSTNAME;
} else if(!strcmp((char*) pName, "$!all-json")) {
@ -702,6 +721,22 @@ uchar *propIDToName(propid_t propID)
return UCHAR_CONSTANT("$QHOUR");
case PROP_SYS_MINUTE:
return UCHAR_CONSTANT("$MINUTE");
case PROP_SYS_NOW_UTC:
return UCHAR_CONSTANT("$NOW_UTC");
case PROP_SYS_YEAR_UTC:
return UCHAR_CONSTANT("$YEAR_UTC");
case PROP_SYS_MONTH_UTC:
return UCHAR_CONSTANT("$MONTH_UTC");
case PROP_SYS_DAY_UTC:
return UCHAR_CONSTANT("$DAY_UTC");
case PROP_SYS_HOUR_UTC:
return UCHAR_CONSTANT("$HOUR_UTC");
case PROP_SYS_HHOUR_UTC:
return UCHAR_CONSTANT("$HHOUR_UTC");
case PROP_SYS_QHOUR_UTC:
return UCHAR_CONSTANT("$QHOUR_UTC");
case PROP_SYS_MINUTE_UTC:
return UCHAR_CONSTANT("$MINUTE_UTC");
case PROP_SYS_MYHOSTNAME:
return UCHAR_CONSTANT("$MYHOSTNAME");
case PROP_CEE:
@ -847,7 +882,7 @@ rsRetVal msgConstruct(msg_t **ppThis)
* especially as I think there is no codepath currently where it would not be
* required (after I have cleaned up the pathes ;)). -- rgerhards, 2008-10-02
*/
datetime.getCurrTime(&((*ppThis)->tRcvdAt), &((*ppThis)->ttGenTime));
datetime.getCurrTime(&((*ppThis)->tRcvdAt), &((*ppThis)->ttGenTime), TIME_IN_LOCALTIME);
memcpy(&(*ppThis)->tTIMESTAMP, &(*ppThis)->tRcvdAt, sizeof(struct syslogTime));
finalize_it:
@ -1566,6 +1601,38 @@ getRawMsg(msg_t * const pM, uchar **pBuf, int *piLen)
}
}
void
getRawMsgAfterPRI(msg_t * const pM, uchar **pBuf, int *piLen)
{
if(pM == NULL) {
*pBuf= UCHAR_CONSTANT("");
*piLen = 0;
} else {
if(pM->pszRawMsg == NULL) {
*pBuf= UCHAR_CONSTANT("");
*piLen = 0;
} else {
/* unfortunately, pM->offAfterPRI seems NOT to be
* correct/consistent in all cases. imuxsock and imudp
* seem to have other values than imptcp. Testbench
* covers some of that. As a work-around, we caluculate
* the value ourselfes here. -- rgerhards, 2015-10-09
*/
size_t offAfterPRI = 0;
if(pM->pszRawMsg[0] == '<') { /* do we have a PRI? */
if(pM->pszRawMsg[2] == '>')
offAfterPRI = 3;
else if(pM->pszRawMsg[3] == '>')
offAfterPRI = 4;
else if(pM->pszRawMsg[4] == '>')
offAfterPRI = 5;
}
*pBuf = pM->pszRawMsg + offAfterPRI;
*piLen = pM->iLenRawMsg - offAfterPRI;
}
}
}
/* note: setMSGLen() is only for friends who really know what they
* do. Setting an invalid length can be desasterous!
@ -2685,15 +2752,19 @@ void MsgSetRawMsgWOSize(msg_t * const pMsg, char* pszRawMsg)
* The variable pRes must point to a user-supplied buffer of
* at least 20 characters.
*/
static void
textpri(const msg_t *const __restrict__ pMsg, uchar *const __restrict__ pRes)
static uchar *
textpri(const msg_t *const __restrict__ pMsg)
{
assert(pRes != NULL);
memcpy(pRes, syslog_fac_names[pMsg->iFacility], len_syslog_fac_names[pMsg->iFacility]);
pRes[len_syslog_fac_names[pMsg->iFacility]] = '.';
memcpy(pRes+len_syslog_fac_names[pMsg->iFacility]+1,
syslog_severity_names[pMsg->iSeverity],
len_syslog_severity_names[pMsg->iSeverity]+1 /* for \0! */);
int lenfac = len_syslog_fac_names[pMsg->iFacility];
int lensev = len_syslog_severity_names[pMsg->iSeverity];
int totlen = lenfac + 1 + lensev + 1;
char *pRes = MALLOC(totlen);
if(pRes != NULL) {
memcpy(pRes, syslog_fac_names[pMsg->iFacility], lenfac);
pRes[lenfac] = '.';
memcpy(pRes+lenfac+1, syslog_severity_names[pMsg->iSeverity], lensev+1 /* for \0! */);
}
return (uchar*)pRes;
}
@ -2706,22 +2777,22 @@ textpri(const msg_t *const __restrict__ pMsg, uchar *const __restrict__ pRes)
*/
typedef enum ENOWType { NOW_NOW, NOW_YEAR, NOW_MONTH, NOW_DAY, NOW_HOUR, NOW_HHOUR, NOW_QHOUR, NOW_MINUTE } eNOWType;
#define tmpBUFSIZE 16 /* size of formatting buffer */
static uchar *getNOW(eNOWType eNow, struct syslogTime *t)
static uchar *getNOW(eNOWType eNow, struct syslogTime *t, const int inUTC)
{
uchar *pBuf;
struct syslogTime tt;
if((pBuf = (uchar*) MALLOC(sizeof(uchar) * tmpBUFSIZE)) == NULL) {
if((pBuf = (uchar*) MALLOC(tmpBUFSIZE)) == NULL) {
return NULL;
}
if(t == NULL) { /* can happen if called via script engine */
datetime.getCurrTime(&tt, NULL);
datetime.getCurrTime(&tt, NULL, inUTC);
t = &tt;
}
if(t->year == 0) { /* not yet set! */
datetime.getCurrTime(t, NULL);
if(t->year == 0 || t->inUTC != inUTC) { /* not yet set! */
datetime.getCurrTime(t, NULL, inUTC);
}
switch(eNow) {
@ -2778,17 +2849,20 @@ getJSONPropVal(msg_t * const pMsg, msgPropDescr_t *pProp, uchar **pRes, rs_size_
if(pProp->id == PROP_CEE) {
jroot = pMsg->json;
MsgLock(pMsg);
} else if(pProp->id == PROP_LOCAL_VAR) {
jroot = pMsg->localvars;
MsgLock(pMsg);
} else if(pProp->id == PROP_GLOBAL_VAR) {
pthread_rwlock_rdlock(&glblVars_rwlock);
jroot = global_var_root;
pthread_mutex_lock(&glblVars_lock);
} else {
DBGPRINTF("msgGetJSONPropVal; invalid property id %d\n",
pProp->id);
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
if(jroot == NULL) goto finalize_it;
if(jroot == NULL) FINALIZE;
if(!strcmp((char*)pProp->name, "!")) {
field = jroot;
@ -2806,7 +2880,9 @@ getJSONPropVal(msg_t * const pMsg, msgPropDescr_t *pProp, uchar **pRes, rs_size_
finalize_it:
if(pProp->id == PROP_GLOBAL_VAR)
pthread_rwlock_unlock(&glblVars_rwlock);
pthread_mutex_unlock(&glblVars_lock);
else
MsgUnlock(pMsg);
if(*pRes == NULL) {
/* could not find any value, so set it to empty */
*pRes = (unsigned char*)"";
@ -2816,6 +2892,75 @@ finalize_it:
}
/* Get a JSON-based-variable as native json object, except
* when it is string type, in which case a string is returned.
* This is an optimization to not use JSON when not strictly
* necessary. This in turn is helpful, as calling json-c is
* *very* expensive due to our need for locking and deep
* copies.
* The caller needs to check pjson and pcstr: one of them
* is non-NULL and contains the return value. Note that
* the caller is responsible for freeing the string pointer
* it if is being returned.
*/
rsRetVal
msgGetJSONPropJSONorString(msg_t * const pMsg, msgPropDescr_t *pProp, struct json_object **pjson,
uchar **pcstr)
{
struct json_object *jroot;
uchar *leaf;
struct json_object *parent;
DEFiRet;
*pjson = NULL, *pcstr = NULL;
if(pProp->id == PROP_CEE) {
jroot = pMsg->json;
MsgLock(pMsg);
} else if(pProp->id == PROP_LOCAL_VAR) {
jroot = pMsg->localvars;
MsgLock(pMsg);
} else if(pProp->id == PROP_GLOBAL_VAR) {
jroot = global_var_root;
pthread_mutex_lock(&glblVars_lock);
} else {
DBGPRINTF("msgGetJSONPropJSON; invalid property id %d\n",
pProp->id);
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
if(!strcmp((char*)pProp->name, "!")) {
*pjson = jroot;
FINALIZE;
}
leaf = jsonPathGetLeaf(pProp->name, pProp->nameLen);
CHKiRet(jsonPathFindParent(jroot, pProp->name, leaf, &parent, 1));
if(jsonVarExtract(parent, (char*)leaf, pjson) == FALSE) {
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
if(*pjson == NULL) {
/* we had a NULL json object and represent this as empty string */
*pcstr = (uchar*) strdup("");
} else {
if(json_object_get_type(*pjson) == json_type_string) {
*pcstr = (uchar*) strdup(json_object_get_string(*pjson));
*pjson = NULL;
}
}
finalize_it:
/* we need a deep copy, as another thread may modify the object */
if(*pjson != NULL)
*pjson = jsonDeepCopy(*pjson);
if(pProp->id == PROP_GLOBAL_VAR)
pthread_mutex_unlock(&glblVars_lock);
else
MsgUnlock(pMsg);
RETiRet;
}
/* Get a JSON-based-variable as native json object */
rsRetVal
msgGetJSONPropJSON(msg_t * const pMsg, msgPropDescr_t *pProp, struct json_object **pjson)
@ -2829,21 +2974,18 @@ msgGetJSONPropJSON(msg_t * const pMsg, msgPropDescr_t *pProp, struct json_object
if(pProp->id == PROP_CEE) {
jroot = pMsg->json;
MsgLock(pMsg);
} else if(pProp->id == PROP_LOCAL_VAR) {
jroot = pMsg->localvars;
MsgLock(pMsg);
} else if(pProp->id == PROP_GLOBAL_VAR) {
pthread_rwlock_rdlock(&glblVars_rwlock);
jroot = global_var_root;
pthread_mutex_lock(&glblVars_lock);
} else {
DBGPRINTF("msgGetJSONPropJSON; invalid property id %d\n",
pProp->id);
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
if(jroot == NULL) {
DBGPRINTF("msgGetJSONPropJSON; jroot empty for property %s\n",
pProp->name);
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
if(!strcmp((char*)pProp->name, "!")) {
*pjson = jroot;
@ -2856,14 +2998,13 @@ msgGetJSONPropJSON(msg_t * const pMsg, msgPropDescr_t *pProp, struct json_object
}
finalize_it:
if(pProp->id == PROP_GLOBAL_VAR) {
if (*pjson != NULL)
*pjson = jsonDeepCopy(*pjson);
pthread_rwlock_unlock(&glblVars_rwlock);
} else {
if (*pjson != NULL)
json_object_get(*pjson);
}
/* we need a deep copy, as another thread may modify the object */
if(*pjson != NULL)
*pjson = jsonDeepCopy(*pjson);
if(pProp->id == PROP_GLOBAL_VAR)
pthread_mutex_unlock(&glblVars_lock);
else
MsgUnlock(pMsg);
RETiRet;
}
@ -3134,6 +3275,9 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
case PROP_RAWMSG:
getRawMsg(pMsg, &pRes, &bufLen);
break;
case PROP_RAWMSG_AFTER_PRI:
getRawMsgAfterPRI(pMsg, &pRes, &bufLen);
break;
case PROP_INPUTNAME:
getInputName(pMsg, &pRes, &bufLen);
break;
@ -3147,10 +3291,10 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
pRes = (uchar*)getPRI(pMsg);
break;
case PROP_PRI_TEXT:
if((pRes = MALLOC(20 * sizeof(uchar))) == NULL)
pRes = textpri(pMsg);
if(pRes == NULL)
RET_OUT_OF_MEMORY;
*pbMustBeFreed = 1;
textpri(pMsg, pRes);
break;
case PROP_IUT:
pRes = UCHAR_CONSTANT("1"); /* always 1 for syslog messages (a MonitorWare thing;)) */
@ -3206,7 +3350,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
pRes = (uchar*)getParseSuccess(pMsg);
break;
case PROP_SYS_NOW:
if((pRes = getNOW(NOW_NOW, ttNow)) == NULL) {
if((pRes = getNOW(NOW_NOW, ttNow, TIME_IN_LOCALTIME)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
@ -3214,7 +3358,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
}
break;
case PROP_SYS_YEAR:
if((pRes = getNOW(NOW_YEAR, ttNow)) == NULL) {
if((pRes = getNOW(NOW_YEAR, ttNow, TIME_IN_LOCALTIME)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
@ -3222,7 +3366,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
}
break;
case PROP_SYS_MONTH:
if((pRes = getNOW(NOW_MONTH, ttNow)) == NULL) {
if((pRes = getNOW(NOW_MONTH, ttNow, TIME_IN_LOCALTIME)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
@ -3230,7 +3374,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
}
break;
case PROP_SYS_DAY:
if((pRes = getNOW(NOW_DAY, ttNow)) == NULL) {
if((pRes = getNOW(NOW_DAY, ttNow, TIME_IN_LOCALTIME)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
@ -3238,7 +3382,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
}
break;
case PROP_SYS_HOUR:
if((pRes = getNOW(NOW_HOUR, ttNow)) == NULL) {
if((pRes = getNOW(NOW_HOUR, ttNow, TIME_IN_LOCALTIME)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
@ -3246,7 +3390,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
}
break;
case PROP_SYS_HHOUR:
if((pRes = getNOW(NOW_HHOUR, ttNow)) == NULL) {
if((pRes = getNOW(NOW_HHOUR, ttNow, TIME_IN_LOCALTIME)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
@ -3254,7 +3398,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
}
break;
case PROP_SYS_QHOUR:
if((pRes = getNOW(NOW_QHOUR, ttNow)) == NULL) {
if((pRes = getNOW(NOW_QHOUR, ttNow, TIME_IN_LOCALTIME)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
@ -3262,7 +3406,71 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
}
break;
case PROP_SYS_MINUTE:
if((pRes = getNOW(NOW_MINUTE, ttNow)) == NULL) {
if((pRes = getNOW(NOW_MINUTE, ttNow, TIME_IN_LOCALTIME)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
bufLen = 2;
}
break;
case PROP_SYS_NOW_UTC:
if((pRes = getNOW(NOW_NOW, ttNow, TIME_IN_UTC)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
bufLen = 10;
}
break;
case PROP_SYS_YEAR_UTC:
if((pRes = getNOW(NOW_YEAR, ttNow, TIME_IN_UTC)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
bufLen = 4;
}
break;
case PROP_SYS_MONTH_UTC:
if((pRes = getNOW(NOW_MONTH, ttNow, TIME_IN_UTC)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
bufLen = 2;
}
break;
case PROP_SYS_DAY_UTC:
if((pRes = getNOW(NOW_DAY, ttNow, TIME_IN_UTC)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
bufLen = 2;
}
break;
case PROP_SYS_HOUR_UTC:
if((pRes = getNOW(NOW_HOUR, ttNow, TIME_IN_UTC)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
bufLen = 2;
}
break;
case PROP_SYS_HHOUR_UTC:
if((pRes = getNOW(NOW_HHOUR, ttNow, TIME_IN_UTC)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
bufLen = 2;
}
break;
case PROP_SYS_QHOUR_UTC:
if((pRes = getNOW(NOW_QHOUR, ttNow, TIME_IN_UTC)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
bufLen = 2;
}
break;
case PROP_SYS_MINUTE_UTC:
if((pRes = getNOW(NOW_MINUTE, ttNow, TIME_IN_UTC)) == NULL) {
RET_OUT_OF_MEMORY;
} else {
*pbMustBeFreed = 1;
@ -3279,13 +3487,27 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
bufLen = 2;
*pbMustBeFreed = 0;
} else {
const char *jstr;
MsgLock(pMsg);
#ifdef HAVE_JSON_OBJECT_TO_JSON_STRING_EXT
int jflag = 0;
if(pProp->id == PROP_CEE_ALL_JSON) {
pRes = (uchar*)strdup(RS_json_object_to_json_string_ext(pMsg->json, JSON_C_TO_STRING_SPACED));
jflag = JSON_C_TO_STRING_SPACED;
} else if(pProp->id == PROP_CEE_ALL_JSON_PLAIN) {
pRes = (uchar*)strdup(RS_json_object_to_json_string_ext(pMsg->json, JSON_C_TO_STRING_PLAIN));
jflag = JSON_C_TO_STRING_PLAIN;
}
jstr = json_object_to_json_string_ext(pMsg->json, jflag);
#else
jstr = json_object_to_json_string(pMsg->json);
#endif
MsgUnlock(pMsg);
if(jstr == NULL) {
RET_OUT_OF_MEMORY;
}
pRes = (uchar*)strdup(jstr);
if(pRes == NULL) {
RET_OUT_OF_MEMORY;
}
*pbMustBeFreed = 1;
}
break;
@ -3311,7 +3533,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
{
struct timespec tp;
if((pRes = (uchar*) MALLOC(sizeof(uchar) * 32)) == NULL) {
if((pRes = (uchar*) MALLOC(32)) == NULL) {
RET_OUT_OF_MEMORY;
}
@ -3323,7 +3545,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
*pbMustBeFreed = 1;
snprintf((char*) pRes, sizeof(uchar) * 32, "%ld", tp.tv_sec);
snprintf((char*) pRes, 32, "%ld", tp.tv_sec);
}
# else
@ -3331,7 +3553,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
{
struct sysinfo s_info;
if((pRes = (uchar*) MALLOC(sizeof(uchar) * 32)) == NULL) {
if((pRes = (uchar*) MALLOC(32)) == NULL) {
RET_OUT_OF_MEMORY;
}
@ -3343,7 +3565,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
*pbMustBeFreed = 1;
snprintf((char*) pRes, sizeof(uchar) * 32, "%ld", s_info.uptime);
snprintf((char*) pRes, 32, "%ld", s_info.uptime);
}
# endif
break;
@ -3410,7 +3632,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
/* we got our end pointer, now do the copy */
/* TODO: code copied from below, this is a candidate for a separate function */
iLen = pFldEnd - pFld + 1; /* the +1 is for an actual char, NOT \0! */
pBufStart = pBuf = MALLOC((iLen + 1) * sizeof(uchar));
pBufStart = pBuf = MALLOC(iLen + 1);
if(pBuf == NULL) {
if(*pbMustBeFreed == 1)
free(pRes);
@ -3522,7 +3744,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
iLenBuf = pmatch[pTpe->data.field.iSubMatchToUse].rm_eo
- pmatch[pTpe->data.field.iSubMatchToUse].rm_so;
pB = MALLOC((iLenBuf + 1) * sizeof(uchar));
pB = MALLOC(iLenBuf + 1);
if (pB == NULL) {
if (*pbMustBeFreed == 1)
@ -3583,12 +3805,12 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
*/
; /*DO NOTHING*/
} else {
if(iTo > bufLen) /* iTo is very large, if no to-position is set in the template! */
if(iTo >= bufLen) /* iTo is very large, if no to-position is set in the template! */
if (pTpe->data.field.options.bFixedWidth == 0)
iTo = bufLen;
iTo = bufLen - 1;
iLen = iTo - iFrom + 1; /* the +1 is for an actual char, NOT \0! */
pBufStart = pBuf = MALLOC((iLen + 1) * sizeof(uchar));
pBufStart = pBuf = MALLOC(iLen + 1);
if(pBuf == NULL) {
if(*pbMustBeFreed == 1)
free(pRes);
@ -3646,7 +3868,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
uchar *pBStart;
uchar *pB;
uchar *pSrc;
pBStart = pB = MALLOC((bufLen + 1) * sizeof(uchar));
pBStart = pB = MALLOC(bufLen + 1);
if(pB == NULL) {
if(*pbMustBeFreed == 1)
free(pRes);
@ -3767,7 +3989,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
int i;
iLenBuf += iNumCC * 4;
pBStart = pB = MALLOC((iLenBuf + 1) * sizeof(uchar));
pBStart = pB = MALLOC(iLenBuf + 1);
if(pB == NULL) {
if(*pbMustBeFreed == 1)
free(pRes);
@ -3902,7 +4124,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
/* check if we need to obtain a private copy */
if(*pbMustBeFreed == 0) {
/* ok, original copy, need a private one */
pB = MALLOC((iLn + 1) * sizeof(uchar));
pB = MALLOC(iLn + 1);
if(pB == NULL) {
RET_OUT_OF_MEMORY;
}
@ -3930,7 +4152,7 @@ uchar *MsgGetProp(msg_t *__restrict__ const pMsg, struct templateEntry *__restri
bufLen = ustrlen(pRes);
iBufLen = bufLen;
/* the malloc may be optimized, we currently use the worst case... */
pBStart = pDst = MALLOC((2 * iBufLen + 3) * sizeof(uchar));
pBStart = pDst = MALLOC(2 * iBufLen + 3);
if(pDst == NULL) {
if(*pbMustBeFreed == 1)
free(pRes);
@ -3978,9 +4200,6 @@ msgSetPropViaJSON(msg_t *__restrict__ const pMsg, const char *name, struct json_
prop_t *propRcvFromIP = NULL;
DEFiRet;
// TODO: think if we need to lock the message mutex. For some updates
// we probably need to!
/* note: json_object_get_string() manages the memory of the returned
* string. So we MUST NOT free it!
*/
@ -4201,6 +4420,9 @@ jsonPathFindParent(struct json_object *jroot, uchar *name, uchar *leaf, struct j
while(name < leaf-1) {
jsonPathFindNext(*parent, namestart, &name, leaf, parent, bCreate);
}
if(*parent == NULL)
ABORT_FINALIZE(RS_RET_NOT_FOUND);
finalize_it:
RETiRet;
}
@ -4261,19 +4483,20 @@ msgAddJSON(msg_t * const pM, uchar *name, struct json_object *json, int force_re
uchar *leaf;
DEFiRet;
MsgLock(pM);
if(name[0] == '!') {
pjroot = &pM->json;
MsgLock(pM);
} else if(name[0] == '.') {
pjroot = &pM->localvars;
MsgLock(pM);
} else if (name[0] == '/') { /* globl var */
pthread_rwlock_wrlock(&glblVars_rwlock);
pjroot = &global_var_root;
if (sharedReference) {
given = json;
json = jsonDeepCopy(json);
json_object_put(given);
}
pthread_mutex_lock(&glblVars_lock);
} else {
DBGPRINTF("Passed name %s is unknown kind of variable (It is not CEE, Local or Global variable).", name);
ABORT_FINALIZE(RS_RET_INVLD_SETOP);
@ -4329,8 +4552,9 @@ msgAddJSON(msg_t * const pM, uchar *name, struct json_object *json, int force_re
finalize_it:
if(name[0] == '/')
pthread_rwlock_unlock(&glblVars_rwlock);
MsgUnlock(pM);
pthread_mutex_unlock(&glblVars_lock);
else
MsgUnlock(pM);
RETiRet;
}
@ -4343,20 +4567,22 @@ msgDelJSON(msg_t * const pM, uchar *name)
uchar *leaf;
DEFiRet;
MsgLock(pM);
if(name[0] == '!') {
jroot = &pM->json;
MsgLock(pM);
} else if(name[0] == '.') {
jroot = &pM->localvars;
MsgLock(pM);
} else if (name[0] == '/') { /* globl var */
pthread_rwlock_wrlock(&glblVars_rwlock);
jroot = &global_var_root;
pthread_mutex_lock(&glblVars_lock);
} else {
DBGPRINTF("Passed name %s is unknown kind of variable (It is not CEE, Local or Global variable).", name);
DBGPRINTF("Passed name %s is unknown kind of variable (It is not CEE, "
"Local or Global variable).", name);
ABORT_FINALIZE(RS_RET_INVLD_SETOP);
}
if(jroot == NULL) {
if(*jroot == NULL) {
DBGPRINTF("msgDelJSONVar; jroot empty in unset for property %s\n",
name);
FINALIZE;
@ -4370,10 +4596,6 @@ msgDelJSON(msg_t * const pM, uchar *name)
json_object_put(*jroot);
*jroot = NULL;
} else {
if(*jroot == NULL) {
/* now we need a root obj */
*jroot = json_object_new_object();
}
leaf = jsonPathGetLeaf(name, ustrlen(name));
CHKiRet(jsonPathFindParent(*jroot, name, leaf, &parent, 1));
if(jsonVarExtract(parent, (char*)leaf, &leafnode) == FALSE)
@ -4391,8 +4613,9 @@ msgDelJSON(msg_t * const pM, uchar *name)
finalize_it:
if(name[0] == '/')
pthread_rwlock_unlock(&glblVars_rwlock);
MsgUnlock(pM);
pthread_mutex_unlock(&glblVars_lock);
else
MsgUnlock(pM);
RETiRet;
}
@ -4577,7 +4800,7 @@ rsRetVal msgQueryInterface(void) { return RS_RET_NOT_IMPLEMENTED; }
* rgerhards, 2008-01-04
*/
BEGINObjClassInit(msg, 1, OBJ_IS_CORE_MODULE)
pthread_rwlock_init(&glblVars_rwlock, NULL);
pthread_mutex_init(&glblVars_lock, NULL);
/* request objects we use */
CHKiRet(objUse(datetime, CORE_COMPONENT));

View File

@ -214,6 +214,7 @@ uchar *getRcvFrom(msg_t *pM);
rsRetVal propNameToID(uchar *pName, propid_t *pPropID);
uchar *propIDToName(propid_t propID);
rsRetVal msgGetJSONPropJSON(msg_t *pMsg, msgPropDescr_t *pProp, struct json_object **pjson);
rsRetVal msgGetJSONPropJSONorString(msg_t * const pMsg, msgPropDescr_t *pProp, struct json_object **pjson, uchar **pcstr);
rsRetVal getJSONPropVal(msg_t *pMsg, msgPropDescr_t *pProp, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed);
rsRetVal msgSetJSONFromVar(msg_t *pMsg, uchar *varname, struct var *var, int force_reset);
rsRetVal msgDelJSON(msg_t *pMsg, uchar *varname);

View File

@ -1465,6 +1465,9 @@ finalize_it:
* However, it caches entries in order to avoid too-frequent requery.
* rgerhards, 2012-03-06
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align" /* TODO: how can we fix these warnings? */
/* Problem with the warnings: they seem to stem back from the way the API is structured */
static rsRetVal
getIFIPAddr(uchar *szif, int family, uchar *pszbuf, int lenBuf)
{
@ -1503,6 +1506,7 @@ finalize_it:
RETiRet;
}
#pragma GCC diagnostic pop
/* queryInterface function

View File

@ -643,6 +643,17 @@ gtlsInitSession(nsd_gtls_t *pThis)
pThis->sess = session;
# if HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION
/* store a pointer to ourselfs (needed by callback) */
gnutls_session_set_ptr(pThis->sess, (void*)pThis);
iRet = gtlsLoadOurCertKey(pThis); /* first load .pem files */
if(iRet == RS_RET_OK) {
gnutls_certificate_set_retrieve_function(xcred, gtlsClientCertCallback);
} else if(iRet != RS_RET_CERTLESS) {
FINALIZE; /* we have an error case! */
}
# endif
finalize_it:
RETiRet;
}
@ -1565,14 +1576,6 @@ Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
}
if(pThis->lenRcvBuf == 0) { /* EOS */
*pLenBuf = 0;
/* in this case, we also need to free the receive buffer, if we
* allocated one. -- rgerhards, 2008-12-03
*/
if(pThis->pszRcvBuf != NULL) {
free(pThis->pszRcvBuf);
pThis->pszRcvBuf = NULL;
}
ABORT_FINALIZE(RS_RET_CLOSED);
}
@ -1589,6 +1592,14 @@ Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
*pLenBuf = iBytesCopy;
finalize_it:
if (iRet != RS_RET_OK) {
/* in this case, we also need to free the receive buffer, if we
* allocated one. -- rgerhards, 2008-12-03 -- moved here by alorbach, 2015-12-01
*/
*pLenBuf = 0;
free(pThis->pszRcvBuf);
pThis->pszRcvBuf = NULL;
}
dbgprintf("gtlsRcv return. nsd %p, iRet %d, lenRcvBuf %d, ptrRcvBuf %d\n", pThis, iRet, pThis->lenRcvBuf, pThis->ptrRcvBuf);
RETiRet;
}
@ -1651,6 +1662,8 @@ EnableKeepAlive(nsd_t *pNsd)
* open a plain tcp socket and then, if in TLS mode, do a handshake on it.
* rgerhards, 2008-03-19
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" /* TODO: FIX Warnings! */
static rsRetVal
Connect(nsd_t *pNsd, int family, uchar *port, uchar *host)
{
@ -1743,6 +1756,7 @@ finalize_it:
RETiRet;
}
#pragma GCC diagnostic pop
/* queryInterface function */

View File

@ -2,7 +2,7 @@
*
* An implementation of the nsd epoll() interface for plain tcp sockets.
*
* Copyright 2009 Rainer Gerhards and Adiscon GmbH.
* Copyright 2009-2016 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@ -252,12 +252,11 @@ Wait(nsdpoll_t *pNsdpoll, int timeout, int *numEntries, nsd_epworkset_t workset[
}
/* we got valid events, so tell the caller... */
dbgprintf("epoll returned %d entries\n", nfds);
DBGPRINTF("epoll returned %d entries\n", nfds);
for(i = 0 ; i < nfds ; ++i) {
pOurEvt = (nsdpoll_epollevt_lst_t*) event[i].data.ptr;
workset[i].id = pOurEvt->id;
workset[i].pUsr = pOurEvt->pUsr;
dbgprintf("epoll push ppusr[%d]: %p\n", i, pOurEvt->pUsr);
}
*numEntries = nfds;

View File

@ -2,7 +2,7 @@
*
* An implementation of the nsd select() interface for GnuTLS.
*
* Copyright (C) 2008-2012 Adiscon GmbH.
* Copyright (C) 2008-2016 Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@ -175,7 +175,6 @@ doRetry(nsd_gtls_t *pNsd)
finalize_it:
if(iRet != RS_RET_OK && iRet != RS_RET_CLOSED && iRet != RS_RET_RETRY)
pNsd->bAbortConn = 1; /* request abort */
dbgprintf("XXXXXX: doRetry: iRet %d, pNsd->bAbortConn %d\n", iRet, pNsd->bAbortConn);
RETiRet;
}

View File

@ -192,7 +192,7 @@ Wait(nssel_t *pThis, int *piNumReady)
* rgerhards, 2008-04-23
*/
static rsRetVal
IsReady(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp, int *pbIsReady, int *piNumReady)
IsReady(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp, int *pbIsReady, int __attribute__((unused)) *piNumReady)
{
DEFiRet;
ISOBJ_TYPE_assert(pThis, nssel);

View File

@ -1106,7 +1106,7 @@ GetName(obj_t *pThis)
ISOBJ_assert(pThis);
if(pThis->pszName == NULL) {
snprintf((char*)szName, sizeof(szName)/sizeof(uchar), "%s %p", objGetClassName(pThis), pThis);
snprintf((char*)szName, sizeof(szName), "%s %p", objGetClassName(pThis), pThis);
SetName(pThis, szName);
/* looks strange, but we NEED to re-check because if there was an
* error in objSetName(), the pointer may still be NULL
@ -1158,7 +1158,7 @@ finalize_it:
/* DEV DEBUG ONLY dbgprintf("caller requested object '%s', found at index %d\n", (*ppInfo)->pszID, i);*/
/*EMPTY BY INTENSION*/;
} else {
dbgprintf("caller requested object '%s', not found (iRet %d)\n", rsCStrGetSzStr(pstrOID), iRet);
dbgprintf("caller requested object '%s', not found (iRet %d)\n", rsCStrGetSzStrNoNULL(pstrOID), iRet);
}
RETiRet;

View File

@ -4,7 +4,7 @@
*
* Module begun 2008-10-09 by Rainer Gerhards (based on previous code from syslogd.c)
*
* Copyright 2008-2014 Rainer Gerhards and Adiscon GmbH.
* Copyright 2008-2015 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@ -280,7 +280,7 @@ rsRetVal
parserConstructViaModAndName(modInfo_t *__restrict__ pMod, uchar *const __restrict__ pName, void *pInst)
{
rsRetVal localRet;
parser_t *pParser;
parser_t *pParser = NULL;
DEFiRet;
if(pInst == NULL && pMod->mod.pm.newParserInst != NULL) {
@ -303,6 +303,8 @@ parserConstructViaModAndName(modInfo_t *__restrict__ pMod, uchar *const __restri
pParser->pInst = pInst;
CHKiRet(parserConstructFinalize(pParser));
finalize_it:
if(iRet != RS_RET_OK)
free(pParser);
RETiRet;
}
BEGINobjDestruct(parser) /* be sure to specify the object type also in END and CODESTART macros! */
@ -344,7 +346,7 @@ static inline rsRetVal uncompressMessage(msg_t *pMsg)
*/
int ret;
iLenDefBuf = glbl.GetMaxLine();
CHKmalloc(deflateBuf = MALLOC(sizeof(uchar) * (iLenDefBuf + 1)));
CHKmalloc(deflateBuf = MALLOC(iLenDefBuf + 1));
ret = uncompress((uchar *) deflateBuf, &iLenDefBuf, (uchar *) pszMsg+1, lenMsg-1);
DBGPRINTF("Compressed message uncompressed with status %d, length: new %ld, old %d.\n",
ret, (long) iLenDefBuf, (int) (lenMsg-1));
@ -474,7 +476,7 @@ SanitizeMsg(msg_t *pMsg)
if(maxDest < sizeof(szSanBuf))
pDst = szSanBuf;
else
CHKmalloc(pDst = MALLOC(sizeof(uchar) * (iMaxLine + 1)));
CHKmalloc(pDst = MALLOC(iMaxLine + 1));
if(iSrc > 0) {
iSrc--; /* go back to where everything is OK */
memcpy(pDst, pszMsg, iSrc); /* fast copy known good */

View File

@ -412,7 +412,7 @@ StartDA(qqueue_t *pThis)
CHKiRet(qqueueConstruct(&pThis->pqDA, QUEUETYPE_DISK , 1, 0, pThis->pConsumer));
/* give it a name */
snprintf((char*) pszDAQName, sizeof(pszDAQName)/sizeof(uchar), "%s[DA]", obj.GetName((obj_t*) pThis));
snprintf((char*) pszDAQName, sizeof(pszDAQName), "%s[DA]", obj.GetName((obj_t*) pThis));
obj.SetName((obj_t*) pThis->pqDA, pszDAQName);
/* as the created queue is the same object class, we take the
@ -2119,7 +2119,7 @@ qqueueStart(qqueue_t *pThis) /* this is the ConstructionFinalizer */
/* special handling */
pThis->iNumWorkerThreads = 1; /* we need exactly one worker */
/* pre-construct file name for .qi file */
pThis->lenQIFNam = snprintf((char*)pszQIFNam, sizeof(pszQIFNam) / sizeof(uchar),
pThis->lenQIFNam = snprintf((char*)pszQIFNam, sizeof(pszQIFNam),
"%s/%s.qi", (char*) pThis->pszSpoolDir, (char*)pThis->pszFilePrefix);
pThis->pszQIFNam = ustrdup(pszQIFNam);
DBGOPRINT((obj_t*) pThis, ".qi file name is '%s', len %d\n", pThis->pszQIFNam,
@ -2627,7 +2627,7 @@ qqueueSetFilePrefix(qqueue_t *pThis, uchar *pszPrefix, size_t iLenPrefix)
if(pszPrefix == NULL) /* just unset the prefix! */
ABORT_FINALIZE(RS_RET_OK);
if((pThis->pszFilePrefix = MALLOC(sizeof(uchar) * iLenPrefix + 1)) == NULL)
if((pThis->pszFilePrefix = MALLOC(iLenPrefix + 1)) == NULL)
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
memcpy(pThis->pszFilePrefix, pszPrefix, iLenPrefix + 1);
pThis->lenFilePrefix = iLenPrefix;

View File

@ -167,6 +167,7 @@ void cnfSetDefaults(rsconf_t *pThis)
BEGINobjConstruct(rsconf) /* be sure to specify the object type also in END macro! */
cnfSetDefaults(pThis);
lookupInitCnf(&pThis->lu_tabs);
CHKiRet(dynstats_initCnf(&pThis->dynstats_buckets));
CHKiRet(llInit(&pThis->rulesets.llRulesets, rulesetDestructForLinkedList,
rulesetKeyDestruct, strcasecmp));
finalize_it:
@ -208,6 +209,7 @@ BEGINobjDestruct(rsconf) /* be sure to specify the object type also in END and C
CODESTARTobjDestruct(rsconf)
freeCnf(pThis);
tplDeleteAll(pThis);
dynstats_destroyAllBuckets();
free(pThis->globals.mainQ.pszMainMsgQFName);
free(pThis->globals.pszConfDAGFile);
lookupDestroyCnf();
@ -427,6 +429,9 @@ void cnfDoObj(struct cnfobj *o)
case CNFOBJ_LOOKUP_TABLE:
lookupTableDefProcessCnf(o);
break;
case CNFOBJ_DYN_STATS:
dynstats_processCnf(o);
break;
case CNFOBJ_PARSER:
parserProcessCnf(o);
break;
@ -514,7 +519,7 @@ static void doDropPrivGid(int iGid)
exit(1);
}
DBGPRINTF("setgid(%d): %d\n", iGid, res);
snprintf((char*)szBuf, sizeof(szBuf)/sizeof(uchar), "rsyslogd's groupid changed to %d", iGid);
snprintf((char*)szBuf, sizeof(szBuf), "rsyslogd's groupid changed to %d", iGid);
logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, szBuf, 0);
}
@ -553,7 +558,7 @@ static void doDropPrivUid(int iUid)
exit(1);
}
DBGPRINTF("setuid(%d): %d\n", iUid, res);
snprintf((char*)szBuf, sizeof(szBuf)/sizeof(uchar), "rsyslogd's userid changed to %d", iUid);
snprintf((char*)szBuf, sizeof(szBuf), "rsyslogd's userid changed to %d", iUid);
logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, szBuf, 0);
}
@ -1004,7 +1009,7 @@ regBuildInModule(rsRetVal (*modInit)(), uchar *name, void *pModHdlr)
DEFiRet;
CHKiRet(module.doModInit(modInit, name, pModHdlr, &pMod));
readyModForCnf(pMod, &pNew, &pLast);
addModToCnfList(pNew, pLast);
addModToCnfList(&pNew, pLast);
finalize_it:
RETiRet;
}
@ -1265,7 +1270,7 @@ validateConf(void)
rsRetVal
load(rsconf_t **cnf, uchar *confFile)
{
int iNbrActions;
int iNbrActions = 0;
int r;
DEFiRet;

Some files were not shown because too many files have changed in this diff Show More