/
githubmirror
/
rsyslog
Обзор
Документация
Войти
/
githubmirror
/
rsyslog
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
runtime/glbl.c
1 722 строки
71 KB
Rainer Gerhards
core: add systemd READY delay opt-in
08 июл 2026, 11:58
08 июл 2026, 11:58
e671f88
Код
Авторство
О чём код?
/* glbl.c - this module holds global defintions and data items. * These are shared among the runtime library. Their use should be * limited to cases where it is actually needed. The main intension for * implementing them was support for the transistion from v2 to v4 * (with fully modular design), but it turned out that there may also * be some other good use cases besides backwards-compatibility. * * Module begun 2008-04-16 by Rainer Gerhards * * Copyright 2008-2024 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include <stdlib.h> #include <sys/socket.h> #include <sys/resource.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/wait.h> #include <fcntl.h> #include <unistd.h> #include <pthread.h> #include <ctype.h> #include <assert.h> #include <stdint.h> #include <string.h> #include <errno.h> #include <json.h> #include "rsyslog.h" #include "obj.h" #include "unicode-helper.h" #include "cfsysline.h" #include "glbl.h" #include "prop.h" #include "atomic.h" #include "errmsg.h" #include "action.h" #include "parserif.h" #include "rainerscript.h" #include "srUtils.h" #include "operatingstate.h" #include "net.h" #include "rsconf.h" #include "queue.h" #include "dnscache.h" #include "parser.h" #include "timezones.h" /* some defaults */ #ifndef DFLT_NETSTRM_DRVR #define DFLT_NETSTRM_DRVR ((uchar *)"ptcp") #endif /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(prop) DEFobjCurrIf(net) /* static data * For this object, these variables are obviously what makes the "meat" of the * class... */ static struct cnfobj *mainqCnfObj = NULL; /* main queue object, to be used later in startup sequence */ static int bPreserveFQDN = 0; /* should FQDNs always be preserved? */ static prop_t *propLocalIPIF = NULL; /* IP address to report for the local host (default is 127.0.0.1) */ static int propLocalIPIF_set = 0; /* is propLocalIPIF already set? */ static prop_t *propLocalHostName = NULL; /* our hostname as FQDN - read-only after startup */ static prop_t *propLocalHostNameToDelete = NULL; /* see GenerateLocalHostName function hdr comment! */ 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, except HUP */ static uchar *LocalDomain = NULL; /* our local domain name - read-only after startup, except HUP */ static int iMaxLine = 8096; int bTerminateInputs = 0; /* global switch that inputs shall terminate ASAP (1=> terminate) */ volatile sig_atomic_t bTerminateInputsSigSafe = 0; int glblUnloadModules = 1; int glblAbortOnProgramError = 0; char **glblDbgFiles = NULL; size_t glblDbgFilesNum = 0; int glblDbgWhitelist = 1; int glblPermitCtlC = 0; /* For global option CompactJsonString: * Compact the JSON variable string, without extra space. * Considering compatibility issues, the default options(CompactJsonString = "off") * keep the same as before. */ int glblJsonFormatOpt = JSON_C_TO_STRING_SPACED; pid_t glbl_ourpid; #ifndef HAVE_ATOMIC_BUILTINS DEF_ATOMIC_HELPER_MUT(mutTerminateInputs); #endif #ifdef USE_UNLIMITED_SELECT static int iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof(fd_mask); /* size of select() bitmask in bytes */ #endif static uchar *SourceIPofLocalClient = NULL; /* [ar] Source IP for local client to be used on multihomed host */ static uchar *GetDfltNetstrmDrvr(rsconf_t *cnf); /* tables for interfacing with the v6 config system */ static struct cnfparamdescr cnfparamdescr[] = { {"workdirectory", eCmdHdlrString, 0}, {"operatingstatefile", eCmdHdlrString, 0}, {"dropmsgswithmaliciousdnsptrrecords", eCmdHdlrBinary, 0}, {"localhostname", eCmdHdlrGetWord, 0}, {"compactjsonstring", eCmdHdlrBinary, 0}, {"preservefqdn", eCmdHdlrBinary, 0}, {"debug.onshutdown", eCmdHdlrBinary, 0}, {"debug.logfile", eCmdHdlrString, 0}, {"debug.gnutls", eCmdHdlrNonNegInt, 0}, {"debug.abortonprogramerror", eCmdHdlrBinary, 0}, {"debug.unloadmodules", eCmdHdlrBinary, 0}, {"defaultnetstreamdrivercafile", eCmdHdlrString, 0}, {"defaultnetstreamdrivercrlfile", eCmdHdlrString, 0}, {"defaultnetstreamdriverkeyfile", eCmdHdlrString, 0}, {"defaultnetstreamdrivercertfile", eCmdHdlrString, 0}, {"defaultnetstreamdriver", eCmdHdlrString, 0}, {"defaultopensslengine", eCmdHdlrString, 0}, {"netstreamdrivercaextrafiles", eCmdHdlrString, 0}, {"maxmessagesize", eCmdHdlrSize, 0}, {"oversizemsg.errorfile", eCmdHdlrGetWord, 0}, {"oversizemsg.report", eCmdHdlrBinary, 0}, {"oversizemsg.input.mode", eCmdHdlrGetWord, 0}, {"reportchildprocessexits", eCmdHdlrGetWord, 0}, {"action.reportsuspension", eCmdHdlrBinary, 0}, {"action.reportsuspensioncontinuation", eCmdHdlrBinary, 0}, {"parser.controlcharacterescapeprefix", eCmdHdlrGetChar, 0}, {"parser.droptrailinglfonreception", eCmdHdlrBinary, 0}, {"parser.droptrailingcronreception", eCmdHdlrBinary, 0}, {"parser.escapecontrolcharactersonreceive", eCmdHdlrBinary, 0}, {"parser.spacelfonreceive", eCmdHdlrBinary, 0}, {"parser.escape8bitcharactersonreceive", eCmdHdlrBinary, 0}, {"parser.escapecontrolcharactertab", eCmdHdlrBinary, 0}, {"parser.escapecontrolcharacterscstyle", eCmdHdlrBinary, 0}, {"parser.parsehostnameandtag", eCmdHdlrBinary, 0}, {"parser.permitslashinprogramname", eCmdHdlrBinary, 0}, {"stdlog.channelspec", eCmdHdlrString, 0}, {"janitor.interval", eCmdHdlrPositiveInt, 0}, {"senders.reportnew", eCmdHdlrBinary, 0}, {"senders.reportgoneaway", eCmdHdlrBinary, 0}, {"senders.timeoutafter", eCmdHdlrPositiveInt, 0}, {"senders.keeptrack", eCmdHdlrBinary, 0}, {"inputs.timeout.shutdown", eCmdHdlrPositiveInt, 0}, {"privdrop.group.keepsupplemental", eCmdHdlrBinary, 0}, {"privdrop.group.id", eCmdHdlrPositiveInt, 0}, {"privdrop.group.name", eCmdHdlrGID, 0}, {"privdrop.user.id", eCmdHdlrPositiveInt, 0}, {"privdrop.user.name", eCmdHdlrUID, 0}, {"net.ipprotocol", eCmdHdlrGetWord, 0}, {"net.acladdhostnameonfail", eCmdHdlrBinary, 0}, {"net.aclresolvehostname", eCmdHdlrBinary, 0}, {"net.enabledns", eCmdHdlrBinary, 0}, {"net.permitACLwarning", eCmdHdlrBinary, 0}, {"maxopenfiles", eCmdHdlrPositiveInt, 0}, {"compatibility.configformat.legacy", eCmdHdlrGetWord, 0}, {"compatibility.configformat.syslogd", eCmdHdlrGetWord, 0}, {"compatibility.configformat.property", eCmdHdlrGetWord, 0}, {"compatibility.defaults.secure", eCmdHdlrGetWord, 0}, {"systemd.notifyreadydelay", eCmdHdlrBinary, 0}, {"abortonuncleanconfig", eCmdHdlrBinary, 0}, {"abortonfailedqueuestartup", eCmdHdlrBinary, 0}, {"variables.casesensitive", eCmdHdlrBinary, 0}, {"environment", eCmdHdlrArray, 0}, {"processinternalmessages", eCmdHdlrBinary, 0}, {"umask", eCmdHdlrFileCreateMode, 0}, {"security.abortonidresolutionfail", eCmdHdlrBinary, 0}, {"internal.developeronly.options", eCmdHdlrInt, 0}, {"internalmsg.ratelimit.interval", eCmdHdlrPositiveInt, 0}, {"internalmsg.ratelimit.burst", eCmdHdlrPositiveInt, 0}, {"internalmsg.severity", eCmdHdlrSeverity, 0}, {"allmessagestostderr", eCmdHdlrBinary, 0}, {"errormessagestostderr.maxnumber", eCmdHdlrPositiveInt, 0}, {"shutdown.enable.ctlc", eCmdHdlrBinary, 0}, {"default.action.queue.timeoutshutdown", eCmdHdlrInt, 0}, {"default.action.queue.timeoutactioncompletion", eCmdHdlrInt, 0}, {"default.action.queue.timeoutenqueue", eCmdHdlrInt, 0}, {"default.action.queue.timeoutworkerthreadshutdown", eCmdHdlrInt, 0}, {"default.ruleset.queue.timeoutshutdown", eCmdHdlrInt, 0}, {"default.ruleset.queue.timeoutactioncompletion", eCmdHdlrInt, 0}, {"default.ruleset.queue.timeoutenqueue", eCmdHdlrInt, 0}, {"default.ruleset.queue.timeoutworkerthreadshutdown", eCmdHdlrInt, 0}, {"reverselookup.cache.ttl.default", eCmdHdlrNonNegInt, 0}, {"reverselookup.cache.ttl.enable", eCmdHdlrBinary, 0}, {"parser.supportcompressionextension", eCmdHdlrBinary, 0}, {"shutdown.queue.doublesize", eCmdHdlrBinary, 0}, {"debug.files", eCmdHdlrArray, 0}, {"debug.whitelist", eCmdHdlrBinary, 0}, {"libcapng.default", eCmdHdlrBinary, 0}, {"libcapng.enable", eCmdHdlrBinary, 0}, }; static struct cnfparamblk paramblk = {CNFPARAMBLK_VERSION, sizeof(cnfparamdescr) / sizeof(struct cnfparamdescr), cnfparamdescr}; static struct cnfparamvals *cnfparamvals = NULL; /* we need to support multiple calls into our param block, so we need * to persist the current settings. Note that this must be re-set * each time a new config load begins. This is a hint if we will * ever implement multi-config support, which is just an idea right now. */ int glblGetMaxLine(rsconf_t *cnf) { /* glblGetMaxLine might be invoked before our configuration exists */ return ((cnf != NULL) ? cnf->globals.iMaxLine : iMaxLine); } int GetGnuTLSLoglevel(rsconf_t *cnf) { /* * Loadable netstream drivers can be initialized while a configuration is * still being parsed, before runConf points at an active configuration. */ if (cnf == NULL) { cnf = loadConf; } return ((cnf != NULL) ? cnf->globals.iGnuTLSLoglevel : 0); } /* define a macro for the simple properties' set and get functions * (which are always the same). This is only suitable for pretty * simple cases which require neither checks nor memory allocation. */ #define SIMP_PROP(nameFunc, nameVar, dataType) \ SIMP_PROP_GET(nameFunc, nameVar, dataType) \ SIMP_PROP_SET(nameFunc, nameVar, dataType) #define SIMP_PROP_SET(nameFunc, nameVar, dataType) \ static rsRetVal Set##nameFunc(dataType newVal) { \ nameVar = newVal; \ return RS_RET_OK; \ } #define SIMP_PROP_GET(nameFunc, nameVar, dataType) \ static dataType Get##nameFunc(void) { \ return (nameVar); \ } SIMP_PROP(PreserveFQDN, bPreserveFQDN, int) SIMP_PROP(mainqCnfObj, mainqCnfObj, struct cnfobj *) #ifdef USE_UNLIMITED_SELECT SIMP_PROP(FdSetSize, iFdSetSize, int) #endif #undef SIMP_PROP #undef SIMP_PROP_SET #undef SIMP_PROP_GET /* This is based on the previous SIMP_PROP but as a getter it uses * additional parameter specifying the configuration it belongs to. * The setter uses loadConf */ #define SIMP_PROP(nameFunc, nameVar, dataType) \ SIMP_PROP_GET(nameFunc, nameVar, dataType) \ SIMP_PROP_SET(nameFunc, nameVar, dataType) #define SIMP_PROP_SET(nameFunc, nameVar, dataType) \ static rsRetVal Set##nameFunc(dataType newVal) { \ loadConf->globals.nameVar = newVal; \ return RS_RET_OK; \ } #define SIMP_PROP_GET(nameFunc, nameVar, dataType) \ static dataType Get##nameFunc(rsconf_t *cnf) { \ return (cnf->globals.nameVar); \ } SIMP_PROP(DropMalPTRMsgs, bDropMalPTRMsgs, int) SIMP_PROP(DisableDNS, bDisableDNS, int) SIMP_PROP(ParserEscapeControlCharactersCStyle, parser.bParserEscapeCCCStyle, int) SIMP_PROP(ParseHOSTNAMEandTAG, parser.bParseHOSTNAMEandTAG, int) SIMP_PROP(OptionDisallowWarning, optionDisallowWarning, int) /* We omit setter on purpose, because we want to customize it */ SIMP_PROP_GET(DfltNetstrmDrvrCAF, pszDfltNetstrmDrvrCAF, uchar *) SIMP_PROP_GET(DfltNetstrmDrvrCRLF, pszDfltNetstrmDrvrCRLF, uchar *) SIMP_PROP_GET(DfltNetstrmDrvrCertFile, pszDfltNetstrmDrvrCertFile, uchar *) SIMP_PROP_GET(DfltNetstrmDrvrKeyFile, pszDfltNetstrmDrvrKeyFile, uchar *) SIMP_PROP_GET(NetstrmDrvrCAExtraFiles, pszNetstrmDrvrCAExtraFiles, uchar *) SIMP_PROP_GET(ParserControlCharacterEscapePrefix, parser.cCCEscapeChar, uchar) SIMP_PROP_GET(ParserDropTrailingLFOnReception, parser.bDropTrailingLF, int) SIMP_PROP_GET(ParserDropTrailingCROnReception, parser.bDropTrailingCR, int) SIMP_PROP_GET(ParserEscapeControlCharactersOnReceive, parser.bEscapeCCOnRcv, int) SIMP_PROP_GET(ParserSpaceLFOnReceive, parser.bSpaceLFOnRcv, int) SIMP_PROP_GET(ParserEscape8BitCharactersOnReceive, parser.bEscape8BitChars, int) SIMP_PROP_GET(ParserEscapeControlCharacterTab, parser.bEscapeTab, int) #undef SIMP_PROP #undef SIMP_PROP_SET #undef SIMP_PROP_GET /* return global input termination status * rgerhards, 2009-07-20 */ static int GetGlobalInputTermState(void) { return ATOMIC_LOAD_32BIT(&bTerminateInputs, &mutTerminateInputs); } /* set global termination state to "terminate". Note that this is a * "once in a lifetime" action which can not be undone. -- gerhards, 2009-07-20 */ static void SetGlobalInputTermination(void) { /* Signal handlers must not take mutTerminateInputs in no-atomic builds. * Publish this one-way mirror first so a shutdown signal delivered during * termination setup may already break input-side blocking calls. */ PREFER_STORE_INT(&bTerminateInputsSigSafe, 1); ATOMIC_STORE_32BIT(&bTerminateInputs, &mutTerminateInputs, 1); } /* 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 rsRetVal storeLocalHostIPIF(uchar *myIP) { DEFiRet; if (propLocalIPIF != NULL) { CHKiRet(prop.Destruct(&propLocalIPIF)); } 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 this to be set 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_set) { 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); } localRet = net.GetIFIPAddr(pNewVal, AF_UNSPEC, myIP, (int)sizeof(myIP)); if (localRet != RS_RET_OK) { 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. * rgerhards, 2011-02-16 */ static rsRetVal setWorkDir(void __attribute__((unused)) * pVal, uchar *pNewVal) { size_t lenDir; int i; struct stat sb; DEFiRet; /* remove trailing slashes */ lenDir = ustrlen(pNewVal); i = lenDir - 1; while (i > 0 && pNewVal[i] == '/') { --i; } if (i < 0) { LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: empty value " "- directive ignored"); ABORT_FINALIZE(RS_RET_ERR_WRKDIR); } if (i != (int)lenDir - 1) { pNewVal[i + 1] = '\0'; LogError(0, RS_RET_WRN_WRKDIR, "$WorkDirectory: trailing slashes " "removed, new value is '%s'", pNewVal); } if (stat((char *)pNewVal, &sb) != 0) { LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: %s can not be " "accessed, probably does not exist - directive ignored", pNewVal); ABORT_FINALIZE(RS_RET_ERR_WRKDIR); } if (!S_ISDIR(sb.st_mode)) { LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: %s not a directory - directive ignored", pNewVal); ABORT_FINALIZE(RS_RET_ERR_WRKDIR); } free(loadConf->globals.pszWorkDir); loadConf->globals.pszWorkDir = pNewVal; finalize_it: RETiRet; } static rsRetVal setDfltNetstrmDrvrCAF(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; FILE *fp; free(loadConf->globals.pszDfltNetstrmDrvrCAF); loadConf->globals.pszDfltNetstrmDrvrCAF = pNewVal; fp = fopen((const char *)pNewVal, "r"); if (fp == NULL) { LogError(errno, RS_RET_NO_FILE_ACCESS, "error: defaultnetstreamdrivercafile file '%s' " "could not be accessed", pNewVal); } else { fclose(fp); } RETiRet; } static rsRetVal setNetstrmDrvrCAExtraFiles(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; FILE *fp; char *token; char *saveptr; int error = 0; char *valCopy = NULL; free(loadConf->globals.pszNetstrmDrvrCAExtraFiles); /* Validate files without modifying the original comma-separated string */ if (pNewVal != NULL) { valCopy = strdup((const char *)pNewVal); if (valCopy == NULL) { LogError(errno, RS_RET_OUT_OF_MEMORY, "error: strdup failed in setNetstrmDrvrCAExtraFiles"); free(pNewVal); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } for (token = strtok_r(valCopy, ",", &saveptr); token != NULL; token = strtok_r(NULL, ",", &saveptr)) { while (isspace((unsigned char)*token)) { token++; } char *end = token + strlen(token) - 1; while (end > token && isspace((unsigned char)*end)) { end--; } *(end + 1) = '\0'; if (*token == '\0') { continue; } fp = fopen((const char *)token, "r"); if (fp == NULL) { LogError(errno, RS_RET_NO_FILE_ACCESS, "error: netstreamdrivercaextrafiles file '%s' " "could not be accessed", token); error = 1; } else { fclose(fp); } } } if (!error) { loadConf->globals.pszNetstrmDrvrCAExtraFiles = pNewVal; } else { /* Validation failed: prevent leak of newly allocated pNewVal */ free(pNewVal); loadConf->globals.pszNetstrmDrvrCAExtraFiles = NULL; } finalize_it: if (valCopy != NULL) { free(valCopy); } RETiRet; } static rsRetVal setDfltNetstrmDrvrCRLF(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; FILE *fp; free(loadConf->globals.pszDfltNetstrmDrvrCRLF); loadConf->globals.pszDfltNetstrmDrvrCRLF = pNewVal; fp = fopen((const char *)pNewVal, "r"); if (fp == NULL) { LogError(errno, RS_RET_NO_FILE_ACCESS, "error: defaultnetstreamdrivercrlfile file '%s' " "could not be accessed", pNewVal); } else { fclose(fp); } RETiRet; } static rsRetVal setDfltNetstrmDrvrCertFile(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; FILE *fp; free(loadConf->globals.pszDfltNetstrmDrvrCertFile); loadConf->globals.pszDfltNetstrmDrvrCertFile = pNewVal; fp = fopen((const char *)pNewVal, "r"); if (fp == NULL) { LogError(errno, RS_RET_NO_FILE_ACCESS, "error: defaultnetstreamdrivercertfile '%s' " "could not be accessed", pNewVal); } else { fclose(fp); } RETiRet; } static rsRetVal setDfltNetstrmDrvrKeyFile(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; FILE *fp; free(loadConf->globals.pszDfltNetstrmDrvrKeyFile); loadConf->globals.pszDfltNetstrmDrvrKeyFile = pNewVal; fp = fopen((const char *)pNewVal, "r"); if (fp == NULL) { LogError(errno, RS_RET_NO_FILE_ACCESS, "error: defaultnetstreamdriverkeyfile '%s' " "could not be accessed", pNewVal); } else { fclose(fp); } RETiRet; } static rsRetVal setDfltNetstrmDrvr(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; free(loadConf->globals.pszDfltNetstrmDrvr); loadConf->globals.pszDfltNetstrmDrvr = pNewVal; RETiRet; } static rsRetVal setDfltOpensslEngine(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; free(loadConf->globals.pszDfltOpensslEngine); loadConf->globals.pszDfltOpensslEngine = pNewVal; RETiRet; } /* Set the maximum number of files the rsyslog process may open. */ rsRetVal glblSetMaxOpenFiles(void __attribute__((unused)) * pVal, int iFiles) { struct rlimit maxFiles; struct rlimit currentLimit; DEFiRet; if (getrlimit(RLIMIT_NOFILE, ¤tLimit) < 0) { currentLimit.rlim_max = 0; } maxFiles.rlim_cur = iFiles; maxFiles.rlim_max = iFiles; if (setrlimit(RLIMIT_NOFILE, &maxFiles) < 0) { /* NOTE: under valgrind, we seem to be unable to extend the size! */ LogError(errno, RS_RET_ERR_RLIM_NOFILE, "could not set process file limit to %d " "[current hard limit %llu]", iFiles, (unsigned long long)currentLimit.rlim_max); ABORT_FINALIZE(RS_RET_ERR_RLIM_NOFILE); } #ifdef USE_UNLIMITED_SELECT SetFdSetSize(howmany(iFiles, __NFDBITS) * sizeof(fd_mask)); #endif DBGPRINTF("Max number of files set to %d [current hard limit %llu].\n", iFiles, (unsigned long long)currentLimit.rlim_max); finalize_it: RETiRet; } static rsRetVal setParserControlCharacterEscapePrefix(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; loadConf->globals.parser.cCCEscapeChar = *pNewVal; RETiRet; } static rsRetVal setParserDropTrailingLFOnReception(void __attribute__((unused)) * pVal, int pNewVal) { DEFiRet; loadConf->globals.parser.bDropTrailingLF = pNewVal; RETiRet; } static rsRetVal setParserDropTrailingCROnReception(void __attribute__((unused)) * pVal, int pNewVal) { DEFiRet; loadConf->globals.parser.bDropTrailingCR = pNewVal; RETiRet; } static rsRetVal setParserEscapeControlCharactersOnReceive(void __attribute__((unused)) * pVal, int pNewVal) { DEFiRet; loadConf->globals.parser.bEscapeCCOnRcv = pNewVal; RETiRet; } static rsRetVal setParserSpaceLFOnReceive(void __attribute__((unused)) * pVal, int pNewVal) { DEFiRet; loadConf->globals.parser.bSpaceLFOnRcv = pNewVal; RETiRet; } static rsRetVal setParserEscape8BitCharactersOnReceive(void __attribute__((unused)) * pVal, int pNewVal) { DEFiRet; loadConf->globals.parser.bEscape8BitChars = pNewVal; RETiRet; } static rsRetVal setParserEscapeControlCharacterTab(void __attribute__((unused)) * pVal, int pNewVal) { DEFiRet; loadConf->globals.parser.bEscapeTab = pNewVal; RETiRet; } /* This function is used both by legacy and RainerScript conf. It is a real setter. */ static void setMaxLine(const int64_t iNew) { if (iNew < 128) { LogError(0, RS_RET_INVALID_VALUE, "maxMessageSize tried to set " "to %lld, but cannot be less than 128 - set to 128 " "instead", (long long)iNew); loadConf->globals.iMaxLine = 128; } else if (iNew > (int64_t)INT_MAX) { LogError(0, RS_RET_INVALID_VALUE, "maxMessageSize larger than " "INT_MAX (%d) - reduced to INT_MAX", INT_MAX); loadConf->globals.iMaxLine = INT_MAX; } else { loadConf->globals.iMaxLine = (int)iNew; } } static rsRetVal legacySetMaxMessageSize(void __attribute__((unused)) * pVal, int64_t iNew) { setMaxLine(iNew); return RS_RET_OK; } static rsRetVal setDebugFile(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; dbgSetDebugFile(pNewVal); free(pNewVal); RETiRet; } static rsRetVal setDebugLevel(void __attribute__((unused)) * pVal, int level) { DEFiRet; dbgSetDebugLevel(level); dbgprintf("debug level %d set via config file\n", level); dbgprintf("This is rsyslog version " VERSION "\n"); RETiRet; } static rsRetVal ATTR_NONNULL() setOversizeMsgInputMode(const uchar *const mode) { DEFiRet; if (!strcmp((char *)mode, "truncate")) { loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Truncate; } else if (!strcmp((char *)mode, "split")) { loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Split; } else if (!strcmp((char *)mode, "accept")) { loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Accept; } else { loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Truncate; } RETiRet; } static rsRetVal ATTR_NONNULL() setReportChildProcessExits(const uchar *const mode) { DEFiRet; if (!strcmp((char *)mode, "none")) { loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_NONE; } else if (!strcmp((char *)mode, "errors")) { loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS; } else if (!strcmp((char *)mode, "all")) { loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ALL; } else { LogError(0, RS_RET_CONF_PARAM_INVLD, "invalid value '%s' for global parameter reportChildProcessExits -- ignored", mode); iRet = RS_RET_CONF_PARAM_INVLD; } RETiRet; } /** Convert enable/warn/disable config-format policy text to its internal enum. */ static rsRetVal ATTR_NONNULL() setCompatConfigFormatMode(const char *const param, const uchar *const mode, int *const dst) { DEFiRet; if (!strcmp((const char *)mode, "enable")) { *dst = COMPAT_CONFIGFORMAT_ENABLE; } else if (!strcmp((const char *)mode, "warn")) { *dst = COMPAT_CONFIGFORMAT_WARN; } else if (!strcmp((const char *)mode, "disable")) { *dst = COMPAT_CONFIGFORMAT_DISABLE; } else { parser_errmsg("invalid value '%s' for global parameter %s", mode, param); iRet = RS_RET_CONF_PARAM_INVLD; } RETiRet; } /** Convert strict/backward-compatible/warn secure-defaults policy text to its internal enum. */ static rsRetVal ATTR_NONNULL() setCompatDefaultsSecure(const uchar *const mode) { DEFiRet; if (!strcmp((const char *)mode, "strict")) { loadConf->globals.compatDefaultsSecure = COMPAT_DEFAULTS_SECURE_STRICT; loadConf->globals.bAbortOnUncleanConfig = 1; } else if (!strcmp((const char *)mode, "backward-compatible")) { loadConf->globals.compatDefaultsSecure = COMPAT_DEFAULTS_SECURE_BACKWARD_COMPATIBLE; } else if (!strcmp((const char *)mode, "warn")) { loadConf->globals.compatDefaultsSecure = COMPAT_DEFAULTS_SECURE_WARN; } else { parser_errmsg("invalid value '%s' for global parameter compatibility.defaults.secure", mode); iRet = RS_RET_CONF_PARAM_INVLD; } RETiRet; } /** Apply a global compatibility enum string during config parsing. */ static rsRetVal ATTR_NONNULL() processCompatGlobalParam(const char *const name, struct cnfparamvals *const pval) { char *mode; DEFiRet; mode = es_str2cstr(pval->val.d.estr, NULL); if (mode == NULL) { parser_errmsg("out of memory processing global parameter %s", name); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (!strcmp(name, "compatibility.configformat.legacy")) { CHKiRet(setCompatConfigFormatMode(name, (uchar *)mode, &loadConf->globals.compatConfigFormatLegacy)); } else if (!strcmp(name, "compatibility.configformat.syslogd")) { CHKiRet(setCompatConfigFormatMode(name, (uchar *)mode, &loadConf->globals.compatConfigFormatSyslogd)); } else if (!strcmp(name, "compatibility.configformat.property")) { CHKiRet(setCompatConfigFormatMode(name, (uchar *)mode, &loadConf->globals.compatConfigFormatProperty)); } else if (!strcmp(name, "compatibility.defaults.secure")) { CHKiRet(setCompatDefaultsSecure((uchar *)mode)); } finalize_it: free(mode); RETiRet; } /** Emit a compatibility warning through the parser diagnostics path. */ static void ATTR_NONNULL() compatParserWarnmsg(const char *const msg) { parser_warnmsg("%s", msg); } /** Emit warning/error for compatibility-controlled legacy syntax and say how to re-enable it. */ static int ATTR_NONNULL() permitCompatSyntax(const int mode, const char *const kind, const char *const text, const char *const option) { int permitted = 1; if (mode == COMPAT_CONFIGFORMAT_WARN) { char msg[1024]; snprintf(msg, sizeof(msg), "obsolete %s syntax encountered: '%s'", kind, text); msg[sizeof(msg) - 1] = '\0'; compatParserWarnmsg(msg); } else if (mode == COMPAT_CONFIGFORMAT_DISABLE) { parser_errmsg("obsolete %s syntax disabled: '%s'; use global(%s=\"enable\") to enable it", kind, text, option); permitted = 0; } return permitted; } int glblPermitLegacyConfigDirective(rsconf_t *cnf, const char *directive) { return permitCompatSyntax(cnf->globals.compatConfigFormatLegacy, "$-directive", directive, "compatibility.configformat.legacy"); } int glblPermitSyslogdConfigFilter(rsconf_t *cnf, const char *filter) { return permitCompatSyntax(cnf->globals.compatConfigFormatSyslogd, "classic syslogd filter", filter, "compatibility.configformat.syslogd"); } int glblPermitPropertyConfigFilter(rsconf_t *cnf, const char *filter) { return permitCompatSyntax(cnf->globals.compatConfigFormatProperty, "classic property-based filter", filter, "compatibility.configformat.property"); } void glblWarnIfInsecureDefault(rsconf_t *cnf, const char *detail) { if (cnf != NULL && cnf->globals.compatDefaultsSecure == COMPAT_DEFAULTS_SECURE_WARN) { parser_warnmsg( "backward-compatible insecure default in use: %s; " "use global(compatibility.defaults.secure=\"strict\") to enable the secure default", detail); } } const uchar *glblGetEffectiveNetstrmDrvr(rsconf_t *cnf, const uchar *localDrvr) { if (localDrvr != NULL) { return localDrvr; } if (cnf == NULL) { return DFLT_NETSTRM_DRVR; } return GetDfltNetstrmDrvr(cnf); } int glblIsTlsCapableNetstrmDrvr(const uchar *drvr) { return drvr != NULL && (!strcasecmp((const char *)drvr, "ossl") || !strcasecmp((const char *)drvr, "gtls") || !strcasecmp((const char *)drvr, "mbedtls")); } static int getDefPFFamily(rsconf_t *cnf) { return cnf->globals.iDefPFFamily; } /* 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) { assert(propLocalIPIF != NULL); return (propLocalIPIF); } /* set our local hostname. Free previous hostname, if it was already set. * Note that we do now do this in a thread. As such, the method here * is NOT 100% clean. If we run into issues, we need to think about * refactoring the whole way we handle the local host name processing. * Possibly using a PROP might be the right solution then. */ static rsRetVal SetLocalHostName(uchar *const newname) { uchar *toFree; if (LocalHostName == NULL || strcmp((const char *)LocalHostName, (const char *)newname)) { toFree = LocalHostName; LocalHostName = newname; } else { toFree = newname; } free(toFree); return RS_RET_OK; } /* return our local hostname. if it is not set, "[localhost]" is returned */ uchar *glblGetLocalHostName(void) { uchar *pszRet; if (LocalHostNameOverride != NULL) { pszRet = LocalHostNameOverride; goto done; } if (LocalHostName == NULL) pszRet = (uchar *)"[localhost]"; else { if (GetPreserveFQDN() == 1) pszRet = LocalFQDNName; else pszRet = LocalHostName; } done: return (pszRet); } /* return the name of the file where oversize messages are written to */ uchar *glblGetOversizeMsgErrorFile(rsconf_t *cnf) { return cnf->globals.oversizeMsgErrorFile; } const uchar *glblGetOperatingStateFile(rsconf_t *cnf) { return cnf->globals.operatingStateFile; } /* return the mode with which oversize messages will be put forward */ int glblGetOversizeMsgInputMode(rsconf_t *cnf) { return cnf->globals.oversizeMsgInputMode; } int glblReportOversizeMessage(rsconf_t *cnf) { return cnf->globals.reportOversizeMsg; } /* logs a message indicating that a child process has terminated. * If name != NULL, prints it as the program name. */ void glblReportChildProcessExit(rsconf_t *cnf, const uchar *name, pid_t pid, int status) { DBGPRINTF("waitpid for child %ld returned status: %2.2x\n", (long)pid, status); if (cnf->globals.reportChildProcessExits == REPORT_CHILD_PROCESS_EXITS_NONE || (cnf->globals.reportChildProcessExits == REPORT_CHILD_PROCESS_EXITS_ERRORS && WIFEXITED(status) && WEXITSTATUS(status) == 0)) { return; } if (WIFEXITED(status)) { int severity = WEXITSTATUS(status) == 0 ? LOG_INFO : LOG_WARNING; if (name != NULL) { LogMsg(0, NO_ERRCODE, severity, "program '%s' (pid %ld) exited with status %d", name, (long)pid, WEXITSTATUS(status)); } else { LogMsg(0, NO_ERRCODE, severity, "child process (pid %ld) exited with status %d", (long)pid, WEXITSTATUS(status)); } } else if (WIFSIGNALED(status)) { if (name != NULL) { LogMsg(0, NO_ERRCODE, LOG_WARNING, "program '%s' (pid %ld) terminated by signal %d", name, (long)pid, WTERMSIG(status)); } else { LogMsg(0, NO_ERRCODE, LOG_WARNING, "child process (pid %ld) terminated by signal %d", (long)pid, WTERMSIG(status)); } } } /* 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 * NOTE: This function tries to avoid locking by not destructing the previous value * immediately. This is so that current readers can continue to use the previous name. * Otherwise, we would need to use read/write locks to protect the update process. * In order to do so, we save the previous value and delete it when we are called again * the next time. Note that this in theory is racy and can lead to a double-free. * In practice, however, the window of exposure to trigger this is extremely short * and as this functions is very infrequently being called (on HUP), the trigger * condition for this bug is so highly unlikely that it never occurs in practice. * Probably if you HUP rsyslog every few milliseconds, but who does that... * To further reduce risk potential, we do only update the property when there * actually is a hostname change, which makes it even less likely. * rgerhards, 2013-10-28 */ static rsRetVal GenerateLocalHostNameProperty(void) { uchar *pszPrev; int lenPrev; prop_t *hostnameNew; uchar *pszName; DEFiRet; if (propLocalHostNameToDelete != NULL) prop.Destruct(&propLocalHostNameToDelete); if (LocalHostNameOverride == NULL) { if (LocalHostName == NULL) pszName = (uchar *)"[localhost]"; else { if (GetPreserveFQDN() == 1) pszName = LocalFQDNName; else pszName = LocalHostName; } } else { /* local hostname is overriden via config */ pszName = LocalHostNameOverride; } DBGPRINTF("GenerateLocalHostName uses '%s'\n", pszName); if (propLocalHostName == NULL) pszPrev = (uchar *)""; /* make sure strcmp() below does not match */ else prop.GetString(propLocalHostName, &pszPrev, &lenPrev); if (ustrcmp(pszPrev, pszName)) { /* we need to update */ CHKiRet(prop.Construct(&hostnameNew)); CHKiRet(prop.SetString(hostnameNew, pszName, ustrlen(pszName))); CHKiRet(prop.ConstructFinalize(hostnameNew)); propLocalHostNameToDelete = propLocalHostName; propLocalHostName = hostnameNew; } finalize_it: RETiRet; } /* return our local hostname as a string property */ static prop_t *GetLocalHostNameProp(void) { return (propLocalHostName); } 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) */ static uchar *GetLocalFQDNName(void) { return (LocalFQDNName == NULL ? (uchar *)"[localhost]" : LocalFQDNName); } /* return the current working directory */ static uchar *GetWorkDir(rsconf_t *cnf) { return (cnf->globals.pszWorkDir == NULL ? (uchar *)"" : cnf->globals.pszWorkDir); } /* return the "raw" working directory, which means * NULL if unset. */ const uchar *glblGetWorkDirRaw(rsconf_t *cnf) { return cnf->globals.pszWorkDir; } /* return the current default netstream driver */ static uchar *GetDfltNetstrmDrvr(rsconf_t *cnf) { return (cnf->globals.pszDfltNetstrmDrvr == NULL ? DFLT_NETSTRM_DRVR : cnf->globals.pszDfltNetstrmDrvr); } /* return the current default openssl engine name */ static uchar *GetDfltOpensslEngine(rsconf_t *cnf) { return (cnf->globals.pszDfltOpensslEngine); } /* [ar] Source IP for local client to be used on multihomed host */ static rsRetVal SetSourceIPofLocalClient(uchar *newname) { if (SourceIPofLocalClient != NULL) { free(SourceIPofLocalClient); } SourceIPofLocalClient = newname; return RS_RET_OK; } static uchar *GetSourceIPofLocalClient(void) { return (SourceIPofLocalClient); } /* queryInterface function * rgerhards, 2008-02-21 */ BEGINobjQueryInterface(glbl) CODESTARTobjQueryInterface(glbl); if (pIf->ifVersion != glblCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->GetWorkDir = GetWorkDir; pIf->GenerateLocalHostNameProperty = GenerateLocalHostNameProperty; pIf->GetLocalHostNameProp = GetLocalHostNameProp; pIf->GetLocalHostIP = GetLocalHostIP; pIf->SetGlobalInputTermination = SetGlobalInputTermination; pIf->GetGlobalInputTermState = GetGlobalInputTermState; pIf->GetSourceIPofLocalClient = GetSourceIPofLocalClient; /* [ar] */ pIf->SetSourceIPofLocalClient = SetSourceIPofLocalClient; /* [ar] */ pIf->GetDefPFFamily = getDefPFFamily; pIf->GetDisableDNS = GetDisableDNS; pIf->GetMaxLine = glblGetMaxLine; pIf->GetOptionDisallowWarning = GetOptionDisallowWarning; pIf->GetDfltNetstrmDrvrCAF = GetDfltNetstrmDrvrCAF; pIf->GetDfltNetstrmDrvrCRLF = GetDfltNetstrmDrvrCRLF; pIf->GetDfltNetstrmDrvrCertFile = GetDfltNetstrmDrvrCertFile; pIf->GetDfltNetstrmDrvrKeyFile = GetDfltNetstrmDrvrKeyFile; pIf->GetDfltNetstrmDrvr = GetDfltNetstrmDrvr; pIf->GetDfltOpensslEngine = GetDfltOpensslEngine; pIf->GetNetstrmDrvrCAExtraFiles = GetNetstrmDrvrCAExtraFiles; pIf->GetParserControlCharacterEscapePrefix = GetParserControlCharacterEscapePrefix; pIf->GetParserDropTrailingLFOnReception = GetParserDropTrailingLFOnReception; pIf->GetParserDropTrailingCROnReception = GetParserDropTrailingCROnReception; pIf->GetParserEscapeControlCharactersOnReceive = GetParserEscapeControlCharactersOnReceive; pIf->GetParserSpaceLFOnReceive = GetParserSpaceLFOnReceive; pIf->GetParserEscape8BitCharactersOnReceive = GetParserEscape8BitCharactersOnReceive; pIf->GetParserEscapeControlCharacterTab = GetParserEscapeControlCharacterTab; pIf->GetLocalHostName = glblGetLocalHostName; pIf->SetLocalHostName = SetLocalHostName; #define SIMP_PROP(name) \ pIf->Get##name = Get##name; \ pIf->Set##name = Set##name; SIMP_PROP(PreserveFQDN); SIMP_PROP(DropMalPTRMsgs); SIMP_PROP(mainqCnfObj); SIMP_PROP(LocalFQDNName) SIMP_PROP(LocalDomain) SIMP_PROP(ParserEscapeControlCharactersCStyle) SIMP_PROP(ParseHOSTNAMEandTAG) #ifdef USE_UNLIMITED_SELECT SIMP_PROP(FdSetSize) #endif #undef SIMP_PROP finalize_it: ENDobjQueryInterface(glbl) /* Reset config variables to default values. * rgerhards, 2008-04-17 */ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal) { free(loadConf->globals.pszDfltNetstrmDrvr); loadConf->globals.pszDfltNetstrmDrvr = NULL; free(loadConf->globals.pszDfltNetstrmDrvrCAF); loadConf->globals.pszDfltNetstrmDrvrCAF = NULL; free(loadConf->globals.pszDfltNetstrmDrvrCRLF); loadConf->globals.pszDfltNetstrmDrvrCRLF = NULL; free(loadConf->globals.pszDfltNetstrmDrvrKeyFile); loadConf->globals.pszDfltNetstrmDrvrKeyFile = NULL; free(loadConf->globals.pszDfltNetstrmDrvrCertFile); loadConf->globals.pszDfltNetstrmDrvrCertFile = NULL; free(loadConf->globals.pszDfltOpensslEngine); loadConf->globals.pszDfltOpensslEngine = NULL; free(LocalHostNameOverride); LocalHostNameOverride = NULL; free(loadConf->globals.oversizeMsgErrorFile); loadConf->globals.oversizeMsgErrorFile = NULL; loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Accept; loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS; free(loadConf->globals.pszWorkDir); loadConf->globals.pszWorkDir = NULL; free((void *)loadConf->globals.operatingStateFile); loadConf->globals.operatingStateFile = NULL; loadConf->globals.bDropMalPTRMsgs = 0; loadConf->globals.systemdNotifyReadyDelay = 0; bPreserveFQDN = 0; loadConf->globals.iMaxLine = 8192; loadConf->globals.reportOversizeMsg = 1; loadConf->globals.parser.cCCEscapeChar = '#'; loadConf->globals.parser.bDropTrailingLF = 1; loadConf->globals.parser.bDropTrailingCR = 0; loadConf->globals.parser.bEscapeCCOnRcv = 1; /* default is to escape control characters */ loadConf->globals.parser.bSpaceLFOnRcv = 0; loadConf->globals.parser.bEscape8BitChars = 0; /* default is not to escape control characters */ loadConf->globals.parser.bEscapeTab = 1; /* default is to escape tab characters */ loadConf->globals.parser.bParserEscapeCCCStyle = 0; #ifdef USE_UNLIMITED_SELECT iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof(fd_mask); #endif return RS_RET_OK; } /* Prepare for new config */ void glblPrepCnf(void) { free(mainqCnfObj); mainqCnfObj = NULL; free(cnfparamvals); cnfparamvals = NULL; } /* handle the timezone() object. Each incarnation adds one additional * zone info to the global table of time zones. */ int bs_arrcmp_glblDbgFiles(const void *s1, const void *s2) { return strcmp((char *)s1, *(char **)s2); } /* handle a global config object. Note that multiple global config statements * are permitted (because of plugin support), so once we got a param block, * we need to hold to it. * rgerhards, 2011-07-19 */ void glblProcessCnf(struct cnfobj *o) { int i; cnfparamvals = nvlstGetParams(o->nvlst, ¶mblk, cnfparamvals); if (cnfparamvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing global " "config parameters [global(...)]"); goto done; } if (Debug) { dbgprintf("glbl param blk after glblProcessCnf:\n"); cnfparamsPrint(¶mblk, cnfparamvals); } /* The next thing is a bit hackish and should be changed in higher * versions. There are a select few parameters which we need to * act on immediately. These are processed here. */ for (i = 0; i < paramblk.nParams; ++i) { if (!cnfparamvals[i].bUsed) continue; if (!strcmp(paramblk.descr[i].name, "processinternalmessages")) { loadConf->globals.bProcessInternalMessages = (int)cnfparamvals[i].val.d.n; cnfparamvals[i].bUsed = TRUE; } else if (!strcmp(paramblk.descr[i].name, "internal.developeronly.options")) { loadConf->globals.glblDevOptions = (uint64_t)cnfparamvals[i].val.d.n; cnfparamvals[i].bUsed = TRUE; } else if (!strcmp(paramblk.descr[i].name, "stdlog.channelspec")) { #ifndef ENABLE_LIBLOGGING_STDLOG LogError(0, RS_RET_ERR, "rsyslog wasn't " "compiled with liblogging-stdlog support. " "The 'stdlog.channelspec' parameter " "is ignored. Note: the syslog API is used instead.\n"); #else loadConf->globals.stdlog_chanspec = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); /* we need to re-open with the new channel */ stdlog_close(loadConf->globals.stdlog_hdl); loadConf->globals.stdlog_hdl = stdlog_open("rsyslogd", 0, STDLOG_SYSLOG, (char *)loadConf->globals.stdlog_chanspec); cnfparamvals[i].bUsed = TRUE; #endif } else if (!strcmp(paramblk.descr[i].name, "operatingstatefile")) { if (loadConf->globals.operatingStateFile != NULL) { LogError(errno, RS_RET_PARAM_ERROR, "error: operatingStateFile already set to '%s' - " "new value ignored", loadConf->globals.operatingStateFile); } else { loadConf->globals.operatingStateFile = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); osf_open(); } } else if (!strcmp(paramblk.descr[i].name, "security.abortonidresolutionfail")) { loadConf->globals.abortOnIDResolutionFail = (int)cnfparamvals[i].val.d.n; cnfparamvals[i].bUsed = TRUE; } else if (!strcmp(paramblk.descr[i].name, "defaultnetstreamdriver")) { uchar *const cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); if (cstr == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "out of memory processing defaultnetstreamdriver"); } else { setDfltNetstrmDrvr(NULL, cstr); } cnfparamvals[i].bUsed = TRUE; } else if (!strncmp(paramblk.descr[i].name, "compatibility.", 14)) { if (processCompatGlobalParam(paramblk.descr[i].name, &cnfparamvals[i]) == RS_RET_OK) { cnfparamvals[i].bUsed = 1; } else { dbgprintf("glblProcessCnf: failed to process early global parameter '%s'\n", paramblk.descr[i].name); } } } done: return; } /* Set mainq parameters. Note that when this is not called, we'll use the * legacy parameter config. mainq parameters can only be set once. */ void glblProcessMainQCnf(struct cnfobj *o) { if (mainqCnfObj == NULL) { mainqCnfObj = o; } else { LogError(0, RS_RET_ERR, "main_queue() object can only be specified " "once - all but first ignored\n"); } } /* destruct the main q cnf object after it is no longer needed. This is * also used to do some final checks. */ void glblDestructMainqCnfObj(void) { /* Only destruct if not NULL! */ if (mainqCnfObj != NULL) { nvlstChkUnused(mainqCnfObj->nvlst); cnfobjDestruct(mainqCnfObj); mainqCnfObj = NULL; } } static int qs_arrcmp_glblDbgFiles(const void *s1, const void *s2) { return strcmp(*((char **)s1), *((char **)s2)); } /* set an environment variable */ static rsRetVal do_setenv(const char *const var) { char varname[128]; const char *val = var; size_t i; DEFiRet; for (i = 0; *val != '='; ++i, ++val) { if (i == sizeof(varname) - i) { parser_errmsg( "environment variable name too long " "[max %zu chars] or malformed entry: '%s'", sizeof(varname) - 1, var); ABORT_FINALIZE(RS_RET_ERR_SETENV); } if (*val == '\0') { parser_errmsg( "environment variable entry is missing " "equal sign (for value): '%s'", var); ABORT_FINALIZE(RS_RET_ERR_SETENV); } varname[i] = *val; } varname[i] = '\0'; ++val; DBGPRINTF("do_setenv, var '%s', val '%s'\n", varname, val); if (setenv(varname, val, 1) != 0) { char errStr[1024]; rs_strerror_r(errno, errStr, sizeof(errStr)); parser_errmsg( "error setting environment variable " "'%s' to '%s': %s", varname, val, errStr); ABORT_FINALIZE(RS_RET_ERR_SETENV); } finalize_it: RETiRet; } /* This processes the "regular" parameters which are to be set after the * config has been fully loaded. */ rsRetVal glblDoneLoadCnf(void) { int i; unsigned char *cstr; DEFiRet; CHKiRet(objUse(net, CORE_COMPONENT)); sortTimezones(loadConf); DBGPRINTF("Timezone information table (%d entries):\n", loadConf->timezones.ntzinfos); displayTimezones(loadConf); if (cnfparamvals == NULL) goto finalize_it; for (i = 0; i < paramblk.nParams; ++i) { if (!cnfparamvals[i].bUsed) continue; if (!strcmp(paramblk.descr[i].name, "workdirectory")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setWorkDir(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "libcapng.default")) { #ifdef ENABLE_LIBCAPNG loadConf->globals.bAbortOnFailedLibcapngSetup = (int)cnfparamvals[i].val.d.n; #else LogError(0, RS_RET_ERR, "rsyslog wasn't " "compiled with libcap-ng support."); #endif } else if (!strcmp(paramblk.descr[i].name, "libcapng.enable")) { #ifdef ENABLE_LIBCAPNG loadConf->globals.bCapabilityDropEnabled = (int)cnfparamvals[i].val.d.n; #else LogError(0, RS_RET_ERR, "rsyslog wasn't " "compiled with libcap-ng support."); #endif } else if (!strcmp(paramblk.descr[i].name, "variables.casesensitive")) { const int val = (int)cnfparamvals[i].val.d.n; fjson_global_do_case_sensitive_comparison(val); DBGPRINTF("global/config: set case sensitive variables to %d\n", val); } else if (!strcmp(paramblk.descr[i].name, "localhostname")) { free(LocalHostNameOverride); LocalHostNameOverride = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); } else if (!strcmp(paramblk.descr[i].name, "defaultnetstreamdriverkeyfile")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setDfltNetstrmDrvrKeyFile(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercertfile")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setDfltNetstrmDrvrCertFile(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercafile")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setDfltNetstrmDrvrCAF(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercrlfile")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setDfltNetstrmDrvrCRLF(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "defaultopensslengine")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setDfltOpensslEngine(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "netstreamdrivercaextrafiles")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setNetstrmDrvrCAExtraFiles(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "preservefqdn")) { bPreserveFQDN = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "compactjsonstring")) { glblJsonFormatOpt = cnfparamvals[i].val.d.n ? JSON_C_TO_STRING_PLAIN : JSON_C_TO_STRING_SPACED; } else if (!strcmp(paramblk.descr[i].name, "dropmsgswithmaliciousdnsptrrecords")) { loadConf->globals.bDropMalPTRMsgs = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "action.reportsuspension")) { loadConf->globals.bActionReportSuspension = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "action.reportsuspensioncontinuation")) { loadConf->globals.bActionReportSuspensionCont = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "maxmessagesize")) { setMaxLine(cnfparamvals[i].val.d.n); } else if (!strcmp(paramblk.descr[i].name, "maxopenfiles")) { loadConf->globals.iMaxOpenFiles = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "oversizemsg.errorfile")) { free(loadConf->globals.oversizeMsgErrorFile); loadConf->globals.oversizeMsgErrorFile = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); } else if (!strcmp(paramblk.descr[i].name, "oversizemsg.report")) { loadConf->globals.reportOversizeMsg = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "oversizemsg.input.mode")) { const char *const tmp = es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setOversizeMsgInputMode((uchar *)tmp); free((void *)tmp); } else if (!strcmp(paramblk.descr[i].name, "reportchildprocessexits")) { const char *const tmp = es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setReportChildProcessExits((uchar *)tmp); free((void *)tmp); } else if (!strcmp(paramblk.descr[i].name, "debug.onshutdown")) { loadConf->globals.debugOnShutdown = (int)cnfparamvals[i].val.d.n; LogMsg(0, RS_RET_OK, LOG_INFO, "debug: onShutdown set to %d", loadConf->globals.debugOnShutdown); } else if (!strcmp(paramblk.descr[i].name, "debug.gnutls")) { loadConf->globals.iGnuTLSLoglevel = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "debug.abortonprogramerror")) { glblAbortOnProgramError = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "debug.unloadmodules")) { glblUnloadModules = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "parser.controlcharacterescapeprefix")) { uchar *tmp = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setParserControlCharacterEscapePrefix(NULL, tmp); free(tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.droptrailinglfonreception")) { const int tmp = (int)cnfparamvals[i].val.d.n; setParserDropTrailingLFOnReception(NULL, tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.droptrailingcronreception")) { const int tmp = (int)cnfparamvals[i].val.d.n; setParserDropTrailingCROnReception(NULL, tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharactersonreceive")) { const int tmp = (int)cnfparamvals[i].val.d.n; setParserEscapeControlCharactersOnReceive(NULL, tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.spacelfonreceive")) { const int tmp = (int)cnfparamvals[i].val.d.n; setParserSpaceLFOnReceive(NULL, tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.escape8bitcharactersonreceive")) { const int tmp = (int)cnfparamvals[i].val.d.n; setParserEscape8BitCharactersOnReceive(NULL, tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharactertab")) { const int tmp = (int)cnfparamvals[i].val.d.n; setParserEscapeControlCharacterTab(NULL, tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharacterscstyle")) { const int tmp = (int)cnfparamvals[i].val.d.n; SetParserEscapeControlCharactersCStyle(tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.parsehostnameandtag")) { const int tmp = (int)cnfparamvals[i].val.d.n; SetParseHOSTNAMEandTAG(tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.permitslashinprogramname")) { loadConf->globals.parser.bPermitSlashInProgramname = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "debug.logfile")) { if (pszAltDbgFileName == NULL) { pszAltDbgFileName = es_str2cstr(cnfparamvals[i].val.d.estr, NULL); /* can actually happen if debug system also opened altdbg */ if (altdbg != -1) { close(altdbg); } if ((altdbg = open(pszAltDbgFileName, O_WRONLY | O_CREAT | O_TRUNC | O_NOCTTY | O_CLOEXEC, S_IRUSR | S_IWUSR)) == -1) { LogError(0, RS_RET_ERR, "debug log file '%s' could not be opened", pszAltDbgFileName); } } LogMsg(0, RS_RET_OK, LOG_INFO, "debug log file is '%s', fd %d", pszAltDbgFileName, altdbg); } else if (!strcmp(paramblk.descr[i].name, "janitor.interval")) { loadConf->globals.janitorInterval = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "net.ipprotocol")) { char *proto = es_str2cstr(cnfparamvals[i].val.d.estr, NULL); if (!strcmp(proto, "unspecified")) { loadConf->globals.iDefPFFamily = PF_UNSPEC; } else if (!strcmp(proto, "ipv4-only")) { loadConf->globals.iDefPFFamily = PF_INET; } else if (!strcmp(proto, "ipv6-only")) { loadConf->globals.iDefPFFamily = PF_INET6; } else { LogError(0, RS_RET_ERR, "invalid net.ipprotocol " "parameter '%s' -- ignored", proto); } free(proto); } else if (!strcmp(paramblk.descr[i].name, "senders.reportnew")) { loadConf->globals.reportNewSenders = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "senders.reportgoneaway")) { loadConf->globals.reportGoneAwaySenders = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "senders.timeoutafter")) { loadConf->globals.senderStatsTimeout = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "senders.keeptrack")) { loadConf->globals.senderKeepTrack = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "inputs.timeout.shutdown")) { loadConf->globals.inputTimeoutShutdown = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "privdrop.group.keepsupplemental")) { loadConf->globals.gidDropPrivKeepSupplemental = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "privdrop.group.id")) { loadConf->globals.gidDropPriv = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "privdrop.group.name")) { loadConf->globals.gidDropPriv = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "privdrop.user.id")) { loadConf->globals.uidDropPriv = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "privdrop.user.name")) { loadConf->globals.uidDropPriv = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "security.abortonidresolutionfail")) { loadConf->globals.abortOnIDResolutionFail = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "net.acladdhostnameonfail")) { loadConf->globals.ACLAddHostnameOnFail = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "net.aclresolvehostname")) { loadConf->globals.ACLDontResolve = !((int)cnfparamvals[i].val.d.n); } else if (!strcmp(paramblk.descr[i].name, "net.enabledns")) { SetDisableDNS(!((int)cnfparamvals[i].val.d.n)); } else if (!strcmp(paramblk.descr[i].name, "net.permitwarning")) { SetOptionDisallowWarning(!((int)cnfparamvals[i].val.d.n)); } else if (!strncmp(paramblk.descr[i].name, "compatibility.", 14)) { /* processed immediately by glblProcessCnf(), as later syntax depends on it */ } else if (!strcmp(paramblk.descr[i].name, "systemd.notifyreadydelay")) { loadConf->globals.systemdNotifyReadyDelay = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "abortonuncleanconfig")) { loadConf->globals.bAbortOnUncleanConfig = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "abortonfailedqueuestartup")) { loadConf->globals.bAbortOnFailedQueueStartup = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "internalmsg.ratelimit.burst")) { loadConf->globals.intMsgRateLimitBurst = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "internalmsg.ratelimit.interval")) { loadConf->globals.intMsgRateLimitItv = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "internalmsg.severity")) { loadConf->globals.intMsgsSeverityFilter = (int)cnfparamvals[i].val.d.n; if ((loadConf->globals.intMsgsSeverityFilter < 0) || (loadConf->globals.intMsgsSeverityFilter > 7)) { parser_errmsg("invalid internalmsg.severity value"); loadConf->globals.intMsgsSeverityFilter = DFLT_INT_MSGS_SEV_FILTER; } } else if (!strcmp(paramblk.descr[i].name, "environment")) { for (int j = 0; j < cnfparamvals[i].val.d.ar->nmemb; ++j) { char *const var = es_str2cstr(cnfparamvals[i].val.d.ar->arr[j], NULL); do_setenv(var); free(var); } } else if (!strcmp(paramblk.descr[i].name, "errormessagestostderr.maxnumber")) { loadConf->globals.maxErrMsgToStderr = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "allmessagestostderr")) { loadConf->globals.bAllMsgToStderr = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "debug.files")) { free(glblDbgFiles); /* "fix" Coverity false positive */ glblDbgFilesNum = cnfparamvals[i].val.d.ar->nmemb; glblDbgFiles = (char **)malloc(cnfparamvals[i].val.d.ar->nmemb * sizeof(char *)); for (int j = 0; j < cnfparamvals[i].val.d.ar->nmemb; ++j) { glblDbgFiles[j] = es_str2cstr(cnfparamvals[i].val.d.ar->arr[j], NULL); } qsort(glblDbgFiles, glblDbgFilesNum, sizeof(char *), qs_arrcmp_glblDbgFiles); } else if (!strcmp(paramblk.descr[i].name, "debug.whitelist")) { glblDbgWhitelist = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "shutdown.queue.doublesize")) { loadConf->globals.shutdownQueueDoubleSize = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "umask")) { loadConf->globals.umask = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "shutdown.enable.ctlc")) { loadConf->globals.permitCtlC = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutshutdown")) { loadConf->globals.actq_dflt_toQShutdown = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutactioncompletion")) { loadConf->globals.actq_dflt_toActShutdown = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutenqueue")) { loadConf->globals.actq_dflt_toEnq = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutworkerthreadshutdown")) { loadConf->globals.actq_dflt_toWrkShutdown = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutshutdown")) { loadConf->globals.ruleset_dflt_toQShutdown = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutactioncompletion")) { loadConf->globals.ruleset_dflt_toActShutdown = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutenqueue")) { loadConf->globals.ruleset_dflt_toEnq = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutworkerthreadshutdown")) { loadConf->globals.ruleset_dflt_toWrkShutdown = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "reverselookup.cache.ttl.default")) { loadConf->globals.dnscacheDefaultTTL = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "reverselookup.cache.ttl.enable")) { loadConf->globals.dnscacheEnableTTL = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "parser.supportcompressionextension")) { loadConf->globals.bSupportCompressionExtension = cnfparamvals[i].val.d.n; } else { dbgprintf( "glblDoneLoadCnf: program error, non-handled " "param '%s'\n", paramblk.descr[i].name); } } if (loadConf->globals.debugOnShutdown && Debug != DEBUG_FULL) { Debug = DEBUG_ONDEMAND; stddbg = -1; } if (loadConf->globals.compatDefaultsSecure == COMPAT_DEFAULTS_SECURE_STRICT) { loadConf->globals.bAbortOnUncleanConfig = 1; } else if (!loadConf->globals.bAbortOnUncleanConfig) { glblWarnIfInsecureDefault(loadConf, "global(abortOnUncleanConfig=\"off\")"); } finalize_it: /* we have now read the config. We need to query the local host name now * as it was set by the config. * * Note: early messages are already emited, and have "[localhost]" as * hostname. These messages are currently in iminternal queue. Once they * are taken from that queue, the hostname will be adapted. */ queryLocalHostname(loadConf); RETiRet; } /* Initialize the glbl class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(prop, CORE_COMPONENT)); /* initialize properties */ storeLocalHostIPIF((uchar *)"127.0.0.1"); /* config handlers are never unregistered and need not be - we are always loaded ;) */ CHKiRet(regCfSysLineHdlr((uchar *)"debugfile", 0, eCmdHdlrGetWord, setDebugFile, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"debuglevel", 0, eCmdHdlrInt, setDebugLevel, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, setWorkDir, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, SetDropMalPTRMsgs, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriver", 0, eCmdHdlrGetWord, setDfltNetstrmDrvr, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultopensslengine", 0, eCmdHdlrGetWord, setDfltOpensslEngine, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercafile", 0, eCmdHdlrGetWord, setDfltNetstrmDrvrCAF, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercrlfile", 0, eCmdHdlrGetWord, setDfltNetstrmDrvrCRLF, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriverkeyfile", 0, eCmdHdlrGetWord, setDfltNetstrmDrvrKeyFile, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercertfile", 0, eCmdHdlrGetWord, setDfltNetstrmDrvrCertFile, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"localhostname", 0, eCmdHdlrGetWord, NULL, &LocalHostNameOverride, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"localhostipif", 0, eCmdHdlrGetWord, setLocalHostIPIF, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"netstreamdrivercaextrafiles", 0, eCmdHdlrGetWord, setNetstrmDrvrCAExtraFiles, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"optimizeforuniprocessor", 0, eCmdHdlrGoneAway, NULL, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"preservefqdn", 0, eCmdHdlrBinary, NULL, &bPreserveFQDN, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"maxmessagesize", 0, eCmdHdlrSize, legacySetMaxMessageSize, NULL, NULL)); /* Deprecated parser config options */ CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, setParserControlCharacterEscapePrefix, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary, setParserDropTrailingLFOnReception, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"droptrailingcronreception", 0, eCmdHdlrBinary, setParserDropTrailingCROnReception, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, setParserEscapeControlCharactersOnReceive, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"spacelfonreceive", 0, eCmdHdlrBinary, setParserSpaceLFOnReceive, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"escape8bitcharactersonreceive", 0, eCmdHdlrBinary, setParserEscape8BitCharactersOnReceive, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactertab", 0, eCmdHdlrBinary, setParserEscapeControlCharacterTab, NULL, NULL)); CHKiRet( regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL)); INIT_ATOMIC_HELPER_MUT(mutTerminateInputs); ENDObjClassInit(glbl) /* Exit the glbl class. * rgerhards, 2008-04-17 */ BEGINObjClassExit(glbl, OBJ_IS_CORE_MODULE) /* class, version */ free(LocalDomain); free(LocalHostName); free(LocalHostNameOverride); free(LocalFQDNName); objRelease(prop, CORE_COMPONENT); if (propLocalHostNameToDelete != NULL) prop.Destruct(&propLocalHostNameToDelete); DESTROY_ATOMIC_HELPER_MUT(mutTerminateInputs); ENDObjClassExit(glbl)