diff options
Diffstat (limited to 'plugins')
38 files changed, 878 insertions, 150 deletions
diff --git a/plugins/im3195/Makefile.am b/plugins/im3195/Makefile.am index bfceb71e..5af0b6f5 100644 --- a/plugins/im3195/Makefile.am +++ b/plugins/im3195/Makefile.am @@ -1,7 +1,7 @@ pkglib_LTLIBRARIES = im3195.la im3195_la_SOURCES = im3195.c -im3195_la_CPPFLAGS = $(rsrt_cflags) $(pthreads_cflags) $(LIBLOGGING_CFLAGS) +im3195_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBLOGGING_CFLAGS) im3195_la_LDFLAGS = -module -avoid-version im3195_la_LIBADD = $(LIBLOGGING_LIBS) diff --git a/plugins/im3195/im3195.c b/plugins/im3195/im3195.c index 32dd8dc1..1c2502fe 100644 --- a/plugins/im3195/im3195.c +++ b/plugins/im3195/im3195.c @@ -83,7 +83,7 @@ void OnReceive(srAPIObj __attribute__((unused)) *pMyAPI, srSLMGObj* pSLMG) srSLMGGetRawMSG(pSLMG, &pszRawMsg); parseAndSubmitMessage(fromHost, fromHostIP, pszRawMsg, strlen((char*)pszRawMsg), - MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_FULL_DELAY); + MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_FULL_DELAY, (uchar*)"im3195"); } diff --git a/plugins/imdiag/Makefile.am b/plugins/imdiag/Makefile.am new file mode 100644 index 00000000..33e86e93 --- /dev/null +++ b/plugins/imdiag/Makefile.am @@ -0,0 +1,6 @@ +pkglib_LTLIBRARIES = imdiag.la + +imdiag_la_SOURCES = imdiag.c +imdiag_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) +imdiag_la_LDFLAGS = -module -avoid-version +imdiag_la_LIBADD = diff --git a/plugins/imdiag/imdiag.c b/plugins/imdiag/imdiag.c new file mode 100644 index 00000000..3cd2dcf8 --- /dev/null +++ b/plugins/imdiag/imdiag.c @@ -0,0 +1,197 @@ +/* imdiag.c + * This is a diagnostics module, primarily meant for troubleshooting + * and information about the runtime state of rsyslog. It is implemented + * as an input plugin, because that interface best suits our needs + * and also enables us to inject test messages (something not yet + * implemented). + * + * File begun on 2008-07-25 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 <stdlib.h> +#include <assert.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <stdarg.h> +#include <ctype.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> +#if HAVE_FCNTL_H +#include <fcntl.h> +#endif +#include "rsyslog.h" +//#include "dirty.h" +#include "cfsysline.h" +#include "module-template.h" +#include "net.h" +#include "netstrm.h" +#include "errmsg.h" + +MODULE_TYPE_INPUT + +/* static data */ +DEF_IMOD_STATIC_DATA +DEFobjCurrIf(net) +DEFobjCurrIf(netstrm) +DEFobjCurrIf(errmsg) + +/* Module static data */ +netstrms_t *pNS; /**< pointer to network stream subsystem */ +netstrm_t **ppLstn[10]; /**< our netstream listners */ +int iLstnMax = 0; /**< max nbr of listeners currently supported */ + + +/* config settings */ + + +/* add a listen socket to our listen socket array. This is a callback + * invoked from the netstrm class. -- rgerhards, 2008-04-23 + */ +static rsRetVal +addTcpLstn(void *pUsr, netstrm_t *pLstn) +{ + DEFiRet; + + ISOBJ_TYPE_assert(pLstn, netstrm); + + if(iLstnMax >= sizeof(ppLstn)/sizeof(netstrm_t)) + ABORT_FINALIZE(RS_RET_MAX_LSTN_REACHED); + + ppLstn[pThis->iLstnMax] = pLstn; + ++iLstnMax; + +finalize_it: + RETiRet; +} + + +/* initialize network stream subsystem */ +static rsRetVal +initNetstrm(void) +{ + DEFiRet; + + /* prepare network stream subsystem */ + CHKiRet(netstrms.Construct(&pNS)); + CHKiRet(netstrms.SetDrvrMode(pNS, 0)); /* always plain text */ + //CHKiRet(netstrms.SetDrvrAuthMode(pThis->pNS, pThis->pszDrvrAuthMode)); + //CHKiRet(netstrms.SetDrvrPermPeers(pThis->pNS, pThis->pPermPeers)); + // TODO: set driver! + CHKiRet(netstrms.ConstructFinalize(pThis->pNS)); + + /* set up listeners */ + CHKiRet(netstrm.LstnInit(pNS, NULL, addTcpLstn, "127.0.0.1", "44514", 1)); + +finalize_it: + if(iRet != RS_RET_OK) { + if(pThis->pNS != NULL) + netstrms.Destruct(&pThis->pNS); + } + RETiRet; +} + + +/* This function is called to gather input. In our case, it is a bit abused + * to drive the listener loop for the diagnostics code. + */ +BEGINrunInput +CODESTARTrunInput +ENDrunInput + + +/* initialize and return if will run or not */ +BEGINwillRun +CODESTARTwillRun + iRet = initNetstrm(); +ENDwillRun + + +BEGINafterRun +CODESTARTafterRun + /* do cleanup here */ + /* finally close our listen streams */ + for(i = 0 ; i < iLstnMax ; ++i) { + netstrm.Destruct(ppLstn + i); + } + + /* destruct netstream subsystem */ + netstrms.Destruct(pNS); +ENDafterRun + + +BEGINmodExit +CODESTARTmodExit + /* release objects we used */ + objRelease(net, LM_NET_FILENAME); + objRelease(netstrm, LM_NETSTRMS_FILENAME); + objRelease(errmsg, CORE_COMPONENT); +ENDmodExit + + +static rsRetVal +resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) +{ + return RS_RET_OK; +} + + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_IMOD_QUERIES +ENDqueryEtryPt + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ +CODEmodInit_QueryRegCFSLineHdlr + pOurTcpsrv = NULL; + /* request objects we use */ + CHKiRet(objUse(net, LM_NET_FILENAME)); + CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME)); + CHKiRet(objUse(errmsg, CORE_COMPONENT)); + +#if 0 + /* register config file handlers */ + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverrun", 0, eCmdHdlrGetWord, + addTCPListener, NULL, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpmaxsessions", 0, eCmdHdlrInt, + NULL, &iTCPSessMax, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverstreamdrivermode", 0, + eCmdHdlrInt, NULL, &iStrmDrvrMode, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverstreamdriverauthmode", 0, + eCmdHdlrGetWord, NULL, &pszStrmDrvrAuthMode, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverstreamdriverpermittedpeer", 0, + eCmdHdlrGetWord, setPermittedPeer, NULL, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, + resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); +#endif +ENDmodInit + + +/* vim:set ai: + */ diff --git a/plugins/imfile/Makefile.am b/plugins/imfile/Makefile.am index a4011d12..551639ba 100644 --- a/plugins/imfile/Makefile.am +++ b/plugins/imfile/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = imfile.la imfile_la_SOURCES = imfile.c -imfile_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags) +imfile_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imfile_la_LDFLAGS = -module -avoid-version imfile_la_LIBADD = diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 3bc07b9c..b0211bf6 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -94,6 +94,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); + MsgSetInputName(pMsg, "imfile"); MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine)); MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine)); @@ -102,7 +103,6 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) pMsg->iFacility = LOG_FAC(pInfo->iFacility); pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); pMsg->bParseHOSTNAME = 0; - datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */ CHKiRet(submitMsg(pMsg)); finalize_it: RETiRet; diff --git a/plugins/imgssapi/Makefile.am b/plugins/imgssapi/Makefile.am index a5cce320..ea016353 100644 --- a/plugins/imgssapi/Makefile.am +++ b/plugins/imgssapi/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = imgssapi.la imgssapi_la_SOURCES = imgssapi.c -imgssapi_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags) +imgssapi_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imgssapi_la_LDFLAGS = -module -avoid-version -imgssapi_la_LIBADD = $(gss_libs) +imgssapi_la_LIBADD = $(GSS_LIBS) diff --git a/plugins/imgssapi/imgssapi.c b/plugins/imgssapi/imgssapi.c index df080020..debe935e 100644 --- a/plugins/imgssapi/imgssapi.c +++ b/plugins/imgssapi/imgssapi.c @@ -55,6 +55,7 @@ #include "tcps_sess.h" #include "errmsg.h" #include "netstrm.h" +#include "glbl.h" MODULE_TYPE_INPUT @@ -80,6 +81,7 @@ DEFobjCurrIf(gssutil) DEFobjCurrIf(errmsg) DEFobjCurrIf(netstrm) DEFobjCurrIf(net) +DEFobjCurrIf(glbl) static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change for multiple instances */ static gss_cred_id_t gss_server_creds = GSS_C_NO_CREDENTIAL; @@ -266,7 +268,8 @@ doOpenLstnSocks(tcpsrv_t *pSrv) if(pGSrv->allowedMethods) { /* fallback to plain TCP */ CHKiRet(tcpsrv.create_tcp_socket(pSrv)); - dbgprintf("Opened %d syslog TCP port(s).\n", *pRet); + } else { + ABORT_FINALIZE(RS_RET_GSS_ERR); } } @@ -333,6 +336,11 @@ addGSSListener(void __attribute__((unused)) *pVal, uchar *pNewVal) } finalize_it: + if(iRet != RS_RET_OK) { + errmsg.LogError(0, NO_ERRCODE, "error %d trying to add listener", iRet); + if(pOurTcpsrv != NULL) + tcpsrv.Destruct(&pOurTcpsrv); + } RETiRet; } @@ -393,10 +401,14 @@ OnSessAcceptGSS(tcpsrv_t *pThis, tcps_sess_t *pSess) allowedMethods = pGSrv->allowedMethods; if(allowedMethods & ALLOWEDMETHOD_GSS) { /* Buffer to store raw message in case that - * gss authentication fails halfway through. + * gss authentication fails halfway through. This buffer + * is currently dynamically allocated, for performance + * reasons we should look for a better way to do it. + * rgerhars, 2008-09-02 */ - char buf[MAXLINE]; + char *buf; int ret = 0; + CHKmalloc(buf = (char*) malloc(sizeof(char) * (glbl.GetMaxLine() + 1))); dbgprintf("GSS-API Trying to accept TCP session %p\n", pSess); @@ -649,6 +661,7 @@ CODESTARTmodExit objRelease(tcpsrv, LM_TCPSRV_FILENAME); objRelease(gssutil, LM_GSSUTIL_FILENAME); objRelease(errmsg, CORE_COMPONENT); + objRelease(glbl, CORE_COMPONENT); objRelease(netstrm, LM_NETSTRM_FILENAME); objRelease(net, LM_NET_FILENAME); ENDmodExit @@ -690,6 +703,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(tcpsrv, LM_TCPSRV_FILENAME)); CHKiRet(objUse(gssutil, LM_GSSUTIL_FILENAME)); CHKiRet(objUse(errmsg, CORE_COMPONENT)); + CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(netstrm, LM_NETSTRM_FILENAME)); CHKiRet(objUse(net, LM_NET_FILENAME)); diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am index 8f50cfb2..5d4d0465 100644 --- a/plugins/imklog/Makefile.am +++ b/plugins/imklog/Makefile.am @@ -11,6 +11,6 @@ if ENABLE_IMKLOG_LINUX imklog_la_SOURCES += linux.c module.h ksym.c ksyms.h ksym_mod.c endif -imklog_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags) +imklog_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imklog_la_LDFLAGS = -module -avoid-version imklog_la_LIBADD = diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c index 39b644c0..090c4e9b 100644 --- a/plugins/imklog/bsd.c +++ b/plugins/imklog/bsd.c @@ -110,15 +110,33 @@ klogWillRun(void) static void readklog(void) { - char *p, *q, line[MAXLINE + 1]; + char *p, *q; int len, i; + int iMaxLine; + uchar bufRcv[4096+1]; + uchar *pRcv = NULL; /* receive buffer */ + + iMaxLine = klog_getMaxLine(); + + /* we optimize performance: if iMaxLine is below 4K (which it is in almost all + * cases, we use a fixed buffer on the stack. Only if it is higher, heap memory + * is used. We could use alloca() to achive a similar aspect, but there are so + * many issues with alloca() that I do not want to take that route. + * rgerhards, 2008-09-02 + */ + if((size_t) iMaxLine < sizeof(bufRcv) - 1) { + pRcv = bufRcv; + } else { + if((pRcv = (uchar*) malloc(sizeof(uchar) * (iMaxLine + 1))) == NULL) + iMaxLine = sizeof(bufRcv) - 1; /* better this than noting */ + } len = 0; for (;;) { - dbgprintf("----------imklog waiting for kernel log line\n"); - i = read(fklog, line + len, MAXLINE - 1 - len); + dbgprintf("----------imklog(BSD) waiting for kernel log line\n"); + i = read(fklog, pRcv + len, iMaxLine - len); if (i > 0) { - line[i + len] = '\0'; + pRcv[i + len] = '\0'; } else { if (i < 0 && errno != EINTR && errno != EAGAIN) { imklogLogIntMsg(LOG_ERR, @@ -129,20 +147,23 @@ readklog(void) break; } - for (p = line; (q = strchr(p, '\n')) != NULL; p = q + 1) { + for (p = pRcv; (q = strchr(p, '\n')) != NULL; p = q + 1) { *q = '\0'; Syslog(LOG_INFO, (uchar*) p); } len = strlen(p); - if (len >= MAXLINE - 1) { + if (len >= iMaxLine - 1) { Syslog(LOG_INFO, (uchar*)p); len = 0; } if (len > 0) - memmove(line, p, len + 1); + memmove(pRcv, p, len + 1); } if (len > 0) - Syslog(LOG_INFO, (uchar*)line); + Syslog(LOG_INFO, pRcv); + + if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1) + free(pRcv); } diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index 1fbc2874..20bc34ab 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -94,6 +94,8 @@ enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); + MsgSetInputName(pMsg, "imklog"); + MsgSetRawMsg(pMsg, (char*)msg); MsgSetUxTradMsg(pMsg, (char*)msg); MsgSetRawMsg(pMsg, (char*)msg); MsgSetMSG(pMsg, (char*)msg); @@ -104,7 +106,6 @@ enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity) 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: @@ -198,6 +199,17 @@ finalize_it: } +/* helper for some klog drivers which need to know the MaxLine global setting. They can + * not obtain it themselfs, because they are no modules and can not query the object hander. + * It would probably be a good idea to extend the interface to support it, but so far + * we create a (sufficiently valid) work-around. -- rgerhards, 2008-11-24 + */ +int klog_getMaxLine(void) +{ + return glbl.GetMaxLine(); +} + + BEGINrunInput CODESTARTrunInput /* this is an endless loop - it is terminated when the thread is diff --git a/plugins/imklog/imklog.h b/plugins/imklog/imklog.h index 0847140b..37bd58b0 100644 --- a/plugins/imklog/imklog.h +++ b/plugins/imklog/imklog.h @@ -58,6 +58,7 @@ rsRetVal imklogLogIntMsg(int priority, char *fmt, ...) __attribute__((format(pri rsRetVal Syslog(int priority, uchar *msg); /* prototypes */ +extern int klog_getMaxLine(void); /* work-around for klog drivers to get configured max line size */ extern int InitKsyms(char *); extern void DeinitKsyms(void); extern int InitMsyms(void); diff --git a/plugins/immark/Makefile.am b/plugins/immark/Makefile.am index 9c0f8f64..6d8ed24a 100644 --- a/plugins/immark/Makefile.am +++ b/plugins/immark/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = immark.la immark_la_SOURCES = immark.c immark.h -immark_la_CPPFLAGS = $(rsrt_cflags) -I$(top_srcdir) $(pthreads_cflags) +immark_la_CPPFLAGS = $(RSRT_CFLAGS) -I$(top_srcdir) $(PTHREADS_CFLAGS) immark_la_LDFLAGS = -module -avoid-version immark_la_LIBADD = diff --git a/plugins/immark/immark.c b/plugins/immark/immark.c index bdca4d58..8504f872 100644 --- a/plugins/immark/immark.c +++ b/plugins/immark/immark.c @@ -41,6 +41,7 @@ #include "cfsysline.h" #include "module-template.h" #include "errmsg.h" +#include "msg.h" MODULE_TYPE_INPUT @@ -76,7 +77,7 @@ CODESTARTrunInput * rgerhards, 2007-12-17 */ CHKiRet(thrdSleep(pThrd, iMarkMessagePeriod, 0)); /* seconds, micro seconds */ - logmsgInternal(NO_ERRCODE, LOG_INFO, (uchar*)"-- MARK --", ADDDATE|MARK); + logmsgInternal(NO_ERRCODE, LOG_INFO, (uchar*)"-- MARK --", MARK); } finalize_it: return iRet; diff --git a/plugins/imrelp/Makefile.am b/plugins/imrelp/Makefile.am index a96e2b42..8c6faff1 100644 --- a/plugins/imrelp/Makefile.am +++ b/plugins/imrelp/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = imrelp.la imrelp_la_SOURCES = imrelp.c -imrelp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(RELP_CFLAGS) $(rsrt_cflags) +imrelp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RELP_CFLAGS) $(RSRT_CFLAGS) imrelp_la_LDFLAGS = -module -avoid-version imrelp_la_LIBADD = $(RELP_LIBS) diff --git a/plugins/imrelp/imrelp.c b/plugins/imrelp/imrelp.c index 5c9bbce1..2255e643 100644 --- a/plugins/imrelp/imrelp.c +++ b/plugins/imrelp/imrelp.c @@ -42,6 +42,7 @@ #include "cfsysline.h" #include "module-template.h" #include "net.h" +#include "msg.h" MODULE_TYPE_INPUT @@ -83,8 +84,8 @@ static relpRetVal onSyslogRcv(uchar *pHostname, uchar __attribute__((unused)) *pIP, uchar *pMsg, size_t lenMsg) { DEFiRet; - parseAndSubmitMessage(pHostname, (uchar*) "[unset]", pMsg, lenMsg, MSG_PARSE_HOSTNAME, - NOFLAG, eFLOWCTL_LIGHT_DELAY); + parseAndSubmitMessage(pHostname, (uchar*) "[unset]", pMsg, lenMsg, PARSE_HOSTNAME, + eFLOWCTL_LIGHT_DELAY, (uchar*)"imrelp", NULL, 0); RETiRet; } diff --git a/plugins/imtcp/Makefile.am b/plugins/imtcp/Makefile.am index de746a95..26653536 100644 --- a/plugins/imtcp/Makefile.am +++ b/plugins/imtcp/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = imtcp.la imtcp_la_SOURCES = imtcp.c -imtcp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags) +imtcp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imtcp_la_LDFLAGS = -module -avoid-version imtcp_la_LIBADD = diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c index 89f1dbcf..19138d94 100644 --- a/plugins/imtcp/imtcp.c +++ b/plugins/imtcp/imtcp.c @@ -80,7 +80,9 @@ static permittedPeers_t *pPermPeersRoot = NULL; /* config settings */ static int iTCPSessMax = 200; /* max number of sessions */ static int iStrmDrvrMode = 0; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */ +static int iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER; /* addtl frame delimiter, e.g. for netscreen, default none */ static uchar *pszStrmDrvrAuthMode = NULL; /* authentication mode to use */ +static uchar *pszInputName = NULL; /* value for inputname property, NULL is OK and handled by core engine */ /* callbacks */ @@ -166,6 +168,8 @@ static rsRetVal addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVa CHKiRet(tcpsrv.SetCBOnRegularClose(pOurTcpsrv, onRegularClose)); CHKiRet(tcpsrv.SetCBOnErrClose(pOurTcpsrv, onErrClose)); CHKiRet(tcpsrv.SetDrvrMode(pOurTcpsrv, iStrmDrvrMode)); + CHKiRet(tcpsrv.SetInputName(pOurTcpsrv, pszInputName == NULL ? (uchar*)"imtcp" : pszInputName)); + CHKiRet(tcpsrv.SetAddtlFrameDelim(pOurTcpsrv, iAddtlFrameDelim)); /* now set optional params, but only if they were actually configured */ if(pszStrmDrvrAuthMode != NULL) { CHKiRet(tcpsrv.SetDrvrAuthMode(pOurTcpsrv, pszStrmDrvrAuthMode)); @@ -239,6 +243,15 @@ resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unus { iTCPSessMax = 200; iStrmDrvrMode = 0; + iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER; + if(pszInputName != NULL) { + free(pszInputName); + pszInputName = NULL; + } + if(pszStrmDrvrAuthMode != NULL) { + free(pszStrmDrvrAuthMode); + pszStrmDrvrAuthMode = NULL; + } return RS_RET_OK; } @@ -273,6 +286,10 @@ CODEmodInit_QueryRegCFSLineHdlr eCmdHdlrGetWord, NULL, &pszStrmDrvrAuthMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverstreamdriverpermittedpeer", 0, eCmdHdlrGetWord, setPermittedPeer, NULL, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserveraddtlframedelimiter", 0, eCmdHdlrInt, + NULL, &iAddtlFrameDelim, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverinputname", 0, + eCmdHdlrGetWord, NULL, &pszInputName, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit diff --git a/plugins/imtemplate/Makefile.am b/plugins/imtemplate/Makefile.am index 0ea4355e..1825b5bc 100644 --- a/plugins/imtemplate/Makefile.am +++ b/plugins/imtemplate/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = imtemplate.la imtemplate_la_SOURCES = imtemplate.c -imtemplate_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags) +imtemplate_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imtemplate_la_LDFLAGS = -module -avoid-version imtemplate_la_LIBADD = diff --git a/plugins/imtemplate/imtemplate.c b/plugins/imtemplate/imtemplate.c index 6d29c4f1..366408a0 100644 --- a/plugins/imtemplate/imtemplate.c +++ b/plugins/imtemplate/imtemplate.c @@ -269,7 +269,6 @@ CODESTARTrunInput pMsg->iFacility = LOG_FAC(pri); pMsg->iSeverity = LOG_PRI(pri); pMsg->bParseHOSTNAME = 0; - getCurrTime(&(pMsg->tTIMESTAMP)); / * use the current time! * / flags |= INTERNAL_MSG; logmsg(pMsg, flags); / * some time, CHKiRet() will work here, too [today NOT!] * / * @@ -315,7 +314,7 @@ CODESTARTwillRun if(udpLstnSocks == NULL) ABORT_FINALIZE(RS_RET_NO_RUN); - if((pRcvBuf = malloc(MAXLINE * sizeof(char))) == NULL) { + if((pRcvBuf = malloc(glbl.GetMaxLine * sizeof(char))) == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } * diff --git a/plugins/imudp/Makefile.am b/plugins/imudp/Makefile.am index 28ee9853..517b1287 100644 --- a/plugins/imudp/Makefile.am +++ b/plugins/imudp/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = imudp.la imudp_la_SOURCES = imudp.c -imudp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags) +imudp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imudp_la_LDFLAGS = -module -avoid-version imudp_la_LIBADD = diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c index b18c0db7..c7e8c1d4 100644 --- a/plugins/imudp/imudp.c +++ b/plugins/imudp/imudp.c @@ -40,6 +40,9 @@ #include "srUtils.h" #include "errmsg.h" #include "glbl.h" +#include "msg.h" +#include "parser.h" +#include "datetime.h" MODULE_TYPE_INPUT @@ -50,7 +53,9 @@ DEF_IMOD_STATIC_DATA DEFobjCurrIf(errmsg) DEFobjCurrIf(glbl) DEFobjCurrIf(net) +DEFobjCurrIf(datetime) +static int iMaxLine; /* maximum UDP message size supported */ static time_t ttLastDiscard = 0; /* timestamp when a message from a non-permitted sender was last discarded * This shall prevent remote DoS when the "discard on disallowed sender" * message is configured to be logged on occurance of such a case. @@ -62,6 +67,8 @@ static uchar *pRcvBuf = NULL; /* receive buffer (for a single packet). We use a * it so that we can check available memory in willRun() and request * termination if we can not get it. -- rgerhards, 2007-12-27 */ +#define TIME_REQUERY_DFLT 2 +static int iTimeRequery = TIME_REQUERY_DFLT;/* how often is time to be queried inside tight recv loop? 0=always */ /* config settings */ @@ -129,20 +136,134 @@ finalize_it: } +/* This function is a helper to runInput. I have extracted it + * from the main loop just so that we do not have that large amount of code + * in a single place. This function takes a socket and pulls messages from + * it until the socket does not have any more waiting. + * rgerhards, 2008-01-08 + * We try to read from the file descriptor until there + * is no more data. This is done in the hope to get better performance + * out of the system. However, this also means that a descriptor + * monopolizes processing while it contains data. This can lead to + * data loss in other descriptors. However, if the system is incapable of + * handling the workload, we will loss data in any case. So it doesn't really + * matter where the actual loss occurs - it is always random, because we depend + * on scheduling order. -- rgerhards, 2008-10-02 + */ +static inline rsRetVal +processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted, + uchar *fromHost, uchar *fromHostFQDN, uchar *fromHostIP) +{ + DEFiRet; + int iNbrTimeUsed; + time_t ttGenTime; + struct syslogTime stTime; + socklen_t socklen; + ssize_t lenRcvBuf; + struct sockaddr_storage frominet; + msg_t *pMsg; + char errStr[1024]; + + iNbrTimeUsed = 0; + while(1) { /* loop is terminated if we have a bad receive, done below in the body */ + socklen = sizeof(struct sockaddr_storage); + lenRcvBuf = recvfrom(fd, (char*) pRcvBuf, iMaxLine, 0, (struct sockaddr *)&frominet, &socklen); + if(lenRcvBuf < 0) { + if(errno != EINTR && errno != EAGAIN) { + rs_strerror_r(errno, errStr, sizeof(errStr)); + DBGPRINTF("INET socket error: %d = %s.\n", errno, errStr); + errmsg.LogError(errno, NO_ERRCODE, "recvfrom inet"); + } + ABORT_FINALIZE(RS_RET_ERR); + } + + /* if we reach this point, we had a good receive and can process the packet received */ + /* check if we have a different sender than before, if so, we need to query some new values */ + if(memcmp(&frominet, frominetPrev, socklen) != 0) { + CHKiRet(net.cvthname(&frominet, fromHost, fromHostFQDN, fromHostIP)); + memcpy(frominetPrev, &frominet, socklen); /* update cache indicator */ + /* Here we check if a host is permitted to send us + * syslog messages. If it isn't, we do not further + * process the message but log a warning (if we are + * configured to do this). + * rgerhards, 2005-09-26 + */ + *pbIsPermitted = net.isAllowedSender((uchar*)"UDP", + (struct sockaddr *)&frominet, (char*)fromHostFQDN); + + if(!*pbIsPermitted) { + DBGPRINTF("%s is not an allowed sender\n", (char*)fromHostFQDN); + if(glbl.GetOption_DisallowWarning) { + time_t tt; + + time(&tt); + if(tt > ttLastDiscard + 60) { + ttLastDiscard = tt; + errmsg.LogError(0, NO_ERRCODE, + "UDP message from disallowed sender %s discarded", + (char*)fromHost); + } + } + } + } + + DBGPRINTF("recv(%d,%d)/%s,acl:%d,msg:%.80s\n", fd, (int) lenRcvBuf, fromHost, *pbIsPermitted, pRcvBuf); + + if(*pbIsPermitted) { + if((iTimeRequery == 0) || (iNbrTimeUsed++ % iTimeRequery) == 0) { + datetime.getCurrTime(&stTime, &ttGenTime); + } + /* we now create our own message object and submit it to the queue */ + CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime)); + /* first trim the buffer to what we have actually received */ + CHKmalloc(pMsg->pszRawMsg = malloc(sizeof(uchar)* lenRcvBuf)); + memcpy(pMsg->pszRawMsg, pRcvBuf, lenRcvBuf); + pMsg->iLenRawMsg = lenRcvBuf; + MsgSetInputName(pMsg, "imudp"); + MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); + pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; + pMsg->bParseHOSTNAME = 1; + MsgSetRcvFrom(pMsg, (char*)fromHost); + CHKiRet(MsgSetRcvFromIP(pMsg, fromHostIP)); + CHKiRet(submitMsg(pMsg)); + } + } + + +finalize_it: + RETiRet; +} + + /* This function is called to gather input. + * Note that udpLstnSocks must be non-NULL because otherwise we would not have + * indicated that we want to run (or we have a programming error ;)). -- rgerhards, 2008-10-02 + * rgerhards, 2008-10-07: I have implemented a very simple, yet in most cases probably + * highly efficient "name caching". Before querying a name, I now check if the name to be + * queried is the same as the one queried in the last message processed. If that is the + * case, we can simple re-use the previous value. This algorithm works quite well with + * few sender, especially if they emit messages in bursts. The more sender and the + * more intermixed messages arrive, the less this algorithm works, but the overhead + * is so minimal (a simple memory compare and move) that this does not hurt. Even + * with a real name lookup cache, this optimization here is useful as it is quicker + * than even a cache lookup). */ BEGINrunInput int maxfds; int nfds; int i; fd_set readfds; - struct sockaddr_storage frominet; - socklen_t socklen; + struct sockaddr_storage frominetPrev; + int bIsPermitted; uchar fromHost[NI_MAXHOST]; uchar fromHostIP[NI_MAXHOST]; uchar fromHostFQDN[NI_MAXHOST]; - ssize_t l; CODESTARTrunInput + /* start "name caching" algo by making sure the previous system indicator + * is invalidated. + */ + bIsPermitted = 0; + memset(&frominetPrev, 0, sizeof(frominetPrev)); /* this is an endless loop - it is terminated when the thread is * signalled to do so. This, however, is handled by the framework, * right into the sleep below. @@ -157,17 +278,14 @@ CODESTARTrunInput maxfds = 0; FD_ZERO (&readfds); - /* Add the UDP listen sockets to the list of read descriptors. - */ - if(udpLstnSocks != NULL) { - for (i = 0; i < *udpLstnSocks; i++) { - if (udpLstnSocks[i+1] != -1) { - if(Debug) - net.debugListenInfo(udpLstnSocks[i+1], "UDP"); - FD_SET(udpLstnSocks[i+1], &readfds); - if(udpLstnSocks[i+1]>maxfds) maxfds=udpLstnSocks[i+1]; - } - } + /* Add the UDP listen sockets to the list of read descriptors. */ + for (i = 0; i < *udpLstnSocks; i++) { + if (udpLstnSocks[i+1] != -1) { + if(Debug) + net.debugListenInfo(udpLstnSocks[i+1], "UDP"); + FD_SET(udpLstnSocks[i+1], &readfds); + if(udpLstnSocks[i+1]>maxfds) maxfds=udpLstnSocks[i+1]; + } } if(Debug) { dbgprintf("--------imUDP calling select, active file descriptors (max %d): ", maxfds); @@ -180,53 +298,14 @@ CODESTARTrunInput /* wait for io to become ready */ nfds = select(maxfds+1, (fd_set *) &readfds, NULL, NULL, NULL); - if(udpLstnSocks != NULL) { - for (i = 0; nfds && i < *udpLstnSocks; i++) { - if (FD_ISSET(udpLstnSocks[i+1], &readfds)) { - socklen = sizeof(frominet); - l = recvfrom(udpLstnSocks[i+1], (char*) pRcvBuf, MAXLINE - 1, 0, - (struct sockaddr *)&frominet, &socklen); - if (l > 0) { - if(net.cvthname(&frominet, fromHost, fromHostFQDN, fromHostIP) == RS_RET_OK) { - dbgprintf("Message from inetd socket: #%d, host: %s\n", - udpLstnSocks[i+1], fromHost); - /* Here we check if a host is permitted to send us - * syslog messages. If it isn't, we do not further - * process the message but log a warning (if we are - * configured to do this). - * rgerhards, 2005-09-26 - */ - if(net.isAllowedSender((uchar*) "UDP", - (struct sockaddr *)&frominet, (char*)fromHostFQDN)) { - parseAndSubmitMessage(fromHost, fromHostIP, pRcvBuf, l, - MSG_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_NO_DELAY); - } else { - dbgprintf("%s is not an allowed sender\n", (char*)fromHostFQDN); - if(glbl.GetOption_DisallowWarning) { - time_t tt; - - time(&tt); - if(tt > ttLastDiscard + 60) { - ttLastDiscard = tt; - errmsg.LogError(0, NO_ERRCODE, - "UDP message from disallowed sender %s discarded", - (char*)fromHost); - } - } - } - } - } else if (l < 0 && errno != EINTR && errno != EAGAIN) { - char errStr[1024]; - rs_strerror_r(errno, errStr, sizeof(errStr)); - dbgprintf("INET socket error: %d = %s.\n", errno, errStr); - errmsg.LogError(errno, NO_ERRCODE, "recvfrom inet"); - /* should be harmless */ - sleep(1); - } - --nfds; /* indicate we have processed one */ - } - } - } + for(i = 0; nfds && i < *udpLstnSocks; i++) { + if(FD_ISSET(udpLstnSocks[i+1], &readfds)) { + processSocket(udpLstnSocks[i+1], &frominetPrev, &bIsPermitted, + fromHost, fromHostFQDN, fromHostIP); + --nfds; /* indicate we have processed one descriptor */ + } + } + /* end of a run, back to loop for next recv() */ } return iRet; @@ -242,7 +321,9 @@ CODESTARTwillRun if(udpLstnSocks == NULL) ABORT_FINALIZE(RS_RET_NO_RUN); - if((pRcvBuf = malloc(MAXLINE * sizeof(char))) == NULL) { + iMaxLine = glbl.GetMaxLine(); + + if((pRcvBuf = malloc((iMaxLine + 1) * sizeof(char))) == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } finalize_it: @@ -269,6 +350,7 @@ CODESTARTmodExit /* release what we no longer need */ objRelease(errmsg, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); + objRelease(datetime, CORE_COMPONENT); objRelease(net, LM_NET_FILENAME); ENDmodExit @@ -288,6 +370,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a net.closeUDPListenSockets(udpLstnSocks); udpLstnSocks = NULL; } + iTimeRequery = TIME_REQUERY_DFLT;/* the default is to query only every second time */ return RS_RET_OK; } @@ -298,6 +381,7 @@ CODESTARTmodInit CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); + CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(net, LM_NET_FILENAME)); /* register config file handlers */ @@ -305,9 +389,10 @@ CODEmodInit_QueryRegCFSLineHdlr addListner, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"udpserveraddress", 0, eCmdHdlrGetWord, NULL, &pszBindAddr, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"udpservertimerequery", 0, eCmdHdlrInt, + NULL, &iTimeRequery, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit -/* - * vi:set ai: +/* vim:set ai: */ diff --git a/plugins/imuxsock/Makefile.am b/plugins/imuxsock/Makefile.am index 11a0ba3a..a2fe0baa 100644 --- a/plugins/imuxsock/Makefile.am +++ b/plugins/imuxsock/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = imuxsock.la imuxsock_la_SOURCES = imuxsock.c -imuxsock_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags) +imuxsock_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imuxsock_la_LDFLAGS = -module -avoid-version imuxsock_la_LIBADD = diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c index 05bcb642..1d88a2b5 100644 --- a/plugins/imuxsock/imuxsock.c +++ b/plugins/imuxsock/imuxsock.c @@ -42,6 +42,7 @@ #include "errmsg.h" #include "net.h" #include "glbl.h" +#include "msg.h" MODULE_TYPE_INPUT @@ -71,14 +72,18 @@ static int startIndexUxLocalSockets; /* process funix from that index on (used t * read-only after startup */ static int funixParseHost[MAXFUNIX] = { 0, }; /* should parser parse host name? read-only after startup */ -static int funixFlags[MAXFUNIX] = { ADDDATE, }; /* should parser parse host name? read-only after startup */ +static int funixFlags[MAXFUNIX] = { IGNDATE, }; /* should parser parse host name? read-only after startup */ static uchar *funixn[MAXFUNIX] = { (uchar*) _PATH_LOG }; /* read-only after startup */ +static uchar *funixHName[MAXFUNIX] = { NULL, }; /* host-name override - if set, use this instead of actual name */ +static int funixFlowCtl[MAXFUNIX] = { eFLOWCTL_NO_DELAY, }; /* flow control settings for this socket */ static int funix[MAXFUNIX] = { -1, }; /* read-only after startup */ static int nfunix = 1; /* number of Unix sockets open / read-only after startup */ /* config settings */ static int bOmitLocalLogging = 0; static uchar *pLogSockName = NULL; +static uchar *pLogHostName = NULL; /* host name to use with this socket */ +static int bUseFlowCtl = 0; /* use flow control or not (if yes, only LIGHT is used! */ static int bIgnoreTimestamp = 1; /* ignore timestamps present in the incoming message? */ @@ -89,10 +94,18 @@ static int bIgnoreTimestamp = 1; /* ignore timestamps present in the incoming me static rsRetVal setSystemLogTimestampIgnore(void __attribute__((unused)) *pVal, int iNewVal) { DEFiRet; - funixFlags[0] = iNewVal ? ADDDATE : NOFLAG; + funixFlags[0] = iNewVal ? IGNDATE : NOFLAG; RETiRet; } +/* set flowcontrol for the system log socket + */ +static rsRetVal setSystemLogFlowControl(void __attribute__((unused)) *pVal, int iNewVal) +{ + DEFiRet; + funixFlowCtl[0] = iNewVal ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY; + RETiRet; +} /* add an additional listen socket. Socket names are added * until the array is filled up. It is never reset, only at @@ -100,6 +113,7 @@ static rsRetVal setSystemLogTimestampIgnore(void __attribute__((unused)) *pVal, * TODO: we should change the array to a list so that we * can support any number of listen socket names. * rgerhards, 2007-12-20 + * added capability to specify hostname for socket -- rgerhards, 2008-08-01 */ static rsRetVal addLstnSocketName(void __attribute__((unused)) *pVal, uchar *pNewVal) { @@ -110,7 +124,10 @@ static rsRetVal addLstnSocketName(void __attribute__((unused)) *pVal, uchar *pNe else { funixParseHost[nfunix] = 0; } - funixFlags[nfunix] = bIgnoreTimestamp ? ADDDATE : NOFLAG; + funixHName[nfunix] = pLogHostName; + pLogHostName = NULL; /* re-init for next, not freed because funixHName[] now owns it */ + funixFlowCtl[nfunix] = bUseFlowCtl ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY; + funixFlags[nfunix] = bIgnoreTimestamp ? IGNDATE : NOFLAG; funixn[nfunix++] = pNewVal; } else { @@ -134,6 +151,10 @@ static rsRetVal discardFunixn(void) free(funixn[i]); funixn[i] = NULL; } + if(funixHName[i] != NULL) { + free(funixHName[i]); + funixHName[i] = NULL; + } } return RS_RET_OK; @@ -144,7 +165,6 @@ static int create_unix_socket(const char *path) { struct sockaddr_un sunx; int fd; - char line[MAXLINE +1]; if (path[0] == '\0') return -1; @@ -155,11 +175,9 @@ static int create_unix_socket(const char *path) sunx.sun_family = AF_UNIX; (void) strncpy(sunx.sun_path, path, sizeof(sunx.sun_path)); fd = socket(AF_UNIX, SOCK_DGRAM, 0); - if (fd < 0 || bind(fd, (struct sockaddr *) &sunx, - SUN_LEN(&sunx)) < 0 || + if (fd < 0 || bind(fd, (struct sockaddr *) &sunx, SUN_LEN(&sunx)) < 0 || chmod(path, 0666) < 0) { - snprintf(line, sizeof(line), "cannot create %s", path); - errmsg.LogError(errno, NO_ERRCODE, "%s", line); + errmsg.LogError(errno, NO_ERRCODE, "connot create '%s'", path); dbgprintf("cannot create %s (%d).\n", path, errno); close(fd); return -1; @@ -171,18 +189,41 @@ static int create_unix_socket(const char *path) /* This function receives data from a socket indicated to be ready * to receive and submits the message received for processing. * rgerhards, 2007-12-20 + * Interface changed so that this function is passed the array index + * of the socket which is to be processed. This eases access to the + * growing number of properties. -- rgerhards, 2008-08-01 */ -static rsRetVal readSocket(int fd, int bParseHost, int flags) +static rsRetVal readSocket(int fd, int iSock) { DEFiRet; int iRcvd; - uchar line[MAXLINE +1]; + int iMaxLine; + uchar bufRcv[4096+1]; + uchar *pRcv = NULL; /* receive buffer */ + + assert(iSock >= 0); + + iMaxLine = glbl.GetMaxLine(); - iRcvd = recv(fd, line, MAXLINE - 1, 0); + /* we optimize performance: if iMaxLine is below 4K (which it is in almost all + * cases, we use a fixed buffer on the stack. Only if it is higher, heap memory + * is used. We could use alloca() to achive a similar aspect, but there are so + * many issues with alloca() that I do not want to take that route. + * rgerhards, 2008-09-02 + */ + if((size_t) iMaxLine < sizeof(bufRcv) - 1) { + pRcv = bufRcv; + } else { + CHKmalloc(pRcv = (uchar*) malloc(sizeof(uchar) * (iMaxLine + 1))); + } + + iRcvd = recv(fd, pRcv, iMaxLine, 0); dbgprintf("Message from UNIX socket: #%d\n", fd); if (iRcvd > 0) { - parseAndSubmitMessage(glbl.GetLocalHostName(), (uchar*)"127.0.0.1", line, - iRcvd, bParseHost, flags, eFLOWCTL_NO_DELAY); + parseAndSubmitMessage(funixHName[iSock] == NULL ? glbl.GetLocalHostName() : funixHName[iSock], + (uchar*)"127.0.0.1", pRcv, + iRcvd, funixParseHost[iSock] ? (funixFlags[iSock] | PARSE_HOSTNAME) : funixFlags[iSock], + funixFlowCtl[iSock], (uchar*)"imuxsock", NULL, 0); } else if (iRcvd < 0 && errno != EINTR) { char errStr[1024]; rs_strerror_r(errno, errStr, sizeof(errStr)); @@ -190,12 +231,15 @@ static rsRetVal readSocket(int fd, int bParseHost, int flags) errmsg.LogError(errno, NO_ERRCODE, "recvfrom UNIX"); } +finalize_it: + if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1) + free(pRcv); + RETiRet; } -/* This function is called to gather input. - */ +/* This function is called to gather input. */ BEGINrunInput int maxfds; int nfds; @@ -237,7 +281,7 @@ CODESTARTrunInput for (i = 0; i < nfunix && nfds > 0; i++) { if ((fd = funix[i]) != -1 && FD_ISSET(fd, &readfds)) { - readSocket(fd, funixParseHost[i], funixFlags[i]); + readSocket(fd, i); --nfds; /* indicate we have processed one */ } } @@ -282,6 +326,9 @@ CODESTARTafterRun /* free no longer needed string */ if(pLogSockName != NULL) free(pLogSockName); + if(pLogHostName != NULL) { + free(pLogHostName); + } discardFunixn(); nfunix = 1; @@ -307,10 +354,15 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a free(pLogSockName); pLogSockName = NULL; } + if(pLogHostName != NULL) { + free(pLogHostName); + pLogHostName = NULL; + } discardFunixn(); nfunix = 1; bIgnoreTimestamp = 1; + bUseFlowCtl = 0; return RS_RET_OK; } @@ -324,6 +376,8 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); + dbgprintf("imuxsock version %s initializing\n", PACKAGE_VERSION); + /* initialize funixn[] array */ for(i = 1 ; i < MAXFUNIX ; ++i) { funixn[i] = NULL; @@ -337,18 +391,24 @@ CODEmodInit_QueryRegCFSLineHdlr NULL, &bIgnoreTimestamp, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketname", 0, eCmdHdlrGetWord, NULL, &pLogSockName, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensockethostname", 0, eCmdHdlrGetWord, + NULL, &pLogHostName, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketflowcontrol", 0, eCmdHdlrBinary, + NULL, &bUseFlowCtl, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"addunixlistensocket", 0, eCmdHdlrGetWord, addLstnSocketName, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); /* the following one is a (dirty) trick: the system log socket is not added via - * an "addUnixListenSocket" config format. As such, the timestamp can not be modified - * via $InputUnixListenSocketIgnoreMsgTimestamp". So we need to add a special directive + * an "addUnixListenSocket" config format. As such, it's properties can not be modified + * via $InputUnixListenSocket*". So we need to add a special directive * for that. We should revisit all of that once we have the new config format... * rgerhards, 2008-03-06 */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketignoremsgtimestamp", 0, eCmdHdlrBinary, setSystemLogTimestampIgnore, NULL, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketflowcontrol", 0, eCmdHdlrBinary, + setSystemLogFlowControl, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit /* vim:set ai: */ diff --git a/plugins/omgssapi/Makefile.am b/plugins/omgssapi/Makefile.am index c2cbe387..a57a64b3 100644 --- a/plugins/omgssapi/Makefile.am +++ b/plugins/omgssapi/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = omgssapi.la omgssapi_la_SOURCES = omgssapi.c -omgssapi_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags) +omgssapi_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) omgssapi_la_LDFLAGS = -module -avoid-version -omgssapi_la_LIBADD = $(gss_libs) +omgssapi_la_LIBADD = $(GSS_LIBS) diff --git a/plugins/omgssapi/omgssapi.c b/plugins/omgssapi/omgssapi.c index 82fca2db..e0cc8af6 100644 --- a/plugins/omgssapi/omgssapi.c +++ b/plugins/omgssapi/omgssapi.c @@ -378,6 +378,7 @@ ENDtryResume BEGINdoAction char *psz; /* temporary buffering */ register unsigned l; + int iMaxLine; CODESTARTdoAction switch (pData->eDestState) { case eDestFORW_SUSP: @@ -392,10 +393,11 @@ CODESTARTdoAction case eDestFORW: dbgprintf(" %s:%s/%s\n", pData->f_hname, getFwdSyslogPt(pData), "tcp-gssapi"); + iMaxLine = glbl.GetMaxLine(); psz = (char*) ppString[0]; l = strlen((char*) psz); - if (l > MAXLINE) - l = MAXLINE; + if((int) l > iMaxLine) + l = iMaxLine; # ifdef USE_NETZIP /* Check if we should compress and, if so, do it. We also @@ -407,10 +409,14 @@ CODESTARTdoAction * rgerhards, 2006-11-30 */ if(pData->compressionLevel && (l > MIN_SIZE_FOR_COMPRESS)) { - Bytef out[MAXLINE+MAXLINE/100+12] = "z"; + Bytef *out; uLongf destLen = sizeof(out) / sizeof(Bytef); uLong srcLen = l; int ret; + /* TODO: optimize malloc sequence? -- rgerhards, 2008-09-02 */ + CHKmalloc(out = (Bytef*) malloc(iMaxLine + iMaxLine/100 + 12)); + out[0] = 'z'; + out[1] = '\0'; ret = compress2((Bytef*) out+1, &destLen, (Bytef*) psz, srcLen, pData->compressionLevel); dbgprintf("Compressing message, length was %d now %d, return state %d.\n", @@ -442,6 +448,7 @@ CODESTARTdoAction } break; } +finalize_it: ENDdoAction diff --git a/plugins/omlibdbi/Makefile.am b/plugins/omlibdbi/Makefile.am index d224f9e4..6a26f807 100644 --- a/plugins/omlibdbi/Makefile.am +++ b/plugins/omlibdbi/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = omlibdbi.la omlibdbi_la_SOURCES = omlibdbi.c -omlibdbi_la_CPPFLAGS = -I$(top_srcdir) $(libdbi_cflags) $(pthreads_cflags) $(rsrt_cflags) +omlibdbi_la_CPPFLAGS = -I$(top_srcdir) $(LIBDBI_CFLAGS) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) omlibdbi_la_LDFLAGS = -module -avoid-version -omlibdbi_la_LIBADD = $(libdbi_libs) +omlibdbi_la_LIBADD = $(LIBDBI_LIBS) diff --git a/plugins/ommail/Makefile.am b/plugins/ommail/Makefile.am index fa470a43..97c9296a 100644 --- a/plugins/ommail/Makefile.am +++ b/plugins/ommail/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = ommail.la ommail_la_SOURCES = ommail.c -ommail_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags) +ommail_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) ommail_la_LDFLAGS = -module -avoid-version ommail_la_LIBADD = diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c index 4bbb844a..5faadce3 100644 --- a/plugins/ommail/ommail.c +++ b/plugins/ommail/ommail.c @@ -60,10 +60,18 @@ DEF_OMOD_STATIC_DATA DEFobjCurrIf(errmsg) DEFobjCurrIf(glbl) +/* we add a little support for multiple recipients. We do this via a + * singly-linked list, enqueued from the top. -- rgerhards, 2008-08-04 + */ +typedef struct toRcpt_s toRcpt_t; +struct toRcpt_s { + uchar *pszTo; + toRcpt_t *pNext; +}; +static toRcpt_t *lstRcpt = NULL; 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) */ @@ -76,7 +84,7 @@ typedef struct _instanceData { uchar *pszSrv; uchar *pszSrvPort; uchar *pszFrom; - uchar *pszTo; + toRcpt_t *lstRcpt; char RcvBuf[1024]; /* buffer for receiving server responses */ size_t lenRcvBuf; size_t iRcvBuf; /* current index into the rcvBuf (buf empty if iRcvBuf == lenRcvBuf) */ @@ -85,6 +93,83 @@ typedef struct _instanceData { } md; /* mode-specific data */ } instanceData; +/* forward definitions (as few as possible) */ +static rsRetVal Send(int sock, char *msg, size_t len); +static rsRetVal readResponse(instanceData *pData, int *piState, int iExpected); + + +/* helpers for handling the recipient lists */ + +/* destroy a complete recipient list */ +static void lstRcptDestruct(toRcpt_t *pRoot) +{ + toRcpt_t *pDel; + + while(pRoot != NULL) { + pDel = pRoot; + pRoot = pRoot->pNext; + /* ready to disalloc */ + free(pDel->pszTo); + free(pDel); + } +} + +/* This function is called when a new recipient email address is to be + * added. rgerhards, 2008-08-04 + */ +static rsRetVal +addRcpt(void __attribute__((unused)) *pVal, uchar *pNewVal) +{ + DEFiRet; + toRcpt_t *pNew = NULL; + + CHKmalloc(pNew = calloc(1, sizeof(toRcpt_t))); + + pNew->pszTo = pNewVal; + pNew->pNext = lstRcpt; + lstRcpt = pNew; + + dbgprintf("ommail::addRcpt adds recipient %s\n", pNewVal); + +finalize_it: + if(iRet != RS_RET_OK) { + if(pNew != NULL) + free(pNew); + free(pNewVal); /* in any case, this is no longer needed */ + } + + RETiRet; +} + + +/* output the recipient list to the mail server + * iStatusToCheck < 0 means no checking should happen + */ +static rsRetVal +WriteRcpts(instanceData *pData, uchar *pszOp, size_t lenOp, int iStatusToCheck) +{ + toRcpt_t *pRcpt; + int iState; + DEFiRet; + + assert(pData != NULL); + assert(pszOp != NULL); + assert(lenOp != 0); + + for(pRcpt = pData->md.smtp.lstRcpt ; pRcpt != NULL ; pRcpt = pRcpt->pNext) { + dbgprintf("Sending '%s: <%s>'\n", pszOp, pRcpt->pszTo); + CHKiRet(Send(pData->md.smtp.sock, (char*)pszOp, lenOp)); + CHKiRet(Send(pData->md.smtp.sock, ": <", sizeof(": <") - 1)); + CHKiRet(Send(pData->md.smtp.sock, (char*)pRcpt->pszTo, strlen((char*)pRcpt->pszTo))); + CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); + if(iStatusToCheck >= 0) + CHKiRet(readResponse(pData, &iState, iStatusToCheck)); + } + +finalize_it: + RETiRet; +} +/* end helpers for handling the recipient lists */ BEGINcreateInstance CODESTARTcreateInstance @@ -107,8 +192,7 @@ CODESTARTfreeInstance 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); + lstRcptDestruct(pData->md.smtp.lstRcpt); } ENDfreeInstance @@ -426,10 +510,7 @@ sendSMTP(instanceData *pData, uchar *body, uchar *subject) 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(WriteRcpts(pData, (uchar*)"RCPT TO", sizeof("RCPT TO") - 1, 250)); CHKiRet(Send(pData->md.smtp.sock, "DATA\r\n", sizeof("DATA\r\n") - 1)); CHKiRet(readResponse(pData, &iState, 354)); @@ -443,9 +524,7 @@ sendSMTP(instanceData *pData, uchar *body, uchar *subject) 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(WriteRcpts(pData, (uchar*)"To", sizeof("To") - 1, -1)); CHKiRet(Send(pData->md.smtp.sock, "Subject: ", sizeof("Subject: ") - 1)); CHKiRet(Send(pData->md.smtp.sock, (char*)subject, strlen((char*)subject))); @@ -531,13 +610,14 @@ CODESTARTparseSelectorAct errmsg.LogError(0, RS_RET_MAIL_NO_FROM, "no sender address given - specify $ActionMailFrom"); ABORT_FINALIZE(RS_RET_MAIL_NO_FROM); } - if(pszTo == NULL) { + if(lstRcpt == NULL) { errmsg.LogError(0, RS_RET_MAIL_NO_TO, "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); + pData->md.smtp.lstRcpt = lstRcpt; /* we "hand over" this memory */ + lstRcpt = NULL; /* note: this is different from pre-3.21.2 versions! */ if(pszSubject == NULL) { /* if no subject is configured, we need just one template string */ @@ -576,10 +656,8 @@ static rsRetVal freeConfigVariables(void) free(pszFrom); pszFrom = NULL; } - if(pszTo != NULL) { - free(pszTo); - pszTo = NULL; - } + lstRcptDestruct(lstRcpt); + lstRcpt = NULL; RETiRet; } @@ -621,10 +699,12 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); + dbgprintf("ommail version %s initializing\n", VERSION); + 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 *)"actionmailto", 0, eCmdHdlrGetWord, addRcpt, NULL, 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)); diff --git a/plugins/ommysql/Makefile.am b/plugins/ommysql/Makefile.am index d5433a40..e253b9da 100644 --- a/plugins/ommysql/Makefile.am +++ b/plugins/ommysql/Makefile.am @@ -1,8 +1,8 @@ pkglib_LTLIBRARIES = ommysql.la ommysql_la_SOURCES = ommysql.c ommysql.h -ommysql_la_CPPFLAGS = $(rsrt_cflags) $(mysql_cflags) $(pthreads_cflags) +ommysql_la_CPPFLAGS = $(RSRT_CFLAGS) $(MYSQL_CFLAGS) $(PTHREADS_CFLAGS) ommysql_la_LDFLAGS = -module -avoid-version -ommysql_la_LIBADD = $(mysql_libs) +ommysql_la_LIBADD = $(MYSQL_LIBS) EXTRA_DIST = createDB.sql contrib/delete_mysql diff --git a/plugins/ommysql/ommysql.c b/plugins/ommysql/ommysql.c index 22abb1d2..ecf738a9 100644 --- a/plugins/ommysql/ommysql.c +++ b/plugins/ommysql/ommysql.c @@ -35,8 +35,7 @@ #include <signal.h> #include <errno.h> #include <time.h> -#include <mysql/mysql.h> -#include <mysql/errmsg.h> +#include <mysql.h> #include "dirty.h" #include "syslogd-types.h" #include "srUtils.h" diff --git a/plugins/ompgsql/Makefile.am b/plugins/ompgsql/Makefile.am index cc1c5f49..607239cd 100644 --- a/plugins/ompgsql/Makefile.am +++ b/plugins/ompgsql/Makefile.am @@ -1,8 +1,8 @@ pkglib_LTLIBRARIES = ompgsql.la ompgsql_la_SOURCES = ompgsql.c ompgsql.h -ompgsql_la_CPPFLAGS = -I$(top_srcdir) $(pgsql_cflags) $(rsrt_cflags) +ompgsql_la_CPPFLAGS = -I$(top_srcdir) $(PGSQL_CFLAGS) $(RSRT_CFLAGS) ompgsql_la_LDFLAGS = -module -avoid-version -ompgsql_la_LIBADD = $(pgsql_libs) +ompgsql_la_LIBADD = $(PGSQL_LIBS) EXTRA_DIST = createDB.sql diff --git a/plugins/omrelp/Makefile.am b/plugins/omrelp/Makefile.am index f8384f42..906aab43 100644 --- a/plugins/omrelp/Makefile.am +++ b/plugins/omrelp/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = omrelp.la omrelp_la_SOURCES = omrelp.c -omrelp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(RELP_CFLAGS) $(rsrt_cflags) +omrelp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RELP_CFLAGS) $(RSRT_CFLAGS) omrelp_la_LDFLAGS = -module -avoid-version omrelp_la_LIBADD = $(RELP_LIBS) diff --git a/plugins/omrelp/omrelp.c b/plugins/omrelp/omrelp.c index 71d6e797..8d74c82f 100644 --- a/plugins/omrelp/omrelp.c +++ b/plugins/omrelp/omrelp.c @@ -159,8 +159,8 @@ CODESTARTdoAction lenMsg = strlen((char*) pMsg); /* TODO: don't we get this? */ /* TODO: think about handling oversize messages! */ - if(lenMsg > MAXLINE) - lenMsg = MAXLINE; + if((int) lenMsg > glbl.GetMaxLine()) + lenMsg = glbl.GetMaxLine(); /* forward */ ret = relpCltSendSyslog(pData->pRelpClt, (uchar*) pMsg, lenMsg); diff --git a/plugins/omsnmp/Makefile.am b/plugins/omsnmp/Makefile.am index d784faca..f75fb091 100644 --- a/plugins/omsnmp/Makefile.am +++ b/plugins/omsnmp/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = omsnmp.la omsnmp_la_SOURCES = omsnmp.c omsnmp.h -omsnmp_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags) +omsnmp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) omsnmp_la_LDFLAGS = -module -avoid-version -omsnmp_la_LIBADD = $(snmp_libs) +omsnmp_la_LIBADD = $(SNMP_LIBS) diff --git a/plugins/omtemplate/Makefile.am b/plugins/omtemplate/Makefile.am new file mode 100644 index 00000000..e816c7c6 --- /dev/null +++ b/plugins/omtemplate/Makefile.am @@ -0,0 +1,8 @@ +pkglib_LTLIBRARIES = omtemplate.la + +omtemplate_la_SOURCES = omtemplate.c +omtemplate_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) +omtemplate_la_LDFLAGS = -module -avoid-version +omtemplate_la_LIBADD = + +EXTRA_DIST = diff --git a/plugins/omtemplate/omtemplate.c b/plugins/omtemplate/omtemplate.c new file mode 100644 index 00000000..e35968ad --- /dev/null +++ b/plugins/omtemplate/omtemplate.c @@ -0,0 +1,220 @@ +/* omtemplate.c + * This is a template for an output module. It implements a very + * simple single-threaded output, just as thought of by the output + * plugin interface. + * + * NOTE: read comments in module-template.h for more specifics! + * + * File begun on 2009-03-16 by RGerhards + * + * Copyright 2009 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 <signal.h> +#include <errno.h> +#include <time.h> +#include "dirty.h" +#include "syslogd-types.h" +#include "srUtils.h" +#include "template.h" +#include "module-template.h" +#include "errmsg.h" +#include "cfsysline.h" + +MODULE_TYPE_OUTPUT + +/* internal structures + */ +DEF_OMOD_STATIC_DATA +DEFobjCurrIf(errmsg) + +typedef struct _instanceData { + /* here you need to define all action-specific data. A record of type + * instanceData will be handed over to each instance of the action. Keep + * in mind that there may be several invocations of the same type of action + * inside rsyslog.conf, and this is what keeps them apart. Do NOT use + * static data for this! + */ + unsigned iSrvPort; /* sample: server port */ +} instanceData; + +/* config variables + * For the configuration interface, we need to keep track of some settings. This + * is done in global variables. It works as follows: when configuration statements + * are entered, the config file handler (or custom function) sets the global + * variable here. When the action then actually is instantiated, this handler + * copies over to instanceData whatever configuration settings (from the global + * variables) apply. The global variables are NEVER used inside an action + * instance (at least this is how it is supposed to work ;) + */ +static int iSrvPort = 0; /* sample: server port */ + + +BEGINcreateInstance +CODESTARTcreateInstance +ENDcreateInstance + + +BEGINisCompatibleWithFeature +CODESTARTisCompatibleWithFeature + /* use this to specify if select features are supported by this + * plugin. If not, the framework will handle that. Currently, only + * RepeatedMsgReduction ("last message repeated n times") is optional. + */ + if(eFeat == sFEATURERepeatedMsgReduction) + iRet = RS_RET_OK; +ENDisCompatibleWithFeature + + +BEGINfreeInstance +CODESTARTfreeInstance + /* this is a cleanup callback. All dynamically-allocated resources + * in instance data must be cleaned up here. Prime examples are + * malloc()ed memory, file & database handles and the like. + */ +ENDfreeInstance + + +BEGINdbgPrintInstInfo +CODESTARTdbgPrintInstInfo + /* permits to spit out some debug info */ +ENDdbgPrintInstInfo + + +BEGINtryResume +CODESTARTtryResume + /* this is called when an action has been suspended and the + * rsyslog core tries to resume it. The action must then + * retry (if possible) and report RS_RET_OK if it succeeded + * or RS_RET_SUSPENDED otherwise. + * Note that no data can be written in this callback, as it is + * not present. Prime examples of what can be retried are + * reconnects to remote hosts, reconnects to database, + * opening of files and the like. + * If there is no retry-type of operation, the action may + * return RS_RET_OK, so that it will get called on its doAction + * entry point (where it receives data), retries there, and + * immediately returns RS_RET_SUSPENDED if that does not work + * out. This disables some optimizations in the core's retry logic, + * but is a valid and expected behaviour. Note that it is also OK + * for the retry entry point to return OK but the immediately following + * doAction call to fail. In real life, for example, a buggy com line + * may cause such behaviour. + * Note that there is no guarantee that the core will very quickly + * call doAction after the retry succeeded. Today, it does, but that may + * not always be the case. + */ +ENDtryResume + +BEGINdoAction +CODESTARTdoAction + /* this is where you receive the message and need to carry out the + * action. Data is provided in ppString[i] where 0 <= i <= num of strings + * requested. + * Return RS_RET_OK if all goes well, RS_RET_SUSPENDED if the action can + * currently not complete, or an error code or RS_RET_DISABLED. The later + * two should only be returned if there is no hope that the action can be + * restored unless an rsyslog restart (prime example is an invalid config). + * Error code or RS_RET_DISABLED permanently disables the action, up to + * the next restart. + */ +ENDdoAction + + +BEGINparseSelectorAct +CODESTARTparseSelectorAct +CODE_STD_STRING_REQUESTparseSelectorAct(1) + /* first check if this config line is actually for us + * This is a clumpsy interface. We receive the action-part of the selector line + * and need to look at the first characters. If they match our signature + * ":omtemplate:", then we need to instantiate an action. It is recommended that + * newer actions just watch for the template and all other parameters are passed in + * via $-config-lines, this will hopefully be compatbile with future config syntaxes. + * If we do not detect our signature, we must return with RS_RET_CONFLINE_UNPROCESSED + * and NOT do anything else. + */ + if(strncmp((char*) p, ":omtemplate:", sizeof(":omtemplate:") - 1)) { + ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); + } + + /* ok, if we reach this point, we have something for us */ + p += sizeof(":omtemplate:") - 1; /* eat indicator sequence (-1 because of '\0'!) */ + CHKiRet(createInstance(&pData)); + + /* check if a non-standard template is to be applied */ + if(*(p-1) == ';') + --p; + /* if we have, call rsyslog runtime to get us template. Note that StdFmt below is + * the standard name. Currently, we may need to patch tools/syslogd.c if we need + * to add a new standard template. + */ + CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_RQD_TPL_OPT_SQL, (uchar*) " StdFmt")); + + /* if we reach this point, all went well, and we can copy over to instanceData + * those configuration elements that we need. + */ + pData->iSrvPort = (unsigned) iSrvPort; /* set configured port */ + +CODE_STD_FINALIZERparseSelectorAct +ENDparseSelectorAct + + +BEGINmodExit +CODESTARTmodExit +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; + iSrvPort = 0; /* zero is the default port */ + RETiRet; +} + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ +CODEmodInit_QueryRegCFSLineHdlr + CHKiRet(objUse(errmsg, CORE_COMPONENT)); + /* register our config handlers */ + /* confguration parameters MUST always be specified in lower case! */ + CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionomtemplteserverport", 0, eCmdHdlrInt, NULL, &iSrvPort, STD_LOADABLE_MODULE_ID)); + /* "resetconfigvariables" should be provided. Notat that it is a chained directive */ + CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); +ENDmodInit + +/* vi:set ai: + */ diff --git a/plugins/omtesting/Makefile.am b/plugins/omtesting/Makefile.am index 8e98ca63..4700e1eb 100644 --- a/plugins/omtesting/Makefile.am +++ b/plugins/omtesting/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = omtesting.la omtesting_la_SOURCES = omtesting.c -omtesting_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags) +omtesting_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) omtesting_la_LDFLAGS = -module -avoid-version omtesting_la_LIBADD = |