diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2012-04-23 14:51:34 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2012-04-23 14:51:34 +0200 |
commit | 2eea95f626badb5a93ff7eca97cc68e5d2f3940a (patch) | |
tree | c7467c2ace398cda5d39e0f6fbda07e38fdc8e5c /runtime | |
parent | 7d8ac48a4a214da917f7455f24b4c292c3e6d015 (diff) | |
parent | 9b06a4c26422b0a8727e1b3c6cc7141226186105 (diff) | |
download | rsyslog-2eea95f626badb5a93ff7eca97cc68e5d2f3940a.tar.gz rsyslog-2eea95f626badb5a93ff7eca97cc68e5d2f3940a.tar.xz rsyslog-2eea95f626badb5a93ff7eca97cc68e5d2f3940a.zip |
Merge branch 'master' into master-elasticsearch
Conflicts:
plugins/omelasticsearch/omelasticsearch.c
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/cfsysline.c | 69 | ||||
-rw-r--r-- | runtime/errmsg.c | 4 | ||||
-rw-r--r-- | runtime/glbl.c | 214 | ||||
-rw-r--r-- | runtime/glbl.h | 34 | ||||
-rw-r--r-- | runtime/msg.c | 172 | ||||
-rw-r--r-- | runtime/net.c | 52 | ||||
-rw-r--r-- | runtime/net.h | 6 | ||||
-rw-r--r-- | runtime/queue.c | 13 | ||||
-rw-r--r-- | runtime/queue.h | 1 | ||||
-rw-r--r-- | runtime/rsyslog.h | 1 | ||||
-rw-r--r-- | runtime/ruleset.c | 15 | ||||
-rw-r--r-- | runtime/ruleset.h | 16 |
12 files changed, 438 insertions, 159 deletions
diff --git a/runtime/cfsysline.c b/runtime/cfsysline.c index 7814e86a..af88b3de 100644 --- a/runtime/cfsysline.c +++ b/runtime/cfsysline.c @@ -155,36 +155,6 @@ finalize_it: } -/* Parse a number from the configuration line. - * rgerhards, 2007-07-31 - */ -static rsRetVal doGetInt(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal) -{ - uchar *p; - DEFiRet; - int64 i; - - assert(pp != NULL); - assert(*pp != NULL); - - CHKiRet(parseIntVal(pp, &i)); - p = *pp; - - if(pSetHdlr == NULL) { - /* we should set value directly to var */ - *((int*)pVal) = (int) i; - } else { - /* we set value via a set function */ - CHKiRet(pSetHdlr(pVal, (int) i)); - } - - *pp = p; - -finalize_it: - RETiRet; -} - - /* Parse a size from the configuration line. This is basically an integer * syntax, but modifiers may be added after the integer (e.g. 1k to mean * 1024). The size must immediately follow the number. Note that the @@ -238,7 +208,44 @@ finalize_it: } -/* Parse and interpet a $FileCreateMode and $umask line. This function +/* Parse a number from the configuration line. + * rgerhards, 2007-07-31 + */ +static rsRetVal doGetInt(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal) +{ + uchar *p; + DEFiRet; + int64 i; + uchar errMsg[256]; /* for dynamic error messages */ + + assert(pp != NULL); + assert(*pp != NULL); + + CHKiRet(doGetSize(pp, NULL,&i)); + p = *pp; + if(i > 2147483648ll) { /*2^31*/ + snprintf((char*) errMsg, sizeof(errMsg)/sizeof(uchar), + "value %lld too large for integer argument.", i); + errmsg.LogError(0, RS_RET_INVALID_VALUE, "%s", errMsg); + ABORT_FINALIZE(RS_RET_INVALID_VALUE); + } + + if(pSetHdlr == NULL) { + /* we should set value directly to var */ + *((int*)pVal) = (int) i; + } else { + /* we set value via a set function */ + CHKiRet(pSetHdlr(pVal, (int) i)); + } + + *pp = p; + +finalize_it: + RETiRet; +} + + +/* Parse and interpret a $FileCreateMode and $umask line. This function * pulls the creation mode and, if successful, stores it * into the global variable so that the rest of rsyslogd * opens files with that mode. Any previous value will be diff --git a/runtime/errmsg.c b/runtime/errmsg.c index 06c553be..dcb5b185 100644 --- a/runtime/errmsg.c +++ b/runtime/errmsg.c @@ -83,13 +83,13 @@ LogError(int iErrno, int iErrCode, char *fmt, ... ) if(iErrno != 0) { rs_strerror_r(iErrno, errStr, sizeof(errStr)); - if(iErrCode == NO_ERRCODE) { + if(iErrCode == NO_ERRCODE || iErrCode == RS_RET_ERR) { snprintf(msg, sizeof(msg), "%s: %s", buf, errStr); } else { snprintf(msg, sizeof(msg), "%s: %s [try http://www.rsyslog.com/e/%d ]", buf, errStr, iErrCode * -1); } } else { - if(iErrCode == NO_ERRCODE) { + if(iErrCode == NO_ERRCODE || iErrCode == RS_RET_ERR) { snprintf(msg, sizeof(msg), "%s", buf); } else { snprintf(msg, sizeof(msg), "%s [try http://www.rsyslog.com/e/%d ]", buf, iErrCode * -1); diff --git a/runtime/glbl.c b/runtime/glbl.c index 885d8468..537b7b4f 100644 --- a/runtime/glbl.c +++ b/runtime/glbl.c @@ -11,21 +11,19 @@ * * This file is part of the rsyslog runtime library. * - * The rsyslog runtime library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The rsyslog runtime library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>. - * - * A copy of the GPL can be found in the file "COPYING" in this distribution. - * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * -or- + * see COPYING.ASL20 in the source distribution + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include "config.h" @@ -45,6 +43,7 @@ #include "atomic.h" #include "errmsg.h" #include "rainerscript.h" +#include "net.h" /* some defaults */ #ifndef DFLT_NETSTRM_DRVR @@ -55,6 +54,7 @@ DEFobjStaticHelpers DEFobjCurrIf(prop) DEFobjCurrIf(errmsg) +DEFobjCurrIf(net) /* static data * For this object, these variables are obviously what makes the "meat" of the @@ -69,11 +69,12 @@ static int iDefPFFamily = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) static int bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records during DNS lookup */ static int option_DisallowWarning = 1; /* complain if message from disallowed sender is received */ static int bDisableDNS = 0; /* don't look up IP addresses of remote messages */ +static prop_t *propLocalIPIF = NULL;/* IP address to report for the local host (default is 127.0.0.1) */ static prop_t *propLocalHostName = NULL;/* our hostname as FQDN - read-only after startup */ -static uchar *LocalHostName = NULL;/* our hostname - read-only after startup */ +static uchar *LocalHostName = NULL;/* our hostname - read-only after startup, except HUP */ static uchar *LocalHostNameOverride = NULL;/* user-overridden hostname - read-only after startup */ -static uchar *LocalFQDNName = NULL;/* our hostname as FQDN - read-only after startup */ -static uchar *LocalDomain; /* our local domain name - read-only after startup */ +static uchar *LocalFQDNName = NULL;/* our hostname as FQDN - read-only after startup, except HUP */ +static uchar *LocalDomain = NULL;/* our local domain name - read-only after startup, except HUP */ static char **StripDomains = NULL;/* these domains may be stripped before writing logs - r/o after s.u., never touched by init */ static char **LocalHosts = NULL;/* these hosts are logged with their hostname - read-only after startup, never touched by init */ static uchar *pszDfltNetstrmDrvr = NULL; /* module name of default netstream driver */ @@ -139,15 +140,12 @@ SIMP_PROP(DefPFFamily, iDefPFFamily, int) /* note that in the future we may chec SIMP_PROP(DropMalPTRMsgs, bDropMalPTRMsgs, int) SIMP_PROP(Option_DisallowWarning, option_DisallowWarning, int) SIMP_PROP(DisableDNS, bDisableDNS, int) -SIMP_PROP(LocalDomain, LocalDomain, uchar*) SIMP_PROP(StripDomains, StripDomains, char**) SIMP_PROP(LocalHosts, LocalHosts, char**) #ifdef USE_UNLIMITED_SELECT SIMP_PROP(FdSetSize, iFdSetSize, int) #endif -SIMP_PROP_SET(LocalFQDNName, LocalFQDNName, uchar*) -SIMP_PROP_SET(LocalHostName, LocalHostName, uchar*) SIMP_PROP_SET(DfltNetstrmDrvr, pszDfltNetstrmDrvr, uchar*) /* TODO: use custom function which frees existing value */ SIMP_PROP_SET(DfltNetstrmDrvrCAF, pszDfltNetstrmDrvrCAF, uchar*) /* TODO: use custom function which frees existing value */ SIMP_PROP_SET(DfltNetstrmDrvrKeyFile, pszDfltNetstrmDrvrKeyFile, uchar*) /* TODO: use custom function which frees existing value */ @@ -176,6 +174,60 @@ static void SetGlobalInputTermination(void) } +/* set the local host IP address to a specific string. Helper to + * small set of functions. No checks done, caller must ensure it is + * ok to call. Most importantly, the IP address must not already have + * been set. -- rgerhards, 2012-03-21 + */ +static inline rsRetVal +storeLocalHostIPIF(uchar *myIP) +{ + DEFiRet; + CHKiRet(prop.Construct(&propLocalIPIF)); + CHKiRet(prop.SetString(propLocalIPIF, myIP, ustrlen(myIP))); + CHKiRet(prop.ConstructFinalize(propLocalIPIF)); + DBGPRINTF("rsyslog/glbl: using '%s' as localhost IP\n", myIP); +finalize_it: + RETiRet; +} + + +/* This function is used to set the IP address that is to be + * reported for the local host. Note that in order to ease things + * for the v6 config interface, we do not allow to set this more + * than once. + * rgerhards, 2012-03-21 + */ +static rsRetVal +setLocalHostIPIF(void __attribute__((unused)) *pVal, uchar *pNewVal) +{ + uchar myIP[128]; + rsRetVal localRet; + DEFiRet; + + CHKiRet(objUse(net, CORE_COMPONENT)); + + if(propLocalIPIF != NULL) { + errmsg.LogError(0, RS_RET_ERR, "$LocalHostIPIF is already set " + "and cannot be reset; place it at TOP OF rsyslog.conf!"); + ABORT_FINALIZE(RS_RET_ERR_WRKDIR); + } + + localRet = net.GetIFIPAddr(pNewVal, AF_UNSPEC, myIP, (int) sizeof(myIP)); + if(localRet != RS_RET_OK) { + errmsg.LogError(0, RS_RET_ERR, "$LocalHostIPIF: IP address for interface " + "'%s' cannnot be obtained - ignoring directive", pNewVal); + } else { + storeLocalHostIPIF(myIP); + } + + +finalize_it: + free(pNewVal); /* no longer needed -> is in prop! */ + RETiRet; +} + + /* This function is used to set the global work directory name. * It verifies that the provided directory actually exists and * emits an error message if not. @@ -226,6 +278,36 @@ finalize_it: RETiRet; } +/* return our local IP. + * If no local IP is set, "127.0.0.1" is selected *and* set. This + * is an intensional side effect that we do in order to keep things + * consistent and avoid config errors (this will make us not accept + * setting the local IP address once a module has obtained it - so + * it forces the $LocalHostIPIF directive high up in rsyslog.conf) + * rgerhards, 2012-03-21 + */ +static prop_t* +GetLocalHostIP(void) +{ + if(propLocalIPIF == NULL) + storeLocalHostIPIF((uchar*)"127.0.0.1"); + return(propLocalIPIF); +} + + +/* set our local hostname. Free previous hostname, if it was already set. + * Note that we do now do this in a thread + * "once in a lifetime" action which can not be undone. -- gerhards, 2009-07-20 + */ +static rsRetVal +SetLocalHostName(uchar *newname) +{ + free(LocalHostName); + LocalHostName = newname; + return RS_RET_OK; +} + + /* return our local hostname. if it is not set, "[localhost]" is returned */ static uchar* @@ -251,6 +333,26 @@ done: } +/* set our local domain name. Free previous domain, if it was already set. + */ +static rsRetVal +SetLocalDomain(uchar *newname) +{ + free(LocalDomain); + LocalDomain = newname; + return RS_RET_OK; +} + + +/* return our local hostname. if it is not set, "[localhost]" is returned + */ +static uchar* +GetLocalDomain(void) +{ + return LocalDomain; +} + + /* generate the local hostname property. This must be done after the hostname info * has been set as well as PreserveFQDN. * rgerhards, 2009-06-30 @@ -295,6 +397,14 @@ GetLocalHostNameProp(void) } +static rsRetVal +SetLocalFQDNName(uchar *newname) +{ + free(LocalFQDNName); + LocalFQDNName = newname; + return RS_RET_OK; +} + /* return the current localhost name as FQDN (requires FQDN to be set) * TODO: we should set the FQDN ourselfs in here! */ @@ -362,6 +472,7 @@ CODESTARTobjQueryInterface(glbl) pIf->GetWorkDir = GetWorkDir; pIf->GenerateLocalHostNameProperty = GenerateLocalHostNameProperty; pIf->GetLocalHostNameProp = GetLocalHostNameProp; + pIf->GetLocalHostIP = GetLocalHostIP; pIf->SetGlobalInputTermination = SetGlobalInputTermination; pIf->GetGlobalInputTermState = GetGlobalInputTermState; #define SIMP_PROP(name) \ @@ -397,30 +508,18 @@ ENDobjQueryInterface(glbl) */ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) { - if(pszDfltNetstrmDrvr != NULL) { - free(pszDfltNetstrmDrvr); - pszDfltNetstrmDrvr = NULL; - } - if(pszDfltNetstrmDrvrCAF != NULL) { - free(pszDfltNetstrmDrvrCAF); - pszDfltNetstrmDrvrCAF = NULL; - } - if(pszDfltNetstrmDrvrKeyFile != NULL) { - free(pszDfltNetstrmDrvrKeyFile); - pszDfltNetstrmDrvrKeyFile = NULL; - } - if(pszDfltNetstrmDrvrCertFile != NULL) { - free(pszDfltNetstrmDrvrCertFile); - pszDfltNetstrmDrvrCertFile = NULL; - } - if(LocalHostNameOverride != NULL) { - free(LocalHostNameOverride); - LocalHostNameOverride = NULL; - } - if(pszWorkDir != NULL) { - free(pszWorkDir); - pszWorkDir = NULL; - } + free(pszDfltNetstrmDrvr); + pszDfltNetstrmDrvr = NULL; + free(pszDfltNetstrmDrvrCAF); + pszDfltNetstrmDrvrCAF = NULL; + free(pszDfltNetstrmDrvrKeyFile); + pszDfltNetstrmDrvrKeyFile = NULL; + free(pszDfltNetstrmDrvrCertFile); + pszDfltNetstrmDrvrCertFile = NULL; + free(LocalHostNameOverride); + LocalHostNameOverride = NULL; + free(pszWorkDir); + pszWorkDir = NULL; bDropMalPTRMsgs = 0; bOptimizeUniProc = 1; bPreserveFQDN = 0; @@ -515,7 +614,7 @@ BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */ CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(errmsg, CORE_COMPONENT)); - /* register config handlers (TODO: we need to implement a way to unregister them) */ + /* config handlers are never unregistered and need not be - we are always loaded ;) */ CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, setWorkDir, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, NULL, &bDropMalPTRMsgs, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriver", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvr, NULL)); @@ -523,6 +622,7 @@ BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriverkeyfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrKeyFile, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercertfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrCertFile, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"localhostname", 0, eCmdHdlrGetWord, NULL, &LocalHostNameOverride, NULL)); + CHKiRet(regCfSysLineHdlr((uchar *)"localhostipif", 0, eCmdHdlrGetWord, setLocalHostIPIF, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"optimizeforuniprocessor", 0, eCmdHdlrBinary, NULL, &bOptimizeUniProc, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"preservefqdn", 0, eCmdHdlrBinary, NULL, &bPreserveFQDN, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"maxmessagesize", 0, eCmdHdlrSize, @@ -537,21 +637,15 @@ ENDObjClassInit(glbl) * rgerhards, 2008-04-17 */ BEGINObjClassExit(glbl, OBJ_IS_CORE_MODULE) /* class, version */ - if(pszDfltNetstrmDrvr != NULL) - free(pszDfltNetstrmDrvr); - if(pszDfltNetstrmDrvrCAF != NULL) - free(pszDfltNetstrmDrvrCAF); - if(pszDfltNetstrmDrvrKeyFile != NULL) - free(pszDfltNetstrmDrvrKeyFile); - if(pszDfltNetstrmDrvrCertFile != NULL) - free(pszDfltNetstrmDrvrCertFile); - if(pszWorkDir != NULL) - free(pszWorkDir); - if(LocalHostName != NULL) - free(LocalHostName); + free(pszDfltNetstrmDrvr); + free(pszDfltNetstrmDrvrCAF); + free(pszDfltNetstrmDrvrKeyFile); + free(pszDfltNetstrmDrvrCertFile); + free(pszWorkDir); + free(LocalDomain); + free(LocalHostName); free(LocalHostNameOverride); - if(LocalFQDNName != NULL) - free(LocalFQDNName); + free(LocalFQDNName); objRelease(prop, CORE_COMPONENT); DESTROY_ATOMIC_HELPER_MUT(mutTerminateInputs); ENDObjClassExit(glbl) diff --git a/runtime/glbl.h b/runtime/glbl.h index 262b2cc2..d2d1e66a 100644 --- a/runtime/glbl.h +++ b/runtime/glbl.h @@ -8,25 +8,23 @@ * Please note that there currently is no glbl.c file as we do not yet * have any implementations. * - * Copyright 2008, 2009 Rainer Gerhards and Adiscon GmbH. + * Copyright 2008-2012 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * - * The rsyslog runtime library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The rsyslog runtime library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>. - * - * A copy of the GPL can be found in the file "COPYING" in this distribution. - * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * -or- + * see COPYING.ASL20 in the source distribution + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #ifndef GLBL_H_INCLUDED @@ -77,7 +75,9 @@ BEGINinterface(glbl) /* name must also be changed in ENDinterface macro! */ */ SIMP_PROP(FdSetSize, int) /* v7: was neeeded to mean v5+v6 - do NOT add anything else for that version! */ - /* next is v8! */ + /* next change is v9! */ + /* v8 - 2012-03-21 */ + prop_t* (*GetLocalHostIP)(void); #undef SIMP_PROP ENDinterface(glbl) #define glblCURR_IF_VERSION 7 /* increment whenever you change the interface structure! */ diff --git a/runtime/msg.c b/runtime/msg.c index 8f92565a..9c7a2203 100644 --- a/runtime/msg.c +++ b/runtime/msg.c @@ -36,6 +36,7 @@ #include <assert.h> #include <ctype.h> #include <sys/socket.h> +#include <sys/sysinfo.h> #include <netdb.h> #include <libestr.h> #include <libee/libee.h> @@ -55,6 +56,7 @@ #include "ruleset.h" #include "prop.h" #include "net.h" +#include "rsconf.h" /* static data */ DEFobjStaticHelpers @@ -261,6 +263,9 @@ static struct { { UCHAR_CONSTANT("190"), 5}, { UCHAR_CONSTANT("191"), 5} }; +static char hexdigit[16] = + {'0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /*syslog facility names (as of RFC5424) */ static char *syslog_fac_names[24] = { "kern", "user", "mail", "daemon", "auth", "syslog", "lpr", @@ -421,7 +426,6 @@ resolveDNS(msg_t *pMsg) { uchar fromHostFQDN[NI_MAXHOST]; DEFiRet; -dbgprintf("XXXX: in msg/resolveDNS (dnscache)\n"); MsgLock(pMsg); CHKiRet(objUse(net, CORE_COMPONENT)); if(pMsg->msgFlags & NEEDS_DNSRESOL) { @@ -562,6 +566,8 @@ propNameStrToID(uchar *pName, propid_t *pPropID) *pPropID = PROP_CEE; } else if(!strcmp((char*) pName, "$bom")) { *pPropID = PROP_SYS_BOM; + } else if(!strcmp((char*) pName, "$uptime")) { + *pPropID = PROP_SYS_UPTIME; } else { *pPropID = PROP_INVALID; iRet = RS_RET_VAR_NOT_FOUND; @@ -1069,6 +1075,12 @@ static rsRetVal MsgSerialize(msg_t *pThis, strm_t *pStrm) objSerializePTR(pStrm, pCSAPPNAME, CSTR); objSerializePTR(pStrm, pCSPROCID, CSTR); objSerializePTR(pStrm, pCSMSGID, CSTR); + + if(pThis->pRuleset != NULL) { + rulesetGetName(pThis->pRuleset); + CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszRuleset"), PROPTYPE_PSZ, + rulesetGetName(pThis->pRuleset))); + } /* offset must be serialized after pszRawMsg, because we need that to obtain the correct * MSG size. @@ -1694,6 +1706,16 @@ void MsgSetRuleset(msg_t *pMsg, ruleset_t *pRuleset) } +/* rgerhards 2012-04-18: set associated ruleset (by ruleset name) + * If ruleset cannot be found, no update is done. + */ +static void +MsgSetRulesetByName(msg_t *pMsg, cstr_t *rulesetName) +{ + rulesetGetRuleset(runConf, &(pMsg->pRuleset), rsCStrGetSzStrNoNULL(rulesetName)); +} + + /* set TAG in msg object * (rewritten 2009-06-18 rgerhards) */ @@ -2351,81 +2373,67 @@ finalize_it: } -/* encode a property in JSON escaped format. This is a helper - * to MsgGetProp. It needs to update all provided parameters. - * Note: Code is borrowed from libee (my own code, so ASL 2.0 - * is fine with it); this function may later be replaced by - * some "better" and more complete implementation (maybe from - * libee or its helpers). - * For performance reasons, we begin to copy the string only - * when we recognice that we actually need to do some escaping. - * rgerhards, 2012-03-16 +/* Encode a JSON value and add it to provided string. Note that + * the string object may be NULL. In this case, it is created + * if and only if escaping is needed. */ static rsRetVal -jsonEncode(uchar **ppRes, unsigned short *pbMustBeFreed, int *pBufLen) +jsonAddVal(uchar *pSrc, unsigned buflen, es_str_t **dst) { - static char hexdigit[16] = - {'0', '1', '2', '3', '4', '5', '6', '7', '8', - '9', 'A', 'B', 'C', 'D', 'E', 'F' }; unsigned char c; es_size_t i; char numbuf[4]; int j; - unsigned buflen; - uchar *pSrc; - es_str_t *dst = NULL; DEFiRet; - pSrc = *ppRes; - buflen = (*pBufLen == -1) ? ustrlen(pSrc) : *pBufLen; for(i = 0 ; i < buflen ; ++i) { c = pSrc[i]; if( (c >= 0x23 && c <= 0x5b) || (c >= 0x5d /* && c <= 0x10FFFF*/) || c == 0x20 || c == 0x21) { /* no need to escape */ - if(dst != NULL) - es_addChar(&dst, c); + if(*dst != NULL) + es_addChar(dst, c); } else { - if(dst == NULL) { + if(*dst == NULL) { if(i == 0) { /* we hope we have only few escapes... */ - dst = es_newStr(buflen+10); + *dst = es_newStr(buflen+10); } else { - dst = es_newStrFromBuf((char*)pSrc, i-1); + *dst = es_newStrFromBuf((char*)pSrc, i-1); } - if(dst == NULL) { + if(*dst == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } } /* we must escape, try RFC4627-defined special sequences first */ switch(c) { case '\0': - es_addBuf(&dst, "\\u0000", 6); + es_addBuf(dst, "\\u0000", 6); break; case '\"': - es_addBuf(&dst, "\\\"", 2); + es_addBuf(dst, "\\\"", 2); break; case '/': - es_addBuf(&dst, "\\/", 2); + es_addBuf(dst, "\\/", 2); break; case '\\': - es_addBuf(&dst, "\\\\", 2); + es_addBuf(dst, "\\\\", 2); break; case '\010': - es_addBuf(&dst, "\\b", 2); + es_addBuf(dst, "\\b", 2); break; case '\014': - es_addBuf(&dst, "\\f", 2); + es_addBuf(dst, "\\f", 2); break; case '\n': - es_addBuf(&dst, "\\n", 2); + es_addBuf(dst, "\\n", 2); break; case '\r': - es_addBuf(&dst, "\\r", 2); + es_addBuf(dst, "\\r", 2); break; case '\t': - es_addBuf(&dst, "\\t", 2); + es_addBuf(dst, "\\t", 2); break; default: /* TODO : proper Unicode encoding (see header comment) */ @@ -2433,12 +2441,38 @@ jsonEncode(uchar **ppRes, unsigned short *pbMustBeFreed, int *pBufLen) numbuf[3-j] = hexdigit[c % 16]; c = c / 16; } - es_addBuf(&dst, "\\u", 2); - es_addBuf(&dst, numbuf, 4); + es_addBuf(dst, "\\u", 2); + es_addBuf(dst, numbuf, 4); break; } } } +finalize_it: + RETiRet; +} + + +/* encode a property in JSON escaped format. This is a helper + * to MsgGetProp. It needs to update all provided parameters. + * Note: Code is borrowed from libee (my own code, so ASL 2.0 + * is fine with it); this function may later be replaced by + * some "better" and more complete implementation (maybe from + * libee or its helpers). + * For performance reasons, we begin to copy the string only + * when we recognice that we actually need to do some escaping. + * rgerhards, 2012-03-16 + */ +static rsRetVal +jsonEncode(uchar **ppRes, unsigned short *pbMustBeFreed, int *pBufLen) +{ + unsigned buflen; + uchar *pSrc; + es_str_t *dst = NULL; + DEFiRet; + + pSrc = *ppRes; + buflen = (*pBufLen == -1) ? ustrlen(pSrc) : *pBufLen; + CHKiRet(jsonAddVal(pSrc, buflen, &dst)); if(dst != NULL) { /* we updated the string and need to replace the @@ -2448,6 +2482,7 @@ jsonEncode(uchar **ppRes, unsigned short *pbMustBeFreed, int *pBufLen) free(*ppRes); *ppRes = (uchar*)es_str2cstr(dst, NULL); *pbMustBeFreed = 1; + *pBufLen = -1; es_deleteStr(dst); } @@ -2456,6 +2491,46 @@ finalize_it: } +/* Format a property as JSON field, that means + * "name"="value" + * where value is JSON-escaped (here we assume that the name + * only contains characters from the valid character set). + * Note: this function duplicates code from jsonEncode(). + * TODO: these two functions should be combined, at least if + * that makes any sense from a performance PoV - definitely + * something to consider at a later stage. rgerhards, 2012-04-19 + */ +static rsRetVal +jsonField(struct templateEntry *pTpe, uchar **ppRes, unsigned short *pbMustBeFreed, int *pBufLen) +{ + unsigned buflen; + uchar *pSrc; + es_str_t *dst = NULL; + DEFiRet; + + pSrc = *ppRes; + buflen = (*pBufLen == -1) ? ustrlen(pSrc) : *pBufLen; + /* we hope we have only few escapes... */ + dst = es_newStr(buflen+es_strlen(pTpe->data.field.fieldName)+15); + es_addChar(&dst, '"'); + es_addStr(&dst, pTpe->data.field.fieldName); + es_addBufConstcstr(&dst, "\"=\""); + CHKiRet(jsonAddVal(pSrc, buflen, &dst)); + es_addChar(&dst, '"'); + + if(*pbMustBeFreed) + free(*ppRes); + /* we know we do not have \0 chars - so the size does not change */ + *pBufLen = es_strlen(dst); + *ppRes = (uchar*)es_str2cstr(dst, NULL); + *pbMustBeFreed = 1; + es_deleteStr(dst); + +finalize_it: + RETiRet; +} + + /* This function returns a string-representation of the * requested message property. This is a generic function used * to abstract properties so that these can be easier @@ -2673,6 +2748,23 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, pRes = (uchar*) "\xEF\xBB\xBF"; *pbMustBeFreed = 0; break; + case PROP_SYS_UPTIME: + { + struct sysinfo s_info; + + if((pRes = (uchar*) MALLOC(sizeof(uchar) * 32)) == NULL) { + RET_OUT_OF_MEMORY; + } + *pbMustBeFreed = 1; + + if(sysinfo(&s_info) < 0) { + *pPropLen = sizeof("**SYSCALL FAILED**") - 1; + return(UCHAR_CONSTANT("**SYSCALL FAILED**")); + } + + snprintf((char*) pRes, sizeof(uchar) * 32, "%ld", s_info.uptime); + } + break; default: /* there is no point in continuing, we may even otherwise render the * error message unreadable. rgerhards, 2007-07-10 @@ -3264,6 +3356,8 @@ dbgprintf("prop repl 4, pRes='%s', len %d\n", pRes, bufLen); *pbMustBeFreed = 1; } else if(pTpe->data.field.options.bJSON) { jsonEncode(&pRes, pbMustBeFreed, &bufLen); + } else if(pTpe->data.field.options.bJSONf) { + jsonField(pTpe, &pRes, pbMustBeFreed, &bufLen); } if(bufLen == -1) @@ -3332,7 +3426,6 @@ msgGetMsgVarNew(msg_t *pThis, uchar *name) propNameStrToID(name, &propid); pszProp = (uchar*) MsgGetProp(pThis, NULL, propid, NULL, &propLen, &bMustBeFreed); -dbgprintf("ZZZZ: var %s returns '%s'\n", name, pszProp); estr = es_newStrFromCStr((char*)pszProp, propLen); if(bMustBeFreed) free(pszProp); @@ -3403,8 +3496,13 @@ rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp) memcpy(&pThis->tRcvdAt, &pProp->val.vSyslogTime, sizeof(struct syslogTime)); } else if(isProp("tTIMESTAMP")) { memcpy(&pThis->tTIMESTAMP, &pProp->val.vSyslogTime, sizeof(struct syslogTime)); + } else if(isProp("pszRuleset")) { + MsgSetRulesetByName(pThis, pProp->val.pStr); } else if(isProp("pszMSG")) { dbgprintf("no longer supported property pszMSG silently ignored\n"); + } else { + dbgprintf("unknown supported property '%s' silently ignored\n", + rsCStrGetSzStrNoNULL(pProp->pcsName)); } finalize_it: diff --git a/runtime/net.c b/runtime/net.c index 4631adc4..dcf9cb52 100644 --- a/runtime/net.c +++ b/runtime/net.c @@ -54,6 +54,9 @@ #include <fnmatch.h> #include <fcntl.h> #include <unistd.h> +#include <ifaddrs.h> +#include <sys/types.h> +#include <arpa/inet.h> #include "syslogd-types.h" #include "module-template.h" @@ -1480,6 +1483,54 @@ finalize_it: } +/* return the IP address (IPv4/6) for the provided interface. Returns + * RS_RET_NOT_FOUND if interface can not be found in interface list. + * The family must be correct (AF_INET vs. AF_INET6, AF_UNSPEC means + * either of *these two*). + * The function re-queries the interface list (at least in theory). + * However, it caches entries in order to avoid too-frequent requery. + * rgerhards, 2012-03-06 + */ +static rsRetVal +getIFIPAddr(uchar *szif, int family, uchar *pszbuf, int lenBuf) +{ + struct ifaddrs * ifaddrs = NULL; + struct ifaddrs * ifa; + void * pAddr; + DEFiRet; + + if(getifaddrs(&ifaddrs) != 0) { + ABORT_FINALIZE(RS_RET_ERR); + } + + for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { + if(strcmp(ifa->ifa_name, (char*)szif)) + continue; + if( (family == AF_INET6 || family == AF_UNSPEC) + && ifa->ifa_addr->sa_family == AF_INET6) { + pAddr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; + inet_ntop(AF_INET6, pAddr, (char*)pszbuf, lenBuf); + break; + } else if(/* (family == AF_INET || family == AF_UNSPEC) + &&*/ ifa->ifa_addr->sa_family == AF_INET) { + pAddr = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; + inet_ntop(AF_INET, pAddr, (char*)pszbuf, lenBuf); + break; + } + } + + if(ifaddrs != NULL) + freeifaddrs(ifaddrs); + + if(ifa == NULL) + iRet = RS_RET_NOT_FOUND; + +finalize_it: + RETiRet; + +} + + /* queryInterface function * rgerhards, 2008-03-05 */ @@ -1511,6 +1562,7 @@ CODESTARTobjQueryInterface(net) pIf->PermittedPeerWildcardMatch = PermittedPeerWildcardMatch; pIf->CmpHost = CmpHost; pIf->HasRestrictions = HasRestrictions; + pIf->GetIFIPAddr = getIFIPAddr; /* data members */ pIf->pACLAddHostnameOnFail = &ACLAddHostnameOnFail; pIf->pACLDontResolve = &ACLDontResolve; diff --git a/runtime/net.h b/runtime/net.h index 101ce79d..1b41c81c 100644 --- a/runtime/net.h +++ b/runtime/net.h @@ -1,6 +1,6 @@ /* Definitions for network-related stuff. * - * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH. + * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * @@ -151,11 +151,13 @@ BEGINinterface(net) /* name must also be changed in ENDinterface macro! */ /* v6 interface additions - 2009-11-16 */ rsRetVal (*HasRestrictions)(uchar *, int *bHasRestrictions); int (*isAllowedSender2)(uchar *pszType, struct sockaddr *pFrom, const char *pszFromHost, int bChkDNS); + /* v7 interface additions - 2012-03-06 */ + rsRetVal (*GetIFIPAddr)(uchar *szif, int family, uchar *pszbuf, int lenBuf); /* data members - these should go away over time... TODO */ int *pACLAddHostnameOnFail; /* add hostname to acl when DNS resolving has failed */ int *pACLDontResolve; /* add hostname to acl instead of resolving it to IP(s) */ ENDinterface(net) -#define netCURR_IF_VERSION 6 /* increment whenever you change the interface structure! */ +#define netCURR_IF_VERSION 7 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObj(net); diff --git a/runtime/queue.c b/runtime/queue.c index cd64b1fc..7085c829 100644 --- a/runtime/queue.c +++ b/runtime/queue.c @@ -2156,13 +2156,16 @@ static rsRetVal qqueuePersist(qqueue_t *pThis, int bIsCheckpoint) CHKiRet(obj.EndSerialize(psQIF)); /* now persist the stream info */ - CHKiRet(strm.Serialize(pThis->tVars.disk.pWrite, psQIF)); - CHKiRet(strm.Serialize(pThis->tVars.disk.pReadDel, psQIF)); + if(pThis->tVars.disk.pWrite != NULL) + CHKiRet(strm.Serialize(pThis->tVars.disk.pWrite, psQIF)); + if(pThis->tVars.disk.pReadDel != NULL) + CHKiRet(strm.Serialize(pThis->tVars.disk.pReadDel, psQIF)); /* tell the input file object that it must not delete the file on close if the queue * is non-empty - but only if we are not during a simple checkpoint */ - if(bIsCheckpoint != QUEUE_CHECKPOINT) { + if(bIsCheckpoint != QUEUE_CHECKPOINT + && pThis->tVars.disk.pReadDel != NULL) { CHKiRet(strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDel, 0)); } @@ -2254,7 +2257,8 @@ CODESTARTobjDestruct(qqueue) * direct queue - because in both cases we have none... ;) * with a child! -- rgerhards, 2008-01-28 */ - if(pThis->qType != QUEUETYPE_DIRECT && !pThis->bEnqOnly && pThis->pqParent == NULL) + if(pThis->qType != QUEUETYPE_DIRECT && !pThis->bEnqOnly && pThis->pqParent == NULL + && pThis->pWtpReg != NULL) ShutdownWorkers(pThis); if(pThis->bIsDA && getPhysicalQueueSize(pThis) > 0 && pThis->bSaveOnShutdown) { @@ -2658,6 +2662,7 @@ DEFpropSetMeth(qqueue, iLowWtrMrk, int) DEFpropSetMeth(qqueue, iDiscardMrk, int) DEFpropSetMeth(qqueue, iFullDlyMrk, int) DEFpropSetMeth(qqueue, iDiscardSeverity, int) +DEFpropSetMeth(qqueue, iLightDlyMrk, int) DEFpropSetMeth(qqueue, bIsDA, int) DEFpropSetMeth(qqueue, iMinMsgsPerWrkr, int) DEFpropSetMeth(qqueue, bSaveOnShutdown, int) diff --git a/runtime/queue.h b/runtime/queue.h index c9fdd94c..3841615a 100644 --- a/runtime/queue.h +++ b/runtime/queue.h @@ -205,6 +205,7 @@ PROTOTYPEpropSetMeth(qqueue, toQShutdown, long); PROTOTYPEpropSetMeth(qqueue, toActShutdown, long); PROTOTYPEpropSetMeth(qqueue, toWrkShutdown, long); PROTOTYPEpropSetMeth(qqueue, toEnq, long); +PROTOTYPEpropSetMeth(qqueue, iLightDlyMrk, int); PROTOTYPEpropSetMeth(qqueue, iHighWtrMrk, int); PROTOTYPEpropSetMeth(qqueue, iLowWtrMrk, int); PROTOTYPEpropSetMeth(qqueue, iDiscardMrk, int); diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index fb0da2d2..058322bd 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -141,6 +141,7 @@ typedef uintTiny propid_t; #define PROP_CEE 200 #define PROP_CEE_ALL_JSON 201 #define PROP_SYS_BOM 159 +#define PROP_SYS_UPTIME 160 /* The error codes below are orginally "borrowed" from diff --git a/runtime/ruleset.c b/runtime/ruleset.c index 00d96714..c384663a 100644 --- a/runtime/ruleset.c +++ b/runtime/ruleset.c @@ -312,8 +312,8 @@ GetRulesetQueue(ruleset_t *pThis) /* Find the ruleset with the given name and return a pointer to its object. */ -static rsRetVal -GetRuleset(rsconf_t *conf, ruleset_t **ppRuleset, uchar *pszName) +rsRetVal +rulesetGetRuleset(rsconf_t *conf, ruleset_t **ppRuleset, uchar *pszName) { DEFiRet; assert(ppRuleset != NULL); @@ -335,7 +335,7 @@ SetDefaultRuleset(rsconf_t *conf, uchar *pszName) DEFiRet; assert(pszName != NULL); - CHKiRet(GetRuleset(conf, &pRuleset, pszName)); + CHKiRet(rulesetGetRuleset(conf, &pRuleset, pszName)); conf->rulesets.pDflt = pRuleset; dbgprintf("default rule set changed to %p: '%s'\n", pRuleset, pszName); @@ -353,7 +353,7 @@ SetCurrRuleset(rsconf_t *conf, uchar *pszName) DEFiRet; assert(pszName != NULL); - CHKiRet(GetRuleset(conf, &pRuleset, pszName)); + CHKiRet(rulesetGetRuleset(conf, &pRuleset, pszName)); conf->rulesets.pCurr = pRuleset; dbgprintf("current rule set changed to %p: '%s'\n", pRuleset, pszName); @@ -497,6 +497,7 @@ debugPrintAll(rsconf_t *conf) static inline rsRetVal doRulesetCreateQueue(rsconf_t *conf, int *pNewVal) { + uchar *rulesetMainQName; DEFiRet; if(conf->rulesets.pCurr == NULL) { @@ -515,7 +516,9 @@ doRulesetCreateQueue(rsconf_t *conf, int *pNewVal) FINALIZE; /* if it is turned off, we do not need to change anything ;) */ dbgprintf("adding a ruleset-specific \"main\" queue"); - CHKiRet(createMainQueue(&conf->rulesets.pCurr->pQueue, UCHAR_CONSTANT("ruleset"))); + rulesetMainQName = (conf->rulesets.pCurr->pszName == NULL)? UCHAR_CONSTANT("ruleset") : + conf->rulesets.pCurr->pszName; + CHKiRet(createMainQueue(&conf->rulesets.pCurr->pQueue, rulesetMainQName)); finalize_it: RETiRet; @@ -599,7 +602,7 @@ CODESTARTobjQueryInterface(ruleset) pIf->SetName = setName; pIf->DebugPrintAll = debugPrintAll; pIf->GetCurrent = GetCurrent; - pIf->GetRuleset = GetRuleset; + pIf->GetRuleset = rulesetGetRuleset; pIf->SetDefaultRuleset = SetDefaultRuleset; pIf->SetCurrRuleset = SetCurrRuleset; pIf->GetRulesetQueue = GetRulesetQueue; diff --git a/runtime/ruleset.h b/runtime/ruleset.h index 9d50f6f7..f4443e18 100644 --- a/runtime/ruleset.h +++ b/runtime/ruleset.h @@ -69,7 +69,23 @@ PROTOTYPEObj(ruleset); /* TODO: remove these -- currently done dirty for config file * redo -- rgerhards, 2011-04-19 + * rgerhards, 2012-04-19: actually, it may be way cooler not to remove + * them and use plain c-style conventions at least inside core objects. */ rsRetVal rulesetDestructForLinkedList(void *pData); rsRetVal rulesetKeyDestruct(void __attribute__((unused)) *pData); + +/* Get name associated to ruleset. This function cannot fail (except, + * of course, if previously something went really wrong). Returned + * pointer is read-only. + * rgerhards, 2012-04-18 + */ +static inline uchar* +rulesetGetName(ruleset_t *pRuleset) +{ + return pRuleset->pszName; +} + + +rsRetVal rulesetGetRuleset(rsconf_t *conf, ruleset_t **ppRuleset, uchar *pszName); #endif /* #ifndef INCLUDED_RULESET_H */ |