1 diff --git a/configure.in b/configure.in
2 index d5f0769..1605bff 100644
7 if test "x$prefix" = "xNONE"; then
8 prefix=$ac_default_prefix
9 - pidfiledir="/var/run"
11 - pidfiledir="${prefix}/var/run"
13 +pidfiledir="${localstatedir}"
15 AM_CONFIG_HEADER(config.h)
17 @@ -70,7 +68,7 @@ AC_ARG_WITH(pidfile-dir,
19 AC_ARG_WITH(timezone-dir,
20 [ --with-timezone-dir=path Use path as the directory to get the timezone files],
21 - timezone_dir=$with_timezone_dir)
22 + timezonedir=$with_timezone_dir)
24 AC_ARG_WITH(ld-library-path,
25 [ --with-ld-library-path=path Set LD_LIBRARY_PATH during runtime to the value given],
26 @@ -92,10 +90,13 @@ AC_ARG_ENABLE(ssl,
27 [ --enable-ssl Enable SSL support.],,enable_ssl="auto")
29 AC_ARG_ENABLE(dynamic-linking,
30 - [ --enable-dynamic-linking Link glib and eventlog dynamically instead of statically.])
31 + [ --enable-dynamic-linking Link glib and eventlog dynamically instead of statically.],,enable_dynamic_linking="auto")
33 AC_ARG_ENABLE(static-linking,
34 - [ --enable-static-linking Link everything statically.])
35 + [ --enable-static-linking Link everything statically.],,enable_static_linking="auto")
37 +AC_ARG_ENABLE(mixed-linking,
38 + [ --enable-mixed-linking Link 3rd party libraries statically, system libraries dynamically],,enable_mixed_linking="auto")
41 [ --enable-ipv6 Enable support for IPv6.],,enable_ipv6="auto")
42 @@ -319,9 +320,6 @@ dnl ***************************************************************************
43 dnl OpenSSL headers/libraries
44 dnl ***************************************************************************
49 # openssl is needed for:
52 @@ -360,7 +358,13 @@ dnl libdbi headers/libraries
53 dnl ***************************************************************************
55 AC_CHECK_LIB(dl, dlsym, DL_LIBS="-ldl")
56 -PKG_CHECK_MODULES(LIBDBI, dbi >= $LIBDBI_MIN_VERSION,, LIBDBI_LIBS="")
57 +PKG_CHECK_MODULES(LIBDBI, dbi >= $LIBDBI_MIN_VERSION,, libdbi_pkgconfig_not_found="1")
59 +if test "$libdbi_pkgconfig_not_found" -eq 1; then
60 + dnl if libdbi has no .pc file, try it without one
61 + AC_CHECK_LIB(dbi, dbi_initialize, LIBDBI_LIBS="-ldbi"; LIBDBI_CFLAGS="-I/usr/include")
65 dnl ***************************************************************************
66 dnl Some more checks based on the detected settings above
67 @@ -606,8 +610,42 @@ int main()
71 -if test "x$enable_dynamic_linking" = "xyes" -a "x$enable_static_linking" = "xyes"; then
72 - AC_MSG_ERROR([You cannot specify dynamic and static linking at the same time.])
73 +if test "$enable_dynamic_linking" = "auto" -a "$enable_static_linking" = "auto" -a "$enable_mixed_linking" = "auto"; then
74 + enable_dynamic_linking="yes"
75 + enable_static_linking="no"
76 + enable_mixed_linking="no"
80 +if test "x$enable_dynamic_linking" = "xyes"; then
81 + linkopts=`expr $linkopts + 1`
83 +if test "x$enable_static_linking" = "xyes"; then
84 + linkopts=`expr $linkopts + 1`
86 +if test "x$enable_mixed_linking" = "xyes"; then
87 + linkopts=`expr $linkopts + 1`
90 +if test "$linkopts" -gt 1; then
91 + AC_MSG_ERROR([You cannot specify multiple linking options at the same time (--enable-dynamic-linking, --enable-static-linking, --enable-mixed-linking).])
94 +if test "x$enable_dynamic_linking" = "xyes"; then
95 + enable_dynamic_linking="yes"
96 + enable_static_linking="no"
97 + enable_mixed_linking="no"
98 + linking_mode="dynamic"
99 +elif test "x$enable_static_linking" = "xyes"; then
100 + enable_dynamic_linking="no"
101 + enable_static_linking="yes"
102 + enable_mixed_linking="no"
103 + linking_mode="static"
104 +elif test "x$enable_mixed_linking" = "xyes"; then
105 + enable_dynamic_linking="no"
106 + enable_static_linking="no"
107 + enable_mixed_linking="yes"
108 + linking_mode="mixed"
111 if test "x$enable_dynamic_linking" != "xyes" -a "x$blb_cv_static_glib" = "xno"; then
112 @@ -615,7 +653,7 @@ if test "x$enable_dynamic_linking" != "xyes" -a "x$blb_cv_static_glib" = "xno";
115 if test "x$enable_dynamic_linking" != "xyes" -a "x$blb_cv_static_openssl" = "xno"; then
116 - AC_MSG_ERROR([static OpenSSL libraries not found (libssl.a and libcrypto.a), either link OpenSSL statically using the --enable-dynamic-linking, or install a static OpenSSL])
117 + AC_MSG_ERROR([static OpenSSL libraries not found (libssl.a, libcrypto.a and their external dependencies like libz.a), either link OpenSSL statically using the --enable-dynamic-linking, or install a static OpenSSL])
121 @@ -672,8 +710,8 @@ AC_DEFINE_UNQUOTED(PATH_PREFIX, "`patheval $prefix`", [prefix directory])
122 AC_DEFINE_UNQUOTED(PATH_SYSCONFDIR, "`patheval $sysconfdir`", [sysconfdir])
123 AC_DEFINE_UNQUOTED(PATH_LOCALSTATEDIR, "`patheval $localstatedir`", [local state directory])
124 AC_DEFINE_UNQUOTED(PATH_PIDFILEDIR, "`patheval $pidfiledir`", [local state directory])
125 -if test -n "$timezone_dir"; then
126 - AC_DEFINE_UNQUOTED(PATH_TIMEZONEDIR, "`patheval $timezone_dir`", [timezone base directory])
127 +if test -n "$timezonedir"; then
128 + AC_DEFINE_UNQUOTED(PATH_TIMEZONEDIR, "`patheval $timezonedir`", [timezone base directory])
130 if test -n "$env_ld_library_path"; then
131 AC_DEFINE_UNQUOTED(ENV_LD_LIBRARY_PATH, "$env_ld_library_path", [set LD_LIBRARY_PATH to this value])
132 @@ -695,6 +733,8 @@ AC_DEFINE_UNQUOTED(ENABLE_ENV_WRAPPER, `enable_value $enable_env_wrapper`, [Enab
134 AM_CONDITIONAL(ENABLE_ENV_WRAPPER, [test "$enable_env_wrapper" = "yes"])
136 +AC_SUBST(timezonedir)
137 +AC_SUBST(pidfiledir)
138 AC_SUBST(DEPS_CPPFLAGS)
141 @@ -729,6 +769,7 @@ echo " compiler : $CC"
142 echo " compiler options : $CFLAGS $CPPFLAGS"
143 echo " linker flags : $LDFLAGS $LIBS"
144 echo " prefix : $prefix"
145 +echo " linking mode : $linking_mode"
147 echo " Sun STREAMS support : ${enable_sun_streams:=no}"
148 echo " Sun Door support : ${enable_sun_door:=no}"
149 diff --git a/contrib/balabit-initscripts/init-functions b/contrib/balabit-initscripts/init-functions
150 index e1898a8..c3b18ef 100644
151 --- a/contrib/balabit-initscripts/init-functions
152 +++ b/contrib/balabit-initscripts/init-functions
153 @@ -6,12 +6,35 @@ NORMAL=
162 +disable_xpg_echo() {
163 + # \X chars only passed to echo under bash, if xpg_echo enabled or echo -e
165 + if [ -n "$BASH_VERSION" ];then
171 # default ps -e cuts the process' name at 8 characters, so we have to list it
173 - SunOS) PSOPTS=" -o pid -o tty -o time -o comm" ;;
175 + PSOPTS=" -o pid -o tty -o time -o comm"
179 + if [ -z "$BASH_VERSION" ]; then
180 + # beware of dash's builtin echo ...
181 + ECHO="/bin/echo -e"
184 + *) disable_xpg_echo ;;
191 @@ -30,7 +53,7 @@ _pid_from_pidfile() {
194 if [ -f "$pidfile" ];then
195 - pid=`head -1 $pidfile`
196 + pid=`head -1 $pidfile 2> /dev/null`
197 if [ $? -ne 0 ]; then
198 # on slow machines (or ones under high load) the pidfile could be
199 # erased between -f and `head` ...
200 @@ -195,17 +218,17 @@ log_use_fancy_output() {
210 - echo "${RED}$@${NORMAL}"
211 + $ECHO "${RED}$@${NORMAL}"
216 - echo "${YELLOW}$@${NORMAL}"
217 + $ECHO "${YELLOW}$@${NORMAL}"
221 @@ -215,7 +238,7 @@ log_begin_msg() {
230 @@ -224,11 +247,11 @@ log_daemon_msg() {
244 @@ -237,9 +260,9 @@ log_progress_msg() {
247 if [ $1 -eq 0 ]; then
256 @@ -250,23 +273,23 @@ log_end_msg() {
263 - echo "${RED}failed!${NORMAL}"
264 + $ECHO "${RED}failed!${NORMAL}"
274 log_action_begin_msg() {
279 log_action_cont_msg() {
284 log_action_end_msg() {
285 @@ -278,15 +301,12 @@ log_action_end_msg() {
288 if [ $1 -eq 0 ]; then
292 - echo "${RED}failed${end}${NORMAL}"
293 + $ECHO "${RED}failed${end}${NORMAL}"
297 -# \X chars only passed to echo under bash, if xpg_echo enabled....
298 -if [ -n "$BASH_VERSION" ];then
302 # vim: ft=sh ts=2 expandtab
304 diff --git a/contrib/balabit-initscripts/init.d b/contrib/balabit-initscripts/init.d
305 index ff2e249..589da86 100644
306 --- a/contrib/balabit-initscripts/init.d
307 +++ b/contrib/balabit-initscripts/init.d
308 @@ -25,6 +25,7 @@ SYSLOGNG_PREFIX=/opt/syslog-ng
309 SYSLOGNG="$SYSLOGNG_PREFIX/sbin/syslog-ng"
310 CONFFILE=$SYSLOGNG_PREFIX/etc/syslog-ng.conf
311 PIDFILE=$SYSLOGNG_PREFIX/var/run/syslog-ng.pid
312 +SYSLOGPIDFILE="/var/run/syslog.pid"
314 INIT_FUNCTIONS=/lib/lsb/init-functions
315 SLNG_INIT_FUNCTIONS=$SYSLOGNG_PREFIX/lib/init-functions
316 @@ -64,6 +65,17 @@ if [ -f /etc/lsb-release ]; then
320 +if [ -f "/etc/redhat-release" ];then
321 + # redhat uses a different syslogd pidfile...
322 + SYSLOGPIDFILE="/var/run/syslogd.pid"
325 +if [ "$OS" = "SunOS" ] || [ "$OS" = "Solaris" ];then
326 + if [ "`uname -r`" = "5.8" ];then
327 + SYSLOGPIDFILE="/etc/syslog.pid"
331 if [ -f /lib/lsb/init-functions ];then
332 # long list of exclusions...
333 if [ -f "/etc/redhat-release" ] || [ -f "/etc/SuSE-release" ];then
334 @@ -117,7 +129,7 @@ check_syntax() {
343 @@ -147,6 +159,11 @@ returnmessage() {
346 echo_n "Starting syslog-ng: "
347 + PID=`pidofproc -p ${PIDFILE} ${SYSLOGNG} | head -1`
348 + if [ -n "$PID" ] && [ $PID -gt 0 ] ;then
349 + log_success_msg "already running: $PID"
352 start_daemon -p ${PIDFILE} ${SYSLOGNG} ${SYSLOGNG_OPTIONS}
354 returnmessage $retval
355 @@ -154,6 +171,13 @@ syslogng_start() {
356 if [ "$OS" = "Linux" ] && [ -d $SUBSYSDIR ];then
357 touch $SUBSYSDIR/syslog-ng
360 + if [ -h $SYSLOGPIDFILE ];then
361 + rm -f $SYSLOGPIDFILE
363 + if [ ! -f $SYSLOGPIDFILE ];then
364 + ln -s $PIDFILE $SYSLOGPIDFILE
369 @@ -180,6 +204,9 @@ syslogng_stop() {
371 if [ $retval -eq 0 ];then
372 rm -f $SUBSYSDIR/syslog-ng ${PIDFILE}
373 + if [ -h $SYSLOGPIDFILE ];then
374 + rm -f $SYSLOGPIDFILE
379 @@ -270,6 +297,14 @@ case "$1" in
384 + PID=`pidofproc -p ${PIDFILE} ${SYSLOGNG} | head -1`
385 + if [ -n "$PID" ] && [ $PID -gt 0 ] ;then
394 @@ -284,4 +319,4 @@ esac
399 +# vim: ts=2 ft=sh noexpandtab
400 diff --git a/contrib/balabit-initscripts/init.d.freebsd b/contrib/balabit-initscripts/init.d.freebsd
401 index 997b4db..de04473 100644
402 --- a/contrib/balabit-initscripts/init.d.freebsd
403 +++ b/contrib/balabit-initscripts/init.d.freebsd
404 @@ -33,9 +33,13 @@ command="$SYSLOGNG_PREFIX/sbin/syslog-ng"
405 required_files="$SYSLOGNG_PREFIX/etc/syslog-ng.conf"
407 start_precmd="syslog_ng_start_precmd"
408 +start_postcmd="syslog_ng_start_postcmd"
409 +stop_postcmd="syslog_ng_stop_postcmd"
410 reload_precmd="syslog_ng_reload_precmd"
411 extra_commands="reload"
413 +# get original syslog pidfile from initscript.
414 +_syslogd_pidfile=`sed -n -e 's/^pidfile="\([^"]*\)"/\1/p' /etc/rc.d/syslogd 2> /dev/null`
415 syslog_ng_start_precmd() {
416 if [ ! -L /dev/log ]; then
417 ln -s /var/run/log /dev/log
418 @@ -50,6 +54,26 @@ syslog_ng_reload_precmd() {
422 +syslog_ng_start_postcmd() {
423 + if [ -n "$_syslogd_pidfile" ]; then
425 + if [ -h $_syslogd_pidfile ]; then
426 + rm -f $_syslogd_pidfile
428 + if [ ! -f $_syslogd_pidfile ]; then
429 + ln -s "$pidfile" "$_syslogd_pidfile"
434 +syslog_ng_stop_postcmd() {
435 + if [ -n "$_syslogd_pidfile" ]; then
436 + if [ -h $_syslogd_pidfile ]; then
437 + rm -f "$_syslogd_pidfile"
442 load_rc_config "$name"
445 diff --git a/contrib/cygwin-packaging/cygwin-postinstall b/contrib/cygwin-packaging/cygwin-postinstall
446 index 4b7bf7d..e812ead 100755
447 --- a/contrib/cygwin-packaging/cygwin-postinstall
448 +++ b/contrib/cygwin-packaging/cygwin-postinstall
449 @@ -21,11 +21,11 @@ then
452 mkdir -p "${DESTDIR}/usr/bin"
453 -mkdir -p "${DESTDIR}/usr/share/doc/syslog-ng"
454 +#mkdir -p "${DESTDIR}/usr/share/doc/syslog-ng"
455 mkdir -p "${DESTDIR}/usr/share/doc/Cygwin"
456 cp contrib/cygwin-packaging/syslog-ng-config "${DESTDIR}/usr/bin"
457 -cp -rp doc/examples/syslog-ng.conf.s* doc/reference/syslog-ng.[tx]* "${DESTDIR}/usr/share/doc/syslog-ng"
458 -tar xzfC doc/reference/syslog-ng.html.tar.gz "${DESTDIR}/usr/share/doc/syslog-ng"
459 +#cp -rp doc/examples/syslog-ng.conf.s* doc/reference/syslog-ng.[tx]* "${DESTDIR}/usr/share/doc/syslog-ng"
460 +#tar xzfC doc/reference/syslog-ng.html.tar.gz "${DESTDIR}/usr/share/doc/syslog-ng"
461 cat > "${DESTDIR}/usr/share/doc/Cygwin/syslog-ng.README" <<'EOF'
462 If you want to use syslog-ng, just run the /usr/bin/syslog-ng-config
463 script. This script will create a default configuration file
464 @@ -42,15 +42,15 @@ The syslog-ng package has been built using the following command
465 sequence from the top level source dir:
469 - --disable-tcp-wrapper \
472 --libexecdir='$(prefix)/sbin' \
473 --localstatedir=/var \
474 --datadir='$(prefix)/share' \
475 --mandir='$(prefix)/share/man' \
476 - --infodir='$(prefix)/share/info'
477 + --infodir='$(prefix)/share/info' \
478 + --enable-dynamic-linking \
479 + --with-pidfile-dir=/var
482 contrib/cygwin-packaging/cygwin-postinstall
483 diff --git a/contrib/cygwin-packaging/syslog-ng-config b/contrib/cygwin-packaging/syslog-ng-config
484 index 790f0cc..7ae5fec 100755
485 --- a/contrib/cygwin-packaging/syslog-ng-config
486 +++ b/contrib/cygwin-packaging/syslog-ng-config
487 @@ -205,13 +205,13 @@ if [ ! -f "${SYSCONFDIR}/syslog-ng.conf" ]
489 echo "Creating default ${SYSCONFDIR}/syslog-ng.conf file"
490 cat > ${SYSCONFDIR}/syslog-ng.conf << EOF
494 - chain_hostnames(no);
502 source applications {
503 @@ -220,7 +220,7 @@ source applications {
507 - file("/dev/kmsg", log_prefix("kernel: "));
508 + file("/dev/kmsg", program_override("kernel: "));
511 destination messages {
512 @@ -240,42 +240,35 @@ EOF
514 setfacl -m u:system:rw- "${SYSCONFDIR}/syslog-ng.conf"
516 -# Check if running on NT
518 -_nt=`expr "${_sys}" : "CYGWIN_NT"`
519 -# On NT ask if syslog-ng should be installed as service
521 +# Check if syslogd is installed and remove on user request.
522 +if cygrunsrv -Q syslogd > /dev/null 2>&1
524 - # Check if syslogd is installed and remove on user request.
525 - if cygrunsrv -Q syslogd > /dev/null 2>&1
526 + echo "Warning: The syslogd service is already installed. You can not"
527 + echo "run both, syslogd and syslog-ng in parallel."
529 + if request "Do you want to deinstall the syslogd service in favor of syslog-ng?"
531 - echo "Warning: The syslogd service is already installed. You can not"
532 - echo "run both, syslogd and syslog-ng in parallel."
534 - if request "Do you want to deinstall the syslogd service in favor of syslog-ng?"
536 - cygrunsrv -E syslogd
537 - cygrunsrv -R syslogd
539 + cygrunsrv -E syslogd
540 + cygrunsrv -R syslogd
542 - # Install syslog-ng service if it is not already installed
543 - if ! cygrunsrv -Q syslog-ng > /dev/null 2>&1
545 +# Install syslog-ng service if it is not already installed
546 +if ! cygrunsrv -Q syslog-ng > /dev/null 2>&1
550 + echo "Warning: The following function requires administrator privileges!"
552 + echo "Do you want to install syslog-ng as service?"
553 + if request "(Say \"no\" if it's already installed as service)"
557 - echo "Warning: The following function requires administrator privileges!"
559 - echo "Do you want to install syslog-ng as service?"
560 - if request "(Say \"no\" if it's already installed as service)"
561 + if cygrunsrv -I syslog-ng -d "CYGWIN syslog-ng" -p /usr/sbin/syslog-ng -a "-F --fd-limit 256"
563 - if cygrunsrv -I syslog-ng -d "CYGWIN syslog-ng" -p /usr/sbin/syslog-ng -a -F
566 - echo "The service has been installed under LocalSystem account."
567 - echo "To start the service, call \`net start syslog-ng' or \`cygrunsrv -S syslog-ng'."
569 - echo "Check ${SYSCONFDIR}/syslog-ng.conf first, if it suits your needs."
572 + echo "The service has been installed under LocalSystem account."
573 + echo "To start the service, call \`net start syslog-ng' or \`cygrunsrv -S syslog-ng'."
575 + echo "Check ${SYSCONFDIR}/syslog-ng.conf first, if it suits your needs."
579 diff --git a/contrib/solaris-packaging/syslog-ng.method b/contrib/solaris-packaging/syslog-ng.method
580 index f0fee58..d819a3c 100755
581 --- a/contrib/solaris-packaging/syslog-ng.method
582 +++ b/contrib/solaris-packaging/syslog-ng.method
583 @@ -13,6 +13,7 @@ SYSLOGNG_PREFIX=/opt/syslog-ng
584 SYSLOGNG="$SYSLOGNG_PREFIX/sbin/syslog-ng"
585 CONFFILE=$SYSLOGNG_PREFIX/etc/syslog-ng.conf
586 PIDFILE=$SYSLOGNG_PREFIX/var/run/syslog-ng.pid
587 +SYSLOGPIDFILE=/var/run/syslog.pid
591 @@ -56,7 +57,7 @@ slng_stop() {
593 _process=`basename $SYSLOGNG`
594 slng_waitforpid "$_process" $syspid
597 if [ $_ret -eq 0 ]; then
600 @@ -68,6 +69,9 @@ slng_stop() {
601 [ $? -ne 0 ] && exit $SMF_EXIT_ERR_FATAL
604 + if [ -h $SYSLOGPIDFILE ];then
605 + rm -f $SYSLOGPIDFILE
609 return $SMF_EXIT_ERR_FATAL
610 @@ -93,6 +97,13 @@ slng_start () {
615 + if [ -h $SYSLOGPIDFILE ];then
616 + rm -f $SYSLOGPIDFILE
618 + if [ ! -f $SYSLOGPIDFILE ];then
619 + ln -s $PIDFILE $SYSLOGPIDFILE
623 return $SMF_EXIT_ERR_FATAL
624 diff --git a/debian/control b/debian/control
625 index c0689a5..0dcc8b3 100644
628 @@ -2,7 +2,7 @@ Source: syslog-ng
631 Maintainer: SZALAY Attila <sasa@debian.org>
632 -Build-depends: debhelper (>=3.0.0), libevtlog-dev, libnet1-dev, libglib2.0-dev (>= 2.4), pkg-config, libdbi-dev
633 +Build-depends: debhelper (>=3.0.0), libevtlog-dev, libnet1-dev, libglib2.0-dev (>= 2.4), pkg-config, libdbi0-dev, libssl-dev
634 Standards-Version: 3.6.1
637 diff --git a/src/affile.c b/src/affile.c
638 index 6d48915..5721a1a 100644
644 affile_open_file(gchar *name, gint flags,
645 - uid_t uid, gid_t gid, mode_t mode,
646 - uid_t dir_uid, gid_t dir_gid, mode_t dir_mode,
647 - gboolean create_dirs, gboolean privileged, gint *fd)
648 + uid_t uid, gid_t gid, mode_t mode,
649 + uid_t dir_uid, gid_t dir_gid, mode_t dir_mode,
650 + gboolean create_dirs, gboolean privileged, gboolean is_pipe, gint *fd)
655 if (strstr(name, "../") || strstr(name, "/.."))
657 @@ -63,20 +64,43 @@ affile_open_file(gchar *name, gint flags,
658 g_process_cap_modify(CAP_DAC_READ_SEARCH, TRUE);
659 g_process_cap_modify(CAP_SYS_ADMIN, TRUE);
661 + if (stat(name, &st) >= 0)
663 + if (is_pipe && !S_ISFIFO(st.st_mode))
665 + msg_error("Error opening pipe, underlying file is not a FIFO, it should be used by file()",
666 + evt_tag_str("filename", name),
670 + else if (!is_pipe && S_ISFIFO(st.st_mode))
672 + msg_error("Error opening file, underlying file is a FIFO, it should be used by pipe()",
673 + evt_tag_str("filename", name),
678 *fd = open(name, flags, mode);
679 + if (is_pipe && *fd < 0 && errno == ENOENT)
681 + if (mkfifo(name, 0666) >= 0)
682 + *fd = open(name, flags, 0666);
687 g_fd_set_cloexec(*fd, TRUE);
689 g_process_cap_modify(CAP_DAC_OVERRIDE, TRUE);
691 + if (uid != (uid_t) -1)
692 fchown(*fd, uid, -1);
694 + if (gid != (gid_t) -1)
695 fchown(*fd, -1, gid);
697 + if (mode != (mode_t) -1)
703 g_process_cap_restore(saved_caps);
704 @@ -99,7 +123,7 @@ affile_sd_open_file(AFFileSourceDriver *self, gchar *name, gint *fd)
706 flags = O_RDONLY | O_NOCTTY | O_NONBLOCK | O_LARGEFILE;
708 - if (affile_open_file(name, flags, -1, -1, -1, 0, 0, 0, 0, !!(self->flags & AFFILE_PRIVILEGED), fd))
709 + if (affile_open_file(name, flags, -1, -1, -1, 0, 0, 0, 0, !!(self->flags & AFFILE_PRIVILEGED), !!(self->flags & AFFILE_PIPE), fd))
713 @@ -196,9 +220,15 @@ affile_sd_notify(LogPipe *s, LogPipe *sender, gint notify_code, gpointer user_da
714 transport = log_transport_plain_new(fd, 0);
715 transport->timeout = 10;
717 - self->reader = log_reader_new(log_proto_plain_new_server(transport, self->reader_options.padding, self->reader_options.msg_size, LPPF_NOMREAD | ((self->reader_options.follow_freq > 0) ? LPPF_IGNORE_EOF : 0)),
720 + self->reader = log_reader_new(
721 + log_proto_plain_new_server(transport, self->reader_options.padding,
722 + self->reader_options.msg_size,
723 + ((self->reader_options.follow_freq > 0)
729 log_reader_set_options(self->reader, s, &self->reader_options, 1, SCS_FILE, self->super.id, self->filename->str);
731 log_reader_set_follow_filename(self->reader, self->filename->str);
732 @@ -290,10 +320,16 @@ affile_sd_init(LogPipe *s)
733 transport->timeout = 10;
735 /* FIXME: we shouldn't use reader_options to store log protocol parameters */
736 - self->reader = log_reader_new(log_proto_plain_new_server(transport, self->reader_options.padding, self->reader_options.msg_size, LPPF_NOMREAD | ((self->reader_options.follow_freq > 0) ? LPPF_IGNORE_EOF : 0)),
738 + self->reader = log_reader_new(
739 + log_proto_plain_new_server(transport, self->reader_options.padding,
740 + self->reader_options.msg_size,
741 + ((self->reader_options.follow_freq > 0)
746 log_reader_set_options(self->reader, s, &self->reader_options, 1, SCS_FILE, self->super.id, self->filename->str);
749 log_reader_set_follow_filename(self->reader, self->filename->str);
751 /* NOTE: if the file could not be opened, we ignore the last
752 @@ -458,7 +494,7 @@ affile_dw_init(LogPipe *s)
753 if (affile_open_file(self->filename->str, flags,
754 self->owner->file_uid, self->owner->file_gid, self->owner->file_perm,
755 self->owner->dir_uid, self->owner->dir_gid, self->owner->dir_perm,
756 - !!(self->owner->flags & AFFILE_CREATE_DIRS), FALSE, &fd))
757 + !!(self->owner->flags & AFFILE_CREATE_DIRS), FALSE, !!(self->owner->flags & AFFILE_PIPE), &fd))
761 diff --git a/src/afsocket.c b/src/afsocket.c
762 index ad8e198..af788f6 100644
765 @@ -90,12 +90,12 @@ afsocket_open_socket(GSockAddr *bind_addr, int stream_or_dgram, int *fd)
767 sock = socket(bind_addr->sa.sa_family, SOCK_DGRAM, 0);
769 - g_fd_set_nonblock(sock, TRUE);
770 - g_fd_set_cloexec(sock, TRUE);
775 + g_fd_set_nonblock(sock, TRUE);
776 + g_fd_set_cloexec(sock, TRUE);
777 saved_caps = g_process_cap_save();
778 g_process_cap_modify(CAP_NET_BIND_SERVICE, TRUE);
779 g_process_cap_modify(CAP_DAC_OVERRIDE, TRUE);
780 @@ -208,7 +208,9 @@ afsocket_sc_init(LogPipe *s)
781 if ((self->owner->flags & AFSOCKET_SYSLOG_PROTOCOL) == 0)
784 - proto = log_proto_plain_new_server(transport, self->owner->reader_options.padding, self->owner->reader_options.msg_size, (self->owner->flags & AFSOCKET_DGRAM) ? LPPF_PKTTERM : 0);
785 + proto = log_proto_plain_new_server(transport, self->owner->reader_options.padding,
786 + self->owner->reader_options.msg_size,
787 + (self->owner->flags & AFSOCKET_DGRAM) ? (LPPF_PKTTERM + LPPF_IGNORE_EOF) : 0);
791 diff --git a/src/afsql.c b/src/afsql.c
792 index 96c5b22..dcbc02e 100644
795 @@ -940,6 +940,7 @@ afsql_dd_new()
796 self->frac_digits = -1;
798 self->validated_tables = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
799 + g_static_mutex_init(&self->queue_lock);
801 init_sequence_number(&self->seq_num);
803 diff --git a/src/apphook.c b/src/apphook.c
804 index ab9cb02..6115b27 100644
807 @@ -54,10 +54,10 @@ run_application_hook(gint type)
812 application_hooks = g_list_remove_link(application_hooks, l);
813 e->func(type, e->user_data);
819 diff --git a/src/cfg-grammar.y b/src/cfg-grammar.y
820 index 9902d84..056783d 100644
821 --- a/src/cfg-grammar.y
822 +++ b/src/cfg-grammar.y
823 @@ -52,6 +52,7 @@ LogParser *last_parser;
824 FilterRE *last_re_filter;
825 LogRewrite *last_rewrite;
826 gint last_addr_family = AF_INET;
827 +gchar *last_include_file;
830 TLSContext *last_tls_context;
831 @@ -92,17 +93,20 @@ cfg_check_template(LogTemplate *template)
844 FilterExprNode *node;
848 -%token KW_SOURCE KW_FILTER KW_PARSER KW_DESTINATION KW_LOG KW_OPTIONS
849 +%token KW_SOURCE KW_FILTER KW_PARSER KW_DESTINATION KW_LOG KW_OPTIONS KW_INCLUDE
851 /* source & destination items */
852 %token KW_INTERNAL KW_FILE KW_PIPE KW_UNIX_STREAM KW_UNIX_DGRAM
853 @@ -154,7 +158,7 @@ cfg_check_template(LogTemplate *template)
855 /* socket related options */
856 %token KW_KEEP_ALIVE KW_MAX_CONNECTIONS
857 -%token KW_LOCALIP KW_IP KW_LOCALPORT KW_PORT KW_DESTPORT KW_FRAMED
858 +%token KW_LOCALIP KW_IP KW_LOCALPORT KW_PORT KW_DESTPORT
859 %token KW_IP_TTL KW_SO_BROADCAST KW_IP_TOS KW_SO_SNDBUF KW_SO_RCVBUF KW_SO_KEEPALIVE KW_SPOOF_SOURCE
862 @@ -182,6 +186,7 @@ cfg_check_template(LogTemplate *template)
864 %token <cptr> IDENTIFIER
870 @@ -276,6 +281,32 @@ cfg_check_template(LogTemplate *template)
871 %type <ptr> string_list
872 %type <ptr> string_list_build
874 +%type <token> reserved_words_as_strings
876 +%type <token> KW_PARSER
877 +%type <token> KW_REWRITE
878 +%type <token> KW_INCLUDE
879 +%type <token> KW_SYSLOG
880 +%type <token> KW_COLUMNS
881 +%type <token> KW_DELIMITERS
882 +%type <token> KW_QUOTES
883 +%type <token> KW_QUOTE_PAIRS
884 +%type <token> KW_NULL
885 +%type <token> KW_CSV_PARSER
886 +%type <token> KW_DB_PARSER
887 +%type <token> KW_ENCODING
888 +%type <token> KW_SET
889 +%type <token> KW_SUBST
890 +%type <token> KW_VALUE
891 +%type <token> KW_PROGRAM_OVERRIDE
892 +%type <token> KW_HOST_OVERRIDE
893 +%type <token> KW_TRANSPORT
894 +%type <token> KW_TRUSTED_KEYS
895 +%type <token> KW_TRUSTED_DN
896 +%type <token> KW_MESSAGE
897 +%type <token> KW_TYPE
898 +%type <token> KW_SQL
903 @@ -283,7 +314,21 @@ start
910 + if (last_include_file && !cfg_lex_process_include(last_include_file))
912 + free(last_include_file);
913 + last_include_file = NULL;
916 + if (last_include_file)
918 + free(last_include_file);
919 + last_include_file = NULL;
926 @@ -296,6 +341,7 @@ stmt
927 | KW_REWRITE rewrite_stmt { cfg_add_rewrite(configuration, $2); }
928 | KW_TEMPLATE template_stmt { cfg_add_template(configuration, $2); }
929 | KW_OPTIONS options_stmt { }
930 + | KW_INCLUDE include_stmt { }
934 @@ -319,6 +365,9 @@ dest_stmt
936 : '{' log_items log_forks log_flags '}' { LogPipeItem *pi = log_pipe_item_append_tail($2, $3); $$ = log_connection_new(pi, $4); }
940 + : string { last_include_file = $1; }
943 : log_item ';' log_items { log_pipe_item_append($1, $3); $$ = $1; }
944 @@ -442,7 +491,7 @@ source_affile_option
945 affile_sd_set_pri_level(last_driver, level);
948 - | KW_FACILITY '(' string ')'
949 + | KW_FACILITY '(' string ')'
953 @@ -708,7 +757,8 @@ source_reader_option
954 | KW_LOG_MSG_SIZE '(' NUMBER ')' { last_reader_options->msg_size = $3; }
955 | KW_LOG_FETCH_LIMIT '(' NUMBER ')' { last_reader_options->fetch_limit = $3; }
956 | KW_PAD_SIZE '(' NUMBER ')' { last_reader_options->padding = $3; }
957 - | KW_FOLLOW_FREQ '(' NUMBER ')' { last_reader_options->follow_freq = $3; }
958 + | KW_FOLLOW_FREQ '(' FLOAT ')' { last_reader_options->follow_freq = (long) ($3 * 1000); }
959 + | KW_FOLLOW_FREQ '(' NUMBER ')' { last_reader_options->follow_freq = ($3 * 1000); }
960 | KW_KEEP_TIMESTAMP '(' yesno ')' { last_reader_options->super.keep_timestamp = $3; }
961 | KW_ENCODING '(' string ')' { last_reader_options->text_encoding = g_strdup($3); free($3); }
963 @@ -777,7 +827,7 @@ dest_afpipe
967 - last_driver = affile_dd_new($1, AFFILE_NO_EXPAND | AFFILE_PIPE);
968 + last_driver = affile_dd_new($1, AFFILE_PIPE);
970 last_writer_options = &((AFFileDestDriver *) last_driver)->writer_options;
971 last_writer_options->flush_lines = 0;
972 @@ -895,7 +945,7 @@ dest_afinet_tcp_option
978 last_tls_context = tls_context_new(TM_CLIENT);
981 @@ -1282,7 +1332,7 @@ filter_fac_list
988 int n = syslog_name_lookup_facility_by_name($1);
990 @@ -1461,6 +1511,34 @@ dnsmode
994 + | reserved_words_as_strings { $$ = cfg_lex_get_keyword_string($1); }
997 +reserved_words_as_strings
998 + /* these keywords were introduced in syslog-ng 3.0 */
1014 + | KW_PROGRAM_OVERRIDE
1015 + | KW_HOST_OVERRIDE
1025 @@ -1483,14 +1561,8 @@ extern int linenum;
1029 - fprintf(stderr, "%s in %s at line %d.\n", msg, configuration->filename, linenum);
1030 + fprintf(stderr, "%s in %s at line %d.\n\n"
1031 + "syslog-ng documentation: http://www.balabit.com/support/documentation/?product=syslog-ng\n"
1032 + "mailing list: https://lists.balabit.hu/mailman/listinfo/syslog-ng\n", msg, cfg_lex_get_current_file(), cfg_lex_get_current_lineno());
1036 -yyparser_reset(void)
1038 - last_driver = NULL;
1039 - last_reader_options = NULL;
1040 - last_writer_options = NULL;
1041 - last_template = NULL;
1043 diff --git a/src/cfg-lex.l b/src/cfg-lex.l
1044 index c9db716..b3c893c 100644
1050 #include <strings.h>
1051 +#include <sys/stat.h>
1055 @@ -52,6 +53,7 @@ static struct keyword keywords[] = {
1056 { "destination", KW_DESTINATION },
1058 { "options", KW_OPTIONS },
1059 + { "include", KW_INCLUDE },
1061 /* source or destination items */
1062 { "file", KW_FILE },
1063 @@ -162,7 +164,6 @@ static struct keyword keywords[] = {
1064 { "localport", KW_LOCALPORT },
1065 { "port", KW_PORT },
1066 { "destport", KW_DESTPORT },
1067 - { "framed", KW_FRAMED },
1068 { "ip_ttl", KW_IP_TTL },
1069 { "ip_tos", KW_IP_TOS },
1070 { "so_broadcast", KW_SO_BROADCAST },
1071 @@ -229,7 +230,20 @@ static struct keyword keywords[] = {
1073 #define MAX_REGEXP_LEN 1024
1076 +typedef struct _CfgIncludeLevel
1079 + gchar *current_file;
1081 + struct yy_buffer_state *yybuf;
1084 +#define MAX_INCLUDE_DEPTH 16
1086 +static CfgIncludeLevel include_stack[MAX_INCLUDE_DEPTH];
1087 +static gint include_depth = 0;
1090 int lex_filter_params = 0;
1091 char buf[MAX_REGEXP_LEN];
1093 @@ -237,6 +251,7 @@ char *str;
1094 static int check_reserved_words(char *token);
1095 static void append_string(int length, char *str);
1096 static void append_char(char c);
1097 +static gboolean cfg_start_next_include(gboolean first_on_this_level);
1101 @@ -254,9 +269,10 @@ word [^ \#'"\(\)\{\}\\;\n\t,|\.]
1105 -\r?\n { linenum++; }
1106 +\r?\n { include_stack[include_depth].linenum++; }
1108 \.\. { return DOTDOT; }
1109 +(-|\+)?{digit}+\.{digit}+ { yylval.fnum = strtod(yytext, NULL); return FLOAT; }
1110 0x{digit}+ { yylval.num = strtoll(yytext, NULL, 16); return NUMBER; }
1111 0{digit}+ { yylval.num = strtoll(yytext, NULL, 8); return NUMBER; }
1112 (-|\+)?{digit}+ { yylval.num = strtoll(yytext, NULL, 10); return NUMBER; }
1113 @@ -298,16 +314,13 @@ word [^ \#'"\(\)\{\}\\;\n\t,|\.]
1118 +<INITIAL><<EOF>> { if (!cfg_start_next_include(FALSE)) yyterminate(); }
1122 -lex_init(FILE *file, gint init_line_num)
1125 - linenum = init_line_num;
1132 check_reserved_words(char *token)
1135 @@ -339,6 +352,7 @@ check_reserved_words(char *token)
1138 keywords[i].kw_status = KWS_NORMAL;
1139 + yylval.token = keywords[i].kw_token;
1140 return keywords[i].kw_token;
1143 @@ -364,3 +378,251 @@ append_char(char c)
1149 +cfg_lex_get_current_file(void)
1151 + CfgIncludeLevel *level = &include_stack[include_depth];
1153 + return level->current_file;
1157 +cfg_lex_get_current_lineno(void)
1159 + CfgIncludeLevel *level = &include_stack[include_depth];
1161 + return level->linenum;
1165 +cfg_lex_get_keyword_string(int kw)
1168 + for (i = 0; i < (sizeof(keywords) / sizeof(struct keyword)); i++)
1170 + if (keywords[i].kw_token == kw)
1172 + msg_warning("WARNING: Your configuration uses a newly introduced reserved word as identifier, please use a different name",
1173 + evt_tag_str("keyword", keywords[i].kw_name),
1174 + evt_tag_str("filename", cfg_lex_get_current_file()),
1175 + evt_tag_int("line", cfg_lex_get_current_lineno()),
1177 + return strdup(keywords[i].kw_name);
1180 + g_assert_not_reached();
1186 +cfg_start_next_include(gboolean first_on_this_level)
1188 + FILE *include_file;
1189 + CfgIncludeLevel *level = &include_stack[include_depth];
1191 + struct yy_buffer_state *yybuf;
1193 + g_assert(level->yybuf == NULL);
1195 + if (include_depth == 0)
1200 + if (!first_on_this_level)
1202 + msg_debug("Finishing include file",
1203 + evt_tag_str("filename", level->current_file),
1204 + evt_tag_int("depth", include_depth),
1208 + if (!level->files)
1210 + yybuf = YY_CURRENT_BUFFER;
1211 + g_free(level->current_file);
1212 + fclose(yybuf->yy_input_file);
1213 + level->current_file = NULL;
1215 + yy_switch_to_buffer(include_stack[include_depth].yybuf);
1216 + include_stack[include_depth].yybuf = NULL;
1217 + if (!first_on_this_level)
1218 + yy_delete_buffer(yybuf);
1223 + filename = (gchar *) level->files->data;
1224 + level->files = g_slist_delete_link(level->files, level->files);
1226 + include_file = fopen(filename, "r");
1227 + if (!include_file)
1229 + msg_error("Error opening include file",
1230 + evt_tag_str("filename", filename),
1231 + evt_tag_int("depth", include_depth),
1236 + msg_debug("Starting to read include file",
1237 + evt_tag_str("filename", filename),
1238 + evt_tag_int("depth", include_depth),
1240 + yybuf = YY_CURRENT_BUFFER;
1241 + if (level->current_file)
1243 + g_free(level->current_file);
1245 + fclose(yybuf->yy_input_file);
1247 + level->current_file = filename;
1248 + level->linenum = 1;
1250 + yy_switch_to_buffer(yy_create_buffer(include_file, YY_BUF_SIZE));
1251 + if (!first_on_this_level)
1252 + yy_delete_buffer(yybuf);
1257 +cfg_lex_process_include(const gchar *filename)
1261 + CfgIncludeLevel *level;
1263 + if (include_depth >= MAX_INCLUDE_DEPTH - 1)
1265 + msg_error("Include file depth is too deep, increase MAX_INCLUDE_DEPTH and recompile",
1266 + evt_tag_str("filename", filename),
1267 + evt_tag_int("depth", include_depth),
1272 + if (filename[0] != '/')
1274 + g_snprintf(buf, sizeof(buf), "%s/%s", PATH_SYSCONFDIR, filename);
1278 + if (stat(filename, &st) < 0)
1280 + msg_error("Include file/directory not found",
1281 + evt_tag_str("filename", filename),
1282 + evt_tag_errno("error", errno),
1286 + include_stack[include_depth].yybuf = YY_CURRENT_BUFFER;
1288 + level = &include_stack[include_depth];
1289 + if (S_ISDIR(st.st_mode))
1292 + GError *error = NULL;
1293 + const gchar *entry;
1295 + dir = g_dir_open(filename, 0, &error);
1298 + msg_error("Error opening directory for reading",
1299 + evt_tag_str("filename", filename),
1300 + evt_tag_str("error", error->message),
1304 + while ((entry = g_dir_read_name(dir)))
1308 + for (p = entry; *p; p++)
1310 + if (!((*p >= 'a' && *p <= 'z') ||
1311 + (*p >= 'A' && *p <= 'Z') ||
1312 + (*p >= '0' && *p <= '9') ||
1313 + (*p == '_') || (*p == '-') || (*p == '.')))
1315 + msg_debug("Skipping include file, does not match pattern [\\-_a-zA-Z0-9]+",
1316 + evt_tag_str("filename", entry),
1324 + gchar *full_filename = g_build_filename(filename, entry, NULL);
1325 + if (stat(full_filename, &st) < 0 || S_ISDIR(st.st_mode))
1327 + msg_debug("Skipping include file as it is a directory",
1328 + evt_tag_str("filename", entry),
1330 + g_free(full_filename);
1333 + level->files = g_slist_insert_sorted(level->files, full_filename, (GCompareFunc) strcmp);
1334 + msg_debug("Adding include file",
1335 + evt_tag_str("filename", entry),
1340 + if (!level->files)
1342 + /* no include files in the specified directory */
1343 + msg_debug("No files in this include directory",
1344 + evt_tag_str("dir", filename),
1347 + include_stack[include_depth].yybuf = NULL;
1353 + g_assert(level->files == NULL);
1354 + level->files = g_slist_prepend(level->files, g_strdup(filename));
1356 + return cfg_start_next_include(TRUE);
1358 + g_slist_foreach(level->files, (GFunc) g_free, NULL);
1359 + g_slist_free(level->files);
1360 + level->files = NULL;
1365 +cfg_lex_init(FILE *file, gint init_line_num)
1367 + CfgIncludeLevel *level;
1370 + level = &include_stack[0];
1371 + level->current_file = g_strdup(configuration->filename);
1372 + level->linenum = init_line_num;
1377 +cfg_lex_deinit(void)
1381 + for (i = 0; i < include_depth; i++)
1383 + CfgIncludeLevel *level = &include_stack[i];
1385 + if (level->current_file)
1386 + g_free(level->current_file);
1388 + g_slist_foreach(level->files, (GFunc) g_free, NULL);
1389 + g_slist_free(level->files);
1390 + level->files = NULL;
1392 + yy_delete_buffer(level->yybuf);
1395 diff --git a/src/cfg.c b/src/cfg.c
1396 index 23d93b6..45e5119 100644
1400 #include "logparser.h"
1401 #include "serialize.h"
1403 +#include <sys/types.h>
1404 +#include <signal.h>
1408 @@ -203,15 +205,6 @@ cfg_deinit(GlobalConfig *cfg)
1409 return log_center_deinit(cfg->center);
1412 -/* extern declarations in the generated parser & lexer */
1414 -extern int yyparse();
1415 -extern void lex_init(FILE *, gint lineno);
1416 -extern int yydebug;
1417 -extern int linenum;
1419 -extern void yyparser_reset(void);
1422 cfg_read_pragmas(GlobalConfig *self, FILE *cfg, gint *lineno)
1424 @@ -358,8 +351,9 @@ cfg_new(gchar *fname)
1425 self->chain_hostnames = TRUE;
1428 - lex_init(cfg, lineno);
1429 + cfg_lex_init(cfg, lineno);
1435 @@ -481,7 +475,15 @@ cfg_reload_config(gchar *fname, GlobalConfig *cfg)
1437 msg_error("Error initializing new configuration, reverting to old config", NULL);
1438 cfg_persist_config_move(new_cfg, cfg);
1440 + if (!cfg_init(cfg))
1442 + /* hmm. hmmm, error reinitializing old configuration, we're hosed.
1443 + * Best is to kill ourselves in the hope that the supervisor
1446 + kill(getpid(), SIGQUIT);
1447 + g_assert_not_reached();
1452 diff --git a/src/cfg.h b/src/cfg.h
1453 index d7b4edc..91f3060 100644
1458 #include <sys/types.h>
1462 struct _LogSourceGroup;
1463 struct _LogDestGroup;
1464 @@ -148,6 +149,19 @@ void cfg_persist_set_version(GlobalConfig *cfg, const gint version);
1466 void persist_config_free(PersistentConfig *persist);
1468 +/* defined in the lexer */
1469 +void yyerror(char *msg);
1471 +int cfg_lex_init(FILE *file, gint init_line_num);
1472 +void cfg_lex_deinit(void);
1473 +gboolean cfg_lex_process_include(const gchar *filename);
1474 +const gchar *cfg_lex_get_current_file(void);
1475 +gint cfg_lex_get_current_lineno(void);
1476 +char *cfg_lex_get_keyword_string(int kw);
1478 +/* defined in the parser */
1481 static inline gboolean
1482 cfg_check_current_config_version(gint req)
1484 diff --git a/src/dnscache.c b/src/dnscache.c
1485 index ef8cc8f..bd23648 100644
1486 --- a/src/dnscache.c
1487 +++ b/src/dnscache.c
1488 @@ -66,6 +66,7 @@ static gint dns_cache_expire_failed = 60;
1489 static gint dns_cache_persistent_count = 0;
1490 static gchar *dns_cache_hosts = NULL;
1491 static time_t dns_cache_hosts_mtime = -1;
1492 +static time_t dns_cache_hosts_checktime = 0;
1495 dns_cache_key_equal(DNSCacheKey *e1, DNSCacheKey *e2)
1496 @@ -156,6 +157,12 @@ static void
1497 dns_cache_check_hosts(void)
1500 + time_t t = time(NULL);
1502 + if (G_LIKELY(dns_cache_hosts_checktime == t))
1505 + dns_cache_hosts_checktime = t;
1507 if (!dns_cache_hosts || stat(dns_cache_hosts, &st) < 0)
1509 @@ -299,6 +306,7 @@ dns_cache_set_params(gint cache_size, gint expire, gint expire_failed, const gch
1510 dns_cache_expire_failed = expire_failed;
1511 dns_cache_hosts = g_strdup(hosts);
1512 dns_cache_hosts_mtime = -1;
1513 + dns_cache_hosts_checktime = 0;
1517 diff --git a/src/filter.c b/src/filter.c
1518 index 0d1fe57..3a14fdd 100644
1521 @@ -375,6 +375,11 @@ filter_netmask_eval(FilterExprNode *s, LogMessage *msg)
1523 addr.s_addr = htonl(INADDR_LOOPBACK);
1527 + /* no address information, return FALSE */
1530 return ((addr.s_addr & self->netmask.s_addr) == (self->address.s_addr)) ^ s->comp;
1533 diff --git a/src/gprocess.c b/src/gprocess.c
1534 index 5a4a76f..004f57c 100644
1535 --- a/src/gprocess.c
1536 +++ b/src/gprocess.c
1537 @@ -87,7 +87,9 @@ static struct
1544 const gchar *chroot_dir;
1545 const gchar *pidfile;
1546 const gchar *pidfile_dir;
1547 @@ -109,9 +111,15 @@ static struct
1552 + .fd_limit_min = 256,
1554 .fd_limit_min = 4096,
1562 #if ENABLE_LINUX_CAPS
1563 @@ -255,6 +263,8 @@ g_process_set_user(const gchar *user)
1565 if (!process_opts.user)
1566 process_opts.user = user;
1572 @@ -268,6 +278,7 @@ g_process_set_group(const gchar *group)
1574 if (!process_opts.group)
1575 process_opts.group = group;
1580 @@ -666,35 +677,20 @@ g_process_change_root(void)
1582 g_process_change_user(void)
1587 #if ENABLE_LINUX_CAPS
1588 if (process_opts.caps)
1589 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
1592 - if (process_opts.user && !resolve_user(process_opts.user, &uid))
1594 - g_process_message("Error resolving user; user='%s'", process_opts.user);
1598 - if (process_opts.group && !resolve_group(process_opts.group, &gid))
1600 - g_process_message("Error resolving group; group='%s'", process_opts.group);
1604 - if ((gint) gid != -1)
1605 + if ((gint) process_opts.gid != -1)
1607 - if (setgid(gid) < 0)
1608 + if (setgid(process_opts.gid) < 0)
1610 - g_process_message("Error in setgid(); group='%s', error='%s'", process_opts.group, g_strerror(errno));
1611 + g_process_message("Error in setgid(); group='%s', gid='%d', error='%s'", process_opts.group, (gint) process_opts.gid, g_strerror(errno));
1615 - if (process_opts.user && initgroups(process_opts.user, gid) < 0)
1616 + if (process_opts.user && initgroups(process_opts.user, process_opts.gid) < 0)
1618 g_process_message("Error in initgroups(); user='%s', error='%s'", process_opts.user, g_strerror(errno));
1620 @@ -702,11 +698,11 @@ g_process_change_user(void)
1624 - if ((gint) uid != -1)
1625 + if ((gint) process_opts.uid != -1)
1627 - if (setuid(uid) < 0)
1628 + if (setuid(process_opts.uid) < 0)
1630 - g_process_message("Error in setuid(); user='%s', error='%s'", process_opts.user, g_strerror(errno));
1631 + g_process_message("Error in setuid(); user='%s', uid='%d', error='%s'", process_opts.user, (gint) process_opts.uid, g_strerror(errno));
1635 @@ -763,6 +759,21 @@ g_process_change_caps(void)
1640 +g_process_resolve_names(void)
1642 + if (process_opts.user && !resolve_user(process_opts.user, &process_opts.uid))
1644 + g_process_message("Error resolving user; user='%s'", process_opts.user);
1645 + process_opts.uid = (uid_t) -1;
1647 + if (process_opts.group && !resolve_group(process_opts.group, &process_opts.gid))
1649 + g_process_message("Error resolving group; group='%s'", process_opts.group);
1650 + process_opts.gid = (gid_t) -1;
1655 * g_process_change_dir:
1657 @@ -1116,6 +1127,7 @@ g_process_start(void)
1659 g_process_detach_tty();
1660 g_process_change_limits();
1661 + g_process_resolve_names();
1663 if (process_opts.mode == G_PM_BACKGROUND)
1665 diff --git a/src/logmsg.c b/src/logmsg.c
1666 index 9bad35f..d7f7558 100644
1669 @@ -264,6 +264,10 @@ log_msg_get_value(LogMessage *self, const gchar *value_name, gssize *length)
1674 + * NOTE: the new_value is taken as a reference, e.g. it'll be assigned to
1675 + * the LogMessage and freed later on.
1678 log_msg_set_value(LogMessage *self, const gchar *value_name, gchar *new_value, gssize length)
1680 @@ -1065,7 +1069,7 @@ log_msg_parse_version(LogMessage *self, const guchar **data, gint *length)
1684 -log_msg_parse_legacy_program_name(LogMessage *self, const guchar **data, gint *length)
1685 +log_msg_parse_legacy_program_name(LogMessage *self, const guchar **data, gint *length, guint flags)
1687 /* the data pointer will not change */
1688 const guchar *src, *prog_start;
1689 @@ -1110,6 +1114,11 @@ log_msg_parse_legacy_program_name(LogMessage *self, const guchar **data, gint *l
1693 + if (flags & LP_STORE_LEGACY_MSGHDR)
1695 + log_msg_set_value(self, "LEGACY_MSGHDR", g_strndup((gchar *) *data, *length - left), *length - left);
1696 + self->flags |= LF_LEGACY_MSGHDR;
1701 @@ -1573,7 +1582,7 @@ log_msg_parse_legacy(LogMessage *self, const guchar *data, gint length, guint fl
1702 log_msg_parse_skip_chars(self, &src, &left, " ", -1);
1704 /* Try to extract a program name */
1705 - log_msg_parse_legacy_program_name(self, &src, &left);
1706 + log_msg_parse_legacy_program_name(self, &src, &left, flags);
1709 /* If we did manage to find a hostname, store it. */
1710 @@ -1598,7 +1607,7 @@ log_msg_parse_legacy(LogMessage *self, const guchar *data, gint length, guint fl
1713 /* Capture the program name */
1714 - log_msg_parse_legacy_program_name(self, &src, &left);
1715 + log_msg_parse_legacy_program_name(self, &src, &left, flags);
1717 self->timestamps[LM_TS_STAMP] = self->timestamps[LM_TS_RECVD];
1719 @@ -1607,7 +1616,7 @@ log_msg_parse_legacy(LogMessage *self, const guchar *data, gint length, guint fl
1720 self->message_len = left;
1721 if ((flags & LP_VALIDATE_UTF8) && g_utf8_validate((gchar *) src, left, NULL))
1722 self->flags |= LF_UTF8;
1728 diff --git a/src/logmsg.h b/src/logmsg.h
1729 index 17d4b5c..6e0a9be 100644
1733 #define LP_ASSUME_UTF8 0x0080
1734 #define LP_VALIDATE_UTF8 0x0100
1735 #define LP_NO_MULTI_LINE 0x0200
1736 +#define LP_STORE_LEGACY_MSGHDR 0x0400
1739 typedef struct _LogPathOptions LogPathOptions;
1740 @@ -97,6 +98,13 @@ enum
1741 LF_OWN_MATCHES = 0x4000,
1742 LF_OWN_ALL = 0x7FF0,
1743 LF_CHAINED_HOSTNAME = 0x8000,
1745 + /* originally parsed from RFC 3164 format and the legacy message header
1746 + * was saved in $LEGACY_MSGHDR. This flag is a hack to avoid a hash lookup
1747 + * in the fast path and indicates that the parser has saved the legacy
1748 + * message header intact in a value named LEGACY_MSGHDR.
1750 + LF_LEGACY_MSGHDR = 0x00010000,
1753 typedef struct _LogMessageSDParam LogMessageSDParam;
1754 @@ -129,12 +137,25 @@ typedef struct _LogMessageMatch
1759 +#if GLIB_SIZEOF_VOID_P == 4
1764 + guint8 builtin_value;
1766 +#elif GLIB_SIZEOF_VOID_P == 8
1769 guint8 builtin_value;
1774 +#error "Unknown pointer size"
1780 @@ -156,9 +177,10 @@ struct _LogMessage
1787 guint32 message_len;
1789 + /* 6 bytes hole */
1791 LogStamp timestamps[LM_TS_MAX];
1793 diff --git a/src/logproto.c b/src/logproto.c
1794 index b2c30ee..9d7187b 100644
1795 --- a/src/logproto.c
1796 +++ b/src/logproto.c
1799 log_proto_set_encoding(LogProto *self, const gchar *encoding)
1801 - self->convert = g_iconv_open("utf-8", encoding);
1802 if (self->convert != (GIConv) -1)
1805 + g_iconv_close(self->convert);
1806 + self->convert = (GIConv) -1;
1808 + if (self->encoding)
1810 + g_free(self->encoding);
1811 + self->encoding = NULL;
1814 + self->convert = g_iconv_open("utf-8", encoding);
1815 + if (self->convert == (GIConv) -1)
1818 + self->encoding = g_strdup(encoding);
1822 @@ -23,6 +34,8 @@ log_proto_free(LogProto *s)
1824 if (s->convert != (GIConv) -1)
1825 g_iconv_close(s->convert);
1827 + g_free(s->encoding);
1828 log_transport_free(s->transport);
1831 @@ -159,6 +172,8 @@ struct _LogProtoPlainServer
1832 gsize buffer_size, buffer_end, buffer_pos;
1833 gsize padding_size, max_msg_size;
1834 GSockAddr *prev_saddr;
1835 + gchar raw_buffer_leftover[8];
1836 + gint raw_buffer_leftover_size;
1837 LogProtoStatus status;
1840 @@ -487,7 +502,8 @@ log_proto_plain_server_fetch(LogProto *s, const guchar **msg, gsize *msg_len, GS
1841 /* if conversion is needed, we first read into an on-stack
1842 * buffer, and then convert it into our internal buffer */
1844 - raw_buffer = g_alloca(self->max_msg_size);
1845 + raw_buffer = g_alloca(self->max_msg_size + self->raw_buffer_leftover_size);
1846 + memcpy(raw_buffer, self->raw_buffer_leftover, self->raw_buffer_leftover_size);
1847 if (!self->padding_size)
1849 avail = self->max_msg_size;
1850 @@ -499,7 +515,7 @@ log_proto_plain_server_fetch(LogProto *s, const guchar **msg, gsize *msg_len, GS
1854 - rc = log_transport_read(self->super.transport, raw_buffer, avail, sa);
1855 + rc = log_transport_read(self->super.transport, raw_buffer + self->raw_buffer_leftover_size, avail, sa);
1857 self->prev_saddr = *sa;
1859 @@ -534,6 +550,13 @@ log_proto_plain_server_fetch(LogProto *s, const guchar **msg, gsize *msg_len, GS
1860 msg_verbose("EOF occurred while reading",
1861 evt_tag_int(EVT_TAG_FD, self->super.transport->fd),
1863 + if (self->raw_buffer_leftover_size > 0)
1865 + msg_error("EOF read on a channel with leftovers from previous character conversion, dropping input",
1867 + self->status = LPS_EOF;
1868 + return self->status;
1870 self->status = LPS_EOF;
1871 if (log_proto_plain_server_fetch_from_buf(self, msg, msg_len, TRUE))
1873 @@ -562,6 +585,9 @@ log_proto_plain_server_fetch(LogProto *s, const guchar **msg, gsize *msg_len, GS
1877 + rc += self->raw_buffer_leftover_size;
1878 + self->raw_buffer_leftover_size = 0;
1880 /* some data was read */
1881 if (self->super.convert != (GIConv) -1)
1883 @@ -581,22 +607,62 @@ log_proto_plain_server_fetch(LogProto *s, const guchar **msg, gsize *msg_len, GS
1887 - /* Incomplete text, do not report an error */
1888 + /* Incomplete text, do not report an error, rather try to read again */
1889 + self->buffer_end = self->buffer_size - avail_out;
1893 + if (avail_in > sizeof(self->raw_buffer_leftover))
1895 + msg_error("Invalid byte sequence, the remaining raw buffer is larger than the supported leftover size",
1896 + evt_tag_str("encoding", self->super.encoding),
1897 + evt_tag_int("avail_in", avail_in),
1898 + evt_tag_int("leftover_size", sizeof(self->raw_buffer_leftover)),
1900 + self->status = LPS_ERROR;
1901 + return self->status;
1903 + memcpy(self->raw_buffer_leftover, raw_buffer, avail_in);
1904 + self->raw_buffer_leftover_size = avail_in;
1905 + msg_debug("Leftover characters remained after conversion, delaying message until another chunk arrives",
1906 + evt_tag_str("encoding", self->super.encoding),
1907 + evt_tag_int("avail_in", avail_in),
1909 + return LPS_SUCCESS;
1914 self->buffer_end = self->buffer_size - avail_out;
1915 /* extend the buffer */
1916 - self->buffer_size *= 2;
1917 - self->buffer = g_realloc(self->buffer, self->buffer_size);
1919 - /* recalculate the out pointer, and add what we have now */
1921 + if (self->buffer_size < self->max_msg_size * 6)
1923 + self->buffer_size *= 2;
1924 + self->buffer = g_realloc(self->buffer, self->buffer_size);
1926 + /* recalculate the out pointer, and add what we have now */
1931 + msg_error("Incoming byte stream requires a too large conversion buffer, probably invalid character sequence",
1932 + evt_tag_str("encoding", self->super.encoding),
1933 + evt_tag_printf("buffer", "%.*s", self->buffer_end, self->buffer),
1935 + self->status = LPS_ERROR;
1936 + return self->status;
1941 - msg_error("Invalid byte sequence or other error while converting input",
1943 + msg_notice("Invalid byte sequence or other error while converting input, skipping character",
1944 + evt_tag_str("encoding", self->super.encoding),
1945 + evt_tag_printf("char", "0x%02x", *(guchar *) raw_buffer),
1947 + self->buffer_end = self->buffer_size - avail_out;
1953 diff --git a/src/logproto.h b/src/logproto.h
1954 index 8a03d75..f94e5df 100644
1955 --- a/src/logproto.h
1956 +++ b/src/logproto.h
1957 @@ -18,6 +18,7 @@ struct _LogProto
1959 LogTransport *transport;
1963 gboolean (*read_state)(LogProto *s, SerializeArchive *archive);
1964 gboolean (*write_state)(LogProto *s, SerializeArchive *archive);
1965 diff --git a/src/logreader.c b/src/logreader.c
1966 index f9567ff..ca800d0 100644
1967 --- a/src/logreader.c
1968 +++ b/src/logreader.c
1969 @@ -103,7 +103,7 @@ log_reader_fd_prepare(GSource *source,
1971 if (self->reader->flags & LR_FOLLOW)
1973 - *timeout = self->reader->options->follow_freq * 1000;
1974 + *timeout = self->reader->options->follow_freq;
1978 @@ -167,7 +167,7 @@ log_reader_fd_check(GSource *source)
1980 if (self->reader->follow_filename && stat(self->reader->follow_filename, &followed_st) != -1)
1982 - if (fd < 0 || st.st_ino != followed_st.st_ino)
1983 + if (fd < 0 || (st.st_ino != followed_st.st_ino && followed_st.st_size > 0))
1985 msg_trace("log_reader_fd_check file moved eof",
1986 evt_tag_int("pos", pos),
1987 @@ -278,6 +278,8 @@ log_reader_fetch_log(LogReader *self, LogProto *proto)
1988 parse_flags |= LP_VALIDATE_UTF8;
1989 if (self->options->options & LRO_NO_MULTI_LINE)
1990 parse_flags |= LP_NO_MULTI_LINE;
1991 + if (self->options->options & LRO_STORE_LEGACY_MSGHDR)
1992 + parse_flags |= LP_STORE_LEGACY_MSGHDR;
1994 if (self->waiting_for_preemption)
1996 @@ -321,7 +323,7 @@ log_reader_fetch_log(LogReader *self, LogProto *proto)
1997 /* no more messages for now */
2001 + if (msg_len > 0 || (self->options->options & LRO_EMPTY_LINES))
2005 @@ -772,6 +774,10 @@ log_reader_options_lookup_flag(const gchar *flag)
2006 return LRO_VALIDATE_UTF8;
2007 if (strcmp(flag, "no-multi-line") == 0 || strcmp(flag, "no_multi_line") == 0)
2008 return LRO_NO_MULTI_LINE;
2009 + if (strcmp(flag, "store-legacy-msghdr") == 0 || strcmp(flag, "store_legacy_msghdr") == 0)
2010 + return LRO_STORE_LEGACY_MSGHDR;
2011 + if (strcmp(flag, "empty-lines") == 0 || strcmp(flag, "empty_lines") == 0)
2012 + return LRO_EMPTY_LINES;
2013 msg_error("Unknown parse flag", evt_tag_str("flag", flag), NULL);
2016 diff --git a/src/logreader.h b/src/logreader.h
2017 index 8e5bc7c..11ff0da 100644
2018 --- a/src/logreader.h
2019 +++ b/src/logreader.h
2021 #define LRO_SYSLOG_PROTOCOL 0x0004
2022 #define LRO_VALIDATE_UTF8 0x0008
2023 #define LRO_NO_MULTI_LINE 0x0010
2024 +#define LRO_STORE_LEGACY_MSGHDR 0x0020
2025 +#define LRO_EMPTY_LINES 0x0040
2027 typedef struct _LogReaderWatch LogReaderWatch;
2029 @@ -77,7 +79,7 @@ typedef struct _LogReader
2030 GSockAddr *peer_addr;
2031 gchar *follow_filename;
2038 @@ -86,7 +88,7 @@ void log_reader_set_follow_filename(LogPipe *self, const gchar *follow_filename)
2039 void log_reader_set_peer_addr(LogPipe *s, GSockAddr *peer_addr);
2040 void log_reader_set_immediate_check(LogPipe *s);
2042 -void log_reader_update_pos(LogReader *self, off_t ofs);
2043 +void log_reader_update_pos(LogReader *self, gint64 ofs);
2044 void log_reader_save_state(LogReader *self, SerializeArchive *archive);
2045 void log_reader_restore_state(LogReader *self, SerializeArchive *archive);
2047 diff --git a/src/logwriter.c b/src/logwriter.c
2048 index bb01148..4d586e5 100644
2049 --- a/src/logwriter.c
2050 +++ b/src/logwriter.c
2051 @@ -236,7 +236,7 @@ log_writer_fd_dispatch(GSource *source,
2052 log_writer_broken(self->writer, NC_CLOSE);
2055 - else if (self->pollfd.revents & (G_IO_ERR))
2056 + else if (self->pollfd.revents & (G_IO_ERR) && num_elements == 0)
2058 msg_error("POLLERR occurred while idle",
2059 evt_tag_int("fd", log_proto_get_fd(self->proto)),
2060 @@ -595,9 +595,20 @@ log_writer_format_log(LogWriter *self, LogMessage *lm, GString *result)
2061 g_string_append_len(result, lm->host, lm->host_len);
2062 g_string_append_c(result, ' ');
2064 - g_string_append_len(result, lm->program, lm->program_len);
2065 - if (lm->program_len > 0)
2066 + if ((lm->flags & LF_LEGACY_MSGHDR))
2069 + const gchar *msghdr;
2071 + msghdr = log_msg_get_value(lm, "LEGACY_MSGHDR", &length);
2074 + g_string_append_len(result, msghdr, length);
2077 + else if (lm->program_len > 0)
2079 + g_string_append_len(result, lm->program, lm->program_len);
2080 if (lm->pid_len > 0)
2082 g_string_append_c(result, '[');
2083 diff --git a/src/main.c b/src/main.c
2084 index ba97f0c..f78dcc1 100644
2087 @@ -366,8 +366,6 @@ main(int argc, char *argv[])
2089 g_process_set_name("syslog-ng");
2091 -#if ENABLE_LINUX_CAPS
2093 /* in this case we switch users early while retaining a limited set of
2094 * credentials in order to initialize/reinitialize the configuration.
2096 @@ -381,27 +379,11 @@ main(int argc, char *argv[])
2100 - g_process_startup_ok();
2102 + g_process_startup_failed(0, TRUE);
2104 + g_process_startup_ok();
2108 - /* if Linux capabilities are not compiled in, the initial setup is
2109 - * performed as the root user, and then the switch to a limited user
2110 - * account is made. This is compatible how syslog-ng behaved before
2111 - * capability support.
2114 - rc = initial_init(&cfg);
2119 - g_process_start();
2120 - g_process_startup_ok();
2126 /* we are running as a non-root user from this point */
2128 @@ -424,6 +406,7 @@ main(int argc, char *argv[])
2132 + g_process_finish();
2136 diff --git a/src/memtrace.c b/src/memtrace.c
2137 index ef4729a..eb33f4f 100644
2138 --- a/src/memtrace.c
2139 +++ b/src/memtrace.c
2140 @@ -121,7 +121,7 @@ z_mem_trace_init(gchar *tracefile)
2141 for (i = 0; i < MEMTRACE_HASH_SIZE; i++)
2143 mem_trace_hash[i].list = -1;
2144 - memset(&mem_trace_hash[i].lock, 0, sizeof(GStaticMutex));
2145 + g_static_mutex_init(&mem_trace_hash[i].lock);
2147 old_malloc = dlsym(RTLD_NEXT, "malloc");
2148 old_free = dlsym(RTLD_NEXT, "free");
2149 diff --git a/src/misc.c b/src/misc.c
2150 index 96fcdd2..364ead6 100644
2153 @@ -274,7 +274,7 @@ resolve_user(const char *user, uid_t *uid)
2161 pw = getpwnam(user);
2162 @@ -299,7 +299,7 @@ resolve_group(const char *group, gid_t *gid)
2170 gr = getgrnam(group);
2171 diff --git a/src/sgroup.c b/src/sgroup.c
2172 index add7ac9..27e863f 100644
2177 #include "messages.h"
2179 +#include "afinter.h"
2182 +#include <string.h>
2185 log_source_group_init(LogPipe *s)
2186 diff --git a/src/templates.c b/src/templates.c
2187 index aee1f34..67b8217 100644
2188 --- a/src/templates.c
2189 +++ b/src/templates.c
2190 @@ -339,17 +339,33 @@ log_macro_expand(GString *result, gint id, guint32 flags, gint ts_format, TimeZo
2194 - /* message, complete with program name and pid */
2195 - result_append(result, msg->program, msg->program_len, !!(flags & LT_ESCAPE));
2196 - if (msg->program_len > 0)
2197 + if ((msg->flags & LF_LEGACY_MSGHDR))
2199 - if (msg->pid_len > 0)
2201 + const gchar *msghdr;
2203 + /* fast path for now, as most messages come from legacy devices */
2205 + msghdr = log_msg_get_value(msg, "LEGACY_MSGHDR", &length);
2208 - result_append(result, "[", 1, !!(flags & LT_ESCAPE));
2209 - result_append(result, msg->pid, msg->pid_len, !!(flags & LT_ESCAPE));
2210 - result_append(result, "]", 1, !!(flags & LT_ESCAPE));
2211 + result_append(result, msghdr, length, !!(flags & LT_ESCAPE));
2216 + /* message, complete with program name and pid */
2217 + result_append(result, msg->program, msg->program_len, !!(flags & LT_ESCAPE));
2218 + if (msg->program_len > 0)
2220 + if (msg->pid_len > 0)
2222 + result_append(result, "[", 1, !!(flags & LT_ESCAPE));
2223 + result_append(result, msg->pid, msg->pid_len, !!(flags & LT_ESCAPE));
2224 + result_append(result, "]", 1, !!(flags & LT_ESCAPE));
2226 + result_append(result, ": ", 2, !!(flags & LT_ESCAPE));
2228 - result_append(result, ": ", 2, !!(flags & LT_ESCAPE));
2232 @@ -433,6 +449,9 @@ log_macro_expand(GString *result, gint id, guint32 flags, gint ts_format, TimeZo
2235 zone_ofs = (zone_info != NULL ? time_zone_info_get_offset(zone_info, stamp->time.tv_sec) : stamp->zone_offset);
2236 + if (zone_ofs == -1)
2237 + zone_ofs = stamp->zone_offset;
2239 t = stamp->time.tv_sec + zone_ofs;
2240 tm = gmtime_r(&t, &tm_storage);
2242 @@ -506,9 +525,6 @@ log_macro_expand(GString *result, gint id, guint32 flags, gint ts_format, TimeZo
2249 g_assert_not_reached();
2252 @@ -634,6 +650,9 @@ log_template_compile(LogTemplate *self, GError **error)
2254 g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
2256 + if (self->compiled_template)
2262 @@ -754,7 +773,7 @@ log_template_append_format(LogTemplate *self, LogMessage *lm, guint flags, gint
2264 flags |= self->flags;
2266 - if (self->compiled_template == NULL && !log_template_compile(self, NULL))
2267 + if (!log_template_compile(self, NULL))
2270 for (p = self->compiled_template; p; p = g_list_next(p))
2271 diff --git a/src/tlscontext.c b/src/tlscontext.c
2272 index b22b546..c06ec88 100644
2273 --- a/src/tlscontext.c
2274 +++ b/src/tlscontext.c
2275 @@ -102,28 +102,41 @@ tls_session_verify_dn(X509_STORE_CTX *ctx)
2279 -tls_session_verify(int ok, X509_STORE_CTX *ctx)
2280 +tls_session_verify(TLSSession *self, int ok, X509_STORE_CTX *ctx)
2282 + /* untrusted means that we have to accept the certificate even if it is untrusted */
2283 + if (self->ctx->verify_mode & TVM_UNTRUSTED)
2286 + /* accept certificate if its fingerprint matches, again regardless whether x509 certificate validation was successful */
2287 if (tls_session_verify_fingerprint(ctx))
2288 - return 1; /* success */
2290 + msg_debug("Certificate accepted because its fingerprint is listed", NULL);
2294 + if (ok && ctx->error_depth != 0 && (ctx->current_cert->ex_flags & EXFLAG_CA) == 0)
2296 + msg_debug("Invalid certificate found in chain, basicConstraints.ca is unset in non-leaf certificate", NULL);
2297 + ctx->error = X509_V_ERR_INVALID_CA;
2301 + /* reject certificate if it is valid, but its DN is not trusted */
2302 if (ok && ctx->error_depth == 0 && !tls_session_verify_dn(ctx))
2304 + msg_debug("Certificate valid, but DN constraints were not met, rejecting", NULL);
2305 ctx->error = X509_V_ERR_CERT_UNTRUSTED;
2306 - return 0; /* fail */
2314 -tls_session_ignore_errors(int ok, X509_STORE_CTX *ctx)
2316 /* if the crl_dir is set in the configuration file but the directory is empty ignore this error */
2317 - if (ok == 0 && ctx->error == X509_V_ERR_UNABLE_TO_GET_CRL)
2321 + if (!ok && ctx->error == X509_V_ERR_UNABLE_TO_GET_CRL)
2323 + msg_notice("CRL directory is set but no CRLs found", NULL);
2331 @@ -132,10 +145,8 @@ tls_session_verify_callback(int ok, X509_STORE_CTX *ctx)
2332 SSL *ssl = X509_STORE_CTX_get_app_data(ctx);
2333 TLSSession *self = SSL_get_app_data(ssl);
2335 - ok = tls_session_verify(ok, ctx);
2336 + ok = tls_session_verify(self, ok, ctx);
2338 - ok = tls_session_ignore_errors(ok, ctx);
2340 tls_log_certificate_validation_progress(ok, ctx);
2342 if (self->verify_func)
2343 @@ -165,9 +176,6 @@ tls_session_set_verify(TLSSession *self, TLSSessionVerifyFunc verify_func, gpoin
2344 self->verify_func = verify_func;
2345 self->verify_data = verify_data;
2346 self->verify_data_destroy = verify_destroy;
2348 - SSL_set_app_data(self->ssl, self);
2349 - SSL_set_verify(self->ssl, SSL_get_verify_mode(self->ssl), tls_session_verify_callback);
2353 @@ -212,11 +220,13 @@ TLSSession *
2354 tls_context_setup_session(TLSContext *self)
2357 + TLSSession *session;
2362 gint verify_mode = 0;
2363 + gint verify_flags = X509_V_FLAG_POLICY_CHECK;
2365 if (self->mode == TM_CLIENT)
2366 self->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
2367 @@ -240,7 +250,9 @@ tls_context_setup_session(TLSContext *self)
2371 - X509_VERIFY_PARAM_set_flags(self->ssl_ctx->param, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
2372 + verify_flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL;
2374 + X509_VERIFY_PARAM_set_flags(self->ssl_ctx->param, verify_flags);
2376 switch (self->verify_mode)
2378 @@ -254,7 +266,7 @@ tls_context_setup_session(TLSContext *self)
2379 verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
2381 case TVM_REQUIRED | TVM_UNTRUSTED:
2382 - verify_mode = SSL_VERIFY_NONE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2383 + verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2385 case TVM_REQUIRED | TVM_TRUSTED:
2386 verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2387 @@ -263,7 +275,7 @@ tls_context_setup_session(TLSContext *self)
2388 g_assert_not_reached();
2391 - SSL_CTX_set_verify(self->ssl_ctx, verify_mode, NULL);
2392 + SSL_CTX_set_verify(self->ssl_ctx, verify_mode, tls_session_verify_callback);
2393 SSL_CTX_set_options(self->ssl_ctx, SSL_OP_NO_SSLv2);
2396 @@ -273,7 +285,10 @@ tls_context_setup_session(TLSContext *self)
2397 SSL_set_connect_state(ssl);
2399 SSL_set_accept_state(ssl);
2400 - return tls_session_new(ssl, self);
2402 + session = tls_session_new(ssl, self);
2403 + SSL_set_app_data(ssl, session);
2407 ssl_error = ERR_get_error();
2408 diff --git a/src/tlscontext.h b/src/tlscontext.h
2409 index ada8e18..568682d 100644
2410 --- a/src/tlscontext.h
2411 +++ b/src/tlscontext.h
2414 #include "syslog-ng.h"
2419 #include <openssl/ssl.h>
2421 @@ -69,6 +69,9 @@ gboolean tls_verify_certificate_name(X509 *cert, const gchar *hostname);
2425 +typedef struct _TLSContext TLSContext;
2426 +typedef struct _TLSSession TLSSession;
2428 #define tls_context_new(m)
2431 diff --git a/src/tlstransport.c b/src/tlstransport.c
2432 index 608a427..2f07625 100644
2433 --- a/src/tlstransport.c
2434 +++ b/src/tlstransport.c
2436 #include "tlstransport.h"
2440 #include "messages.h"
2442 #include <openssl/ssl.h>
2443 @@ -149,4 +151,4 @@ log_transport_tls_free_method(LogTransport *s)
2444 log_transport_free_method(s);
2449 diff --git a/tests/functional/func_test.py b/tests/functional/func_test.py
2450 index d7af8ff..ffd0fae 100755
2451 --- a/tests/functional/func_test.py
2452 +++ b/tests/functional/func_test.py
2455 import os, sys, signal, traceback, time, errno
2456 from socket import *
2461 @@ -39,12 +40,24 @@ class SocketSender(MessageSender):
2462 self.sock = socket(self.family, SOCK_STREAM)
2464 self.sock.connect(self.sock_name)
2465 + self.sock.setsockopt(SOL_SOCKET, SO_SNDTIMEO, struct.pack('ll', 3, 0))
2467 + self.sock.send('')
2469 def sendMessage(self, msg):
2470 line = '%s%s' % (msg, self.terminate_seq)
2471 if self.send_by_bytes:
2477 + if e[0] == errno.ENOBUFS:
2478 + print 'got ENOBUFS, sleeping...'
2482 + print "hmm... got an error to the 'send' call, maybe syslog-ng is not accepting messages?"
2487 @@ -59,6 +72,9 @@ class SocketSender(MessageSender):
2488 print 'got ENOBUFS, sleeping...'
2492 + print "hmm... got an error to the 'send' call, maybe syslog-ng is not accepting messages?"
2496 if self.family == AF_UNIX:
2497 diff --git a/tests/unit/test_logqueue.c b/tests/unit/test_logqueue.c
2498 index 6e9dd00..b27f08e 100644
2499 --- a/tests/unit/test_logqueue.c
2500 +++ b/tests/unit/test_logqueue.c
2501 @@ -115,6 +115,91 @@ testcase_zero_diskbuf_alternating_send_acks()
2507 +/* no synchronization between the feed/consume threads, therefore it does
2508 + * not succeed reliably. commented out for now, will fix at the next
2509 + * logqueue related threaded issue */
2511 +GStaticMutex threaded_lock = G_STATIC_MUTEX_INIT;
2514 +threaded_feed(gpointer st)
2516 + LogQueue *q = (LogQueue *) st;
2517 + char *msg_str = "<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép";
2519 + LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;
2522 + for (i = 0; i < 100000; i++)
2524 + msg = log_msg_new(msg_str, strlen(msg_str), g_sockaddr_inet_new("10.10.10.10", 1010), 0, NULL, -1);
2525 + log_msg_add_ack(msg, &path_options);
2526 + msg->ack_func = test_ack;
2528 + g_static_mutex_lock(&threaded_lock);
2529 + if (!log_queue_push_tail(q, msg, &path_options))
2531 + fprintf(stderr, "Queue unable to consume enough messages: %d\n", fed_messages);
2532 + return GUINT_TO_POINTER(1);
2534 + g_static_mutex_unlock(&threaded_lock);
2540 +threaded_consume(gpointer st)
2542 + LogQueue *q = (LogQueue *) st;
2544 + LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;
2548 + for (i = 0; i < 100000; i++)
2550 + g_static_mutex_lock(&threaded_lock);
2552 + success = log_queue_pop_head(q, &msg, &path_options, FALSE);
2553 + g_static_mutex_unlock(&threaded_lock);
2555 + g_assert(!success || (success && msg != NULL));
2558 + fprintf(stderr, "Queue didn't return enough messages: i=%d\n", i);
2559 + return GUINT_TO_POINTER(1);
2562 + log_msg_ack(msg, &path_options);
2563 + log_msg_unref(msg);
2570 +testcase_with_threads()
2573 + GThread *thread_feed, *thread_consume;
2576 + for (i = 0; i < 100; i++)
2578 + q = log_queue_new(100000, 0, 64);
2579 + thread_feed = g_thread_create(threaded_feed, q, TRUE, NULL);
2581 + thread_consume = g_thread_create(threaded_consume, q, TRUE, NULL);
2582 + g_thread_join(thread_feed);
2583 + g_thread_join(thread_consume);
2585 + log_queue_free(q);
2593 diff --git a/tests/unit/test_template.c b/tests/unit/test_template.c
2594 index 675b9d6..c499d8d 100644
2595 --- a/tests/unit/test_template.c
2596 +++ b/tests/unit/test_template.c
2597 @@ -18,9 +18,13 @@ testcase(LogMessage *msg, gchar *template, gchar *expected)
2600 GString *res = g_string_sized_new(128);
2601 + static TimeZoneInfo *tzinfo = NULL;
2604 + tzinfo = time_zone_info_new(NULL);
2606 templ = log_template_new("dummy", template);
2607 - log_template_format(templ, msg, LT_ESCAPE, TS_FMT_BSD, NULL, 3, 0, res);
2608 + log_template_format(templ, msg, LT_ESCAPE, TS_FMT_BSD, tzinfo, 3, 0, res);
2610 if (strcmp(res->str, expected) != 0)
2612 @@ -39,7 +43,7 @@ int
2613 main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED)
2616 - char *msg_str = "<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép";
2617 + char *msg_str = "<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]:árvíztűrőtükörfúrógép";
2621 @@ -172,6 +176,14 @@ main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED)
2622 testcase(msg, "$PID", "");
2625 + msg_str = "<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]:árvíztűrőtükörfúrógép";
2627 + msg = log_msg_new(msg_str, strlen(msg_str), g_sockaddr_inet_new("10.10.10.10", 1010), LP_STORE_LEGACY_MSGHDR, NULL, -1);
2629 + testcase(msg, "$LEGACY_MSGHDR", "syslog-ng[23323]:");
2630 + testcase(msg, "$MSGHDR", "syslog-ng[23323]:");
2631 + log_msg_unref(msg);
2633 msg_str = "<132>1 2006-10-29T01:59:59.156+01:00 mymachine evntslog 3535 ID47 [exampleSDID@0 iut=\"3\" eventSource=\"Application\" eventID=\"1011\"][examplePriority@0 class=\"high\"] BOMAn application event log entry...";
2634 msg = log_msg_new(msg_str, strlen(msg_str), g_sockaddr_inet_new("10.10.10.10", 1010), LP_SYSLOG_PROTOCOL, NULL, -1);
2636 diff --git a/tgz2build/rules b/tgz2build/rules
2637 index 57eb338..7f2c776 100644
2638 --- a/tgz2build/rules
2639 +++ b/tgz2build/rules
2640 @@ -3,7 +3,7 @@ STAMPDIR=tgz2build/stamps
2641 DOCDIR=$(PREFIX)/doc
2644 -CONFIGURE_OPTS := --prefix $(ZBS_PREFIX) --enable-ssl --enable-dynamic-linking --enable-sql --enable-spoof-source --disable-tcp-wrapper --disable-pcre --with-ld-library-path=$(ZBS_PREFIX)/lib
2645 +CONFIGURE_OPTS := --prefix $(ZBS_PREFIX) --enable-ssl --enable-dynamic-linking --enable-sql --enable-spoof-source --disable-tcp-wrapper --disable-pcre --with-ld-library-path=$(ZBS_PREFIX)/lib --with-pidfile-dir=$(ZBS_PREFIX)/var/run
2646 INSTALL:=./install-sh
2647 RPATH=-Wl,-R/opt/syslog-ng/lib