diff options
author | Michael Biebl <biebl@debian.org> | 2008-07-23 02:22:26 +0200 |
---|---|---|
committer | Michael Biebl <biebl@debian.org> | 2008-07-23 02:22:26 +0200 |
commit | a0a154c1e0b88afbe3cabc2a5a4d3a4523681576 (patch) | |
tree | 8ab4f9d7e06b45a9874c0d5ad25223de133ef206 /plugins | |
parent | 991c6cc7f1b1586b3fad07460503bb9f7a34ad07 (diff) | |
download | rsyslog-a0a154c1e0b88afbe3cabc2a5a4d3a4523681576.tar.gz |
Imported Upstream version 3.18.1upstream/3.18.1
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/imfile/imfile.c | 5 | ||||
-rw-r--r-- | plugins/imklog/Makefile.am | 12 | ||||
-rw-r--r-- | plugins/imklog/Makefile.in | 34 | ||||
-rw-r--r-- | plugins/imklog/bsd.c | 181 | ||||
-rw-r--r-- | plugins/imklog/imklog.c | 683 | ||||
-rw-r--r-- | plugins/imklog/imklog.h | 32 | ||||
-rw-r--r-- | plugins/imklog/ksym.c | 113 | ||||
-rw-r--r-- | plugins/imklog/ksym_mod.c | 12 | ||||
-rw-r--r-- | plugins/imklog/linux.c | 544 | ||||
-rw-r--r-- | plugins/immark/immark.c | 2 | ||||
-rw-r--r-- | plugins/imuxsock/imuxsock.c | 2 | ||||
-rw-r--r-- | plugins/omgssapi/omgssapi.c | 38 | ||||
-rw-r--r-- | plugins/ommail/Makefile.am | 6 | ||||
-rw-r--r-- | plugins/ommail/Makefile.in | 494 | ||||
-rw-r--r-- | plugins/ommail/ommail.c | 630 | ||||
-rw-r--r-- | plugins/omrelp/omrelp.c | 12 |
16 files changed, 2148 insertions, 652 deletions
diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 162cab9..75e54f0 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -95,7 +95,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); - MsgSetHOSTNAME(pMsg, LocalHostName); + MsgSetHOSTNAME(pMsg, (char*)LocalHostName); MsgSetTAG(pMsg, (char*)pInfo->pszTag); pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); @@ -379,6 +379,9 @@ ENDafterRun */ BEGINmodExit CODESTARTmodExit + /* release objects we used */ + objRelease(datetime, CORE_COMPONENT); + objRelease(errmsg, CORE_COMPONENT); ENDmodExit diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am index 11e0096..246b330 100644 --- a/plugins/imklog/Makefile.am +++ b/plugins/imklog/Makefile.am @@ -1,6 +1,16 @@ pkglib_LTLIBRARIES = imklog.la -imklog_la_SOURCES = imklog.c imklog.h module.h ksym.c ksyms.h ksym_mod.c +imklog_la_SOURCES = imklog.c imklog.h + +# select klog "driver" +if ENABLE_IMKLOG_BSD +imklog_la_SOURCES += bsd.c +endif + +if ENABLE_IMKLOG_LINUX +imklog_la_SOURCES += linux.c module.h ksym.c ksyms.h ksym_mod.c +endif + imklog_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) imklog_la_LDFLAGS = -module -avoid-version imklog_la_LIBADD = diff --git a/plugins/imklog/Makefile.in b/plugins/imklog/Makefile.in index 3e7802e..08134db 100644 --- a/plugins/imklog/Makefile.in +++ b/plugins/imklog/Makefile.in @@ -32,6 +32,10 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ + +# select klog "driver" +@ENABLE_IMKLOG_BSD_TRUE@am__append_1 = bsd.c +@ENABLE_IMKLOG_LINUX_TRUE@am__append_2 = linux.c module.h ksym.c ksyms.h ksym_mod.c subdir = plugins/imklog DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -51,8 +55,14 @@ am__installdirs = "$(DESTDIR)$(pkglibdir)" pkglibLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(pkglib_LTLIBRARIES) imklog_la_DEPENDENCIES = -am_imklog_la_OBJECTS = imklog_la-imklog.lo imklog_la-ksym.lo \ - imklog_la-ksym_mod.lo +am__imklog_la_SOURCES_DIST = imklog.c imklog.h bsd.c linux.c module.h \ + ksym.c ksyms.h ksym_mod.c +@ENABLE_IMKLOG_BSD_TRUE@am__objects_1 = imklog_la-bsd.lo +@ENABLE_IMKLOG_LINUX_TRUE@am__objects_2 = imklog_la-linux.lo \ +@ENABLE_IMKLOG_LINUX_TRUE@ imklog_la-ksym.lo \ +@ENABLE_IMKLOG_LINUX_TRUE@ imklog_la-ksym_mod.lo +am_imklog_la_OBJECTS = imklog_la-imklog.lo $(am__objects_1) \ + $(am__objects_2) imklog_la_OBJECTS = $(am_imklog_la_OBJECTS) imklog_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -70,7 +80,7 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(imklog_la_SOURCES) -DIST_SOURCES = $(imklog_la_SOURCES) +DIST_SOURCES = $(am__imklog_la_SOURCES_DIST) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -202,7 +212,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ zlib_libs = @zlib_libs@ pkglib_LTLIBRARIES = imklog.la -imklog_la_SOURCES = imklog.c imklog.h module.h ksym.c ksyms.h ksym_mod.c +imklog_la_SOURCES = imklog.c imklog.h $(am__append_1) $(am__append_2) imklog_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) imklog_la_LDFLAGS = -module -avoid-version imklog_la_LIBADD = @@ -275,9 +285,11 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imklog_la-bsd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imklog_la-imklog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imklog_la-ksym.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imklog_la-ksym_mod.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imklog_la-linux.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -307,6 +319,20 @@ imklog_la-imklog.lo: imklog.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imklog_la-imklog.lo `test -f 'imklog.c' || echo '$(srcdir)/'`imklog.c +imklog_la-bsd.lo: bsd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imklog_la-bsd.lo -MD -MP -MF $(DEPDIR)/imklog_la-bsd.Tpo -c -o imklog_la-bsd.lo `test -f 'bsd.c' || echo '$(srcdir)/'`bsd.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/imklog_la-bsd.Tpo $(DEPDIR)/imklog_la-bsd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bsd.c' object='imklog_la-bsd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imklog_la-bsd.lo `test -f 'bsd.c' || echo '$(srcdir)/'`bsd.c + +imklog_la-linux.lo: linux.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imklog_la-linux.lo -MD -MP -MF $(DEPDIR)/imklog_la-linux.Tpo -c -o imklog_la-linux.lo `test -f 'linux.c' || echo '$(srcdir)/'`linux.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/imklog_la-linux.Tpo $(DEPDIR)/imklog_la-linux.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='linux.c' object='imklog_la-linux.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imklog_la-linux.lo `test -f 'linux.c' || echo '$(srcdir)/'`linux.c + imklog_la-ksym.lo: ksym.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imklog_la-ksym.lo -MD -MP -MF $(DEPDIR)/imklog_la-ksym.Tpo -c -o imklog_la-ksym.lo `test -f 'ksym.c' || echo '$(srcdir)/'`ksym.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/imklog_la-ksym.Tpo $(DEPDIR)/imklog_la-ksym.Plo diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c new file mode 100644 index 0000000..39b644c --- /dev/null +++ b/plugins/imklog/bsd.c @@ -0,0 +1,181 @@ +/* klog for BSD, based on the FreeBSD syslogd implementation. + * + * This contains OS-specific functionality to read the BSD + * kernel log. For a general overview, see head comment in + * imklog.c. + * + * Copyright (C) 2008 by Rainer Gerhards for the modifications of + * the original FreeBSD sources. + * + * I would like to express my gratitude to those folks which + * layed an important foundation for rsyslog to build on. + * + * This file is part of rsyslog. + * + * Rsyslog is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Rsyslog is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + * + * This file is based on earlier work included in the FreeBSD sources. We + * integrated it into the rsyslog project. The copyright below applies, and + * I also reproduce the original license under which we aquired the code: + * + * Copyright (c) 1983, 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * If you would like to use the code under the BSD license, you should + * aquire your own copy of BSD's syslogd, from which we have taken it. The + * code in this file is modified and may only be used under the terms of + * the GPLv3+ as specified above. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> + +#include "rsyslog.h" +#include "imklog.h" + +/* globals */ +static int fklog = -1; /* /dev/klog */ + +#ifndef _PATH_KLOG +# define _PATH_KLOG "/dev/klog" +#endif + +/* open the kernel log - will be called inside the willRun() imklog + * entry point. -- rgerhards, 2008-04-09 + */ +rsRetVal +klogWillRun(void) +{ + DEFiRet; + + fklog = open(_PATH_KLOG, O_RDONLY, 0); + if (fklog < 0) { + dbgprintf("can't open %s (%d)\n", _PATH_KLOG, errno); + iRet = RS_RET_ERR; // TODO: better error code + } + + RETiRet; +} + + +/* Read /dev/klog while data are available, split into lines. + * Contrary to standard BSD syslogd, we do a blocking read. We can + * afford this as imklog is running on its own threads. So if we have + * a single file, it really doesn't matter if we wait inside a 1-file + * select or the read() directly. + */ +static void +readklog(void) +{ + char *p, *q, line[MAXLINE + 1]; + int len, i; + + len = 0; + for (;;) { + dbgprintf("----------imklog waiting for kernel log line\n"); + i = read(fklog, line + len, MAXLINE - 1 - len); + if (i > 0) { + line[i + len] = '\0'; + } else { + if (i < 0 && errno != EINTR && errno != EAGAIN) { + imklogLogIntMsg(LOG_ERR, + "imklog error %d reading kernel log - shutting down imklog", + errno); + fklog = -1; + } + break; + } + + for (p = line; (q = strchr(p, '\n')) != NULL; p = q + 1) { + *q = '\0'; + Syslog(LOG_INFO, (uchar*) p); + } + len = strlen(p); + if (len >= MAXLINE - 1) { + Syslog(LOG_INFO, (uchar*)p); + len = 0; + } + if (len > 0) + memmove(line, p, len + 1); + } + if (len > 0) + Syslog(LOG_INFO, (uchar*)line); +} + + +/* to be called in the module's AfterRun entry point + * rgerhards, 2008-04-09 + */ +rsRetVal klogAfterRun(void) +{ + DEFiRet; + if(fklog != -1) + close(fklog); + RETiRet; +} + + + +/* to be called in the module's WillRun entry point, this is the main + * "message pull" mechanism. + * rgerhards, 2008-04-09 + */ +rsRetVal klogLogKMsg(void) +{ + DEFiRet; + readklog(); + RETiRet; +} + + +/* provide the (system-specific) default facility for internal messages + * rgerhards, 2008-04-14 + */ +int +klogFacilIntMsg(void) +{ + return LOG_SYSLOG; +} diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index bfea8c6..f7aee5b 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -1,14 +1,24 @@ -/* The kernel log input module for Linux. This file heavily - * borrows from the klogd daemon provided by the sysklogd project. - * Many thanks for this piece of software. +/* The kernel log module. + * + * This is an abstracted module. As Linux and BSD kernel log is conceptually the + * same, we do not do different input plugins for them but use + * imklog in both cases, just with different "backend drivers" for + * the different platforms. This also enables a rsyslog.conf to + * be used on multiple platforms without the need to take care of + * what the kernel log is coming from. + * + * See platform-specific files (e.g. linux.c, bsd.c) in the plugin's + * working directory. For other systems with similar kernel logging + * functionality, no new input plugin shall be written but rather a + * driver be developed for imklog. Please note that imklog itself is + * mostly concerned with handling the interface. Any real action happens + * in the drivers, as things may be pretty different on different + * platforms. * * Please note that this file replaces the klogd daemon that was * also present in pre-v3 versions of rsyslog. * - * I have begun to convert this to an input module on 2007-12-17. - * IMPORTANT: more than a single instance is currently not supported. This - * needs to be revisited once the config file and input module interface - * supports multiple instances! + * Copyright (C) 2008 by Rainer Gerhards and Adiscon GmbH * * This file is part of rsyslog. * @@ -29,559 +39,158 @@ */ #include "config.h" #include "rsyslog.h" -#include <stdlib.h> #include <stdio.h> #include <assert.h> -#include <signal.h> #include <string.h> -#include <pthread.h> +#include <stdarg.h> +#include <ctype.h> + #include "syslogd.h" #include "cfsysline.h" -#include "template.h" +#include "obj.h" #include "msg.h" #include "module-template.h" +#include "datetime.h" #include "imklog.h" MODULE_TYPE_INPUT /* Module static data */ DEF_IMOD_STATIC_DATA +DEFobjCurrIf(datetime) /* configuration settings TODO: move to instance data? */ int dbgPrintSymbols = 0; /* this one is extern so the helpers can access it! */ -static int symbols_twice = 0; -static int use_syscall = 0; -static int symbol_lookup = 1; +int symbols_twice = 0; +int use_syscall = 0; +int symbol_lookup = 0; /* on recent kernels > 2.6, the kernel does this */ +int bPermitNonKernel = 0; /* permit logging of messages not having LOG_KERN facility */ +int iFacilIntMsg; /* the facility to use for internal messages (set by driver) */ /* TODO: configuration for the following directives must be implemented. It * was not done yet because we either do not yet have a config handler for * that type or I thought it was acceptable to push it to a later stage when * I gained more handson experience with the input module interface (and the * changes resulting from that). -- rgerhards, 2007-12-20 */ -static char *symfile = NULL; -static int console_log_level = -1; - - -/* Includes. */ -#include <unistd.h> -#include <errno.h> -#include <sys/fcntl.h> -#include <sys/stat.h> - -#if HAVE_TIME_H -# include <time.h> -#endif - -#include <stdarg.h> -#include <paths.h> -#include "ksyms.h" - -#define __LIBRARY__ -#include <unistd.h> - - -#if !defined(__GLIBC__) -# define __NR_ksyslog __NR_syslog -_syscall3(int,ksyslog,int, type, char *, buf, int, len); -#else -#include <sys/klog.h> -#define ksyslog klogctl -#endif - - - -#ifndef _PATH_KLOG -#define _PATH_KLOG "/proc/kmsg" -#endif - -#define LOG_BUFFER_SIZE 4096 -#define LOG_LINE_LENGTH 1000 - -static int kmsg; -static char log_buffer[LOG_BUFFER_SIZE]; - -static enum LOGSRC {none, proc, kernel} logsrc; - +char *symfile = NULL; +int console_log_level = -1; -/* Function prototypes. */ -extern int ksyslog(int type, char *buf, int len); - - -/* Write a message to the message queue. - * returns -1 if it fails, something else otherwise +/* enqueue the the kernel message into the message queue. + * The provided msg string is not freed - thus must be done + * by the caller. + * rgerhards, 2008-04-12 */ -static rsRetVal writeSyslogV(int iPRI, const char *szFmt, va_list va) +static rsRetVal +enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity) { DEFiRet; - int iChars; - int iLen; - time_t tNow; - char msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */ - - assert(szFmt != NULL); - - /* build the message */ - time(&tNow); - /* we can use sprintf safely below, because we know the size of the constants. - * By doing so, we save some cpu cycles and code complexity (for unnecessary - * error checking). - */ - iLen = sprintf(msgBuf, "<%d>%.15s kernel: ", iPRI, ctime(&tNow) + 4); - - iChars = vsnprintf(msgBuf + iLen, sizeof(msgBuf) / sizeof(char) - iLen, szFmt, va); - - /* here we must create our message object and supply it to the message queue - */ - CHKiRet(parseAndSubmitMessage(LocalHostName, msgBuf, strlen(msgBuf), MSG_DONT_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY)); + msg_t *pMsg; + + assert(msg != NULL); + assert(pszTag != NULL); + + CHKiRet(msgConstruct(&pMsg)); + MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); + MsgSetUxTradMsg(pMsg, (char*)msg); + MsgSetRawMsg(pMsg, (char*)msg); + MsgSetMSG(pMsg, (char*)msg); + MsgSetHOSTNAME(pMsg, (char*)LocalHostName); + MsgSetTAG(pMsg, (char*)pszTag); + pMsg->iFacility = LOG_FAC(iFacility); + pMsg->iSeverity = LOG_PRI(iSeverity); + pMsg->bParseHOSTNAME = 0; + datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */ + CHKiRet(submitMsg(pMsg)); finalize_it: RETiRet; } -/* And now the same with variable arguments */ -static int writeSyslog(int iPRI, const char *szFmt, ...) -{ - int iRet; - va_list va; - - assert(szFmt != NULL); - va_start(va, szFmt); - iRet = writeSyslogV(iPRI, szFmt, va); - va_end(va); - - return(iRet); -} - -rsRetVal Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3))); -rsRetVal Syslog(int priority, char *fmt, ...) +/* parse the PRI from a kernel message. At least BSD seems to have + * non-kernel messages inside the kernel log... + * Expected format: "<pri>". piPri is only valid if the function + * successfully returns. If there was a proper pri ppSz is advanced to the + * position right after ">". + * rgerhards, 2008-04-14 + */ +static rsRetVal +parsePRI(uchar **ppSz, int *piPri) { DEFiRet; - va_list ap; - char *argl; - - /* Output using syslog. */ - if (!strcmp(fmt, "%s")) { - va_start(ap, fmt); - argl = va_arg(ap, char *); - if (argl[0] == '<' && argl[1] && argl[2] == '>') { - switch ( argl[1] ) - { - case '0': - priority = LOG_EMERG; - break; - case '1': - priority = LOG_ALERT; - break; - case '2': - priority = LOG_CRIT; - break; - case '3': - priority = LOG_ERR; - break; - case '4': - priority = LOG_WARNING; - break; - case '5': - priority = LOG_NOTICE; - break; - case '6': - priority = LOG_INFO; - break; - case '7': - default: - priority = LOG_DEBUG; - } - argl += 3; - } - iRet = writeSyslog(priority, fmt, argl); - va_end(ap); - } else { - va_start(ap, fmt); - iRet = writeSyslogV(priority, fmt, ap); - va_end(ap); - } - - RETiRet; -} - - -static void CloseLogSrc(void) -{ - /* Turn on logging of messages to console, but only if we had the -c - * option -- rgerhards, 2007-08-01 - */ - if (console_log_level != -1) - ksyslog(7, NULL, 0); - - /* Shutdown the log sources. */ - switch ( logsrc ) - { - case kernel: - ksyslog(0, 0, 0); - Syslog(LOG_INFO, "Kernel logging (ksyslog) stopped."); - break; - case proc: - close(kmsg); - Syslog(LOG_INFO, "Kernel logging (proc) stopped."); - break; - case none: - break; - } + int i; + uchar *pSz; - return; -} + assert(ppSz != NULL); + pSz = *ppSz; + assert(pSz != NULL); + assert(piPri != NULL); + if(*pSz != '<' || !isdigit(*(pSz+1))) + ABORT_FINALIZE(RS_RET_INVALID_PRI); -static enum LOGSRC GetKernelLogSrc(void) -{ - auto struct stat sb; - - /* Set level of kernel console messaging.. */ - if ( (console_log_level != -1) && - (ksyslog(8, NULL, console_log_level) < 0) && - (errno == EINVAL) ) - { - /* - * An invalid arguement error probably indicates that - * a pre-0.14 kernel is being run. At this point we - * issue an error message and simply shut-off console - * logging completely. - */ - Syslog(LOG_WARNING, "Cannot set console log level - disabling " - "console output."); + ++pSz; + i = 0; + while(isdigit(*pSz)) { + i = i * 10 + *pSz++ - '0'; } - /* - * First do a stat to determine whether or not the proc based - * file system is available to get kernel messages from. - */ - if ( use_syscall || - ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) ) - { - /* Initialize kernel logging. */ - ksyslog(1, NULL, 0); - Syslog(LOG_INFO, "imklogd %s, log source = ksyslog " - "started.", VERSION); - return(kernel); - } + if(*pSz != '>') + ABORT_FINALIZE(RS_RET_INVALID_PRI); - if ( (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 ) - { - char sz[512]; - snprintf(sz, sizeof(sz), "imklog: Cannot open proc file system, %d - %s.\n", errno, strerror(errno)); - logmsgInternal(LOG_SYSLOG|LOG_ERR, sz, ADDDATE); - ksyslog(7, NULL, 0); /* TODO: check this, implement more */ - return(none); - } + /* OK, we have a valid PRI */ + *piPri = i; + *ppSz = pSz + 1; /* update msg ptr to position after PRI */ - Syslog(LOG_INFO, "imklog %s, log source = %s started.", \ - VERSION, _PATH_KLOG); - return(proc); +finalize_it: + RETiRet; } -/* Copy characters from ptr to line until a char in the delim - * string is encountered or until min( space, len ) chars have - * been copied. - * - * Returns the actual number of chars copied. +/* log an imklog-internal message + * rgerhards, 2008-04-14 */ -static int copyin( char *line, int space, - const char *ptr, int len, - const char *delim ) +rsRetVal imklogLogIntMsg(int priority, char *fmt, ...) { - auto int i; - auto int count; - - count = len < space ? len : space; + DEFiRet; + va_list ap; + uchar msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */ + uchar *pLogMsg; - for(i=0; i<count && !strchr(delim, *ptr); i++ ) { - *line++ = *ptr++; - } + va_start(ap, fmt); + vsnprintf((char*)msgBuf, sizeof(msgBuf) / sizeof(char), fmt, ap); + pLogMsg = msgBuf; + va_end(ap); - return(i); -} + iRet = enqMsg((uchar*)pLogMsg, (uchar*) ((iFacilIntMsg == LOG_KERN) ? "kernel:" : "imklog:"), + iFacilIntMsg, LOG_PRI(priority)); -/* - * Messages are separated by "\n". Messages longer than - * LOG_LINE_LENGTH are broken up. - * - * Kernel symbols show up in the input buffer as : "[<aaaaaa>]", - * where "aaaaaa" is the address. These are replaced with - * "[symbolname+offset/size]" in the output line - symbolname, - * offset, and size come from the kernel symbol table. - * - * If a kernel symbol happens to fall at the end of a message close - * in length to LOG_LINE_LENGTH, the symbol will not be expanded. - * (This should never happen, since the kernel should never generate - * messages that long. - * - * To preserve the original addresses, lines containing kernel symbols - * are output twice. Once with the symbols converted and again with the - * original text. Just in case somebody wants to run their own Oops - * analysis on the syslog, e.g. ksymoops. - */ -static void LogLine(char *ptr, int len) -{ - enum parse_state_enum { - PARSING_TEXT, - PARSING_SYMSTART, /* at < */ - PARSING_SYMBOL, - PARSING_SYMEND /* at ] */ - }; - - static char line_buff[LOG_LINE_LENGTH]; - - static char *line =line_buff; - static enum parse_state_enum parse_state = PARSING_TEXT; - static int space = sizeof(line_buff)-1; - - static char *sym_start; /* points at the '<' of a symbol */ - - auto int delta = 0; /* number of chars copied */ - auto int symbols_expanded = 0; /* 1 if symbols were expanded */ - auto int skip_symbol_lookup = 0; /* skip symbol lookup on this pass */ - auto char *save_ptr = ptr; /* save start of input line */ - auto int save_len = len; /* save length at start of input line */ - - while( len > 0 ) - { - if( space == 0 ) /* line buffer is full */ - { - /* - ** Line too long. Start a new line. - */ - *line = 0; /* force null terminator */ - - dbgprintf("Line buffer full:\n"); - dbgprintf("\tLine: %s\n", line); - - Syslog( LOG_INFO, "%s", line_buff ); - line = line_buff; - space = sizeof(line_buff)-1; - parse_state = PARSING_TEXT; - symbols_expanded = 0; - skip_symbol_lookup = 0; - save_ptr = ptr; - save_len = len; - } - - switch( parse_state ) - { - case PARSING_TEXT: - delta = copyin( line, space, ptr, len, "\n[" ); - line += delta; - ptr += delta; - space -= delta; - len -= delta; - - if( space == 0 || len == 0 ) - { - break; /* full line_buff or end of input buffer */ - } - - if( *ptr == '\0' ) /* zero byte */ - { - ptr++; /* skip zero byte */ - space -= 1; - len -= 1; - - break; - } - - if( *ptr == '\n' ) /* newline */ - { - ptr++; /* skip newline */ - space -= 1; - len -= 1; - - *line = 0; /* force null terminator */ - Syslog( LOG_INFO, "%s", line_buff ); - line = line_buff; - space = sizeof(line_buff)-1; - if (symbols_twice) { - if (symbols_expanded) { - /* reprint this line without symbol lookup */ - symbols_expanded = 0; - skip_symbol_lookup = 1; - ptr = save_ptr; - len = save_len; - } - else - { - skip_symbol_lookup = 0; - save_ptr = ptr; - save_len = len; - } - } - break; - } - if( *ptr == '[' ) /* possible kernel symbol */ - { - *line++ = *ptr++; - space -= 1; - len -= 1; - if (!skip_symbol_lookup) - parse_state = PARSING_SYMSTART; /* at < */ - break; - } - /* Now that line_buff is no longer fed to *printf as format - * string, '%'s are no longer "dangerous". - */ - break; - - case PARSING_SYMSTART: - if( *ptr != '<' ) - { - parse_state = PARSING_TEXT; /* not a symbol */ - break; - } - - /* - ** Save this character for now. If this turns out to - ** be a valid symbol, this char will be replaced later. - ** If not, we'll just leave it there. - */ - - sym_start = line; /* this will point at the '<' */ - - *line++ = *ptr++; - space -= 1; - len -= 1; - parse_state = PARSING_SYMBOL; /* symbol... */ - break; - - case PARSING_SYMBOL: - delta = copyin( line, space, ptr, len, ">\n[" ); - line += delta; - ptr += delta; - space -= delta; - len -= delta; - if( space == 0 || len == 0 ) - { - break; /* full line_buff or end of input buffer */ - } - if( *ptr != '>' ) - { - parse_state = PARSING_TEXT; - break; - } - - *line++ = *ptr++; /* copy the '>' */ - space -= 1; - len -= 1; - - parse_state = PARSING_SYMEND; - - break; - - case PARSING_SYMEND: - if( *ptr != ']' ) - { - parse_state = PARSING_TEXT; /* not a symbol */ - break; - } - - /* - ** It's really a symbol! Replace address with the - ** symbol text. - */ - { - auto int sym_space; - - unsigned long value; - auto struct symbol sym; - auto char *symbol; - - *(line-1) = 0; /* null terminate the address string */ - value = strtoul(sym_start+1, (char **) 0, 16); - *(line-1) = '>'; /* put back delim */ - - if ( !symbol_lookup || (symbol = LookupSymbol(value, &sym)) == (char *)0 ) - { - parse_state = PARSING_TEXT; - break; - } - - /* - ** verify there is room in the line buffer - */ - sym_space = space + ( line - sym_start ); - if( (unsigned) sym_space < strlen(symbol) + 30 ) /*(30 should be overkill)*/ - { - parse_state = PARSING_TEXT; /* not enough space */ - break; - } - - delta = sprintf( sym_start, "%s+%d/%d]", - symbol, sym.offset, sym.size ); - - space = sym_space + delta; - line = sym_start + delta; - symbols_expanded = 1; - } - ptr++; - len--; - parse_state = PARSING_TEXT; - break; - - default: /* Can't get here! */ - parse_state = PARSING_TEXT; - - } - } - - return; + RETiRet; } -static void LogKernelLine(void) +/* log a kernel message + * rgerhards, 2008-04-14 + */ +rsRetVal Syslog(int priority, uchar *pMsg) { - auto int rdcnt; + DEFiRet; + rsRetVal localRet; - /* - * Zero-fill the log buffer. This should cure a multitude of - * problems with klogd logging the tail end of the message buffer - * which will contain old messages. Then read the kernel log - * messages into this fresh buffer. - */ - memset(log_buffer, '\0', sizeof(log_buffer)); - if ( (rdcnt = ksyslog(2, log_buffer, sizeof(log_buffer)-1)) < 0 ) - { - char sz[512]; - if(errno == EINTR) - return; - snprintf(sz, sizeof(sz), "imklog: Error return from sys_sycall: %d - %s\n", errno, strerror(errno)); - logmsgInternal(LOG_SYSLOG|LOG_ERR, sz, ADDDATE); - } - else - LogLine(log_buffer, rdcnt); - return; -} + /* Output using syslog */ + localRet = parsePRI(&pMsg, &priority); + if(localRet != RS_RET_INVALID_PRI && localRet != RS_RET_OK) + FINALIZE; + /* if we don't get the pri, we use whatever we were supplied */ + /* ignore non-kernel messages if not permitted */ + if(bPermitNonKernel == 0 && LOG_FAC(priority) != LOG_KERN) + FINALIZE; /* silently ignore */ -static void LogProcLine(void) -{ - auto int rdcnt; + iRet = enqMsg((uchar*)pMsg, (uchar*) "kernel:", LOG_FAC(priority), LOG_PRI(priority)); - /* - * Zero-fill the log buffer. This should cure a multitude of - * problems with klogd logging the tail end of the message buffer - * which will contain old messages. Then read the kernel messages - * from the message pseudo-file into this fresh buffer. - */ - memset(log_buffer, '\0', sizeof(log_buffer)); - if ( (rdcnt = read(kmsg, log_buffer, sizeof(log_buffer)-1)) < 0 ) - { - if ( errno == EINTR ) - return; - Syslog(LOG_ERR, "Cannot read proc file system: %d - %s.", errno, strerror(errno)); - } - else - LogLine(log_buffer, rdcnt); - - return; +finalize_it: + RETiRet; } @@ -592,64 +201,32 @@ CODESTARTrunInput * right into the sleep below. */ while(!pThrd->bShallStop) { - /* we do not need to handle the RS_RET_TERMINATE_NOW case any - * special because we just need to terminate. This may be different - * if a cleanup is needed. But for now, we can just use CHKiRet(). - * rgerhards, 2007-12-17 + /* klogLogKMsg() waits for the next kernel message, obtains it + * and then submits it to the rsyslog main queue. + * rgerhards, 2008-04-09 */ - switch ( logsrc ) - { - case kernel: - LogKernelLine(); - break; - case proc: - LogProcLine(); - break; - case none: - /* TODO: We need to handle this case here somewhat more intelligent - * This is now at least partly done - code should never reach this point - * as willRun() already checked for the "none" status -- rgerhards, 2007-12-17 - */ - pause(); - break; - } + CHKiRet(klogLogKMsg()); } - RETiRet; +finalize_it: ENDrunInput BEGINwillRun - /* Initialize this module. If that fails, we tell the engine we don't like to run */ - /* Determine where kernel logging information is to come from. */ - logsrc = GetKernelLogSrc(); - if(logsrc == none) { - iRet = RS_RET_NO_KERNEL_LOGSRC; - } else { - if (symbol_lookup) { - symbol_lookup = (InitKsyms(symfile) == 1); - symbol_lookup |= InitMsyms(); - if (symbol_lookup == 0) { - Syslog(LOG_WARNING, "cannot find any symbols, turning off symbol lookups\n"); - } - } - } CODESTARTwillRun + iRet = klogWillRun(); ENDwillRun BEGINafterRun CODESTARTafterRun - /* cleanup here */ - if(logsrc != none) - CloseLogSrc(); - - DeinitKsyms(); - DeinitMsyms(); + iRet = klogAfterRun(); ENDafterRun BEGINmodExit CODESTARTmodExit + /* release objects we used */ + objRelease(datetime, CORE_COMPONENT); ENDmodExit @@ -664,7 +241,9 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a symbols_twice = 0; use_syscall = 0; symfile = NULL; - symbol_lookup = 1; + symbol_lookup = 0; + bPermitNonKernel = 0; + iFacilIntMsg = klogFacilIntMsg(); return RS_RET_OK; } @@ -672,17 +251,17 @@ BEGINmodInit() CODESTARTmodInit *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr + CHKiRet(objUse(datetime, CORE_COMPONENT)); + + iFacilIntMsg = klogFacilIntMsg(); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"debugprintkernelsymbols", 0, eCmdHdlrBinary, NULL, &dbgPrintSymbols, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbollookup", 0, eCmdHdlrBinary, NULL, &symbol_lookup, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbolstwice", 0, eCmdHdlrBinary, NULL, &symbols_twice, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogusesyscallinterface", 0, eCmdHdlrBinary, NULL, &use_syscall, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogpermitnonkernelfacility", 0, eCmdHdlrBinary, NULL, &bPermitNonKernel, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"kloginternalmsgfacility", 0, eCmdHdlrFacility, NULL, &iFacilIntMsg, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit -/* - * Local variables: - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - * vi:set ai: +/* vim:set ai: */ diff --git a/plugins/imklog/imklog.h b/plugins/imklog/imklog.h index 71525a7..a37ecc9 100644 --- a/plugins/imklog/imklog.h +++ b/plugins/imklog/imklog.h @@ -2,8 +2,10 @@ * These are the definitions for the klog message generation module. * * File begun on 2007-12-17 by RGerhards + * Major change: 2008-04-09: switched to a driver interface for + * several platforms * - * Copyright 2007 Rainer Gerhards and Adiscon GmbH. + * Copyright 2007-2008 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * @@ -28,9 +30,33 @@ #include "rsyslog.h" #include "syslogd.h" -/* global variables */ +/* interface to "drivers" + * the platform specific drivers must implement these entry points. Only one + * driver may be active at any given time, thus we simply rely on the linker + * to resolve the addresses. + * rgerhards, 2008-04-09 + */ +rsRetVal klogLogKMsg(void); +rsRetVal klogWillRun(void); +rsRetVal klogAfterRun(void); +int klogFacilIntMsg(void); + +/* the following data members may be accessed by the "drivers" + * I admit this is not the cleanest way to doing things, but I honestly + * believe it is appropriate for the job that needs to be done. + * rgerhards, 2008-04-09 + */ +extern int symbols_twice; +extern int use_syscall; +extern int symbol_lookup; +extern char *symfile; +extern int console_log_level; extern int dbgPrintSymbols; +/* the functions below may be called by the drivers */ +rsRetVal imklogLogIntMsg(int priority, char *fmt, ...) __attribute__((format(printf,2, 3))); +rsRetVal Syslog(int priority, uchar *msg); + /* prototypes */ extern int InitKsyms(char *); extern void DeinitKsyms(void); @@ -38,8 +64,6 @@ extern int InitMsyms(void); extern void DeinitMsyms(void); extern char * ExpandKadds(char *, char *); extern void SetParanoiaLevel(int); -extern void vsyslog(int pri, const char *fmt, va_list ap); -rsRetVal Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3))); #endif /* #ifndef IMKLOG_H_INCLUDED */ /* vi:set ai: diff --git a/plugins/imklog/ksym.c b/plugins/imklog/ksym.c index b7d5903..f636a7b 100644 --- a/plugins/imklog/ksym.c +++ b/plugins/imklog/ksym.c @@ -138,7 +138,7 @@ static char *system_maps[] = /* Function prototypes. */ -static char * FindSymbolFile(void); +static char *FindSymbolFile(void); static int AddSymbol(unsigned long, char*); static void FreeSymbols(void); static int CheckVersion(char *); @@ -173,38 +173,36 @@ extern int InitKsyms(char *mapfile) auto FILE *sym_file; + BEGINfunc /* Check and make sure that we are starting with a clean slate. */ if ( num_syms > 0 ) FreeSymbols(); - /* - * Search for and open the file containing the kernel symbols. - */ - if ( mapfile != (char *) 0 ) { - if ( (sym_file = fopen(mapfile, "r")) == (FILE *) 0 ) + /* Search for and open the file containing the kernel symbols. */ + if ( mapfile != NULL ) { + if ( (sym_file = fopen(mapfile, "r")) == NULL ) { - Syslog(LOG_WARNING, "Cannot open map file: %s.", mapfile); + imklogLogIntMsg(LOG_WARNING, "Cannot open map file: %s.", mapfile); return(0); } } else { - if ( (mapfile = FindSymbolFile()) == (char *) 0 ) { - Syslog(LOG_WARNING, "Cannot find map file."); + if ( (mapfile = FindSymbolFile()) == NULL ) { + imklogLogIntMsg(LOG_WARNING, "Cannot find map file."); dbgprintf("Cannot find map file.\n"); return(0); } - if ( (sym_file = fopen(mapfile, "r")) == (FILE *) 0 ) { - Syslog(LOG_WARNING, "Cannot open map file."); + if ( (sym_file = fopen(mapfile, "r")) == NULL ) { + imklogLogIntMsg(LOG_WARNING, "Cannot open map file."); dbgprintf("Cannot open map file.\n"); return(0); } } - /* - * Read the kernel symbol table file and add entries for each + /* Read the kernel symbol table file and add entries for each * line. I suspect that the use of fscanf is not really in vogue * but it was quick and dirty and IMHO suitable for fixed format * data such as this. If anybody doesn't agree with this please @@ -213,7 +211,7 @@ extern int InitKsyms(char *mapfile) */ while ( !feof(sym_file) ) { if ( fscanf(sym_file, "%lx %c %s\n", &address, &type, sym) != 3 ) { - Syslog(LOG_ERR, "Error in symbol table input (#1)."); + imklogLogIntMsg(LOG_ERR, "Error in symbol table input (#1)."); fclose(sym_file); return(0); } @@ -221,7 +219,7 @@ extern int InitKsyms(char *mapfile) dbgprintf("Address: %lx, Type: %c, Symbol: %s\n", address, type, sym); if ( AddSymbol(address, sym) == 0 ) { - Syslog(LOG_ERR, "Error adding symbol - %s.", sym); + imklogLogIntMsg(LOG_ERR, "Error adding symbol - %s.", sym); fclose(sym_file); return(0); } @@ -231,23 +229,24 @@ extern int InitKsyms(char *mapfile) } - Syslog(LOG_INFO, "Loaded %d symbols from %s.", num_syms, mapfile); + imklogLogIntMsg(LOG_INFO, "Loaded %d symbols from %s.", num_syms, mapfile); switch(version) { case -1: - Syslog(LOG_WARNING, "Symbols do not match kernel version."); + imklogLogIntMsg(LOG_WARNING, "Symbols do not match kernel version."); num_syms = 0; break; case 0: - Syslog(LOG_WARNING, "Cannot verify that symbols match kernel version."); + imklogLogIntMsg(LOG_WARNING, "Cannot verify that symbols match kernel version."); break; case 1: - Syslog(LOG_INFO, "Symbols match kernel version %s.", vstring); + imklogLogIntMsg(LOG_INFO, "Symbols match kernel version %s.", vstring); break; } fclose(sym_file); + ENDfunc return(1); } @@ -292,44 +291,42 @@ extern void DeinitKsyms(void) **************************************************************************/ static char *FindSymbolFile(void) { - auto char *file = (char *) 0, + auto char *file = NULL, **mf = system_maps; - auto struct utsname utsname; - static char symfile[100]; - - auto FILE *sym_file = (FILE *) 0; + static char mysymfile[100]; + auto FILE *sym_file = NULL; + BEGINfunc - if ( uname(&utsname) < 0 ) { - Syslog(LOG_ERR, "Cannot get kernel version information."); + if(uname(&utsname) < 0) { + imklogLogIntMsg(LOG_ERR, "Cannot get kernel version information."); return(0); } dbgprintf("Searching for symbol map.\n"); - for(mf = system_maps; *mf != (char *) 0 && file == (char *) 0; ++mf) { - - snprintf(symfile, sizeof(symfile), "%s-%s", *mf, utsname.release); - dbgprintf("Trying %s.\n", symfile); - if ( (sym_file = fopen(symfile, "r")) != (FILE *) 0 ) { - if (CheckMapVersion(symfile) == 1) - file = symfile; + for(mf = system_maps; *mf != NULL && file == NULL; ++mf) { + snprintf(mysymfile, sizeof(mysymfile), "%s-%s", *mf, utsname.release); + dbgprintf("Trying %s.\n", mysymfile); + if((sym_file = fopen(mysymfile, "r")) != NULL) { + if(CheckMapVersion(mysymfile) == 1) + file = mysymfile; fclose(sym_file); } - if (sym_file == (FILE *) 0 || file == (char *) 0) { - sprintf (symfile, "%s", *mf); - dbgprintf("Trying %s.\n", symfile); - if ( (sym_file = fopen(symfile, "r")) != (FILE *) 0 ) { - if (CheckMapVersion(symfile) == 1) - file = symfile; + if(sym_file == NULL || file == NULL) { + sprintf (mysymfile, "%s", *mf); + dbgprintf("Trying %s.\n", mysymfile); + if((sym_file = fopen(mysymfile, "r")) != NULL ) { + if (CheckMapVersion(mysymfile) == 1) + file = mysymfile; fclose(sym_file); } } - } /* At this stage of the game we are at the end of the symbol tables. */ dbgprintf("End of search list encountered.\n"); + ENDfunc return(file); } @@ -410,13 +407,13 @@ static int CheckVersion(char *version) * version level. */ if ( uname(&utsname) < 0 ) { - Syslog(LOG_ERR, "Cannot get kernel version information."); + imklogLogIntMsg(LOG_ERR, "Cannot get kernel version information."); return(0); } dbgprintf("Comparing kernel %s with symbol table %s.\n", utsname.release, vstring); if ( sscanf (utsname.release, "%d.%d.%d", &major, &minor, &patch) < 3 ) { - Syslog(LOG_ERR, "Kernel send bogus release string `%s'.", utsname.release); + imklogLogIntMsg(LOG_ERR, "Kernel send bogus release string `%s'.", utsname.release); return(0); } @@ -464,18 +461,18 @@ static int CheckMapVersion(char *fname) auto char type, sym[512]; - if ( (sym_file = fopen(fname, "r")) != (FILE *) 0 ) { + if ( (sym_file = fopen(fname, "r")) != NULL ) { /* * At this point a map file was successfully opened. We * now need to search this file and look for version * information. */ - Syslog(LOG_INFO, "Inspecting %s", fname); + imklogLogIntMsg(LOG_INFO, "Inspecting %s", fname); version = 0; while ( !feof(sym_file) && (version == 0) ) { if ( fscanf(sym_file, "%lx %c %s\n", &address, &type, sym) != 3 ) { - Syslog(LOG_ERR, "Error in symbol table input (#2)."); + imklogLogIntMsg(LOG_ERR, "Error in symbol table input (#2)."); fclose(sym_file); return(0); } @@ -487,7 +484,7 @@ static int CheckMapVersion(char *fname) switch ( version ) { case -1: - Syslog(LOG_ERR, "Symbol table has incorrect version number.\n"); + imklogLogIntMsg(LOG_ERR, "Symbol table has incorrect version number.\n"); break; case 0: dbgprintf("No version information found.\n"); @@ -527,7 +524,7 @@ static int AddSymbol(unsigned long address, char *symbol) /* Then the space for the symbol. */ sym_array[num_syms].name = (char *) malloc(strlen(symbol)*sizeof(char) + 1); - if ( sym_array[num_syms].name == (char *) 0 ) + if ( sym_array[num_syms].name == NULL ) return(0); sym_array[num_syms].value = address; @@ -566,13 +563,13 @@ char * LookupSymbol(unsigned long value, struct symbol *sym) struct symbol ksym, msym; if (!sym_array) - return((char *) 0); + return(NULL); last = sym_array[0].name; ksym.offset = 0; ksym.size = 0; if ( value < sym_array[0].value ) - return((char *) 0); + return(NULL); for(lp = 0; lp <= num_syms; ++lp) { if ( sym_array[lp].value > value ) { @@ -587,7 +584,7 @@ char * LookupSymbol(unsigned long value, struct symbol *sym) name = LookupModuleSymbol(value, &msym); if ( ksym.offset == 0 && msym.offset == 0 ) { - return((char *) 0); + return(NULL); } if ( ksym.offset == 0 || msym.offset < 0 || @@ -602,7 +599,7 @@ char * LookupSymbol(unsigned long value, struct symbol *sym) } - return((char *) 0); + return(NULL); } /************************************************************************** @@ -683,8 +680,8 @@ extern char *ExpandKadds(char *line, char *el) * open for patches. */ if ( i_am_paranoid && - (strstr(line, "Oops:") != (char *) 0) && !InitMsyms() ) - Syslog(LOG_WARNING, "Cannot load kernel module symbols.\n"); + (strstr(line, "Oops:") != NULL) && !InitMsyms() ) + imklogLogIntMsg(LOG_WARNING, "Cannot load kernel module symbols.\n"); /* @@ -692,7 +689,7 @@ extern char *ExpandKadds(char *line, char *el) * messages in this line. */ if ( (num_syms == 0) || - (kp = strstr(line, "[<")) == (char *) 0 ) { + (kp = strstr(line, "[<")) == NULL ) { #ifdef __sparc__ if (num_syms) { /* On SPARC, register dumps do not have the [< >] characters in it. @@ -780,7 +777,7 @@ extern char *ExpandKadds(char *line, char *el) *elp++ = *sl++; /* Now poised at a kernel delimiter. */ - if ( (kp = strstr(sl, ">]")) == (char *) 0 ) { + if ( (kp = strstr(sl, ">]")) == NULL ) { strcpy(el, sl); return(el); } @@ -788,7 +785,7 @@ extern char *ExpandKadds(char *line, char *el) strncpy(num,sl+1,kp-sl-1); num[kp-sl-1] = '\0'; value = strtoul(num, (char **) 0, 16); - if ( (symbol = LookupSymbol(value, &sym)) == (char *) 0 ) + if ( (symbol = LookupSymbol(value, &sym)) == NULL ) symbol = sl; strcat(elp, symbol); @@ -805,10 +802,10 @@ extern char *ExpandKadds(char *line, char *el) strncat(elp, kp, value); elp += value; sl = kp + value; - if ( (kp = strstr(sl, "[<")) == (char *) 0 ) + if ( (kp = strstr(sl, "[<")) == NULL ) strcat(elp, sl); } - while ( kp != (char *) 0); + while ( kp != NULL); dbgprintf("Expanded line: %s\n", el); return(el); diff --git a/plugins/imklog/ksym_mod.c b/plugins/imklog/ksym_mod.c index 3e064e2..6e48e89 100644 --- a/plugins/imklog/ksym_mod.c +++ b/plugins/imklog/ksym_mod.c @@ -158,10 +158,10 @@ extern int InitMsyms(void) if ( ksyms == NULL ) { if ( errno == ENOENT ) - Syslog(LOG_INFO, "No module symbols loaded - " + imklogLogIntMsg(LOG_INFO, "No module symbols loaded - " "kernel modules not enabled.\n"); else - Syslog(LOG_ERR, "Error loading kernel symbols " \ + imklogLogIntMsg(LOG_ERR, "Error loading kernel symbols " \ "- %s\n", strerror(errno)); return(0); } @@ -200,9 +200,9 @@ extern int InitMsyms(void) } if ( rtn == 0 ) - Syslog(LOG_INFO, "No module symbols loaded."); + imklogLogIntMsg(LOG_INFO, "No module symbols loaded."); else - Syslog(LOG_INFO, "Loaded %d %s from %d module%s", rtn, \ + imklogLogIntMsg(LOG_INFO, "Loaded %d %s from %d module%s", rtn, \ (rtn == 1) ? "symbol" : "symbols", \ num_modules, (num_modules == 1) ? "." : "s."); @@ -295,7 +295,7 @@ struct Module *AddModule(module) if ( sym_array_modules == NULL ) { - Syslog(LOG_WARNING, "Cannot allocate Module array.\n"); + imklogLogIntMsg(LOG_WARNING, "Cannot allocate Module array.\n"); return NULL; } mp = sym_array_modules; @@ -307,7 +307,7 @@ struct Module *AddModule(module) if ( mp == NULL ) { - Syslog(LOG_WARNING, "Cannot allocate Module array.\n"); + imklogLogIntMsg(LOG_WARNING, "Cannot allocate Module array.\n"); return NULL; } diff --git a/plugins/imklog/linux.c b/plugins/imklog/linux.c new file mode 100644 index 0000000..faf2013 --- /dev/null +++ b/plugins/imklog/linux.c @@ -0,0 +1,544 @@ +/* klog for linux, based on the FreeBSD syslogd implementation. + * + * This contains OS-specific functionality to read the BSD + * kernel log. For a general overview, see head comment in + * imklog.c. + * + * This file heavily borrows from the klogd daemon provided by + * the sysklogd project. Many thanks for this piece of software. + * + * This file is part of rsyslog. + * + * Rsyslog is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Rsyslog is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. +*/ +#include "config.h" +#include "rsyslog.h" +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <signal.h> +#include <string.h> +#include <pthread.h> +#include "syslogd.h" +#include "cfsysline.h" +#include "template.h" +#include "msg.h" +#include "module-template.h" +#include "imklog.h" + + +/* Includes. */ +#include <unistd.h> +#include <errno.h> +#include <sys/fcntl.h> +#include <sys/stat.h> + +#if HAVE_TIME_H +# include <time.h> +#endif + +#include <stdarg.h> +#include <paths.h> +#include "ksyms.h" + +#define __LIBRARY__ +#include <unistd.h> + + +#if !defined(__GLIBC__) +# define __NR_ksyslog __NR_syslog +_syscall3(int,ksyslog,int, type, char *, buf, int, len); +#else +#include <sys/klog.h> +#define ksyslog klogctl +#endif + + + +#ifndef _PATH_KLOG +#define _PATH_KLOG "/proc/kmsg" +#endif + +#define LOG_BUFFER_SIZE 4096 +#define LOG_LINE_LENGTH 1000 + +static int kmsg; +static char log_buffer[LOG_BUFFER_SIZE]; + +static enum LOGSRC {none, proc, kernel} logsrc; + + +/* Function prototypes. */ +extern int ksyslog(int type, char *buf, int len); + + +static void CloseLogSrc(void) +{ + /* Turn on logging of messages to console, but only if we had the -c + * option -- rgerhards, 2007-08-01 + */ + if (console_log_level != -1) + ksyslog(7, NULL, 0); + + /* Shutdown the log sources. */ + switch ( logsrc ) + { + case kernel: + ksyslog(0, 0, 0); + imklogLogIntMsg(LOG_INFO, "Kernel logging (ksyslog) stopped."); + break; + case proc: + close(kmsg); + imklogLogIntMsg(LOG_INFO, "Kernel logging (proc) stopped."); + break; + case none: + break; + } + + return; +} + + +static enum LOGSRC GetKernelLogSrc(void) +{ + auto struct stat sb; + + /* Set level of kernel console messaging.. */ + if ( (console_log_level != -1) && + (ksyslog(8, NULL, console_log_level) < 0) && + (errno == EINVAL) ) + { + /* + * An invalid arguement error probably indicates that + * a pre-0.14 kernel is being run. At this point we + * issue an error message and simply shut-off console + * logging completely. + */ + imklogLogIntMsg(LOG_WARNING, "Cannot set console log level - disabling " + "console output."); + } + + /* + * First do a stat to determine whether or not the proc based + * file system is available to get kernel messages from. + */ + if ( use_syscall || + ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) ) + { + /* Initialize kernel logging. */ + ksyslog(1, NULL, 0); + imklogLogIntMsg(LOG_INFO, "imklog %s, log source = ksyslog " + "started.", VERSION); + return(kernel); + } + + if ( (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 ) + { + char sz[512]; + snprintf(sz, sizeof(sz), "imklog: Cannot open proc file system, %d - %s.\n", errno, strerror(errno)); + logmsgInternal(LOG_SYSLOG|LOG_ERR, sz, ADDDATE); + ksyslog(7, NULL, 0); /* TODO: check this, implement more */ + return(none); + } + + imklogLogIntMsg(LOG_INFO, "imklog %s, log source = %s started.", VERSION, _PATH_KLOG); + return(proc); +} + + +/* Copy characters from ptr to line until a char in the delim + * string is encountered or until min( space, len ) chars have + * been copied. + * + * Returns the actual number of chars copied. + */ +static int copyin( uchar *line, int space, + const char *ptr, int len, + const char *delim ) +{ + auto int i; + auto int count; + + count = len < space ? len : space; + + for(i=0; i<count && !strchr(delim, *ptr); i++ ) { + *line++ = *ptr++; + } + + return(i); +} + +/* + * Messages are separated by "\n". Messages longer than + * LOG_LINE_LENGTH are broken up. + * + * Kernel symbols show up in the input buffer as : "[<aaaaaa>]", + * where "aaaaaa" is the address. These are replaced with + * "[symbolname+offset/size]" in the output line - symbolname, + * offset, and size come from the kernel symbol table. + * + * If a kernel symbol happens to fall at the end of a message close + * in length to LOG_LINE_LENGTH, the symbol will not be expanded. + * (This should never happen, since the kernel should never generate + * messages that long. + * + * To preserve the original addresses, lines containing kernel symbols + * are output twice. Once with the symbols converted and again with the + * original text. Just in case somebody wants to run their own Oops + * analysis on the syslog, e.g. ksymoops. + */ +static void LogLine(char *ptr, int len) +{ + enum parse_state_enum { + PARSING_TEXT, + PARSING_SYMSTART, /* at < */ + PARSING_SYMBOL, + PARSING_SYMEND /* at ] */ + }; + + static uchar line_buff[LOG_LINE_LENGTH]; + + static uchar *line =line_buff; + static enum parse_state_enum parse_state = PARSING_TEXT; + static int space = sizeof(line_buff)-1; + + static uchar *sym_start; /* points at the '<' of a symbol */ + + auto int delta = 0; /* number of chars copied */ + auto int symbols_expanded = 0; /* 1 if symbols were expanded */ + auto int skip_symbol_lookup = 0; /* skip symbol lookup on this pass */ + auto char *save_ptr = ptr; /* save start of input line */ + auto int save_len = len; /* save length at start of input line */ + + while( len > 0 ) + { + if( space == 0 ) /* line buffer is full */ + { + /* + ** Line too long. Start a new line. + */ + *line = 0; /* force null terminator */ + + //dbgprintf("Line buffer full:\n"); + //dbgprintf("\tLine: %s\n", line); + + Syslog(LOG_INFO, line_buff); + line = line_buff; + space = sizeof(line_buff)-1; + parse_state = PARSING_TEXT; + symbols_expanded = 0; + skip_symbol_lookup = 0; + save_ptr = ptr; + save_len = len; + } + + switch( parse_state ) + { + case PARSING_TEXT: + delta = copyin(line, space, ptr, len, "\n[" ); + line += delta; + ptr += delta; + space -= delta; + len -= delta; + + if( space == 0 || len == 0 ) + { + break; /* full line_buff or end of input buffer */ + } + + if( *ptr == '\0' ) /* zero byte */ + { + ptr++; /* skip zero byte */ + space -= 1; + len -= 1; + + break; + } + + if( *ptr == '\n' ) /* newline */ + { + ptr++; /* skip newline */ + space -= 1; + len -= 1; + + *line = 0; /* force null terminator */ + Syslog(LOG_INFO, line_buff); + line = line_buff; + space = sizeof(line_buff)-1; + if (symbols_twice) { + if (symbols_expanded) { + /* reprint this line without symbol lookup */ + symbols_expanded = 0; + skip_symbol_lookup = 1; + ptr = save_ptr; + len = save_len; + } + else + { + skip_symbol_lookup = 0; + save_ptr = ptr; + save_len = len; + } + } + break; + } + if( *ptr == '[' ) /* possible kernel symbol */ + { + *line++ = *ptr++; + space -= 1; + len -= 1; + if (!skip_symbol_lookup) + parse_state = PARSING_SYMSTART; /* at < */ + break; + } + /* Now that line_buff is no longer fed to *printf as format + * string, '%'s are no longer "dangerous". + */ + break; + + case PARSING_SYMSTART: + if( *ptr != '<' ) + { + parse_state = PARSING_TEXT; /* not a symbol */ + break; + } + + /* + ** Save this character for now. If this turns out to + ** be a valid symbol, this char will be replaced later. + ** If not, we'll just leave it there. + */ + + sym_start = line; /* this will point at the '<' */ + + *line++ = *ptr++; + space -= 1; + len -= 1; + parse_state = PARSING_SYMBOL; /* symbol... */ + break; + + case PARSING_SYMBOL: + delta = copyin( line, space, ptr, len, ">\n[" ); + line += delta; + ptr += delta; + space -= delta; + len -= delta; + if( space == 0 || len == 0 ) + { + break; /* full line_buff or end of input buffer */ + } + if( *ptr != '>' ) + { + parse_state = PARSING_TEXT; + break; + } + + *line++ = *ptr++; /* copy the '>' */ + space -= 1; + len -= 1; + + parse_state = PARSING_SYMEND; + + break; + + case PARSING_SYMEND: + if( *ptr != ']' ) + { + parse_state = PARSING_TEXT; /* not a symbol */ + break; + } + + /* + ** It's really a symbol! Replace address with the + ** symbol text. + */ + { + auto int sym_space; + + unsigned long value; + auto struct symbol sym; + auto char *symbol; + + *(line-1) = 0; /* null terminate the address string */ + value = strtoul((char*)(sym_start+1), (char **) 0, 16); + *(line-1) = '>'; /* put back delim */ + + if ( !symbol_lookup || (symbol = LookupSymbol(value, &sym)) == (char *)0 ) + { + parse_state = PARSING_TEXT; + break; + } + + /* + ** verify there is room in the line buffer + */ + sym_space = space + ( line - sym_start ); + if( (unsigned) sym_space < strlen(symbol) + 30 ) /*(30 should be overkill)*/ + { + parse_state = PARSING_TEXT; /* not enough space */ + break; + } + + // TODO: sprintf!!!! + delta = sprintf( (char*) sym_start, "%s+%d/%d]", + symbol, sym.offset, sym.size ); + + space = sym_space + delta; + line = sym_start + delta; + symbols_expanded = 1; + } + ptr++; + len--; + parse_state = PARSING_TEXT; + break; + + default: /* Can't get here! */ + parse_state = PARSING_TEXT; + + } + } + + return; +} + + +static void LogKernelLine(void) +{ + auto int rdcnt; + + /* + * Zero-fill the log buffer. This should cure a multitude of + * problems with klogd logging the tail end of the message buffer + * which will contain old messages. Then read the kernel log + * messages into this fresh buffer. + */ + memset(log_buffer, '\0', sizeof(log_buffer)); + if ( (rdcnt = ksyslog(2, log_buffer, sizeof(log_buffer)-1)) < 0 ) + { + char sz[512]; + if(errno == EINTR) + return; + snprintf(sz, sizeof(sz), "imklog: Error return from sys_sycall: %d - %s\n", errno, strerror(errno)); + logmsgInternal(LOG_SYSLOG|LOG_ERR, sz, ADDDATE); + } + else + LogLine(log_buffer, rdcnt); + return; +} + + +static void LogProcLine(void) +{ + auto int rdcnt; + + /* + * Zero-fill the log buffer. This should cure a multitude of + * problems with klogd logging the tail end of the message buffer + * which will contain old messages. Then read the kernel messages + * from the message pseudo-file into this fresh buffer. + */ + memset(log_buffer, '\0', sizeof(log_buffer)); + if ( (rdcnt = read(kmsg, log_buffer, sizeof(log_buffer)-1)) < 0 ) { + if ( errno == EINTR ) + return; + imklogLogIntMsg(LOG_ERR, "Cannot read proc file system: %d - %s.", errno, strerror(errno)); + } else { + LogLine(log_buffer, rdcnt); + } + + return; +} + + +/* to be called in the module's WillRun entry point + * rgerhards, 2008-04-09 + */ +rsRetVal klogLogKMsg(void) +{ + DEFiRet; + switch(logsrc) { + case kernel: + LogKernelLine(); + break; + case proc: + LogProcLine(); + break; + case none: + /* TODO: We need to handle this case here somewhat more intelligent + * This is now at least partly done - code should never reach this point + * as willRun() already checked for the "none" status -- rgerhards, 2007-12-17 + */ + pause(); + break; + } + RETiRet; +} + + +/* to be called in the module's WillRun entry point + * rgerhards, 2008-04-09 + */ +rsRetVal klogWillRun(void) +{ + DEFiRet; + /* Initialize this module. If that fails, we tell the engine we don't like to run */ + /* Determine where kernel logging information is to come from. */ + logsrc = GetKernelLogSrc(); + if(logsrc == none) { + iRet = RS_RET_NO_KERNEL_LOGSRC; + } else { + if (symbol_lookup) { + symbol_lookup = (InitKsyms(symfile) == 1); + symbol_lookup |= InitMsyms(); + if (symbol_lookup == 0) { + imklogLogIntMsg(LOG_WARNING, "cannot find any symbols, turning off symbol lookups"); + } + } + } + + RETiRet; +} + + +/* to be called in the module's AfterRun entry point + * rgerhards, 2008-04-09 + */ +rsRetVal klogAfterRun(void) +{ + DEFiRet; + /* cleanup here */ + if(logsrc != none) + CloseLogSrc(); + + DeinitKsyms(); + DeinitMsyms(); + + RETiRet; +} + + +/* provide the (system-specific) default facility for internal messages + * rgerhards, 2008-04-14 + */ +int +klogFacilIntMsg(void) +{ + return LOG_KERN; +} + + +/* vi:set ai: + */ diff --git a/plugins/immark/immark.c b/plugins/immark/immark.c index 30118de..0bc3199 100644 --- a/plugins/immark/immark.c +++ b/plugins/immark/immark.c @@ -84,6 +84,8 @@ ENDrunInput BEGINwillRun CODESTARTwillRun + /* We set the global MarkInterval to what is configured here -- rgerhards, 2008-07-15 */ + MarkInterval = iMarkMessagePeriod; if(iMarkMessagePeriod == 0) iRet = RS_RET_NO_RUN; ENDwillRun diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c index 3cdcbf0..f879803 100644 --- a/plugins/imuxsock/imuxsock.c +++ b/plugins/imuxsock/imuxsock.c @@ -181,7 +181,7 @@ static rsRetVal readSocket(int fd, int bParseHost, int flags) iRcvd = recv(fd, line, MAXLINE - 1, 0); dbgprintf("Message from UNIX socket: #%d\n", fd); if (iRcvd > 0) { - parseAndSubmitMessage(LocalHostName, line, iRcvd, bParseHost, flags, eFLOWCTL_LIGHT_DELAY); + parseAndSubmitMessage((char*)LocalHostName, line, iRcvd, bParseHost, flags, eFLOWCTL_LIGHT_DELAY); } else if (iRcvd < 0 && errno != EINTR) { char errStr[1024]; rs_strerror_r(errno, errStr, sizeof(errStr)); diff --git a/plugins/omgssapi/omgssapi.c b/plugins/omgssapi/omgssapi.c index be05177..34abfe0 100644 --- a/plugins/omgssapi/omgssapi.c +++ b/plugins/omgssapi/omgssapi.c @@ -4,7 +4,7 @@ * NOTE: read comments in module-template.h to understand how this file * works! * - * Copyright 2007 Rainer Gerhards and Adiscon GmbH. + * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * @@ -79,7 +79,7 @@ DEFobjCurrIf(gssutil) DEFobjCurrIf(tcpclt) typedef struct _instanceData { - char f_hname[MAXHOSTNAMELEN+1]; + char *f_hname; short sock; /* file descriptor */ enum { /* TODO: we shoud revisit these definitions */ eDestFORW, @@ -162,6 +162,9 @@ CODESTARTfreeInstance tcpclt.Destruct(&pData->pTCPClt); if(pData->sock >= 0) close(pData->sock); + + if(pData->f_hname != NULL) + free(pData->f_hname); ENDfreeInstance @@ -551,7 +554,7 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) /* extract the host first (we do a trick - we replace the ';' or ':' with a '\0') * now skip to port and then template name. rgerhards 2005-07-06 */ - for(q = p ; *p && *p != ';' && *p != ':' ; ++p) + for(q = p ; *p && *p != ';' && *p != ':' && *p != '#' ; ++p) /* JUST SKIP */; pData->port = NULL; @@ -575,27 +578,21 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) } } + /* now skip to template */ bErr = 0; - while(*p && *p != ';') { - if(*p && *p != ';' && !isspace((int) *p)) { - if(bErr == 0) { /* only 1 error msg! */ - bErr = 1; - errno = 0; - errmsg.LogError(NO_ERRCODE, "invalid selector line (port), probably not doing " - "what was intended"); - } - } - ++p; - } + while(*p && *p != ';' && *p != '#' && !isspace((int) *p)) + ++p; /*JUST SKIP*/ /* TODO: make this if go away! */ - if(*p == ';') { + if(*p == ';' || *p == '#' || isspace(*p)) { + uchar cTmp = *p; *p = '\0'; /* trick to obtain hostname (later)! */ - strcpy(pData->f_hname, (char*) q); - *p = ';'; - } else - strcpy(pData->f_hname, (char*) q); + CHKmalloc(pData->f_hname = strdup((char*) q)); + *p = cTmp; + } else { + CHKmalloc(pData->f_hname = strdup((char*) q)); + } /* process template */ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, @@ -701,6 +698,5 @@ CODEmodInit_QueryRegCFSLineHdlr ENDmodInit #endif /* #ifdef USE_GSSAPI */ -/* - * vi:set ai: +/* vi:set ai: */ diff --git a/plugins/ommail/Makefile.am b/plugins/ommail/Makefile.am new file mode 100644 index 0000000..7e9f5f1 --- /dev/null +++ b/plugins/ommail/Makefile.am @@ -0,0 +1,6 @@ +pkglib_LTLIBRARIES = ommail.la + +ommail_la_SOURCES = ommail.c +ommail_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) +ommail_la_LDFLAGS = -module -avoid-version +ommail_la_LIBADD = diff --git a/plugins/ommail/Makefile.in b/plugins/ommail/Makefile.in new file mode 100644 index 0000000..8fe419a --- /dev/null +++ b/plugins/ommail/Makefile.in @@ -0,0 +1,494 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = plugins/ommail +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(pkglibdir)" +pkglibLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(pkglib_LTLIBRARIES) +ommail_la_DEPENDENCIES = +am_ommail_la_OBJECTS = ommail_la-ommail.lo +ommail_la_OBJECTS = $(am_ommail_la_OBJECTS) +ommail_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(ommail_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(ommail_la_SOURCES) +DIST_SOURCES = $(ommail_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +HAVE_MYSQL_CONFIG = @HAVE_MYSQL_CONFIG@ +HAVE_PGSQL_CONFIG = @HAVE_PGSQL_CONFIG@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +RELP_CFLAGS = @RELP_CFLAGS@ +RELP_LIBS = @RELP_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dl_libs = @dl_libs@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gss_libs = @gss_libs@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdbi_cflags = @libdbi_cflags@ +libdbi_libs = @libdbi_libs@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +mysql_cflags = @mysql_cflags@ +mysql_libs = @mysql_libs@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pgsql_cflags = @pgsql_cflags@ +pgsql_libs = @pgsql_libs@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pthreads_cflags = @pthreads_cflags@ +pthreads_libs = @pthreads_libs@ +rfc3195_cflags = @rfc3195_cflags@ +rfc3195_libs = @rfc3195_libs@ +rt_libs = @rt_libs@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +snmp_cflags = @snmp_cflags@ +snmp_libs = @snmp_libs@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +zlib_libs = @zlib_libs@ +pkglib_LTLIBRARIES = ommail.la +ommail_la_SOURCES = ommail.c +ommail_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) +ommail_la_LDFLAGS = -module -avoid-version +ommail_la_LIBADD = +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/ommail/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu plugins/ommail/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(pkglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" + @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pkglibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pkglibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(pkglibdir)/$$f"; \ + else :; fi; \ + done + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +ommail.la: $(ommail_la_OBJECTS) $(ommail_la_DEPENDENCIES) + $(ommail_la_LINK) -rpath $(pkglibdir) $(ommail_la_OBJECTS) $(ommail_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ommail_la-ommail.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +ommail_la-ommail.lo: ommail.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ommail_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ommail_la-ommail.lo -MD -MP -MF $(DEPDIR)/ommail_la-ommail.Tpo -c -o ommail_la-ommail.lo `test -f 'ommail.c' || echo '$(srcdir)/'`ommail.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ommail_la-ommail.Tpo $(DEPDIR)/ommail_la-ommail.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ommail.c' object='ommail_la-ommail.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ommail_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ommail_la-ommail.lo `test -f 'ommail.c' || echo '$(srcdir)/'`ommail.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pkglibLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c new file mode 100644 index 0000000..218c73c --- /dev/null +++ b/plugins/ommail/ommail.c @@ -0,0 +1,630 @@ +/* ommail.c + * + * This is an implementation of a mail sending output module. So far, we + * only support direct SMTP, that is talking to a SMTP server. In the long + * term, support for using sendmail should also be implemented. Please note + * that the SMTP protocol implementation is a very bare one. We support + * RFC821/822 messages, without any authentication and any other nice + * features (no MIME, no nothing). It is assumed that proper firewalling + * and/or STMP server configuration is used together with this module. + * + * NOTE: read comments in module-template.h to understand how this file + * works! + * + * File begun on 2008-04-04 by RGerhards + * + * Copyright 2008 Rainer Gerhards and Adiscon GmbH. + * + * This file is part of rsyslog. + * + * Rsyslog is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Rsyslog is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + */ +#include "config.h" +#include "rsyslog.h" +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <unistd.h> +#include <errno.h> +#include <netdb.h> +#include <time.h> +#include <sys/socket.h> +#include "syslogd.h" +#include "syslogd-types.h" +#include "srUtils.h" +#include "cfsysline.h" +#include "module-template.h" +#include "errmsg.h" + +MODULE_TYPE_OUTPUT + +/* internal structures + */ +DEF_OMOD_STATIC_DATA +DEFobjCurrIf(errmsg) + +static uchar *pszSrv = NULL; +static uchar *pszSrvPort = NULL; +static uchar *pszFrom = NULL; +static uchar *pszTo = NULL; +static uchar *pszSubject = NULL; +static int bEnableBody = 1; /* should a mail body be generated? (set to 0 eg for SMS gateways) */ + +typedef struct _instanceData { + int iMode; /* 0 - smtp, 1 - sendmail */ + int bHaveSubject; /* is a subject configured? (if so, it is the second string provided by rsyslog core) */ + int bEnableBody; /* is a body configured? (if so, it is the second string provided by rsyslog core) */ + union { + struct { + uchar *pszSrv; + uchar *pszSrvPort; + uchar *pszFrom; + uchar *pszTo; + char RcvBuf[1024]; /* buffer for receiving server responses */ + size_t lenRcvBuf; + size_t iRcvBuf; /* current index into the rcvBuf (buf empty if iRcvBuf == lenRcvBuf) */ + int sock; /* socket to this server (most important when we do multiple msgs per mail) */ + } smtp; + } md; /* mode-specific data */ +} instanceData; + + +BEGINcreateInstance +CODESTARTcreateInstance +ENDcreateInstance + + +BEGINisCompatibleWithFeature +CODESTARTisCompatibleWithFeature + if(eFeat == sFEATURERepeatedMsgReduction) + iRet = RS_RET_OK; +ENDisCompatibleWithFeature + + +BEGINfreeInstance +CODESTARTfreeInstance + if(pData->iMode == 0) { + if(pData->md.smtp.pszSrv != NULL) + free(pData->md.smtp.pszSrv); + if(pData->md.smtp.pszSrvPort != NULL) + free(pData->md.smtp.pszSrvPort); + if(pData->md.smtp.pszFrom != NULL) + free(pData->md.smtp.pszFrom); + if(pData->md.smtp.pszTo != NULL) + free(pData->md.smtp.pszTo); + } +ENDfreeInstance + + +BEGINdbgPrintInstInfo +CODESTARTdbgPrintInstInfo + printf("mail"); /* TODO: extend! */ +ENDdbgPrintInstInfo + + +/* TCP support code, should probably be moved to net.c or some place else... -- rgerhards, 2008-04-04 */ + +/* "receive" a character from the remote server. A single character + * is returned. Returns RS_RET_NO_MORE_DATA if the server has closed + * the connection and RS_RET_IO_ERROR if something goes wrong. This + * is a blocking read. + * rgerhards, 2008-04-04 + */ +static rsRetVal +getRcvChar(instanceData *pData, char *pC) +{ + DEFiRet; + ssize_t lenBuf; + assert(pData != NULL); + + if(pData->md.smtp.iRcvBuf == pData->md.smtp.lenRcvBuf) { /* buffer empty? */ + /* yes, we need to read the next server response */ + do { + lenBuf = recv(pData->md.smtp.sock, pData->md.smtp.RcvBuf, sizeof(pData->md.smtp.RcvBuf), 0); + if(lenBuf == 0) { + ABORT_FINALIZE(RS_RET_NO_MORE_DATA); + } else if(lenBuf < 0) { + if(errno != EAGAIN) { + ABORT_FINALIZE(RS_RET_IO_ERROR); + } + } else { + /* good read */ + pData->md.smtp.iRcvBuf = 0; + pData->md.smtp.lenRcvBuf = lenBuf; + } + + } while(lenBuf < 1); + } + + /* when we reach this point, we have a non-empty buffer */ + *pC = pData->md.smtp.RcvBuf[pData->md.smtp.iRcvBuf++]; + +finalize_it: + RETiRet; +} + + +/* close the mail server connection + * rgerhards, 2008-04-08 + */ +static rsRetVal +serverDisconnect(instanceData *pData) +{ + DEFiRet; + assert(pData != NULL); + + if(pData->md.smtp.sock != -1) { + close(pData->md.smtp.sock); + pData->md.smtp.sock = -1; + } + + RETiRet; +} + + +/* open a connection to the mail server + * rgerhards, 2008-04-04 + */ +static rsRetVal +serverConnect(instanceData *pData) +{ + struct addrinfo *res = NULL; + struct addrinfo hints; + char *smtpPort; + char *smtpSrv; + char errStr[1024]; + + DEFiRet; + assert(pData != NULL); + + if(pData->md.smtp.pszSrv == NULL) + smtpSrv = "127.0.0.1"; + else + smtpSrv = (char*)pData->md.smtp.pszSrv; + + if(pData->md.smtp.pszSrvPort == NULL) + smtpPort = "25"; + else + smtpPort = (char*)pData->md.smtp.pszSrvPort; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; /* TODO: make configurable! */ + hints.ai_socktype = SOCK_STREAM; + if(getaddrinfo(smtpSrv, smtpPort, &hints, &res) != 0) { + dbgprintf("error %d in getaddrinfo\n", errno); + ABORT_FINALIZE(RS_RET_IO_ERROR); + } + + if((pData->md.smtp.sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) { + dbgprintf("couldn't create send socket, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr))); + ABORT_FINALIZE(RS_RET_IO_ERROR); + } + + if(connect(pData->md.smtp.sock, res->ai_addr, res->ai_addrlen) != 0) { + dbgprintf("create tcp connection failed, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr))); + ABORT_FINALIZE(RS_RET_IO_ERROR); + } + +finalize_it: + if(res != NULL) + freeaddrinfo(res); + + if(iRet != RS_RET_OK) { + if(pData->md.smtp.sock != -1) { + close(pData->md.smtp.sock); + pData->md.smtp.sock = -1; + } + } + + RETiRet; +} + + +/* send text to the server, blocking send */ +static rsRetVal +Send(int sock, char *msg, size_t len) +{ + DEFiRet; + size_t offsBuf = 0; + ssize_t lenSend; + + assert(msg != NULL); + + if(len == 0) /* it's valid, but does not make much sense ;) */ + FINALIZE; + + do { + lenSend = send(sock, msg + offsBuf, len - offsBuf, 0); + if(lenSend == -1) { + if(errno != EAGAIN) { + dbgprintf("message not (tcp)send, errno %d", errno); + ABORT_FINALIZE(RS_RET_TCP_SEND_ERROR); + } + } else if(lenSend != (ssize_t) len) { + offsBuf += len; /* on to next round... */ + } else { + FINALIZE; + } + } while(1); + +finalize_it: + RETiRet; +} + + +/* send body text to the server, blocking send + * The body is special in that we must escape a leading dot inside a line + */ +static rsRetVal +bodySend(instanceData *pData, char *msg, size_t len) +{ + DEFiRet; + char szBuf[2048]; + size_t iSrc; + size_t iBuf = 0; + int bHadCR = 0; + int bInStartOfLine = 1; + + assert(pData != NULL); + assert(msg != NULL); + + for(iSrc = 0 ; iSrc < len ; ++iSrc) { + if(iBuf >= sizeof(szBuf) - 1) { /* one is reserved for our extra dot */ + CHKiRet(Send(pData->md.smtp.sock, szBuf, iBuf)); + iBuf = 0; + } + szBuf[iBuf++] = msg[iSrc]; + switch(msg[iSrc]) { + case '\r': + bHadCR = 1; + break; + case '\n': + if(bHadCR) + bInStartOfLine = 1; + bHadCR = 0; + break; + case '.': + if(bInStartOfLine) + szBuf[iBuf++] = '.'; /* space is always reserved for this! */ + /*FALLTHROUGH*/ + default: + bInStartOfLine = 0; + bHadCR = 0; + break; + } + } + + if(iBuf > 0) { /* incomplete buffer to send (the *usual* case)? */ + CHKiRet(Send(pData->md.smtp.sock, szBuf, iBuf)); + } + +finalize_it: + RETiRet; +} + + +/* read response line from server + */ +static rsRetVal +readResponseLn(instanceData *pData, char *pLn, size_t lenLn) +{ + DEFiRet; + size_t i = 0; + char c; + + assert(pData != NULL); + assert(pLn != NULL); + + do { + CHKiRet(getRcvChar(pData, &c)); + if(c == '\n') + break; + 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: + RETiRet; +} + + +/* read numerical response code from server and compare it to requried response code. + * If they two don't match, return RS_RET_SMTP_ERROR. + * rgerhards, 2008-04-07 + */ +static rsRetVal +readResponse(instanceData *pData, int *piState, int iExpected) +{ + DEFiRet; + int bCont; + char buf[128]; + + assert(pData != NULL); + assert(piState != NULL); + + bCont = 1; + do { + CHKiRet(readResponseLn(pData, buf, sizeof(buf))); + /* note: the code below is not 100% clean as we may have received less than 4 characters. + * However, as we have a fixed size this will not create a vulnerability. An error will + * also most likely be generated, so it is quite acceptable IMHO -- rgerhards, 2008-04-08 + */ + if(buf[3] != '-') { /* last or only response line? */ + bCont = 0; + *piState = buf[0] - '0'; + *piState = *piState * 10 + buf[1] - '0'; + *piState = *piState * 10 + buf[2] - '0'; + if(*piState != iExpected) + ABORT_FINALIZE(RS_RET_SMTP_ERROR); + } + } while(bCont); + +finalize_it: + RETiRet; +} + + +/* create a timestamp suitable for use with the Date: SMTP body header + * rgerhards, 2008-04-08 + */ +static void +mkSMTPTimestamp(uchar *pszBuf, size_t lenBuf) +{ + time_t tCurr; + struct tm tmCurr; + static const char szDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + static const char szMonth[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + time(&tCurr); + gmtime_r(&tCurr, &tmCurr); + snprintf((char*)pszBuf, lenBuf, "Date: %s, %2d %s %4d %2d:%02d:%02d UT\r\n", szDay[tmCurr.tm_wday], tmCurr.tm_mday, + szMonth[tmCurr.tm_mon], 1900 + tmCurr.tm_year, tmCurr.tm_hour, tmCurr.tm_min, tmCurr.tm_sec); +} + + +/* send a message via SMTP + * rgerhards, 2008-04-04 + */ +static rsRetVal +sendSMTP(instanceData *pData, uchar *body, uchar *subject) +{ + DEFiRet; + int iState; /* SMTP state */ + uchar szDateBuf[64]; + + assert(pData != NULL); + + CHKiRet(serverConnect(pData)); + CHKiRet(readResponse(pData, &iState, 220)); + + CHKiRet(Send(pData->md.smtp.sock, "HELO ", 5)); + CHKiRet(Send(pData->md.smtp.sock, (char*)LocalHostName, strlen((char*)LocalHostName))); + CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); + CHKiRet(readResponse(pData, &iState, 250)); + + CHKiRet(Send(pData->md.smtp.sock, "MAIL FROM: <", sizeof("MAIL FROM: <") - 1)); + CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszFrom, strlen((char*)pData->md.smtp.pszFrom))); + CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); + CHKiRet(readResponse(pData, &iState, 250)); + + CHKiRet(Send(pData->md.smtp.sock, "RCPT TO: <", sizeof("RCPT TO: <") - 1)); + CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszTo, strlen((char*)pData->md.smtp.pszTo))); + CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); + CHKiRet(readResponse(pData, &iState, 250)); + + CHKiRet(Send(pData->md.smtp.sock, "DATA\r\n", sizeof("DATA\r\n") - 1)); + CHKiRet(readResponse(pData, &iState, 354)); + + /* now come the data part */ + /* header */ + mkSMTPTimestamp(szDateBuf, sizeof(szDateBuf)); + CHKiRet(Send(pData->md.smtp.sock, (char*)szDateBuf, strlen((char*)szDateBuf))); + + CHKiRet(Send(pData->md.smtp.sock, "From: <", sizeof("From: <") - 1)); + CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszFrom, strlen((char*)pData->md.smtp.pszFrom))); + CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); + + CHKiRet(Send(pData->md.smtp.sock, "To: <", sizeof("To: <") - 1)); + CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszTo, strlen((char*)pData->md.smtp.pszTo))); + CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); + + CHKiRet(Send(pData->md.smtp.sock, "Subject: ", sizeof("Subject: ") - 1)); + CHKiRet(Send(pData->md.smtp.sock, (char*)subject, strlen((char*)subject))); + CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); + + CHKiRet(Send(pData->md.smtp.sock, "X-Mailer: rsyslog-immail\r\n", sizeof("x-mailer: rsyslog-immail\r\n") - 1)); + + CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); /* indicate end of header */ + + /* body */ + if(pData->bEnableBody) + CHKiRet(bodySend(pData, (char*)body, strlen((char*) body))); + + /* end of data, back to envelope transaction */ + CHKiRet(Send(pData->md.smtp.sock, "\r\n.\r\n", sizeof("\r\n.\r\n") - 1)); + CHKiRet(readResponse(pData, &iState, 250)); + + CHKiRet(Send(pData->md.smtp.sock, "QUIT\r\n", sizeof("QUIT\r\n") - 1)); + CHKiRet(readResponse(pData, &iState, 221)); + + /* we are finished, a new connection is created for each request, so let's close it now */ + CHKiRet(serverDisconnect(pData)); + +finalize_it: + RETiRet; +} + + +/* in tryResume we check if we can connect to the server in question. If that is OK, + * we close the connection without doing any actual SMTP transaction. It will be + * reopened during the actual send process. This may not be the best way to do it if + * there is a problem inside the SMTP transaction. However, we can't find that out without + * actually initiating something, and that would be bad. The logic here helps us + * correctly recover from an unreachable/down mail server, which is probably the majority + * of problem cases. For SMTP transaction problems, we will do lots of retries, but if it + * is a temporary problem, it will be fixed anyhow. So I consider this implementation to + * be clean enough, especially as I think other approaches have other weaknesses. + * rgerhards, 2008-04-08 + */ +BEGINtryResume +CODESTARTtryResume + CHKiRet(serverConnect(pData)); + CHKiRet(serverDisconnect(pData)); /* if we fail, we will never reach this line */ +finalize_it: + if(iRet == RS_RET_IO_ERROR) + iRet = RS_RET_SUSPENDED; +ENDtryResume + + +BEGINdoAction +CODESTARTdoAction + dbgprintf(" Mail\n"); + + /* forward */ + if(pData->bHaveSubject) + iRet = sendSMTP(pData, ppString[0], ppString[1]); + else + iRet = sendSMTP(pData, ppString[0], (uchar*)"message from rsyslog"); + + if(iRet != RS_RET_OK) { + /* error! */ + dbgprintf("error sending mail, suspending\n"); + iRet = RS_RET_SUSPENDED; + } +ENDdoAction + + +BEGINparseSelectorAct +CODESTARTparseSelectorAct + if(!strncmp((char*) p, ":ommail:", sizeof(":ommail:") - 1)) { + p += sizeof(":ommail:") - 1; /* eat indicator sequence (-1 because of '\0'!) */ + } else { + ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); + } + + /* ok, if we reach this point, we have something for us */ + if((iRet = createInstance(&pData)) != RS_RET_OK) + FINALIZE; + + /* TODO: check strdup() result */ + + if(pszFrom == NULL) { + errmsg.LogError(NO_ERRCODE, "no sender address given - specify $ActionMailFrom"); + ABORT_FINALIZE(RS_RET_MAIL_NO_FROM); + } + if(pszTo == NULL) { + errmsg.LogError(NO_ERRCODE, "no recipient address given - specify $ActionMailTo"); + ABORT_FINALIZE(RS_RET_MAIL_NO_TO); + } + + pData->md.smtp.pszFrom = (uchar*) strdup((char*)pszFrom); + pData->md.smtp.pszTo = (uchar*) strdup((char*)pszTo); + + if(pszSubject == NULL) { + /* if no subject is configured, we need just one template string */ + CODE_STD_STRING_REQUESTparseSelectorAct(1) + } else { + CODE_STD_STRING_REQUESTparseSelectorAct(2) + pData->bHaveSubject = 1; + CHKiRet(OMSRsetEntry(*ppOMSR, 1, (uchar*)strdup((char*) pszSubject), OMSR_NO_RQD_TPL_OPTS)); + } + if(pszSrv != NULL) + pData->md.smtp.pszSrv = (uchar*) strdup((char*)pszSrv); + if(pszSrvPort != NULL) + pData->md.smtp.pszSrvPort = (uchar*) strdup((char*)pszSrvPort); + pData->bEnableBody = bEnableBody; + + /* process template */ + CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_FileFormat")); +CODE_STD_FINALIZERparseSelectorAct +ENDparseSelectorAct + + +/* Free string config variables and reset them to NULL (not necessarily the default!) */ +static rsRetVal freeConfigVariables(void) +{ + DEFiRet; + + if(pszSrv != NULL) { + free(pszSrv); + pszSrv = NULL; + } + if(pszSrvPort != NULL) { + free(pszSrvPort); + pszSrvPort = NULL; + } + if(pszFrom != NULL) { + free(pszFrom); + pszFrom = NULL; + } + if(pszTo != NULL) { + free(pszTo); + pszTo = NULL; + } + + RETiRet; +} + + +BEGINmodExit +CODESTARTmodExit + /* cleanup our allocations */ + freeConfigVariables(); + + /* release what we no longer need */ + objRelease(errmsg, CORE_COMPONENT); +ENDmodExit + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_OMOD_QUERIES +ENDqueryEtryPt + + +/* Reset config variables for this module to default values. + */ +static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) +{ + DEFiRet; + bEnableBody = 1; + iRet = freeConfigVariables(); + RETiRet; +} + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ +CODEmodInit_QueryRegCFSLineHdlr + /* tell which objects we need */ + CHKiRet(objUse(errmsg, CORE_COMPONENT)); + + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpserver", 0, eCmdHdlrGetWord, NULL, &pszSrv, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpport", 0, eCmdHdlrGetWord, NULL, &pszSrvPort, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailfrom", 0, eCmdHdlrGetWord, NULL, &pszFrom, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailto", 0, eCmdHdlrGetWord, NULL, &pszTo, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsubject", 0, eCmdHdlrGetWord, NULL, &pszSubject, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailenablebody", 0, eCmdHdlrBinary, NULL, &bEnableBody, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr( (uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); +ENDmodInit + +/* vim:set ai: + */ diff --git a/plugins/omrelp/omrelp.c b/plugins/omrelp/omrelp.c index 39d2581..0457168 100644 --- a/plugins/omrelp/omrelp.c +++ b/plugins/omrelp/omrelp.c @@ -53,7 +53,7 @@ DEFobjCurrIf(errmsg) static relpEngine_t *pRelpEngine; /* our relp engine */ typedef struct _instanceData { - char f_hname[MAXHOSTNAMELEN+1]; + char *f_hname; int compressionLevel; /* 0 - no compression, else level for zlib */ char *port; int bInitialConnect; /* is this the initial connection request of our module? (0-no, 1-yes) */ @@ -98,6 +98,9 @@ CODESTARTfreeInstance if(pData->pRelpClt != NULL) relpEngineCltDestruct(pRelpEngine, &pData->pRelpClt); + if(pData->f_hname != NULL) + free(pData->f_hname); + ENDfreeInstance @@ -284,10 +287,11 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) /* TODO: make this if go away! */ if(*p == ';') { *p = '\0'; /* trick to obtain hostname (later)! */ - strcpy(pData->f_hname, (char*) q); + CHKmalloc(pData->f_hname = strdup((char*) q)); *p = ';'; - } else - strcpy(pData->f_hname, (char*) q); + } else { + CHKmalloc(pData->f_hname = strdup((char*) q)); + } /* process template */ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_ForwardFormat")); |